commit b3b88fc33364358b3c9dace45a6ad2a3527d9490 Author: chrin Date: Tue Dec 13 12:44:04 2022 +0100 cdev-1.7.2n diff --git a/.setup b/.setup new file mode 100755 index 0000000..1c009e4 --- /dev/null +++ b/.setup @@ -0,0 +1,97 @@ +#!/bin/csh +# +# File: $CDEV/.setup +# +# EPICS users, see lines below containing EPICS +# + if ( $?CDEV == 0 ) then + setenv CDEVVERSION 1.7.2 + + echo "Setting up CDEV Version $CDEVVERSION" + +# to use EPICS, define EPICSLIB or uncomment these lines: +# if ( $?EPICSLIB == 0 ) then +# setup epics +# endif + + setenv OS `uname -s` + setenv REVISION `uname -r` + + switch ($OS) + case HP-UX: + setenv LIBDIR `echo $REVISION | awk '{ FS="."; printf("hpux-%s.%s", $2, $3); exit; }'` + breaksw + + case SunOS: + setenv OS_MAJOR_REV `echo $REVISION | awk '{FS="."; print $1; exit; }'` + if ($OS_MAJOR_REV < 4) then + setenv LIBDIR sunos + else + setenv LIBDIR solaris + endif + breaksw + + case Linux: + setenv LIBDIR Linux + breaksw + + case AIX: + setenv LIBDIR `echo uname -v | awk '{FS="."; printf("aix-%s.%s", $REVISION, $1); exit; }'` + breaksw + + default: + setenv LIBDIR $OS + breaksw + + endsw + + + setenv CDEV `pwd` + setenv CDEVLIB $CDEV/lib/$LIBDIR + setenv CDEVSHOBJ $CDEVLIB + setenv CDEVBIN $CDEV/bin/$LIBDIR + setenv CDEVINCLUDE $CDEV/include + setenv CDEVDDL $CDEV/ddl/master.bdd + setenv CDEV_ACCOUNT_FILE $CDEV/ddl/cdevAccount.txt + + setenv PATH ${PATH}:${CDEVBIN} + +# to use EPICS, uncomment these 2 lines and comment out next 2 + setenv EPICS /devl/epics + setenv EPICSLIB /devl/epics/base/lib/Linux + setenv SHLIB_PATH ${CDEVSHOBJ}:${CDEVLIB}:${EPICSLIB} + setenv LD_LIBRARY_PATH ${CDEVSHOBJ}:${CDEVLIB}:${EPICSLIB} +# setenv SHLIB_PATH ${CDEVSHOBJ}:${CDEVLIB} +# setenv LD_LIBRARY_PATH ${CDEVSHOBJ}:${CDEVLIB} + + unsetenv LIBDIR + unsetenv OS_MAJOR_REV + unsetenv OS + unsetenv REVISION + +#---- Automatic way to recreate the important symbolik links--------------- + +set R=`cat /etc/redhat-release | awk 'BEGIN{FS=" "};{print $5}'` +set MAKEFILE1="Makefile.linux-redhat$R-x86" +set DIR1="include/makeinclude/" +set DIR2="extensions/cdevGenericServer/include/makeinclude/" + +if ( -e $DIR1$MAKEFILE1 ) then + echo "Creating the Symbolic link ${DIR1}Makefile.linux -> $MAKEFILE1" + rm -f ${DIR1}Makefile.linux + ln -s $MAKEFILE1 ${DIR1}Makefile.linux +else + echo "file $MAKEFILE1 does not exist in $DIR1" +endif + +if ( -e $DIR2$MAKEFILE1 ) then + echo "Creating the Symbolic link ${DIR2}Makefile.linux -> $MAKEFILE1" + rm -f ${DIR2}Makefile.linux + ln -s $MAKEFILE1 ${DIR2}Makefile.linux +else + echo "file $MAKEFILE1 does not exist in $DIR2" +endif +#----------------------------------------------------------------------------- + endif + + diff --git a/NMakefile.mak b/NMakefile.mak new file mode 100644 index 0000000..44a3595 --- /dev/null +++ b/NMakefile.mak @@ -0,0 +1,24 @@ +BASEDIR = $(MAKEDIR) +DIRS = $(BASEDIR)\src \ + $(BASEDIR)\extensions\cdevGenericServer \ + $(BASEDIR)\applications\cdevGateway +BINDIRS = $(BASEDIR)\lib\WINNT-4.0-DEBUG \ + $(BASEDIR)\lib\WINNT-4.0 \ + $(BASEDIR)\bin\WINNT-4.0-DEBUG \ + $(BASEDIR)\bin\WINNT-4.0 \ + $(BASEDIR)\extensions\cdevGenericServer\lib\WINNT-4.0-DEBUG \ + $(BASEDIR)\extensions\cdevGenericServer\lib\WINNT-4.0 \ + $(BASEDIR)\extensions\cdevGenericServer\bin\WINNT-4.0-DEBUG \ + $(BASEDIR)\extensions\cdevGenericServer\bin\WINNT-4.0 \ + $(BASEDIR)\applications\cdevGateway\bin\WINNT-4.0-DEBUG \ + $(BASEDIR)\applications\cdevGateway\bin\WINNT-4.0 + +notarget : all + +all clean : + @for %d in ($(DIRS)) do @if exist %d cd %d & $(MAKE) /NOLOGO $@ /f NMakefile.mak + +purge : + @for %d in ($(DIRS)) do @if exist %d cd %d & $(MAKE) /NOLOGO $@ /f NMakefile.mak + @for %d in ($(BINDIRS)) do @if exist %d rmdir /s /q %d + diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..32adabb --- /dev/null +++ b/NOTICE @@ -0,0 +1,37 @@ + COPYRIGHT AND LICENSE + +Copyright (c) 1995,1996 Southeastern Universities Research Association + Continuous Electron Beam Accelerator Facility + Thomas Jefferson National Accelerator Facility + 12000 Jefferson Avenue, Newport News, VA 23606 + +This material resulted from work developed under a United States Government +Contract and is subject to the following license: + +The Government retains a paid-up, nonexclusive, irrevocable worldwide license +to reproduce, prepare derivative works, perform publicly and display publicly +by or for the Government including the right to distribute to other Government +contractors. + + + DISCLAIMER AND LIMITATION OF WARRANTY. + + ALL SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY. THERE + ARE NO WARRANTIES EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED + WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR + PURPOSE. THERE IS NO WARRANTY THAT USE WILL NOT INFRINGE + ANY PATENT, COPYRIGHT OR TRADEMARK. + +In consideration of the use of the software and other materials, user agrees +that neither the Government nor SURA/TJNAF will be liable for any damages with +respect to such use, and user shall hold both the Government and SURA/TJNAF +harmless from and indemnify them against any and all liability for damages +arising out of the use of such software and other materials. In no event shall +the Government or SURA/TJNAF be liable whether arising under contract, tort, +strict liability or otherwise for any incidental, indirect or consequential +loss or damage of any nature arising at any time from any cause whatsoever. In +addition, the Government and SURA/TJNAF assume no obligation for defending +against third party claims or threats of claims arising as a result of user's +use of the software or materials either as delivered to user or as modified by +user. + \ No newline at end of file diff --git a/NewDist b/NewDist new file mode 100755 index 0000000..b2de438 --- /dev/null +++ b/NewDist @@ -0,0 +1,82 @@ +#! /bin/csh -f + +echo "--------------------------------------------------------------------------" +echo "NewDist: Building compressed file for CDEV Distribution" +echo " Prior to running this program, make sure that all changes " +echo " that are to be distributed with this release have been checked" +echo " into CVS." +echo " " +echo " Last used successfully by Walt Akers on 07/24/99" +echo "--------------------------------------------------------------------------" + +if ($#argv < 2) then + echo "Format is: NewDist MajorVer MinorVer " + echo " ... MajorVer is the major version number of cdev" + echo " ... MinorVer is the minor version number of cdev" + echo " ... Release is the release number of cdev\n" + echo "Example: To create a distribution for cdev/1.6.2 the" + echo " command will be NewDist 1 6 2\n" + exit +else + set MAJORVER=$1 + set MINORVER=$2 + if($#argv >2) then + set RELEASE=$3 + set CVSTAG=CDEV_R${MAJORVER}_${MINORVER}_${RELEASE} + set DISTDIR=cdev_${MAJORVER}.${MINORVER}.${RELEASE} + else + set RELEASE=None + set CVSTAG=CDEV_R${MAJORVER}_${MINORVER} + set DISTDIR=cdev_${MAJORVER}.${MINORVER} + endif +endif + +echo "Steps: This program will perform the following steps" +echo " to create the distribution.\n" +echo " 1) It will install a revision number in cdev" +echo " that identifies this version using the " +echo " MajorVer/MinorVer/Revision number provided.\n" +echo " (cdev/1.6.2 would be labeled cdev_R1_6_2.\n" +echo " 2) cvs export will be executed to create a" +echo " clean copy of the distribution in a new" +echo " directory.\n" +echo " (cdev/1.6.2 would be installed in cdev_1.6.2)\n" +echo " 3) tar will be used to create an archive of the" +echo " cdev distribution.\n" +echo " (cdev/1.6.2 would be archived to cdev_1.6.2.tar)\n" +echo " 4) gzip will be used to make a compress the archive\n" +echo " (cdev/1.6.2 would be compressed to cdev_1.6.2.tar.gz\n" +echo " 5) compress will be used to compress the archive using" +echo " an alternate format.\n" +echo " (cdev/1.6.2 would be compressed to cdev_1.6.2.tar.Z)\n" +echo " 6) The temporary directory will be deleted.\n" +echo "------------------------------- OPTIONS --------------------------------\n" +echo "Major Version : $MAJORVER " +echo "Minor Version : $MINORVER " +echo "Release : $RELEASE " +echo "CVS Release Tag : $CVSTAG " +echo "Distribution Name : $DISTDIR \n" +echo "------------------------------------------------------------------------\n" + +echo "Press +C to quit or to continue" +read +echo "Continuing...\n" +echo "STEP 1: Tagging CDEV with Revision Tag $CVSTAG" +cvs rtag -afRF $CVSTAG cdev + +echo "STEP 2: Exporting CDEV to temporary directory $DISTDIR" +cvs export -r $CVSTAG -d $DISTDIR cdev + +echo "STEP 3: Creating archive ${DISTDIR}.tar from $DISTDIR" +tar -cvhf ${DISTDIR}.tar $DISTDIR +cp ${DISTDIR}.tar ${DISTDIR}.tar.saf + +echo "STEP 4: Compressing ${DISTDIR}.tar using gzip" +gzip ${DISTDIR}.tar + +echo "STEP 5: Compressing ${DISTDIR}.tag using compress" +mv ${DISTDIR}.tar.saf ${DISTDIR}.tar +compress ${DISTDIR}.tar + +echo "STEP 6: Deleting temporary directory" +rm -rf ${DISTDIR} diff --git a/NewTag b/NewTag new file mode 100755 index 0000000..1c58513 --- /dev/null +++ b/NewTag @@ -0,0 +1,51 @@ +#! /bin/csh -f + +echo "--------------------------------------------------------------------------" +echo "NewTag: Updates the CVS tag for all files in the CDEV distribution" +echo " Prior to running this program, make sure that all changes " +echo " that are to be distributed with this release have been checked" +echo " into CVS." +echo " " +echo " Last used successfully by Walt Akers on 09/13/99" +echo "--------------------------------------------------------------------------" + +if ($#argv < 2) then + echo "Format is: NewTag MajorVer MinorVer " + echo " ... MajorVer is the major version number of cdev" + echo " ... MinorVer is the minor version number of cdev" + echo " ... Release is the release number of cdev\n" + echo "Example: To update the CVS tag for cdev/1.7.1 the" + echo " command will be NewTag 1 7 1\n" + exit +else + set MAJORVER=$1 + set MINORVER=$2 + if($#argv >2) then + set RELEASE=$3 + set CVSTAG=CDEV_R${MAJORVER}_${MINORVER}_${RELEASE} + set DISTDIR=cdev_${MAJORVER}.${MINORVER}.${RELEASE} + else + set RELEASE=None + set CVSTAG=CDEV_R${MAJORVER}_${MINORVER} + set DISTDIR=cdev_${MAJORVER}.${MINORVER} + endif +endif + +echo "Steps: This program will perform the following steps" +echo " to create the distribution.\n" +echo " 1) It will install a revision number in cdev" +echo " that identifies this version using the " +echo " MajorVer/MinorVer/Revision number provided.\n" +echo " (cdev/1.6.2 would be labeled cdev_R1_6_2.\n" +echo "------------------------------- OPTIONS --------------------------------\n" +echo "Major Version : $MAJORVER " +echo "Minor Version : $MINORVER " +echo "Release : $RELEASE " +echo "CVS Release Tag : $CVSTAG " +echo "------------------------------------------------------------------------\n" + +echo "Press +C to quit or to continue" +read +echo "Continuing...\n" +echo "STEP 1: Tagging CDEV with Revision Tag $CVSTAG" +cvs rtag -afRF $CVSTAG cdev diff --git a/PORTING b/PORTING new file mode 100644 index 0000000..fd97c48 --- /dev/null +++ b/PORTING @@ -0,0 +1,25 @@ +This document describes how to port CDEV to a different UNIX platform. +Currently, CDEV with channel access service has been tested on HP-UX 9.x, +HP-UX 10.1(2), Solaris 2.5(6), and Linux 2.0.x, and CDEV without channel +access service has been ported to SunOs (gcc-2.7), Ultrix (gcc-2.6), Irix, +VMS (DEC C++) and AIX. The following are brief description of what one may +have to do to port CDEV. +1) Makefile and Makefile.common have to be changed a little (Check README). +We are in the process to find a way to configure makefiles for different +platform. + +2)in src/cdevIO, xdrClass.h may need to add some header file for rpc related +stuff. + +3)in src/cdevIO. cdevData.i contains inlined functions for cdevData. If one +has trouble to build library using inline function, add _CDEV_NO_INLINE +to one's C++ flag. + +4)one can build CDEV in a share library form and dynammically load services +if the operating system permits. Currently one can have CDEV shared library +on HP-UX, SunOs, Solaris, Linux, Irix. If shared libray of CDEV is desired +form on a different platform, src/common/shObjLoader, that loads services +into applications dynamically, has to be modified. + +Eventually, all system dependent stuff will be in one file somewhere. But +for now we don't have time to do that. diff --git a/README b/README new file mode 100644 index 0000000..896d77b --- /dev/null +++ b/README @@ -0,0 +1,306 @@ +----------------------------------------------------------------------------- + Copyright (c) 1995 Southeastern Universities Research Association, + Continuous Electron Beam Accelerator Facility + + This software was developed under a United States Government license + described in the NOTICE file included as part of this distribution. +----------------------------------------------------------------------------- + +PACKAGE NAME: cdev + +PURPOSE: To provide a simplified and extensible object oriented + interface to the services provided by any control system + or other message based system. + +VERSION: 1.7.2 + +DESCRIPTION: + The cdev (common device) C++ library is designed to provide a + standard application programming interface (API) to one or + more underlying packages, typically control system interfaces. + The implementation is in 2 layers: the uppermost layer is used + directly by an application, and provides an abstraction of the + underlying package as well as many general purpose features. + The second layer (service layer) provides the interface to one + or more underlying packages, and is implemented as loadable + libraries. + + cdev was initially developed at Jefferson Lab in collaboration + with the EPICS community, and is now available to anyone to take. + It has been interfaced to a variety of accelerator control systems, + including EPICS, systems at SLAC, CERN, Brookhaven and others. + + We welcome all comments, suggestions, bug reports, and (especially) + bug fixes. There are many planned enhancements, and we welcome + volunteers to contribute to this project. See the release notes + for a summary of planned features. + + +DIRECTORIES: + + ./src * cdev source parent directory, + * contains makefiles and subdirectories + * with the source code necessary to + * create the cdev libraries + + ./src/ca (only used by EPICS) + ./src/cdevIO + ./src/common + ./src/callback + ./src/device + ./src/directory + ./src/group + ./src/lib + ./src/namesvc + ./src/system + ./src/utility + + ./extensions + * cdev network extensions to allow quick + * and easy development of cdev servers + ./extensions/cdevGenericServers + ./extensions/SimpleService + + ./include * header files for cdev applications, + * this directory will be populated + * during the first execution of make + + ./lib * cdev library parent directory, this + * directory will be populated with + * subdirectories that contain target + * specific libraries and object files + + ./lib/hpux-09.XX + ./lib/hpux-10.XX + ./lib/solaris + ./lib/Linux + ... + + ./bin * cdev binary parent directory, this + * directory will be populated with + * subdirectories that contain target + * specific sample applications created + * with the cdev libraries + + ./bin/hpux-09.XX + ./bin/hpux-10.XX + ./bin/solaris + ./bin/Linux + ... + + ./applications + * ./applications/cdevGateway. + A simple cdevGateway using cdevGenericServer library. + + ./doc * directory containing the most up-to-date + * cdev documentation. + +BUILDING CDEV: After installing the cdev package from the distribution + media to the target directory, the user should be aware + of the following considerations prior to starting a build. + + Configure cdevDirectory and static services: + + This must be done before any installation procedures. + + cdev supports dynamically linked services as well as + statically linked (archive library) services. In each + case, services are accessible by name. For statically + linked services, cdevDirectory must be configured to + reference all needed services so that they are linked + in at load time. + + Additionally, cdevDirectory supports a default service + which is used if no entry in a ddl file (or other + user supplied directory service) for that operation. + cdev is shipped with code to default to the EPICS + channel access library. This default is enabled by + defining the flag _HAS_CA. + + There is a script (configSvc) in the src directory to assist + in generating the proper code for the default service and + statically linked services. + + Example: + You wish to use the EPICS channel access (ca) service and a + service with name xyz, and want to enable defaulting to ca: + + configSvc services=ca xyz \ + headers=/usr/local/epics/base/include \ + /usr/local/cdev/src/ca /usr/local/cdev/src/xyz \ + flags=_HAS_CA + + The headers are the include directories needed for these + services. The services are the names of the services. The + configSvc will generate Makefile and cdevSvcConfig.cc in + src/directory directory. + + MAKE VARIABLES: + + The cdev makefiles require several environment variables + to be specified in order to compile correctly. These + variables may either be entered explicitly on the make + command line or may be specified in the local environment. + + The following variables should be specified... + + MAKE This variable specifies the make command + that will be used in the makefiles of the + subdirectories. Always use gnu make. + + CDEV top directory of cdev. + + CDEVSHOBJ directory in which shared libraries for services + are installed. + + EPICS This variable contains the EPICS root directory. + This variable is undefined by default, and must + be specified by the user if one wants to build + channel access service. + + EPICSLIB This variable contains the EPICS library path. + It is used when one wants to build channel access + service. + + COMPILING THE DISTRIBUTION: + + In order to compile this distribution you must perform the + following steps. + + 1) Determine the required values of the makefile variables + listed that will be necessary to compile cdev for your + system. + + + 2) Go to $CDEV/include/makeinclude directory. Make a link + to a right makefile. For example, on a Sun running solaris, + do ln -s Makefile.solaris Makefile.OS + + 3) Change directories to the cdev distribution src directory. + This is where the Makefile and Makefile.config will be + located. + + 4) If you have compiled the cdev distribution for and other + TARGET in the past, you should execute a 'make clean' to + remove any outdated object files. + + 5) If you want to change default timeout value and connection + retry frequency in channel access of EPICS, you should change + DEFAULT_TIMEOUT and DEFAULT_CONN_FREQUENCY values in the + caRequestObject.h right now. + + 6) Run configSvc in the src directory. This will generate Makefile + and cdevSvcConfig.cc in src/directory. + + 7) Type make, the output will tell you the following: + Type one of the following: + make hpux for HP systems + make hpux-sl for HP systems building shared library + make hpux-cl for HP systems with CenterLine + make hpux-cl-sl for HP systems with CenterLine Building shared library + make irix5 for SGI running irix5 + make irix5-sl for SGI running irix5 building shared library + make sunos4-gcc for SunOs 4.x and gcc + make sunos4-gcc-sl for SunOs 4.x and gcc building shared library + make solaris for Solaris2.x + make solaris-sl for Solaris2.x and building shared library + make solaris-gcc for Solaris2.x and gcc + make solaris-gcc-sl for Solaris2.x and gcc building shared library + make ultrix-gcc for ultrix 4.x and gcc + make aix for IBM AIX 4.x + make linux-sl for linux shared library + make linux for linux archived library + make clean + Pick one from the above to build src distribution. If there is no + one from the above list to match your platform, you can take a look + at the Makefile.config to create one. Please send e-mail to us + at cdev@jlab.org about your new makefile. + + 8) The libcdev.so or libcdev.a will be installed in $CDEV/lib/$(ARCH). + and all services (caService.so) are installed in the $CDEVSHOBJ/1.7. + All executables are installed in $CDEV/bin/$(ARCH). + + 9) Now you are ready to use cdev. If you decide to build extension part + of cdev, you can go to extensions/cdevGenericServer directory. + + 10) Go to include/makeinclude directory. Make a link for a right Makefile. + For example, on Linux machine, you will do + ln -s Makefile.linux Makefile.OS. + + 11) Go back to $CDEV/extensions/cdevGenericServer. Type make (make sure + it is gnu make). It should build everything from NameServer (rsvcServer) + to libcdevGenericServer.a(so), libcdevClient.a(so), + libcdevReactor.a(so), libcdevClientLite.a(so), librsvc.a(so) and + rnsService.so. The rsvcServer will be in $CDEV/bin/$(ARCH), and + rnsService.so is installed in $CDEVSHOBJ/1.7, the rest of them + will be in $CDEV/lib/$(ARCH). + + 12) If you wish to use the generic CLIP service (used in communicating with + CLIP servers written in Java), go to $CDEV/extensions/CLIPService + and type make. The service will be placed into $CDEVSHOBJ/1.7. + + 13) If you wish to use cdevGateway (needed for Java clients), go to + $CDEV/applications/cdevGateway and type make. Executable will be placed in + $CDEVBIN and service in $CDEVSHOBJ/1.7. + + +USING CDEV: After reviewing the documentation supplied with this cdev + distribution, you should be able to construct a cdev application. + + In order to compile this application you must perform the following: + + 1) Specify the cdev header files that you will be using within the + source code. + + 2) Add the path to the cdev include files to your compiler command + line. + + example: + + -I$(CDEV)/include + + 3) Add the path to the cdev libraries to your compiler or linker + command line. + + example: + + -L$(CDEVROOT)/lib/solaris + + 4) Specify the cdev libraries to be linked to your application on + the compiler or linker command line. These libraries are + libEpicsCa.a and libcdev.a. Additionally, the yacc, lex + and math libraries must be linked. (EpicsCa only needed for + programs statically linking to EPICS channel access.) + + a) Link with archived library + + example: + + -lcdev -lcaService -L$(EPICSLIB) -ly -ll -lm + + b) Link with shared library + + example: + + -lcdev -ly -ll -lm + + + 5) Set the CDEVDDL environment variable. This is a variable + specifying the location of DDL file (device definition file). + This variable should be set prior to executing your new + application. + + example: + + setenv CDEVDDL /usr/cdev/ddl/myFile.ddl + + 6) Set the CDEVSHOBJ environment variable if your application is linked + with shared library. This is a variable specifying the directory of + caService.so which contains all shared object codes for channel access. + Default location is /usr/local/lib. + + + + + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/applications/cdevGateway/Makefile b/applications/cdevGateway/Makefile new file mode 100755 index 0000000..4e66fc5 --- /dev/null +++ b/applications/cdevGateway/Makefile @@ -0,0 +1,29 @@ +ifneq ("$(VERBOSE)", "YES") + MAKE := $(MAKE) -s VERBOSE=NO +endif + +all: + @echo "=> Building CDEV Gateway Client/Server" + @$(MAKE) -C server $@ + @$(MAKE) -C service $@ + @echo "<= Done...\n" + +apps: + @echo "=> Building Test Applications" + @$(MAKE) -C test + @echo "<= Done...\n" + +clean: + @echo "=> Cleaning CDEV Gateway Directories" + @$(MAKE) -C server $@ + @$(MAKE) -C service $@ + @$(MAKE) -C test $@ + @echo "<= Done...\n" + +purge: + @echo "=> Purging CDEV Gateway Directories" + @$(MAKE) -C server $@ + @$(MAKE) -C service $@ + @$(MAKE) -C test $@ + @rm -rf bin + @echo "<= Done...\n" diff --git a/applications/cdevGateway/NMakefile.mak b/applications/cdevGateway/NMakefile.mak new file mode 100644 index 0000000..0baf7df --- /dev/null +++ b/applications/cdevGateway/NMakefile.mak @@ -0,0 +1,37 @@ +!IF "$(VERBOSE)" != "YES" +MAKE = $(MAKE) -s VERBOSE=NO +!ENDIF + +BASEDIR = $(MAKEDIR) + +SERVER_DIR = $(BASEDIR)\server +SERVICE_DIR = $(BASEDIR)\service +APP_DIR = $(BASEDIR)\test + +CLEAN_DIRS = $(SERVER_DIR)\ + $(SERVICE_DIR)\ + $(APP_DIR) + + +all: + @echo =^> Building CDEV Gateway Client/Server + @for %d in ($(SERVER_DIR) $(SERVICE_DIR)) do @cd %d & $(MAKE) /NOLOGO /f NMakefile.mak + @echo ^<= Done... + + +apps: + @echo =^> Building Test Applications + @for %d in ($(APP_DIR)) do @cd %d & $(MAKE) /NOLOGO /f NMakefile.mak + @echo ^<= Done... + + +clean: + @echo =^> Cleaning CDEV Gateway Directories + @for %d in ($(CLEAN_DIRS)) do @cd %d & $(MAKE) /NOLOGO /f NMakefile.mak clean + @echo ^<= Done... + +purge: + @echo =^> Purging CDEV Gateway Directories + @for %d in ($(CLEAN_DIRS)) do @cd %d & $(MAKE) /NOLOGO /f NMakefile.mak purge + -@rmdir /s /q $(BASEDIR)\bin + @echo ^<= Done... diff --git a/applications/cdevGateway/doc/cdevGateway.book b/applications/cdevGateway/doc/cdevGateway.book new file mode 100755 index 0000000..ded88a8 Binary files /dev/null and b/applications/cdevGateway/doc/cdevGateway.book differ diff --git a/applications/cdevGateway/doc/cdevGateway.doc b/applications/cdevGateway/doc/cdevGateway.doc new file mode 100755 index 0000000..3f55468 Binary files /dev/null and b/applications/cdevGateway/doc/cdevGateway.doc differ diff --git a/applications/cdevGateway/doc/cdevGatewayLOF.doc b/applications/cdevGateway/doc/cdevGatewayLOF.doc new file mode 100755 index 0000000..cd8de8b Binary files /dev/null and b/applications/cdevGateway/doc/cdevGatewayLOF.doc differ diff --git a/applications/cdevGateway/doc/cdevGatewayTITLE.doc b/applications/cdevGateway/doc/cdevGatewayTITLE.doc new file mode 100755 index 0000000..e3cc5af Binary files /dev/null and b/applications/cdevGateway/doc/cdevGatewayTITLE.doc differ diff --git a/applications/cdevGateway/doc/cdevGatewayTOC.doc b/applications/cdevGateway/doc/cdevGatewayTOC.doc new file mode 100755 index 0000000..6f8f0e1 Binary files /dev/null and b/applications/cdevGateway/doc/cdevGatewayTOC.doc differ diff --git a/applications/cdevGateway/doc/html/bullet.jpg b/applications/cdevGateway/doc/html/bullet.jpg new file mode 100755 index 0000000..a79a191 Binary files /dev/null and b/applications/cdevGateway/doc/html/bullet.jpg differ diff --git a/applications/cdevGateway/doc/html/cdevGateway.html b/applications/cdevGateway/doc/html/cdevGateway.html new file mode 100755 index 0000000..f8982d9 --- /dev/null +++ b/applications/cdevGateway/doc/html/cdevGateway.html @@ -0,0 +1,875 @@ + + +CDEV Gateway + + + + + + +


+ + + +
+ + + + CDEV Gateway +

+ +

+ A Message Router/Concentrator for CDEV Clients +

+ +

+ Walt Akers, Chip Watson, Jie Chen +

+ +

+ Version 1.0 February 13, 1997 +

+ +

+ TJNAF - Thomas Jefferson National Accelerator Facility +

+ +

+
+ +


+ + + + + +
+ + + + Table of Contents +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + 1. +
+
+ + CDEV Gateway Fundamentals +
+
+ + +
+
+ + Overview of the CDEV Gateway +
+
+ + +
+
+ + Purpose of the CDEV Gateway +
+
+ + +
+
+ + Features of the CDEV Gateway Service +
+
+ + 2. +
+
+ + Building the CDEV Gateway Service +
+
+ + +
+
+ + Location of Files +
+
+ + +
+
+ + Steps to Building the Server and Service +
+
+ + 3. +
+
+ + Starting the CDEV Gateway +
+
+ + +
+
+ + Starting the Gateway Server +
+
+ + +
+
+ + Start-up Arguments for the Gateway Server +
+
+ + 4. +
+
+ + Troubleshooting Server Start-up +
+
+ + 5. +
+
+ + DDL Entries for the CDEV Gateway Client +
+
+ + +
+
+ + Setting Up the DDL +
+
+
+ +


+ + + + + +
+ + + + List of Figures +

+
+ + + + Figure 2: + Simple DDL file for the Gateway Service +
+
+ +


+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + 1. +

+
+ + + CDEV Gateway Fundamentals +

+
+ + + Overview of the + CDEV Gateway +

+
+ + The CDEV Gateway is a server that acts as an intermediary between a CDEV + application and remote services. A single network connection is established between + the client and the gateway through which all CDEV requests will be routed. When the + gateway receives a request from the client, it establishes the appropriate connection + to the actual service, makes the request, and returns the result to the client + application. +

+
+ + + Purpose of the + CDEV Gateway +

+
+ + The CDEV Gateway was designed to support the JAVA/CDEV API. Because JAVA + code must be small in order to load and execute efficiently, it was critical to move as + much code as possible out of JAVA and into a CDEV "proxy" which could perform + connection management and dynamic library loading. This allows the JAVA + application to access new services provided in C++ without adding any new code. +

+ The JAVA/CDEV library locates the CDEV Gateway by using a hostname and port that + is provided in an environment variable. After determining the location of the server, + JAVA will establish a connection to the gateway and then begin transmitting its CDEV + requests in standard CLIP (CDEV Linear Internet Protocol). +

+ The gateway can also be used by standard C or C++ CDEV applications to perform + message routing. This approach can lessen the number of connections to actual + control system devices and reduce network traffic significantly. The gateway is located + by the gateway service by looking up its name (as specified in the CDEV DDL) in the + global name server (The current name server is distributed as part of the CDEV + Generic Server in the CDEV distribution). +

+
+ + + Features of the + CDEV Gateway + Service +

+
+ + + + + + + + + + + + + +
+ + +

+
+ + The CDEV Gateway is constructed using the CDEV Generic Server Engine and + the CLIP Protocol. +

+
+ + +

+
+ + Each gateway server registers its name, host and port with the CDEV Name + Server when it is started. +

+
+ + +

+
+ + The name of the specific gateway to be used is associated with a CDEV device/ + message combination by using the "server" field of the class-data in the CDEV + DDL file. Syntax is described later in this document. +

+
+ + +

+
+ + The gateway service will establish one connection to a named gateway to perform + all transactions. +

+
+ + +

+
+ + The client application uses a special DDL file that redirects all signals to the + gateway service. This allows the gateway server to maintain the actual control + system connections from a centralized location. +

+
+ + +

+
+ + The gateway server may have a standard DDL that redirects requests to the + actual service OR it may have a special DDL that routes requests to another + gateway. The system has currently been tested by routing messages through as + many as ten gateways before reaching the actual control system. Note that + performance begins to degrade substantially after routing through five gateways - + but is still reasonable. +

+
+
+ + 2. +

+
+ + + Building the CDEV Gateway Service +

+
+ + + Location of Files +

+
+ + The source code for the Gateway Service is provided with the CDEV distribution + starting with version 1.5. The source code is located in the directory $CDEV/ + applications/cdevGateway. The following steps should be taken to build the Gateway + Server and Service. +

+
+ + + Steps to Building + the Server and + Service +

+
+ + + + + + + + + + + + + +
+ + 1. +

+
+ + Obtain and install the CDEV distribution - Version 1.5 or higher. +

+
+ + 2. +

+
+ + Follow the installation steps to build CDEV on your system. This includes setting + all of the environment variables required by CDEV. +

+
+ + 3. +

+
+ + Follow the installation steps to build the CDEV Generic Server and deploy the + CDEV Name Server. +

+
+ + 4. +

+
+ + There is a collection of platform specific makefiles in the directory $CDEV/ + extensions/cdevGenericServer/include/makeinclude. Link the makefile that is + appropriate to your architecture to the file Makefile.OS in THAT directory. +

+ + For example, to link to the makefile for HP-UX, you would type the following + command. +

+ +

+ cd $CDEV/extensions/cdevGenericServer/makeinclude +

+ ln -s Makefile.hpux Makefile.OS +

+ +

+
+ + 5. +

+
+ + Change directories to $CDEV/applications/cdevGateway. +

+
+ + 6. +

+
+ + Type make to compile and link the CDEV Gateway Service shared object and the + CDEV Gateway Server. Note that you must be using GNU make in order to build + this distribution. +

+
+ + Upon completion the Makefile will generate the shared object for the gateway service + and will install it into your CDEVSHOBJ directory. The gateway server will be + compiled, linked and installed in the directory $CDEV/applications/cdevGateway/bin/ + ARCH/cdevGateway. At this point you are ready to start the gateway server. +

+
+ + 3. +

+
+ + + Starting the CDEV Gateway +

+
+ + + Starting the + Gateway Server +

+
+ + The following steps should be taken to execute the cdevGateway. +

+ + + + + + + +
+ + 1. +

+
+ + Ensure that the required CDEV and CDEV Generic Server environment variables + have been set. These include: +

+ + + + + + + +
+ + CDEVDDL +

+
+ + This is the name of the DDL file that indicates where + messages should be routed. Typically, this DDL will + route the messages to the actual control system + devices. +

+
+ + CDEVSHOBJ +

+
+ + This is the location of the CDEV shared object files. +

+
+ + CDEV_NAME_SERVER +

+
+ + This is the host where the CDEV Name Server is + running. +

+
+
+ + 2. +

+
+ + Move to the directory where the CDEV Gateway Server binary is located: by + default $CDEV/applications/cdevGateway/bin/ARCH, where ARCH is the name of + the host architecture. +

+
+ + 3. +

+
+ + Type the command ./cdevGateway at the command line. This will start a gateway + server with the name Gateway1 on the current host using TCP/IP port 9573. This + information can be confirmed by using the dumpServer command that is + provided with the CDEV Generic Server Engine to display the contents of the + CDEV Name Server. +

+
+ + At this point the cdevGateway should be ready for use by client applications. +

+
+ + + Start-up + Arguments for the + Gateway Server +

+
+ + The user can specify the name of port used by the CDEV Gateway from the command + line when the server is started. The gateway server will accept the following + parameters from start-up. +

+ + + + + +
+ + s=server name +

+
+ + This allows the caller to specify the server name that + will be registered with the name server. By default + the server name is Gateway1. +

+
+ + p=port number +

+
+ + This allows the caller to specify the port that the + server will use to receive incoming requests. By + default the port used by the server is 9573. +

+
+
+ + 4. +

+
+ + + Troubleshooting Server Start-up +

+ + When the server is started it may display one or more error conditions that will prevent + it from operating properly. +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Error: +

+
+ + syntax error at line:# +

+
+ + + Meaning: +

+
+ + This message indicates that the CDEVDDL file that is being + used by the gateway is formatted improperly. +

+
+ + + Solution: +

+
+ + Edit the CDEVDDL file and correct any formatting errors that + may exist. +

+
+ + + Error: +

+
+ + ERROR: Gateway1 server already exists in GATEWAY domain +

+
+ + + Meaning: +

+
+ + This message indicates that a gateway server with the name + Gateway1 has already been started and is currently registered + with the CDEV Name Server. +

+
+ + + Solution: +

+
+ + The gateway will continue to attempt to register itself with the + name server every 30 seconds. If the message continues to + appear, then restart the gateway using the s parameter to + specify a different server name OR shutdown the other + gateway that is using the same name. +

+
+ + + Error: +

+
+ + Could not communicate with name server +

+ ERROR: Failed to execute "REGISTER SERVER" operation +

+
+ + + Meaning: +

+
+ + This message indicates that the CDEV Name Server could not + be accessed either because it is not running or because the + CDEV_NAME_SERVER environment variable does not specify + the correct host. +

+
+ + + Solution: +

+
+ + Ensure that the CDEV_NAME_SERVER environment variable + is set and indicates the host where the name server is running. + If this is correct, check to ensure that the name server is + actually running on the specified host. +

+
+ + + Error: +

+
+ + Error: Server Gateway1 - Unable to open listening socket +

+
+ + + Meaning: +

+
+ + This message indicates that the port that the name server is + attempting to use to listen for new connections is already in + use. +

+
+ + + Solution: +

+
+ + Use the command line arguments to specify a different listening + port. +

+
+ + +

+ +

+ +

+ +

+
+ + 5. +

+
+ + + DDL Entries for the CDEV Gateway Client +

+
+ + + Setting Up the + DDL +

+
+ + The following example illustrates how to add a service entry to identify the CDEV + Gateway Service and how to use the class-data to specify the server that the gateway + service will use for routing messages. +

+ +

+ + Figure 2: + + Simple DDL file for the Gateway Service +
+ + + +
+ + +

+/*
+ * This is the service definition, it tells CDEV that there is
+ * a service named Gateway and that it will use the cdevData
+ * tag 'server' to locate the gateway using the CDEV Name Server.
+ */
+service Gateway 
+   {
+   tags {server}
+   }
+ 
+/*
+ * This class definition identifies the class gatewayClass which
+ * supports the "get","set", "monitorOn" and "monitorOff"
+ * commands on attributes "attrib0" and "attrib1". Note that
+ * requests made to attrib0 will be routed through "Gateway1"
+ * and requests made to attrib1 will be routed through 
+ * "Gateway2".
+ */ 
+class gatewayClass 
+   {
+       verbs {get, set, monitorOn, monitorOff}
+   attributes 
+      { 
+      attrib0 Gateway {server=Gateway1};
+      attrib1 Gateway {server=Gateway2};
+      }
+}
+ 
+/*
+ * Finally, the CDEV DDL identifies two devices that are of type
+ * gatewayClass. Any time one of the supported messages is passed
+ * to one of these devices it will be routed through a CDEV 
+ * Gateway.
+ */
+gatewayClass : device0, device1;
+			
+
+
+ +

+ + +

+
+ diff --git a/applications/cdevGateway/doc/makehtml b/applications/cdevGateway/doc/makehtml new file mode 100755 index 0000000..65f798a --- /dev/null +++ b/applications/cdevGateway/doc/makehtml @@ -0,0 +1,21 @@ +#! /bin/csh + +if( -f fmbatch.dat) rm fmbatch.dat +if( -d html) rm -rf html +mkdir -p html +cp $CDEV/doc/bullet.jpg html + +foreach x (`find . -name \*.doc -a ! -name \*TOC.doc -a ! -name \*LOF.doc`) + echo "Open $x" >> fmbatch.dat + echo "SaveAs ma $x html/`basename $x .doc`.mif" >> fmbatch.dat + end + +fmbatch fmbatch.dat + +cd html + +foreach x (`find . -name \*.mif -a ! -name \*TITLE.mif`) + mif2html -t 'CDEV Gateway Documentation' -o `basename $x .mif`.html `basename $x .mif`TITLE.mif \-TOC \-LOF $x + end + +rm *.mif diff --git a/applications/cdevGateway/server/.shobj/Linux/cdevGateway.o b/applications/cdevGateway/server/.shobj/Linux/cdevGateway.o new file mode 100644 index 0000000..08f58be Binary files /dev/null and b/applications/cdevGateway/server/.shobj/Linux/cdevGateway.o differ diff --git a/applications/cdevGateway/server/Makefile b/applications/cdevGateway/server/Makefile new file mode 100755 index 0000000..91d5811 --- /dev/null +++ b/applications/cdevGateway/server/Makefile @@ -0,0 +1,15 @@ +ARCH = OS +SHOBJ = YES + +include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.$(ARCH) + +APPNAME = "CDEV Gateway Server" +CXXINCLUDES = -I./ +LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + +TARGETS = $(CDEVBIN)/cdevGateway + +targets : $(TARGETS) + +$(CDEVBIN)/cdevGateway : $(OBJDIR)/cdevGateway.o + $(LINK.cc) -o $@ $^ $(LIBS) diff --git a/applications/cdevGateway/server/NMakefile.mak b/applications/cdevGateway/server/NMakefile.mak new file mode 100755 index 0000000..2e637f1 --- /dev/null +++ b/applications/cdevGateway/server/NMakefile.mak @@ -0,0 +1,20 @@ +.SUFFIXES: .cc .obj + +APPNAME = "CDEV Gateway Program" +ARCH = WINNT-4.0 +SHOBJ = YES + +BINARIES = $(CDEVBIN)\cdevGateway.exe + +include ..\..\..\extensions\cdevGenericServer\include\makeinclude\Makefile.WINNT-4.0 + +CXXINCLUDES = /I .\\ + +targets : $(BINARIES) + +$(CDEVBIN)\cdevGateway.exe : .exec\$(TARGETDIR)\cdevGateway.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... diff --git a/applications/cdevGateway/server/cdevGateway.cc b/applications/cdevGateway/server/cdevGateway.cc new file mode 100755 index 0000000..921b935 --- /dev/null +++ b/applications/cdevGateway/server/cdevGateway.cc @@ -0,0 +1,248 @@ +#include +#include +#include +#include + +#include "cdevGateway.h" + +GatewayServer *gatewayServer; + +// ***************************************************************************** +// * GatewayServer::GatewayServer : +// * This is the constructor for the gateway server. It initializes the +// * underlying cdevServer object and sets the nextCollectionInt variable +// * to zero. +// * +// * The constructor will also extract all of the file descriptors from the +// * cdevSystem object and will create a GatewayHandler for each of them... +// * The fdChangedCallback method will be register with the cdevSystem to +// * ensure that these GatewayHandlers will be regularly updated/removed +// * as they become connected and disconnected. +// ***************************************************************************** +GatewayServer::GatewayServer ( char * domain, char * server, unsigned short port, double pulse ) + : cdevServer(domain, server, port, pulse), nextCollectionInt(0) + { + int fdBufSize = 256; + int * fdBuf = NULL; + + // ********************************************************************* + // * Get the list of all file descriptors that are in use by the + // * cdevSystem class. + // ********************************************************************* + do { + fdBuf = new int[fdBufSize]; + if(cdevSystem::defaultSystem().getFd(fdBuf, fdBufSize)!=CDEV_SUCCESS) + { + delete fdBuf; + fdBufSize *= 2; + fdBuf = NULL; + } + } while (fdBuf==NULL); + + // ********************************************************************* + // * Create a GatewayHandler to manage each of the file descriptors + // * that was provided by the cdevSystem class, and register them with + // * the Reactor. + // ********************************************************************* + for(int i=0; iReactor.registerHandler(hdlr, cdevEventHandler::READ_MASK); + } + else server->Reactor.removeHandler(fd); + } + + +// ***************************************************************************** +// * GatewayServer::handleTimeout : +// * This is the handleTimeout method. It is called by the cdevReactor +// * periodically to make sure that all events are being handled. +// ***************************************************************************** +int GatewayServer::handleTimeout ( void ) + { + cdevSystem::defaultSystem().pend(0.001); + return 0; + } + +// ***************************************************************************** +// * GatewayServer::processMessages : +// * This is the processMessages method. It receives the inbound requests +// * from the clients and then calls CDEV to process the requests. +// ***************************************************************************** +void GatewayServer::processMessages ( void ) +{ +int data_handled = 0; +cdevMessage * request; +while(dequeue(request)==0) + { + if(!strcmp(request->getMessage(), "register") || + !strcmp(request->getMessage(), "unregister")) + { + enqueue(request); + delete (request); + } + else + { + int result (CDEV_SUCCESS); + cdevCallback cb (gatewayCallback, request); + int deviceCount (request->getDeviceCount()); + char ** deviceList = request->getDeviceList(); + char * message = request->getMessage(); + cdevData * context = request->getContext(); + cdevData * dataOut = request->getData(); + cdevRequestObject * req = NULL; + + if(deviceCount<=0 || deviceList==NULL || message==NULL) + { + result = CDEV_ERROR; + } + else + { + if(deviceCount==1) + { + req = cdevRequestObject::attachPtr(deviceList[0], message); + } + else { + char name[32]; + sprintf(name, "~Collection%i", nextCollectionInt++); + cdevCollection *col = cdevCollection::attachPtr(name); + col->add(deviceCount, deviceList); + req = col->getRequestObject(message); + } + if(context) req->setContext(*context); + result = req->sendCallback(dataOut, cb); + if(result==CDEV_SUCCESS) data_handled++; + } + + if(result != CDEV_SUCCESS) + { + request->setCompletionCode(result); + enqueue(request); + delete request; + } + } + + // ********************************************************************* + // * Note: The developer MUST do a pend at this point in order to + // * have the file descriptors updated... However, the wait time can be + // * very, very short. + // ********************************************************************* + if(data_handled) cdevSystem::defaultSystem().pend(0.000001); + } +} + +// ***************************************************************************** +// * GatewayServer::gatewayCallback : +// * This is the callback function that is called each time a request has +// * been processed by CDEV. The cdevMessage that was used to make the +// * request is stored in the userarg parameter and this method will pass +// * the result to the cdevGateway for processing. +// * +// * When the isTransactionDone flag is set to TRUE, this method will +// * delete the cdevMessage object. +// ***************************************************************************** +void GatewayServer::gatewayCallback ( int status, void *userarg, cdevRequestObject &, cdevData &data) + { + cdevMessage * message = (cdevMessage *)userarg; + + + message->setCompletionCode(status); + message->setData(&data, 1); + message->setOperationCode(cdevCallback::isTransactionDone()?1:0); + gatewayServer->enqueue(message); + message->setData(NULL); + + if(cdevCallback::isTransactionDone()) delete message; + } + + +int main(int argc, char ** argv) + { + char serverName[255]; + int serverPort = 9573; + int mismatch = 0; + + strcpy(serverName, "Gateway1"); + + for(int i=1; i +HEADING1 HEADING1 # to
(HEADING0 becomes

, HEADING1 +HEADING2 HEADING2 # becomes

, etc.). Links to them are +HEADING3 HEADING3 # placed in the automatically generated table +HEADING4 HEADING4 # of contents. The FrameMaker paragraph +HEADING5 HEADING5 # numbering is used. You probably don't want +HEADING6 HEADING6 # to use HEADING0, as TITLE and LOCALTITLE are + # translated to

. HEADING6 is translated + # to

as there is no in basic HMTL. + +UHEADING0 UHEADING0 # These are translated to HTML headings

+UHEADING1 UHEADING1 # to

; however, they are omitted from the +UHEADING2 UHEADING2 # automatically generated table of contents. +UHEADING3 UHEADING3 # The FrameMaker paragraph numbering is used. +UHEADING4 UHEADING4 # The comments above regarding HEADING0 and +UHEADING5 UHEADING5 # HEADING6 also apply to UHEADING0 and +UHEADING6 UHEADING6 # UHEADING6. + +INDENTHEADING0 INDENTHEADING0 # These are the same as UHEADING, but are +INDENTHEADING1 INDENTHEADING1 # indented one level using the HTML
    tag. +INDENTHEADING2 INDENTHEADING2 # The comments above regarding HEADING0 and +INDENTHEADING3 INDENTHEADING3 # HEADING6 also apply to INDENTHEADING0 +INDENTHEADING4 INDENTHEADING4 # and INDENTHEADING6. +INDENTHEADING5 INDENTHEADING5 +INDENTHEADING6 INDENTHEADING6 + +BODY BODY # Normal text. + +GLOSSARY1 GLOSSARY1 # FrameMaker lists of the type: +GLOSSARY2 GLOSSARY2 # shortlong text +GLOSSARY3 GLOSSARY3 # shortlong text +COMGLOSSARY1 COMGLOSSARY1 # shortlong text +COMGLOSSARY2 COMGLOSSARY2 # etc. +COMGLOSSARY3 COMGLOSSARY3 # Translated to : + #
    + #
    short
    long text + #
    short
    long text + #
    short
    long text + # etc. + #
    + # If the paragraph type is COMGLOSSARY then + #
    becomes
    . This means that + # the viewer will try to fit the short text + # and the long text in one line. Otherwise + # the short text will be on a separate line + # with the long text below shifted to the + # right. This should give a reasonable result + # given that the short text is up to 4 + # characters long. Otherwise the long text is + # displayed on a separate line (viewer- + # dependent). + # + # GLOSSARY2, GLOSSARY3, COMGLOSSARY2 and + # COMGLOSSARY3 are indented. + +PROGRAM PROGRAM # Program code is considered to be + # preformatted (
     in HTML).
    +
    +REFERENCE 	REFERENCE	# Assumed to be FrameMaker lines of the type:
    +COMREFERENCE	COMREFERENCE	#	[1]	Reference 1
    +				#	[2]	Reference 2
    +				#	[3]	Reference 3
    +				#	etc.
    +				# where the [?] is the paragraph numbering.
    +				# Becomes:
    +				#	
    + #
    [1]
    Reference 1 + #
    [2]
    Reference 2 + #
    [3]
    Reference 3 + # etc. + #
    + # If the paragraph type is COMREFERENCE then + #
    becomes
    . This means that + # the viewer will try to fit the paragraph + # numbering and and the reference text in one + # line. Otherwise the paragraph numbering + # will be on a separate line with the + # reference text below shifted to the right. + +TITLE TITLE # The title of the document. It is always + # moved to the head of the file (or indexfile), + # before the automatically generated index. + # Translates as HTML

    . + +LOCALTITLE LOCALTITLE # The title of the current chapter or file. + # Printed wherever it is. Translates as HTML + #

    . + +TOC TOC # Paragraphs with this tag are removed. All + # paragraphs with paragraph tags with "TOC", + # "IX", "LOT", "LOF", "AIX", "AML", "APL", + # "IOM", "LOM", "LOP" or "SIX" in them are + # also removed. They are assumed to be + # generated by FrameMaker. + +ADDRESS ADDRESS # Corresponds to the
    tag in HTML. + +AUTHOR AUTHOR # The author of the document. This is moved + # to the head of the file (or indexfile), + # after the title and before the automatically + # generated index). Uses
    HTML tag. + +ABSTRACT ABSTRACT # The abstract is emphasized ( tag in + # HTML). + +ACRONYM ACRONYM # This is handled the same as COMGLOSSARY. + +LISTINDENT1 LISTINDENT1 # Non-consecutive lists with full indent +LISTINDENT2 LISTINDENT2 # (HTML:
    item) +LISTINDENT3 LISTINDENT3 +LISTINDENT4 LISTINDENT4 +LISTINDENT5 LISTINDENT5 +LISTINDENT6 LISTINDENT6 + +LISTBULLET1 LISTBULLET1 # Non-consecutive lists with bullet as mark +LISTBULLET2 LISTBULLET2 # (HTML:
    • item) +LISTBULLET3 LISTBULLET3 +LISTBULLET4 LISTBULLET4 +LISTBULLET5 LISTBULLET5 +LISTBULLET6 LISTBULLET6 + +LISTMARK1 LISTMARK1 # Lists using MIF PgfNumString as mark +LISTMARK2 LISTMARK2 # (HTML:
      mark
      item) +LISTMARK3 LISTMARK3 +LISTMARK4 LISTMARK4 +LISTMARK5 LISTMARK5 +LISTMARK6 LISTMARK6 + +LISTNUMBER1 LISTNUMBER1 # Numbered consecutive lists +LISTNUMBER2 LISTNUMBER2 # (HTML:
      1. item) +LISTNUMBER3 LISTNUMBER3 +LISTNUMBER4 LISTNUMBER4 +LISTNUMBER5 LISTNUMBER5 +LISTNUMBER6 LISTNUMBER6 + +LISTCONTINUE1 LISTCONTINUE1 # Additional paragraphs in any type of list +LISTCONTINUE2 LISTCONTINUE2 +LISTCONTINUE3 LISTCONTINUE3 +LISTCONTINUE4 LISTCONTINUE4 +LISTCONTINUE5 LISTCONTINUE5 +LISTCONTINUE6 LISTCONTINUE6 + +FIGURE FIGURE # Figure text is indented + +TABLE TABLE # Table text is indented + +CELLHEADING CELLHEADING # Table heading becomes bold +CELLBODY CELLBODY # Table cells become normal text + +FOOTNOTE BODY # Footnotes are treated as normal text + +HTML1 HTML

        ; # User defined tags. First specify start +HTML2 HTML

        ; # tag(s) then ; and then optional end tag(s). + +# Add your own tag mappings below + +Numbered LISTNUMBER1 +Indented LISTINDENT1 +FUNC_NAME BODY +FUNC_PROTO BODY +FUNC_DEF BODY +FUNC_DEF2 BODY +Bulleted LISTBULLET1 +OMT_METHOD BODY +FIGURE_CONT BODY +FUNCTION_DEF BODY +Centered INDENTHEADING2 +Heading1 HEADING2 +Numbered1 LISTNUMBER1 +IndentedBold INDENTHEADING1 +HeadingRunIn INDENTHEADING1 + +Abstract ABSTRACT +Acronym ACRONYM +Address BODY +Bibliography BODY +Blank Page Msg BODY +Body BODY +Change TABLE +Credit COMGLOSSARY1 +Doc (Applicable) COMREFERENCE +Doc (Reference) COMREFERENCE +Equation BODY +Equation (Appendix) BODY +Example BODY +Figure Title FIGURE +Figure TitleLOF BODY +Figure Title (Appendix) FIGURE +Footer BODY +Footnote BODY +Guideline BODY +Header BODY +Heading 1 HEADING1 +Heading 1TOC UHEADING1 +Heading 1 (Appendix) HEADING1 +Heading 1 (Appendix)TOC UHEADING1 +Heading 2 HEADING2 +Heading 2TOC UHEADING2 +Heading 2 (Appendix) HEADING2 +Heading 2 (Appendix)TOC UHEADING2 +Heading 3 HEADING3 +Heading 3TOC UHEADING3 +Heading 3 (Appendix) HEADING3 +Heading 3 (Appendix)TOC UHEADING3 +Heading 4 HEADING4 +Heading 4TOC UHEADING4 +Heading 4 (Appendix) HEADING4 +Heading 4 (Appendix)TOC UHEADING4 +Heading 5 HEADING5 +Heading 5TOC UHEADING5 +Heading 5 (Appendix) HEADING5 +Heading 5 (Appendix)TOC UHEADING5 +Heading 6 HEADING6 +Heading 6TOC UHEADING6 +Heading 6 (Appendix) HEADING6 +Heading 6 (Appendix)TOC UHEADING6 +List Initialize BODY +List Bullet 1 LISTBULLET1 +List Bullet 2 LISTBULLET2 +List Bullet 3 LISTBULLET3 +List Bullet 4 LISTBULLET4 +List Bullet 5 LISTBULLET5 +List Bullet 6 LISTBULLET6 +List Char 1 LISTNUMBER1 +List Char 2 LISTNUMBER2 +List Char 3 LISTNUMBER3 +List Char 4 LISTNUMBER4 +List Char 5 LISTNUMBER5 +List Char 6 LISTNUMBER6 +List Num 1 LISTNUMBER1 +List Num 2 LISTNUMBER2 +List Num 3 LISTNUMBER3 +List Num 4 LISTNUMBER4 +List Num 5 LISTNUMBER5 +List Num 6 LISTNUMBER6 +List Cont 1 LISTCONTINUE1 +List Cont 2 LISTCONTINUE2 +List Cont 3 LISTCONTINUE3 +List Cont 4 LISTCONTINUE4 +List Cont 5 LISTCONTINUE5 +List Cont 6 LISTCONTINUE6 +List Hang 1 LISTMARK1 +List Hang 2 LISTMARK2 +List Hang 3 LISTMARK3 +List Hang 4 LISTMARK4 +List Hang 5 LISTMARK5 +List Hang 6 LISTMARK6 +Message BODY +Page Number BODY +Paragraph BODY +Preformatted PROGRAM +Requirement BODY +Subheading UHEADING4 +Table Cell (Center) CELLBODY +Table Cell (Decimal) CELLBODY +Table Cell (Left) CELLBODY +Table Cell (Right) CELLBODY +Table Cell Bullet 1 CELLBODY +Table Cell Bullet 2 CELLBODY +Table Cell Char 1 CELLBODY +Table Cell Char 2 CELLBODY +Table Cell Cont 1 CELLBODY +Table Cell Cont 2 CELLBODY +Table Cell Num 1 CELLBODY +Table Cell Num 2 CELLBODY +Table Heading (Center) CELLHEADING +Table Heading (Left) CELLHEADING +Table Heading (Right) CELLHEADING +Table Title BODY +Table TitleLOT BODY +Table Title (Appendix) BODY +Title LOCALTITLE diff --git a/doc/cdevIntroduction.book b/doc/cdevIntroduction.book new file mode 100755 index 0000000..2e5117e Binary files /dev/null and b/doc/cdevIntroduction.book differ diff --git a/doc/cdevIntroduction.doc b/doc/cdevIntroduction.doc new file mode 100755 index 0000000..a6a61b2 Binary files /dev/null and b/doc/cdevIntroduction.doc differ diff --git a/doc/cdevIntroductionLOF.doc b/doc/cdevIntroductionLOF.doc new file mode 100755 index 0000000..f4dfee6 Binary files /dev/null and b/doc/cdevIntroductionLOF.doc differ diff --git a/doc/cdevIntroductionTITLE.doc b/doc/cdevIntroductionTITLE.doc new file mode 100755 index 0000000..9dab765 Binary files /dev/null and b/doc/cdevIntroductionTITLE.doc differ diff --git a/doc/cdevIntroductionTOC.doc b/doc/cdevIntroductionTOC.doc new file mode 100755 index 0000000..7a75c0b Binary files /dev/null and b/doc/cdevIntroductionTOC.doc differ diff --git a/doc/cdevReference.book b/doc/cdevReference.book new file mode 100755 index 0000000..aaf8e47 Binary files /dev/null and b/doc/cdevReference.book differ diff --git a/doc/cdevReference.doc b/doc/cdevReference.doc new file mode 100755 index 0000000..3b66a78 Binary files /dev/null and b/doc/cdevReference.doc differ diff --git a/doc/cdevReferenceLOF.doc b/doc/cdevReferenceLOF.doc new file mode 100755 index 0000000..5cebc78 Binary files /dev/null and b/doc/cdevReferenceLOF.doc differ diff --git a/doc/cdevReferenceTITLE.doc b/doc/cdevReferenceTITLE.doc new file mode 100755 index 0000000..26e79cd Binary files /dev/null and b/doc/cdevReferenceTITLE.doc differ diff --git a/doc/cdevReferenceTOC.doc b/doc/cdevReferenceTOC.doc new file mode 100755 index 0000000..aaea1a2 Binary files /dev/null and b/doc/cdevReferenceTOC.doc differ diff --git a/doc/cdevServiceGuide.book b/doc/cdevServiceGuide.book new file mode 100755 index 0000000..6bafd3a Binary files /dev/null and b/doc/cdevServiceGuide.book differ diff --git a/doc/cdevServiceGuide.doc b/doc/cdevServiceGuide.doc new file mode 100755 index 0000000..4b20d39 Binary files /dev/null and b/doc/cdevServiceGuide.doc differ diff --git a/doc/cdevServiceGuideLOF.doc b/doc/cdevServiceGuideLOF.doc new file mode 100755 index 0000000..8ffc144 Binary files /dev/null and b/doc/cdevServiceGuideLOF.doc differ diff --git a/doc/cdevServiceGuideTITLE.doc b/doc/cdevServiceGuideTITLE.doc new file mode 100755 index 0000000..e228b57 Binary files /dev/null and b/doc/cdevServiceGuideTITLE.doc differ diff --git a/doc/cdevServiceGuideTOC.doc b/doc/cdevServiceGuideTOC.doc new file mode 100755 index 0000000..76b1bb5 Binary files /dev/null and b/doc/cdevServiceGuideTOC.doc differ diff --git a/doc/cdevTutorial.book b/doc/cdevTutorial.book new file mode 100755 index 0000000..4beadc6 Binary files /dev/null and b/doc/cdevTutorial.book differ diff --git a/doc/cdevTutorial.doc b/doc/cdevTutorial.doc new file mode 100755 index 0000000..9cee0c6 Binary files /dev/null and b/doc/cdevTutorial.doc differ diff --git a/doc/cdevTutorialLOF.doc b/doc/cdevTutorialLOF.doc new file mode 100755 index 0000000..c5739f3 Binary files /dev/null and b/doc/cdevTutorialLOF.doc differ diff --git a/doc/cdevTutorialTITLE.doc b/doc/cdevTutorialTITLE.doc new file mode 100755 index 0000000..42de67f Binary files /dev/null and b/doc/cdevTutorialTITLE.doc differ diff --git a/doc/cdevTutorialTOC.doc b/doc/cdevTutorialTOC.doc new file mode 100755 index 0000000..ea0e55e Binary files /dev/null and b/doc/cdevTutorialTOC.doc differ diff --git a/doc/cdevUtilities.book b/doc/cdevUtilities.book new file mode 100755 index 0000000..dbc45f3 Binary files /dev/null and b/doc/cdevUtilities.book differ diff --git a/doc/cdevUtilities.doc b/doc/cdevUtilities.doc new file mode 100755 index 0000000..d34ff73 Binary files /dev/null and b/doc/cdevUtilities.doc differ diff --git a/doc/cdevUtilitiesLOF.doc b/doc/cdevUtilitiesLOF.doc new file mode 100755 index 0000000..49f2c9e Binary files /dev/null and b/doc/cdevUtilitiesLOF.doc differ diff --git a/doc/cdevUtilitiesTITLE.doc b/doc/cdevUtilitiesTITLE.doc new file mode 100755 index 0000000..6164e0d Binary files /dev/null and b/doc/cdevUtilitiesTITLE.doc differ diff --git a/doc/cdevUtilitiesTOC.doc b/doc/cdevUtilitiesTOC.doc new file mode 100755 index 0000000..5219f56 Binary files /dev/null and b/doc/cdevUtilitiesTOC.doc differ diff --git a/doc/fmbatch.dat b/doc/fmbatch.dat new file mode 100755 index 0000000..27a045a --- /dev/null +++ b/doc/fmbatch.dat @@ -0,0 +1,4 @@ +Open releaseNotes1_7.doc +SaveAs ma releaseNotes1_7.doc html/releaseNotes1_7.mif +Open releaseNotes1_7TITLE.doc +SaveAs ma releaseNotes1_7TITLE.doc html/releaseNotes1_7TITLE.mif diff --git a/doc/html/TestPlan_1.5.html b/doc/html/TestPlan_1.5.html new file mode 100755 index 0000000..04fd9f4 --- /dev/null +++ b/doc/html/TestPlan_1.5.html @@ -0,0 +1,555 @@ + + +CDEV Documentation + + + + + + + + +



        + + + +
        + + + + NOTE: Information addressing the appropriate content of each of the following sections can be found + in Section 2.0 of the Test Plan Instructions. +

        +
        +


        + + + +
        + + Test Plan Title: +

        +
        + + CDEV 1.5 Release Test +

        +
        +


        + + + +
        + + + + Author(s): + Walt Akers +

        + + Date Submitted: + Dec 10, 1996 +

        + + + +
        + + Revision Number: +

        +
        + + Rev. 1, Dec 10, 1996 +

        +
        + + Brief Purpose of Test +

        + + + +
        + + + This test will ensure the proper operation of the Control Device Interface (CDEV) + Version 1.5. +

        +
        + + Anticipated Benefits +

        + + + +
        + + + The new version of CDEV will introduce Collection Devices into the API and will + correct several deficiencies that were identified in earlier versions of the class + library. +

        +
        + + Beam Conditions Required +

        + + + +
        + + + Complete all of the following tables, entering a value or an X in the appropriate spaces: + + + + + + + + + + + + + + + + + +
        + + Beam Type/Current (enter value) +
        +
        + + +
        +
        + + Beam Type/Current (enter value) +
        +
        + + +
        +
        + + Beam Type +
        +
        + + Beam Current +
        +
        + + Beam Off +
        +
        + + +
        +
        + + + + + + + + + + + + + + + + + + + +
        + + Beam Energy (select one) +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + Beam Energy (select one) +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + + + + + + + + + + + + + + + + + + +
        + + Beam Termination Point (select one) +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + Beam Termination Point (select one) +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + +
        +
        + + + + + + + + + +
        + + Type of Test (select one) +
        +
        + + +
        +
        + + Type of Test (select one) +
        +
        + + +
        +
        +

        +
        + + Time Required +

        + + + +
        + + + 30 Minutes +

        +
        + + Preferred Time of Test +

        + + + +
        + + + Daylight +

        +
        + + Staff Required to Execute the Test (including contact info) +

        + + + +
        + + + Walt Akers - ext. 7669 +

        +
        + + Controlled Access Requirements +

        + + + +
        + + + None +

        +
        + + Hardware and/or Software Changes Required +

        + + + +
        + + + NOTE: If software changes are part of the test plan, include the name of the application, the old + revision level, the new revision level, and if applicable, whether or not it is possible to roll back to the + old revision level (are there hardware limitations, etc.). +

        + No existing software will be modified. A new version of CDEV will be added. +

        +
        + + Setup Procedure +

        + + + + + + + +
        + + 1. +

        +
        + + Install and compile the CDEV libraries in /usr/csite2/cdev/1.5 +

        +
        + + 2. +

        +
        + + Unarchive and compile ACE Version 4.0.32 +

        +
        + + 3. +

        +
        + + Compile and link the CDEV Generic Server Engine +

        +
        + + Test Procedure +

        + + + + + + + +
        + + 1. +

        +
        + + Execute /usr/csite2/cdev/1.5/test/cdevDataTest Application to ensure that the + data components of the library are functioning properly. +

        +
        + + 2. +

        +
        + + Execute /usr/csite2/cdev/1.5/test/collectionTest Application to ensure that + CDEV collection devices are functioning properly (this requires the local + test.ddl to be the CDEVDDL file.) +

        +
        + + 3. +

        +
        + + Execute /usr/csite2/cdev/1.5/extensions/cdevGenericServer/bin/hpux-09.XX/ + NameServer, TestServer and TestProgram to ensure that the CDEV Generic + Server Engine and communications portions of CDEV are functioning cor + rectly. +

        +
        + + Backout Procedure +

        + + + +
        + + 1. +

        +
        + + Because the version of CDEV that is in use is a selectable value, the installation + and operation of Version 1.5 of CDEV is of no impact unless it is specifically + chosen. Therefore, no backout procedures are specified. +

        +
        + + Test Results +

        + + + +
        + + + The test was conducted for two version of the operating system, therefore, the + results will be presented separately: +

        + HPUX 09.XX: +

        + cdevDataTest Program: Pass on all 18 Sub-Tests +

        + cdevDataEqualTest Program: Pass +

        + cdevDataTagMapTest Program: Pass +

        + collectionTest Program: Pass on 1000 Iterations +

        + +

        + NameServer Program: Executed correctly +

        + TestServer Program: Executed correctly for 100,000 packets. +

        + TestProgram Program: Executed correclty for 100,000 packets. +

        + +

        + HPUX 10.XX: +

        + The following corrections had to be made to the system in order to get the + 10.XX machines to function properly. +

        + +

        + Directory /cs/lib had to be linked to /cs/op/lib. +

        + Directory /usr/csite/cdev had to be linked to directory /usr/csite2/cdev. +

        + File /cs/lib/epics3.12/hpux-10.xx/libca.sl had to be made executable. +

        + +

        + cdevDataTest Program: Pass on all 18 Sub-Tests +

        + cdevDataEqualTest Program: Pass +

        + cdevDataTagMapTest Program: Pass +

        + collectionTest Program: Pass on 1000 Iterations +

        + +

        + NameServer Program: Executed correctly +

        + TestServer Program: Executed correctly for 215,000 packets. +

        + TestProgram Program: Executed correclty for 215,000 packets. +

        + +

        +
        +
        + diff --git a/doc/html/bullet.jpg b/doc/html/bullet.jpg new file mode 100755 index 0000000..a79a191 Binary files /dev/null and b/doc/html/bullet.jpg differ diff --git a/doc/html/cdevAdminGuide.html b/doc/html/cdevAdminGuide.html new file mode 100755 index 0000000..96ca7f0 --- /dev/null +++ b/doc/html/cdevAdminGuide.html @@ -0,0 +1,556 @@ + + +CDEV Documentation + + + + + + +


        + + + +
        + + + + CDEV Administrator's + Guide +

        + + Chip Watson, Jie Chen, Danjin Wu, Walt Akers +

        + +

        + Version 1.5 December 9, 1996 +

        + +

        + TJNAF - Thomas Jefferson National Accelerator Facility +

        +
        + +


        + + + + + +
        + + + + Table of Contents +

        +
        + + + + + + + + + + + + + + + + + +
        + + 1. +
        +
        + + Directory Structure of the CDEV Distribution +
        +
        + + +
        +
        + + Directory Structure +
        +
        + + 2. +
        +
        + + Installing and Building the CDEV Libraries +
        +
        + + +
        +
        + + How to Start +
        +
        + + +
        +
        + + Configuring Static Services +
        +
        + + +
        +
        + + Setting the Local Environment +
        +
        + + +
        +
        + + Compiling the Distribution +
        +
        +
        + + +


        + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + + Directory Structure of the CDEV Distribution +

        +
        + + + Directory + Structure +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + ./src +

        +
        + + The CDEV source parent directory, it contains makefiles and + subdirectories with the source code necessary to create the + CDEV libraries. +

        +
        + + ./src/ca +

        +
        + + Souce code providing CDEV service support for channel + access and EPICS. +

        +
        + + ./src/cdevIO +

        +
        + + Souce code for the cdevData object and its components. +

        +
        + + ./src/common +

        +
        + + Source code for CDEV components that are used by class + internals. +

        +
        + + ./src/callback +

        +
        + + Source code for the cdevCallback object used with callback + operations and monitors. +

        +
        + + ./src/device +

        +
        + + Source code for the cdevDevice and cdevRequestObject + objects and their associated component classes. +

        +
        + + ./src/directory +

        +
        + + Source code for the cdevDirectory anc cdevSvcFinder classes. +

        +
        + + ./src/group +

        +
        + + Source code for the cdevGroup and cdevTranObj classes. +

        +
        + + ./src/lib +

        +
        + + Directory for library Makefile and temporary object files. +

        +
        + + ./src/namesvc +

        +
        + + Source code for tools used to parse the CDEV DDL file. +

        +
        + + ./src/system +

        +
        + + Source code for the cdevSystem and cdevService classes and + their associated components. +

        +
        + + ./src/utility +

        +
        + + Source code for a CDEV utility application. +

        +
        + + ./include +

        +
        + + Header files for CDEV applications, this directory will be + populated during the first execution of make +

        +
        + + ./lib +

        +
        + + The CDEV library parent directory, will be populated wth + subdirectories for each target architecture. +

        +
        + + ./bin +

        +
        + + The CDEV binary parent directory, will be populated wth + subdirectories for each target architecture. +

        +
        + + ./doc +

        +
        + + Contains most up to date versions of the CDEV documentation. +

        +
        + + ./example +

        +
        + + Sample applications and services that use CDEV. +

        +
        + + ./extensions +

        +
        + + Software extensions and services for CDEV that are being + developed by individual developers. These services add value + to CDEV, however, they are not required by the system. +

        +
        +
        + + 2. +

        +
        + + + Installing and Building the CDEV Libraries +

        +
        + + + How to Start +

        +
        + + The following steps should be taken in order to obtain and install CDEV at your site. +

        + + + + + +
        + + 1. +

        +
        + + Obtain a copy of the CDEV distribution. A complete copy of the CDEV + distribution may be obtained by anonymous ftp at ftp.cebaf.gov in the directory + pub/cdev. +

        +
        + + 2. +

        +
        + + Unarchive and install the distribution. The CDEV distribution is provided in a + compressed and archived format. The archive may be decompressed using the + GNU gzip program. The archive may then be extracted using the UNIX tar + command. +

        +
        +
        + + + Configuring Static + Services +

        +
        + + + +
        + + 3. +

        +
        + + Configure static services (archive libraries). If you will be using the archive + library version of CDEV, you must tell CDEV the names of the services it will be + expected to use. This must be done before any other installation procedures. +

        + + The CDEV system provides a way to configure services so that applications can + access them by name. For example, if you have the channel access service (ca) + and a locally developed service (xyz), you can configure CDEV to use these + services with the following command. +

        +
        +
        
        + 
        +   configSvc services=ca xyz headers=/usr/local/epics/include \\
        +      /usr/local/cdev/src/ca /usr/local/cdev/src/xyz
        +	
        + + + +
        + + + +

        + In the above examples, services are the names of the CDEV services that should + be supported, and headers are the directories that should be searched for the + associated header files for these services. The configSvc script will generate a + Makefile and cdevSvcConfig.cc in the ./src/directory directory. +

        + + +

        +
        +
        + + + Setting the Local + Environment +

        +
        + + + +
        + + 4. +

        +
        + + Set CDEV required make variables. The following environmental variables must + be defined prior to making the CDEV libraries. +

        + + CDEV: This is the root directory of the CDEV distribution. +

        + +

        + CDEVDDL: This is the location of the CDEV Device Definition + Language file. +

        + +

        + CDEVSHOBJ: This is the directory where the CDEV shared + libraries and shared objects will be stored. +

        + +

        + CDEVINCLUDE: This is the directory whewre the CDEV header files + are located. +

        + +

        + SHOBJ: This variable indicates that a sharable object library + should be compiled. In order to generate a + sharable library, SHOBJ="YES" should be + specified. This variable is undefined by default. +

        +
        +
        + + + Compiling the + Distribution +

        +
        + + + + + + + + + + + +
        + + 5. +

        +
        + + Change directories to the CDEV distribution ./src directory. This is where the + Makefile and Makefile.common will be located. +

        +
        + + 6. +

        +
        + + If you have compiled the CDEV distribution for another TARGET in the past, you + should execute a 'make clean' to remove any outdated object files. +

        +
        + + 7. +

        +
        + + If you want to change default time-out value and connection retry frequency in + channel access or EPICS, you should change DEFAULT_TIMEOUT and + DEFAULT_CONN_FREQUENCY values in the caRequestObject.h. +

        +
        + + 8. +

        +
        + + To begin compilation type the command 'make all' or 'make'. This will compile all + libraries and utility applications and place them in the appropriate TARGET + directories. +

        +
        + + 9. +

        +
        + + To remove objects after making archive libraries, type 'make cleanObjs'. This is + useful to make the archive libraries and then make the shared libraries. +

        +
        +
        + diff --git a/doc/html/cdevCbinding.html b/doc/html/cdevCbinding.html new file mode 100755 index 0000000..9d92242 --- /dev/null +++ b/doc/html/cdevCbinding.html @@ -0,0 +1,699 @@ + + +CDEV Documentation + + + + + + +


        + + + +
        + + + + CDEV C Binding Guide +

        + + +

        + Chip Watson, Jie Chen, Danjin Wu, Walt Akers +

        + +

        + Version 1.4 October 24, 1996 +

        + +

        + TJNAF - Thomas Jefferson National Accelerator Facility +

        + +

        +
        + + + +


        + + + + + + + + + +
        + + + + cdev C Binding +

        + + Updated: +

        + +

        +
        + + + + This working document describes a C binding to the cdev control system interface (see the cdev + Design Document, and the cdev User's Guide). +

        + + Design Choices: +

        + + + + + + + +
        + + 1. +

        +
        + + All C routine names begin with "cdev" (common device). +

        +
        + + 2. +

        +
        + + Most C routines return completion status; 0==success (allows enumerated errors). A few + return integer values (prefixed in this document with "int"). +

        +
        + + 3. +

        +
        + + All data passed through the interface will be in the form of integers, strings or a self describing + structure. Library calls will be provided to manipulate this structure. +

        +
        + + Comparison with C++ binding: +

        + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + cdevData, cdevRequestObject, and cdevGroup objects will be accessed through object id's. +

        +
        + + 2. +

        +
        + + cdevDevice will only be referenced by device name. +

        +
        + + 3. +

        +
        + + Only a single, default, cdevSystem will be supported. +

        +
        + + 4. +

        +
        + + Since no function overloading is available, I/O operations on a cdevData object will have to + pass a datatype argument, similar to EPICS channel access. +

        +
        + + 5. +

        +
        + + Routines which return strings will malloc the string, and the caller must free it. +

        +
        + + 6. +

        +
        + + Function names are generally constructed from the class name followed by the method name, + e.g. cdevGroupStart. +

        +
        + + 7. +

        +
        + + Creating objects will be done by routines like cdevGroupAllocate, which will essentially + return a pointer to the created object. +

        +
        + + 8. +

        +
        + + cdevSystem methods will drop "System" from the name, and the notion of "system" will be + invisible. +

        +
        + + 9. +

        +
        + + cdevDevice methods will drop "Device". cdevRequestObject methods will use the shorter + "cdevRequest". +

        +
        +
        + + + + C Binding User's Guide +

        +
        + + + + Simple message passing routines: +

        + + Devices are addressed by name, and operations are performed by sending a message string and an + additional optional data object identifier. This data object is self describing in the sense that it con + tains indicators of the data type (int, float, etc.) and size (array lengths). Data returned from the + control system will also be through a data object. +

        + + + +
        + + + status = cdevSend (char* devName, char* message, +

        + cdev_data_t out, cdev_data_t in); +

        +
        + + The data objects act as small databases able to hold multiple tagged data items. Items are inserted + into or extracted from the database via access routines. These access routines are also responsible + for any necessary data type conversions. Tags are passed to the cdevData routines as integers, and + are looked up in the tag database by specifying an ascii tag name. The most common tags are + "value", "timeStamp", "status", and "severity". +

        + Data object manipulation routines: +

        + + + +
        + + + cdevDataAllocate (cdev_data_t* id); +

        + cdevDataFree (cdev_data_t id); +

        + cdevDataTagC2I (char* tag, int *tagid); +

        + cdevDataTagI2C (int tagid, char** tag); /* caller must free string */ +

        + cdevDataInsertTag (int tag, char* ctag); +

        + cdevDataInsert (cdev_data_t id, int tagid, int type, void * data); +

        + int cdevDataInsertArray(cdev_data_t id, int tagid, int type, void *data, size_t len, size_t + ndim); +

        + cdevDataGet (cdev_data_t id, int tagid, int type, void * data); +

        + cdevDataFind (cdev_data_t id, int tagid, void ** data); +

        + int cdevDataGetType (cdev_data_t id, int tagid); +

        + int cdevDataGetDim (cdev_data_t id, int tagid); +

        + int cdevDataGetElems (cdev_data_t id, int tagid); +

        + cdevDataGetBounds (cdev_data_t id, int tagid, int *bounds, int bsize); +

        + cdevDataSetBounds (cdev_data_t id, int tagid, int *bounds, int bsize); +

        + void cdevDataRemoveAll(cdev_data_t id); +

        + cdevDataRemove (cdev_data_t id, int tagid); +

        + cdevDataChangeTag (cdev_data_t id, int tagid, int newtagid); +

        + cdevDataAsciiDump (cdev_data_t id, FILE *fp); +

        + void cdevDataCopy(cdev_data_t from, cdev_data_t *to); +

        +
        + + For example, to read the current from a magnet named NLQ1: +

        + + + +
        + + + cdev_data_t result; +

        + float current; +

        + int status, valtag; +

        + status = cdevDataAllocate (&result); +

        + status = cdevDataTagC2I ("value",&valtag); +

        + status = cdevSend("NLQ1","read current",NULL,result); +

        + status = cdevDataGet(result, valtag, CDEV_FLOAT, current); +

        +
        + + The first call to a device automatically connects to the requested service, initializing any underly + ing packages as needed. These routines are synchronous (operation completes before return); + asynchronous routines are discussed below. +

        + The message (second) argument selects what operation and attribute to access. Many messages + are by convention of the form "verb attribute", and typical verbs include get, set, monitorOn, and + monitorOff. +

        + + Binding a device and message +

        + + In order to avoid the overhead of parsing the device name and message on each call, it is possible + to get a handle which binds the device and message into a request. +

        + + + +
        + + + status = cdevRequestAllocate(char* device, char*message, CDEVREQUESTID* reqid); +

        +
        + + Operations may be performed on this request object without specifying device and message. +

        + + + +
        + + + status = cdevRequestSend(reqid, out, result); +

        +
        + + Request objects maintain a connection to a server, and the state of this connection may be + obtained: +

        + + + +
        + + + state = cdevRequestState (reqid); +

        +
        + + The current access rights (read, write, none) for this request object may be obtained: +

        + + + +
        + + + access = cdevRequestAccess (reqid); +

        +
        + + Given the request object, it is also possible to extract the device name and message: +

        + + + +
        + + + cdevRequestDevice (reqid, char** name); /* caller must free string */ +

        + cdevRequestMessage (reqid, char** msg); +

        +
        + + Monitoring and Asynchronous I/O +

        + + A message sent to a device may result in an asynchronous reply, or more than one reply. In addi + tion, abnormal conditions may occur in the device which are of interest to the application. Each of + these results in a message back to the client which is asynchronous with respect to program exe + cution. Several calls are provided to deal with asynchronous data. +

        + + + +
        + + Asynchronous Messages +

        +
        + +
        + + An asynchronous version of the message send call will send the mes + sage, but not wait for the reply. Two async forms are supported: one returning data to a caller's + data object, and the other returning data to a callback function. The reply argument is replaced by + an additional structure which specified a user callback function. +

        + + + +
        + + + status = cdevSendNoBlock(char* device, char* message, +

        + cdev_data_t out, cdev_data_t result); +

        + status = cdevSendCallback(char* device, char* message, +

        + cdev_data_t out, CDEVCALLBACK* callback); +

        +
        + + Similarly for request objects: +

        + + + + + +
        + + + status = cdevRequestSendNoBlock(cdev_data_t out, cdev_data_t result); +

        + status = cdevRequestSendCallback(cdev_data_t out, CDEVCALLBACK* callback); +

        +
        + + Monitoring: +

        +
        + +
        + + Monitoring is started and stopped by two using the message "monitorOn xxx" and + "monitorOff xxx". +

        + + + + + +
        + + + status = cdevSendCallback("deviceName", "monitorOn attributeName",NULL, callback); +

        +
        + + Synchronization +

        +
        + +
        + + In order to synchronize with asynchronous messages, both a poll and a pend + call are available, as well as an explicit flush. A pend with 0.0 seconds waits forever. +

        + + + +
        + + + cdevFlush (); +

        + cdevPoll (); +

        + cdevPend (float seconds); +

        +
        + + If seconds==0.0, wait forever. +

        + + + +
        + + Grouping +

        +
        + +
        + + Grouping of operations will be similar to that specified for EZCA, with slight varia + tions. The grouping calls are useful for synchronizing with a set of asynchronous calls. +

        + + + + + +
        + + + cdevGroupAllocate(GROUPID* groupid); +

        + cdevGroupStart(groupid); +

        + cdevGroupEnd(groupid); +

        + cdevGroupPoll(groupid); +

        + cdevGroupPend(groupid); +

        + cdevGroupAllFinished (groupid); +

        + cdevGroupStatus (groupid, int *status, int *nstatus); /* initially nstatus = len of status */ +

        +
        + + File Descriptors +

        +
        + +
        + + To integrate other asynchronous systems, such as X windows, it is often neces + sary to obtain file descriptors for select operations. +

        + + + + + +
        + + + status = cdevGetFD(int fd[], int * numFD); +

        +
        + + Context +

        +
        + +
        + + Operations on a device take place within a context. The context is maintained by the + device as a cdev_data_t structure. The following routines are used to get and set the context; set + ting items within the context is done by the cdevData* routines. +

        + + + + + +
        + + + cdevGetContext(char *devname, cdev_data_t *id); +

        + cdevSetContext(char *devname, cdev_data_t id); +

        +
        + + Private Data +

        +
        + +
        + + Each device also maintains a private data pointer, to be used by the application + developer for any purpose desired. +

        + + + +
        + + + cdevGetPrivate (char *devname, void **data); +

        + cdevSetPrivate (char *devname, void *data); +

        +
        + + These same four routines are available for request objects: +

        + + + +
        + + + cdevRequestGetContext (reqid, cdev_data_t *id); +

        + cdevRequestSetContext (reqid, cdev_data_t id); +

        + cdevRequestGetPrivate (reqid, void **data); +

        + cdevRequestSetPrivate (reqid, void *data); +

        +
        + + Error Reporting and Handling +

        + + This group of routines is also modeled after EZCA (assume identical functionality). +

        + Turn automatic error reporting on and off: +

        + + + +
        + + + cdevAutoErrorOn (); +

        + cdevAutoErrorOff (); +

        +
        + + Set the severity threshold at which errors should be reported: +

        + + + +
        + + + cdevSetThreshold (int new); +

        + cdevReportError (int severity, char *name, +

        + CDEVREQUESTID request, char* format, ...); +

        + cdevGetErrorString (); +

        + cdevSetErrorHandler (function); +

        +
        + + Note: For simplicity of use, a very compact set of error codes is implemented in cdev. The follow + ing error codes are defined in the header file cdevErrCode.h. +

        + CDEV_SUCCESS = 0 Success +

        + CDEV_INVALIDOBJ = 1 Invalid cdev object used +

        + CDEV_INVALIDARG = 2 Invalid argument passed to cdev method +

        + CDEV_INVALIDSVC = 3 Wrong service during dynamic loading +

        + CDEV_NOTCONNECTED = 4 Not connected to low-level network service +

        + CDEV_IOFAILED = 5 Low-level network service IO failed +

        + CDEV_CONFLICT = 6 Conflicting of data types or data tags +

        + CDEV_NOTFOUND = 7 Cdev cannot find specified data or tag +

        + CDEV_TIMEOUT = 8 Time out +

        + CDEV_CONVERT = 9 cdevData conversion error +

        + + Name Services +

        + + There is a special device named cdevDirectory which provides a set of query capabilities: +

        + + + +
        + + + status = cdevSend("cdevDirectory", "query", +

        + cdev_data_t selection, cdev_data_t result); +

        +
        + + The selection data object specifies one or more tags used to select device names. The result con + tains a list of devices accessed through the "value" tag. +

        + +

        +
        + diff --git a/doc/html/cdevCollectionDesign.html b/doc/html/cdevCollectionDesign.html new file mode 100755 index 0000000..c039c8e --- /dev/null +++ b/doc/html/cdevCollectionDesign.html @@ -0,0 +1,4336 @@ + + +CDEV Documentation + + + + + + +


        + + + +
        + + + + cdevCollection Device + Requirements and Design +

        + + +

        + Walt Akers, Chip Watson, Jie Chen +

        + +

        + Version 1.5 December 9, 1996 +

        + +

        + TJNAF - Thomas Jefferson National Accelerator Facility +

        + +

        +
        + +


        + + + + + +
        + + + + Table of Contents +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +
        +
        + + cdevCollection Class Design +
        +
        + + +
        +
        + + Purpose of the Class +
        +
        + + +
        +
        + + Requirements of the Class +
        +
        + + +
        +
        + + Method Overview of the Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + cdevCollection +
        +
        + + +
        +
        + + ~cdevCollection +
        +
        + + +
        +
        + + getRequestObject +
        +
        + + +
        +
        + + attachRef/attachPtr +
        +
        + + +
        +
        + + detach +
        +
        + + +
        +
        + + className +
        +
        + + +
        +
        + + add +
        +
        + + +
        +
        + + add +
        +
        + + +
        +
        + + add +
        +
        + + +
        +
        + + add +
        +
        + + +
        +
        + + addRegexp +
        +
        + + +
        +
        + + remove +
        +
        + + +
        +
        + + remove +
        +
        + + +
        +
        + + remove +
        +
        + + +
        +
        + + remove +
        +
        + + +
        +
        + + removeRegexp +
        +
        +
        + + 2. +
        +
        + + cdevCollectionRequest Class Design +
        +
        + + +
        +
        + + Purpose of the Class +
        +
        + + +
        +
        + + Requirements of the Class +
        +
        + + +
        +
        + + Method Overview of the Class +
        + + + + + + + + + +
        + + +
        +
        + + constructor +
        +
        + + +
        +
        + + destructor +
        +
        + + +
        +
        + + attachPtr +
        +
        + + +
        +
        + + className +
        +
        +
        + + 3. +
        +
        + + cdevGrpCollectionRequest Class Design +
        +
        + + +
        +
        + + Purpose of the Class +
        +
        + + +
        +
        + + Requirements of the Class +
        +
        + + +
        +
        + + Attribute Overview of the Class +
        + + + + + + + + + + + + + + + +
        + + +
        +
        + + sendStatus +
        +
        + + +
        +
        + + sendCheckSum +
        +
        + + +
        +
        + + collections +
        +
        + + +
        +
        + + nCollections +
        +
        + + +
        +
        + + requestOrder +
        +
        + + +
        +
        + + nRequests +
        +
        + + +
        +
        + + format +
        +
        +
        + + +
        +
        + + Method Overview of the Class +
        + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + constructor +
        +
        + + +
        +
        + + destructor +
        +
        + + +
        +
        + + getState +
        +
        + + +
        +
        + + getAccess +
        +
        + + +
        +
        + + setContext +
        +
        + + +
        +
        + + send +
        +
        + + +
        +
        + + sendNoBlock +
        +
        + + +
        +
        + + sendCallback +
        +
        + + +
        +
        + + className +
        +
        +
        + + 4. +
        +
        + + cdevDefCollectionRequest Class Design +
        +
        + + +
        +
        + + Purpose of the Class +
        +
        + + +
        +
        + + Requirements of the Class +
        +
        + + +
        +
        + + Attribute Overview of the Class +
        + + + + + + + + + + + +
        + + +
        +
        + + sendStatus +
        +
        + + +
        +
        + + sendCheckSum +
        +
        + + +
        +
        + + requests +
        +
        + + +
        +
        + + nRequests +
        +
        + + +
        +
        + + format +
        +
        +
        + + +
        +
        + + Method Overview of the Class +
        + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + constructor +
        +
        + + +
        +
        + + destructor +
        +
        + + +
        +
        + + getState +
        +
        + + +
        +
        + + getAccess +
        +
        + + +
        +
        + + setContext +
        +
        + + +
        +
        + + send +
        +
        + + +
        +
        + + sendNoBlock +
        +
        + + +
        +
        + + sendCallback +
        +
        + + +
        +
        + + className +
        +
        +
        + + 5. +
        +
        + + Defining cdevCollections in the CDEV DDL File +
        +
        + + +
        +
        + + Overview +
        +
        + + 6. +
        +
        + + Elementary Commands of the cdevCollection +
        +
        + + +
        +
        + + Attaching to a cdevCollection +
        +
        + + +
        +
        + + Detaching from a cdevCollection +
        +
        + + +
        +
        + + Adding Devices to a cdevCollection +
        +
        + + +
        +
        + + Adding a Single Device to a cdevCollection +
        +
        + + +
        +
        + + Adding Multiple Devices to a cdevCollection +
        +
        + + +
        +
        + + Adding an Array of Devices to a cdevCollection +
        +
        + + +
        +
        + + Adding a NULL-Terminated Array of Devices to a cdevCollection +
        +
        + + +
        +
        + + Adding Devices to a cdevCollection Using Regular Expressions +
        +
        + + +
        +
        + + Removing a Single Device from a cdevCollection +
        +
        + + +
        +
        + + Removing Multiple Devices from a cdevCollection +
        +
        + + +
        +
        + + Removing an Array of Devices from a cdevCollection +
        +
        + + +
        +
        + + Removing a NULL-Terminated Array of Devices from a cdevCollection +
        +
        + + +
        +
        + + Removing Devices from a cdevCollection Using Regular Expressions +
        +
        + + +
        +
        + + Getting a List of Devices from a cdevCollection +
        +
        + + 7. +
        +
        + + Restrictions of the cdevCollection Device +
        +
        +
        + +


        + + + + + +
        + + + + List of Figures +

        +
        + + + + Figure 1: + Object Inheritance Hierarchy of the cdevCollection Class +
        + + Figure 2: + Object Model of the cdevCollection Class +
        + + Figure 3: + Object Inheritance Hierarchy of the cdevCollectionRequest Class +
        + + Figure 4: + Object Model of the cdevCollectionRequest Class +
        + + Figure 5: + Object Inheritance Hierarchy of the cdevGrpCollectionRequest Class +
        + + Figure 6: + Object Model of the cdevGrpCollectionRequest Class +
        + + Figure 7: + Object Inheritance Hierarchy of the cdevDefCollectionRequest Class +
        + + Figure 8: + Object Model of the cdevDefCollectionRequest Class +
        + + Figure 9: + cdevCollection Definition in the CDEV DDL File +
        + + Figure 10: + Attach to a cdevCollection using attachPtr and attachRef +
        + + Figure 11: + Detach from a cdevCollection using detach +
        + + Figure 12: + Adding a single device to a cdevCollection +
        + + Figure 13: + Adding multiple devices to a cdevCollection +
        + + Figure 14: + Adding an array of devices to a cdevCollection +
        + + Figure 15: + Adding a NULL-terminated array of devices to a cdevCollection +
        + + Figure 16: + Adding a device to a cdevCollection using regular expressions +
        + + Figure 17: + Removing a single device from a cdevCollection +
        + + Figure 18: + Removing multiple devices from a cdevCollection +
        + + Figure 19: + Removing an array of devices from a cdevCollection +
        + + Figure 20: + Removing a NULL-terminated array of devices from a cdevCollection +
        + + Figure 21: + Removing devices from a cdevCollection using regular expressions +
        + + Figure 22: + Getting a list of devices from a cdevCollection +
        +
        + +


        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + + cdevCollection Class Design +

        +
        + + + Purpose of the + Class +

        +
        + + The cdevCollection class provides a mechanism for sending a message to a collection + of named devices. The object inheritance hierarchy of the cdevCollection is described + in the following object diagram. +

        + +

        + + Figure 1: + + Object Inheritance Hierarchy of the cdevCollection Class + +

        +
        + + + Requirements of + the Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +

        +
        + + A cdevCollection is a cdevDevice and is a named entity within the CDEV system + of objects. +

        +
        + + +

        +
        + + The name of the cdevCollection must be unique within the CDEV system of + objects. +

        +
        + + +

        +
        + + Only one instance of a named cdevCollection may exist within an executing + application. +

        +
        + + +

        +
        + + The cdevCollection object contains a single linked list of device names. These + device names define the collection. +

        +
        + + +

        +
        + + A cdevCollection object may be defined in the CDEV DDL file or may be + dynamically created at run-time. +

        +
        + + +

        +
        + + The CDEV DDL definition of a cdevCollection object contains the names of all + device names that comprise the object. However, names may be added to this list + after it has been instantiated. +

        +
        + + +

        +
        + + Device names may be added to or removed from a cdevCollection object using + the add and remove methods of the cdevCollection class. +

        +
        + + +

        +
        + + The component device names of a cdevCollection object may be added or + removed until the first message has been sent to the cdevCollection, after which + the collection of device names cannot be modified. +

        +
        + + +

        +
        + + A device name can only occur once within a cdevCollection object. +

        +
        + + +

        +
        + + When a device name string is added to the cdevCollection object using the add + method, the method makes a copy of the string. The original string remains the + property of the caller. +

        +
        + + +

        +
        + + When a device name string is removed from the cdevCollection object using the + remove method, the string that was generated when the device name was added + will be automatically deleted. +

        +
        + + +

        +
        + + When the cdevCollection object is destroyed, it is responsible for deleting any of + the device name strings that it has allocated. +

        +
        + + +

        +
        + + The getRequestObject method of a cdevCollection object returns a + cdevCollectionRequest object. This object inherits from (and is in the form of) a + cdevRequestObject object. +

        +
        + + +

        +
        + + A cdevCollection object inherits its send, sendCallback and sendNoBlock + functionality from the cdevDevice object. This functionality should be automatic + because the cdevDevice object calls the getRequestObject method to obtain a + request object for the device/message combination associated with the request. +

        +
        + + +

        + + Figure 2: + + Object Model of the cdevCollection Class +
        + + + +
        + + +
        
        +methods:
        +cdevCollection   (char *, cdevSystem &) 
        +~cdevCollection  (void)                         :{virtual}
        +getRequestObject (char *, cdevRequestObject *&) :{virtual} int
        + 
        +attachRef     (char *)               :{static}  cdevCollection &
        +attachPtr     (char *)               :{static}  cdevCollection *
        +attachRef     (char *, cdevSystem &) :{static}  cdevCollection *
        +attachPtr     (char *, cdevSystem &) :{static}  cdevCollection &
        +detach        (cdevCollection &)     :{static}  void
        +detach        (cdevCollection *)     :{static}  void
        +className     (void)                 :{virtual} char *
        +add           (char *)               :          int
        +add           (int, char *, ...)     :          int
        +add           (int, char **)         :          int
        +add           (char **)              :          int
        +addRegexp     (char *)               :          int
        +remove        (char *)               :          int
        +remove        (int, char *, ...)     :          int
        +remove        (int, char **)         :          int
        +remove        (char **)              :          int
        +removeRegexp  (char *)               :          int
        +			
        +
        +
        + +

        +
        + + + Method Overview + of the Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + cdevCollection +

        +
        + + cdevCollection (char * name, cdevSystem & system); +

        + + This is the constructor for the cdevCollection class. It has the + following properties. +

        + + + + + + + + + +
        + + +

        +
        + + This method is protected to prevent cdevCollections from + being instantiated directly. New cdevCollection instances + are created by using the attachPtr or attachRef method of + the cdevCollection class. +

        +
        + + +

        +
        + + The name that is provided to the cdevCollection is the + device name that CDEV will use to refer to it. The name + must be unique within the CDEV system of objects and + cannot be the same as the name of any regular cdevDevice + that exists in the CDEV DDL file. +

        +
        + + +

        +
        + + The cdevSystem reference that is provided is the + cdevSystem instance that will be used to poll, pend and + flush the cdevCollection object. +

        +
        + + +

        +
        + + If the name provided is the name of a cdevCollection that + has been specified in the CDEV DDL file, then the list of + devices will be populated from the names that are + specified. Otherwise, an empty cdevCollection instance will + be created. +

        +
        +
        + + + ~cdevCollection +

        +
        + + virtual ~cdevCollection (void); +

        + + This is the destructor for a cdevCollection object. It has the + following properties. +

        + + + + + + + +
        + + +

        +
        + + This method is protected to prevent the cdevCollection + object from being destroyed by the application. This + method should only be called by the cdevSystem object + when the application is terminating. +

        +
        + + +

        +
        + + Because the cdevCollection object will normally be referred + to as a cdevDevice object, this destructor is virtual to + ensure that the 'most senior' destructor is called first. +

        +
        + + +

        +
        + + This method will delete all device name strings that are + associated with the cdevCollection object. +

        +
        +
        + + + getRequestObject +

        +
        + + virtual int getRequestObject ( char *msg, +

        + cdevRequestObject* &req); +

        + + This method is called in order to obtain the cdevRequestObject + associated with the specified device/msg combination. This + method returns CDEV_SUCCESS if the cdevRequestObject + was successfully obtained. This method has the following + properties. +

        + + + + + +
        + + +

        +
        + + The cdevRequestObject pointer that is returned is actually + a pointer to a cdevCollectionRequest object. +

        +
        + + +

        +
        + + If a cdevCollectionRequest already exists for the specified + device/msg combination, it will be returned. Otherwise, the + method will call the attachPtr method of the + cdevCollectionRequest in order to obtain a new request + object. +

        +
        +
        + + + attachRef/attachPtr +

        +
        + + cdevCollection & attachRef (char * name); +

        + cdevCollection & attachRef (char * name, cdevSystem & sys); +

        + cdevCollection * attachPtr (char * name); +

        + cdevCollection * attachPtr (char * name, cdevSystem &sys); +

        + + These methods are used to obtain a pointer or reference to a + cdevCollection object. The name variable specifies the name of + the collection to be attached. These method have the following + properties. +

        + + + + + + + + + + + + + +
        + + +

        +
        + + All functionality for these methods is stored in the attachPtr + (char *, cdevSystem &) method. All other methods will call + this one. +

        +
        + + +

        +
        + + The method will first determine if the device has already + been created. If it has been created and its className + method returns "cdevCollection", then the existing + cdevCollection will be returned. If a non-collection + cdevDevice of the same name has already been + constructed, then NULL will be returned. +

        +
        + + +

        +
        + + If a device with the specified name has not already been + created, then the method will search the cdevDirectory for + the specified name. If the device name is in the + cdevDirectory AND is of class "collection", then a new + cdevCollection will be instantiated and returned. If a non- + collection cdevDevice of the same name exists in the + cdevDirectory, then NULL will be returned. +

        +
        + + +

        +
        + + If a device with the specified name has not been + instantiated and does not exist in the cdevDirectory, then a + new, empty cdevCollection will be created with the + specified name. +

        +
        + + +

        +
        + + If NULL is returned to one of the attachRef methods, then a + reference to a cdevErrorCollection object will be returned to + the caller. +

        +
        + + +

        +
        + + The refCount property of the cdevCollection will be + incremented each time a copy of the cdevCollection object + is obtained by the application. +

        +
        +
        + + + detach +

        +
        + + int detach (cdevCollection & col); +

        + int detach (cdevCollection * col); +

        + + This method is called to detach a pointer or reference to a + cdevCollection object. It has the following properties. +

        + + + + + +
        + + +

        +
        + + This method decrements the refCount property of the + cdevCollection object. +

        +
        + + +

        +
        + + When the refCount property is decremented to 0, then the + cdevCollection object will be deleted. +

        +
        +
        + + + className +

        +
        + + char * className (void); +

        + + This method returns the name of the class; "cdevCollection". If + the developer inherits a service specific cdevCollection, then + this method should not be altered or overridden. +

        +
        + + + add +

        +
        + + int add (char *name); +

        + + This method will add the individual name to the list of device + names that are in the cdevCollection. This method has the + following properties. +

        + + + + + + + + + +
        + + +

        +
        + + If a cdevCollectionRequest object has been instantiated for + this cdevCollection device, then the operation will fail and + CDEV_INVALIDOP will be returned. +

        +
        + + +

        +
        + + If the name provided is NULL or empty, then the operation + will fail and CDEV_INVALIDOP will be returned. +

        +
        + + +

        +
        + + If the name specified already exists in the collection of + names, then the operation will fail and CDEV_WARNING + will be returned. +

        +
        + + +

        +
        + + If the name specified is not already in the list, then the + method will append the device name to the end of the list + and return CDEV_SUCCESS. +

        +
        +
        + + + add +

        +
        + + int add (int num, char *firstname,...); +

        + + This method will attempt to add a list of num names to the + cdevCollection. This method has the following properties. +

        + + + + + + + + + + + +
        + + +

        +
        + + If a cdevCollectionRequest object has been instantiated for + this cdevCollection device, then the operation will fail and + CDEV_INVALIDOP will be returned. +

        +
        + + +

        +
        + + This method will call the add (char *name) method for each + name that is specified. +

        +
        + + +

        +
        + + If the add method fails to add any of the device name + strings to the list, then the error code that was generated by + the call to add (char * name) will be returned. +

        +
        + + +

        +
        + + If an error occurs while adding a name to the list, the + method will continue with the next name until the last name + is reached. +

        +
        + + +

        +
        + + If no errors occur while adding names to the list, then + CDEV_SUCCESS will be returned to the caller. +

        +
        +
        + + + add +

        +
        + + int add (int num, char **names); +

        + + This method will attempt to add num device names from the + names array to the list using the add (char *name) method of + the cdevCollection. This method has the same properties as + the add (int num, char * firstname,...) method. +

        +
        + + + add +

        +
        + + int add (char **names); +

        + + This method will attempt to add each device name from the + NULL terminated names array to the list using the add (char + *name) method of the cdevCollection. This method has the + same properties as the add (int num, char * firstname,...) + method. +

        +
        + + + addRegexp +

        +
        + + int addRegexp (char *regexp); +

        + + This method will query the system name server for the list of all + names in the cdevDirectory that match the specified regular + expression. the array of names will be added to the list using + the add (int num, char ** names) method and the result of this + operation will be returned. +

        +
        + + + remove +

        +
        + + int remove (char *name); +

        + + This method will remove the specified device name from list of + device names that is stored in the cdevCollection object. This + method has the following properties. +

        + + + + + + + + + +
        + + +

        +
        + + If a cdevCollectionRequest object has been instantiated for + this cdevCollection device, then the operation will fail and + CDEV_INVALIDOP will be returned. +

        +
        + + +

        +
        + + If the name provided is NULL or empty, then the operation + will fail and CDEV_WARNING will be returned. +

        +
        + + +

        +
        + + If the name specified does not exist in the collection of + names, then the operation will fail and CDEV_WARNING + will be returned. +

        +
        + + +

        +
        + + If the name specified exists in the list, then it will be + removed and CDEV_SUCCESS will be returned. +

        +
        +
        + + + remove +

        +
        + + int remove (int num, char *name,...); +

        + + This method will attempt to remove a list of num names from + the cdevCollection. This method has the following properties. +

        + + + + + + + + + + + +
        + + +

        +
        + + If a cdevCollectionRequest object has been instantiated for + this cdevCollection device, then the operation will fail and + CDEV_INVALIDOP will be returned. +

        +
        + + +

        +
        + + This method will call the remove (char *name) method for + each name that is specified. +

        +
        + + +

        +
        + + If the remove method fails to remove any of the device + name strings from the list, then the error code that was + generated by the call to remove (char * name) will be + returned. +

        +
        + + +

        +
        + + If an error occurs while removing a name from the list, the + method will continue with the next name until the last name + is reached. +

        +
        + + +

        +
        + + If no errors occur while removing names from the list, then + CDEV_SUCCESS will be returned to the caller. +

        +
        +
        + + + remove +

        +
        + + int remove (int num, char **names); +

        + + This method will attempt to remove num device names as + specified in the names array from the list using the remove + (char *name) method of the cdevCollection. This method has + the same properties as the remove (int num, char * name,...) + method. +

        +
        + + + remove +

        +
        + + int remove (char **names); +

        + + This method will attempt to remove each device name as + specified in the NULL terminated names array from the list + using the remove (char *name) method of the cdevCollection. + This method has the same properties as the remove (int num, + char * name,...) method. +

        + + +

        +
        + + + removeRegexp +

        +
        + + int removeRegexp (char *regexp); +

        + + This method will query the system name server for the list of all + names in the cdevDirectory that match the specified regular + expression. the array of names will be removed from the list + using the remove (int num, char ** names) method and the + result of this operation will be returned. +

        +
        +
        + + 2. +

        +
        + + + cdevCollectionRequest Class Design +

        +
        + + + Purpose of the + Class +

        +
        + + The cdevCollectionRequest class is an abstract base class from which other + cdevCollectionRequest objects a re derived. It provides a protected constructor and + destructor that are used to initialize its internals, however, the primary mechanism that + is used to obtain a cdevCollectionRequest object is the attachPtr method. +

        + + Figure 3: + + Object Inheritance Hierarchy of the cdevCollectionRequest Class + +

        +
        + + + Requirements of + the Class +

        +
        + + + + + + + + + + + + + + + +
        + + +

        +
        + + This class will provide a mechanism for the caller to obtain a pointer to a + cdevCollectionRequest derived object that can be used as an interface to a + collection of devices. +

        +
        + + +

        +
        + + The device/message combinations may fall into a variety of services. +

        +
        + + +

        +
        + + The derived class will provide default support for the methods send, sendCallback + and sendNoBlock. +

        +
        + + +

        +
        + + The send and sendNoBlock methods will rely on the sendCallback method to + transmit their request and receive a reply. +

        +
        + + +

        +
        + + Each data item that is returned by the individual devices must be scalar in nature. + Non-scalar results returned by a device will be discarded. +

        +
        + + +

        +
        + + If the scalar data that is returned by multiple devices is not homogeneous, the + data type will be promoted in such a way as to ensure that no data is lost. +

        +
        + + +

        +
        + + A special tagged data item, "resultCode" will be added to the cdevGlobalTagTable. + This data item will hold an ordered array of the completion codes that were + returned to the callback function in the status parameter. +

        +
        + + +

        + + Figure 4: + + Object Model of the cdevCollectionRequest Class +
        + + + +
        + + +
        
        +attributes:
        +RESULT_CODE_TAG: int
        + 
        +methods:
        +cdevCollectionRequest   (char **, int, char *, cdevSystem &) 
        +~cdevCollectionRequest  (void)  :{virtual}
        + 
        +attachPtr               (...)   :{static} cdevCollectionRequest 
        +* 
        +className               (void)  :{virtual} char *
        +resultCodeTag           (void)  :{virtual} int
        +			
        +
        +
        + +

        +
        + + + Method Overview + of the Class +

        +
        + + + + + + + + + +
        + + + constructor +

        +
        + + cdevCollectionRequest( char **devices, int nDevices, +

        + char * msg, cdevSystem & system); +

        + + This is the constructor for the cdevCollectionRequest class. It + has the following properties. +

        + + + + + + + +
        + + +

        +
        + + This method is protected to prevent the direct instantiation + of new cdevCollectionRequests. New instances of the + cdevCollectionRequest objects are created by using the + attachPtr or attachRef method of the cdevRequestObject + class which will call the local attachPtr method to create a + new object if necessary. +

        +
        + + +

        +
        + + The constructor is called by the cdevCollection object and + is provided with a list and count of devices that will be + included in the collection and the message that will be sent + to them. +

        +
        + + +

        +
        + + The cdevSystem reference that is provided is the + cdevSystem instance that will be used to poll, pend and + flush the cdevCollectionRequest object. +

        +
        +
        + + + destructor +

        +
        + + virtual ~cdevCollectionRequest (void); +

        + + This is the destructor for a cdevCollectionRequest object. It has + the following properties. +

        + + + + + +
        + + +

        +
        + + This method is protected to prevent the + cdevCollectionRequest object from being destroyed by the + application. This method should only be called by the + cdevSystem object when the application is terminating. +

        +
        + + +

        +
        + + Because the cdevCollectionRequest object will normally be + referred to as a cdevRequestObject object, this destructor + is virtual to ensure that the 'most senior' destructor is + called first. +

        +
        +
        + + + attachPtr +

        +
        + + cdevCollectionRequest * attachPtr +

        + ( cdevCollection &col, char *msg, cdevSystem &sys); +

        + + This method is used by the cdevCollection object to obtain a + new cdevCollectionRequest object. +

        + + + + + + + + + + + +
        + + +

        +
        + + This method will obtain a copy of the device names from + the cdevCollection object and will poll the cdevDirectory + object to determine which service each of them is + associated with. +

        +
        + + +

        +
        + + If the devices are all from a single service, this method will + return a service specific collection request object. +

        +
        + + +

        +
        + + If the devices are from a variety of services, this method will + return a cdevGrpCollectionRequest that contains the + service specific collection request objects. +

        +
        + + +

        +
        + + Device/message combinations that are not associated with + a service will be ignored. +

        +
        + + +

        +
        + + If none of the device/message combinations can be + associated with a service, then an error message will be + generated and NULL will be returned. +

        +
        +
        + + + className +

        +
        + + char * className (void); +

        + + This method returns the name of the class; + "cdevCollectionRequest". If the developer inherits a service + specific cdevCollectionRequest, then this method should not be + altered or overridden. +

        +
        +
        + + 3. +

        +
        + + + cdevGrpCollectionRequest Class Design +

        +
        + + + Purpose of the + Class +

        +
        + + The cdevGrpCollectionRequest class is used when the list of devices will be serviced + by more than one cdevService. This class will create and maintain a list of service + specific cdevCollectionRequest objects and will compile the results into a single + cdevData object that will be returned to the caller. +

        + + Figure 5: + + Object Inheritance Hierarchy of the cdevGrpCollectionRequest Class + +

        +
        + + + Requirements of + the Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +

        +
        + + This class will break the list of devices into groups that will be associated with + individual services. +

        +
        + + +

        +
        + + A service-specific cdevCollectionRequest will be created and maintained for each + of the individual groups of devices. +

        +
        + + +

        +
        + + The methods send, sendNoBlock and sendCallback will be provided to allow the + message to be transmitted to all of the embedded collections. +

        +
        + + +

        +
        + + The send and sendNoBlock methods will utilize the sendCallback method to + transmit messages. This will reduce the amount of code that is required to + perform message transmission. +

        +
        + + +

        +
        + + The class will collect all of the data from the service-specific collections into a + single cdevData object that will be provided to the user. The "resultCode" tag will + contain an array of completion codes that will indicate the completion status for + each device/message request. +

        +
        + + +

        +
        + + The cdevGrpCollectionRequest object will maintain order information about the + individual devices that exist in the various service-specific collections. Resultant + data items will be placed in the correct order in the cdevData item that is returned + to the caller. +

        +
        + + +

        +
        + + If the data arrays that are returned by multiple collections are not homogeneous, + the data type will be promoted in such a way as to ensure that no data is lost. +

        +
        + + +

        +
        + + If a device does not have an associated cdev service, then its "resultCode" entry + will be set to CDEV_NOT_FOUND. +

        +
        + + +

        +
        + + If none of the devices can be associated with a service, then any call to send, + sendNoBlock or sendCallback will fail and will return CDEV_ERROR. +

        +
        + + +

        +
        + + If CDEV_ERROR is returned when the sendCallback method is used, then the + user defined callback function will not be called. +

        +
        + + +

        +
        + + The send method will wait for a predefined period (5 seconds) for all of the service + specific collection objects to return their results. If one or more of the service + specific collections fails to respond within that period, then the send method will + fail and will return CDEV_ERROR. +

        +
        + + +

        +
        + + When using the sendCallback method, if one or more of the service specific + collections fails to respond, the user defined callback method will never be called. +

        +
        + + +

        +
        + + Calls to the getState and getAccess methods will poll each of the embedded + collections and will return an enumerated type that reflects the most restrictive + state that exists. +

        +
        + + +

        +
        + + Calls to the setContext method will result in the setContext method being called + for each of the embedded service-specific collections. +

        +
        + + +

        + + Figure 6: + + Object Model of the cdevGrpCollectionRequest Class +
        + + + +
        + + +
        
        +attributes:
        +sendStatus   : struct SendStatus
        +sendCheckSum : int
        +collections  : cdevCollectionRequest **
        +nCollections : int
        +requestOrder : int *
        +nRequests    : int
        +format       : cdevData
        + 
        +methods:
        +cdevGrpCollectionRequest   (char **, int, char *, cdevSystem &) 
        +~cdevGrpCollectionRequest  (void)         :{virtual}
        + 
        +getState     (void)                       :{virtual} int
        +getAccess    (void)                       :{virtual} int
        +setContext   (cdevData &)                 :{virtual} int
        +send         (cdevData &, cdevData &)     :{virtual} int
        +send         (cdevData &, cdevData *)     :{virtual} int
        +send         (cdevData *, cdevData &)     :{virtual} int
        +send         (cdevData *, cdevData *)     :{virtual} int
        +sendNoBlock  (cdevData &, cdevData &)     :{virtual} int
        +sendNoBlock  (cdevData &, cdevData *)     :{virtual} int
        +sendNoBlock  (cdevData *, cdevData &)     :{virtual} int
        +sendNoBlock  (cdevData *, cdevData *)     :{virtual} int
        +sendCallback (cdevData &, cdevCallback &) :{virtual} int
        +sendCallback (cdevData *, cdevCallback &) :{virtual} int
        +className    (void)                       :{virtual} char *
        +			
        +
        +
        + +

        +
        + + + Attribute + Overview of the + Class +

        +
        + + + + + + + + + + + + + + + +
        + + + sendStatus +

        +
        + + typedef struct { +

        + int completionCode; +

        + int finished; +

        + cdevData *data; +

        + } SendStatus sendStatus; +

        + + This is a structure that is provided as the void * argument to the + callback function that is used for the send method. This + structure identifies the cdevData object that is to be populated + with the results and is also used to maintain a completionCode + and the finished semaphore. +

        +
        + + + sendCheckSum +

        +
        + + int sendCheckSum; +

        + + Because the send method uses the sendCallback method to + transmit its requests, a callback associated with an earlier + (timed-out) call to send may occur while the + cdevGrpCollectionRequest object is waiting. The + sendCheckSum is used by the callback method to ensure that + the correct request is being processed. +

        +
        + + + collections +

        +
        + + cdevCollectionRequest * collections; +

        + + This is an array of the service-specific collections. The first + entry in this list is a NULL collection that is used to identify all + devices that are not supported by a service. +

        +
        + + + nCollections +

        +
        + + int nCollections; +

        + + This is the number of cdevCollectionRequests that have been + allocated to the collections array. +

        +
        + + + requestOrder +

        +
        + + int * requestOrder; +

        + + This is an array of integers that corresponds to each device that + is in the cdevCollection. Each entry contains an integer that is + the index of the service-specific cdevCollectionRequest that is + associated with the individual device. This array is used to + place the data items from the various devices in the correct + order in the resultant cdevData item. +

        +
        + + + nRequests +

        +
        + + int nRequests; +

        + + This is the number of entries in the requestOrder array (the + number of devices in the collection). +

        +
        + + + format +

        +
        + + cdevData format; +

        + + This is a cdevData object that has the same internal structure + as the first data object retrieved from the + cdevGrpCollectionRequest. This cdevData object is used to + pre-format the user provided cdevData objects to the correct + data types in order to reduce the time expended in reformatting + the incoming data during type promotions. +

        + +

        + +

        +
        +
        + + + Method Overview + of the Class +

        +
        + + + + + + + + + + + + + + + + + + + +
        + + + constructor +

        +
        + + cdevGrpCollectionRequest +

        + (char **devices, int nDevices, char *msg, cdevSystem& sys); +

        + + This is the constructor for the cdevGrpCollectionRequest + object. It will descend the list of devices that is provided and will + identify the cdev services that are associated with them. The + constructor will then create a service-specific + cdevCollectionRequest object for each group of devices. +

        + Devices that are not associated with a service will be placed on + a 'dead' list and will automatically be marked with the + resultCode CDEV_NOT_FOUND whenever the send, + sendNoBlock or sendCallback methods are employed. +

        +
        + + + destructor +

        +
        + + ~cdevGrpCollectionRequest (void); +

        + + This is the destructor for the class. It will delete all of the + service-specific cdevCollectionRequests and will free any + memory that was previously allocated to the class. +

        +
        + + + getState +

        +
        + + int getState (void); +

        + + This method calls the getState method of all of the service- + specific cdevCollectionRequest objects. The method will return + the most restrictive state that is encountered from any its + embedded collections. +

        +
        + + + getAccess +

        +
        + + int getAccess (void); +

        + + This method calls the getAccess method of all of the service- + specific cdevCollectionRequest objects. The method will return + the most restrictive state that is encountered from any of its + embedded collections. +

        +
        + + + setContext +

        +
        + + int setContext (cdevData &ctx); +

        + + This method will call the setContext method of all of the + service-specific cdevCollectionRequest objects. This method + will always return CDEV_SUCCESS. +

        +
        + + + send +

        +
        + + int send (cdevData & in, cdevData & out); +

        + int send (cdevData * in, cdevData & out); +

        + int send (cdevData & in, cdevData * out); +

        + int send (cdevData * in, cdevData * out); +

        + + The send methods are used to synchronously transmit a + message to all of the devices that are embedded within the + cdevGrpCollectionRequest object. The method will employ the + sendCallback method to transmit the message and then will + wait for a predefined period (5 seconds) for all of the collections + to respond. The method will display an error and return + CDEV_ERROR if the collections do not reply within the time + period. +

        +
        + + + sendNoBlock +

        +
        + + int sendNoBlock (cdevData & in, cdevData & out); +

        + int sendNoBlock (cdevData * in, cdevData & out); +

        + int sendNoBlock (cdevData & in, cdevData * out); +

        + int sendNoBlock (cdevData * in, cdevData * out); +

        + + The sendNoBlock methods are used to asynchronously send a + message to all of the devices that are embedded within the + cdevGrpCollectionRequest object. The method relies on the + sendCallback method to transmit the request. The caller must + have established a cdevGroup prior to submitting the message + in order to detect when all of the collections have responded. +

        +
        + + + sendCallback +

        +
        + + int sendCallback (cdevData & in, cdevCallback & callback); +

        + int sendCallback (cdevData * in, cdevCallback & callback); +

        + + The sendCallback methods are used to asynchronously + transmit a message to all of the devices that are embedded + within the cdevGrpCollectionRequest object. The user defined + callback method will be called when all of the service-specific + collections have responded. +

        + If one or more of the service-specific collections fails to + respond, then the user specific callback will never be executed. +

        + A copy is made of the callback object that is provided by the + user to ensure that it is not inadvertently deleted before the + callback function has been called. +

        +
        + + + className +

        +
        + + const char *className (void) const; +

        + + This method will return the name of the class: + "cdevGrpCollectionRequest". +

        +
        +
        + + 4. +

        +
        + + + cdevDefCollectionRequest Class Design +

        +
        + + + Purpose of the + Class +

        +
        + + The cdevDefCollectionRequest object is the default collection request object for cdev. + If the service developer does not provide a service-specific collection mechanism, + then cdev will use this object to support collection request calls to the service. +

        + This class performs collection operations by walking through the list of service-specific + request objects and executing them one at a time. The results from the individual + request objects will then be compiled into a single cdevData object that is returned to + the caller. +

        + +

        + + Figure 7: + + Object Inheritance Hierarchy of the cdevDefCollectionRequest Class + +

        +
        + + + Requirements of + the Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + +
        + + +

        +
        + + This class will obtain a service-specific cdevRequestObject for each device that is + specified. +

        +
        + + +

        +
        + + The methods send, sendNoBlock and sendCallback will be provided to allow the + message to be transmitted to all of the embedded request objects. +

        +
        + + +

        +
        + + The send and sendNoBlock methods will utilize the sendCallback method to + transmit messages. This will reduce the amount of code that is required to + perform message transmission. +

        +
        + + +

        +
        + + The class will collect all of the data from the service-specific request objects into a + single cdevData object that will be provided to the user. The "resultCode" tag will + contain an array of completion codes that will indicate the completion status for + each device/message request. +

        +
        + + +

        +
        + + The cdevDefCollectionRequest object will maintain order information about the + individual devices. Resultant data items will be placed in the correct order in the + cdevData item that is returned to the caller. +

        +
        + + +

        +
        + + If the data that is returned by the individual devices is not homogeneous, the data + type will be promoted in such a way as to ensure that no data is lost. +

        +
        + + +

        +
        + + If CDEV_ERROR is returned when the sendCallback method is used, then the + user defined callback function will not be called. +

        +
        + + +

        +
        + + The send method will wait for a predefined period (5 seconds) for all of the request + objects to respond. If one or more of the request objects fails to respond within + that period, then the send method will fail and will return CDEV_ERROR. +

        +
        + + +

        +
        + + When using the sendCallback method, if one or more of the request objects fails + to respond, the user defined callback method will never be called. +

        +
        + + +

        +
        + + Calls to the getState and getAccess methods will poll each of the embedded + request objects and will return an enumerated type that reflects the most + restrictive state that exists. +

        +
        + + +

        +
        + + Calls to the setContext method will result in the setContext method being called + for each of the embedded request objects. +

        +
        + + +

        + + Figure 8: + + Object Model of the cdevDefCollectionRequest Class +
        + + + +
        + + +
        
        +attributes:
        +sendStatus   : struct SendStatus
        +sendCheckSum : int
        +requests     : cdevRequestObject **
        +nRequests    : int
        +format       : cdevData
        + 
        +methods:
        +cdevDefCollectionRequest   (char **, int, char *, cdevSystem &) 
        +~cdevDefCollectionRequest  (void)         :{virtual}
        + 
        +getState     (void)                       :{virtual} int
        +getAccess    (void)                       :{virtual} int
        +setContext   (cdevData &)                 :{virtual} int
        +send         (cdevData &, cdevData &)     :{virtual} int
        +send         (cdevData &, cdevData *)     :{virtual} int
        +send         (cdevData *, cdevData &)     :{virtual} int
        +send         (cdevData *, cdevData *)     :{virtual} int
        +sendNoBlock  (cdevData &, cdevData &)     :{virtual} int
        +sendNoBlock  (cdevData &, cdevData *)     :{virtual} int
        +sendNoBlock  (cdevData *, cdevData &)     :{virtual} int
        +sendNoBlock  (cdevData *, cdevData *)     :{virtual} int
        +sendCallback (cdevData &, cdevCallback &) :{virtual} int
        +sendCallback (cdevData *, cdevCallback &) :{virtual} int
        +className    (void)                       :{virtual} char *
        +			
        +
        +
        + +

        +
        + + + Attribute + Overview of the + Class +

        +
        + + + + + + + + + + + +
        + + + sendStatus +

        +
        + + typedef struct { +

        + int completionCode; +

        + int finished; +

        + cdevData *data; +

        + } SendStatus sendStatus; +

        + + This is a structure that is provided as the void * argument to the + callback function that is used for the send method. This + structure identifies the cdevData object that is to be populated + with the results and is also used to maintain a completionCode + and the finished semaphore. +

        +
        + + + sendCheckSum +

        +
        + + int sendCheckSum; +

        + + Because the send method uses the sendCallback method to + transmit its requests, a callback associated with an earlier + (timed-out) call to send may occur while the + cdevDefCollectionRequest object is waiting. The + sendCheckSum is used by the callback method to ensure that + the correct request is being processed. +

        +
        + + + requests +

        +
        + + cdevRequestObject ** requests; +

        + + This is an array of request objects that are associated with + each of the devices in the collection. +

        +
        + + + nRequests +

        +
        + + int nRequests; +

        + + This is the number of request objects in the requests array (the + number of devices in the collection). +

        +
        + + + format +

        +
        + + cdevData format; +

        + + This is a cdevData object that has the same internal structure + as the first data object generated by the + cdevDefCollectionRequest. This cdevData object is used to + pre-format the user provided cdevData objects to the correct + data types in order to reduce the time expended in reformatting + the incoming data during type promotions. +

        +
        +
        + + + Method Overview + of the Class +

        +
        + + + + + + + + + + + + + + + + + + + +
        + + + constructor +

        +
        + + cdevDefCollectionRequest +

        + (char **devices, int nDevices, char *msg, cdevSystem& sys); +

        + + This is the constructor for the cdevDefCollectionRequest + object. It will descend the list of devices that is provided and will + connect to the cdevRequestObject associated with each + device. +

        +
        + + + destructor +

        +
        + + ~cdevDefCollectionRequest (void); +

        + + This is the destructor for the class. It will free any memory that + was previously allocated to the class. +

        +
        + + + getState +

        +
        + + int getState (void); +

        + + This method calls the getState method of all of the embedded + request objects. The method will return the most restrictive + state that is encountered. +

        +
        + + + getAccess +

        +
        + + int getAccess (void); +

        + + This method calls the getAccess method of all of the embedded + request objects. The method will return the most restrictive + state that is encountered. +

        +
        + + + setContext +

        +
        + + int setContext (cdevData &ctx); +

        + + This method will call the setContext method of all of the + embedded request objects. This method will always return + CDEV_SUCCESS. +

        +
        + + + send +

        +
        + + int send (cdevData & in, cdevData & out); +

        + int send (cdevData * in, cdevData & out); +

        + int send (cdevData & in, cdevData * out); +

        + int send (cdevData * in, cdevData * out); +

        + + The send methods are used to synchronously transmit a + message to all of the devices that are embedded within the + cdevDefCollectionRequest object. The method will employ the + sendCallback method to transmit the message and then will + wait for a predefined period (5 seconds) for all of the request + objects to respond. The method will display an error and return + CDEV_ERROR if the request objects do not reply within the + time period. +

        +
        + + + sendNoBlock +

        +
        + + int sendNoBlock (cdevData & in, cdevData & out); +

        + int sendNoBlock (cdevData * in, cdevData & out); +

        + int sendNoBlock (cdevData & in, cdevData * out); +

        + int sendNoBlock (cdevData * in, cdevData * out); +

        + + The sendNoBlock methods are used to asynchronously send a + message to all of the devices that are embedded within the + cdevDefCollectionRequest object. The method relies on the + sendCallback method to transmit the request. The caller must + have established a cdevGroup prior to submitting the message + in order to detect when all of the request objects have + responded. +

        +
        + + + sendCallback +

        +
        + + int sendCallback (cdevData & in, cdevCallback & callback); +

        + int sendCallback (cdevData * in, cdevCallback & callback); +

        + + The sendCallback methods are used to asynchronously + transmit a message to all of the devices that are embedded + within the cdevDefCollectionRequest object. The user defined + callback method will be called when all of the request objects + have responded. +

        + If one or more of the request objects fails to respond, then the + user specific callback will never be executed. +

        + A copy is made of the callback object that is provided by the + user to ensure that it is not inadvertently deleted before the + callback function has been called. +

        +
        + + + className +

        +
        + + const char *className (void) const; +

        + + This method will return the name of the class: + "cdevDefCollectionRequest". +

        +
        +
        + + 5. +

        +
        + + + Defining cdevCollections in the CDEV DDL File +

        +
        + + + Overview +

        +
        + + A cdevCollection device can be implemented in one of two ways; the developer can + create an empty cdevCollection dynamically and add devices to it, or a collection entry + can be placed in the CDEV DDL file that identifies the collection and its constituent + devices. The syntax for defining a cdevCollection device in the CDEV DDL file is as + follows. +

        + + Figure 9: + + cdevCollection Definition in the CDEV DDL File +
        + + + +
        + + +
        
        +/* service definitions */
        +...
        + 
        +/* class definitions */
        +...
        + 
        +/* device instances */
        +...
        + 
        +/* alias definitions */
        +...
        + 
        +collection cDevice1 : 
        +device0, 
        +device1, 
        +device2 
        +;
        + 
        +collection cDevice2 : 
        +device3 
        +device4 
        +device5
        +;
        +			
        +
        +
        + +

        + + +

        + In the example above two cdevCollections are defined. A cdevCollection definition is + started by using the keyword "collection", followed by a space and then the name of + the collection. Note that the name of the collection must be unique and cannot be + shared with any other device in the cdev system. +

        + The device name is followed by a white space character (which is required), and + then a colon, followed by another white space character and then the list of devices. + The device names that are in the list may be separated by either white space of a + comma delimiter. The list of devices is terminated by a semicolon. +

        + The current implementation of the CDEV DDL is order dependent. Because of this, + the developer should place the collection definitions after the definitions of all devices + and aliases. +

        +
        + + 6. +

        +
        + + + Elementary Commands of the cdevCollection +

        +
        + + + Attaching to a + cdevCollection +

        +
        + + In order to use a cdevCollection, the developer must first use the attachRef or + attachPtr method to obtain a pointer to the device. If the device name that is provided + to the method is the name of a predefined collection device that exists in the CDEV + DDL file, then it will be populated with the devices that are specified in the device list. + If the device name is NOT specified in the CDEV DDL file, then a warning will be + displayed and an empty cdevCollection will be created. +

        + The code below illustrates how to obtain a reference to a cdevCollection using the + attachRef method, and how to obtain a pointer to a cdevCollection using the attachPtr + method. In the example, the "brandNew" cdevCollection will be created with no + constituent devices because it is not defined in the CDEV DDL file. The "cDevice1" + collection will be populated with the devices: "device0", "device1", and "device2" as + defined in the CDEV DDL file. +

        + + Figure 10: + + Attach to a cdevCollection using attachPtr and attachRef +
        + + + +
        + + +
        
        +#include <cdevCollection.h>
        + 
        +void main ( void )
        +{
        +/***************************************************************
        + * Obtain a reference to a cdevCollection device named 
        + * "brandNew". Because this collection is not defined in the 
        + * CDEV DDL file, it will be created with no constituent 
        + * devices.
        + 
        +***************************************************************/
        +cdevCollection & brandNew = 
        +cdevCollection::attachRef("brandNew");
        + 
        +/***************************************************************
        + * Obtain a reference to a cdevCollection device named 
        + * "cDevice1". This collection is defined in the CDEV DDL file 
        + * and will be populated with the devices: "device0", "device1", 
        + * and "device2".
        + 
        +***************************************************************/
        +cdevCollection * cDevice1 = 
        +cdevCollection::attachPtr("cDevice1");
        +}
        +			
        +
        +
        + +

        +
        + + + Detaching from a + cdevCollection +

        +
        + + Because only one copy of each cdevDevice or cdevCollection exists in the + cdevSystem, the number of references to a device that are in use is tracked using a + reference count variable. The detach method decrements that reference count. When + the reference count reaches 0, the cdevSystem may delete the device. +

        + The following illustration shows how to detach from a cdevCollection. +

        + + Figure 11: + + Detach from a cdevCollection using detach +
        + + + +
        + + +
        
        +#include <cdevCollection.h>
        + 
        +void main ( void )
        +{
        +cdevCollection & cDevice1 = 
        +cdevCollection::attachRef("cDevice1");
        +cdevCollection::detach(cDevice1);
        +}
        +			
        +
        +
        + +

        +
        + + + Adding Devices to + a cdevCollection +

        +
        + + When creating an empty cdevCollection device, the developer will have to add the + constituent devices to the collection using one of the variations of the "add" method. + These methods will allow the developer to add either individual devices, lists of + devices, or devices from the CDEV DDL file that match a specific regular expression. +

        + It should be noted by the developer that only cdevDevices may be added to a + cdevCollection. The current design of the cdevCollection device does not support + adding collections to a collection. +

        + The variations of the add method are described in the following sections. +

        +
        + + + Adding a Single + Device to a + cdevCollection +

        +
        + + When adding a single device to a collection, the add (char * name) method should be + employed. This method will add the specified device name to the list of device names + (if any) that already exists in the cdevCollection. The following source code illustrates + how to add the cdevDevice "device0" to the cdevCollection "brandNew". +

        + +

        + + Figure 12: + + Adding a single device to a cdevCollection +
        + + + +
        + + +
        
        +#include <cdevCollection.h>
        +void main ( void )
        +{
        +/**************************************************************
        + * Attach to an undefined cdevCollection device and then add 
        + * the cdevDevice "device0" to it.
        + **************************************************************/
        +cdevCollection & brandNew = 
        +cdevCollection::attachRef("brandNew");
        +brandNew.add("device0");
        +}
        +			
        +
        +
        + +

        +
        + + + Adding Multiple + Devices to a + cdevCollection +

        +
        + + There are several variations of the add method that will allow you to add several + devices to a cdevCollection using a single method. This method uses a variable length + argument list to allow the caller to pass in an arbitrary number of device names as + parameters to the call. +

        + +

        + + Figure 13: + + Adding multiple devices to a cdevCollection +
        + + + +
        + + +
        
        +#include <cdevCollection.h>
        + 
        +void main ( void )
        +{
        +/**************************************************************
        + * Attach to the cdevCollection "brandNew" and add four device
        + * names to it.
        + **************************************************************/
        +cdevCollection & brandNew = 
        +cdevCollection::attachRef("brandNew");
        +brandNew.add(4, "device0", "device1", "device2", "device3");
        +}
        +			
        +
        +
        + +

        +
        + + + Adding an Array of + Devices to a + cdevCollection +

        +
        + + This add method allows the developer to add an array of device names to the + cdevCollection. In this variation of the add method, the caller must specify the number + of device names that are stored in the array. +

        + +

        + + Figure 14: + + Adding an array of devices to a cdevCollection +
        + + + +
        + + +
        
        +#include <cdevCollection.h>
        + 
        +char * devices[] = {"device0", "device1", "device2", "device3"};
        + 
        +void main ( void )
        +{
        +/**************************************************************
        + * Attach to the cdevCollection "brandNew" and add four device
        + * names to it.
        + **************************************************************/
        +cdevCollection & brandNew = 
        +cdevCollection::attachRef("brandNew");
        +brandNew.add(4, devices);
        +}
        +			
        +
        +
        + +

        +
        + + + Adding a NULL- + Terminated Array + of Devices to a + cdevCollection +

        +
        + + This add method allows the developer to add an array of device names to the + cdevCollection. In this variation of the add method, the last character string pointer in + the array must be NULL. +

        + +

        + + Figure 15: + + Adding a NULL-terminated array of devices to a cdevCollection +
        + + + +
        + + +
        
        +#include <cdevCollection.h>
        + 
        +char * devices[] = {"device0", "device1", "device2", NULL};
        + 
        +void main ( void )
        +{
        +/**************************************************************
        + * Attach to the cdevCollection "brandNew" and add a NULL
        + * terminated list of devices to it.
        + **************************************************************/
        +cdevCollection & brandNew = 
        +cdevCollection::attachRef("brandNew");
        +brandNew.add(devices);
        +}
        +			
        +
        +
        + +

        +
        + + + Adding Devices to + a cdevCollection + Using Regular + Expressions +

        +
        + + The addRegexp method uses the regular expression parsing interface of the + cdevDirectory device to obtain the names of all of the devices that match the specified + expression. This list of names will then be added to the cdevCollection device. The + regular expression may be in either standard format or the format used for UNIX + filename expansion. See the cdevDirectory documentation for more information on + regular expressions. +

        + The following code illustrates loading all devices that match the expression "device?". +

        + + Figure 16: + + Adding a device to a cdevCollection using regular expressions +
        + + + +
        + + +
        
        +#include <cdevCollection.h>
        + 
        +void main ( void )
        +{
        +/**************************************************************
        + * Attach to the cdevCollection "brandNew" and add a NULL
        + * terminated list of devices to it.
        + **************************************************************/
        +cdevCollection & brandNew = 
        +cdevCollection::attachRef("brandNew");
        +brandNew.addRegexp("device?");
        +}
        +			
        +
        +
        + +

        +
        + + + Removing a + Single Device from + a cdevCollection +

        +
        + + When removing a single device from a collection, the remove (char * name) method + should be employed. This method will remove the specified device name from the list + of device names (if any) that already exists in the cdevCollection. The following source + code illustrates how to remove the cdevDevice "device0" from the cdevCollection + "cDevice1". +

        + +

        + + Figure 17: + + Removing a single device from a cdevCollection +
        + + + +
        + + +
        
        +#include <cdevCollection.h>
        + 
        +void main ( void )
        +{
        +/**************************************************************
        + * Attach to a defined cdevCollection device and then remove 
        + * the cdevDevice "device0" from it.
        + **************************************************************/
        +cdevCollection & cDevice1 = 
        +cdevCollection::attachRef("cDevice1");
        +cDevice1.remove("device0");
        +}
        +			
        +
        +
        + +

        +
        + + + Removing + Multiple Devices + from a + cdevCollection +

        +
        + + There are several variations of the remove method that will allow you to remove + several devices from a cdevCollection using a single function call. This method uses a + variable length argument list to allow the caller to pass in an arbitrary number of + device names as parameters to the call. +

        + +

        + + Figure 18: + + Removing multiple devices from a cdevCollection +
        + + + +
        + + +
        
        +#include <cdevCollection.h>
        + 
        +void main ( void )
        +{
        +/**************************************************************
        + * Attach to a defined cdevCollection device and then remove 
        + * two cdevDevices from it.
        + **************************************************************/
        +cdevCollection & cDevice1 = 
        +cdevCollection::attachRef("cDevice1");
        +cDevice1.remove(2, "device0", "device2");
        +}
        +			
        +
        +
        + +

        +
        + + + Removing an + Array of Devices + from a + cdevCollection +

        +
        + + This remove method allows the developer to remove an array of device names from + the cdevCollection. In this variation of the remove method, the caller must specify the + number of device names that are stored in the array. +

        + +

        + + Figure 19: + + Removing an array of devices from a cdevCollection +
        + + + +
        + + +
        
        +#include <cdevCollection.h>
        + 
        +char * devices[] = {"device0", "device2"};
        + 
        +void main ( void )
        +{
        +/**************************************************************
        + * Attach to a defined cdevCollection device and then remove 
        + * two cdevDevices from it.
        + **************************************************************/
        +cdevCollection & cDevice1 = 
        +cdevCollection::attachRef("cDevice1");
        +cDevice1.remove(2, devices);
        +}
        +			
        +
        +
        + +

        +
        + + + Removing a NULL- + Terminated Array + of Devices from a + cdevCollection +

        +
        + + This remove method allows the developer to remove an array of device names from + the cdevCollection. In this variation of the remove method, the last character string + pointer in the array must be NULL. +

        + +

        + + Figure 20: + + Removing a NULL-terminated array of devices from a cdevCollection +
        + + + +
        + + +
        
        +#include <cdevCollection.h>
        + 
        +char * devices[] = {"device0", "device2", NULL};
        + 
        +void main ( void )
        +{
        +/**************************************************************
        + * Attach to a defined cdevCollection device and then remove 
        + * a NULL terminated list of devices from it.
        + **************************************************************/
        +cdevCollection & cDevice1 = 
        +cdevCollection::attachRef("cDevice1");
        +cDevice1.remove(devices);
        +}
        +			
        +
        +
        + +

        +
        + + + Removing + Devices from a + cdevCollection + Using Regular + Expressions +

        +
        + + The removeRegexp method uses the regular expression parsing interface of the + cdevDirectory device to obtain the names of all of the devices that match the specified + expression. This list of names will then be removed from the cdevCollection device. + The regular expression may be in either standard format or the format used for UNIX + filename expansion. See the cdevDirectory documentation for more information on + regular expressions. +

        + The following code illustrates removing all devices that match the expression + "device?" from the cdevCollection "cDevice1". +

        + + Figure 21: + + Removing devices from a cdevCollection using regular expressions +
        + + + +
        + + +
        
        +#include <cdevCollection.h>
        + 
        +void main ( void )
        +{
        +/**************************************************************
        + * Attach to a defined cdevCollection device and then remove 
        + * all devices that match the specified regular expression.
        + **************************************************************/
        +cdevCollection & cDevice1 = 
        +cdevCollection::attachRef("cDevice1");
        +cDevice1.removeRegexp("device?");
        +}
        +			
        +
        +
        + +

        +
        + + + Getting a List of + Devices from a + cdevCollection +

        +
        + + In some cases the developer may want to obtain a list of devices that constitute a + cdevCollection. This can be done by using the getList method. This method will obtain + a NULL terminated list of devices that currently comprise the cdevCollection. The + developer is responsible for deleting the character string array that is returned by this + method, however, one should not delete the individual character strings that are + stored in the array. +

        + +

        + + Figure 22: + + Getting a list of devices from a cdevCollection +
        + + + +
        + + +
        
        +#include <cdevCollection.h>
        + 
        +void main ( void )
        +{
        +/**************************************************************
        + * Attach to a cdevCollection device and then use the getList
        + * method to obtain the array of names that are currently
        + * stored in the cdevCollection and display them.
        + *
        + * Note that the list (not the list items) must be deleted by
        + * the caller.
        + **************************************************************/
        +cdevCollection & cDevice1 = 
        +cdevCollection::attachRef("cDevice1");
        + 
        +char ** list = cDevice1.getList();
        +for(char **s = list; *s!=NULL; s++) printf("%s\\n", *s);
        +delete list;
        +}
        +			
        +
        +
        + +

        +
        + + 7. +

        +
        + + + Restrictions of the cdevCollection Device +

        + + + + + + + + + + + + + +
        + + 1. +

        +
        + + Device names can only be added to or removed from the cdevCollection device + until it has been used once. After a cdevCollectionRequest object has been + generated from a specific cdevCollection device, the device list cannot be + modified. +

        +
        + + 2. +

        +
        + + cdevCollection devices do not support the messages "monitorOn" and + "monitorOff". Only monotonic operations are currently supported by the + cdevCollection device. +

        +
        + + 3. +

        +
        + + cdevCollection definitions must be the last things defined in the CDEV DDL file. + This is because the constituent devices must have already been defined when the + cdevCollection is defined. +

        +
        + + 4. +

        +
        + + When the data from a cdevDevice operation is used to construct the output + cdevData object for a cdevCollection operation, only data that is scalar in nature + will be used. If a cdevDevice returns tagged data items that are arrays in its + results, those data items will not be included in the result. +

        +
        + + 5. +

        +
        + + cdevCollection objects must be comprised of regular cdevDevice objects only. + Because the cdevCollection does not support cdevDevices that return arrays of + data in their result, a cdevCollection can not contain another cdevCollection. +

        +
        + + 6. +

        +
        + + If a cdevCollection consists of devices from multiple services, the collection does + not guarantee the order in which the cdevDevice's requests will be serviced. + Because services perform at varying speeds, a faster service may process its + devices requests sooner than another service. +

        +
        +
        + diff --git a/doc/html/cdevGateway.html b/doc/html/cdevGateway.html new file mode 100755 index 0000000..8485ceb --- /dev/null +++ b/doc/html/cdevGateway.html @@ -0,0 +1,864 @@ + + +CDEV Documentation + + + + + + +


        + + + +
        + + + + CDEV Gateway +

        + + +

        + A Message Router/Concentrator for CDEV Clients +

        + +

        + Walt Akers, Chip Watson, Jie Chen +

        + +

        + Version 1.0 - February 13, 1997 +

        + +

        + TJNAF - Thomas Jefferson National Accelerator Facility +

        + +

        +
        + +


        + + + + + +
        + + + + Table of Contents +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +
        +
        + + CDEV Gateway Fundamentals +
        +
        + + +
        +
        + + Overview of the CDEV Gateway +
        +
        + + +
        +
        + + Purpose of the CDEV Gateway +
        +
        + + +
        +
        + + Features of the CDEV Gateway Service +
        +
        + + 2. +
        +
        + + Building the CDEV Gateway Service +
        +
        + + +
        +
        + + Location of Files +
        +
        + + +
        +
        + + Steps to Building the Server and Service +
        +
        + + 3. +
        +
        + + Starting the CDEV Gateway +
        +
        + + +
        +
        + + Starting the Gateway Server +
        +
        + + +
        +
        + + Start-up Arguments for the Gateway Server +
        +
        + + 4. +
        +
        + + Troubleshooting Server Start-up +
        +
        + + 5. +
        +
        + + DDL Entries for the CDEV Gateway Client +
        +
        + + +
        +
        + + Setting Up the DDL +
        +
        +
        + +


        + + + + + +
        + + + + List of Figures +

        +
        + + + + Figure 1: + Simple DDL file for the Gateway Service +
        +
        + +


        + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + + CDEV Gateway Fundamentals +

        +
        + + + Overview of the + CDEV Gateway +

        +
        + + The CDEV Gateway is a server that acts as an intermediary between a CDEV + application and remote services. A single network connection is established between + the client and the gateway through which all CDEV requests will be routed. When the + gateway receives a request from the client, it establishes the appropriate connection + to the actual service, makes the request, and returns the result to the client + application. +

        +
        + + + Purpose of the + CDEV Gateway +

        +
        + + The CDEV Gateway was designed to support the JAVA/CDEV API. Because JAVA + code must be small in order to load and execute efficiently, it was critical to move as + much code as possible out of JAVA and into a CDEV "proxy" which could perform + connection management and dynamic library loading. This allows the JAVA + application to access new services provided in C++ without adding any new code. +

        + The JAVA/CDEV library locates the CDEV Gateway by using a hostname and port that + is provided in an environment variable. After determining the location of the server, + JAVA will establish a connection to the gateway and then begin transmitting its CDEV + requests in standard CLIP (CDEV Linear Internet Protocol). +

        + The gateway can also be used by standard C or C++ CDEV applications to perform + message routing. This approach can lessen the number of connections to actual + control system devices and reduce network traffic significantly. The gateway is located + by the gateway service by looking up its name (as specified in the CDEV DDL) in the + global name server (The current name server is distributed as part of the CDEV + Generic Server in the CDEV distribution). +

        +
        + + + Features of the + CDEV Gateway + Service +

        +
        + + + + + + + + + + + + + +
        + + +

        +
        + + The CDEV Gateway is constructed using the CDEV Generic Server Engine and + the CLIP Protocol. +

        +
        + + +

        +
        + + Each gateway server registers its name, host and port with the CDEV Name + Server when it is started. +

        +
        + + +

        +
        + + The name of the specific gateway to be used is associated with a CDEV device/ + message combination by using the "server" field of the service data in the CDEV + DDL file. Syntax is described later in this document. +

        +
        + + +

        +
        + + The gateway service will establish one connection to a named gateway to perform + all transactions. +

        +
        + + +

        +
        + + The client application uses a special DDL file that redirects all signals to the + gateway service. This allows the gateway server to maintain the actual control + system connections from a centralized location. +

        +
        + + +

        +
        + + The gateway server may have a standard DDL that redirects requests to the + actual service OR it may have a special DDL that routes requests to another + gateway. The system has currently been tested by routing messages through as + many as ten gateways before reaching the actual control system. Note that + performance begins to degrade substantially after routing through five gateways - + but is still reasonable. +

        +
        +
        + + 2. +

        +
        + + + Building the CDEV Gateway Service +

        +
        + + + Location of Files +

        +
        + + The source code for the Gateway Service is provided with the CDEV distribution + starting with version 1.5. The source code is located in the directory $CDEV/ + applications/cdevGateway. The following steps should be taken to build the Gateway + Server and Service. +

        +
        + + + Steps to Building + the Server and + Service +

        +
        + + + + + + + + + + + + + +
        + + 1. +

        +
        + + Obtain and install the CDEV distribution - Version 1.5 or higher. +

        +
        + + 2. +

        +
        + + Follow the installation steps to build CDEV on your system. This includes setting + all of the environment variables required by CDEV. +

        +
        + + 3. +

        +
        + + Follow the installation steps to build the CDEV Generic Server and deploy the + CDEV Name Server. +

        +
        + + 4. +

        +
        + + There is a collection of platform specific makefiles in the directory $CDEV/ + extensions/cdevGenericServer/include/makeinclude. Link the makefile that is + appropriate to your architecture to the file Makefile.OS in THAT directory. +

        + + For example, to link to the makefile for HP-UX, you would type the following + command. +

        + +

        + cd $CDEV/extensions/cdevGenericServer/makeinclude +

        + ln -s Makefile.hpux Makefile.OS +

        + +

        +
        + + 5. +

        +
        + + Change directories to $CDEV/applications/cdevGateway. +

        +
        + + 6. +

        +
        + + Type make to compile and link the CDEV Gateway Service shared object and the + CDEV Gateway Server. Note that you must be using GNU make in order to build + this distribution. +

        +
        + + Upon completion the Makefile will generate the shared object for the gateway service + and will install it into your CDEVSHOBJ directory. The gateway server will be + compiled, linked and installed in the directory $CDEV/applications/cdevGateway/bin/ + ARCH/cdevGateway. At this point you are ready to start the gateway server. +

        +
        + + 3. +

        +
        + + + Starting the CDEV Gateway +

        +
        + + + Starting the + Gateway Server +

        +
        + + The following steps should be taken to execute the cdevGateway. +

        + + + + + + + +
        + + 1. +

        +
        + + Ensure that the required CDEV and CDEV Generic Server environment variables + have been set. These include: +

        + + + + + + + +
        + + CDEVDDL +

        +
        + + This is the name of the DDL file that indicates where + messages should be routed. Typically, this DDL will + route the messages to the actual control system + devices. +

        +
        + + CDEVSHOBJ +

        +
        + + This is the location of the CDEV shared object files. +

        +
        + + CDEV_NAME_SERVER +

        +
        + + This is the host where the CDEV Name Server is + running. +

        +
        +
        + + 2. +

        +
        + + Move to the directory where the CDEV Gateway Server binary is located: by + default $CDEV/applications/cdevGateway/bin/ARCH, where ARCH is the name of + the host architecture. +

        +
        + + 3. +

        +
        + + Type the command ./cdevGateway at the command line. This will start a gateway + server with the name Gateway1 on the current host using TCP/IP port 9573. This + information can be confirmed by using the dumpServer command that is + provided with the CDEV Generic Server Engine to display the contents of the + CDEV Name Server. +

        +
        + + At this point the cdevGateway should be ready for use by client applications. +

        +
        + + + Start-up + Arguments for the + Gateway Server +

        +
        + + The user can specify the name of port used by the CDEV Gateway from the command + line when the server is started. The gateway server will accept the following + parameters from start-up. +

        + + + + + +
        + + s=server name +

        +
        + + This allows the caller to specify the server name that + will be registered with the name server. By default + the server name is Gateway1. +

        +
        + + p=port number +

        +
        + + This allows the caller to specify the port that the + server will use to receive incoming requests. By + default the port used by the server is 9573. +

        +
        +
        + + 4. +

        +
        + + + Troubleshooting Server Start-up +

        + + When the server is started it may display one or more error conditions that will prevent + it from operating properly. +

        + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + Error: +

        +
        + + syntax error at line:# +

        +
        + + Meaning: +

        +
        + + This message indicates that the CDEVDDL file that is being + used by the gateway is formatted improperly. +

        +
        + + Solution: +

        +
        + + Edit the CDEVDDL file and correct any formatting errors that + may exist. +

        +
        + + Error: +

        +
        + + ERROR: Gateway1 server already exists in GATEWAY domain +

        +
        + + Meaning: +

        +
        + + This message indicates that a gateway server with the name + Gateway1 has already been started and is currently registered + with the CDEV Name Server. +

        +
        + + Solution: +

        +
        + + The gateway will continue to attempt to register itself with the + name server every 30 seconds. If the message continues to + appear, then restart the gateway using the s parameter to + specify a different server name OR shutdown the other + gateway that is using the same name. +

        +
        + + Error: +

        +
        + + Could not communicate with name server +

        + ERROR: Failed to execute "REGISTER SERVER" operation +

        +
        + + Meaning: +

        +
        + + This message indicates that the CDEV Name Server could not + be accessed either because it is not running or because the + CDEV_NAME_SERVER environment variable does not specify + the correct host. +

        +
        + + Solution: +

        +
        + + Ensure that the CDEV_NAME_SERVER environment variable + is set and indicates the host where the name server is running. + If this is correct, check to ensure that the name server is + actually running on the specified host. +

        +
        + + Error: +

        +
        + + Error: Server Gateway1 - Unable to open listening socket +

        +
        + + Meaning: +

        +
        + + This message indicates that the port that the name server is + attempting to use to listen for new connections is already in + use. +

        +
        + + Solution: +

        +
        + + Use the command line arguments to specify a different listening + port. +

        +
        + + +

        + +

        + +

        + +

        +
        + + 5. +

        +
        + + + DDL Entries for the CDEV Gateway Client +

        +
        + + + Setting Up the + DDL +

        +
        + + The following example illustrates how to add a service entry to identify the CDEV + Gateway Service and how to use the service data to specify the server that the + gateway service will use for routing messages. +

        + +

        + + Figure 1: + + Simple DDL file for the Gateway Service +
        + + + +
        + + +
        
        +/*
        + * This is the service definition, it tells CDEV that there is
        + * a service named Gateway and that it will use the cdevData
        + * tag 'server' to locate the gateway using the CDEV Name Server.
        + */
        +service Gateway 
        +   {
        +   tags {server}
        +   }
        + 
        +/*
        + * This class definition identifies the class gatewayClass which
        + * supports the "get","set", "monitorOn" and "monitorOff"
        + * commands on attributes "attrib0" and "attrib1". Note that
        + * requests made to attrib0 will be routed through "Gateway1"
        + * and requests made to attrib1 will be routed through 
        + * "Gateway2".
        + */ 
        +class gatewayClass 
        +   {
        +       verbs {get, set, monitorOn, monitorOff}
        +   attributes 
        +      { 
        +      attrib0 Gateway {server=Gateway1};
        +      attrib1 Gateway {server=Gateway2};
        +      }
        +}
        + 
        +/*
        + * Finally, the CDEV DDL identifies two devices that are of type
        + * gatewayClass. Any time one of the supported messages is passed
        + * to one of these devices it will be routed through a CDEV 
        + * Gateway.
        + */
        +gatewayClass : device0, device1;
        +			
        +
        +
        + +

        + + +

        +
        + diff --git a/doc/html/cdevIntroduction.html b/doc/html/cdevIntroduction.html new file mode 100755 index 0000000..aab7098 --- /dev/null +++ b/doc/html/cdevIntroduction.html @@ -0,0 +1,1968 @@ + + +CDEV Documentation + + + + + + +


        + + + +
        + + + + Introduction to CDEV +

        + + Overview of the Control Device Interface +

        + +

        + + Chip Watson, Jie Chen, Danjin Wu, Walt Akers +

        + +

        + Version 1.5 December 9, 1996 +

        + +

        + TJNAF - Thomas Jefferson National Accelerator Facility +

        + +

        +
        + +


        + + + + + +
        + + + + Table of Contents +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +
        +
        + + Introduction +
        +
        + + +
        +
        + + What is CDEV +
        +
        + + +
        +
        + + Layering and Abstraction +
        +
        + + +
        +
        + + Information Hiding +
        +
        + + +
        +
        + + Device Object +
        +
        + + +
        +
        + + Standard Messages +
        +
        + + +
        +
        + + Data Object +
        +
        + + 2. +
        +
        + + Basic Operations on Devices and Data +
        +
        + + 3. +
        +
        + + Asychronous Operations +
        +
        + + +
        +
        + + Callback Object +
        +
        + + +
        +
        + + System Object +
        +
        + + +
        +
        + + Group Object +
        +
        + + +
        +
        + + Request Object +
        +
        + + +
        +
        + + File Descriptors and "select" +
        +
        + + 4. +
        +
        + + Error Handling +
        +
        + + 5. +
        +
        + + Name Resolution +
        +
        + + +
        +
        + + cdevDirectory Object +
        +
        + + +
        +
        + + Service Definition +
        +
        + + +
        +
        + + Device Class Definition +
        +
        + + +
        +
        + + Instance Definition +
        +
        + + +
        +
        + + Aliases +
        +
        + + 6. +
        +
        + + Channel Access Service +
        +
        +
        + +


        + + + + + +
        + + + + List of Figures +

        +
        + + + + Figure 1: + Sample usage of the send method of a cdevDevice +
        + + Figure 2: + Overview of cdevData operations +
        + + Figure 3: + Three forms of the send command +
        + + Figure 4: + Overview of the cdevCallback object and the cdevCallbackFunction +
        + + Figure 5: + Structure of the cdevCallback object +
        + + Figure 6: + Usage of the pend method in the cdevSystem object +
        + + Figure 7: + Synchronization methods in the cdevSystem object +
        + + Figure 8: + Sample usage of the cdevGroup object +
        + + Figure 9: + Sample usage of the cdevRequestObject object +
        + + Figure 10: + Structure of the cdevRequestObject object +
        + + Figure 11: + File descriptor routines of the cdevSystem object +
        + + Figure 12: + Using CDEV file descriptors with the UNIX select function +
        + + Figure 13: + Error handling mechanisms provided by the cdevSystem object +
        + + Figure 14: + Enumerated severity codes generated by CDEV +
        + + Figure 15: + Enumerated error codes generated by CDEV +
        + + Figure 16: + Obtaining a reference to the cdevDirectory device +
        + + Figure 17: + Virtual form of the data in a cdevDirectory +
        + + Figure 18: + Syntax of the #include directive +
        + + Figure 19: + Sample service definition +
        + + Figure 20: + Sample service definition +
        + + Figure 21: + Sample inherited class definition +
        + + Figure 22: + Multiple instances of the magnet class +
        + + Figure 23: + Alias device name +
        +
        + +


        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + + Introduction +

        +
        + + + What is CDEV +

        +
        + + The CDEV (common device) C++ class library is an object-oriented framework that + provides a standard interface between an application and one or more underlying + control packages or systems. Each underlying package (called a service) is + dynamically loaded at run-time, allowing an application to access a new service by + name without re-compilation or re-linking. A major feature of CDEV is its ability to hide + the implementation details of a particular device from the high level application + developer. This allows server implementation choices to be changed without breaking + high level client applications. Additionally, because the application is unaware of the + underlying service's specific implementation, CDEV is a powerful vehicle for + developing portable applications. +

        + The basic CDEV interface can be described through a device/message paradigm. The + device is not necessarily a physical object, rather, it is a cdevDevice object that + provides a standard interface to CDEV. The application uses this interface to send + messages to the device. When the cdevDevice receives this message it will + dynamically load the appropriate service (as defined in the CDEV device definition + file), and forward the message to it. The service may then perform any action + necessary to satisfy the application's request. +

        + The CDEV API is optimized for repetitive operations, in particular for monitoring value + changes within a server. Asychronous operations with callbacks are supported, + including asychronous error notification. Specifically, CDEV supports most features of + channel access (the EPICS communications protocol). +

        +
        + + + Layering and + Abstraction +

        +
        + + The CDEV library provides a standard interface to one or more underlying control + packages or systems. Currently CDEV provides support for EPICS channel access, + tcl scripts, the ACE communications package (a C++ class library over TCP/IP). The + ACE package is used to communicate with an on-line accelerator modeling package + and with CODA, the CEBAF On-line Data Acquisition system. Access to the EPICS + archive data will be added in a later release. All data will be available through a single + API (application programming interface). +

        +
        + + + Information Hiding +

        +
        + + The ability to hide the implementation details of a particular device (such as the choice + of records in EPICS) from the high level application developer, allows server + implementation choices to be changed without breaking all high level client + applications. For example, several records may be merged into a new custom record + without changing applications which access those records through the CDEV API. +

        +
        + + + Device Object +

        +
        + + The basic idea behind CDEV is that all I/O is performed by sending messages to + devices. A device is a named entity in the control system which can respond to a set + of messages such as on or off or get current. Further, a device is a virtual entity + potentially spanning multiple servers and services such as channel access, an + archiver, and a static database. +

        + Each device and message pair is mapped to a unique service (such as channel + access) and service dependent data (such as the process variable name in EPICS). + This mapping is kept in a name service, and is ultimately initialized from an ASCII file. + The designer/maintainer of the server would typically be the person responsible for + keeping the mapping current. +

        +
        + + + Standard + Messages +

        +
        + + Most devices will implement a number of attributes which may be read or written. In + order to facilitate developing generic applications, the following standard messages + are recommended for devices, where attrib is some attribute of the device: +

        +
        
        +   set attrib            => Set the value of the attribute
        +   get attrib            => Get the value of the attribute
        +   monitorOn attrib      => Start monitoring the value of the attribute
        +   monitorOff attrib     => Stop monitoring the value of the attribute
        +	
        +
        + + + Data Object +

        +
        + + The message sent to the device may have an associated data object. For example, + the message set current will have an associated value for the new current setting. This + value is passed as an additional argument on the send call. +

        + Data returned from the server to the client may contain multiple tagged values, + including value, status, and timestamp. Each of these items is extracted from the + returned data object by specifying a name or an integer tag. Any data object may + contain an arbitrary number of tagged entries, allowing considerable flexibility in + defining future clients and servers. +

        + Acknowledgment: This work derives some of its ideas about devices and messages + from work done at Argonne by Claude Saunders on a device oriented layer above + channel access. Much additional analysis & design work has been done by members + of the EPICS collaboration. +

        +
        + + 2. +

        +
        + + + Basic Operations on Devices and Data +

        + + The basic user deals only with the device and data objects. The device is created by + name, and I/O consists of sending messages to this device. The device object is the + simplest I/O object to use: a single device (magnet, viewer, etc.) may be completely + controlled from a single device object, with data being passed by 2 data objects (one + for output, another for returned results; dataless commands would not require either). + The following sample code reads the magnet current from one magnet, and sets the + magnet current for a second magnet to that value: +

        + +

        + + Figure 1: + + Sample usage of the send method of a cdevDevice +
        + + + +
        + + +
        
        +void main () 
        +   {
        +   // *************************************************************
        +   // * Get references to the 2 devices
        +   // *************************************************************
        +   cdevDevice& mag1 = cdevDevice::attachRef ("Magnet1");
        +   cdevDevice& mag2 = cdevDevice::attachRef ("Magnet2");
        +   cdevData result;
        + 
        +   // *************************************************************
        +   // * Get the current from the first magnet and use it to set 
        +   // * the current on the second.
        +   // *************************************************************   
        +   mag1.send("get current", NULL, result);
        +   mag2.send("set current", result, NULL);
        +   }
        +			
        +
        +
        + +

        + + +

        + The send call, which is synchronous, takes 3 arguments, and returns an integer + status: +

        +
        
        +   int send(char* msg, cdevData& out, cdevData& result);
        +	
        + + Like all CDEV calls, a return code of 0 means success (error handling is described in + a later section). The first argument to send is a character string message. The device + name and this string uniquely determine the underlying service to use, and whatever + addressing data that service needs to locate the server. The first send operation + automatically connects to the requested service, initializing any underlying packages + as needed. +

        + The second and third arguments are outbound and result data of type cdevData. This + is a composite data object which may contain an arbitrary number of data values + tagged with an integer tag. The data is self-describing to the extent that cdevData + keeps track of the data type, and can automatically convert between data types + through C++ function overloading or by explicit direction from the caller. The integer + tags are not known to the user at compile time (i.e., no header files required), and can + be referred to by character string equivalents. The cdevData class keeps track of all + integer tags and their character string equivalents. Character string tags may be + converted to integer tags at run time to improve performance. The following code + demonstrates how to insert values into and extract values from a cdevData object: +

        + + Figure 2: + + Overview of cdevData operations +
        + + + +
        + + +
        
        +cdevData d1, d2;
        +int valtag;
        +float x, x2;
        +int status;
        +...
        +d1.tagC2I("value",&valtag);     // get the integer tag for "value"
        +...
        +d1.insert("value",37.9);        // insert using a character tag
        +device.send("message",d1,d2);   // send d1, get back d2
        +d2.get(valtag,&x);              // get "value" from d2 into x
        +d2.get("status",&status);       // extract the "status"
        +x2 = d2;                        // get "value" into x2 (= overload)
        +			
        +
        +
        + +

        + + +

        + The last line above demonstrates using operator overloading to extract the "value" + item from the data object; i.e., the character tag "value" is the default tag to use in + extracting a data item for the "=" function overload. This form is available for all scalar + types supported by cdevData. +

        + Most I/O operations use the "value" tag to transmit a single value (scalar or array). + Other commonly used tags are "status" and "time" (a POSIX time struct). These + tagged data items are optionally returned by some servers under the control of the I/O + context (see below for changing the default context). +

        + In this release, cdevData supports the following data types: unsigned char, short, + unsigned short, int, unsigned int, long, unsigned long, float, double, character strings + and time stamp. All data types may be either scalar or multi-dimensional arrays. +

        +
        + + 3. +

        +
        + + + Asychronous Operations +

        + + In addition to the synchronous send, there are 2 asynchronous forms for sending + messages. The class definition for all three forms is given below. +

        + +

        + + Figure 3: + + Three forms of the send command +
        + + + +
        + + +
        
        +class cdevDevice: 
        +{
        +public:
        +   int send (char* msg, cdevData& out, cdevData& result);
        +   int sendNoBlock (char* msg, cdevData& out, cdevData& result);
        +   int sendCallback (char* msg, cdevData& out, cdevCallback cb);
        +};
        +			
        +
        +
        + +

        + + +

        + The second form, sendNoBlock, takes the same arguments as send but completes + asynchronously. That is, the result will be invalid until some synchronizing action is + taken (discussed below). The third form returns the result to a callback function + specified as part of the callback argument. For each of these asychronous calls, the + message may be buffered by the underlying service, so that upon return from the call + there is no guarantee that the message has even been sent yet. Transmission may be + forced with a flush call using the cdevSystem object described below. A flush is + automatically performed if pend is called. +

        +
        + + + Callback Object +

        +
        + + The callback object is a simple object containing 2 items: a function pointer, and an + arbitrary user argument. As an example, the following code fragment demonstrates + monitoring the magnet current asynchronously (the third argument to the callback + function is discussed later): +

        + +

        + + Figure 4: + + Overview of the cdevCallback object and the cdevCallbackFunction +
        + + + +
        + + +
        
        +// declare the callback func
        +cdevCallbackFunction gotit;
        + 
        +// create callback object                                    
        +cdevCallback callbk(gotit, myarg);                                    
        +...
        +mag1.sendCallback("monitorOn current",NULL,callbk);
        +...
        + 
        +void gotit(int status, void* userarg, cdevRequestObject& reqobj,
        +         cdevData& result)
        +   {
        +   float f = result;
        +   printf("new value is %f\\n",f);
        +   }
        + 
        +			
        +
        +
        + +

        + + +

        + The following code defines the callback (the cdevRequestObject is described below): +

        + +

        + + Figure 5: + + Structure of the cdevCallback object +
        + + + +
        + + +
        
        +typedef void (*cdevCallbackFunction)(int status, void* userarg,
        +                               cdevRequestObject& reqobj,
        +                               cdevData& result);
        +class cdevCallback 
        +{
        +public:
        +   cdevCallback (cdevCallbackFunction func, void* userarg);
        +   cdevCallbackFunction function;
        +   void* userarg;
        +}
        +			
        +
        +
        + +

        +
        
        + 
        +	
        +
        + + + System Object +

        +
        + + Waiting for completion of asychronous operations may be accomplished in one of two + ways: (1) using groups, and (2) using the system object. The system object keeps + track of all devices, and contains methods for flushing, polling, and pending for + asychronous operations. +

        + +

        + + Figure 6: + + Usage of the pend method in the cdevSystem object +
        + + + +
        + + +
        
        +// get default system
        +cdevSystem& sys = cdevSystem::defaultSystem();   
        +...
        +mag1.sendNoBlock("on",...);  // async op(s)
        +mag2.sendNoBlock("on",...);  // async op(s)
        +...
        +sys.pend();                  // wait for all I/O to complete   
        +			
        +
        +
        + +

        + + +

        + The following class interface shows the forms for each synchronization method: +

        + +

        + + Figure 7: + + Synchronization methods in the cdevSystem object +
        + + + +
        + + +
        
        +class cdevSystem 
        +{
        +public:
        +   intflush();
        +   int   poll();
        +   intpend();
        +}
        +			
        +
        +
        + +

        + + +

        + flush: Flush all pending output to the network for those services that perform send + buffering. +

        + poll: Flush all pending output, and process all received replies (including dispatching + callbacks, if any). Any received monitor callbacks will be delivered as well. +

        + pend: Flush all pending output, and process all replies for the specified number of + seconds. If the time argument is omitted, wait until all replies have been received. If a + monitor operation was started, this waits for the connection (first callback) only. +

        +
        + + + Group Object +

        +
        + + An alternative mechanism for waiting for asychronous calls is through the use of + groups. A group keeps track off all I/O operations started from the time the group is + started until the group is ended. Groups may be nested or overlapped, and support + the same flush/poll/pend operations as the system object. For example: +

        + +

        + + Figure 8: + + Sample usage of the cdevGroup object +
        + + + +
        + + +
        
        +cdevGroup g1, g2;
        +...
        +g1.start();
        +mag1.sendCallback(...);
        +mag2.sendCallback(...);
        +g2.start();
        +bpm1.sendNoBlock(...);
        +bpm2.sendNoBlock(...);
        +g1.end();
        +mag3.sendCallback(...);
        +bpm3.sendNoBlock(...);
        +g2.end();
        +g1.pend(4.0);
        +// at this point operations on mag1, mag2, bpm1, & bpm2 are done
        +// or have timed out (error handling discussed later).
        +...
        +// mag3 and bpm3 may not be finished yet, pend on the second
        +// group to wait for their completion
        +g2.pend();
        +			
        +
        +
        + +

        + + +

        + Note: Allowing nested or overlapped groups allows library calls to start or stop groups + without needing to know if another group is already active. +

        + Groups may be operated in one of two modes. Immediate mode (default) causes + grouped operations to be immediately executed, and the group is just used for + completion synchronization. Deferred mode causes messages to be held back until + the group is ended and the operations are flushed. After the operations are complete, + he group of operations may be flushed again (without re-posting), allowing the group + to function as a list manager/executor. +

        +
        + + + Request Object +

        +
        + + Occasionally, an I/O operation may need to be repeated may times. In this case, it is + not efficient to parse the message each time to determine which server to use. It is + possible to bypass this parsing by creating a request object. The request object is like + the device object, except that the message string is specified at creation time, and the + request object is therefore specific to the particular underlying service to which that + message must be directed. +

        + In the case of EPICS channel access, the request object opens and maintains the + channel to the EPICS process variable. The request object is NOT the same as an + EPICS channel, in that the request object binds a device and a message, and the + message implies a direction. If the message is considered to be of the form verb + + attribute then the EPICS channel essentially binds device and attribute but not verb. In + some future release of CDEV, a more channel like object may be included if there is a + demand for it. If two cdevRequestObjects reference the same EPICS channel, only a + single channel access connection is established. +

        + The following code demonstrates sending a set of data values to a single magnet + using a request object. Note that the send call omits the message argument: +

        + + Figure 9: + + Sample usage of the cdevRequestObject object +
        + + + +
        + + +
        
        +cdevRequestObject& mag1BDL =
        +   cdevRequestObject::attachRef("mag1","set BDL");
        +cdevData mydata;
        +...
        +   {
        +   mydata = i*10;               // 10 amp steps
        +   mag1BDL.send(mydata,NULL);   // ignore errors for now
        +   sleep(1);
        +   }
        +			
        +
        +
        + +

        + + +

        + In most cases, the device object will create the request object to perform a requested + I/O operation. All 3 forms of send are supported by the request object, with a calling + syntax identical to the device calls without the message argument. The interface to the + request object is given below: +

        + +

        + + Figure 10: + + Structure of the cdevRequestObject object +
        + + + +
        + + +
        
        +class cdevRequestObject 
        +{
        +public:
        +   char* message();           // returns the message string
        +   cdevDevice& device();      // returns the device object
        +   int state();               // connected/disconnected/   
        +   int access();              // read/write/none
        +   int send(cdevData& out, cdevData& result);
        +   int sendNoBlock(cdevData& out, cdevData& result);
        +   int sendCallback(cdevData& out, cdevCallback callback);
        +}
        +			
        +
        +
        + +

        + + +

        + When an asynchronous operation completes, the relevant request object is passed to + the user's callback routine. This allows the user to extract the message string and + device name from the request object if necessary or desired. +

        +
        + + + File Descriptors + and "select" +

        +
        + + An alternative mechanism for dealing with asynchronous operations is to directly test + the file descriptors being used. This interface is currently implemented in the + cdevSystem class. The pertinent methods have the following form: +

        + +

        + + Figure 11: + + File descriptor routines of the cdevSystem object +
        + + + +
        + + +
        
        +typedef void (*cdevFdChangedCallback)(int fd, int opened, 
        +             void* userarg)
        +class cdevSystem 
        +{
        +public:
        +   ...
        +   int getFd(int fd[], int &numFD);
        +   int addFdChangedCallback(cdevFdChangedCallback cbk, void* arg);
        +}
        +			
        +
        +
        + +

        + + The getFd method will populate a user allocated array of integers (fd) with the file + descriptors currently in use by the cdevSystem object. The number of file descriptors + that were allocated by the user is specified in the numFD variable. Upon completion, + the numFD variable will be set to the number of file descriptors actually copied into the + fd array. An error is returned if the buffer is not sufficient to store the complete set of + file descriptors. +

        + The addFdChangedCallback method allows the user to specify a function to be called + each time a file descriptor is added (opened=1) or closed (opened=0). +

        + The following code illustrates the usage of the UNIX select call: +

        + +

        + + Figure 12: + + Using CDEV file descriptors with the UNIX select function +
        + + + +
        + + +
        
        +int myFD[5];
        + 
        +void mySelectLoop ( cdevSystem & system )
        +   {
        +   int fd[20];
        +   int numFD = 15, nfds;
        +   fd_set rfds; // Ready file descriptors
        +   fd_set afds; // Active file descriptors
        + 
        +   // Copy the file descriptors I am already using to the list
        +   memcpy(fd, myFD, sizeof(myFD));
        + 
        +   // Get the file descriptors in use by the cdevSystem object
        +   system.getFd(&fd[5], numFD);
        +   
        +   // Add in the 5 previously defined file descriptors
        +   numFD += 5;
        + 
        +   // Zero the active file descriptors
        +   FD_ZERO(&afds);
        +   
        +   // Setup the active file descriptors
        + 
        +   // Get the maximum number of file descriptors
        +   nfds = FD_SETSIZE;
        +   
        +   while(1) {
        +      // Copy the active descriptors to the ready descriptors
        +      memcpy((void *)&rfds, (void *)&afds, sizeof(rfds));
        + 
        +      // Use select to detect activity on the file descriptors
        +   
        +      // Iterate through the list of file descriptors 
        +         {
        +         if (FD_ISSET(fd[i], &rfds) 
        +            {
        +            // Respond to active file descriptor here
        +            }
        +         }
        +      }
        +   }
        +			
        +
        +
        + +

        +
        + + 4. +

        +
        + + + Error Handling +

        + + Most CDEV routines return an integer status, with 0=success. Errors may also be + automatically printed or routed to a user supplied error handler. Control over this + behavior is through the system object: +

        + +

        + + Figure 13: + + Error handling mechanisms provided by the cdevSystem object +
        + + + +
        + + +
        
        +typedef void (*cdevErrorHandler)(int severity, char* text, 
        +                                 cdevRequestObject& request);
        +class cdevSystem 
        +{
        +public:
        +   ...
        +   int autoErrorOn();
        +   int autoErrorOff();
        +   cdevErrorHandler setErrorHandler(cdevErrorHandler handler = 0);
        +   int reportError(int severity, char *name, 
        +                   cdevRequestObject* request, char* format, ...);
        +   void setThreshold ( int errorThreshold );
        +}
        +			
        +
        +
        + +

        + + +

        + The severity parameter indicates the level of the error. Severity levels are informative, + warning, error, and severe error. The following values are defined in cdevErrCode.h to + describe the severity of an error message: +

        + +

        + + Figure 14: + + Enumerated severity codes generated by CDEV +
        + + + +
        + + +
        
        +CDEV_SEVERITY_INFO    Informative message
        + 
        +CDEV_SEVERITY_WARN    Warning message - operation encountered a
        +                      problem during processing.
        + 
        +CDEV_SEVERITY_ERROR   Error message - operation cannot be completed
        + 
        +CDEV_SEVERITY_SEVERE  Severe/Fatal Error - cdev cannot continue 
        +                      execution
        +			
        +
        +
        + +

        + + +

        + autoErrorOn Turn on default error handling, which prints error to stdout. +

        + autoErrorOff Turn off default error handling. +

        + setErrorHandler Set a new function to be the system error handler. Return the old + function pointer. Omitting the argument resets the handler to the default handler which + simply prints error messages to stderr. +

        + reportError Routine which behaves like printf with 3 additional arguments (severity, + caller's name, and request object if available). +

        + Note: For simplicity of use, a very compact set of error codes is implemented in CDEV. + The following error codes are defined in the header file cdevErrCode.h. +

        + +

        + + Figure 15: + + Enumerated error codes generated by CDEV +
        + + + +
        + + +
        
        +CDEV_WARNING        = -2  Failure of function is non-consequential
        +CDEV_ERROR          = -1  Errors that are not in any categories
        +CDEV_SUCCESS        = 0   Success
        +CDEV_INVALIDOBJ     = 1   Invalid cdev objects
        +CDEV_INVALIDARG     = 2   Invalid argument passed to cdev calls
        +CDEV_INVALIDSVC     = 3   Wrong service during dynamic loading
        +CDEV_INVALIDOP      = 4   Operation is unsupported (collection)
        +CDEV_NOTCONNECTED   = 5   Not connected to low network service
        +CDEV_IOFAILED       = 6   Low level network service IO failed
        +CDEV_CONFLICT       = 7   Conflicts of data types or tags
        +CDEV_NOTFOUND       = 8   Cannot find user request (cdevData)
        +CDEV_TIMEOUT        = 9   Time out
        +CDEV_CONVERT        = 10  cdevData Conversion error
        +CDEV_OUTOFRANGE     = 11  Value out of range for device attribute
        +CDEV_NOACCESS       = 12  Insufficient access to perform request
        +CDEV_ACCESSCHANGED  = 13  Change in access permission of device
        +CDEV_DISCONNECTED   = 60  Application has lost server connection
        +CDEV_RECONNECTED    = 61  Application has regained server connection
        +			
        +
        +
        + +

        +
        + + 5. +

        +
        + + + Name Resolution +

        + + Some type of name resolution system is needed to (1) locate which package (called a + service) underneath CDEV will support the specified message for the specified device + and (2) provide parameters needed by the service to contact the server and perform + the desired operation. For example, the message "get current" sent to a magnet + "mag1" might use the service "ca" (channel access), with parameter "mag1cur.val" + (record and field). This parameter is referred to as service data, i.e. data used by the + service to perform the operation. The user is typically unaware of this data, which + should be supplied by the device implementer. +

        +
        + + + cdevDirectory + Object +

        +
        + + Name resolution in CDEV is implemented by the cdevDirectory device. The + cdevDirectory device supports a query message allowing the user to search the + Device Directory List (DDL) for devices which are (1) members of a user specified + class or (2) match a user specified regular expression. +

        + As with any cdevDevice object, the user instantiates a cdevDirectory device by using + the cdevDevice::attachPtr() or cdevDevice::attachRef() method. The following code + fragment illustrates the correct method for attaching to a cdevDirectory device. +

        +
        
        + 
        +	
        + + Figure 16: + + Obtaining a reference to the cdevDirectory device +
        + + + +
        + + +
        
        +cdevDevice & device = cdevDevice::attachRef("cdevDirectory");
        +			
        +
        +
        + +

        + + +

        + Like all other devices, the cdevDirectory response to messages. The following + messages may be submitted to this device: +

        + + + + + + + + + + + + + + + + + + + +
        + + +

        +
        + + query: Identify the devices that match the selection criteria. +

        +
        + + +

        +
        + + queryClass: Identify the DDL class from which a device is instantiated. +

        +
        + + +

        +
        + + queryAttributes: Identify all attributes supported by a device or a DDL class. +

        +
        + + +

        +
        + + queryMessages: Identify all messages supported by a device or DDL class. +

        +
        + + +

        +
        + + queryVerbs: Identify all verbs supported by a device or DDL class. +

        +
        + + +

        +
        + + service: Identify the service that is used by a device/message pair. +

        +
        + + +

        +
        + + serviceData: Identify service data specified for a device/message pair. +

        +
        + + +

        +
        + + update: Add information to the cdevDirectory data structure. +

        +
        + + +

        +
        + + validate: Verify that a device or DDL class contains certain definitions. +

        +
        + + +

        + By default, there is a single directory device. To allow for arbitrary expansion CDEV + will allow each service to register additional directory devices with the system object. + A search list of directories may be specified to the system directory device (planned + feature). +

        + Each directory acts as if it has a table of information in the following form: +

        + +

        + + Figure 17: + + Virtual form of the data in a cdevDirectory +
        + + + +
        + + +
        
        +dev-class dev-namemessageserviceservice-data
        +   magnet   mag1   on   ca   {pv=M1CSR.VAL default=1}
        +			
        +
        +
        + +

        + + +

        + This table is loaded from a device definition file which describes the mapping from + (device,message) to (service,serviceData), where "service" is one of the dynamically + loaded CDEV services, and "serviceData" is whatever information that service needs + to send the message to the device. In this example the service data contains an + EPICS process variable name and a default value to write to that channel. +

        + It is NOT the purpose of the device definition file to completely specify the datatypes of + all data passed between device and user. CDEV does considerable data type + conversion as needed, and services do reasonable run-time validation. The goal is to + make the file as small as is reasonably possible and still maintain readability. +

        + General: +

        + + + +
        + + + + leading whitespace is not significant +

        + + + any amount of whitespace may separate language elements, including + space, tab, and newline, with the exception that at least one whitespace + character is needed before the colon separating a class name and its + inherited classes. +

        + + + keywords are case sensitive +

        + + NOTE: This specification is preliminary, and will be expanded to support additional + features as time allows. +

        + The interface definition consists of three parts: service definitions, device class + definitions, and device instantiation (in that order). Standard definitions may be + specified via include files using a cpp syntax: +

        + +

        + + Figure 18: + + Syntax of the #include directive +
        + + + +
        + + +
        
        +#include "filename"
        +				
        +
        +
        + +

        +
        +
        + + + Service Definition +

        +
        + + The service definition declares a service name, and lists all tags which the service will + accept for its "serviceData". The following 3 lines define a service named "myservice" + which supports serviceData that specifies values for any of the tags "abc", "def", and + "ghi": +

        + +

        + + Figure 19: + + Sample service definition +
        + + + +
        + + +
        
        +service myservice 
        +   {
        +   tags {abc, def, ghi}
        +   }
        +			
        +
        +
        + +

        + + +

        + As a more concrete example, the following is the specification for thechannel access + service: +

        + +

        + + Figure 20: + + Sample service definition +
        + + + +
        + + +
        
        +service ca
        +   {
        +   tags {pv, default}
        +   }
        +			
        +
        +
        + +

        + + +

        + The "pv" tag is used to specify the process variable name, and the "default" tag is used + to specify a default value for a "set" operation (examples are below). +

        +
        + + + Device Class + Definition +

        +
        + + Device classes are used to define a collection of similar devices; that is, devices which + will respond to the same set of messages. In order to simplify class definition, the + following design choices are made: +

        + + + +
        + + + + multiple inheritance is supported, and +

        + + + messages may be defined as verb + attribute, where the list of verbs is + defined separately from the list of attributes. +

        + + The second item reduces the amount of text needed to define a device, since all + operations on a single attribute (get, set, monitor, etc.) may be defined in a single line + as long as they all use the same serviceData. +

        + For this initial specification, the class definition contains 4 parts: +

        + + + inheritance specification +

        + + + verbs +

        + + + attributes +

        + + + messages +

        + + For each attribute or message there are 3 parts: +

        + + + attribute or message text +

        + + + service name +

        + + + service data +

        + + Service data is zero or more (name=value) pairs, where the allowed set of names are + defined by the "tags" clause in the service specification. The value may contain a pair + of angle brackets "<>" into which the device name will be substituted. +

        + Example: Suppose there are a set of magnets for which it is possible to read and write + bdl (integral field), and current (amps). That is, the messages "get bdl", "get current", + "set bdl", etc. are valid. Also, each magnet responds to the commands "on" and "off". + Further suppose that the beamline position and length of the magnet are available in a + static database (assume read/write). +

        + Here is a complete class definition: +

        + +

        + + Figure 21: + + Sample inherited class definition +
        + + + +
        + + +
        
        +class stdio 
        +   {
        +   verbs {get, set, monitorOn, monitorOff}
        +   }
        + 
        +class magnet : stdio 
        +   {
        +   attributes 
        +      {
        +      bdl    ca {pv=<>.bdl};
        +      current ca {pv=<>.val};
        +      zpos    os {path=<>/phy/z};
        +      length    os {path=<>/phy/len}
        +      }
        +   messages 
        +      {
        +      on   ca {pv=<>CSR.val, default=1};
        +      off   ca {pv=<>CSR.val, default=0};
        +      }
        +   }
        +				
        +
        +
        + +

        + + +

        + Note the semicolon at the end of each line of attributes or messages (except for the + last line). Note also that the process variable name has a place holder into which the + device name will be substituted. More sophisticated name mangling is envisaged, but + not for this release. Syntax is still open to revision. +

        +
        +
        + + + Instance Definition +

        +
        + + Instances of a class are given by following the class name with a list of instance + names. Device names may be separated by whitespace characters (including + newline) or by commas. +

        + +

        + + Figure 22: + + Multiple instances of the magnet class +
        + + + +
        + + +
        
        +magnet : m1 m2 m3;
        +			
        +
        +
        + +

        + + +

        + Combined with the previous definition, the message "on" sent to magnet m2 would + select the process variable "m2CSR.val" with "1" as the value to write. +

        +
        + + + Aliases +

        +
        + + Sometimes it is convenient to refer to a device by more than one name. The DDL + syntax supports simple aliases, one per line. +

        + +

        + + Figure 23: + + Alias device name +
        + + + +
        + + +
        
        +alias myname m1
        +			
        +
        +
        + +

        + + +

        + +

        +
        + + 6. +

        +
        + + + Channel Access Service +

        + + EPICS / Channel Access version 3.12 is recommended. +

        + Features: +

        + + + + + + + + + +
        + + +

        +
        + + Supports synchronous and asynchronous send's. +

        +
        + + +

        +
        + + Tracks file descriptor registration. +

        +
        + + +

        +
        + + Fetches data in native type (type conversion done on client and not server). +

        +
        + + +

        +
        + + Provides a default name service so that if a device is not defined, then an + EPICS channel access connection is attempted with the record name set equal + to the device name, and the field name set equal to the attribute name. +

        +
        + + Restrictions: +

        + + + + + + + +
        + + +

        +
        + + Only supports set/get/monitorOn/monitorOff verbs and the pv and readonly + tags. Support for arbitrary messages with default data will be in the next release. +

        +
        + + +

        +
        + + Discards all exception callbacks from channel access in this version. +

        +
        + + +

        +
        + + Channel access security is not supported in this release. +

        +
        + + Compilation options: +

        + + + + + + + +
        + + +

        +
        + + _CA_SYNC_CONN = perform connections synchronously, waiting up to 4 + seconds. +

        +
        + + +

        +
        + + _CDEV_DEBUG = print verbose messages +

        +
        + + +

        +
        + + _EPICS_3_12 = if not defined, use 3.11 calls instead. +

        +
        + + +

        + +

        +
        + diff --git a/doc/html/cdevReference.html b/doc/html/cdevReference.html new file mode 100755 index 0000000..359ba24 --- /dev/null +++ b/doc/html/cdevReference.html @@ -0,0 +1,8150 @@ + + +CDEV Documentation + + + + + + +


        + + + +
        + + + + CDEV Reference Guide +

        + + +

        + Chip Watson, Jie Chen, Danjin Wu, Walt Akers +

        + +

        + Version 1.5 - December 9, 1996 +

        + +

        + TJNAF - Thomas Jefferson National Accelerator Facility +

        +
        + +


        + + + + + +
        + + + + Table of Contents +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +
        +
        + + The cdevCallback Class +
        +
        + + +
        +
        + + Overview of the cdevCallback Class +
        +
        + + +
        +
        + + Public Methods of the cdevCallback Class +
        + + + + + + + + + + + + + + + +
        + + +
        +
        + + cdevCallback +
        +
        + + +
        +
        + + callbackFunction +
        +
        + + +
        +
        + + userarg +
        +
        + + +
        +
        + + operator == +
        +
        + + +
        +
        + + operator != +
        +
        + + +
        +
        + + fireCallback +
        +
        + + +
        +
        + + isTransactionDone +
        +
        +
        + + 2. +
        +
        + + The cdevCollection Class +
        +
        + + +
        +
        + + Overview of the cdevCollection Class +
        +
        + + +
        +
        + + Public Methods of the cdevCollection Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + cdevCollection +
        +
        + + +
        +
        + + ~cdevCollection +
        +
        + + +
        +
        + + getRequestObject +
        +
        + + +
        +
        + + attachRef/attachPtr +
        +
        + + +
        +
        + + detach +
        +
        + + +
        +
        + + className +
        +
        + + +
        +
        + + add +
        +
        + + +
        +
        + + add +
        +
        + + +
        +
        + + add +
        +
        + + +
        +
        + + add +
        +
        + + +
        +
        + + addRegexp +
        +
        + + +
        +
        + + remove +
        +
        + + +
        +
        + + remove +
        +
        + + +
        +
        + + remove +
        +
        + + +
        +
        + + remove +
        +
        + + +
        +
        + + removeRegexp +
        +
        +
        + + 3. +
        +
        + + The cdevCollectionRequest Class +
        +
        + + +
        +
        + + Overview of the cdevCollection Request Class +
        +
        + + +
        +
        + + Public Methods of the cdevCollection Request Class +
        + + + + + + + + + + + +
        + + +
        +
        + + constructor +
        +
        + + +
        +
        + + destructor +
        +
        + + +
        +
        + + attachPtr +
        +
        + + +
        +
        + + className +
        +
        + + +
        +
        + + resultCodeTag +
        +
        +
        + + 4. +
        +
        + + The cdevData Class +
        +
        + + +
        +
        + + Overview of the cdevData Class +
        +
        + + +
        +
        + + Public Methods of the cdevData Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + tagC2I +
        +
        + + +
        +
        + + tagI2C +
        +
        + + +
        +
        + + insertTag +
        +
        + + +
        +
        + + addTagCallback +
        +
        + + +
        +
        + + delTagCallback +
        +
        + + +
        +
        + + readTagTable +
        +
        + + +
        +
        + + Operator = +
        +
        + + +
        +
        + + Cast operators +
        +
        + + +
        +
        + + Operator == +
        +
        + + +
        +
        + + Operator != +
        +
        + + +
        +
        + + asciiDump +
        +
        + + +
        +
        + + xdrSize +
        +
        + + +
        +
        + + xdrExport +
        +
        + + +
        +
        + + xdrExport +
        +
        + + +
        +
        + + xdrImport +
        +
        + + +
        +
        + + remove +
        +
        + + +
        +
        + + changeTag +
        +
        + + +
        +
        + + getType +
        +
        + + +
        +
        + + getDim +
        +
        + + +
        +
        + + getElems +
        +
        + + +
        +
        + + getBounds +
        +
        + + +
        +
        + + setBounds +
        +
        + + +
        +
        + + insert (scalar) +
        +
        + + +
        +
        + + insert (array) +
        +
        + + +
        +
        + + insert (character string) +
        +
        + + +
        +
        + + get +
        +
        + + +
        +
        + + get (character string) +
        +
        + + +
        +
        + + find +
        +
        +
        + + 5. +
        +
        + + The cdevDevice Class +
        +
        + + +
        +
        + + Overview of the cdevDevice Class +
        +
        + + +
        +
        + + Public Methods of the cdevDevice Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + attachRef +
        +
        + + +
        +
        + + attachPtr +
        +
        + + +
        +
        + + detach +
        +
        + + +
        +
        + + detach +
        +
        + + +
        +
        + + getRequestObject +
        +
        + + +
        +
        + + name +
        +
        + + +
        +
        + + system +
        +
        + + +
        +
        + + setContext +
        +
        + + +
        +
        + + getContext +
        +
        + + +
        +
        + + setPrivate +
        +
        + + +
        +
        + + getPrivate +
        +
        + + +
        +
        + + send +
        +
        + + +
        +
        + + sendNoBlock +
        +
        + + +
        +
        + + sendCallback +
        +
        +
        + + 6. +
        +
        + + The cdevError Class +
        +
        + + +
        +
        + + Overview of the cdevError Class +
        +
        + + +
        +
        + + Public Methods of the cdevError Class +
        + + + + + + + + + + + +
        + + +
        +
        + + autoErrorOn +
        +
        + + +
        +
        + + autoErrorOff +
        +
        + + +
        +
        + + reportError +
        +
        + + +
        +
        + + setErrorHandler +
        +
        + + +
        +
        + + setThreshold +
        +
        +
        + + 7. +
        +
        + + The cdevGroup Class +
        +
        + + +
        +
        + + Overview of the cdevGroup Class +
        +
        + + +
        +
        + + Public Methods of the cdevGroup Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + cdevGroup +
        +
        + + +
        +
        + + start +
        +
        + + +
        +
        + + end +
        +
        + + +
        +
        + + flush +
        +
        + + +
        +
        + + poll +
        +
        + + +
        +
        + + pend +
        +
        + + +
        +
        + + pend +
        +
        + + +
        +
        + + allFinished +
        +
        + + +
        +
        + + status +
        +
        + + +
        +
        + + execDeferred +
        +
        + + +
        +
        + + execImmediate +
        +
        + + +
        +
        + + executionMode +
        +
        + + +
        +
        + + readyToExec +
        +
        +
        + + 8. +
        +
        + + The cdevIOContext Class +
        +
        + + +
        +
        + + Overview of the cdevIOContext Class +
        +
        + + +
        +
        + + Public Methods of the cdevIOContext Class +
        + + + + + + + + + +
        + + +
        +
        + + getContext +
        +
        + + +
        +
        + + setContext +
        +
        + + +
        +
        + + getPrivate +
        +
        + + +
        +
        + + setPrivate +
        +
        +
        + + 9. +
        +
        + + The cdevRequestObject Class +
        +
        + + +
        +
        + + Overview of the cdevRequestObject Class +
        +
        + + +
        +
        + + Public Methods of the cdevRequestObject Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + attachRef +
        +
        + + +
        +
        + + attachRef +
        +
        + + +
        +
        + + attachPtr +
        +
        + + +
        +
        + + attachPtr +
        +
        + + +
        +
        + + detach +
        +
        + + +
        +
        + + detach +
        +
        + + +
        +
        + + message +
        +
        + + +
        +
        + + device +
        +
        + + +
        +
        + + system +
        +
        + + +
        +
        + + service +
        +
        + + +
        +
        + + getState +
        +
        + + +
        +
        + + getAccess +
        +
        + + +
        +
        + + setContext +
        +
        + + +
        +
        + + getContext +
        +
        + + +
        +
        + + getPrivate +
        +
        + + +
        +
        + + setPrivate +
        +
        + + +
        +
        + + send +
        +
        + + +
        +
        + + sendNoBlock +
        +
        + + +
        +
        + + sendCallback +
        +
        +
        + + 10. +
        +
        + + The cdevSelector Class +
        +
        + + +
        +
        + + Overview of the cdevSelector Class +
        +
        + + +
        +
        + + Public Methods of the cdevSelector Class +
        + + + + + + + + + + + +
        + + +
        +
        + + insertEvent +
        +
        + + +
        +
        + + removeEvent +
        +
        + + +
        +
        + + purge +
        +
        + + +
        +
        + + writefd +
        +
        + + +
        +
        + + readfd +
        +
        +
        + + 11. +
        +
        + + The cdevService Class +
        +
        + + +
        +
        + + Overview of the cdevService Class +
        +
        + + +
        +
        + + Public Methods of the cdevService Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + flush +
        +
        + + +
        +
        + + poll +
        +
        + + +
        +
        + + pend +
        +
        + + +
        +
        + + pend +
        +
        + + +
        +
        + + getRequestObject +
        +
        + + +
        +
        + + getNameServer +
        +
        + + +
        +
        + + getCollectionRequest +
        +
        + + +
        +
        + + getFd +
        +
        + + +
        +
        + + registerFd +
        +
        + + +
        +
        + + autoErrorOn +
        +
        + + +
        +
        + + autoErrorOff +
        +
        + + +
        +
        + + reportError +
        +
        + + +
        +
        + + setErrorHandler +
        +
        + + +
        +
        + + setThreshold +
        +
        + + +
        +
        + + name +
        +
        +
        + + 12. +
        +
        + + The cdevSync Class +
        +
        + + +
        +
        + + Overview of the cdevSync Class +
        +
        + + +
        +
        + + Public Methods of the cdevSync Class +
        + + + + + + + + + +
        + + +
        +
        + + flush +
        +
        + + +
        +
        + + poll +
        +
        + + +
        +
        + + pend +
        +
        + + +
        +
        + + pend +
        +
        +
        + + 13. +
        +
        + + The cdevSystemBase Class +
        +
        + + +
        +
        + + Overview of the cdevSystemBase Class +
        +
        + + +
        +
        + + Public Methods of the cdevSystemBase Class +
        + + + +
        + + +
        +
        + + getRequestObject +
        +
        +
        + + 14. +
        +
        + + The cdevSystem Class +
        +
        + + +
        +
        + + Overview of the cdevSystem Class +
        +
        + + +
        +
        + + Public Methods of the cdevSystem Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + attachRef +
        +
        + + +
        +
        + + attachPtr +
        +
        + + +
        +
        + + defaultSystem +
        +
        + + +
        +
        + + getDevice +
        +
        + + +
        +
        + + getRequestObject +
        +
        + + +
        +
        + + name +
        +
        + + +
        +
        + + prefix +
        +
        + + +
        +
        + + prefix +
        +
        + + +
        +
        + + flush +
        +
        + + +
        +
        + + poll +
        +
        + + +
        +
        + + pend +
        +
        + + +
        +
        + + pend +
        +
        + + +
        +
        + + getFd +
        +
        + + +
        +
        + + addFdChangedCallback +
        +
        + + +
        +
        + + autoErrorOn +
        +
        + + +
        +
        + + autoErrorOff +
        +
        + + +
        +
        + + reportError +
        +
        + + +
        +
        + + setErrorHandler +
        +
        + + +
        +
        + + setThreshold +
        +
        +
        + + 15. +
        +
        + + The cdevTranObj Class +
        +
        + + +
        +
        + + Overview of the cdevTranObj Class +
        +
        + + +
        +
        + + Public Data Properties of the cdevTranObj Class +
        + + + + + + + + + +
        + + +
        +
        + + system_ +
        +
        + + +
        +
        + + reqObj_ +
        +
        + + +
        +
        + + resultData_ +
        +
        + + +
        +
        + + userCallback_ +
        +
        +
        + + +
        +
        + + Public Member Functions of the cdevTranObj Class +
        + + + + + + + + + +
        + + +
        +
        + + status +
        +
        + + +
        +
        + + removeFromGrps +
        +
        + + +
        +
        + + enableDeleteCbk +
        +
        + + +
        +
        + + disableDeleteCbk +
        +
        +
        + + 16. +
        +
        + + Language Specification for the cdev DDL file +
        +
        + + +
        +
        + + Language Specification +
        +
        + + 17. +
        +
        + + Regular Expressions +
        +
        + + +
        +
        + + Overview of Regular Expressions +
        +
        + + +
        +
        + + Ordinary Characters +
        +
        + + +
        +
        + + Special Characters +
        + + + + + + + + + + + + + +
        + + +
        +
        + + . [ \\ +
        +
        + + +
        +
        + + * +
        +
        + + +
        +
        + + ^ +
        +
        + + +
        +
        + + $ +
        +
        + + +
        +
        + + delimiter +
        +
        + + +
        +
        + + period +
        +
        +
        + + +
        +
        + + Bracket Expression +
        + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + bracket expression +
        +
        + + +
        +
        + + . * [ \\ +
        +
        + + +
        +
        + + matching list +
        +
        + + +
        +
        + + non-matching list +
        +
        + + +
        +
        + + collating element +
        +
        + + +
        +
        + + collating symbol +
        +
        + + +
        +
        + + noncollating char +
        +
        + + +
        +
        + + equivalence class +
        +
        + + +
        +
        + + range expression +
        +
        + + +
        +
        + + character class +
        +
        +
        + + +
        +
        + + Matching Multiple Characters +
        + + + + + + + + + + + +
        + + +
        +
        + + RERE +
        +
        + + +
        +
        + + RE* +
        +
        + + +
        +
        + + \\(RE\\) +
        +
        + + +
        +
        + + \\n +
        +
        + + +
        +
        + + RE\\{m,n\\} +
        +
        +
        + + +
        +
        + + Expression Anchoring +
        +
        +
        + +


        + + + + + +
        + + + + List of Figures +

        +
        + + + + Figure 1: + Object model of the cdevCallback class +
        + + Figure 2: + Object Model of the cdevCollection Class +
        + + Figure 3: + Object Model of the cdevCollectionRequest Class +
        + + Figure 4: + Object model of the cdevData class +
        + + Figure 5: + Object model of the cdevDevice class +
        + + Figure 6: + Return codes generated by the send method. +
        + + Figure 7: + Object model of the cdevError class +
        + + Figure 8: + Object model of the cdevGroup class +
        + + Figure 9: + Object model of the cdevIOContext class +
        + + Figure 10: + Object model of the cdevRequestObject class +
        + + Figure 11: + Return codes generated by the send method. +
        + + Figure 12: + Object model of the cdevSelector class +
        + + Figure 13: + Object model of the cdevService class +
        + + Figure 14: + Object model of the cdevSync class +
        + + Figure 15: + Object model of the cdevSystemBase class +
        + + Figure 16: + Object model of the cdevSystem class +
        + + Figure 17: + Object model of the cdevTranObj class +
        + + Figure 18: + Language specification for the cdev DDL file +
        +
        + +


        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + + The cdevCallback Class +

        +
        + + + Overview of the + cdevCallback + Class +

        +
        + + The cdevCallback C++ class is used by the sendCallback method to specify the + callback function that should be executed when the message has been processed. + This class also allows the caller to include a user specified argument that will be + provided as a parameter in the callback function when it is executed. +

        + +

        + + Figure 1: + + Object model of the cdevCallback class +
        + + + +
        + + +
        
        +class cdevCallback
        +methods:
        +callbackFunction (void)           : cdevCallbackFunction
        +userarg          (void)           : void *
        +operator ==      (cdevCallback &) : int
        +operator !=      (cdevCallback &) : int
        +fireCallback     (...)            : void
        +isTransactionDone(void)   {static}: int
        +			
        +
        +
        + +

        +
        + + + Public Methods of + the cdevCallback + Class +

        +
        + + + + + + + + + + + + + + + +
        + + + cdevCallback +

        +
        + + cdevCallback (void); +

        + cdevCallback (cdevCallbackFunction func, void * userarg); +

        + cdevCallback (cdevCallback & callback); +

        + + This is the constructor for the callback object. It sets the internal + pointers to the user specified callback function and userarg + pointer. +

        +
        + + + callbackFunction +

        +
        + + cdevCallbackFunction callbackFunction (void); +

        + + Obtains a pointer to the callback function that is stored within + the cdevCallback object. +

        +
        + + + userarg +

        +
        + + void * userarg (void); +

        + + Obtains a pointer to the user argument that is stored within the + cdevCallback object. +

        +
        + + + operator == +

        +
        + + int operator == (const cdevCallback& callback); +

        + + Used to compare two cdevCallback objects. Two objects are + considered equal if they point to the same callback function and + user argument. +

        +
        + + + operator != +

        +
        + + int operator != (const cdevCallback& callback); +

        + + Used to compare two cdevCallback objects. Two objects are + considered equal if they point to the same callback function and + user argument. +

        +
        + + + fireCallback +

        +
        + + void fireCallback ( int status, +

        + void * userarg, +

        + cdevRequestObject & req, +

        + cdevData & result, +

        + int partialTransaction = 0); +

        + + This method allows the caller to dispatch the callback function + with the specified parameters. If the callback represents a + response that is one of many that will occur, then the + partialTransaction flag should be set to non-zero. The value of + this flag can be retrieved by calling the static + cdevCallback::isTransactionDone method. +

        +
        + + + isTransactionDone +

        +
        + + int isTransactionDone ( void ); +

        + + This method returns an integer indicating if this callback + indicates the end of the transaction. In the event of multi-part + transactions such as "monitorOn", this method will return a + non-zero value indicating that more callbacks can be expected. + In the event of monotonic operations such as "get" or "set", or + when the last monitor callback is received, this method will + return zero. +

        +
        +
        + + 2. +

        +
        + + + The cdevCollection Class +

        +
        + + + Overview of the + cdevCollection + Class +

        +
        + + The cdevCollection class provides a mechanism for sending a message to a collection + of named devices. The class maintains a list of CDEV devices that are associated + through an entry in the CDEV DDL file. The developer also dynamically create a + cdevCollection device. +

        + + Figure 2: + + Object Model of the cdevCollection Class +
        + + + +
        + + +
        
        +cdevCollection
        +methods:
        +cdevCollection   (char *, cdevSystem &) 
        +~cdevCollection  (void)                         :{virtual}
        +getRequestObject (char *, cdevRequestObject *&) :{virtual} int
        + 
        +attachRef     (char *)               :{static}  cdevCollection &
        +attachPtr     (char *)               :{static}  cdevCollection *
        +attachRef     (char *, cdevSystem &) :{static}  cdevCollection *
        +attachPtr     (char *, cdevSystem &) :{static}  cdevCollection &
        +detach        (cdevCollection &)     :{static}  void
        +detach        (cdevCollection *)     :{static}  void
        +className     (void)                 :{virtual} char *
        +add           (char *)               :          int
        +add           (int, char *, ...)     :          int
        +add           (int, char **)         :          int
        +add           (char **)              :          int
        +addRegexp     (char *)               :          int
        +remove        (char *)               :          int
        +remove        (int, char *, ...)     :          int
        +remove        (int, char **)         :          int
        +remove        (char **)              :          int
        +removeRegexp  (char *)               :          int
        +			
        +
        +
        + +

        +
        + + + Public Methods of + the + cdevCollection + Class +

        +
        + + + +
        + + + cdevCollection +

        +
        + + cdevCollection (char * name, cdevSystem & system); +

        + + This is the constructor for the cdevCollection class. It has the + following properties. +

        +
        + + + This method is protected to prevent cdevCollections from + being instantiated directly. New cdevCollection instances + are created by using the attachPtr or attachRef method of + the cdevCollection class. +

        + + + The name that is provided to the cdevCollection is the + device name that CDEV will use to refer to it. The name + must be unique within the CDEV system of objects and + cannot be the same as the name of any regular cdevDevice + that exists in the CDEV DDL file. +

        + + + The cdevSystem reference that is provided is the + cdevSystem instance that will be used to poll, pend and + flush the cdevCollection object. +

        + + + If the name provided is the name of a cdevCollection that + has been specified in the CDEV DDL file, then the list of + devices will be populated from the names that are + specified. Otherwise, an empty cdevCollection instance will + be created. +

        + + + +
        + + + ~cdevCollection +

        +
        + + virtual ~cdevCollection (void); +

        + + This is the destructor for a cdevCollection object. It has the + following properties. +

        +
        + + + This method is protected to prevent the cdevCollection + object from being destroyed by the application. This + method should only be called by the cdevSystem object + when the application is terminating. +

        + + + Because the cdevCollection object will normally be referred + to as a cdevDevice object, this destructor is virtual to + ensure that the 'most senior' destructor is called first. +

        + + + This method will delete all device name strings that are + associated with the cdevCollection object. +

        + + + +
        + + + getRequestObject +

        +
        + + virtual int getRequestObject ( char *msg, +

        + cdevRequestObject* &req); +

        + + This method is called in order to obtain the cdevRequestObject + associated with the specified device/msg combination. This + method returns CDEV_SUCCESS if the cdevRequestObject + was successfully obtained. This method has the following + properties. +

        +
        + + + The cdevRequestObject pointer that is returned is actually + a pointer to a cdevCollectionRequest object. +

        + + + If a cdevCollectionRequest already exists for the specified + device/msg combination, it will be returned. Otherwise, the + method will call the attachPtr method of the + cdevCollectionRequest in order to obtain a new request + object. +

        + + + +
        + + + attachRef/attachPtr +

        +
        + + cdevCollection & attachRef (char * name); +

        + cdevCollection & attachRef (char * name, cdevSystem & sys); +

        + cdevCollection * attachPtr (char * name); +

        + cdevCollection * attachPtr (char * name, cdevSystem &sys); +

        + + These methods are used to obtain a pointer or reference to a + cdevCollection object. The name variable specifies the name of + the collection to be attached. These method have the following + properties. +

        +
        + + + All functionality for these methods is stored in the attachPtr + (char *, cdevSystem &) method. All other methods will call + this one. +

        + + + The method will first determine if the device has already + been created. If it has been created and its className + method returns "cdevCollection", then the existing + cdevCollection will be returned. If a non-collection + cdevDevice of the same name has already been + constructed, then NULL will be returned. +

        + + + If a device with the specified name has not already been + created, then the method will search the cdevDirectory for + the specified name. If the device name is in the + cdevDirectory AND is of class "collection", then a new + cdevCollection will be instantiated and returned. If a non- + collection cdevDevice of the same name exists in the + cdevDirectory, then NULL will be returned. +

        + + + If a device with the specified name has not been + instantiated and does not exist in the cdevDirectory, then a + new, empty cdevCollection will be created with the + specified name. +

        + + + If NULL is returned to one of the attachRef methods, then a + reference to a cdevErrorCollection object will be returned to + the caller. +

        + + + The refCount property of the cdevCollection will be + incremented each time a copy of the cdevCollection object + is obtained by the application. +

        + + + +
        + + + detach +

        +
        + + int detach (cdevCollection & col); +

        + int detach (cdevCollection * col); +

        + + This method is called to detach a pointer or reference to a + cdevCollection object. It has the following properties. +

        +
        + + + This method decrements the refCount property of the + cdevCollection object. +

        + + + When the refCount property is decremented to 0, then the + cdevCollection object will be deleted. +

        + + + + + +
        + + + className +

        +
        + + char * className (void); +

        + + This method returns the name of the class; "cdevCollection". If + the developer inherits a service specific cdevCollection, then + this method should not be altered or overridden. +

        +
        + + + add +

        +
        + + int add (char *name); +

        + + This method will add the individual name to the list of device + names that are in the cdevCollection. This method has the + following properties. +

        +
        + + + If a cdevCollectionRequest object has been instantiated for + this cdevCollection device, then the operation will fail and + CDEV_INVALIDOP will be returned. +

        + + + If the name provided is NULL or empty, then the operation + will fail and CDEV_INVALIDOP will be returned. +

        + + + If the name specified already exists in the collection of + names, then the operation will fail and CDEV_WARNING + will be returned. +

        + + + If the name specified is not already in the list, then the + method will append the device name to the end of the list + and return CDEV_SUCCESS. +

        + + + +
        + + + add +

        +
        + + int add (int num, char *firstname,...); +

        + + This method will attempt to add a list of num names to the + cdevCollection. This method has the following properties. +

        +
        + + + If a cdevCollectionRequest object has been instantiated for + this cdevCollection device, then the operation will fail and + CDEV_INVALIDOP will be returned. +

        + + + This method will call the add (char *name) method for each + name that is specified. +

        + + + If the add method fails to add any of the device name + strings to the list, then the error code that was generated by + the call to add (char * name) will be returned. +

        + + + If an error occurs while adding a name to the list, the + method will continue with the next name until the last name + is reached. +

        + + + If no errors occur while adding names to the list, then + CDEV_SUCCESS will be returned to the caller. +

        + + + + + + + + + +
        + + + add +

        +
        + + int add (int num, char **names); +

        + + This method will attempt to add num device names from the + names array to the list using the add (char *name) method of + the cdevCollection. This method has the same properties as + the add (int num, char * firstname,...) method. +

        +
        + + + add +

        +
        + + int add (char **names); +

        + + This method will attempt to add each device name from the + NULL terminated names array to the list using the add (char + *name) method of the cdevCollection. This method has the + same properties as the add (int num, char * firstname,...) + method. +

        +
        + + + addRegexp +

        +
        + + int addRegexp (char *regexp); +

        + + This method will query the system name server for the list of all + names in the cdevDirectory that match the specified regular + expression. the array of names will be added to the list using + the add (int num, char ** names) method and the result of this + operation will be returned. +

        +
        + + + remove +

        +
        + + int remove (char *name); +

        + + This method will remove the specified device name from list of + device names that is stored in the cdevCollection object. This + method has the following properties. +

        +
        + + + If a cdevCollectionRequest object has been instantiated for + this cdevCollection device, then the operation will fail and + CDEV_INVALIDOP will be returned. +

        + + + If the name provided is NULL or empty, then the operation + will fail and CDEV_WARNING will be returned. +

        + + + If the name specified does not exist in the collection of + names, then the operation will fail and CDEV_WARNING + will be returned. +

        + + + If the name specified exists in the list, then it will be + removed and CDEV_SUCCESS will be returned. +

        + + + +
        + + + remove +

        +
        + + int remove (int num, char *name,...); +

        + + This method will attempt to remove a list of num names from + the cdevCollection. This method has the following properties. +

        +
        + + + If a cdevCollectionRequest object has been instantiated for + this cdevCollection device, then the operation will fail and + CDEV_INVALIDOP will be returned. +

        + + + This method will call the remove (char *name) method for + each name that is specified. +

        + + + If the remove method fails to remove any of the device + name strings from the list, then the error code that was + generated by the call to remove (char * name) will be + returned. +

        + + + If an error occurs while removing a name from the list, the + method will continue with the next name until the last name + is reached. +

        + + + If no errors occur while removing names from the list, then + CDEV_SUCCESS will be returned to the caller. +

        + + + + + + + +
        + + + remove +

        +
        + + int remove (int num, char **names); +

        + + This method will attempt to remove num device names as + specified in the names array from the list using the remove + (char *name) method of the cdevCollection. This method has + the same properties as the remove (int num, char * name,...) + method. +

        +
        + + + remove +

        +
        + + int remove (char **names); +

        + + This method will attempt to remove each device name as + specified in the NULL terminated names array from the list + using the remove (char *name) method of the cdevCollection. + This method has the same properties as the remove (int num, + char * name,...) method. +

        + + +

        +
        + + + removeRegexp +

        +
        + + int removeRegexp (char *regexp); +

        + + This method will query the system name server for the list of all + names in the cdevDirectory that match the specified regular + expression. the array of names will be removed from the list + using the remove (int num, char ** names) method and the + result of this operation will be returned. +

        +
        + + +

        +
        + + 3. +

        +
        + + + The cdevCollectionRequest Class +

        +
        + + + Overview of the + cdevCollection + Request Class +

        +
        + + The cdevCollectionRequest class is an abstract base class from which other + cdevCollectionRequest objects are derived. It provides a protected constructor and + destructor that are used to initialize its internals, however, the primary mechanism that + is used to obtain a cdevCollectionRequest object is the attachPtr method. +

        + + Figure 3: + + Object Model of the cdevCollectionRequest Class +
        + + + +
        + + +
        
        +cdevCollectionRequest
        +attributes:
        +RESULT_CODE_TAG: int
        + 
        +methods:
        +cdevCollectionRequest   (char **, int, char *, cdevSystem &) 
        +~cdevCollectionRequest  (void)  :{virtual}
        + 
        +attachPtr               (...)   :{static} cdevCollectionRequest * 
        +className               (void)  :{virtual} char *
        +resultCodeTag           (void)  :{virtual} int
        +			
        +
        +
        + +

        +
        + + + Public Methods of + the + cdevCollection + Request Class +

        +
        + + + +
        + + + constructor +

        +
        + + cdevCollectionRequest( char **devices, int nDevices, +

        + char * msg, cdevSystem & system); +

        + + This is the constructor for the cdevCollectionRequest class. It + has the following properties. +

        +
        + + + This method is protected to prevent the direct instantiation + of new cdevCollectionRequests. New instances of the + cdevCollectionRequest objects are created by using the + attachPtr or attachRef method of the cdevRequestObject + class which will call the local attachPtr method to create a + new object if necessary. +

        + + + The constructor is called by the cdevCollection object and + is provided with a list and count of devices that will be + included in the collection and the message that will be sent + to them. +

        + + + The cdevSystem reference that is provided is the + cdevSystem instance that will be used to poll, pend and + flush the cdevCollectionRequest object. +

        + + + +
        + + + destructor +

        +
        + + virtual ~cdevCollectionRequest (void); +

        + + This is the destructor for a cdevCollectionRequest object. It has + the following properties. +

        +
        + + + This method is protected to prevent the + cdevCollectionRequest object from being destroyed by the + application. This method should only be called by the + cdevSystem object when the application is terminating. +

        + + + Because the cdevCollectionRequest object will normally be + referred to as a cdevRequestObject object, this destructor + is virtual to ensure that the 'most senior' destructor is + called first. +

        + + + +
        + + + attachPtr +

        +
        + + cdevCollectionRequest * attachPtr +

        + ( cdevCollection &col, char *msg, cdevSystem &sys); +

        + + This method is used by the cdevCollection object to obtain a + new cdevCollectionRequest object. +

        +
        + + + This method will obtain a copy of the device names from + the cdevCollection object and will poll the cdevDirectory + object to determine which service each of them is + associated with. +

        + + + If the devices are all from a single service, this method will + return a service specific collection request object. +

        + + + If the devices are from a variety of services, this method will + return a cdevGrpCollectionRequest that contains the + service specific collection request objects. +

        + + + Device/message combinations that are not associated with + a service will be ignored. +

        + + + If none of the device/message combinations can be + associated with a service, then an error message will be + generated and NULL will be returned. +

        + + + + + +
        + + + className +

        +
        + + char * className (void); +

        + + This method returns the name of the class; + "cdevCollectionRequest". If the developer inherits a service + specific cdevCollectionRequest, then this method should not be + altered or overridden. +

        +
        + + + resultCodeTag +

        +
        + + int resultCodetag (void); +

        + + This method returns the integer tag that should be used to + insert the result code that was geneterated when the message + was sent to the actual device. +

        +
        + + +

        + +

        + +

        + +

        +
        + + 4. +

        +
        + + + The cdevData Class +

        +
        + + + Overview of the + cdevData Class +

        +
        + + The cdevData C++ class is a self describing data object. This class is the primary + mechanism for data interchange within the cdev system. The cdevData object is + capable of storing and retrieving data items of all the primitive data types, as well as + character strings and time stamps. These data items may be scalar or multi- + dimensional arrays. +

        + + Figure 4: + + Object model of the cdevData class +
        + + + +
        + + +
        
        +class cdevData
        +methods:
        +tagC2I                   (char *, int *)         :int
        +tagI2C                   (int, char * &)         :int
        +insertTag                (int, char *)           :void
        +addTagCallback           (cdevTagTableCallback*) :void
        +delTagCallback           (cdevTagTableCallback*) :void
        +readTagTable             (int *&,char **&,int &) :int
        +operator ==              (cdevData & data)       :int
        +operator !=              (cdevData & data)       :int
        +operator =               (cdevData &)            :cdevData &
        +operator char            (void)                  :char
        +operator short           (void)                  :short
        +operator unsigned short  (void)                  :unsigned short
        +operator int             (void)                  :int
        +operator unsigned int    (void)                  :unsigned int
        +operator long            (void)                  :long
        +operator unsigned long   (void)                  :unsigned long
        +operator float           (void)                  :float
        +operator double          (void)                  :double
        +asciiDump                (FILE *)                :void
        +xdrSize                  (size_t *, size_t *)    :int
        +xdrExport                (char **, size_t *)     :int
        +xdrExport                (char *, size_t, size_t):int 
        +xdrImport                (char *, size_t)        :int
        +remove                   (...)                   :void 
        +changeTag                (...)                   :int
        +getType                  (...)                   :cdevDataTypes
        +getDim                   (...)                   :int
        +getElems                 (...)                   :int   
        +getBounds                (...)                   :int
        +setBounds                (...)                   :int
        +insert                   (...)                   :int
        +get                      (...)                   :int
        +find                     (...)                   :int
        +			
        +
        +
        + +

        +
        + + + Public Methods of + the cdevData + Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + tagC2I +

        +
        + + static int tagC2I (char *ctag, int *tag); +

        + + Converts a character string tag name to its unique integer + identifier. The function returns CDEV_SUCCESS if the + conversion was successful, otherwise it returns + CDEV_ERROR. +

        +
        + + + tagI2C +

        +
        + + static int tagI2C (int tag, char * &ctag); +

        + + Converts a unique integer tag number to its related character + string tag. The function returns CDEV_SUCCESS if the + conversion was successful, otherwise it returns + CDEV_ERROR. +

        +
        + + + insertTag +

        +
        + + static void insertTag(int tag, char *ctag); +

        + + Adds a new, unique tag identifier to the static table of tags. Both + the tag integer and the character string must be unique. + Returns CDEV_SUCCESS on success, or CDEV_ERROR on + failure. +

        +
        + + + addTagCallback +

        +
        + + static void addTagCallback(cdevTagTableCallback * cb); +

        + + This method is used to install a cdevTagTableCallback object in + the global tag table that will be called each time a new tag is + inserted into the global tag table. This method may be used by + service developers to detect when new tags are created and + update the corresponding tag mapping tables on remote + servers. +

        + The cdevTagTableCallback class contains a user defined + callback method that takes as its parameters the new tag's + integer identifier and its string equivalent. +

        +
        + + + delTagCallback +

        +
        + + static void delTagCallback(cdevTagTableCallback * cb); +

        + + This method removes the specified callback object from the + global tag table. The callback should have been previously + installed using the addTagCallback method. +

        +
        + + + readTagTable +

        +
        + + static int readTagTable(int *&tag, char **&ctag, int &ntag); +

        + + This method will read the complete contents of the global tag + table and use the data to populate the caller provided variables. + The ntags parameter will be set to the number of tags that were + found in the global tag table. +

        + The tag array and the ctag array will both be allocated to a size + sufficient to hold the resultant data. The tag parameter will + contain the list of integer tags and the ctag array will contain the + list of corresponding character strings. +

        + The caller will be responsible for deleting the arrays that are + returned by this method. Because the ctag array contains + pointers to the actual strings from the global tag table, the caller + should delete the array only (not the individual elements). +

        +
        + + + Operator = +

        +
        + + cdevData & operator = (cdevData & data); +

        + + This is the assignment operator for the class. It will copy the + exact contents of the cdevData object specified by data to the + current cdevData object. +

        +
        + + + Cast operators +

        +
        + + operator char (void); +

        + operator short (void); +

        + operator unsigned short (void); +

        + operator int (void); +

        + operator unsigned int (void); +

        + operator long (void); +

        + operator unsigned long (void); +

        + operator float (void); +

        + operator double (void); +

        + operator char* (void); +

        + + Directly extracts a scalar value that is stored in the "value" data + item, and returns it as the value of the current cdevData object. +

        +
        + + + Operator == +

        +
        + + int operator == (cdevData & data); +

        + + This operator will do a deep comparison of two cdevData + objects, including a comparison of the individual elements of + array data. The order in which the tagged data items were + inserted into either object is unimportant. +

        +
        + + + Operator != +

        +
        + + int operator != (cdevData & data); +

        + + This operator will do a deep comparison of two cdevData + objects, including a comparison of the individual elements of + array data. The order in which the tagged data items were + inserted into either object is unimportant. +

        +
        + + + asciiDump +

        +
        + + void asciiDump (FILE * fp); +

        + + Outputs the complete contents of the cdevData object to a file. + If no file pointer is specified, then stdout will be used. +

        +
        + + + xdrSize +

        +
        + + int xdrSize (size_t * bufLen, size_t * elementCount); +

        + + Calculates the size of the buffer (bufLen) that will be required to + store this cdevData object as represented by XDR. The total + number of data items (elementCount) that will be placed in the + buffer is also calculated. The values obtained from this function + may be passed to the xdrExport method in order to use a pre- + allocated data buffer. +

        +
        + + + xdrExport +

        +
        + + int xdrExport (char ** buf, size_t * bufLen); +

        + + Allocates a buffer (buf) of sufficient size to hold the XDR + representation of this cdevData object. It will then translate all + data items stored within the object to XDR and write this data to + the buffer. The size of the allocated buffer will be provided to + the caller in the bufLen variable. +

        +
        + + + xdrExport +

        +
        + + int xdrExport (char * buf, size_t bufLen, size_t count); +

        + + Populates the preallocated buffer (buf) with the XDR + representation of the contents of this cdevData object. The + buffer length (bufLen) and number of elements (count) must + have been calculated in advance using the xdrSize method. +

        +
        + + + xdrImport +

        +
        + + int xdrImport (char * buf, size_t bufLen); +

        + + Decodes the caller supplied buffer (buf) from XDR + representation and populates the cdevData object with the + contents. The caller must specify the number of bytes in the + XDR buffer (bufLen). +

        +
        + + + remove +

        +
        + + void remove(void); +

        + void remove(int tag); +

        + void remove(char * ctag); +

        + + Removes the data item specified by the unique tag name or + integer from this cdevData object. If the tag is not specified, + then all data items will be removed from the object. +

        +
        + + + changeTag +

        +
        + + int changeTag(int oldTag, int newTag); +

        + int changeTag(int oldTag, char *c_newTag); +

        + int changeTag(char *c_oldTag, int newTag); +

        + int changeTag(char *c_oldTag, char *c_newTag); +

        + + Retags a data item that is currently stored in the cdevData + object from "oldTag" to "newTag". By using this method the data + can be renamed internally without having to perform a copy or + removal. This function is overloaded to support any + permutation of character string tag or integer tag identifier. +

        +
        + + + getType +

        +
        + + cdevDataTypes getType(int tag); +

        + cdevDataTypes getType(char *ctag); +

        + + Retrieves the enumerated data type of the specified tagged + data item within this cdevData object. The following + enumerated types are defined in the file cdevTypes.h. +

        + + + + + + + + + + + + + + + + + + + + + +
        + + CDEV_BYTE +

        +
        + + 8 bit unsigned character +

        +
        + + CDEV_INT16 +

        +
        + + 16 bit signed integer +

        +
        + + CDEV_UINT16 +

        +
        + + 16 bit unsigned integer +

        +
        + + CDEV_INT32 +

        +
        + + 32 bit signed integer +

        +
        + + CDEV_UINT32 +

        +
        + + 32 bit unsigned integer +

        +
        + + CDEV_FLOAT +

        +
        + + single precision floating point +

        +
        + + CDEV_DOUBLE +

        +
        + + double precision floating point. +

        +
        + + CDEV_STRING +

        +
        + + NULL terminated character + string +

        +
        + + CDEV_TIMESTAMP +

        +
        + + cdev time stamp +

        +
        + + CDEV_INVALID +

        +
        + + invalid or unknown data type +

        +
        +
        + + + getDim +

        +
        + + int getDim(int tag, size_t *dim); +

        + int getDim(char *ctag, size_t *dim); +

        + + Retrieves the number of dimensions in a data item that is an + array. If dim is 0, then the data item is scalar, otherwise, the + data item is a "dim" dimensional array. This function is + overloaded to support either the integer tag or character string + tag. +

        +
        + + + getElems +

        +
        + + int getElems(int tag, size_t *elems); +

        + int getElems(char *ctag, size_t *elems); +

        + + Retrieves the number of data elements in all dimensions of a + multi-dimensional array. If elems is 1, then the data item is + scalar, otherwise, the data item is an array of "elems" elements. + This function is overloaded to support either the integer tag or + character string tag. +

        +
        + + + getBounds +

        +
        + + int getBounds( int tag, +

        + cdevBounds * bounds, +

        + size_t numBounds); +

        + int getBounds( char * ctag, +

        + cdevBounds * bounds, +

        + size_t numBounds); +

        + + Obtains the bounding dimensions of the array specified by the + caller provided tag. The cdevBounds structure contains two + integers: offset and length. The length variable represents the + number of data elements in that dimension of the array. The + offset integer is provided for use in specifying the position of + arrays that are sub-sets of the actual data. A version of this + function is available that uses an array of integers rather than + the cdevBounds structure. This function is overloaded to + support either the integer tag or character string tag. +

        +
        + + + setBounds +

        +
        + + int setBounds( int tag, +

        + cdevBounds * bounds, +

        + size_t numBounds); +

        + int setBounds( char * ctag, +

        + cdevBounds * bounds, +

        + size_t numBounds); +

        + + Specifies the bounding dimensions of a multi-dimensional array + of data. In order to use this function, the number of dimensions + in the array must be specified as a parameter to the insert + command when placing the data into the cdevData object. The + cdevBounds structure contains two integers: offset and length. + The length variable represents the number of data elements in + that dimension of the array. The offset integer is provided for + use in specifying the position of arrays that are sub-sets of the + actual data. A version of this function is available that uses an + array of integers rather than the cdevBounds structure. This + function is overloaded to support either the integer tag or + character string tag. +

        +
        + + + insert (scalar) +

        +
        + + int insert (int tag, BYTE data); +

        + int insert (int tag, short data); +

        + int insert (int tag, unsigned short data); +

        + int insert (int tag, int data); +

        + int insert (int tag, unsigned int data); +

        + int insert (int tag, long data); +

        + int insert (int tag, unsigned long data); +

        + int insert (int tag, float data); +

        + int insert (int tag, double data); +

        + int insert (int tag, cdev_TS_STAMP data); +

        + + These methods allow the user to insert a single data item into + the cdevData object using the specified tag. If another data + item already occupies that tag within the cdevData object, the + new data item will override the old one. Although only the + integer tag prototypes are shown, these functions are + overloaded to support both the integer and character string + data tags. +

        +
        + + + insert (array) +

        +
        + + int insert (int tag, BYTE * data, size_t len, size_t ndim); +

        + int insert (int tag, short * data, size_t len, size_t ndim); +

        + int insert (int tag, unsigned short * data, size_t len, size_t ndim); +

        + int insert (int tag, int * data, size_t len, size_t ndim); +

        + int insert (int tag, unsigned int * data, size_t len, size_t ndim); +

        + int insert (int tag, long * data, size_t len, size_t ndim); +

        + int insert (int tag, unsigned long * data, size_t len, size_t ndim); +

        + int insert (int tag, float * data, size_t len, size_t ndim); +

        + int insert (int tag, double * data, size_t len, size_t ndim); +

        + + These methods allow the user to insert array data items into the + cdevData object using the specified tag. The len parameter is + used to specify the total number of items in the array. The ndim + parameter is used to specify the number of dimensions in the + array (1 by default). Although only the integer tag prototypes + are shown, these functions are overloaded to support both the + integer and character string data tags. +

        +
        + + + insert (character string) +

        +
        + + +

        + int insert (int tag, char * data); +

        + int insert (int tag, char ** data, size_t len, size_t ndim); +

        + + These methods are used to add NULL terminated character + strings to the cdevData object. These methods differ from the + others because a single character string is treated as a scalar + value. The len parameter (where used) specifies the total + number of character strings in the array. The ndim parameter is + used to specify the number of dimensions in the array (1 by + default). Although only the integer tag prototypes are shown, + these functions are overloaded to support both the integer and + character string data tags. +

        +
        + + + get +

        +
        + + int get(int tag, BYTE * data); +

        + int get(int tag, short * data); +

        + int get(int tag, unsigned short * data); +

        + int get(int tag, int * data); +

        + int get(int tag, unsigned int * data); +

        + int get(int tag, long * data); +

        + int get(int tag, unsigned long * data); +

        + int get(int tag, float * data); +

        + int get(int tag, double * data); +

        + int get(int tag, cdev_TS_STAMP * data); +

        + + These methods are used to retrieve scalar values and arrays + that are stored in the cdevData object. When retrieving an + array, it is the caller's responsibility to call the getElems method + to obtain the number of elements and then pre-allocate the + buffer to receive the data. If the receiving data type does not + match the data type stored in the cdevData object, then the + data will be converted to the new type when it is extracted. + Although only the integer tag prototypes are shown, these + functions are overloaded to support both the integer and + character string data tags. +

        +
        + + + get (character string) +

        +
        + + +

        + int get(int tag, char * data, size_t len); +

        + int get(int tag, char ** data); +

        + + These methods are used to retrieve character strings and + arrays of character strings from a cdevData object. When + obtaining a single character string, the length of the allocated + buffer must be specified in the len parameter. When obtaining + an array of character strings, the caller must pre-allocate the + POINTERS for each element in the array. The cdevData object + will allocate sufficient memory to each of the pointers to hold + the individual character strings. It then becomes the + responsibility of the caller to free the memory assigned to those + pointers. If the receiving data type does not match the data + type stored in the cdevData object, then the data will be + converted to the new type when it is extracted. Although only + the integer tag prototypes are shown, these functions are + overloaded to support both the integer and character string + data tags. +

        +
        + + + find +

        +
        + + int find(int tag, void* &data); +

        + int find(char * ctag, void* &data); +

        + + Retrieves a pointer to the data within the cdevData object. The + caller is responsible for ensuring that the receiving pointer is of + the correct data type for the data within the object. This function + is overloaded to support both integer and character string tag + identifiers. +

        +
        +
        + + 5. +

        +
        + + + The cdevDevice Class +

        +
        + + + Overview of the + cdevDevice Class +

        +
        + + The cdevDevice C++ class is the user's primary interface to cdev. In fact, it is possible + to develop complete cdev applications using only cdevDevice and cdevData objects. + The cdevDevice class defines the basic interface that all applications must use to + transmit messages to a cdev service. +

        + +

        + + Figure 5: + + Object model of the cdevDevice class +
        + + + +
        + + +
        
        +class cdevDevice
        +methods:
        +attachRef         (char *)             :cdevDevice&
        +attachPtr         (char *)             :cdevDevice*
        +detach            (cdevDevice&)        :void
        +detach            (cdevDevice*)        :void
        +getRequestObject  (char *msg)          :cdevRequestObject*
        +name              (void)               :char *
        +system            (void)               :cdevSystem&
        +setContext        (cdevData&)          :int
        +send              (char*, cdevData&, cdevData&)     :   int
        +send              (char*, cdevData*, cdevData&)     :   int
        +send              (char*, cdevData&, cdevData*)     :   int
        +send              (char*, cdevData*, cdevData*)     :   int
        +sendNoBlock       (char*, cdevData&, cdevData&)     :   int
        +sendNoBlock       (char*, cdevData*, cdevData&)     :   int
        +sendNoBlock       (char*, cdevData&, cdevData*)     :   int
        +sendNoBlock       (char*, cdevData*, cdevData*)     :   int
        +sendCallback      (char*, cdevData&, cdevCallback&) :   int
        +sendCallback      (char*, cdevData*, cdevCallback&) :   int
        +			
        +
        +
        + +

        + + + +
        + + + +

        +
        +
        + + + Public Methods of + the cdevDevice + Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + attachRef +

        +
        + + static cdevDevice& attachRef (char *name); +

        + + Obtains a reference to a cdevDevice object by name. By + default, the new object will be managed by the default + cdevSystem. +

        +
        + + + attachPtr +

        +
        + + static cdevDevice* attachPtr (char *name); +

        + + Obtains a pointer to a cdevDevice object specified by name. By + default, the new object will be managed by the default + cdevSystem. +

        +
        + + + detach +

        +
        + + static void detach (cdevDevice& dev); +

        + + Removes a referenced cdevDevice object from its associated + cdevSystem object. Ordinary applications should never use this + command. +

        +
        + + + detach +

        +
        + + static void detach (cdevDevice* dev); +

        + + Detaches the cdevDevice object specified by dev from its + associated cdevSystem object. Ordinary applications should + never use this command. +

        +
        + + + getRequestObject +

        +
        + + cdevRequestObject* getRequestObject (char *msg); +

        + + Obtains a service specific request object. This function uses + the name of the device specified within the cdevDevice object, + and the message provided by the caller to determine which + cdev service will be used to service this request. The service is + then loaded (if necessary), and is contacted to provided a + request object for the device/message combination. This + cdevRequestObject will then be used to communicate with the + service directly. +

        +
        + + + name +

        +
        + + const char *name (void) const; +

        + + Returns the name of the device. +

        +
        + + + system +

        +
        + + cdevSystem& system (void) const; +

        + + Obtains a reference to the underlying cdevSystem object that + manages this device. +

        +
        + + + setContext +

        +
        + + int setContext (cdevData& cxt); +

        + + Used to insert a cdevData object containing tagged values that + control optional behavior of the underlying device. The context + is often used to specify which properties (value, status, + severity) a device returns in response to a "get" message. It is + important to note that any change made to the context of a + cdevDevice will automatically be propagated to all + cdevRequestObjects created from that device. Therefore, any + message specific context settings should be specified directly + to the cdevRequestObject, rather than to the cdevDevice. +

        +
        + + + getContext +

        +
        + + cdevData & getContext (void); +

        + + Retrieves a reference to the cdevData object that contains the + context for a specific device. +

        +
        + + + setPrivate +

        +
        + + void setPrivate (void * data); +

        + + Associates a user specified data object with this cdevDevice + object. The pointer can be retrieved later using the getPrivate + method. +

        +
        + + + getPrivate +

        +
        + + void * getPrivate (void); +

        + + Retrieves a pointer to a data object that was placed in this + cdevDevice object using the setPrivate function. +

        +
        + + + send +

        +
        + + int send (char *msg, cdevData &out, cdevData& result); +

        + int send (char *msg, cdevData *out, cdevData& result); +

        + int send (char *msg, cdevData &out, cdevData* result); +

        + int send (char *msg, cdevData *out, cdevData* result); +

        + + The send function is the standard method for synchronously + communicating with a device. The caller provides the message + as a character string in the msg parameter. The out cdevData + object contains any property values that the device will need to + perform the task. The result cdevData object will contain the + output properties that resulted from the call. This function will + return one of the error code defined in cdevErrCode.h. +

        + +

        +
        + + Figure 6: + + Return codes generated by the send method. +
        + + + +
        + + +
        
        +CDEV_WARNING:        Failure of the request in non-critical.
        +CDEV_SUCCESS:        The message was processed successfully.
        +CDEV_ERROR:          Failed to process message.
        +CDEV_INVALIDOBJ:     Invalid cdev request object used.
        +CDEV_INVALIDARG:     Invalid argument passed to cdev call.
        +CDEV_INVALIDSVC:     Wrong service during dynamic loading.
        +CDEV_INVALIDOP:      Operation is not supported on device.
        +CDEV_NOTCONNECTED:   Not connected to low level network 
        +                     service.
        +CDEV_IOFAILED:       Low level network service IO failed.
        +CDEV_CONFLICT:       Conflicts of data types or tags.
        +CDEV_NOTFOUND:       Cannot find specified data in cdevData.
        +CDEV_TIMEOUT:        Time out.
        +CDEV_CONVERT:        cdevData conversion error.
        +CDEV_OUTOFRANGE:     Value out of range for device attribute.
        +CDEV_NOACCESS:       Insufficient access to perform request.
        +CDEV_ACCESSCHANGED:  Change in access permission of device.
        +CDEV_DISCONNECTED:   The service has lost contact with the 
        +                     device.
        +CDEV_RECONNECTED:    The service has regained contact with 
        +                     the device.
        +			
        +
        +
        + +

        + + + + + +
        + + + sendNoBlock +

        +
        + + int sendNoBlock(char *msg, cdevData &out, cdevData &result); +

        + int sendNoBlock(char *msg, cdevData *out, cdevData &result); +

        + int sendNoBlock(char *msg, cdevData &out, cdevData *result); +

        + int sendNoBlock(char *msg, cdevData *out, cdevData *result); +

        + + The sendNoBlock method uses the same parameters and + syntax as the send method. However, rather than waiting for + the underlying service to respond to the request, this function + will return immediately. The caller must utilize a cdevGroup + object to detect when this transaction has been completed. +

        +
        + + + sendCallback +

        +
        + + int sendCallback ( char *msg, cdevData &out, +

        + cdevCallback &callback); +

        + int sendCallback ( char *msg, cdevData *out, +

        + cdevCallback &callback); +

        + + The sendCallback function is the standard method for + asynchronously communicating with a device. Rather than + providing a result cdevData object, this method requires the + user to provide the address of a cdevCallback object. This + object contains a user supplied pointer and the address of a + function to call when the message has been successfully + processed. +

        +
        +
        + + 6. +

        +
        + + + The cdevError Class +

        +
        + + + Overview of the + cdevError Class +

        +
        + + The cdevError C++ class is an abstract base class that provides error handling + services that are used by both the cdevService object and the cdevSystem object. It's + constructors are protected to prevent it from being instantiated directly. +

        + +

        + + Figure 7: + + Object model of the cdevError class +
        + + + +
        + + +
        
        +class cdevError
        +methods:
        +autoErrorOn      ( void )            {virtual} : int
        +autoErrorOff     ( void )            {virtual} : int
        +reportError      ( ... )             {virtual} : int
        +setErrorHandler  (cdevErrorHandler ) {virtual} : void
        +setThreshold     ( int )             {virtual} : void
        +className        ( void )            {virtual} : char * 
        +			
        +
        +
        + +

        + + + +
        + + + +

        +
        +
        + + + Public Methods of + the cdevError + Class +

        +
        + + + + + + + + + + + +
        + + + autoErrorOn +

        +
        + + int autoErrorOn (void); +

        + + Informs the cdevError class that it should use its internal default + error handler to process any error messages that are + generated by objects within its control. This is the default + operating condition for the class. +

        +
        + + + autoErrorOff +

        +
        + + int autoErrorOff (void); +

        + + Informs the cdevError class that it should use the user supplied + error handling function to process any error messages that are + generated by objects within its control. +

        +
        + + + reportError +

        +
        + + int reportError ( int severity, char *name, +

        + cdevRequestObject *obj, +

        + char *formatString,...); +

        + + Emits an error message. The severity field indicates the + severity of the error, the name string identifies the object that + generated the error, the obj parameter is the + cdevRequestObject that was in use when the error occurred, + and the formatString and additional parameters (...) should be + formatted in the same manner as the parameters used by + printf. +

        + The integer used by severity should have one of the following + values indicating the severity of the error that has occurred. +

        + + + +
        + + CDEV_SEVERITY_INFO +

        +
        + +
        + + + +
        + + +

        +
        + + No error. +

        + + + + + + + +
        + + CDEV_SEVERITY_WARN +

        +
        + + An error occurred that should + not impact continued + processing. +

        +
        + + CDEV_SEVERITY_ERROR +

        +
        + + An error occurred and should + be corrected before continuing. +

        +
        + + CDEV_SEVERITY_SEVERE +

        +
        + + A severe or fatal error has + occurred and cdev cannot + continue normal execution. +

        +
        +
        +
        + + + setErrorHandler +

        +
        + + void setErrorHandler (cdevErrorHandler handler); +

        + + Used to to install a user specified error handler. This error + handler will be called when an error occurs if the autoErrorOff + method has been used to disable the default error handler. The + user provided error handler should have the following + prototype: +

        + void handler (int severity, char *text, cdevRequestObject *obj); +

        + The severity parameter will contain one of the integers + specified in the reportError documentation, the text parameter + will contain the text of the error, and the obj parameter will + contain the cdevRequestObject that was in use when the error + occurred. +

        +
        + + + setThreshold +

        +
        + + void setThreshold (int errorThreshold); +

        + + Used to specify the level of severity at which errors should be + submitted to the error handler. The value of errorThreshold + should be one of the severity levels specified in the reportError + method. +

        +
        +
        + + 7. +

        +
        + + + The cdevGroup Class +

        +
        + + + Overview of the + cdevGroup Class +

        +
        + + The cdevGroup C++ class provides the mechanisms that cdev uses to collect together + a list of operations to be executed, perhaps repeatedly, as a group, and to detect the + completion of multiple requests that form a group. +

        + +

        + + Figure 8: + + Object model of the cdevGroup class +
        + + + +
        + + +
        
        +class cdevSync
        +			
        +
        +
        + +

        + + + +
        + + + +

        +
        +
        + + + Public Methods of + the cdevGroup + Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + cdevGroup +

        +
        + + cdevGroup (unsigned blockSize, cdevSystem& system); +

        + + This is the constructor for the cdevGroup object. It receives a + blockSize parameter which specifies the maximum number of + cdevTranObj objects that may be added and a cdevSystem + parameter that the group object will be associated with. If no + parameters are specified blockSize will be set to + DEFAULT_BLOCK_SIZE and the system will be set to + cdevSystem::defaultSystem(). The mode of the constructed + group will be CDEV_EXEC_IMMEDIATE. +

        +
        + + + start +

        +
        + + int start (void); +

        + + Starts a group of transactions. This means that each time a + message is sent asynchronously to a device, the associated + cdevTranObj will be included in this group. The system will stop + adding transactions to this group after the end method has + been executed. +

        + If the mode of the group is CDEV_EXEC_IMMEDIATE, the + operations are immediately forwarded to the service and to the + appropriate server. If the mode of the group is + CDEV_EXEC_DEFERRED, the operation is kept in a list within + the group, and sent to the service/server when flush() or pend() + is called. +

        +
        + + + end +

        +
        + + int end (void); +

        + + Informs the system that no more new transactions should be + included in this group object. +

        +
        + + + flush +

        +
        + + int flush (void); +

        + + Flushes any pending outbound requests to their respective + services. +

        + If the group is in deferred execution mode, and the grouped + commands have either not yet been flushed, or have previously + been flushed and have all completed, then flush will send the + commands to the underlying services. After completion, flush + may be called again to re-execute the grouped commands. +

        +
        + + + poll +

        +
        + + int poll (void); +

        + + Directly polls each of the cdevGroup's underlying services for + activity, and delivers any asynchronous callbacks that are + ready. +

        +
        + + + pend +

        +
        + + int pend (int fd); +

        + + Automatically end and flush the group if it is started, and wait + until all operations within the group are completed or until a + timeout occurs. +

        + In particular: waits for a default period of time for the specified + file descriptor to have an I/O event. If the fd parameter is not + provided, the cdevGroup object will wait for an I/O event on any + of its contained file descriptors. When an event occurs on one + of the file descriptors, the cdevGroup object will call the + respective cdevService to process the event and dispatch any + asynchronous callbacks that are ready. +

        +
        + + + pend +

        +
        + + int pend (double seconds, int fd); +

        + + Automatically end and flush the group if it is started, and wait + until all operations within the group are completed or until a + timeout occurs. +

        + In particular, processes all I/O events that occur on the file + descriptor during the specified period of time. If the fd + parameter is not provided, the cdevGroup object will wait for I/O + events on all of its contained file descriptors. When an event + occurs on one of the file descriptors, the cdevGroup object will + call the respective cdevService to process the event and + dispatch any asynchronous callbacks that are ready. +

        +
        + + + allFinished +

        +
        + + int allFinished (void); +

        + + Checks the status of the cdevGroup object to determine if all + transactions have been completed. Returns 1 if all transactions + are complete or 0 if they are not. +

        +
        + + + status +

        +
        + + int status (int status[], int &numTransactions); +

        + + Retrieves the status of the individual transaction objects that + are stored within the cdevGroup object. The cdevGroup class + will populate the status array with up to numTransactions. The + numTransactions parameter will then be set to the number of + transactions that were actually loaded. If a status entry is 0, + then the associated transaction has been completed. Returns + CDEV_SUCCESS on successful completion, or + CDEV_INVALIDARG if the status array is too small. +

        +
        + + + execDeferred +

        +
        + + int execDeferred (void); +

        +
        + + + execImmediate +

        +
        + + int execImmediate (void); +

        + + Changes the behaviour of execution of commands inside the + group. execDeferred will buffer all commands until pend or poll + flush is called; execImmediate will flush commands to + underlying services immediately. +

        +
        + + + executionMode +

        +
        + + int executionMode (void) const; +

        + + Return execution mode: CDEV_EXEC_DEFERRED or + CDEV_EXEC_IMMEDIATE. +

        +
        + + + readyToExec +

        +
        + + int readyToExec (void) const; +

        + + For deferred mode group only. Return execution stage: +

        + 0 = still in the buffered stage. +

        + 1 = ready to flush all buffered commands. +

        + +

        +
        +
        + + 8. +

        +
        + + + The cdevIOContext Class +

        +
        + + + Overview of the + cdevIOContext + Class +

        +
        + + The cdevIOContext C++ class is an abstract base class that is inherited by both the + cdevRequestObject class and the cdevDevice class. This class defines the + mechanisms that are used to store and retrieve context information. +

        + +

        + + Figure 9: + + Object model of the cdevIOContext class +
        + + + +
        + + +
        
        +class cdevIOContext
        +methods:
        +getContext ( void )           {virtual} : cdevData &
        +setContext ( cdevData &cxt )   {virtual} : int
        +getPrivate ( void )                     : void *
        +setPrivate ( void * data )              : void
        +className  ( void )           {virtual} : char * 
        +			
        +
        +
        + +

        + + + +
        + + + +

        +
        +
        + + + Public Methods of + the + cdevIOContext + Class +

        +
        + + + + + + + + + +
        + + + getContext +

        +
        + + cdevData & getContext (void); +

        + + Obtains a reference to the cdevData object that contains the + context for a specific device. +

        +
        + + + setContext +

        +
        + + int setContext (cdevData& cxt); +

        + + Used to insert a cdevData object containing tagged values that + control optional behavior of the underlying device. The context + is often used to specify which properties (value, status, + severity) a device returns in response to a "get" message. . +

        +
        + + + getPrivate +

        +
        + + void * getPrivate (void); +

        + + Retrieves a pointer to a data object that was placed in this + object using the setPrivate function. +

        +
        + + + setPrivate +

        +
        + + void setPrivate (void * data); +

        + + Associates a user specified data object with this object. The + pointer can be retrieved later using the getPrivate method. +

        +
        +
        + + 9. +

        +
        + + + The cdevRequestObject Class +

        +
        + + + Overview of the + cdevRequestObject + Class +

        +
        + + The cdevRequestObject C++ class provides the user with a higher performance + interface to devices in cdev. Each time a cdevDevice object receives a message + string, it must parse the message and then connect to the appropriate service. The + cdevRequestObject allows the user to bind a device name to a message and then + connect to the underlying service only once. Thereafter, the cdevRequestObject will + remain connected to the service and can process its associated message with much + higher efficiency. +

        + +

        + + Figure 10: + + Object model of the cdevRequestObject class +
        + + + +
        + + +
        
        +class cdevRequestObject
        +methods:
        +attachRef    (char *, char *)            : cdevRequestObject&
        +attachRef    (cdevDevice &, char *)      : cdevRequestObject&
        +attachPtr    (char *, char *)            : cdevRequestObject*
        +attachPtr    (cdevDevice &, char *)      : cdevRequestObject*
        +detach       (cdevRequestObject&)        : void
        +detach       (cdevRequestObject*)        : void
        +message      (void)                      : char *
        +device       (void)                      : cdevDevice&
        +system       (void)                      : cdevSystem&
        +service      (void)                      : cdevService&
        +setContext   (cdevData &)                : int
        +getState     (void)                      : int
        +getAccess    (void)                      : int
        +send         (cdevData&, cdevData&)      : int
        +send         (cdevData*, cdevData&)      : int
        +send         (cdevData&, cdevData*)      : int
        +send         (cdevData*, cdevData*)      : int
        +sendNoBlock  (cdevData&, cdevData&)      : int
        +sendNoBlock  (cdevData*, cdevData&)      : int
        +sendNoBlock  (cdevData&, cdevData*)      : int
        +sendNoBlock  (cdevData*, cdevData*)      : int
        +sendCallback (cdevData&, cdevCallback&)  : int
        +sendCallback (cdevData*, cdevCallback&)  : int
        +className    (void)                      : char *
        +			
        +
        +
        + +

        +
        + + + Public Methods of + the + cdevRequestObject + Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + attachRef +

        +
        + + static cdevRequestObject& attachRef (char *device, char * msg); +

        + + Obtains a reference to a cdevRequestObject object by + specifying the name of the device and the message string. By + default, the new object will be managed by the default + cdevSystem. +

        +
        + + + attachRef +

        +
        + + static cdevRequestObject& attachRef (cdevDevice &dev, char * msg); +

        + + Obtains a reference to a cdevRequestObject object by + providing a reference to the associated cdevDevice object and + the message string. By default, the new object will be managed + by the default cdevSystem. +

        +
        + + + attachPtr +

        +
        + + static cdevRequestObject* attachPtr (char *device, char * msg); +

        + + Obtains a pointer to a cdevRequestObject by specifying the + name of the device and the message string. By default, the new + object will be managed by the default cdevSystem. +

        +
        + + + attachPtr +

        +
        + + static cdevRequestObject* attachPtr (cdevDevice &dev, char * msg); +

        + + Obtains a pointer to a cdevRequestObject by providing a + reference to the associated cdevDevice object and the + message string. By default, the new object will be managed by + the default cdevSystem. +

        +
        + + + detach +

        +
        + + static void detach (cdevRequestObject& dev); +

        + + Removes a referenced cdevRequestObject object from its + associated cdevSystem object. Ordinary applications should + never use this command. +

        +
        + + + detach +

        +
        + + static void detach (cdevRequestObject* dev); +

        + + Detaches the cdevRequestObject object specified by dev from + its associated cdevSystem object. Ordinary applications should + never use this command. +

        +
        + + + message +

        +
        + + char *message (void) const; +

        + + Retrieves the message string that is associated with this + cdevRequestObject. +

        +
        + + + device +

        +
        + + cdevDevice &device (void) const; +

        + + Retrieves a reference to the cdevDevice object that is + associated with this cdevRequestObject. +

        +
        + + + system +

        +
        + + cdevSystem& system (void) const; +

        + + Retrieves a reference to the underlying cdevSystem object that + manages this cdevRequestObject. +

        +
        + + + service +

        +
        + + cdevService& service (void) const; +

        + + Retrieves a reference to the underlying cdevService object that + this cdevRequestObject is attached to. +

        +
        + + + getState +

        +
        + + int getState (void); +

        + + Obtains the state of the underlying device. This function returns + one of the following values as defined in cdevErrCode.h. +

        + + + + + + + +
        + + CDEV_STATE_CONNECTED: +

        +
        + + Object is connected. +

        +
        + + CDEV_STATE_NOTCONNECTED: +

        +
        + + Object is not connected. +

        + +

        +
        + + CDEV_STATE_INVALID: +

        +
        + + Object is invalid. +

        +
        + + +

        + The service developer is responsible for implementing this + function correctly in the service related cdevRequestObject. +

        +
        + + + getAccess +

        +
        + + int getAccess (void); +

        + + Obtains access control information about the underlying + device. This function returns one of the following values as + defined in cdevErrCode.h. +

        + + + + + + + +
        + + CDEV_ACCESS_NONE: +

        +
        + + No access to attribute. +

        +
        + + CDEV_ACCESS_READONLY: +

        +
        + + Read-only access. +

        +
        + + CDEV_ACCESS_WRITE: +

        +
        + + Read-write access. +

        +
        + + +

        + The service developer is responsible for implementing this + function correctly in the service related cdevRequestObject. +

        +
        + + + setContext +

        +
        + + int setContext (cdevData& cxt); +

        + + Used to insert a cdevData object containing tagged values that + control optional behavior of the underlying device. The context + is often used to specify which properties (value, status, + severity) a device returns in response to a "get" message. The + service developer may override the default behavior of this + method to better accomodate the requirements of the service. +

        +
        + + + getContext +

        +
        + + cdevData & getContext (void); +

        + + Retrieves a reference to the cdevData object that contains the + context for a specific cdevRequestObject. The service + developer may override the default behavior of this method to + better accomodate the requirements of the service. +

        +
        + + + getPrivate +

        +
        + + void * getPrivate (void); +

        + + Retrieves a pointer to a data object that was placed in this + object using the setPrivate function. +

        +
        + + + setPrivate +

        +
        + + void setPrivate (void * data); +

        + + Associates a user specified data object with this + cdevRequestObject. The pointer can be retrieved later using + the getPrivate method. +

        +
        + + + send +

        +
        + + int send (cdevData &out, cdevData& result); +

        + int send (cdevData *out, cdevData& result); +

        + int send (cdevData &out, cdevData* result); +

        + int send (cdevData *out, cdevData* result); +

        + + The send function is the standard method for synchronously + communicating with a device. The out cdevData object + contains any property values that the device will need to + perform the task. The result cdevData object will contain the + output properties that resulted from the call. The service + developer is responsible for implementing this method in the + service specified cdevRequestObject. This function will return + one of the error code defined in cdevErrCode.h. +

        + +

        +
        + + Figure 11: + + Return codes generated by the send method. +
        + + + +
        + + +
        
        +CDEV_WARNING:         Failure of the function is non-consequential.
        +CDEV_SUCCESS:         The message was processed successfully.
        +CDEV_ERROR:           Failed to process message.
        +CDEV_INVALIDOBJ:      Invalid cdev request object used.
        +CDEV_INVALIDARG:      Invalid argument passed to cdev call.
        +CDEV_INVALIDSVC:      Wrong service during dynamic loading.
        +CDEV_NOTCONNECTED:    Not connected to low level network service.
        +CDEV_INVALIDOP:       The operation is not supported by the device.
        +CDEV_IOFAILED:        Low level network service IO failed.
        +CDEV_CONFLICT:        Conflicts of data types or tags.
        +CDEV_NOTFOUND:        Cannot find specified data in cdevData.
        +CDEV_TIMEOUT:         Time out.
        +CDEV_CONVERT:         cdevData conversion error.
        +CDEV_OUTOFRANGE:      Value out of range for device attribute.
        +CDEV_NOACCESS:        Insufficient access to perform request.
        +CDEV_ACCESSCHANGED:   Change in access permission of device.
        +CDEV_DISCONNECTED:    Service has lost contact with the device.
        +CDEV_RECONNECTED:     Service has regained contact with the device.
        +			
        +
        +
        + +

        + + + + + +
        + + + sendNoBlock +

        +
        + + int sendNoBlock (cdevData &out, cdevData &result); +

        + int sendNoBlock (cdevData *out, cdevData &result); +

        + int sendNoBlock (cdevData &out, cdevData *result); +

        + int sendNoBlock (cdevData *out, cdevData *result); +

        + + The sendNoBlock method uses the same parameters and + syntax as the send method. However, rather than waiting for + the underlying service to respond to the request, this function + will return immediately.The caller must use a cdevGroup object + in order to detect when the transaction has been completed. + The service developer is responsible for implementing this + method in the service specified cdevRequestObject. +

        +
        + + + sendCallback +

        +
        + + int sendCallback (cdevData &out, cdevCallback &callback); +

        + int sendCallback (cdevData *out, cdevCallback &callback); +

        + + The sendCallback function is the standard method for + asynchronously communicating with a device. Rather than + providing a result cdevData object, this method requires the + user to provide the address of a cdevCallback object. This + object contains a user supplied pointer and the address of a + function to call when the message has been successfully + processed. The service developer is responsible for + implementing this method in the service specified + cdevRequestObject. +

        +
        +
        + + 10. +

        +
        + + + The cdevSelector Class +

        +
        + + + Overview of the + cdevSelector + Class +

        +
        + + The cdevSelector C++ class is a utility class that may be used by service developers. + It allows a service that does not use network I/O to provide a locally managed file + descriptor to the cdevSystem object. The service may then use the insertEvent + method to signal the cdevSystem object that the services needs attention. +

        + +

        + + Figure 12: + + Object model of the cdevSelector class +
        + + + +
        + + +
        
        +class cdevSelector
        +methods:
        +insertEvent       (int)     :  int
        +removeEvent       (int)     :  int
        +purge             (void)    :  void
        +writefd           (void)    :  int
        +readfd            (void)    :  int
        +			
        +
        +
        + +

        + + + +
        + + + +

        +
        +
        + + + Public Methods of + the cdevSelector + Class +

        +
        + + + + + + + + + + + +
        + + + insertEvent +

        +
        + + int insertEvent ( int numEvents ); +

        + + Inserts the number of bytes specified in the numEvents + parameter into the file descriptor. If numEvents is not specified, + then one byte will be written. +

        +
        + + + removeEvent +

        +
        + + int removeEvent ( int numEvents ); +

        + + Removes the number of bytes specified in the numEvents + parameter from the file descriptor. If numEvents is not + specified, then one byte will be read. This function uses the + ioctl function to ensure that the numEvents parameter does not + exceed the actual number of bytes available from the file + descriptor. +

        +
        + + + purge +

        +
        + + void purge ( void ); +

        + + Removes all bytes from the file descriptor. +

        +
        + + + writefd +

        +
        + + int writefd ( void ); +

        + + Returns the write file descriptor that is stored within the + cdevSelector object. +

        +
        + + + readfd +

        +
        + + int readfd ( void ); +

        + + Returns the read file descriptor that is stored within the + cdevSelector object. +

        +
        +
        + + 11. +

        +
        + + + The cdevService Class +

        +
        + + + Overview of the + cdevService Class +

        +
        + + The cdevService C++ class is an abstract base class for all cdev services. This class + defines the mechanisms that cdev will utilize to communicate with the underlying + control system. It is the responsibility of the service developer to 'flesh out' the virtual + functions that are defined within this class and to develop the code necessary to + communicate with the underlying control system. +

        + +

        + + Figure 13: + + Object model of the cdevService class +
        + + + +
        + + +
        
        +class cdevSystemBase
        +			
        +
        +
        + +

        + + + +
        + + + +

        +
        +
        + + + Public Methods of + the cdevService + Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + flush +

        +
        + + int flush (void); +

        + + Flushes any pending outbound requests to their respective + devices. This is a pure virtual function that must be provided by + the service developer. +

        +
        + + + poll +

        +
        + + int poll (void); +

        + + Directly polls each of the cdevService's underlying file + descriptors for activity, and delivers any asynchronous + callbacks that are ready. This is a pure virtual function that must + be provided by the service developer. +

        +
        + + + pend +

        +
        + + int pend (int fd); +

        + + Waits for a default period of time for the specified file descriptor + to have an I/O event. If the fd parameter is not provided, the + cdevService object will wait for an I/O event on any of its + contained file descriptors. When an event occurs on one of the + file descriptors, the cdevService object will call the appropriate + function to process the event and dispatch any asynchronous + callbacks that are ready. This is a pure virtual function that must + be provided by the service developer. +

        +
        + + + pend +

        +
        + + int pend (double seconds, int fd); +

        + + Processes all I/O events that occur on the file descriptor during + the specified period of time. If the fd parameter is not provided, + the cdevService object will wait for I/O events on all of its + contained file descriptors. When an event occurs on one of the + file descriptors, the cdevService object will call the appropriate + functions to process the event and dispatch any asynchronous + callbacks that are ready. This is a pure virtual function that must + be provided by the service developer. +

        +
        + + + getRequestObject +

        +
        + + int getRequestObject ( char *dev, char *msg, +

        + cdevRequestObject* &req); +

        + + Obtains a pointer to a cdevRequestObject that is specific to this + service and the specified device/message combination. This + method should only be called by the cdevSystem object. This is + a pure virtual function that must be provided by the service + developer. +

        +
        + + + getNameServer +

        +
        + + int getNameServer (cdevDevice* &server); +

        + + Obtains a cdevDevice object identifying the name server for + this service. A service is not required to provide its own name + server and may simply set the server parameter to NULL. This + is a pure virtual function an must be provided by the service + developer. +

        +
        + + + getCollectionRequest +

        +
        + + int getCollectionRequest ( char ** devices, +

        + int nDevices, char * msg, +

        + cdevCollectionRequest * &req); +

        + + This method allows the caller to obtain a + cdevCollectionRequest object that will contain only devices that + are associated with the service. A default mechanism is + provided to support this functionality, however, the developer + may create a special request object to optimize these + operations. +

        +
        + + + getFd +

        +
        + + int getFd (int* &fd, int &numFd); +

        + + Retrieves a list of file descriptors that are contained within the + cdevService object. The fd pointer will be given the pointer to + the internal array of file descriptors, and the numFD parameter + will be set to the number of file descriptors in the list. A service + that does not use file descriptors should set the fd and numFD + parameters to NULL and 0, respectively. This is a pure virtual + function that must be provided by the service developer. +

        +
        + + + registerFd +

        +
        + + int registerFd (int fd, int opened); +

        + + The service developer may implement this method to allow + external file descriptors to be added to the list of file descriptors + in the service. The fd parameter should contain the file + descriptor, and the opened parameter should contain 1 to add it + to the list or 0 to remove it from the list. +

        +
        + + + autoErrorOn +

        +
        + + int autoErrorOn (void); +

        + + Informs the cdevService object that it should use its internal + default error handler to process any error messages that are + generated by objects within its control. This is the default + operating condition for the cdevService object. +

        +
        + + + autoErrorOff +

        +
        + + int autoErrorOff (void); +

        + + Informs the cdevService object that it should use its internal + default error handler to process any error messages that are + generated by objects within its control. This is the default + operating condition for the cdevService object. +

        +
        + + + reportError +

        +
        + + int reportError ( int severity, char *name, +

        + cdevRequestObject *obj, +

        + char *formatString,...); +

        + + Emits an error message. The severity field indicates the + severity of the error, the name string identifies the object that + generated the error, the obj parameter is the + cdevRequestObject that was in use when the error occurred, + and the formatString and additional parameters (...) should be + formatted in the same manner as the parameters used by + printf. +

        + The integer used by severity should have one of the following + values indicating the severity of the error that has occurred. +

        + + + + + + + + + +
        + + CDEV_SEVERITY_INFO: +

        +
        + + No error. +

        +
        + + CDEV_SEVERITY_WARN: +

        +
        + + An error occurred that should + not impact continued + processing. +

        +
        + + CDEV_SEVERITY_ERROR: +

        +
        + + An error occurred and should + be corrected before continuing. +

        +
        + + CDEV_SEVERITY_SEVERE: +

        +
        + + A severe or fatal error has + occurred and cdev cannot + continue normal execution. +

        +
        + + +

        +
        + + + setErrorHandler +

        +
        + + void setErrorHandler (cdevErrorHandler handler); +

        + + Used to to install a user specified error handler. This error + handler will be called when an error occurs if the autoErrorOff + method has been used to disable the default error handler. The + user provided error handler should have the following + prototype: +

        + void handler (int severity, char *text, cdevRequestObject *obj); +

        + The severity parameter will contain one of the integers + specified in the reportError documentation, the text parameter + will contain the text of the error, and the obj parameter will + contain the cdevRequestObject that was in use when the error + occurred. +

        +
        + + + setThreshold +

        +
        + + void setThreshold (int errorThreshold); +

        + + Used to specify the level of severity at which errors should be + submitted to the error handler. The value of errorThreshold + should be one of the severity levels specified in the reportError + method. +

        +
        + + + name +

        +
        + + char *name (void) const; +

        + + Retrieves the name of the service. This method is used + extensively to determine the service that underlies a specific + cdevRequestObject object. If not over-ridden by the service + developer, this method will return the string "cdevService". +

        +
        +
        + + 12. +

        +
        + + + The cdevSync Class +

        +
        + + + Overview of the + cdevSync Class +

        +
        + + The cdevSync C++ class is a pure virtual base class that declares the I/O operations + that must be supported by the cdevService object and the cdevSystem object. + Because several of its functions are pure virtual, it cannot be instantiated directly. +

        + +

        + + Figure 14: + + Object model of the cdevSync class +
        + + + +
        + + +
        
        +class cdevSync
        +methods:
        +flush      ( void )         {pure virtual}  :int
        +poll       ( void )         {pure virtual}  :int
        +pend       ( int )          {pure virtual}  :int
        +pend       ( double, int )  {pure virtual}  :int
        +className  ( void )         {virtual}       :char * 
        +			
        +
        +
        + +

        + + + +
        + + + +

        +
        +
        + + + Public Methods of + the cdevSync + Class +

        +
        + + + + + + + + + +
        + + + flush +

        +
        + + int flush (void); +

        + + Flushes any pending outbound requests to their respective + services. This is a pure virtual method that is implemented in + derived classes. +

        +
        + + + poll +

        +
        + + int poll (void); +

        + + Directly polls each of the underlying services for activity, and + delivers any asynchronous callbacks that are ready. This is a + pure virtual function that is implemented in the derived classes. +

        +
        + + + pend +

        +
        + + int pend (int fd); +

        + + Waits for a default period of time for the specified file descriptor + to have an I/O event. If the fd parameter is not provided, the + cdevSync object will wait for an I/O event on any of its + contained file descriptors. When an event occurs on one of the + file descriptors, the cdevSync object will call the appropriate + functions to process the event and dispatch any asynchronous + callbacks that are ready. This is a pure virtual function that is + implemented in the derived classes. +

        +
        + + + pend +

        +
        + + int pend (double seconds, int fd); +

        + + Processes all I/O events that occur on the file descriptor during + the specified period of time. If the fd parameter is not provided, + the cdevSync object will wait for I/O events on all of its + contained file descriptors. When an event occurs on one of the + file descriptors, the cdevSync object will call the appropriate + functions to process the event and dispatch any asynchronous + callbacks that are ready. This is a pure virtual function that is + implemented in the derived classes. +

        +
        +
        + + 13. +

        +
        + + + The cdevSystemBase Class +

        +
        + + + Overview of the + cdevSystemBase + Class +

        +
        + + The cdevSystemBase C++ class is a pure virtual base class that inherits the + capabilities of both the cdevError class and the cdevSync class. It then declares the + functions necessary to obtain a request object. Because several of its functions are + pure virtual, it cannot be instantiated directly. +

        + +

        + + Figure 15: + + Object model of the cdevSystemBase class +
        + + + +
        + + +
        
        +class cdevSystemBase
        +methods:
        +getRequestObject  ( ... )  {pure virtual} : int
        +className         ( void ) {virtual}      : char * 
        +			
        +
        +
        + +

        + + + +
        + + + +

        +
        +
        + + + Public Methods of + the + cdevSystemBase + Class +

        +
        + + + +
        + + + getRequestObject +

        +
        + + int getRequestObject ( char *device, char *msg, +

        + cdevRequestObject &req); +

        + + Obtains a reference to a cdevRequestObject from a specified + device name and message name. The object that is produced + by this function will be owned and controlled by the + cdevSystem object that created it. This means that flush, poll + and pend commands must be routed through the owning + cdevSystem object in order to effect this cdevRequetsObject. + Returns CDEV_SUCCESS or an enumerated error code. +

        +
        +
        + + 14. +

        +
        + + + The cdevSystem Class +

        +
        + + + Overview of the + cdevSystem Class +

        +
        + + The cdevSystem C++ class provides the mechanisms that cdev uses to manage and + communicate with multiple services. This class also provides the caller with the tools + necessary to instantiate cdevDevice objects and cdevRequestObject objects. +

        + +

        + + Figure 16: + + Object model of the cdevSystem class +
        + + + +
        + + +
        
        +class cdevSystemBase
        +			
        +
        +
        + +

        + + + +
        + + + +

        +
        +
        + + + Public Methods of + the cdevSystem + Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + attachRef +

        +
        + + static cdevSystem& attachRef(char *name, char *prefix); +

        + + Obtains a reference to a new or existing cdevSystem object + that has the specified name. The prefix parameter is optional, + but, if provided will be prepended to the name of each device + that is requested through the named cdevSystem object before + it is found in the device definition file. +

        +
        + + + attachPtr +

        +
        + + static cdevSystem* attachPtr(char *name, char *prefix); +

        + + Obtains a pointer to a new or existing cdevSystem object that + has the specified name. The prefix parameter is optional, but, if + provided will be prepended to the name of each device that is + requested through the named cdevSystem object before it is + found in the device definition file. +

        +
        + + + defaultSystem +

        +
        + + static cdevSystem &defaultSystem (void); +

        + + Obtains a reference to the default cdevSystem object. In most + applications this mechanism is used to access the cdevSystem + object. +

        +
        + + + getDevice +

        +
        + + cdevDevice* getDevice (char *device); +

        + + Retrieves a pointer to a cdevDevice object by name. The object + that is returned by this function will be owned and controlled by + the cdevSystem object that created it. This means that flush, + poll and pend commands must be routed through the owning + cdevSystem object in order to effect this cdevDevice object. +

        +
        + + + getRequestObject +

        +
        + + int getRequestObject ( char *device, char *msg, +

        + cdevRequestObject &req); +

        + + Retrieves a reference to a cdevRequestObject from a specified + device name and message name. The object that is produced + by this function will be owned and controlled by the + cdevSystem object that created it. This means that flush, poll + and pend commands must be routed through the owning + cdevSystem object in order to effect this cdevRequestObject. + Returns CDEV_SUCCESS or an enumerated error code. +

        +
        + + + name +

        +
        + + char *name (void); +

        + + Returns the name of this cdevSystem object. +

        +
        + + + prefix +

        +
        + + char *prefix (void); +

        + + Retrieves a pointer to the prefix string that is currently being + used by the cdevSystem object. See the attachPtr entry for a + description of the prefix string. +

        +
        + + + prefix +

        +
        + + void prefix (char *pre); +

        + + Changes the prefix string that is being used by the cdevSystem + object. See the attachPtr entry for a description of the prefix + string. +

        +
        + + + flush +

        +
        + + int flush (void); +

        + + Flushes any pending outbound requests to their respective + services. +

        +
        + + + poll +

        +
        + + int poll (void); +

        + + Directly polls each of the cdevSystem's underlying services for + activity, and delivers any asynchronous callbacks that are + ready. +

        +
        + + + pend +

        +
        + + int pend (int fd); +

        + + Waits for a default period of time for the specified file descriptor + to have an I/O event. If the fd parameter is not provided, the + cdevSystem object will wait for an I/O event on any of its + contained file descriptors. When an event occurs on one of the + file descriptors, the cdevSystem object will call the respective + cdevService to process the event and dispatch any + asynchronous callbacks that are ready. +

        +
        + + + pend +

        +
        + + int pend (double seconds, int fd); +

        + + Processes all I/O events that occur on the file descriptor during + the specified period of time. If the fd parameter is not provided, + the cdevSystem object will wait for I/O events on all of its + contained file descriptors. When an event occurs on one of the + file descriptors, the cdevSystem object will call the respective + cdevService to process the event and dispatch any + asynchronous callbacks that are ready. +

        +
        + + + getFd +

        +
        + + int getFd (int fd[], int &numFD); +

        + + Retrieves a list of file descriptors that are contained within the + cdevSystem object. The fd array must be preallocated, and the + maximum number of elements should be specified in the + numFD parameter. Upon completion, the fd array will be + populated with the list of file descriptors, and the numFD + parameter will contain the actual count. +

        +
        + + + addFdChangedCallback +

        +
        + + +

        + int addFdChangedCallback (cdevFdChangedCallback cbk, +

        + void*userarg) +

        + + Adds a new function to be called each time a service + announces to the system that it has opened or closed a file + descriptor. The function will be called with 3 arguments: +

        + + void (*cdevFdChangedCallback) (int fd, int opened, +

        + void *userarg) +

        + + The first argument specifies the file descriptor, the second is 1 + for opened, 0 for closed, and the last argument is the user + specified argument. +

        +
        + + + autoErrorOn +

        +
        + + int autoErrorOn (void); +

        + + Informs the cdevSystem object that it should use its internal + default error handler to process any error messages that are + generated by objects within its control. This is the default + operating condition for the cdevSystem object. +

        +
        + + + autoErrorOff +

        +
        + + int autoErrorOff (void); +

        + + Informs the cdevSystem object that it should use the user + supplied error handling function to process any error messages + that are generated by objects within its control. +

        +
        + + + reportError +

        +
        + + int reportError ( int severity, char *name, +

        + cdevRequestObject *obj, +

        + char *formatString,...); +

        + + Emits an error message. The severity field indicates the + severity of the error, the name string identifies the object that + generated the error, the obj parameter is the + cdevRequestObject that was in use when the error occurred, + and the formatString and additional parameters (...) should be + formatted in the same manner as the parameters used by + printf. +

        + The integer used by severity should have one of the following + values indicating the severity of the error that has occurred. +

        + + + + + + + + + +
        + + CDEV_SEVERITY_INFO: +

        +
        + + No error. +

        +
        + + CDEV_SEVERITY_WARN: +

        +
        + + An error occurred that should + not impact continued + processing. +

        +
        + + CDEV_SEVERITY_ERROR: +

        +
        + + An error occurred and should + be corrected before continuing. +

        +
        + + CDEV_SEVERITY_SEVERE: +

        +
        + + A severe or fatal error has + occurred and cdev cannot + continue normal execution. +

        +
        +
        + + + setErrorHandler +

        +
        + + void setErrorHandler (cdevErrorHandler handler); +

        + + Used to to install a user specified error handler. This error + handler will be called when an error occurs if the autoErrorOff + method has been used to disable the default error handler. The + user provided error handler should have the following + prototype: +

        + void handler (int severity, char *text, cdevRequestObject *obj); +

        + The severity parameter will contain one of the integers + specified in the reportError documentation, the text parameter + will contain the text of the error, and the obj parameter will + contain the cdevRequestObject that was in use when the error + occurred. +

        +
        + + + setThreshold +

        +
        + + void setThreshold (int errorThreshold); +

        + + Used to specify the level of severity at which errors should be + submitted to the error handler. The value of errorThreshold + should be one of the severity levels specified in the reportError + method. +

        +
        +
        + + 15. +

        +
        + + + The cdevTranObj Class +

        +
        + + + Overview of the + cdevTranObj Class +

        +
        + + The cdevTranObj (cdev transaction object) C++ class is a container class that is used + to maintain information that is required for individual operations within a service. This + class stores a copy of the cdevRequestObject that was used to submit a request, the + cdevSystem object in which the request object was created, the cdevCallback object + provided by the user, and the cdevData object that the returned data should be placed + in. Because this object is intended for usage only by cdev internals, all of its data + elements are public. +

        + The cdevTranObj is used to submit a request from the cdevRequestObject to the + cdevService. It may also be used to place a transaction into a group of requests using + a cdevGroup object. The service notifies the cdevSystem object and the cdevGroup + objects that this transaction has been processed by calling its removeFromGrps + method. This will effectively remove the cdevTranObj from all groups that it is + associated with. +

        + +

        + + Figure 17: + + Object model of the cdevTranObj class +
        + + + +
        + + +
        
        +class cdevTranObj
        +properties:
        +system_         : cdevSystem *
        +reqObj_         : cdevRequestObject *
        +resultData_     : cdevData *
        +userCallback_   : cdevCallback *
        + 
        +methods:
        +status             (void) : int 
        +removeFromGrps     (void) : int
        +enableDeleteCbk    (void) : void
        +disableDeleteCbk   (void) : void
        +			
        +
        +
        + +

        +
        + + + Public Data + Properties of the + cdevTranObj Class +

        +
        + + + + + + + + + +
        + + + system_ +

        +
        + + cdevSystem *system_; +

        + + This is a pointer to the cdevSystem that contains this + transaction object. The transaction will be processed whenever + the poll or pend methods of this cdevSystem object are + executed. +

        +
        + + + reqObj_ +

        +
        + + cdevRequestObject *reqObj_; +

        + + This is a pointer to the cdevRequestObject that was called to + submit this transaction. This cdevRequestObject will be + submitted to the user specified callback function when the + transaction has been completed. +

        +
        + + + resultData_ +

        +
        + + cdevData *resultData_; +

        + + This is the cdevData object that will be populated with the + results of the transaction. This object will also be submitted to + the user specified callback function when the transaction has + been completed. +

        +
        + + + userCallback_ +

        +
        + + cdevCallback *userCallback_; +

        + + This class contains a pointer to the caller specified callback + function as well as any user argument. The callback function + will be executed when the transaction has been completed. + Note that it is the responsibility of the service to execute this + callback function when it has finished processing the + transaction. +

        +
        +
        + + + Public Member + Functions of the + cdevTranObj Class +

        +
        + + + + + + + + + +
        + + + status +

        +
        + + int status (void); +

        + + Returns the status of the cdevTranObj object. The value + returned will be 1 if this object is a member of any cdevGroup + object, or -1 if this object is not a member of any cdevGroup + object. +

        +
        + + + removeFromGrps +

        +
        + + int removeFromGrps (void); +

        + + Removes this transaction object from any cdevGroup object + that it may be in. +

        +
        + + + enableDeleteCbk +

        +
        + + void enableDeleteCbk (void); +

        + + Sets the internal flag telling the transaction object to delete its + internal callback object while executing its destructor. This is + the default behavior for the cdevTranObj. +

        +
        + + + disableDeleteCbk +

        +
        + + void disableDeleteCbk (void); +

        + + Sets the internal flag telling the transaction object not to delete + its internal callback object while executing its destructor. This + mode should be used when the user specified callback object + is shared by numerous transaction objects. +

        +
        +
        + + 16. +

        +
        + + + Language Specification for the cdev DDL file +

        +
        + + + Language + Specification +

        +
        + + In the following, required language elements are in double quotes, optional elements + are in square brackets. Names are arbitrary character strings. value is of any type. + Plus sign indicates concatenation, vertical bar alternate choices. +

        + +

        + + Figure 18: + + Language specification for the cdev DDL file +
        + + + +
        + + +
        
        +specification = serviceSpecs + classSpecs + instances + aliases + 
        +collections
        + 
        +serviceSpecs = serviceSpec + [serviceSpecs]
        +serviceSpec = "service" + name + "{" + "tags" + "{" + tagList + "}" 
        ++ "}"
        +tagList = tag + ["," + tagList]
        + 
        +classSpecs = classSpec + [classSpecs]
        +classSpec = "class" + name + [" : " + parentList] + "{" + 
        +         verbs + attributes + messages
        +parentList = name + ["," + parentList]
        +verbs = "verbs" + "{" + verbList + "}"
        +verbList = name + ["," + verbList]
        +attributes = "attributes" + "{" + attrList + "}"
        +attrList = name + serviceName + ["{" + serviceData + "}"] + [";" + 
        +attrList]
        +serviceData = name + "=" + value
        +messages = "messages" + "{" + msgList + "}"
        +msgList = msg + serviceName + ["{" + serviceData + "}"] + [";" + 
        +msgList]
        +msg = name | """string"""
        + 
        +instances = className + ":" instanceList + ";"
        +instanceList = instance + [" " + instanceList]
        + 
        +aliases = alias + [" " + aliases]
        +alias = "alias " + aliasname + " " + actualname
        + 
        +collections = collection + " " + name + " : " instanceList + ";"
        +instanceList = instance + [" " + instanceList]
        +			
        +
        +
        + +

        +
        + + 17. +

        +
        + + + Regular Expressions +

        +
        + + + Overview of + Regular + Expressions +

        +
        + + A regular expression is a mechanism supported by many utilities for locating and + manipulating patterns in text. Basic regular expression (RE) notation and construction + rules apply to utilities defined as using basic REs. Any exceptions to the following + rules are noted in the descriptions of the specific utilities that use REs. +

        +
        + + + Ordinary + Characters +

        +
        + + An ordinary character is an RE that matches itself. An ordinary character is any + character in the supported character set except <newline> and the regular expression + special characters listed in Special Characters below. An ordinary character preceded + by a backslash (\\) is treated as the ordinary character itself, except when the character + is (, ), {, or }, or the digits 1 through 9 (see REs Matching Multiple Characters). + Matching is based on the bit pattern used for encoding the character; not on the + graphic representation of the character. +

        +
        + + + Special Characters +

        +
        + + A regular expression special character preceded by a backslash is a regular + expression that matches the special character itself. When not preceded by a + backslash, such characters have special meaning in the specification of REs. Regular + expression special characters and the contexts in which they have special meaning + are: +

        + + + + + + + + + + + + + +
        + + + . [ \\ +

        +
        + + The period, left square bracket, and backslash are special + except when used in a bracket expression (see RE Bracket + Expression). +

        +
        + + + * +

        +
        + + The asterisk is special except when used in a bracket + expression, as the first character of a regular expression, or as + the first character following the character pair \\( (see REs + Matching Multiple Characters). +

        +
        + + + ^ +

        +
        + + The circumflex is special when used as the first character of an + entire RE (see Expression Anchoring) or as the first character + of a bracket expression. +

        +
        + + + $ +

        +
        + + The dollar sign is special when used as the last character of an + entire RE (see Expression Anchoring). +

        +
        + + + delimiter +

        +
        + + Any character used to bound (i.e., delimit) an entire RE is + special for that RE. +

        +
        + + + period +

        +
        + + A period (.), when used outside of a bracket expression, is an + RE that matches any printable or nonprintable character except + <newline>. +

        +
        +
        + + + Bracket + Expression +

        +
        + + A bracket expression enclosed in square brackets ([ ]) is an RE that matches a single + collating element contained in the nonempty set of collating elements represented by + the bracket expression. The following rules apply to bracket expressions: +

        + + + + + + + + + + + + + + + + + + + + + +
        + + + bracket expression +

        +
        + + A bracket expression is either a matching list expression or a + non-matching list expression, and consists of one or more + expressions in any order. Expressions can be: collating + elements, collating symbols, noncollating characters, + equivalence classes, range expressions, or character classes. + The right bracket (]) loses its special meaning and represents + itself in a bracket expression if it occurs first in the list (after an + initial ^, if any). Otherwise, it terminates the bracket expression + (unless it is the ending right bracket for a valid collating symbol, + equivalence class, or character class, or it is the collating + element within a collating symbol or equivalence class + expression). The special characters +

        +
        + + + . * [ \\ +

        +
        + + (period, asterisk, left bracket, and backslash) lose their special + meaning within a bracket expression. +

        +
        + + + matching list +

        +
        + + A matching list expression specifies a list that matches any one + of the characters represented in the list. The first character in + the list cannot be the circumflex. For example, [abc] is an RE + that matches any of a, b, or c. +

        +
        + + + non-matching list +

        +
        + + A non-matching list expression begins with a circumflex (^), and + specifies a list that matches any character except <newline> + and the characters represented in the list. For example, [^abc] + is an RE that matches any character except <newline> or a, b, + or c. The circumflex has this special meaning only when it + occurs first in the list, immediately following the left square + bracket. +

        +
        + + + collating element +

        +
        + + A collating element is a sequence of one or more characters + that represents a single element in the collating sequence as + identified via the most current setting of the locale category + LC_COLLATE (see setlocale(3C)). +

        +
        + + + collating symbol +

        +
        + + A collating symbol is a collating element enclosed within + bracket-period ([.....]) delimiters. Multi-character collating + elements must be represented as collating symbols to + distinguish them from single-character collating elements. For + example, if the string ch is a valid collating element, then [.ch.] + is treated as an element matching the same string of + characters, while ch is treated as a simple list of the characters + c and h. If the string within the bracket-period delimiters is not a + valid collating element in the current collating sequence + definition, the symbol is treated as an invalid expression. +

        +
        + + + noncollating char +

        +
        + + A noncollating character is a character that is ignored for + collating purposes. By definition, such characters cannot + participate in equivalence classes or range expressions. +

        +
        + + + equivalence class +

        +
        + + An equivalence class expression represents the set of collating + elements belonging to an equivalence class. It is expressed by + enclosing any one of the collating elements in the equivalence + class within bracket-equal ([=...=]) delimiters. For example, if + ,,and A belong to the same equivalence class, then [[=a=]b], + =]b], and [[=A=]b] are each equivalent toAb]. +

        +
        + + + range expression +

        +
        + + A range expression represents the set of collating elements + that fall between two elements in the current collation sequence + as defined via the most current setting of the locale category + LC_COLLATE (see setlocale(3C)). It is expressed as the + starting point and the ending point separated by a hyphen (-). +

        + The starting range point and the ending range point must be a + collating element, collating symbol, or equivalence class + expression. An equivalence class expression used as an end + point of a range expression is interpreted such that all collating + elements within the equivalence class are included in the + range. For example, if the collating order is A, a, B, b, C, c, ch, + D, d; and A and a constitute an equivalence class, then the + expression [[=a=]-D] is treated as [AaBbCc[.ch.]D]. +

        + Both starting and ending range points must be valid collating + elements, collating symbols, or equivalence class expressions, + and the ending range point must collate equal to or higher than + the starting range point; otherwise the expression is invalid. For + example, with the above collating order and assuming that E is + a noncollating character, then both the expressions [[=A=]-E] + and [d-a] are invalid. +

        + An ending range point can also be the starting range point in a + subsequent range expression. Each such range expression is + evaluated separately. For example, the bracket expression [a- + m-o] is treated as [a-mm-o]. +

        + The hyphen character is treated as itself if it occurs first (after + an initial ^, if any) or last in the list, or as the rightmost symbol in + a range expression. As examples, the expressions [-ac] and + [ac-] are equivalent and match any of the characters a, c, or -; + the expressions [^-ac] and [^ac-] are equivalent and match any + characters except <newline>, a, c, or -; the expression [%--] + matches any of the characters in the defined collating + sequence between % and - inclusive; the expression [--@] + matches any of the characters in the defined collating + sequence between - and @ inclusive; and the expression [a-- + @] is invalid, assuming - precedes a in the collating sequence. +

        +
        + + + character class +

        +
        + + A character class expression represents the set of characters + belonging to a character class, as defined via the most current + setting of the locale category LC_CTYPE. It is expressed as a + character class name enclosed within bracket-colon ([: :]) + delimiters. +

        + Valid character class expressions and the class they represent + are: +

        + [:alpha:] letters +

        + [:upper:] upper-case letters +

        + [:lower:] lower-case letters +

        + [:digit:] decimal digits +

        + [:xdigit:] hexadecimal digits +

        + [:alnum:] letters or decimal digits +

        + [:space:] characters producing white- space in displayed text +

        + [:print:] printing characters +

        + [:punct:] punctuation characters +

        + [:graph:] characters with a visible representation +

        + [:cntrl:] control characters +

        +
        +
        + + + Matching Multiple + Characters +

        +
        + + The following rules may be used to construct REs matching multiple characters from + REs matching a single character: +

        + + + + + + + + + + + +
        + + + RERE +

        +
        + + The concatenation of REs is an RE that matches the first + encountered concatenation of the strings matched by each + component of the RE. For example, the RE bc matches the + second and third characters of the string abcdefabcdef. +

        +
        + + + RE* +

        +
        + + An RE matching a single character followed by an asterisk (*) is + an RE that matches zero or more occurrences of the RE + preceding the asterisk. The first encountered string that permits + a match is chosen, and the matched string will encompass the + maximum number of characters permitted by the RE. For + example, in the string abbbcdeabbbbbbcde, both the RE b*c + and the RE bbb*c are matched by the +

        + substring bbbc in the second through fifth positions. An asterisk + as the first character of an RE loses this special meaning and is + treated as itself. +

        +
        + + + \\(RE\\) +

        +
        + + A subexpression can be defined within an RE by enclosing it + between the character pairs \\( and \\). Such a subexpression + matches whatever it would have matched without the \\( and \\). + Subexpressions can be arbitrarily nested. An asterisk + immediately following the \\( loses its special meaning and is + treated as itself. An asterisk immediately following the \\) is + treated as an invalid character. +

        +
        + + + \\n +

        +
        + + The expression \\n matches the same string of characters as + was matched by a subexpression enclosed between \\( and \\) + preceding the \\n. The character n must be a digit from 1 + through 9, specifying the n-th subexpression (the one that + begins with the n-th \\( and ends with the corresponding paired + \\). For example, the expression ^\\(.*\\)\\1$ matches a line + consisting of two adjacent appearances of the same string. +

        + If the \\n is followed by an asterisk, it matches zero or more + occurrences of the subexpression referred to. For example, the + expression \\(ab\\(cd\\)ef\\)Z\\2*Z\\1 matches the string + abcdefZcdcdZabcdef. +

        +
        + + + RE\\{m,n\\} +

        +
        + + An RE matching a single character followed by \\{m\\}, \\{m,\\}, or + \\{m,n\\} is an RE that matches repeated occurrences of the RE. + The values of m and n must be decimal integers in the range 0 + through 255, with m specifying the exact or minimum number of + occurrences and n specifying the maximum number of + occurrences. \\{m\\} matches exactly m occurrences of the + preceding RE, \\{m,\\} matches at least m occurrences, and + \\{m,n\\} matches any number of occurrences between m and n, + inclusive. +

        + The first encountered string that matches the expression is + chosen; it will contain as many occurrences of the RE as + possible. For example, in the string abbbbbbbc the RE b\\{3\\} is + matched by characters two through four, the RE b\\{3,\\} is + matched by characters two through eight, and the RE b\\{3,5\\}c + is matched by characters four through nine. +

        +
        +
        + + + Expression + Anchoring +

        +
        + + An RE can be limited to matching strings that begin or end a line (i.e., anchored) + according to the following rules: +

        + + + A circumflex (^)as the first RE anchors the expression to the beginning of a line; + only strings starting at the first character of a line are matched by the RE. For + example, the RE ^ab matches the string ab in the line abcdef, but not the same + string in the line cdefab. +

        + + + A dollar sign ($) as the last character of an RE anchors the expression to the end + of a line; only strings ending at the last character of a line are matched by the RE. + For example, the RE ab$ matches the string ab in the line cdefab, but not the + same string in the line abcdef. +

        + + + An RE anchored by both ^ and $ matches only strings that are lines. For example, + the RE ^abcdef$ matches only lines consisting of the string abcdef. +

        + + +

        + + +

        +
        + diff --git a/doc/html/cdevScriptService.html b/doc/html/cdevScriptService.html new file mode 100755 index 0000000..2f5178e --- /dev/null +++ b/doc/html/cdevScriptService.html @@ -0,0 +1,949 @@ + + +CDEV Documentation + + + + + + +


        + + + +
        + + + + CDEV Script Service +

        + + +

        + A Tool for Using Interactive Scripts from CDEV +

        + +

        + Walt Akers +

        + +

        + Version 1.0 - February 11, 1997 +

        + +

        + TJNAF - Thomas Jefferson National Accelerator Facility +

        + +

        +
        + +


        + + + + + +
        + + + + Table of Contents +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +
        +
        + + Script Service Fundamentals +
        +
        + + +
        +
        + + Overview of the Script Service +
        +
        + + +
        +
        + + Features of the Script Service +
        +
        + + 2. +
        +
        + + Building the Script Service +
        +
        + + +
        +
        + + Location of Files +
        +
        + + +
        +
        + + Steps to Building Service +
        +
        + + 3. +
        +
        + + Structure of Data Provided to the Script +
        +
        + + +
        +
        + + General Form of Data String +
        +
        + + +
        +
        + + Representation of Scalar Data +
        +
        + + +
        +
        + + Representation of Array Data +
        +
        + + 4. +
        +
        + + Structure of Data Returned from the Script +
        +
        + + +
        +
        + + Returning Data to the Calling CDEV Application +
        +
        + + +
        +
        + + General Form of String Data +
        +
        + + +
        +
        + + Returning a Single Result Packet +
        +
        + + +
        +
        + + Returning Multiple Result Packets +
        +
        + + +
        +
        + + Special Considerations +
        +
        + + 5. +
        +
        + + DDL Entries for the Script Service +
        +
        + + +
        +
        + + Setting Up the DDL +
        +
        +
        + +


        + + + + + +
        + + + + List of Figures +

        +
        + + + + Figure 1: + General form of string representation of cdevData +
        + + Figure 2: + String representation of scalar data in a cdevData object +
        + + Figure 3: + String representation of array data +
        + + Figure 4: + Returning a single result packet to the CDEV application +
        + + Figure 5: + Returning a multiple result packets to the CDEV application +
        + + Figure 6: + Simple DDL file for the Script Service +
        +
        + +


        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + + Script Service Fundamentals +

        +
        + + + Overview of the + Script Service +

        +
        + + The CDEV Script Service is designed to allow a a CDEV application to execute an + external script to process a message. The output that is produced by the executable + will be returned to the caller in the form of a cdevData. The CDEV Script Service + meets the following requirements. +

        +
        + + + Features of the + Script Service +

        +
        + + + + + + + + + + + + + + + + + + + + + +
        + + +

        +
        + + The filename of the script is associated with a CDEV device/message + combination by using the "filename" field of the service data in the CDEV DDL file. + Syntax is described later in this document. +

        +
        + + +

        +
        + + A new process will be spawned for the script each time it is executed. Its standard + output (stdout) file descriptor will be redirected to return data to the main CDEV + application, allowing the script to return results to the parent process. +

        +
        + + +

        +
        + + The external executable file can be any form of user shell, batch file or binary + application that is supported on the host platform. +

        +
        + + +

        +
        + + The Script Service supports all of CDEV's send mechanisms; "send", + "sendNoBlock" and "sendCallback". Because of limits imposed on the number of + active processes, the user is advised to use the synchronous "send" method + whenever practical. +

        +
        + + +

        +
        + + When called by CDEV, the script will receive three arguments; the name of the + CDEV device associated with the request, the message string that was submitted + to the device, and a string that describes the contents of the outbound cdevData + object. +

        +
        + + +

        +
        + + The reply that is written to the standard output by the script must have a specific + format as described later in this document. A script may return more than one + reply packet to the caller. +

        +
        + + +

        +
        + + The script notifies CDEV that it has written its last reply packet by writing "done" + alone on a line to the standard output. +

        +
        + + +

        +
        + + If the script is to return multiple results, it should write "end" alone on a line to the + standard output between each packet, and write "done" alone on a line following + the last packet. +

        +
        + + +

        +
        + + If the script returns a value in the "status" tag of its reply packet, this will be + provided to the caller as the completion code of the message. Traditionally a + status of 0 indicates success, and all other values indicated an error occurred. +

        +
        + + +

        +
        + + Because the callback mechanism of the Script Service is triggered by output from + the script, the script developer should at least write "done" to the standard output + even if the application returns no output. +

        +
        +
        + + 2. +

        +
        + + + Building the Script Service +

        +
        + + + Location of Files +

        +
        + + The source code for the Script Service is provided with the CDEV distribution starting + with version 1.5. The source code is located in the directory $CDEV/extensions/ + ScriptService. The following steps should be taken to build the ScriptService. +

        +
        + + + Steps to Building + Service +

        +
        + + + + + + + + + + + +
        + + 1. +

        +
        + + Obtain and install the CDEV distribution - Version 1.5 or higher. +

        +
        + + 2. +

        +
        + + Follow the installation steps to build CDEV on your system. This includes setting + all of the environment variables required by CDEV. +

        +
        + + 3. +

        +
        + + Change directories to $CDEV/extensions/ScriptService/src. +

        +
        + + 4. +

        +
        + + There is a collection of platform specific makefiles in the directory $CDEV/ + extensions/cdevGenericServer/include/makeinclude. Link the makefile that is + appropriate to your architecture to the file Makefile.OS. +

        + + For example, to link to the makefile for HP-UX, you would type the following + command. +

        + +

        + ln -s Makefile.hpux Makefile.OS +

        + +

        +
        + + 5. +

        +
        + + Type make to compile and link the Script Service shared object. Note that you + must be using GNU make in order to build this distribution. +

        +
        + + Upon completion the Makefile will generate the shared object for the Script Service + and will install it into your CDEVSHOBJ directory. At this point you are ready to use + the Script Service. +

        +
        + + 3. +

        +
        + + + Structure of Data Provided to the Script +

        +
        + + + General Form of + Data String +

        +
        + + When a developer makes a CDEV send call, he may provide outbound data in the + form of a cdevData object. Before calling the script, this data is converted into a string + and provided as the third argument to the application (the first argument is the device + name and the second is the message). The structure of the outbound data string is of + the following form. +

        + +

        + + Figure 1: + + General form of string representation of cdevData +
        + + + +
        + + +
        
        +tag1="string value"
        +tag2=1.00
        +			
        +
        +
        + +

        + + +

        +
        + + + Representation of + Scalar Data +

        +
        + + The above example shows two data entries of the form tag=value. Each entry is + separated by a carriage return. The first entry has a tag name of 'tag1' and a value of + 'string value'. You will note that 'string value' is enclosed in double quotes in the + example. This is used to notify the script that the value is a non-numeric character + string. In the second data entry the value '1.0' is not enclosed in quotes, indicating that + the value is a number. +

        + The following example illustrates how scalar values stored in a cdevData object would + look when they are passed to the script. +

        + +

        + + Figure 2: + + String representation of scalar data in a cdevData object +
        + + + +
        + + +
        
        +Data stored in cdevData object:
        +      Tag:   value
        +      Data Type:   character string
        +      Value:   Test
        + 
        +      Tag:   status
        +      Data Type:   integer
        +      Value:   0
        + 
        +      Tag:   controlHigh
        +      Data Type:   double
        +      Value:   1.001
        + 
        +String representation provided to script:
        +      value="Test"\\n
        +      status=0\\n
        +      controlHigh=1.001\\n
        +			
        +
        +
        + +

        + + +

        +
        + + + Representation of + Array Data +

        +
        + + If array data is stored in the outbound cdevData object, it too can be provided to the + script. The data is structured in the standard C format where opening and closing + braces mark the beginning and end (respectively) of each array bound. The following + example illustrates how various arrays would be represented as strings. +

        + + Figure 3: + + String representation of array data +
        + + + +
        + + +
        
        +Data stored in cdevData object:
        +      Tag:   value
        +      Data Type:   character string [3]
        +      Value:   "value1" "value2" "value3"
        + 
        +String representation provided to script:
        +      value={"value1","value2","value3"}\\n
        + 
        +
        + 
        +Data stored in cdevData object:
        +      Tag:   value
        +      Data Type:   double [3]
        +      Value:   1.0, 2.0, 3.01
        + 
        +String representation provided to script:
        +      value={1,2,3.01}\\n
        + 
        +
        + 
        +Data stored in cdevData object:
        +      Tag:   value
        +      Data Type:   double [3][2]
        +      Value:   1.0, 2.0,   3.0, 4.0,    5.0, 6.0
        + 
        +String representation provided to script:
        +      value={{1,2},{3,4},{5,6}}\\n
        +			
        +
        +
        + +

        +
        + + 4. +

        +
        + + + Structure of Data Returned from the Script +

        +
        + + + Returning Data to + the Calling CDEV + Application +

        +
        + + Before CDEV starts the script, it creates a pipe that is used to pass data between the + script and the CDEV application. One end of this pipe is maintained by the application + and the other end of the pipe is provided to the script as its standard output. This + means that anytime the script uses the "echo" command or the "printf" command, the + data that it output's will be transmitted through the pipe to the parent application. +

        + The script is responsible for formatting the data into a collection of character strings + that can be recognized by the CDEV application. +

        +
        + + + General Form of + String Data +

        +
        + + In general, the data that is returned from a script is of the same form as described in + the preceding section, "Structure of Data Provided to the Script". The most notable + difference is that the script must terminate the list by providing a character string that + indicates that the group of data items is complete; the string "end" or "done" alone on + a line. +

        +
        + + + Returning a + Single Result + Packet +

        +
        + + If the script is going to return exactly one result packet (a group of tags and values that + will be used to populate the result cdevData), then it should write the string "done" on + a line by itself immediately following the output data. This will notify the Script Service + that no more data will be returned from the script. +

        + The following example shows how a single result will be returned from a script. Note + that the "status" tag contains the completion code that will be returned to the CDEV + application. +

        + + Figure 4: + + Returning a single result packet to the CDEV application +
        + + + +
        + + +
        
        +#\\! /bin/csh -f
        + 
        +echo value=\\"Test\\"
        +echo status=0
        +echo controlLow=1.5
        +echo controlHigh=25.1
        +echo done
        +			
        +
        +
        + +

        +
        + + + Returning + Multiple Result + Packets +

        +
        + + Returning multiple results from a single script execution is not generally advised. + However, If the script is going to return more than one result packet, then each interim + packet should be terminated by the "end" keyword on a line by itself. The "done" + keyword should follow the last entry. +

        + The following example shows how two results will be returned from a script. +

        + + Figure 5: + + Returning a multiple result packets to the CDEV application +
        + + + +
        + + +
        
        +#\\! /bin/csh -f
        + 
        +echo value=\\"Start Result 1\\"
        +echo status=0
        +echo end
        +echo value=\\"Start Result 2\\"
        +echo status=-1
        +echo done
        +			
        +
        +
        + +

        +
        + + + Special + Considerations +

        +
        + + If the script that is being executed will not return a result, then the developer should + still write "done" to the standard output in order to notify the CDEV application that it + should no longer wait for output. If the script is not returning a result, it may write the + terminating "done" at the beginning of the script or at the end. Because synchronous + calls will block until a reply is received, the developer should return a result to the + CDEV application as quickly as possible. +

        + If the developer never writes anything to the standard output, then the user specified + CDEV callback will never be executed... therefore, it is crucial to notify the CDEV + application when the script has completed. +

        +
        + + 5. +

        +
        + + + DDL Entries for the Script Service +

        +
        + + + Setting Up the + DDL +

        +
        + + The following example illustrates how to add a service entry to identify the Script + Service and how to use the service data to specify the filename that the Script Service + will execute to service a message. +

        + + Figure 6: + + Simple DDL file for the Script Service +
        + + + +
        + + +
        
        +/*
        + * This is the service definition, it tells CDEV that there is
        + * a service named Script and that it will use the cdevData
        + * tag 'filename' to read configuration information from the
        + * DDL file entries.
        + */
        +service Script 
        +   {
        +   tags {filename}
        +   }
        + 
        +/*
        + * This class definition identifies the class scriptClass which
        + * supports the "get and "set" commands on attributes "attrib0"
        + * and "attrib1".  Note that attrib0 will call script /bin/ouch
        + * and attrib1 will call script /bin/wammo.
        + */ 
        +class scriptClass 
        +   {
        +       verbs {get, set}
        +   attributes 
        +      { 
        +      attrib0 Script {filename = /bin/ouch};
        +            attrib1 Script {filename = /bin/wammo};
        +      }
        +}
        + 
        +/*
        + * Finally, the CDEV DDL identifies two devices that are of type
        + * scriptClass.  Any time one of the supported messages is passed
        + * to one of these devices it will activate the corresponding
        + * script.
        + */
        +scriptClass : device0, device1;
        + 
        +			
        +
        +
        + +

        + + +

        +
        + diff --git a/doc/html/cdevServiceGuide.html b/doc/html/cdevServiceGuide.html new file mode 100755 index 0000000..d9eb623 --- /dev/null +++ b/doc/html/cdevServiceGuide.html @@ -0,0 +1,6349 @@ + + +CDEV Documentation + + + + + + +


        + + + +
        + + + + Service Developer's Guide +

        + + Techniques for Developing Services using the +

        + Control Device Interface +

        + + +

        + Chip Watson, Jie Chen, Danjin Wu, Walt Akers +

        + +

        + Version 1.5 - December 9, 1996 +

        + +

        + TJNAF - Thomas Jefferson National Accelerator Facility +

        +
        + +


        + + + + + +
        + + + + Table of Contents +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +
        +
        + + Overview of cdev Services +
        +
        + + +
        +
        + + What is a cdev Service +
        +
        + + +
        +
        + + Service Classes +
        +
        + + +
        +
        + + Request Object Classes +
        +
        + + +
        +
        + + Loader Functions +
        +
        + + +
        +
        + + What the Developer Must Understand +
        +
        + + 2. +
        +
        + + Developing cdev Services +
        +
        + + +
        +
        + + Steps in Developing a cdev Service +
        +
        + + 3. +
        +
        + + The cdevService Class +
        +
        + + +
        +
        + + Overview of the cdevService Class +
        +
        + + +
        +
        + + The flush Method +
        +
        + + +
        +
        + + The poll Method +
        +
        + + +
        +
        + + The pend Method +
        +
        + + +
        +
        + + The getRequestObject Method +
        +
        + + +
        +
        + + Public Member Functions of the cdevService ClassPublic Functions of the cdevService Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + flush +
        +
        + + +
        +
        + + poll +
        +
        + + +
        +
        + + pend +
        +
        + + +
        +
        + + pend +
        +
        + + +
        +
        + + getRequestObject +
        +
        + + +
        +
        + + getNameServer +
        +
        + + +
        +
        + + getCollectionRequest +
        +
        + + +
        +
        + + getFd +
        +
        + + +
        +
        + + registerFd +
        +
        + + +
        +
        + + autoErrorOn +
        +
        + + +
        +
        + + autoErrorOff +
        +
        + + +
        +
        + + reportError +
        +
        + + +
        +
        + + setErrorHandler +
        +
        + + +
        +
        + + setThreshold +
        +
        + + +
        +
        + + name +
        +
        +
        + + 4. +
        +
        + + The cdevRequestObject Class +
        +
        + + +
        +
        + + Overview of the cdevRequest Object Class +
        +
        + + +
        +
        + + Public Member Functions of the cdevRequest Object Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + attachRef +
        +
        + + +
        +
        + + attachRef +
        +
        + + +
        +
        + + attachPtr +
        +
        + + +
        +
        + + attachPtr +
        +
        + + +
        +
        + + detach +
        +
        + + +
        +
        + + detach +
        +
        + + +
        +
        + + message +
        +
        + + +
        +
        + + device +
        +
        + + +
        +
        + + system +
        +
        + + +
        +
        + + service +
        +
        + + +
        +
        + + getState +
        +
        + + +
        +
        + + getAccess +
        +
        + + +
        +
        + + setContext +
        +
        + + +
        +
        + + getContext +
        +
        + + +
        +
        + + getPrivate +
        +
        + + +
        +
        + + setPrivate +
        +
        + + +
        +
        + + send +
        +
        + + +
        +
        + + sendNoBlock +
        +
        + + +
        +
        + + sendCallback +
        +
        +
        + + 5. +
        +
        + + The cdevCollectionRequest Class +
        +
        + + +
        +
        + + Overview of the cdevCollection Request Class +
        +
        + + +
        +
        + + Public Member Functions of the cdevCollection Request Class +
        + + + + + + + + + + + +
        + + +
        +
        + + constructor +
        +
        + + +
        +
        + + destructor +
        +
        + + +
        +
        + + attachPtr +
        +
        + + +
        +
        + + className +
        +
        + + +
        +
        + + resultCodeTag +
        +
        +
        + + 6. +
        +
        + + The Service Loader Function +
        +
        + + +
        +
        + + Overview +
        +
        + + +
        +
        + + Naming Convention +
        +
        + + 7. +
        +
        + + The cdevTranObj Class +
        +
        + + +
        +
        + + Overview of the cdevTranObj Class +
        +
        + + +
        +
        + + Public Data Properties of the cdevTranObj Class +
        + + + + + + + + + +
        + + +
        +
        + + system_ +
        +
        + + +
        +
        + + reqObj_ +
        +
        + + +
        +
        + + resultData_ +
        +
        + + +
        +
        + + userCallback_ +
        +
        +
        + + +
        +
        + + Public Member Functions of the cdevTranObj Class +
        + + + + + + + + + +
        + + +
        +
        + + status +
        +
        + + +
        +
        + + removeFromGrps +
        +
        + + +
        +
        + + enableDeleteCbk +
        +
        + + +
        +
        + + disableDeleteCbk +
        +
        +
        + + 8. +
        +
        + + Default Service Behavior for Standard Messages +
        +
        + + +
        +
        + + Overview +
        +
        + + +
        +
        + + "get" Message +
        +
        + + +
        +
        + + "set" Message +
        +
        + + +
        +
        + + "monitorOn" Message +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + CDEV_SUCCESS: +
        +
        + + +
        +
        + + CDEV_DISCONNECTED: +
        +
        + + +
        +
        + + CDEV_RECONNECTED: +
        +
        + + +
        +
        + + CDEV_ERROR: +
        +
        + + +
        +
        + + CDEV_INVALIDOBJ: +
        +
        + + +
        +
        + + CDEV_INVALIDARG: +
        +
        + + +
        +
        + + CDEV_INVALIDSVC: +
        +
        + + +
        +
        + + CDEV_NOTCONNECTED: +
        +
        + + +
        +
        + + CDEV_IOFAILED: +
        +
        + + +
        +
        + + CDEV_CONFLICT: +
        +
        + + +
        +
        + + CDEV_NOTFOUND: +
        +
        + + +
        +
        + + CDEV_TIMEOUT: +
        +
        + + +
        +
        + + CDEV_CONVERT: +
        +
        + + +
        +
        + + CDEV_OUTOFRANGE: +
        +
        + + +
        +
        + + CDEV_NOACCESS: +
        +
        + + +
        +
        + + CDEV_ACCESSCHANGED: +
        +
        +
        + + +
        +
        + + "monitorOff" Message +
        + + + + + + + + + +
        + + +
        +
        + + device +
        +
        + + +
        +
        + + attribute +
        +
        + + +
        +
        + + function +
        +
        + + +
        +
        + + userarg +
        +
        +
        + + 9. +
        +
        + + demoService: A Sample cdev Service +
        +
        + + +
        +
        + + Overview of the demoService +
        +
        + + +
        +
        + + The demoDevice Object +
        +
        + + +
        +
        + + The demoService Object +
        +
        + + +
        +
        + + The enqueueTransaction Method +
        +
        + + +
        +
        + + The processTransaction Method +
        +
        + + +
        +
        + + The newDemoService Function +
        +
        + + +
        +
        + + The cdevSelector Object +
        +
        + + +
        +
        + + The VERB Enumeration +
        +
        + + +
        +
        + + The ATTR Enumeration +
        +
        + + +
        +
        + + The demoRequestObject Object +
        +
        + + +
        +
        + + Makefile for the demoService +
        +
        + + +
        +
        + + Device Definition File for the demoService +
        +
        +
        + +


        + + + + + +
        + + + + List of Figures +

        +
        + + + + Figure 1: + Return codes generated by the send method. +
        + + Figure 2: + Naming convention and syntax for the cdevService loader function +
        + + Figure 3: + Example cdevService loader function +
        + + Figure 4: + Default behavior of the "get" and "set" messages +
        + + Figure 5: + Default behavior of the "monitorOn" and "monitorOff" messages +
        + + Figure 6: + demoDevice.h: Header file for devices used by the demoService +
        + + Figure 7: + demoDevice.cc: C++ source for the demoDevice class +
        + + Figure 8: + demoService.h: Header file for the demoService class +
        + + Figure 9: + demoService.cc: Source code for the demoService class +
        + + Figure 10: + demoRequestObject.h: Header file for the demoRequestObject class +
        + + Figure 11: + demoRequestObject.cc: Source for the demoRequestObject class +
        + + Figure 12: + Makefile for the demoService +
        + + Figure 13: + Device Definition Language file for the demoService +
        +
        + +


        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + + Overview of cdev Services +

        +
        + + + What is a cdev + Service +

        +
        + + The cdev library defines a command set that can be used to provide a homogenous + interface to differing control systems. In order to incorporate a control system into the + cdev environment, the developer must create linking code that allows the cdev system + to communicate with the system. This linking code is called a cdev service. At a + minimum, the cdev service developer must develop two interface classes and a simple + constructor function in order to create a new service. These classes and functions will + be described at length in the sections that follow. +

        +
        + + + Service Classes +

        +
        + + Each service must define a service class that provides the mechanisms for + communicating with the underlying control system. This class is inherited from the + cdevService class, from which it gains most of its functionality. The main effort for the + developer in creating this class is in the flush, poll and pend methods. These methods + are functionally identical to those defined in the cdevSystem object, however, the + developer must provide concrete mechanisms for communicating with the intended + control system, as well as managing and reporting errors that might occur during + normal operation. +

        +
        + + + Request Object + Classes +

        +
        + + The service developer must also create a request object class that provides the + mechanisms for a cdevDevice object to communicate with the developer's service + class. This class is inherited from the cdevRequestObject class, from which it gains + most of its functionality. The primary effort for the developer in creating this class is in + the send, sendNoBlock and sendCallback functions. The service creator must also + develop his strategy for efficiently communicating with the underlying system. The + source code in the following chapters will illustrate a queueing scheme that provides a + very simple and efficient linkage between the service and the request object. The + request object is also responsible for detecting and reporting errors that occur within + its domain. +

        +
        + + + Loader Functions +

        +
        + + The loader function is an extern "C" function that is called by the cdevSystem object to + dynamically construct a copy of the service class. +

        +
        + + + What the + Developer Must + Understand +

        +
        + + In order to create cdev services, the developer must have an extensive understanding + of the complete cdev system. A potential service developer should first develop + applications using existing cdev services in order to understand the expected behavior + of a service. The developer should then familiarize himself completely with all of the + classes within the cdev library, paying special attention to the cdevService class and + the cdevRequestObject class. +

        + The following chapters describe the structure and syntax of the most important of + these classes and an overview of how certain messages are expected to behave. This + manual finishes with the complete annotated source code for a demonstration service + that operates on a virtual control system. +

        +
        + + 2. +

        +
        + + + Developing cdev Services +

        +
        + + + Steps in + Developing a cdev + Service +

        +
        + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + Install and build the cdev distribution. Obtain a copy of the most recent cdev + distribution and install it on your system. +

        +
        + + 2. +

        +
        + + Define the devices in your control system. Define the names, attributes and + messages associated with each device in your control system. This information + will be critical in the construction of the Device Definition Language file that cdev + will use to determine which service will process messages for a device. +

        +
        + + 3. +

        +
        + + Design and document specific device/message behavior. Determine the + specific inputs and outputs required for each device to process a message. + Design and document how the service will route messages to the underlying + control system. Ensure that the disposition of standard messages within your + service is consistent with the behavior of standard cdev services. +

        +
        + + 4. +

        +
        + + Develop your cdevService object. This object is a sub-class of the cdevService + class and will be responsible for responding to flush, poll, and pend requests from + the cdevSystem object. The service object should be able to perform all interface + tasks necessary to link the service specific cdevRequestObjects to the underlying + control system. +

        +
        + + 5. +

        +
        + + Develop your cdevRequestObject object. This object is a sub-class of the + cdevRequestObject class and will be responsible for responding to send, + sendNoBlock and sendCallback requests from the cdev application. +

        +
        + + 6. +

        +
        + + Develop your cdevCollectionRequest object (optional). If your service will + provide specialized support for collections of devices, it wil be necessary to + develop a cdevCollectionRequest object that processes these requests. +

        +
        + + 7. +

        +
        + + Create a service loader function. This function is described earlier in this + document and is used by the cdevSystem object to an instantiate a new service + object for this service. +

        +
        + + 8. +

        +
        + + Compile and link the shared object. Compile a position-independent shared + object file that cdev can load on request. The service's shared object file should + contain all of the object code necessary to directly load and utilize the service. + This file should be copied to the directory where the other cdev services are + stored. +

        +
        + + +

        +
        + + 3. +

        +
        + + + The cdevService Class +

        +
        + + + Overview of the + cdevService Class +

        +
        + + The cdevService C++ class is an abstract base class for all cdev services. This class + defines the mechanisms that cdev will utilize to communicate with your underlying + control system. It is the responsibility of the service developer to 'flesh out' the virtual + functions that are defined within this class and to develop the code necessary to + communicate with the underlying control system. +

        + The primary methods that developers must concern themselves with are flush, poll + pend, and getRequestObject. These methods represent the majority of the work that + must be performed in developing a cdev service. +

        +
        + + + The flush Method +

        +
        + + The flush method is responsible for submitting any unsent messages to the device. + This may entail submission of a message using a network protocol or simply calling a + statically linked C function. The cdevSystem object will call this method prior to each + pend or poll operation, or whenever the flush method of the system object is called + directly by the user. +

        +
        + + + The poll Method +

        +
        + + The poll method is responsible for directly polling each of the physical devices that are + managed by the service to detect if they require attention (typically by checking a + single socket). This method is typically utilized to allow the physical device an + opportunity to return a response to a previously sent message. The cdevSystem + object will call this method whenever the application calls the poll method of the + system object. Most services can route this call directly to their associated pend + method. +

        +
        + + + The pend Method +

        +
        + + The pend method allows the service to wait for a period of time for one of its + underlying devices to require attention. After waiting for a specified period of time, this + method will return CDEV_SUCCESS if it successfully serviced any of its underlying + devices, or CDEV_TIMEOUT if no device became active during that period. This + method is typically called by the cdevSystem object in response to a change in state + of one or more of the service's file descriptors. +

        +
        + + + The + getRequestObject + Method +

        +
        + + The getRequestObject method is used by the cdevSystem object to obtain a new + instance of one of the service's request objects in response to a request made by the + application. The service may internally define many request object types for use by + applications, therefore, it is the responsibility of this function to return the correct + request object for the specified device / message combination. Typically a service will + only define one type of request object and will use it for all requests. +

        +
        + + + Public Member + Functions of the + cdevService Class +

        + Public Functions + of the + cdevService Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + flush +

        +
        + + int flush (void); +

        + + Flushes any pending outbound requests to the appropriate + servers. This is a pure virtual function that must be provided by + the service developer. +

        +
        + + + poll +

        +
        + + int poll (void); +

        + + Directly polls each of the cdevService's underlying file + descriptors for activity, and delivers any asynchronous + callbacks that are ready. This is a pure virtual function that must + be provided by the service developer. +

        +
        + + + pend +

        +
        + + int pend (int fd); +

        + + Waits for a default period of time for the specified file descriptor + to have an I/O event. If the fd parameter is not provided, the + cdevService object will wait for an I/O event on any of its + contained file descriptors. When an event occurs on one of the + file descriptors, the cdevService object will call the appropriate + function to process the event and dispatch any asynchronous + callbacks that are ready. This is a pure virtual function that must + be provided by the service developer. +

        +
        + + + pend +

        +
        + + int pend (double seconds, int fd); +

        + + Processes all I/O events that occur on the file descriptor during + the specified period of time. If the fd parameter is not provided, + the cdevService object will wait for I/O events on all of its + contained file descriptors. When an event occurs on one of the + file descriptors, the cdevService object will call the appropriate + functions to process the event and dispatch any asynchronous + callbacks that are ready. This is a pure virtual function that must + be provided by the service developer. +

        +
        + + + getRequestObject +

        +
        + + int getRequestObject ( char *dev, char *msg, +

        + cdevRequestObject* &req); +

        + + Obtains a pointer to a cdevRequestObject that is specific to this + service and the specified device/message combination. This + method should only be called by the cdevSystem object. This is + a pure virtual function that must be provided by the service + developer. +

        +
        + + + getNameServer +

        +
        + + int getNameServer (cdevDevice* &server); +

        + + Obtains a cdevDevice object identifying the name server for + this service. A service is not required to provide its own name + server and may simply set the server parameter to NULL. This + is a pure virtual function an must be provided by the service + developer. +

        +
        + + + getCollectionRequest +

        +
        + + int getCollectionRequest ( char ** devices, +

        + int nDevices, char * msg, +

        + cdevCollectionRequest * &req); +

        + + This method allows the caller to obtain a + cdevCollectionRequest object that will contain only devices that + are associated with the service. A default mechanism is + provided to support this functionality, however, the developer + may create a special request object to optimize these + operations. +

        +
        + + + getFd +

        +
        + + int getFd (int* &fd, int &numFd); +

        + + Retrieves a list of file descriptors that are contained within the + cdevService object. The fd pointer will be given the pointer to + the internal array of file descriptors, and the numFD parameter + will be set to the number of file descriptors in the list. A service + that does not use file descriptors should set the fd and numFD + parameters to NULL and 0, respectively. This is a pure virtual + function that must be provided by the service developer. +

        +
        + + + registerFd +

        +
        + + int registerFd (int fd, int opened); +

        + + The service developer may implement this method to allow + external file descriptors to be added to the list of file descriptors + in the service. The fd parameter should contain the file + descriptor, and the opened parameter should contain 1 to add it + to the list or 0 to remove it from the list. +

        +
        + + + autoErrorOn +

        +
        + + int autoErrorOn (void); +

        + + Informs the cdevService object that it should use its internal + default error handler to process any error messages that are + generated by objects within its control. This is the default + operating condition for the cdevService object. +

        +
        + + + autoErrorOff +

        +
        + + int autoErrorOff (void); +

        + + Informs the cdevService object that it should use its internal + default error handler to process any error messages that are + generated by objects within its control. This is the default + operating condition for the cdevService object. +

        +
        + + + reportError +

        +
        + + int reportError ( int severity, char *name, +

        + cdevRequestObject *obj, +

        + char *formatString,...); +

        + + Emits an error message. The severity field indicates the + severity of the error, the name string identifies the object that + generated the error, the obj parameter is the + cdevRequestObject that was in use when the error occurred, + and the formatString and additional parameters (...) should be + formatted in the same manner as the parameters used by + printf. +

        + The integer used by severity should have one of the following + values indicating the severity of the error that has occurred. +

        + + + + + + + + + +
        + + CDEV_SEVERITY_INFO: +

        +
        + + No error. +

        +
        + + CDEV_SEVERITY_WARN: +

        +
        + + An error occurred that should + not impact continued + processing. +

        +
        + + CDEV_SEVERITY_ERROR: +

        +
        + + An error occurred and should + be corrected before + continuing. +

        +
        + + CDEV_SEVERITY_SEVERE: +

        +
        + + A severe or fatal error has + occurred and cdev cannot + continue normal execution. +

        +
        +
        + + + setErrorHandler +

        +
        + + void setErrorHandler (cdevErrorHandler handler); +

        + + Used to install a user specified error handler. This error handler + will be called when an error occurs if the autoErrorOff method + has been used to disable the default error handler. The user + provided error handler should have the following prototype: +

        + void handler (int severity, char *text, cdevRequestObject *obj); +

        + The severity parameter will contain one of the integers + specified in the reportError documentation, the text parameter + will contain the text of the error, and the obj parameter will + contain the cdevRequestObject that was in use when the error + occurred. +

        +
        + + + setThreshold +

        +
        + + void setThreshold (int errorThreshold); +

        + + Used to specify the level of severity at which errors should be + submitted to the error handler. The value of errorThreshold + should be one of the severity levels specified in the reportError + method. +

        +
        + + + name +

        +
        + + char *name (void) const; +

        + + Retrieves the name of the service. This method is used + extensively to determine the service that underlies a specific + cdevRequestObject object. If not over-ridden by the service + developer, this method will return the string "cdevService". +

        +
        +
        + + 4. +

        +
        + + + The cdevRequestObject Class +

        +
        + + + Overview of the + cdevRequest + Object Class +

        +
        + + The cdevRequestObject C++ class is the application's interface to the underlying + service. Each service must provide a service specific request object that applications + may use to send messages to the service. +

        + The message associated with a cdevRequestObject may be sent to a device using + one of the three send member functions, these are: send, sendNoBlock, and + sendCallback. The syntax and functionality of these methods is described in the + section below. The majority of work in the development of a service specific request + object is in the development of these three methods. +

        +
        + + + Public Member + Functions of the + cdevRequest + Object Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + attachRef +

        +
        + + static cdevRequestObject& attachRef (char *device, char * + msg); +

        + + Obtains a reference to a cdevRequestObject object by + specifying the name of the device and the message string. By + default, the new object will be managed by the default + cdevSystem. +

        +
        + + + attachRef +

        +
        + + static cdevRequestObject& attachRef (cdevDevice &dev, char * + msg); +

        + + Obtains a reference to a cdevRequestObject object by + providing a reference to the associated cdevDevice object and + the message string. By default, the new object will be managed + by the default cdevSystem. +

        +
        + + + attachPtr +

        +
        + + static cdevRequestObject* attachPtr (char *device, char * msg); +

        + + Obtains a pointer to a cdevRequestObject by specifying the + name of the device and the message string. By default, the new + object will be managed by the default cdevSystem. +

        +
        + + + attachPtr +

        +
        + + static cdevRequestObject* attachPtr (cdevDevice &dev, char * + msg); +

        + + Obtains a pointer to a cdevRequestObject by providing a + reference to the associated cdevDevice object and the + message string. By default, the new object will be managed by + the default cdevSystem. +

        +
        + + + detach +

        +
        + + static void detach (cdevRequestObject& dev); +

        + + Removes a referenced cdevRequestObject object from its + associated cdevSystem object. Ordinary applications should + never use this command. +

        +
        + + + detach +

        +
        + + static void detach (cdevRequestObject* dev); +

        + + Detaches the cdevRequestObject object specified by dev from + its associated cdevSystem object. Ordinary applications should + never use this command. +

        +
        + + + message +

        +
        + + char *message (void) const; +

        + + Retrieves the message string that is associated with this + cdevRequestObject. +

        +
        + + + device +

        +
        + + cdevDevice &device (void) const; +

        + + Retrieves a reference to the cdevDevice object that is + associated with this cdevRequestObject. +

        +
        + + + system +

        +
        + + cdevSystem& system (void) const; +

        + + Retrieves a reference to the underlying cdevSystem object that + manages this cdevRequestObject. +

        +
        + + + service +

        +
        + + cdevService& service (void) const; +

        + + Retrieves a reference to the underlying cdevService object that + this cdevRequestObject is attached to. +

        +
        + + + getState +

        +
        + + int getState (void); +

        + + Obtains the state of the underlying device. This function returns + one of the following values as defined in cdevErrCode.h. +

        + + + + + + + +
        + + CDEV_STATE_CONNECTED: +

        +
        + + Object is connected. +

        +
        + + CDEV_STATE_NOTCONNECTED: +

        +
        + + Object is not connected. +

        +
        + + CDEV_STATE_INVALID: +

        +
        + + Object is invalid. +

        +
        + + The service developer is responsible for implementing this + function correctly in the service related cdevRequestObject. +

        +
        + + + getAccess +

        +
        + + int getAccess (void); +

        + + Obtains access control information about the underlying + device. This function returns one of the following values as + defined in cdevErrCode.h. +

        + + + + + + + +
        + + CDEV_ACCESS_NONE: +

        +
        + + No access to attribute. +

        +
        + + CDEV_ACCESS_READONLY: +

        +
        + + Read-only access. +

        +
        + + CDEV_ACCESS_WRITE: +

        +
        + + Read-write access. +

        +
        + + The service developer is responsible for implementing this + function correctly in the service related cdevRequestObject. +

        +
        + + + setContext +

        +
        + + int setContext (cdevData& cxt); +

        + + Used to insert a cdevData object containing tagged values that + control optional behavior of the underlying device. The context + is often used to specify which properties (value, status, + severity) a device returns in response to a "get" message. The + service developer may override the default behavior of this + method to better accommodate the requirements of the + service. +

        +
        + + + getContext +

        +
        + + cdevData & getContext (void); +

        + + Retrieves a reference to the cdevData object that contains the + context for a specific cdevRequestObject. The service + developer may override the default behavior of this method to + better accommodate the requirements of the service. +

        +
        + + + getPrivate +

        +
        + + void * getPrivate (void); +

        + + Retrieves a pointer to a data object that was placed in this + object using the setPrivate function. +

        +
        + + + setPrivate +

        +
        + + void setPrivate (void * data); +

        + + Associates a user specified data object with this + cdevRequestObject. The pointer can be retrieved later using + the getPrivate method. +

        +
        + + + send +

        +
        + + int send (cdevData &out, cdevData& result); +

        + int send (cdevData *out, cdevData& result); +

        + int send (cdevData &out, cdevData* result); +

        + int send (cdevData *out, cdevData* result); +

        + + The send function is the standard method for synchronously + communicating with a device. The out cdevData object + contains any property values that the device will need to + perform the task. The result cdevData object will contain the + output properties that resulted from the call. The service + developer is responsible for implementing this method in the + service specified cdevRequestObject. This function will return + one of the error code defined in cdevErrCode.h. +

        +
        + + Figure 1: + + Return codes generated by the send method. +
        + + + +
        + + +
        
        +CDEV_WARNING:       The failure was non-critical.
        +CDEV_SUCCESS:       The message was processed successfully.
        +CDEV_ERROR:         Failed to process message.
        +CDEV_INVALIDOBJ:    Invalid cdev request object used.
        +CDEV_INVALIDARG:    Invalid argument passed to cdev call.
        +CDEV_INVALIDSVC:    Wrong service during dynamic loading.
        +CDEV_INVALIDOP:     The operation is not supported.
        +CDEV_NOTCONNECTED:  Not connected to low level network 
        +                    service.
        +CDEV_IOFAILED:      Low level network service IO failed.
        +CDEV_CONFLICT:      Conflicts of data types or tags.
        +CDEV_NOTFOUND:      Cannot find specified data in cdevData.
        +CDEV_TIMEOUT:       Time out.
        +CDEV_CONVERT:       cdevData conversion error.
        +CDEV_OUTOFRANGE:    Value out of range for device attribute.
        +CDEV_NOACCESS:      Insufficient access to perform request.
        +CDEV_ACCESSCHANGED: Change in access permission of device.
        +CDEV_DISCONNECTED:  The service has lost contact with the 
        +                    device.
        +CDEV_RECONNECTED:   The service has regained contact with 
        +                    the device.
        +			
        +
        +
        + +

        + + + + + +
        + + + sendNoBlock +

        +
        + + int sendNoBlock (cdevData &out, cdevData &result); +

        + int sendNoBlock (cdevData *out, cdevData &result); +

        + int sendNoBlock (cdevData &out, cdevData *result); +

        + int sendNoBlock (cdevData *out, cdevData *result); +

        + + The sendNoBlock method uses the same parameters and + syntax as the send method. However, rather than waiting for + the underlying service to respond to the request, this function + will return immediately.The caller must use a cdevGroup object + in order to detect when the transaction has been completed. + The service developer is responsible for implementing this + method in the service specified cdevRequestObject. +

        +
        + + + sendCallback +

        +
        + + int sendCallback (cdevData &out, cdevCallback &callback); +

        + int sendCallback (cdevData *out, cdevCallback &callback); +

        + + The sendCallback function is the standard method for + asynchronously communicating with a device. Rather than + providing a result cdevData object, this method requires the + user to provide the address of a cdevCallback object. This + object contains a user supplied pointer and the address of a + function to call when the message has been successfully + processed. The service developer is responsible for + implementing this method in the service specified + cdevRequestObject. +

        +
        +
        + + 5. +

        +
        + + + The cdevCollectionRequest Class +

        +
        + + + Overview of the + cdevCollection + Request Class +

        +
        + + The cdevCollectionRequest class is an abstract base class from which other + cdevCollectionRequest objects are derived. It provides a protected constructor and + destructor that are used to initialize its internals, however, the primary mechanism that + is used to obtain a cdevCollectionRequest object is the attachPtr method. +

        + Because the cdevCollectionRequest is inherited from the cdevRequestObject, all of + the methods of that class must be fulfilled in addition to those specific to the + cdevCollectionRequest class. +

        +
        + + + Public Member + Functions of the + cdevCollection + Request Class +

        +
        + + + + + + + + + + + +
        + + + constructor +

        +
        + + cdevCollectionRequest( char **devices, int nDevices, +

        + char * msg, cdevSystem & system); +

        + + This is the constructor for the cdevCollectionRequest class. It + has the following properties. +

        + + + + + + + +
        + + +

        +
        + + This method is protected to prevent the direct instantiation + of new cdevCollectionRequests. New instances of the + cdevCollectionRequest objects are created by using the + attachPtr or attachRef method of the cdevRequestObject + class which will call the local attachPtr method to create a + new object if necessary. +

        +
        + + +

        +
        + + The constructor is called by the cdevCollection object and + is provided with a list and count of devices that will be + included in the collection and the message that will be sent + to them. +

        +
        + + +

        +
        + + The cdevSystem reference that is provided is the + cdevSystem instance that will be used to poll, pend and + flush the cdevCollectionRequest object. +

        +
        +
        + + + destructor +

        +
        + + virtual ~cdevCollectionRequest (void); +

        + + This is the destructor for a cdevCollectionRequest object. It has + the following properties. +

        + + + + + +
        + + +

        +
        + + This method is protected to prevent the + cdevCollectionRequest object from being destroyed by the + application. This method should only be called by the + cdevSystem object when the application is terminating. +

        +
        + + +

        +
        + + Because the cdevCollectionRequest object will normally be + referred to as a cdevRequestObject object, this destructor + is virtual to ensure that the 'most senior' destructor is + called first. +

        +
        +
        + + + attachPtr +

        +
        + + cdevCollectionRequest * attachPtr +

        + ( cdevCollection &col, char *msg, cdevSystem &sys); +

        + + This method is used by the cdevCollection object to obtain a + new cdevCollectionRequest object. +

        + + + + + + + + + + + +
        + + +

        +
        + + This method will obtain a copy of the device names from + the cdevCollection object and will poll the cdevDirectory + object to determine which service each of them is + associated with. +

        +
        + + +

        +
        + + If the devices are all from a single service, this method will + return a service specific collection request object. +

        +
        + + +

        +
        + + If the devices are from a variety of services, this method will + return a cdevGrpCollectionRequest that contains the + service specific collection request objects. +

        +
        + + +

        +
        + + Device/message combinations that are not associated with + a service will be ignored. +

        +
        + + +

        +
        + + If none of the device/message combinations can be + associated with a service, then an error message will be + generated and NULL will be returned. +

        +
        +
        + + + className +

        +
        + + char * className (void); +

        + + This method returns the name of the class; + "cdevCollectionRequest". If the developer inherits a service + specific cdevCollectionRequest, then this method should not be + altered or overridden. +

        +
        + + + resultCodeTag +

        +
        + + int resultCodetag (void); +

        + + This method returns the integer tag that should be used to + insert the result code that was geneterated when the message + was sent to the actual device. +

        +
        + + +

        + +

        + +

        + +

        +
        + + 6. +

        +
        + + + The Service Loader Function +

        +
        + + + Overview +

        +
        + + The service loader function is used to create an initial instance of the service after the + its associated shared object file has been dynamically loaded. +

        +
        + + + Naming + Convention +

        +
        + + The naming convention for this class is very specific. The following syntax is required: +

        + +

        + + Figure 2: + + Naming convention and syntax for the cdevService loader function +
        + + + +
        + + +
        
        +cdevService *newXxxxxService (char * name, cdevSystem * system);
        +			
        +
        +
        + +

        + + +

        + In the function name above the Xxxxx should be replaced by the name of the service + with the first character capitalized. A service named demo would have a loader + function named newDemoService. The loader function is only required to allocate a + new service class for the service and return a pointer to it. The following example + illustrates how the loader function for the demo service would be written. +

        + +

        + + Figure 3: + + Example cdevService loader function +
        + + + +
        + + +
        
        +#include <cdevService.h>
        + 
        +// ****************************************************************
        +// * Include file with definition of the service class
        +// ****************************************************************
        +#include "demoService.h"
        + 
        +// ****************************************************************
        +// * Loader function for the demoService class 
        +// ****************************************************************
        +cdevService *newDemoService (char * name, cdevSystem * system)
        +   {
        +   return new demoService(name, *system);   
        +   }
        +			
        +
        +
        + +

        +
        + + 7. +

        +
        + + + The cdevTranObj Class +

        +
        + + + Overview of the + cdevTranObj Class +

        +
        + + The cdevTranObj (cdev transaction object) C++ class is a container class that is used + to maintain information that is required for individual operations within a service. This + class stores a copy of the cdevRequestObject that was used to submit a request, the + cdevSystem object in which the request object was created, the cdevCallback object + provided by the user, and the cdevData object that the returned data should be placed + in. Because this object is intended for usage only by cdev internals, all of its data + elements are public. +

        + The cdevTranObj is used to submit a request from the cdevRequestObject to the + cdevService. It is also used to place a transaction into a group of requests using the + cdevGroup object. The service notifies the cdevSystem object and the cdevGroup + objects that this transaction has been processed by calling its removeFromGrps + method. This will effectively remove the cdevTranObj from all groups that it is + associated with. +

        +
        + + + Public Data + Properties of the + cdevTranObj Class +

        +
        + + + + + + + + + +
        + + + system_ +

        +
        + + cdevSystem *system_; +

        + + This is a pointer to the cdevSystem that contains this + transaction object. The transaction will be processed whenever + the poll or pend methods of this cdevSystem object are + executed. +

        +
        + + + reqObj_ +

        +
        + + cdevRequestObject *reqObj_; +

        + + This is a pointer to the cdevRequestObject that was called to + submit this transaction. This cdevRequestObject will be + submitted to the user specified callback function when the + transaction has been completed. +

        +
        + + + resultData_ +

        +
        + + cdevData *resultData_; +

        + + This is the cdevData object that will be populated with the + results of the transaction. This object will also be submitted to + the user specified callback function when the transaction has + been completed. +

        +
        + + + userCallback_ +

        +
        + + cdevCallback *userCallback_; +

        + + This class contains a pointer to the caller specified callback + function as well as any user argument. The callback function + will be executed when the transaction has been completed. + Note that it is the responsibility of the service to execute this + callback function when it has finished processing the + transaction. +

        +
        +
        + + + Public Member + Functions of the + cdevTranObj Class +

        +
        + + + + + + + + + +
        + + + status +

        +
        + + int status (void); +

        + + Returns the status of the cdevTranObj object. The value + returned will be 1 if this object is a member of any cdevGroup + object, or -1 if this object is not a member of any cdevGroup + object. +

        +
        + + + removeFromGrps +

        +
        + + int removeFromGrps (void); +

        + + Removes this transaction object from any cdevGroup object + that it may be in. +

        +
        + + + enableDeleteCbk +

        +
        + + void enableDeleteCbk (void); +

        + + Sets the internal flag telling the transaction object to delete its + internal callback object while executing its destructor. This is + the default behavior for the cdevTranObj. +

        +
        + + + disableDeleteCbk +

        +
        + + void disableDeleteCbk (void); +

        + + Sets the internal flag telling the transaction object not to delete + its internal callback object while executing its destructor. This + mode should be used when the user specified callback object + is shared by numerous transaction objects. +

        +
        + + +

        +
        + + 8. +

        +
        + + + Default Service Behavior for Standard Messages +

        +
        + + + Overview +

        +
        + + The cdev library is designed to provide a standard calling interface to dissimilar + devices within a control system. This interface is accommodated through the use of + the cdevDevice methods send, sendNoBlock and sendCallback. However, because + each service can define the names and behaviors of the messages that it supports, + the user must be increasingly aware of which service may process its messages. +

        + In order to reduce the required knowledge of the user, and to improve the consistency + of all services, all cdev services should provide well-defined support for a minimum list + of verbs. +

        + The following verbs should be implemented to provide a standard behavior in all cdev + services: get, set, monitorOn, and monitorOff. +

        +
        + + + "get" Message +

        +
        + + The "get" verb can be joined with any attribute of a device to form a "get" message. + This message is then sent to the device in order to obtain the value of specified + properties of the attribute. The following steps should be executed in order to utilize a + "get" message. +

        + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + Obtain a pointer to the cdevDevice object for the device that you wish to address. +

        +
        + + 2. +

        +
        + + Create a message string by concatenating the attribute that you wish to address + to the "get" verb. For instance, to get the VAL attribute of a device, the message + strings should be: "get VAL". +

        +
        + + 3. +

        +
        + + Optionally, use the cdevDevice object created in step 1 and the message string + created in step 2 to obtain a pointer to a cdevRequestObject object. +

        +
        + + 4. +

        +
        + + Set the context of the cdevDevice or cdevRequestObject to indicate which + properties you wish to obtain. A non-zero value in any property indicates that its + value should be returned. If no context has been specified, the service should + return the value property by default. A complete description of the context data + object is provided in the cdevDevice documentation. +

        +
        + + 5. +

        +
        + + Use the send, sendNoBlock, or sendCallback message to submit the message + to the device. +

        +
        + + 6. +

        +
        + + Evaluate the return value from the send command to determine if the operation + completed successful. Any value other than CDEV_SUCCESS indicates that an + error occurred in handling the message. +

        +
        + + 7. +

        +
        + + If the call was completed successfully, extract the desired properties from the + resultant cdevData object. +

        +
        +
        + + + "set" Message +

        +
        + + The "set" verb can be joined with any attribute of a device to form a "set" message. + This message is then sent to the device in order to set the value property of the + attribute. The following steps should be executed in order to utilize a "set" message. +

        + + + + + + + + + + + + + +
        + + 1. +

        +
        + + Obtain a pointer to the cdevDevice object for the device that you wish to address. +

        +
        + + 2. +

        +
        + + Create a message string by concatenating the attribute that you wish to address + to the "set" verb. For instance, to set the bdl attribute of a device, the message + string should be: "set bdl". +

        +
        + + 3. +

        +
        + + Optionally, use the cdevDevice object created in step 1 and the message string + created in step 2 to obtain a pointer to a cdevRequestObject object. +

        +
        + + 4. +

        +
        + + Set the value property of the outbound cdevData object to the new value. +

        +
        + + 5. +

        +
        + + Use the send, sendNoBlock, or sendCallback message to submit the message + to the device. +

        +
        + + 6. +

        +
        + + Evaluate the return value from the specific send command to determine if the + message was transmitted successful. Any value other than CDEV_SUCCESS + indicates that the message was not transmitted successfully. +

        +
        + + In the following example, the "get" message will be used to obtain the properties + value, status and severity from the bdl attribute of device MQB1S01, the "set" + message will then be used to copy the value property to the bdl attribute of device + MQB1S02. +

        + +

        + + Figure 4: + + Default behavior of the "get" and "set" messages +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevRequestObject.h>
        +#include <cdevData.h>
        + 
        +// ****************************************************************
        +// * The printError function will be used to output any error that
        +// * that occurs during the processing of the "get" or "set"
        +// * messages.
        +// ****************************************************************
        +int printError (int errCode)
        +   {
        +   switch(errCode) 
        +      {   
        +      // ******* Unknown device or device/message mismatch ******
        +      case CDEV_INVALIDOBJ:
        +         printf("Unknown device or device/message mismatch\\n");
        +         break;
        + 
        +      // * Communications error between application and service *
        +      case CDEV_NOTCONNECTED:
        +      case CDEV_IOFAILED:
        +      case CDEV_TIMEOUT:
        +         printf("Communications error while sending\\n");
        +         break;
        + 
        +			
        +
        +
        + +

        + + Figure 4: + Default behavior of the "get" and "set" messages (continued) +
        + + + +
        + + +
        
        +      // ******* No data or bad data passed with message ********
        +      case CDEV_INVALIDARG:
        +      case CDEV_OUTOFRANGE:
        +      case CDEV_NOTFOUND:
        +      case CDEV_CONVERT:
        +         printf("Bad or missing value passed in message\\n");
        +         break;
        + 
        +      // ******************** Generic Error *********************
        +      case CDEV_ERROR:
        +      case default:
        +         printf("Unable to send message\\n");
        +         break;
        +      }
        +   }
        + 
        +void main()
        +   {
        +   cdevRequestObject * req1, *req2;
        +   cdevData            ctx;
        +   cdevData            output, input;
        +   double              val;
        +   int                 errorCode = CDEV_SUCCESS;
        + 
        +   // ***********************************************************
        +   // * Obtain a pointer to the cdevRequestObject for the
        +   // * "get bdl" message on device "MQB1S01".
        +   // ***********************************************************
        +   req1 = cdevRequestObject::attachPtr("MQB1S01", "get bdl");
        + 
        +   // ***********************************************************
        +   // * Place a non-zero value in the properties value, status,
        +   // * severity.
        +   // ***********************************************************
        +   ctx.set("value", 1);
        +   ctx.set("status", 1);
        +   ctx.set("severity", 1);
        +   
        +   // ***********************************************************
        +   // * Set the context of the cdevRequestObject.
        +   // ***********************************************************
        +   req1->setContext(ctx);
        + 
        +   // ***********************************************************
        +   // * Submit the message to the device and test the return 
        +   // * value to ensure that the message was processed correctly
        +   // ***********************************************************
        +   if((errorCode=req1->send(NULL, &output))==CDEV_SUCCESS) 
        +      {
        +      // ********************************************************
        +      // * Message was transmitted and processed successfuly.
        +      // ********************************************************
        +      char   stat[50], sev[255];
        +      output.get("value", &val);
        +      output.get("status", stat, 50);
        +			
        +
        +
        + +

        + + Figure 4: + Default behavior of the "get" and "set" messages +
        + + + +
        + + +
        
        +      output.get("severity", sev, 50);
        +      printf("Val:%f, status:%s, severity:%s", val, stat, sev);
        +      }   
        +   else printError(errorCode);
        + 
        +   // ***********************************************************
        +   // * Obtain a pointer to the cdevRequestObject for the
        +   // * "set bdl" message on device "MQB1S02".
        +   // ***********************************************************
        +   req2 = cdevRequestObject::attachPtr("MQB1S02", "set bdl");
        + 
        +   // ***********************************************************
        +   // * Insert the new value into the input cdevData object.
        +   // ***********************************************************
        +   input.insert("value", value);
        + 
        +   // ***********************************************************
        +   // * Submit the message "set bdl" to the device and test 
        +   // * the return value to ensure that the message was 
        +   // * processed successfully. Note that, by default, the set
        +   // * message does not generate any output.
        +   // ***********************************************************
        +   if((errorCode==req2->send(&input, NULL))==CDEV_SUCCESS) 
        +      {
        +      // ********************************************************
        +      // * Message was transmitted and processed successfuly.
        +      // ********************************************************
        +      printf("Message was transmitted successfully\\n");
        +      }
        +   else printError(errorCode);
        +   }
        +			
        +
        +
        + +

        +
        + + + "monitorOn" + Message +

        +
        + + The "monitorOn" verb can be joined with any attribute of a device to form a + "monitorOn" message. This message is tells the cdevDevice that each time one of the + monitored properties changes, it should call the user specified callback function with + the updated value. This message should always be submitted using the + sendCallback method of the cdevDevice or cdevRequestObject in order to provide + the address of the callback function. +

        + The following steps should be executed in order to submit a "monitorOn" message. +

        + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + Obtain a pointer to the cdevDevice object for the device that you wish to address. +

        +
        + + 2. +

        +
        + + Create a message string by concatenating the attribute that you wish to address + to the "monitorOn" verb. For instance, to monitor a property of the bdl attribute of a + device, the message string should be: "monitorOn bdl". +

        +
        + + 3. +

        +
        + + Optionally, use the cdevDevice object created in step 1 and the message string + created in step 2 to obtain a pointer to a cdevRequestObject object. +

        +
        + + 4. +

        +
        + + Set the context of the cdevDevice or cdevRequestObject to indicate the properties + that you wish to monitor, and the properties you wish to receive when a change + occurs. The context used by the "monitorOn" message differs from that of the + "get" message in that different non-zero values have special meanings. The + following is a list of integer values that should be supported by the context of a + "monitorOn" message. +

        + + 0 The value of this property should never be + returned. +

        + +

        + 1 This property should not be monitored, but it + should be returned as context when a monitored + value changes; e.g. a time stamp. +

        + +

        + 2 Monitor this property and call the callback function + when it changes, however, return only this property + in the resultant cdevData object. +

        + +

        + 3 Monitor this property and call the callback function + when it changes and include the value of all + properties whose context is 1 in the resultant + cdevData object. +

        + +

        +
        + + 5. +

        +
        + + Create a cdevCallback object that contains the address of the cdevCallback + function and a void pointer to any user argument that should be provided to the + callback function. +

        +
        + + 6. +

        +
        + + Use the sendCallback message to submit the message to the device. +

        +
        + + 7. +

        +
        + + Evaluate the return value from the specific sendCallback command to determine + if the message was transmitted successful. Any value other than + CDEV_SUCCESS indicates that the message was not transmitted successfully. +

        +
        + + 8. +

        +
        + + Monitor the status returned to the cdevCallbackFunction to determine if the + callback is operating correctly. Any of the following values may be returned in the + status parameter. +

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + CDEV_SUCCESS: +

        +
        + + The value has changed and the new value is + stored in the cdevData parameter. This status is + also generated when the monitorOn command + is initially issued. +

        +
        + + + CDEV_DISCONNECTED: +

        +
        + + The connection has been lost between the + application and the server. +

        +
        + + + CDEV_RECONNECTED: +

        +
        + + The connection between the application and the + server has been re-established and the updated + value is available in the cdevData parameter. +

        +
        + + + CDEV_ERROR: +

        +
        + + The message was not processed successfully. +

        +
        + + + CDEV_INVALIDOBJ: +

        +
        + + Invalid cdev request object used. +

        +
        + + + CDEV_INVALIDARG: +

        +
        + + Invalid argument passed to cdev call. +

        +
        + + + CDEV_INVALIDSVC: +

        +
        + + Wrong service during dynamic loading. +

        +
        + + + CDEV_NOTCONNECTED: +

        +
        + + Not connected to low level network service. +

        +
        + + + CDEV_IOFAILED: +

        +
        + + Low level network service IO failed. +

        +
        + + + CDEV_CONFLICT: +

        +
        + + Conflicts of data types or tags. +

        +
        + + + CDEV_NOTFOUND: +

        +
        + + Cannot find specified data in cdevData. +

        +
        + + + CDEV_TIMEOUT: +

        +
        + + Time out. +

        +
        + + + CDEV_CONVERT: +

        +
        + + cdevData conversion error. +

        +
        + + + CDEV_OUTOFRANGE: +

        +
        + + Value out of range for device attribute. +

        +
        + + + CDEV_NOACCESS: +

        +
        + + Insufficient access to perform request. +

        +
        + + + CDEV_ACCESSCHANGED: +

        +
        + + Change in access permission of device. +

        +
        +
        + + 9. +

        +
        + + Because the monitorOn command is a single message that may generate many + responses, the developer may have difficulty in determining when the last reply + has been received. In order to accomodate this, the developer may call the + cdevCallback::isTransactionDone() method to determine if the callback that is + being processed is the last one that is associated with that request. The service + developer is expected to use the cdevCallback::fireCallback method to ensure that + this parameter is set to the proper value. +

        +
        +
        + + + "monitorOff" + Message +

        +
        + + The "monitorOff" verb can be joined with any attribute of a device to form a + "monitorOff" message. This message is tells the cdevDevice to deactivate a + monitorOn command that was previously set on one or more of its attributes. +

        + This message should always be called using the sendCallback method in order to + specify the address of the callback function that was used in creating the monitor. +

        + The service checks the following things to determine which monitor is to be removed. +

        + + + + + + + + + +
        + + + device +

        +
        + + The service will locate all active monitors that + have been placed on the specified device. +

        +
        + + + attribute +

        +
        + + From the list of obtained above, the service will + locate all active monitors on the specified + attribute. +

        +
        + + + function +

        +
        + + From the list obtained above, the service will + locate all active monitors that have the specified + callback function. If this value is NULL, then all + elements from the previous list will be removed. +

        +
        + + + userarg +

        +
        + + From the list obtained above, the service will + locate and remove all monitors that have the + same user argument. If this value is NULL, then + all elements from the previous list will be + removed. +

        +
        + + The following steps should be executed in order to submit a "monitorOff" message. +

        + + + + + + + + + + + +
        + + 1. +

        +
        + + Obtain a pointer to the cdevDevice object for the device that you wish to address. +

        +
        + + 2. +

        +
        + + Create a message string by concatenating the attribute that you wish to address + to the "monitorOff" verb. For instance, to monitor a property of the bdl attribute of a + device, the message string should be: "monitorOn bdl". +

        +
        + + 3. +

        +
        + + Optionally, use the cdevDevice object created in step 1 and the message string + created in step 2 to obtain a pointer to a cdevRequestObject object. +

        +
        + + 4. +

        +
        + + Create a cdevCallback object that contains the address of the cdevCallback + function and a void pointer to the user argument that was originally provided to the + monitorOn message. +

        +
        + + 5. +

        +
        + + Use the sendCallback message to submit the message to the device. +

        +
        + + The following example illustrates how to use the "monitorOn" and "monitorOff" to + install and remove monitors. This example also demonstrates the to correct way to + utilize the cdevCallback function. +

        + +

        + + Figure 5: + + Default behavior of the "monitorOn" and "monitorOff" messages +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevRequestObject.h>
        +#include <cdevData.h>
        +#include <cdevCallback.h>
        + 
        +// ****************************************************************
        +// * This is the callback function that will be executed each time
        +// * one of my monitored values changes.
        +// ****************************************************************
        +void callback (int status, void * userarg, 
        +             cdevRequestObject & req, cdevData & data)
        +   {
        +   switch(status)
        +      {
        +      // *********************************************************
        +      // * If I receive one of these message then I know that 
        +      // * updated data is available in the cdevData object.
        +      // *********************************************************
        +      case CDEV_SUCCESS:
        +      case CDEV_RECONNECTED:
        +         // ******************************************************
        +         // * I will call the getType method to determine if the
        +         // * value attribuite is present in the cdevData object.
        +         // * If it is, then I will known that it is responsible
        +         // * for triggering this callback.
        +         // ******************************************************
        +         if(data.getType("value")!=CDEV_INVALID)
        +            {         
        +            // **************************************************
        +            // * I have specified that I wanted status and 
        +            // * severity to be returned as context whenever the 
        +            // * value property has changed.  Therefore, I will 
        +            // * output all of these properties.
        +            // **************************************************
        +            double * valPtr;
        +            char   * statPtr;
        +            char   * sevPtr;
        +            data.find("value",    (void *&)valPtr);
        +            data.find("status",   (void *&)statPtr);
        +            data.find("severity", (void *&)sevPtr);
        +            printf("Val:%f, status:%s, severity:%s", 
        +                  *valPtr, statPtr, sevPtr);
        +            }
        +         // ******************************************************
        +         // * I will call the getType method of the cdevData 
        +         // * object to determine if the controlHigh property is
        +         // * present. If it is, I will know that it triggered
        +         // * this callback.    
        +         // ******************************************************
        +			
        +
        +
        + +

        + + Figure 5: + Default behavior of the "monitorOn" and "monitorOff" messages (continued) +
        + + + +
        + + +
        
        +         else if(getType("controlHigh")!=CDEV_INVALID)
        +            {
        +            double * controlPtr;
        +            data.find("controlHigh", (void *&) controlPtr);
        +            printf("Control High is now %f\\n", *controlPtr);
        +            }
        +      break;
        + 
        +      // *********************************************************
        +      // * This status indicates that the connection has been lost
        +      // * between the application and the server.
        +      // *********************************************************
        +      case CDEV_DISCONNECTED:
        +         fprintf(stderr, "Connection lost to server\\n");
        +         break;
        + 
        +      // *********************************************************
        +      // * This status indicates that an error occurred while 
        +      // * installing or operating the monitor.
        +      // *********************************************************
        +      case CDEV_ERROR:
        +         fprintf(stderr, "Error while monitoring");
        +         break;
        +      }
        +   }
        + 
        +void main()
        +   {
        +   cdevSystem        * system;
        +   cdevDevice        * dev;
        +   cdevRequestObject * req;
        +   cdevData            ctx;
        + 
        +   // ***********************************************************
        +   // * Construct a cdevCallback object that has a pointer to the
        +   // * cdevCallback function and a NULL user argument.
        +   // ***********************************************************
        +   cdevCallback cb(callback, NULL);
        + 
        +   // ***********************************************************
        +   // * Obtain a pointer to the default cdevSystem in order to
        +   // * accomodate polling.
        +   // ***********************************************************
        +   system = &cdevSystem::defaultSystem();
        + 
        +   // ***********************************************************
        +   // * Obtain a pointer to the cdevDevice MQB1S01
        +   // ***********************************************************
        +   dev = cdevDevice::attachPtr("MQB1S01");
        + 
        +   // ***********************************************************
        +   // * Obtain a pointer to the cdevRequestObject for the
        +   // * "monitorOff bdl" message on device "MQB1S01".
        +   // ***********************************************************
        +   req = dev->getRequestObject("MQB1S01", "monitorOn bdl");
        +			
        +
        +
        + +

        + + Figure 5: + Default behavior of the "monitorOn" and "monitorOff" messages (continued) +
        + + + +
        + + +
        
        + 
        +   // ###########################################################
        +   // # Setup the context to indicate the data that should be 
        +   // # returned whenever one of the values is changed.
        +   // ###########################################################
        + 
        +   // ***********************************************************
        +   // * Any time the "value" property changes, I want to receive
        +   // * the "status" and "severity" properties.
        +   // ***********************************************************
        +   ctx.insert("value", 3);
        +   ctx.insert("status", 1);
        +   ctx.insert("severity", 1);
        + 
        +   // ***********************************************************
        +   // * Any time the "controlhigh" property changes, I only want
        +   // * to receive its new value.
        +   // ***********************************************************
        +   ctx.insert("controlHigh", 2);
        + 
        +   // ***********************************************************
        +   // * Set the context of the cdevRequestObject to the new 
        +   // * context.
        +   // ***********************************************************
        +   req->setContext(ctx);
        + 
        +   // ************************************************************
        +   // * Submit the "monitorOn" message using the sendCallback
        +   // * method of the cdevRequestObject.
        +   // ************************************************************
        +   if(req->sendCallback(NULL, cb)==CDEV_SUCCESS)
        +      {
        +      // ********************************************************
        +      // * Pend for 60 second.
        +      // ********************************************************
        +      system->pend(60.0);
        +      
        +      // ********************************************************
        +      // * Send a "monitorOff bdl" message to disable the monitor
        +      // * that was just installed.
        +      // ********************************************************
        +      dev->sendCallback("monitorOff bdl", NULL, cb);
        +      }
        +   else fprintf(stderr, "Failed to install monitor\\n");
        +   }
        +			
        +
        +
        + +

        +
        + + 9. +

        +
        + + + demoService: A Sample cdev Service +

        +
        + + + Overview of the + demoService +

        +
        + + The demoService service is a sample cdev service that operates on a virtual control + system. For the purposes of this illustration, this control system is represented by a + group of demoDevice classes. +

        +
        + + + The demoDevice + Object +

        +
        + + Each demoDevice object represents a single device that has two value attributes: + BDL and VAL. Each of these two attributes has the following properties: +

        + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + value: This is the double precision value of the attribute. +

        +
        + + 2. +

        +
        + + status: This is the current status of the attribute, it may have one of the + following values. +

        + + 0 No error. +

        + 1 The value property is below the range specified by the + controlLow property. +

        + 2 The value property is below the range specified by the + alarmLow property. +

        + 3 The value property is above the range specified by the + alarmHigh property. +

        + 4 The value property is above the range specified by the + controlHigh property. +

        + +

        +
        + + 3. +

        +
        + + severity: This is a string that describes the current status of the attribute. +

        +
        + + 4. +

        +
        + + units: These are the units that are used to express the value properties + of the attribute. +

        +
        + + 5. +

        +
        + + controlLow: This is a double precision number reflecting the minimum physical + value for the attribute. +

        +
        + + 6. +

        +
        + + controlHigh: This is a double precision number reflecting the maximum + physical value for the attribute. +

        +
        + + 7. +

        +
        + + alarmLow: This is a double precision number reflecting the lower alarm + threshold for this attribute. +

        +
        + + 8. +

        +
        + + alarmHigh: This is a double precision number reflecting the upper alarm + threshold for this attribute. +

        +
        + + The complete source code for the demoDevice class and its instances are provided in + the following source code examples. +

        + +

        + + Figure 6: + + demoDevice.h: Header file for devices used by the demoService +
        + + + +
        + + +
        
        +#ifndef _DEMO_DEVICE_H_
        +#define _DEMO_DEVICE_H_
        + 
        +#include <stdlib.h>
        + 
        +enum demoStatus { 
        +   NORMAL=0, ERROR_LOW, ALARM_LOW, ALARM_HIGH, ERROR_HIGH };
        + 
        +// ****************************************************************
        +// * struct demoAttrib:
        +// *   The demoAttrib structure contains all of the properties 
        +// *   that are supported by a single attribute of a demoDevice
        +// *   structure.
        +// ****************************************************************
        +typedef struct
        +   {
        +   char   name     [32];   // Name of this attribute
        +   char   units    [32];   // Units that value is measured in
        +   double   value;   // Value of the attribute
        +   double   controlLow;   // Minimum value of the attribute
        +   double   controlHigh;   // Maximum value of the attribute
        +   double   alarmLow;   // Minimum value resulting in alarm
        +   double   alarmHigh;   // Maximum value resulting in alarm
        +   } demoAttrib;
        +   
        + 
        +// ****************************************************************
        +// * class demoDevice:
        +// *   The demoDevice structure is a crude representation of a
        +// *   control system device.  Although these devices are not
        +// *   attached to physical hardware, they support the concept of
        +// *   value, units, control limits, display limits, alarm limits,
        +// *   alarm status and alarm severity.
        +// *
        +// *   The demoService is designed to provide a cdev interface to
        +// *   these devices.  Note that this device knows nothing about
        +// *   cdev or any component of cdev.  It is entirely the
        +// *   responsibility of cdev to accomodate the device with little
        +// *   or no alterations.
        +// ****************************************************************
        +class demoDevice
        +{
        +private:
        +   char       *   name;   // Name of this device
        +   demoAttrib *   attr;   // List of embedded attributes
        +   size_t   count;   // Number of embedded attributes
        + 
        +public:
        +   demoDevice ( char * Name, demoAttrib * Attr, size_t Count );
        +   ~demoDevice( void );
        +   
        +   char * getName   ( void );   // Get name of the device
        +   size_t getCount   ( void );   // Get number of attributes
        +   int    getIndex   ( char *Attr );   // Get index of Attr
        +   char * getUnits   ( int idx );   // Get units of measure
        +			
        +
        +
        + +

        + + Figure 6: + demoDevice.h: (continued) +
        + + + +
        + + +
        
        +   double getValue   ( int idx );   // Get attribute value
        +   double getControlLow   ( int idx );   // Get min control value
        +   double getControlHigh   ( int idx );   // Get max control value
        +   double getAlarmLow   ( int idx );   // Get min alarm value
        +   double getAlarmHigh   ( int idx );   // Get max alarm value
        +   demoStatus getStatus   ( int idx );   // Get alarm status
        +   char *     getSeverity   ( int idx );   // Get alarm severity
        + 
        +   int setValue ( int idx, double val );   // Set the attribute value
        +};
        + 
        +// ****************************************************************
        +// * These are the names of the demoDevices that will exists in 
        +// * this demonstration control system.
        +// ****************************************************************
        +extern demoDevice DEVICE0;
        +extern demoDevice DEVICE1;
        +extern demoDevice DEVICE2;
        +extern demoDevice DEVICE3;
        +extern demoDevice DEVICE4;
        + 
        +#endif /* _DEMO_DEVICE_H_ */
        +			
        +
        +
        + +

        + + +

        + +

        + +

        + + Figure 7: + + demoDevice.cc: C++ source for the demoDevice class +
        + + + +
        + + +
        
        +#include <string.h>
        +#include "demoDevice.h"
        + 
        +// ****************************************************************
        +// * demoDevice::demoDevice :
        +// *    This is the constructor for the demoDevice.  It assigns the
        +// * value passed in the Name parameter as the name of the device, 
        +// * and it uses the array provided in the Attr parameter as its 
        +// * list of attributes.  The number of attributes in the array
        +// * should be provided in the Count parameter.
        +// ****************************************************************
        +demoDevice::demoDevice (char *Name, demoAttrib *Attr, size_t Count)
        +   : attr(Attr), count(Count)
        +   {
        +   name = Name?strdup(Name):NULL;
        +   }
        +   
        +// ****************************************************************
        +// * demoDevice::~demoDevice :
        +// *    This is the destructor for the demoDevice, it deletes the name 
        +// * string that was allocated in the constructor.
        +// ****************************************************************
        +			
        +
        +
        + +

        + + Figure 7: + demoDevice.cc: (continued) +
        + + + +
        + + +
        
        +demoDevice::~demoDevice ( void ) 
        +   { 
        +   if(name!=NULL) delete name; 
        +   }
        +   
        +// ****************************************************************
        +// * demoDevice::getName :
        +// *    This function allows the caller to obtain the name of the 
        +// * demoDevice
        +// ****************************************************************
        +char * demoDevice::getName ( void ) 
        +   { 
        +   return name; 
        +   }
        +   
        +// ****************************************************************
        +// * demoDevice::getCount :
        +// *    This function returns the number of attributes in this 
        +// * demoDevice.
        +// ****************************************************************
        +size_t demoDevice::getCount ( void ) 
        +   {
        +   return count;
        +   }
        +   
        +// ****************************************************************
        +// * demoDevice::getIndex :
        +// *    This method allows the caller to obtain the index of a specific
        +// * attribute by name.  If the value returned is less than 0, then 
        +// * the attribute does not exist on this device.
        +// ****************************************************************
        +int demoDevice::getIndex ( char * Attr )
        +   {
        +   for(int i=count-1; i>=0 && strcmp(Attr, attr[i].name)!=0; i--);
        +   return i;   
        +   }
        + 
        +// ****************************************************************
        +// * demoDevice::getUnits :
        +// *    This method returns the units of measure used by the attribute
        +// * at the specified index.  Returns NULL if the index is out of 
        +// * range.
        +// ****************************************************************
        +char * demoDevice::getUnits ( int idx )
        +   {
        +   return (idx>=0 && idx<count)?attr[idx].units:NULL;
        +   }
        +   
        +// ****************************************************************
        +// * demoDevice::getValue :
        +// * Allows the user to obtain the value of the specified attribute. 
        +// * Returns 0 if the attribute is invalid.
        +// ****************************************************************
        +double demoDevice::getValue ( int idx )
        +			
        +
        +
        + +

        + + Figure 7: + demoDevice.cc: (continued) +
        + + + +
        + + +
        
        +   {
        +   return (idx>=0 && idx<count)?attr[idx].value:0.0;
        +   }
        + 
        +// ****************************************************************
        +// * demoDevice::getControlLow :
        +// * Returns the minimum legal value for the device.  Returns -1E300 
        +// * if the attribute is invalid.
        +// ****************************************************************
        +double demoDevice::getControlLow ( int idx )
        +   {
        +   return (idx>=0 && idx<count)?attr[idx].controlLow:-1E300;
        +   }
        +   
        +// ****************************************************************
        +// * demoDevice::getControlHigh :
        +// * Returns the maximum legal value for the device.  Returns 1E300 
        +// * if the attribute is invalid.
        +// ****************************************************************
        +double demoDevice::getControlHigh ( int idx )
        +   {
        +   return (idx>=0 && idx<count)?attr[idx].controlHigh:1E300;
        +   }
        + 
        +// ****************************************************************
        +// * demoDevice::getAlarmLow :
        +// * Returns the minimum legal value for the device.  Returns -1E300 
        +// * if the attribute is invalid.
        +// ****************************************************************
        +double demoDevice::getAlarmLow ( int idx )
        +   {
        +   return (idx>=0 && idx<count)?attr[idx].alarmLow:-1E300;
        +   }
        +   
        + 
        +// ****************************************************************
        +// * demoDevice::getAlarmHigh :
        +// * Returns the maximum legal value for the device.  Returns 1E300 
        +// * if the attribute is invalid.
        +// ****************************************************************
        +double demoDevice::getAlarmHigh ( int idx )
        +   {
        +   return (idx>=0 && idx<count)?attr[idx].alarmHigh:1E300;
        +   }
        + 
        +// ****************************************************************
        +// * demoDevice::getStatus :
        +// * Calculates and returns the alarm status of the attribute at the
        +// * specified index.  Returns NULL if the index is out of range.
        +// ****************************************************************
        +demoStatus demoDevice::getStatus ( int idx ) 
        +   {
        +   demoStatus status = NORMAL;
        +   if(idx>=0 && idx<count)
        +      {
        +			
        +
        +
        + +

        + + Figure 7: + demoDevice.cc: (continued) +
        + + + +
        + + +
        
        +         status = ERROR_LOW;
        +         status = ALARM_LOW;
        +         status = NORMAL;
        +         status = ALARM_HIGH;
        +      else status = ERROR_HIGH;
        +      }
        +   return status;
        +   }
        +   
        +// ****************************************************************
        +// * demoDevice::getSeverity :
        +// *    Calculates and returns the alarm severity of the attribute at 
        +// * the specified index.  Returns NULL if the index is out of 
        +// * range.
        +// ****************************************************************
        +char * demoDevice::getSeverity ( int idx )
        +   {
        +   static char * status[] =
        +      {
        +      "No alarm",
        +      "Attribute value is below its minimum legal boundary",
        +      "Attribute value is at or below its minimum alarm boundary",
        +      "Attribute value is at or above its maximum alarm boundary",
        +      "Attribute value is above its maximum legal boundary"
        +      };
        +   return status[getStatus(idx)];
        +   }
        +   
        +// ****************************************************************
        +// * demoDevice::setValue :
        +// * Allows the user to set the value of the specified attribute. 
        +// * Returns 0 if the attribute was successfully set, otherwise -1.
        +// ****************************************************************
        +int demoDevice::setValue ( int idx, double val )
        +   {
        +   int result = -1;
        +   
        +   if(idx>=0 && idx<count)
        +      {
        +      if(val > attr[idx].controlLow && 
        +         {
        +         attr[idx].value = val;
        +         result = 0;
        +         }
        +      }
        +   return result;
        +   }
        + 
        +			
        +
        +
        + +

        + + Figure 7: + demoDevice.cc: (continued) +
        + + + +
        + + +
        
        +// ****************************************************************
        +// * These are the attribute definitions that will be used to 
        +// * construct the fictitious devices in the demo control system.  
        +// * The values and names used here are inconsequential.
        +// ****************************************************************
        +demoAttrib DEVICE0Attrib [2] =
        +   {
        +   { "VAL", "amps",         0.0, -30.0, 30.0, -20.0, 20.0 },
        +   { "BDL", "gauss-meters", 0.0, -14.0,  7.0, -10.0,  5.0 }
        +   };
        +   
        +demoAttrib DEVICE1Attrib [2] =
        +   {
        +   { "VAL", "amps",         0.0, -20.0, 20.0, -15.0, 15.0 },
        +   { "BDL", "gauss-meters", 0.0, -10.0, 10.0,  -7.5,  7.5 }
        +   };
        +   
        +demoAttrib DEVICE2Attrib [2] =
        +   {
        +   { "VAL", "amps",         0.25, -12.0, 10.0, -9.0,  7.0 },
        +   { "BDL", "gauss-meters", 1.0,  -10.0, 10.0, -7.5,  7.5 }
        +   };
        + 
        +demoAttrib DEVICE3Attrib [2] = 
        +   {
        +   { "VAL", "amps",         1.25, -12.0, 10.0, -9.0,  7.0 },
        +   { "BDL", "gauss-meters", 8.0,  -10.0, 10.0, -7.5,  7.5 }
        +   };
        + 
        +demoAttrib DEVICE4Attrib [2] = 
        +   {
        +   { "VAL", "amps",         11.25, -12.0, 13.0, -9.0, 10.0 },
        +   { "BDL", "gauss-meters",  8.0,  -10.0, 10.0, -7.5,  8.25 }
        +   };
        + 
        +// ****************************************************************
        +// * Instances of the ficticious devices in out control system.
        +// **************************************************************** 
        +demoDevice DEVICE0("DEVICE0", DEVICE0Attrib, 2);
        +demoDevice DEVICE1("DEVICE1", DEVICE1Attrib, 2);
        +demoDevice DEVICE2("DEVICE2", DEVICE2Attrib, 2);
        +demoDevice DEVICE3("DEVICE3", DEVICE3Attrib, 2);
        +demoDevice DEVICE4("DEVICE4", DEVICE4Attrib, 2);
        +			
        +
        +
        + +

        + + +

        +
        + + + The demoService + Object +

        +
        + + The demoService C++ class is derived from the cdevService class. It maintains a list + of references to the devices that are defined in the demoDevice source code. This + class also provides the mechanisms that its request objects will use to communicate + with these devices. +

        +
        + + + The + enqueueTransaction + Method +

        +
        + + The demoService class uses a queueing scheme to manage outbound transaction + objects. Whenever a request object wishes to submit a message to the service, it will + call the service's enqueueTransaction method. This method receives a pointer to the + cdevTranObj object that contains information about the transaction. It also receives a + pointer to a cdevData object that contains any information that the service will need to + complete the request. +

        + Messages passed to the enqueueTransaction method will be stored in an internal + linked-list until the pend or poll methods are called. The pend and poll methods are + responsible for transferring the messages to the processTransaction method. +

        +
        + + + The + processTransaction + Method +

        +
        + + The processTransaction method is where all messages sent to the service are + dispatched to the underlying demoDevice control system. Unlike the pend and poll + methods which restrict their activity to a caller specified period of time, the + processTransaction method operates without regard to time. It will process one + complete message before returning. Because this is a private member function, it may + only be called by methods that exist within the class. +

        +
        + + + The + newDemoService + Function +

        +
        + + This is the service specific loader function for the demoService object. It is called once + by the cdevSystem object in order to instantiate a single instance of the demoService. + If more than one cdevSystem object is used by an application, the newDemoService + function may be called more than once. +

        +
        + + + The cdevSelector + Object +

        +
        + + Each demoService object contains one instance of the cdevSelector class. This object + gives the service a file descriptor that it may provide to the cdevSystem object for use + in the select function. The service may then manipulate the state of the file descriptor + by using the cdevSelector interface to indicate that one of its underlying devices + requires attention. +

        +
        + + + The VERB + Enumeration +

        +
        + + This enumerated type defines a unique integer value for each of the verbs that may be + applied to attributes comprising devices in this service. +

        +
        + + + The ATTR + Enumeration +

        +
        + + This enumerated type defines a unique integer identifier for each of the attributes that + are comprise a device within this service. +

        + +

        + + Figure 8: + + demoService.h: Header file for the demoService class +
        + + + +
        + + +
        
        +#ifndef _DEMO_SERVICE_H_
        +#define _DEMO_SERVICE_H_ 1
        + 
        +#include <cdevService.h>
        +#include <cdevTranObj.h>
        +#include <cdevSelector.h>
        + 
        +// ****************************************************************
        +// * The demoDevice.h file defines the behavior of the demoDevice 
        +// * objects.  These objects are crude representations of control 
        +// * system hardware interfaces.  The structure and operation of 
        +// * these objects are for illustration purposes only, and are 
        +// * significantly less important than the cdev objects. 
        +// ****************************************************************
        +#include <demoDevice.h>
        +			
        +
        +
        + +

        + + Figure 8: + demoService.h: (continued) +
        + + + +
        + + +
        
        +#define DEMO_SERVICE_NAME "demoService"
        + 
        +// ****************************************************************
        +// * Service Loader:
        +// * The first step in building a new service is to construct a 
        +// * service loader function.  This function will allow cdev to 
        +// * dynamically initialize a service by name.   
        +// *   
        +// * The function should adhere to this naming convention...
        +// *     cdevService * newXXX (char * name, cdevSystem * system);
        +// *     Where 'XXX' should be replaced with the name of the 
        +// *     service class with the first character capitalized.
        +// *
        +// * The function should also be declared as 'extern "C"' to allow 
        +// * it to be called and loaded from within an external shared 
        +// * library module.
        +// * 
        +// * This function serves only to construct a new instance of 
        +// * the specified service, and return it to the instanciating 
        +// * cdevSystem object.
        +// ****************************************************************
        +extern "C" cdevService *
        +newDemoService ( char * name, cdevSystem * system );
        + 
        +// ****************************************************************
        +// * demoService:
        +// * This class provides the mechanisms that the cdev system will 
        +// * use to communicate with the demo service.
        +// *   
        +// *    Note that this service is inherited from the cdevService class 
        +// * and receives much of its functionality from that class.
        +// ****************************************************************
        +class demoService : public cdevService
        +{
        +friend class demoRequestObject;
        +public:
        +   // *************************************************************
        +   // * Tags used by the service and its associate classes.
        +   // *************************************************************
        +   static int VALUE_TAG;
        +   static int STATUS_TAG;
        +   static int SEVERITY_TAG;
        +   static int UNITS_TAG;
        +   static int CTRLHIGH_TAG;
        +   static int CTRLLOW_TAG;
        +   static int ALRMHIGH_TAG;
        +   static int ALRMLOW_TAG;
        +   
        +   // *************************************************************
        +   // * demoService::VERB
        +   // *   This is the enumerated list of verbs that are supported by
        +   // *   devices in this service.  
        +   // *************************************************************
        +   enum VERB {
        +      INVALID_VERB=0x00,
        +			
        +
        +
        + +

        + + Figure 8: + demoService.h: (continued) +
        + + + +
        + + +
        
        +      GET         =0x01, // "get"        - obtains a device value
        +      SET         =0x02, // "set"        - sets a device value
        +      VERB_MASK   =0xff     
        +      }; 
        + 
        +   // *************************************************************
        +   // * demoService::ATTR
        +   // * This is a list of the data items that may be operated on    
        +   // * using some or all of the demoService::VERB elements.
        +   // *************************************************************
        +   enum ATTR {
        +      INVALID_ATTR=0x0000,
        +      VAL         =0x0100, // "VAL"      - value of the device
        +      BDL         =0x0200, // "BDL"      - bdl value of the device
        +      ATTR_MASK   =0xff00  
        +      }; 
        + 
        +   // *************************************************************
        +   // * demoService::demoService :
        +   // * This constructor is responsible for performing all service
        +   // * initialization.  Returns nothing.
        +   // *************************************************************
        +   demoService (char * name, 
        +              cdevSystem & system = cdevSystem::defaultSystem());
        +   
        +   // *************************************************************
        +   // * demoService::getFd
        +   // * This function will return the list of file descriptors that 
        +   // * the demoService is using.  This will allow the file 
        +   // * descriptors to be used in global select and poll calls 
        +   // * performed at the cdevSystem class level.
        +   // *
        +   // * Returns CDEV_SUCCESS on success or an enumerated error.
        +   // *************************************************************
        +   int getFd ( int * &fd, int & numFd );
        +   
        +   // *************************************************************
        +   // * demoService::flush :
        +   // * This function flushes all communications buffers that the 
        +   // * service may have open.
        +   // *
        +   // * Returns CDEV_SUCCESS on success or an enumerated error.
        +   // *************************************************************
        +   int flush ( void );
        +   
        +   // *************************************************************
        +   // * demoService::poll :
        +   // * This function polls the file descriptors used by the service
        +   // * until one of them becomes active or a discrete amount of 
        +   // * time has expired.
        +   // *
        +   // * Returns CDEV_SUCCESS on success or an enumerated error.
        +   // *************************************************************
        +   int poll ( void );
        +			
        +
        +
        + +

        + + Figure 8: + demoService.h: (continued) +
        + + + +
        + + +
        
        +   // *************************************************************
        +   // * demoService::pend :
        +   // * Pends until the named file descriptor (or any descriptor
        +   // * if fd = -1) is ready.  Will pend forever if the descriptor 
        +   // * does not become active.
        +   // *
        +   // * Returns CDEV_SUCCESS on success or an enumerated error.
        +   // *************************************************************
        +   int pend ( int fd = -1 );
        + 
        +   // *************************************************************
        +   // * demoService::pend :
        +   // * Pends until the named file descriptor (or any descriptor
        +   // * if fd = -1) is ready.  Will pend for no longer than the 
        +   // * user specified number of seconds.
        +   // *
        +   // *   Returns CDEV_SUCCESS on success or an enumerated error.
        +   // *************************************************************
        +   int pend ( double seconds, int fd = -1 );
        +   
        +   // *************************************************************
        +   // * demoService::getNameServer :
        +   // * This function should obtain the default name server for this 
        +   // * object.  It does nothing for now.
        +   // *************************************************************
        +   int getNameServer(cdevDevice * &ns);
        + 
        +   // *************************************************************
        +   // * demoService::getRequestObject :
        +   // * This is the interface that cdev objects will use to obtain a
        +   // * demoRequestObject object.  The demoRequestObject represents 
        +   // * a combined device/message pair that is associated with the 
        +   // * demoService.
        +   // *
        +   // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
        +   // *************************************************************
        +   int getRequestObject (char * device, char * message,
        +                      cdevRequestObject * &req);
        +   
        +protected:
        +   // *************************************************************
        +   // * demoService::~demoService :
        +   // * The destructor is protected to prevent it from being called
        +   // * directly.  The destructor performs any clean-up or shutdown
        +   // * operations.  Returns nothing.
        +   // *************************************************************
        +   ~demoService ( void );
        +   
        +   // *************************************************************
        +   // * demoService::enqueueTransaction :
        +   // * Allows the caller to place a cdevTranObj object and cdevData
        +   // * object into the outgoing queue.
        +   // *************************************************************
        +   int enqueueTransaction ( cdevTranObj * obj, cdevData * inbound);
        + 
        +			
        +
        +
        + +

        + + Figure 8: + demoService.h: (continued) +
        + + + +
        + + +
        
        +   // *************************************************************
        +   // * demoService::defCallback :
        +   // * This function is a default callback for the service.
        +   // *************************************************************
        +   static void defCallback (int, void *, cdevRequestObject &, 
        +                        cdevData &);
        +private:
        +   // *************************************************************
        +   // * Queue of transaction information.  This queue is used to 
        +   // * manage incoming requests and their associated data.  It is a 
        +   // * simple single-linked list.  Data hiding is not violated by 
        +   // * the public data in this class, because the entire class is a 
        +   // * private element of the demoService class.  
        +   // * This mini-class maintains a duplicate copy of the inbound 
        +   // * data so that the user is free to delete it.  It also makes a 
        +   // * copy of any pertinent context variables as they existed when 
        +   // * the object was created.
        +   // *************************************************************
        +   class cdevTranNode 
        +   {
        +   public:
        +      cdevTranNode * next;
        +      cdevTranObj  * obj;   
        +      cdevData       inbound;
        +      int            VALUE_CTX;
        +      int            STATUS_CTX;
        +      int            SEVERITY_CTX;
        +      int            UNITS_CTX;
        +      int            CTRLHIGH_CTX;
        +      int            CTRLLOW_CTX;
        +      int            ALRMHIGH_CTX;
        +      int            ALRMLOW_CTX;
        +            
        +      inline cdevTranNode  ( cdevTranObj * Obj, cdevData *Inbound);
        +      inline ~cdevTranNode ( void ) {}
        +   } * transactions;
        + 
        +   // *************************************************************
        +   // * demoService::processTransaction :
        +   // * This function will take a cdevTranObj and will locate the 
        +   // * demoDevice.  It will then interpret the verb and attribute 
        +   // * and will execute the correct command on the demoDevice.
        +   // *
        +   // * Note:   This object is responsible for deleting the 
        +   // *       cdevTranObj after it has been processed.
        +   // *************************************************************
        +   int processTransaction ( demoService::cdevTranNode * node);
        + 
        +   // *************************************************************
        +   // * This is an array of pointer to the demoDevice objects that
        +   // * this service will manipulate.  These object are crude 
        +   // * representations of a hardware device interface.
        +   // *************************************************************
        +   demoDevice *devices[5];
        + 
        +			
        +
        +
        + +

        + + Figure 8: + demoService.h: (continued) +
        + + + +
        + + +
        
        +   // *************************************************************
        +   // * Default cdevCallback object for the service and the request 
        +   // * object
        +   // *************************************************************
        +   cdevCallback callback;
        + 
        +   // *************************************************************
        +   // * The cdevSelector object is used to provide a file 
        +   // * descriptor that the cdevService can use to pend for I/O 
        +   // * events in the absence of any real I/O descriptors.
        +   // *************************************************************   
        +   cdevSelector selector;
        +   int          readfd[1];
        +};
        + 
        + 
        +// ****************************************************************
        +// * demoService::cdevTranNode::cdevTranNode :
        +// *    This is the constructor for the cdevTranNode class.
        +// ****************************************************************
        +demoService::cdevTranNode::cdevTranNode 
        +   ( cdevTranObj * Obj, cdevData * Inbound )
        +   : next(NULL), obj(Obj), VALUE_CTX(1), STATUS_CTX(0), 
        +     SEVERITY_CTX(0), UNITS_CTX(0), CTRLHIGH_CTX(0), 
        +     CTRLLOW_CTX(0), ALRMHIGH_CTX(0), ALRMLOW_CTX(0)
        +   {
        +   // *************************************************************
        +   // * Make a duplicate copy of the inbound data
        +   // *************************************************************
        +   if(Inbound!=NULL) inbound = *Inbound;
        + 
        +   // *************************************************************
        +   // * Extract the pertinent context values.  Note that I am using 
        +   // * the tag values defined in the service for speed, however, I 
        +   // * could simply use the character string equivalents for 
        +   // * simplicity.
        +   // *************************************************************
        +   if(obj!=NULL)
        +      {
        +      cdevData    & context = obj->reqObj_->getContext();
        +      context.get(demoService::VALUE_TAG,    &VALUE_CTX);
        +      context.get(demoService::STATUS_TAG,   &STATUS_CTX);
        +      context.get(demoService::SEVERITY_TAG, &SEVERITY_CTX);
        +      context.get(demoService::UNITS_TAG,    &UNITS_CTX);
        +      context.get(demoService::CTRLHIGH_TAG, &CTRLHIGH_CTX);
        +      context.get(demoService::CTRLLOW_TAG,  &CTRLLOW_CTX);
        +      context.get(demoService::ALRMHIGH_TAG, &ALRMHIGH_CTX);
        +      context.get(demoService::ALRMLOW_TAG,  &ALRMLOW_CTX);
        +      }
        +   }
        + 
        +#endif /* _DEMO_SERVICE_H_ */
        + 
        +			
        +
        +
        + +

        + + Figure 9: + + demoService.cc: Source code for the demoService class +
        + + + +
        + + +
        
        +#include <stdarg.h>
        +#include <cdevSystem.h>
        +#include <cdevTranObj.h>
        +#include <cdevClock.h>
        +#include <demoService.h>
        +#include <demoRequestObject.h>
        + 
        +// ****************************************************************
        +// * newDemoService:
        +// * This function is called by cdev to perform the initial 
        +// * instanciation of a demo device service.  This function is used 
        +// * to perform dynamic name resolution for the services that are 
        +// * specified within the DDL file or the name server.
        +// ****************************************************************
        +cdevService * newDemoService ( char * name, cdevSystem * system )
        +   {
        +   return new demoService(name, *system);
        +   }
        +   
        +// ****************************************************************
        +// * demoService::demoService :
        +// * This constructor is responsible for performing all service
        +// * initialization.  Returns nothing.
        +// ****************************************************************
        +demoService::demoService ( char * name, cdevSystem & system) 
        +   : cdevService (name, system), transactions(NULL), 
        +     callback    (defCallback, NULL)
        +   {
        +   // ************************************************************
        +   // * Obtain the values of the static tags used by this service
        +   // ************************************************************
        +   cdevData::tagC2I("value",       &VALUE_TAG);
        +   cdevData::tagC2I("status",      &STATUS_TAG);
        +   cdevData::tagC2I("severity",    &SEVERITY_TAG);
        +   cdevData::tagC2I("units",       &UNITS_TAG);
        +   cdevData::tagC2I("controlHigh", &CTRLHIGH_TAG);
        +   cdevData::tagC2I("controlLow",  &CTRLLOW_TAG);
        +   cdevData::tagC2I("alarmHigh",   &ALRMHIGH_TAG);
        +   cdevData::tagC2I("alarmLow",    &ALRMLOW_TAG);
        + 
        +   // ************************************************************
        +   // * At this point, I will transfer pointers to the external 
        +   // * demoDevice objects into my array of demoDevice pointers.
        +   // *************************************************************
        +   devices[0] = &DEVICE0;
        +   devices[1] = &DEVICE1;
        +   devices[2] = &DEVICE2;
        +   devices[3] = &DEVICE3;
        +   devices[4] = &DEVICE4;
        +   }   
        + 
        +// ****************************************************************
        +// * demoService::~demoService :
        +// * The destructor is protected to prevent it from being called
        +// * directly.  The destructor performs any clean-up or shutdown
        +			
        +
        +
        + +

        + + Figure 9: + demoService.cc: (continued) +
        + + + +
        + + +
        
        +// * operations.  Returns nothing.
        +// ****************************************************************
        +demoService::~demoService ( void )
        +   {
        +   // *************************************************************
        +   // * Delete all outstanding transaction object nodes.  Note that 
        +   // * typically a transaction object should not be deleted until 
        +   // * after it has been processed, because a group object may be 
        +   // * waiting on it. However, the removeFromGrps method will 
        +   // * remove the transaction object from any groups that may be 
        +   // * waiting for it.
        +   // *************************************************************
        +   while(transactions != NULL)
        +      {
        +      cdevTranNode * node = transactions;
        +      transactions        = node->next;
        +      if(node->obj!=NULL) 
        +         {
        +         if(node->obj->status()!=-1) node->obj->removeFromGrps();
        +         delete node->obj;
        +         }
        +      delete node;
        +      }
        +   }   
        +   
        +// ****************************************************************
        +// * demoService::getFd
        +// * This function will return the list of file descriptors that the
        +// * demoService is using.  This will allow the file descriptors to
        +// * be used in global select and poll calls performed at the 
        +// * cdevSystem class level.
        +// *
        +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
        +// ****************************************************************
        +int demoService::getFd ( int * &fd, int & numFd )
        +   {
        +   readfd[0] = selector.readfd();
        +   fd        = readfd;
        +   numFd     = 1;
        +   return CDEV_SUCCESS;
        +   }   
        + 
        + 
        +// ****************************************************************
        +// * demoService::flush :
        +// * This function flushes all communications buffers that the 
        +// * service may have open.
        +// * Returns CDEV_SUCCESS on success or an enumerated error.
        +// * Note: This service does not use communications buffers.
        +// ****************************************************************
        +int demoService::flush ( void )
        +   {
        +   return CDEV_SUCCESS;
        +   }
        + 
        +			
        +
        +
        + +

        + + Figure 9: + demoService.cc: (continued) +
        + + + +
        + + +
        
        +// ****************************************************************
        +// * demoService::poll :
        +// * This function submits a pend request that is short enough to 
        +// * allow only one cdevTranObj to be dequeued and submitted to the 
        +// * demoDevice for processing.
        +// * Returns CDEV_SUCCESS on success or an enumerated error.
        +// ****************************************************************
        +int demoService::poll ( void )
        +   {
        +   return pend(0.0001);
        +   }   
        + 
        +// ****************************************************************
        +// * demoService::pend :
        +// * This function will process all of the cdevTranObj messages that 
        +// * are residing in the queue.
        +// * Returns CDEV_SUCCESS on success or an enumerated error.
        +// ****************************************************************
        +int demoService::pend ( int )
        +   {
        +   while(transactions != NULL)
        +      {
        +      cdevTranNode * node = transactions;
        +      transactions = node->next;
        +      processTransaction (node);
        +      }
        +   selector.purge();
        +   return CDEV_SUCCESS;
        +   }
        + 
        +// ****************************************************************
        +// * demoService::pend :
        +// * Pends until the named file descriptor (or any file descriptor
        +// * if fd = -1) is ready.  Will pend for no longer than the user
        +// * specified number of seconds.
        +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
        +// ****************************************************************
        +int demoService::pend ( double seconds, int )
        +   {
        +   cdevTimeValue t(seconds);
        +   cdevClock timer;
        +   
        +   timer.schedule(NULL, t);
        + 
        +   while(transactions!=NULL && !timer.expired())
        +      {
        +      cdevTranNode * node = transactions;
        +      transactions        = node->next;
        +      processTransaction(node);
        +      selector.removeEvent();
        +      }
        + 
        +   if(transactions==NULL) selector.purge();
        +   return CDEV_SUCCESS;
        +   }
        +			
        +
        +
        + +

        + + Figure 9: + demoService.cc: (continued) +
        + + + +
        + + +
        
        +// ****************************************************************
        +// * demoService::getRequestObject :
        +// * This is the interface that cdev objects will use to obtain a
        +// * demoRequestObject object.  The demoRequestObject represents a 
        +// * combined device and message pair that is associated with the 
        +// * demoService.
        +// *
        +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
        +// ****************************************************************
        +int demoService::getRequestObject ( char * device, char * message, 
        +                              cdevRequestObject * &req)
        +   {
        +   req = new demoRequestObject (device, message, system_);
        +   return (req ? CDEV_SUCCESS : CDEV_ERROR);
        +   }
        + 
        +// ****************************************************************
        +// * demoService::enqueueTransaction :
        +// * Allows the caller to place a cdevTranObj object and cdevData
        +// * object into the outgoing queue.  This function also calls the 
        +// * selector.insertEvent() method to activate the file descriptor.
        +// ****************************************************************
        +int demoService::enqueueTransaction ( cdevTranObj * obj, 
        +                                cdevData * inbound )
        +   {
        +   int result = CDEV_SUCCESS;
        +   
        +   if(obj!=NULL)
        +      {
        +      cdevTranNode * node = transactions, * prev = NULL;
        +      while(node!=NULL)
        +         {
        +         prev = node;
        +         node = prev->next;
        +         }
        +      node = new cdevTranNode(obj, inbound);
        +      if(prev==NULL) transactions = node;
        +      else           prev->next   = node;
        +      selector.insertEvent();
        +      }
        +   else result = CDEV_INVALIDARG;
        + 
        +   return result;
        +   }   
        + 
        +// ****************************************************************
        +// * demoService::processTransaction :
        +// * This function will take a cdevTranNode and will locate the 
        +// * device associated with it.  It will then interpret the verb and 
        +// * attribute and will execute the correct command on the device.
        +// *
        +// * Note:   This object is responsible for deleting the cdevTranNode 
        +// * after it has been processed.
        +// ****************************************************************
        +int demoService::processTransaction ( cdevTranNode * node )
        +			
        +
        +
        + +

        + + Figure 9: + demoService.cc: (continued) +
        + + + +
        + + +
        
        +   {
        +   cdevTranObj       * obj    = node->obj;
        +   demoRequestObject * reqObj = 
        +      obj?(demoRequestObject *)obj->reqObj_:NULL;
        +   cdevData          * out    = 
        +      obj?obj->resultData_:NULL;
        +   char              * name   = 
        +      obj?(char *)obj->reqObj_->device().name():NULL;
        +   int                 result = CDEV_SUCCESS;
        +   int                 idx    = 0;
        +   cdevData            data;
        +      
        +   // *************************************************************
        +   // * Ensure that if the obj is valid it has a valid cdevData 
        +   // * object for its result.
        +   // *************************************************************
        +   if(obj!=NULL && obj->resultData_==NULL) obj->resultData_=&data;
        +   out = obj?obj->resultData_:NULL;
        +   
        +   // *************************************************************
        +   // * Ensure that a valid transaction object was submitted.  
        +   // * Remembering to produce an error that the user can catch.
        +   // *************************************************************
        +   if(obj==NULL) result=
        +      reqObj->emitError(CDEV_INVALIDARG, "service");
        +   
        +   // *************************************************************
        +   // * Test to ensure that the device name specified is valid and 
        +   // * obtain the index to the demoDevice in the array.  A better
        +   // * implementation might cache a pointer to the specific device
        +   // * within the demoRequestObject.
        +   // *************************************************************
        +   else if(strncmp(reqObj->device().name(), "DEVICE", 6)!=0 ||
        +      (idx = atoi(reqObj->device().name()+6))<0  || idx > 9)
        +      {
        +      result = reqObj->emitError(CDEV_INVALIDSVC, "service");
        +      }
        + 
        +   // *************************************************************
        +   // * Process the specific message.
        +   // *************************************************************
        +   else if(result==CDEV_SUCCESS)
        +      {
        +      int attr = -1;
        + 
        +      // *********************************************************
        +      // * Obtain the index of the attribute within the demoDevice
        +      // *********************************************************
        +      if((reqObj->command() & ATTR_MASK)==VAL) 
        +         attr=devices[idx]->getIndex("VAL");
        + 
        +      else if((reqObj->command() & ATTR_MASK)==BDL)
        +         attr=devices[idx]->getIndex("BDL");
        +         
        +      switch(reqObj->command())
        +			
        +
        +
        + +

        + + Figure 9: + demoService.cc: (continued) +
        + + + +
        + + +
        
        +         {
        +         // *****************************************************
        +         // * "get VAL" || "get BDL" messages
        +         // *    This will populate the outbound cdevData object
        +         // *   with all of the context items that were in 
        +         // *   place when the transaction object was created.
        +         // *****************************************************
        +         case GET         | VAL:
        +         case GET         | BDL:
        +         if(node->VALUE_CTX)       
        +            out->insert(VALUE_TAG, 
        +                      devices[idx]->getValue(attr));
        +         if(node->STATUS_CTX)      
        +            out->insert(STATUS_TAG,
        +                      devices[idx]->getStatus(attr));
        +         if(node->SEVERITY_CTX)    
        +            out->insert(SEVERITY_TAG, 
        +                      devices[idx]->getSeverity(attr));
        +         if(node->UNITS_CTX)       
        +            out->insert(UNITS_TAG, 
        +                      devices[idx]->getUnits(attr));
        +         if(node->CTRLLOW_CTX)  
        +            out->insert(CTRLLOW_TAG, 
        +                      devices[idx]->getControlLow(attr));
        +         if(node->CTRLHIGH_CTX) 
        +            out->insert(CTRLHIGH_TAG, 
        +                      devices[idx]->getControlHigh(attr));
        +         if(node->ALRMLOW_CTX)    
        +            out->insert(ALRMLOW_TAG, 
        +                      devices[idx]->getAlarmLow(attr));
        +         if(node->ALRMHIGH_CTX)   
        +            out->insert(ALRMHIGH_TAG, 
        +                      devices[idx]->getAlarmHigh(attr));
        +         break;         
        + 
        +         // *****************************************************
        +         // * "set VAL" || "set BDL" message.  These messages
        +         // * will allow the caller to set the current value of 
        +         // * the device.  This section ensures that an error
        +         // * is emitted if the operation fails.
        +         // *****************************************************
        +         case SET         | VAL:
        +         if(node->inbound.getType(VALUE_TAG)==CDEV_DOUBLE) 
        +            {
        +            double val;
        +            size_t elems = 0;
        +            
        +            node->inbound.getElems(VALUE_TAG, &elems);
        +            if(elems==1 && 
        +               node->inbound.get(VALUE_TAG, &val)==CDEV_SUCCESS)
        +               {
        +               if(devices[idx]->setValue(attr, val)==0)
        +                  {
        +                  result = CDEV_SUCCESS;
        +                  }
        +			
        +
        +
        + +

        + + Figure 9: + demoService.cc: (continued) +
        + + + +
        + + +
        
        +               else 
        +                  {
        +                  system_.reportError
        +                     (2, demoService::name(), *reqObj, 
        +                     "Value out of range for this device\\n",); 
        +                  result = CDEV_INVALIDARG;
        +                  }
        +               }
        +            else result = 
        +               reqObj->emitError(CDEV_CONFLICT, "service");
        +            }
        +         else result = 
        +            reqObj->emitError(CDEV_INVALIDARG, "service");
        +         break;
        +                     
        +         // *****************************************************
        +         // * Invalid combination of verb and attribute
        +         // *****************************************************
        +         default:
        +         result = reqObj->emitError(CDEV_ERROR, "service");
        +         break;
        +         }
        + 
        +      // ********************************************************
        +      // * Fire the user specified callback function to give the
        +      // * user the result.
        +      // ********************************************************
        +      if(obj->userCallback_!=NULL)
        +         {
        +         (*(obj->userCallback_->callbackFunction()))
        +            (result==CDEV_SUCCESS?CDEV_SUCCESS:CDEV_ERROR,
        +             obj->userCallback_->userarg(),
        +             *reqObj,
        +             *out);
        +         }
        +      }
        + 
        +   // ************************************************************
        +   // * Delete the cdevTranNode object.
        +   // ************************************************************
        +   if(node!=NULL)
        +      {
        +      if(node->obj!=NULL)
        +         {
        +         node->obj->removeFromGrps();
        +         delete node->obj;
        +         }
        +      delete node;
        +      }
        + 
        +   // ************************************************************
        +   // * Return the result.
        +   // ************************************************************
        +   return result;
        +   }
        +			
        +
        +
        + +

        + + Figure 9: + demoService.cc: (continued) +
        + + + +
        + + +
        
        +// ****************************************************************
        +// * demoService::defCallback :
        +// * This function is a default callback function for the service.
        +// ****************************************************************
        +void demoService::defCallback ( int, void *, cdevRequestObject &, 
        +                           cdevData &)
        +   {
        +   }
        +			
        +
        +
        + +

        + + +

        +
        + + + The + demoRequestObject + Object +

        +
        + + The demoRequestObject C++ class is derived from the cdevRequestObject class. + When the caller uses the cdevDevice object to submit a supported message to one of + the demoDevices, a demoRequestObject is created. This object defines the send, + sendNoBlock and sendCallback methods that are used to submit messages to the + demoService object. This request object restricts itself to using the + enqueueTransaction method of the demoService object to submit messages. A real + implementation might precalculate and cache many of the data variables and pointers + within the request object. These variable can be retrieved by the service during + successive executions of the message. +

        + +

        + + Figure 10: + + demoRequestObject.h: Header file for the demoRequestObject class +
        + + + +
        + + +
        
        +#ifndef _DEMO_REQUEST_OBJECT_H_
        +#define _DEMO_REQUEST_OBJECT_H_
        + 
        +#include <cdevTranObj.h>
        +#include <cdevGroup.h>
        +#include <cdevErrCode.h>
        +#include <demoService.h>
        + 
        +// ****************************************************************
        +// * class demoRequestObject:
        +// * The demoRequestObject class provides the interface for sending 
        +// * messages to a demoDevice.  All device/message commands are 
        +// * routed 
        +// * through a demoRequestObject either directly or indirectly.
        +// *   
        +// * Note that this object is inherited from the standard 
        +// * cdevRequestObject and derives most of its functionality from 
        +// * that class.
        +// ****************************************************************
        +class demoRequestObject : public cdevRequestObject 
        +{
        +public:
        +   // ************************************************************
        +   // * demoRequestObject::demoRequestObject :
        +   // * This constructor initializes a device/message combination
        +   // * associated with a demoDevice.  Returns nothing.
        +   // ************************************************************
        +   demoRequestObject ( char * device, char * message, 
        +      cdevSystem & system=cdevSystem::defaultSystem());
        +			
        +
        +
        + +

        + + Figure 10: + demoRequestObject.h: (continued) +
        + + + +
        + + +
        
        +   // *************************************************************
        +   // * demoRequestObject::~demoRequestObject :
        +   // * This destructor performs any deallocation operations
        +   // * necessary, prior to the destruction of the object.
        +   // * Returns nothing.
        +   // *************************************************************
        +   ~demoRequestObject ( void ) {}
        +            
        +   // *************************************************************
        +   // * demoRequestObject::send : 
        +   // * The send interface is used to provide synchronous I/O with 
        +   // * the service.
        +   // *
        +   // * Returns CDEV_SUCCESS on success or an enumerated error.
        +   // *************************************************************
        +   int send ( cdevData & in, cdevData & out ) 
        +      { return send(&in, &out); }
        +   int send ( cdevData * in, cdevData & out ) 
        +      { return send(in, &out);  }
        +   int send ( cdevData & in, cdevData * out ) 
        +      { return send(&in, out);  }
        +   int send ( cdevData * in, cdevData * out );
        + 
        +   // *************************************************************
        +   // * demoRequestObject::sendNoBlock :
        +   // * The sendNoBlock interface is used in concert with cdevGroup
        +   // * or cdevSystem to execute a series of operations.  
        +   // *
        +   // * Returns CDEV_SUCCESS on success or an enumerated error.
        +   // *************************************************************
        +   int sendNoBlock (cdevData & in, cdevData & out) 
        +      { return sendNoBlock(&in, &out); }
        +   int sendNoBlock (cdevData * in, cdevData & out) 
        +      { return sendNoBlock(in, &out); }
        +   int sendNoBlock (cdevData & in, cdevData * out) 
        +      { return sendNoBlock(&in, out); }
        +   int sendNoBlock (cdevData * in, cdevData * out);
        +      
        +   // *************************************************************
        +   // * demoRequestObject::sendCallback :
        +   // * The sendCallback interface provides asynch communications
        +   // * with the service. 
        +   // *
        +   // *   Returns CDEV_SUCCESS on success or an enumerated error.
        +   // *************************************************************
        +   int sendCallback (cdevData & in, cdevCallback & callback) 
        +      { return sendCallback(&in, callback); }
        +   int sendCallback (cdevData * in, cdevCallback & callback);
        +   
        +   // *************************************************************
        +   // * demoRequestObject::emitError :
        +   // * This method is used to emit a descriptive error if a 
        +   // * failure occurs while transmitting or receiving a message.
        +   // *************************************************************
        +   int emitError ( int result, char * function );
        +			
        +
        +
        + +

        + + Figure 10: + demoRequestObject.h: (continued) +
        + + + +
        + + +
        
        +   // *************************************************************
        +   // * demoRequestObject::className :
        +   // * This function returns the name of the class as a constant 
        +   // * string
        +   // *************************************************************
        +   const char * className ( void ) const 
        +      { 
        +      return "demoRequestObject"; 
        +      }
        +   
        +   // *************************************************************
        +   // * demoRequestObject::command :
        +   // * Returns the combined verb and attr that describe this 
        +   // * demoRequestObject.  This command is used by the demoService
        +   // * to determine the operation that is specified by this object.
        +   // *************************************************************
        +   int command ( void ) { return (verb | attr); }
        + 
        +private:
        +   demoService::VERB verb;
        +   demoService::ATTR attr;
        +   };
        + 
        +#endif /* _DEMO_REQUEST_OBJECT_H_ */
        +			
        +
        +
        + +

        + + +

        + +

        + +

        + + Figure 11: + + demoRequestObject.cc: Source for the demoRequestObject class +
        + + + +
        + + +
        
        +#include <ctype.h>
        +#include <demoRequestObject.h>
        + 
        +// ****************************************************************
        +// * demoRequestObject::demoRequestObject :
        +// * This constructor initializes the internals of a device/message
        +// * pair associated with the compound device.
        +// *
        +// * Returns nothing.
        +// ****************************************************************
        +demoRequestObject::demoRequestObject 
        +   ( char *device, char *message, cdevSystem & system)
        +   : cdevRequestObject(device, message, system), 
        +     verb(demoService::INVALID_VERB), 
        +     attr(demoService::INVALID_ATTR)
        +   {
        +   char Verb[32];
        +   char Attr[32];
        +   char * mptr = message;
        +   char * vptr = Verb;
        +   char * aptr = Attr;
        +			
        +
        +
        + +

        + + Figure 11: + demoRequestObject.cc: (continued) +
        + + + +
        + + +
        
        +   // *************************************************************
        +   // * Extract the verb and the attribute from the message string
        +   // * that was provided by the caller.
        +   // *************************************************************
        +   while(*mptr &&  isspace(*mptr)) mptr++;
        +   while(*mptr && !isspace(*mptr)) *(vptr++) = *(mptr++);
        +   *vptr = 0;
        +   while(*mptr &&  isspace(*mptr)) mptr++;
        +   while(*mptr && !isspace(*mptr)) *(aptr++) = *(mptr++);
        +   *aptr = 0;   
        +   
        +   // *************************************************************
        +   // * Evaluate the Verb element and assign the appropriate value 
        +   // * to the enumerated verb variable.
        +   // *************************************************************
        +   if     (!strcmp(Verb, "get"))        verb = demoService::GET;
        +   else if(!strcmp(Verb, "set"))        verb = demoService::SET;
        +   
        +   // *************************************************************
        +   // * Evaluate the Attr element and assign the appropriate value 
        +   // * to the enumerated attr variable.
        +   // *************************************************************
        +   if     (!strcmp(Attr, "VAL"))        attr = demoService::VAL;
        +   else if(!strcmp(Attr, "BDL"))        attr = demoService::BDL;
        +   }
        +              
        +// ****************************************************************
        +// * demoRequestObject::sendNoBlock :
        +// *    This function allows the caller to submit an asynchronous 
        +// * message to the server for processing.
        +// ****************************************************************   
        +int demoRequestObject::sendNoBlock (cdevData * in, cdevData * out) 
        +   {
        +   // *************************************************************
        +   // * Get a pointer to the demoService to handle this request
        +   // *************************************************************
        +   demoService   * svc  = (demoService *)service_;
        +   
        +   // *************************************************************
        +   // * Construct a cdev transaction object to track this 
        +   // * transaction. Use the disableDeleteCbk method to prevent the
        +   // * cdevCallback object from being deleted by the cdevTranObj.
        +   // *************************************************************
        +   cdevTranObj   * xobj = 
        +      new cdevTranObj(&system_, this, out, &svc->callback);
        +   xobj->disableDeleteCbk();
        + 
        +   // *************************************************************
        +   // * Enqueue the transaction object so that it may be processed 
        +   // * later.  The result returned by the enqueueTransaction 
        +   // * function is returned by this function.
        +   // *************************************************************
        +   return emitError
        +      (svc->enqueueTransaction(xobj, in), "sendNoBlock");
        +   }
        +			
        +
        +
        + +

        + + Figure 11: + demoRequestObject.cc: (continued) +
        + + + +
        + + +
        
        +// ****************************************************************
        +// * demoRequestObject::sendCallback :
        +// *    This function allows the caller to submit an asynchronous 
        +// * message to the server for processing.
        +// ****************************************************************   
        +int demoRequestObject::sendCallback 
        +   (cdevData * in, cdevCallback & callback) 
        +   {
        +   // ************************************************************
        +   // * Get a pointer to the demoService to handle this request
        +   // ************************************************************
        +   demoService    * svc  = (demoService *)service_;
        +   
        +   // ************************************************************
        +   // * Make a cdev transaction object to track this transaction. 
        +   // * Note that the user specified callback object is provided 
        +   // * to the object and that no cdevData object is provided for 
        +   // * the result.
        +   // ************************************************************
        +   cdevTranObj  * xobj = 
        +      new cdevTranObj(&system_, this, NULL, &callback);
        +   xobj->disableDeleteCbk();
        + 
        +   // ************************************************************
        +   // * Enqueue the transaction object so that it may be processed 
        +   // * later.  The result returned by the enqueueTransaction 
        +   // * function is returned by this function.
        +   // ************************************************************
        +   return emitError
        +      (svc->enqueueTransaction(xobj, in), "sendCallback");
        +   }
        + 
        +// ****************************************************************
        +// * demoRequestObject::send : 
        +// *   The send interface is used for synchronous I/O with the service.
        +// *   Returns CDEV_SUCCESS on success or CDEV_ERROR on error.
        +// *   Note:   Do not delete the transaction object, it will be deleted by 
        +// * the processTransaction method in the service.
        +// ****************************************************************
        +int demoRequestObject::send ( cdevData * in, cdevData * out )
        +   {
        +   int           result = CDEV_SUCCESS;
        +   cdevTranObj * xobj;
        + 
        +   // *************************************************************
        +   // * Get a pointer to the demoService to handle this request
        +   // *************************************************************
        +   demoService * svc = (demoService *)service_;
        +   
        +   // *************************************************************
        +   // * Construct a group object that can be used to pend for the 
        +   // * completion of the send event.
        +   // *************************************************************
        +   cdevGroup group(DEFAULT_BLOCK_SIZE, system());
        +			
        +
        +
        + +

        + + Figure 11: + demoRequestObject.cc: (continued) +
        + + + +
        + + +
        
        +   // *************************************************************
        +   // * Start the group prior to creating the transaction object.
        +   // *************************************************************
        +   group.start();
        +   
        +   // *************************************************************
        +   // * Construct a cdev transaction object to track this 
        +   // * transaction. Note that the callback object that exists 
        +   // * within the service is specified as the callback object for 
        +   // * this transaction.
        +   // *************************************************************
        +   xobj = new cdevTranObj(&system_, this, out, &svc->callback);
        +   xobj->disableDeleteCbk();
        + 
        +   // *************************************************************
        +   // * End the group and prepare to pend for the completion of the 
        +   // * task.
        +   // *************************************************************
        +   group.end();
        +   
        +   // *************************************************************
        +   // * Enqueue the transaction object so that it may be processed 
        +   // * later.
        +   // *************************************************************
        +   if((result=svc->enqueueTransaction(xobj, in))==CDEV_SUCCESS)
        +      {
        +      // *********************************************************
        +      // * Pend for a period of not more than 5 seconds, or until
        +      // * the message has been completed.
        +      // *********************************************************
        +      result = group.pend(5.0);
        +      }
        +   
        +   // *************************************************************
        +   // * Use the reportError function to report an error if one 
        +   // * occurred.
        +   // *************************************************************
        +   return emitError(result, "send");
        +   }
        + 
        +// ****************************************************************
        +// * demoRequestObject::emitError :
        +// * This method is used to emit a descriptive error if a failure 
        +// * occurs while transmitting or receiving a message.
        +// ****************************************************************
        +int demoRequestObject::emitError ( int result, char * function )
        +   {
        +   switch(result)
        +      {
        +      case CDEV_SUCCESS:
        +      system().reportError(CDEV_SEVERITY_INFO, service().name(), 
        +         *this, "%s operation successful\\n", function); 
        +      break;
        +			
        +
        +
        + +

        + + Figure 11: + demoRequestObject.cc: (continued) +
        + + + +
        + + +
        
        +      case CDEV_INVALIDOBJ:
        +      system().reportError(CDEV_SEVERITY_ERROR, service().name(), 
        +         *this, "Invalid object detecting in %s operation\\n", 
        +         function); 
        +      break;
        +      
        +      case CDEV_INVALIDARG:
        +      system().reportError(CDEV_SEVERITY_ERROR, service().name(), 
        +         *this, 
        +         "Invalid argument for \\"%s\\" message in %s operation\\n", 
        +         message(), function); 
        +      break;
        +      
        +      case CDEV_INVALIDSVC:
        +      system().reportError(CDEV_SEVERITY_SEVERE, service().name(), 
        +         *this, "Wrong service loaded during dynamic loading\\n"); 
        +      break;
        +      
        +      case CDEV_NOTCONNECTED:
        +      system().reportError(CDEV_SEVERITY_ERROR, service().name(), 
        +         *this, "Network connection error in %s operation\\n",
        +         function);
        +      break;
        +      
        +      case CDEV_IOFAILED:
        +      system().reportError(CDEV_SEVERITY_ERROR, service().name(), 
        +         *this, "I/O failure during %s operation\\n", function);
        +      break;
        +      
        +      case CDEV_CONFLICT:
        +      system().reportError(CDEV_SEVERITY_WARN, service().name(), 
        +      *this, 
        +      "Data type provided is inconsistent with \\"%s\\" message\\n",
        +      message());
        +      break;
        +      
        +      case CDEV_NOTFOUND:
        +      system().reportError(CDEV_SEVERITY_WARN, service().name(), 
        +      *this,
        +      "Tagged data item missing from cdevData in %s operation\\n",
        +      function);
        +      break;
        +      
        +      case CDEV_TIMEOUT:
        +      system().reportError(CDEV_SEVERITY_WARN, service().name(), 
        +         *this,
        +         "Timed-out while waiting for response in %s operation\\n",
        +         function);
        +      break;
        +      
        +      case CDEV_CONVERT:
        +      system().reportError(CDEV_SEVERITY_WARN, service().name(), 
        +         *this, "Data conversion error in %s operation\\n",
        +         function);
        +      break;
        +			
        +
        +
        + +

        + + Figure 11: + demoRequestObject.cc: (continued) +
        + + + +
        + + +
        
        +      case CDEV_DISCONNECTED:
        +      system().reportError(CDEV_SEVERITY_WARN, service().name(), 
        +         *this, "Disconnected from service during %s operation\\n",
        +         function);
        +      break;
        +      
        +      case CDEV_RECONNECTED:
        +      system().reportError(CDEV_SEVERITY_INFO, service().name(), 
        +         *this, "Reconnected to service during %s operation\\n",
        +         function);
        +      break;
        +      }
        +   return result;
        +   }
        +			
        +
        +
        + +

        + + +

        +
        + + + Makefile for the + demoService +

        +
        + + The following Makefile can be used to build the shared object for the demoService. + This makefile uses the Makefile.common of the cdev system for its base. It has the + additional requirement that the CDEVSHOBJ environment variable must be defined. + This variable defines where the shared objects used by cdev should be stored. +

        + +

        + + Figure 12: + + Makefile for the demoService +
        + + + +
        + + +
        
        +###################################################################
        +# Makefile for demoService shared object
        +###################################################################
        +CDEVROOT = $(CDEV)
        +SHOBJ=YES
        +include $(CDEVROOT)/src/Makefile.common
        + 
        +LIBS =    -L$(LIBDIR) -lcdev -ly -ll -lm
        +OBJS = demoService.o demoRequestObject.o demoDevice.o
        +CLASS_INCLUDES = -I.
        +CXXEXTRA = -Aa +a1 -z +z -pta -g $(CLASS_INCLUDES)
        + 
        +all: demoService.so 
        + 
        +demoService.so : $(OBJS) 
        +   @echo Creating demoService shared object
        +   @rm -f demoService.so 
        +   CC -b -o demoService.so $(OBJS)
        +   @cp demoService.so $(CDEVSHOBJ)/demoService.so
        +   @echo done
        + 
        +clean:
        +   @echo Cleaning up source directory
        +   @rm -rf *.so *.a *~ *.o core ptrepository TC.Cache
        +   @echo done
        + 
        +			
        +
        +
        + +

        +
        + + + Device Definition + File for the + demoService +

        +
        + + The following Device Definition Language (DDL) file defines the verbs and attributes + supported by the demoDevice. It them defines the instances of demo devices that are + available for use. This DDL file may be used in conjunction with the cdevUtil + application to communicate with the demoDevice control system. +

        + +

        + + Figure 13: + + Device Definition Language file for the demoService +
        + + + +
        + + +
        
        +/*
        + * Service definitions
        + */
        +service demo {
        +   tags {XYZ}
        +   }
        +   
        +/*
        + * Class definitions
        + */
        +class demoDevice {
        +   verbs { get, set}
        +   attributes
        +      {
        +      VAL demo {};
        +      BDL demo {};
        +      }
        +   }
        +   
        +/*
        + * Device instanciations
        + */
        +demoDevice :
        +   DEVICE0
        +   DEVICE1
        +   DEVICE2
        +   DEVICE3
        +   DEVICE4;
        +			
        +
        +
        + +

        + + +

        +
        + diff --git a/doc/html/cdevTutorial.html b/doc/html/cdevTutorial.html new file mode 100755 index 0000000..cffe31b --- /dev/null +++ b/doc/html/cdevTutorial.html @@ -0,0 +1,9738 @@ + + +CDEV Documentation + + + + + + +


        + + + +
        + + + + A CDEV Tutorial +

        + + Techniques for using the Control Device Interface +

        + + +

        + Chip Watson, Jie Chen, Danjin Wu, Walt Akers +

        + +

        + Version 1.5 - December 9, 1996 +

        + +

        + TJNAF - Thomas Jefferson National Accelerator Facility +

        +
        + +


        + + + + + +
        + + + + Table of Contents +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +
        +
        + + Developing CDEV Applications +
        +
        + + +
        +
        + + Overview +
        +
        + + +
        +
        + + Steps in Developing a CDEV Application +
        +
        + + 2. +
        +
        + + Developing Device Definition Language Files +
        +
        + + +
        +
        + + Device Definition Language (DDL) File Overview +
        +
        + + +
        +
        + + Service Definitions +
        +
        + + +
        +
        + + Class Definitions +
        +
        + + +
        +
        + + Verb Definitions +
        +
        + + +
        +
        + + Class Inheritance +
        +
        + + +
        +
        + + Attribute Definitions +
        +
        + + +
        +
        + + Attribute Service Data +
        +
        + + +
        +
        + + Message Definitions +
        +
        + + +
        +
        + + Device Instances +
        +
        + + +
        +
        + + Device Name Substitution +
        +
        + + +
        +
        + + Device Name Aliasing +
        +
        + + +
        +
        + + Defining cdevCollections +
        +
        + + +
        +
        + + #include Directive +
        +
        + + +
        +
        + + Sample DDL +
        +
        + + 3. +
        +
        + + Using the cdevSystem Object +
        +
        + + +
        +
        + + Overview of the cdevSystem Class +
        +
        + + +
        +
        + + Public Functions of the cdevSystem Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + attachRef +
        +
        + + +
        +
        + + attachPtr +
        +
        + + +
        +
        + + defaultSystem +
        +
        + + +
        +
        + + getDevice +
        +
        + + +
        +
        + + getRequestObject +
        +
        + + +
        +
        + + name +
        +
        + + +
        +
        + + prefix +
        +
        + + +
        +
        + + prefix +
        +
        + + +
        +
        + + flush +
        +
        + + +
        +
        + + poll +
        +
        + + +
        +
        + + pend +
        +
        + + +
        +
        + + pend +
        +
        + + +
        +
        + + getFd +
        +
        + + +
        +
        + + addFdChanged Callback +
        +
        + + +
        +
        + + autoErrorOn +
        +
        + + +
        +
        + + autoErrorOff +
        +
        + + +
        +
        + + reportError +
        +
        + + +
        +
        + + setErrorHandler +
        +
        + + +
        +
        + + setThreshold +
        +
        +
        + + +
        +
        + + Sample Code +
        +
        + + 4. +
        +
        + + Using the cdevDevice Object +
        +
        + + +
        +
        + + Overview of the cdevDevice Class +
        +
        + + +
        +
        + + Public Functions of the cdevDevice Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + attachRef +
        +
        + + +
        +
        + + attachPtr +
        +
        + + +
        +
        + + detach +
        +
        + + +
        +
        + + detach +
        +
        + + +
        +
        + + getRequestObject +
        +
        + + +
        +
        + + name +
        +
        + + +
        +
        + + system +
        +
        + + +
        +
        + + setContext +
        +
        + + +
        +
        + + getContext +
        +
        + + +
        +
        + + setPrivate +
        +
        + + +
        +
        + + getPrivate +
        +
        + + +
        +
        + + send +
        +
        + + +
        +
        + + sendNoBlock +
        +
        + + +
        +
        + + sendCallback +
        +
        +
        + + +
        +
        + + Sample Code +
        +
        + + +
        +
        + + Attaching to a cdevDevice Object +
        +
        + + +
        +
        + + Getting and Setting Context for a cdevDevice +
        +
        + + +
        +
        + + Sending Messages to a Device Synchronously +
        +
        + + +
        +
        + + Sending Messages to a Device Asynchronously +
        +
        + + +
        +
        + + Using sendNoBlock +
        +
        + + +
        +
        + + Managing sendNoBlock Messages with the cdevSystem object +
        +
        + + +
        +
        + + Grouping sendNoBlock Messages with cdevGroup +
        +
        + + +
        +
        + + Using deferred groups for repeating lists of operations +
        +
        + + +
        +
        + + Using sendCallback +
        +
        + + 5. +
        +
        + + Using the cdevRequestObject Object +
        +
        + + +
        +
        + + Overview of the cdevRequestObject Class +
        +
        + + +
        +
        + + Public Member Functions of the cdevRequestObject Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + attachRef +
        +
        + + +
        +
        + + attachRef +
        +
        + + +
        +
        + + attachPtr +
        +
        + + +
        +
        + + attachPtr +
        +
        + + +
        +
        + + detach +
        +
        + + +
        +
        + + detach +
        +
        + + +
        +
        + + message +
        +
        + + +
        +
        + + device +
        +
        + + +
        +
        + + system +
        +
        + + +
        +
        + + service +
        +
        + + +
        +
        + + getState +
        +
        + + +
        +
        + + getAccess +
        +
        + + +
        +
        + + setContext +
        +
        + + +
        +
        + + getContext +
        +
        + + +
        +
        + + getPrivate +
        +
        + + +
        +
        + + setPrivate +
        +
        + + +
        +
        + + send +
        +
        + + +
        +
        + + sendNoBlock +
        +
        + + +
        +
        + + sendCallback +
        +
        +
        + + +
        +
        + + Sample Code +
        +
        + + +
        +
        + + Attaching to a cdevRequestObject Object +
        +
        + + +
        +
        + + Getting and Setting Context for a cdevRequestObject +
        +
        + + +
        +
        + + Sending Messages to a Device Synchronously +
        +
        + + +
        +
        + + Sending Messages to a Device Asynchronously +
        +
        + + +
        +
        + + Using sendNoBlock +
        +
        + + +
        +
        + + Managing sendNoBlock Messages with the cdevSystem object +
        +
        + + +
        +
        + + Grouping sendNoBlock Messages with cdevGroup +
        +
        + + +
        +
        + + Using deferred groups for repeating lists of operations +
        +
        + + +
        +
        + + Using sendCallback +
        +
        + + 6. +
        +
        + + Using the cdevData Object +
        +
        + + +
        +
        + + Overview of the cdevData Class +
        +
        + + +
        +
        + + cdevData Tags +
        +
        + + +
        +
        + + XDR Packaging of cdevData Objects +
        +
        + + +
        +
        + + Public Functions of the cdevData Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + tagC2I +
        +
        + + +
        +
        + + tagI2C +
        +
        + + +
        +
        + + insertTag +
        +
        + + +
        +
        + + operator = +
        +
        + + +
        +
        + + Cast operators +
        +
        + + +
        +
        + + asciiDump +
        +
        + + +
        +
        + + xdrSize +
        +
        + + +
        +
        + + xdrExport +
        +
        + + +
        +
        + + xdrExport +
        +
        + + +
        +
        + + xdrImport +
        +
        + + +
        +
        + + remove +
        +
        + + +
        +
        + + changeTag +
        +
        + + +
        +
        + + getType +
        +
        + + +
        +
        + + getDim +
        +
        + + +
        +
        + + getElems +
        +
        + + +
        +
        + + getBounds +
        +
        + + +
        +
        + + setBounds +
        +
        + + +
        +
        + + insert (scalar) +
        +
        + + +
        +
        + + insert (array) +
        +
        + + +
        +
        + + insert (character string) +
        +
        + + +
        +
        + + get +
        +
        + + +
        +
        + + get (character string) +
        +
        + + +
        +
        + + find +
        +
        +
        + + +
        +
        + + Sample Code +
        +
        + + 7. +
        +
        + + Using the cdevDirectory Device +
        +
        + + +
        +
        + + cdevDirectory Device +
        +
        + + +
        +
        + + Attaching to the cdevDirectory +
        +
        + + +
        +
        + + Messages Supported by cdevDirectory +
        +
        + + +
        +
        + + "query" +
        +
        + + +
        +
        + + "queryClass" +
        +
        + + +
        +
        + + "queryAttributes" +
        +
        + + +
        +
        + + "queryMessages" +
        +
        + + +
        +
        + + "queryVerbs" +
        +
        + + +
        +
        + + "service" +
        +
        + + +
        +
        + + "serviceData" +
        +
        + + +
        +
        + + "update" +
        +
        + + +
        +
        + + "validate" +
        +
        + + 8. +
        +
        + + Default Service Behavior for Standard Messages +
        +
        + + +
        +
        + + Overview +
        +
        + + +
        +
        + + "get" Message +
        +
        + + +
        +
        + + "set" Message +
        +
        + + +
        +
        + + "monitorOn" Message +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + CDEV_SUCCESS: +
        +
        + + +
        +
        + + CDEV_DISCONNECTED: +
        +
        + + +
        +
        + + CDEV_RECONNECTED: +
        +
        + + +
        +
        + + CDEV_ERROR: +
        +
        + + +
        +
        + + CDEV_INVALIDOBJ: +
        +
        + + +
        +
        + + CDEV_INVALIDARG: +
        +
        + + +
        +
        + + CDEV_INVALIDSVC: +
        +
        + + +
        +
        + + CDEV_NOTCONNECTED: +
        +
        + + +
        +
        + + CDEV_IOFAILED: +
        +
        + + +
        +
        + + CDEV_CONFLICT: +
        +
        + + +
        +
        + + CDEV_NOTFOUND: +
        +
        + + +
        +
        + + CDEV_TIMEOUT: +
        +
        + + +
        +
        + + CDEV_CONVERT: +
        +
        + + +
        +
        + + CDEV_OUTOFRANGE: +
        +
        + + +
        +
        + + CDEV_NOACCESS: +
        +
        + + +
        +
        + + CDEV_ACCESSCHANGED: +
        +
        +
        + + +
        +
        + + "monitorOff" Message +
        + + + + + + + + + +
        + + +
        +
        + + device +
        +
        + + +
        +
        + + attribute +
        +
        + + +
        +
        + + function +
        +
        + + +
        +
        + + userarg +
        +
        +
        +
        + +


        + + + + + +
        + + + + List of Figures +

        +
        + + + + Figure 1: + Service definitions in the CDEV DDL file +
        + + Figure 2: + CDEV DDL class definition containing a list of verbs +
        + + Figure 3: + CDEV DDL class definition using inheritance +
        + + Figure 4: + CDEV DDL class definition containing a list of attributes +
        + + Figure 5: + CDEV DDL class definition containing a list of messages +
        + + Figure 6: + CDEV DDL class definition to instantiate a list of devices +
        + + Figure 7: + Implementing device name substitution in a CDEV DDL file +
        + + Figure 8: + Implementing device name aliasing in a CDEV DDL file +
        + + Figure 9: + cdevCollection Definition in the CDEV DDL File +
        + + Figure 10: + Using the #include directive in a CDEV DDL file +
        + + Figure 11: + Sample complete DDL file +
        + + Figure 12: + Methods for obtaining a cdevSystem object +
        + + Figure 13: + Installing a user specified error handler +
        + + Figure 14: + Return codes generated by the send method +
        + + Figure 15: + Attaching to a cdevDevice object +
        + + Figure 16: + Altering the context of a cdevDevice object +
        + + Figure 17: + Using the send method of a cdevDevice object +
        + + Figure 18: + Using sendNoBlock to communicate with a cdevDevice +
        + + Figure 19: + Using the sendCallback method of a cdevDevice object +
        + + Figure 20: + Return codes generated by the send method +
        + + Figure 21: + Obtaining a cdevRequestObject from a cdevDevice object +
        + + Figure 22: + Altering the context of a cdevRequestObject object +
        + + Figure 23: + Using the send method of a cdevRequestObject object +
        + + Figure 24: + Using sendNoBlock to communicate with a cdevRequestObject +
        + + Figure 25: + Using the sendCallback method of a cdevRequestObject object +
        + + Figure 26: + Using insertTag to add a new tag +
        + + Figure 27: + Using tagC2I and tagI2C to determine cdevData tag identifiers +
        + + Figure 28: + Inserting and retrieving scalar data items using a cdevData object +
        + + Figure 29: + Using the changeTag method of the cdevData object +
        + + Figure 30: + Using one-dimensional arrays with cdevData objects +
        + + Figure 31: + Using multi-dimensional arrays with cdevData objects +
        + + Figure 32: + Using character strings with cdevData objects +
        + + Figure 33: + Using character string arrays with cdevData objects +
        + + Figure 34: + Using the find method of the cdevData object +
        + + Figure 35: + Attaching to the cdevDirectory device +
        + + Figure 36: + cdevData Input/Output associated with a "query" message +
        + + Figure 37: + Using the "query" Message with a cdevDirectory device +
        + + Figure 38: + cdevData input/output associated with a "queryClass" message +
        + + Figure 39: + Using the "queryClass" message with a cdevDirectory device +
        + + Figure 40: + cdevData input/output associated with a "queryAttributes" message +
        + + Figure 41: + Using the "queryAttributes" message with a cdevDirectory device +
        + + Figure 42: + cdevData input/output associated with a "queryMessages" message +
        + + Figure 43: + Using the "queryMessages" message with a cdevDirectory device +
        + + Figure 44: + cdevData input/output associated with a "queryVerbs" message +
        + + Figure 45: + Using the "queryVerbs" message with a cdevDirectory device +
        + + Figure 46: + cdevData input/output associated with a "service" message +
        + + Figure 47: + Using the "service" message with a cdevDirectory device +
        + + Figure 48: + cdevData input/output associated with a "serviceData" message +
        + + Figure 49: + Using the "serviceData" message with a cdevDirectory device +
        + + Figure 50: + cdevData input/output associated with a "update" message +
        + + Figure 51: + Using the "update" message with a cdevDirectory device +
        + + Figure 52: + cdevData input/output associated with a "validate" message +
        + + Figure 53: + Using the "update" message with a cdevDirectory device +
        + + Figure 54: + Default behavior of the "get" and "set" messages +
        + + Figure 55: + Default behavior of the "monitorOn" and "monitorOff" messages +
        +
        + +


        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + + Developing CDEV Applications +

        +
        + + + Overview +

        +
        + + The purpose of this section is to describe the steps that a CDEV user must perform in + order to effectively develop a CDEV application. This section assumes that the user is + either using one of the CDEV services provided in the CDEV distribution, or has a + local or third party developed CDEV service with which the application will + communicate. +

        +
        + + + Steps in + Developing a + CDEV Application +

        +
        + + + + + + + + + + + +
        + + 1. +

        +
        + + Construct a CDEV device definition file. The CDEV device definition file is the + roadmap that CDEV uses to define services and determine which device and + message combinations are associated with those services. This file should be + constructed and defined in the CDEVDDL environment variable prior to executing + a CDEV application. Check with the CDEV adminstrator to determine if this file + already exists on your system. +

        +
        + + 2. +

        +
        + + Design and write your source code. This step is intentional broad in scope + because the capabilities provided by various CDEV services may be completely + dissimilar in nature. The primary capability that CDEV provides is standardization + of the interface between any application and any underlying CDEV service. +

        +
        + + 3. +

        +
        + + Compile and link application with the CDEV library. This step requires the + source code to include the necessary CDEV C++ header files and linking with the + libcdev.sl or libcdev.a libraries. +

        +
        + + 4. +

        +
        + + Set any required environment variables. The primary environment variables + required by CDEV are CDEVSHOBJ and CDEVDDL. CDEVSHOBJ is used to + located shared objects, and cdevddl is used to specify the complete path to the + CDEV device definition file. Individual services may have additional requirements. +

        +
        + + 5. +

        +
        + + Execute your application. +

        +
        + + Note: Applications linked with the archive library are not capable of loading + dynamically loadable CDEV services. +

        +
        + + 2. +

        +
        + + + Developing Device Definition Language Files +

        +
        + + + Device Definition + Language (DDL) + File Overview +

        +
        + + The Device Definition Language File or DDL File is the roadmap that CDEV uses to + associate certain device and message combinations with a CDEV service. The DDL + file provides the mechanism for defining service definitions, class definitions and + instance definitions. +

        +
        + + + Service Definitions +

        +
        + + The service definition is used to publicly define the existence of a CDEV service. The + service definition declares the name of the service and the names of any special + cdevData tags that the service will use. The following is a simple service definition. +

        + +

        + + Figure 1: + + Service definitions in the CDEV DDL file +
        + + + +
        + + +
        
        +/* 
        + * Definition of service X 
        + */
        +service x
        +   {
        +   tags { tag1, tag2 }
        +   }
        + 
        +/* 
        + * Definition of service y
        + */
        +service y
        +   {
        +   tags {}
        +   }
        +			
        +
        +
        + +

        + + +

        + The service definition above defines the service "x" and service "y". During the + execution of a CDEV application, when a device and message combination is related + to the "x" service, CDEV will attempt to load the dynamic library for the service. By + convention the name of the library will be "xService.so", where "x" is the name of the + service within the DDL file. +

        + The service definition also defines the tags "tag1" and "tag2" in conjunction with + service "x". These tags will be used later to define special service data that is related + to a specific device attribute. Service "y" has no special tags associated with it. +

        + This example also illustrates the formats of comments within the DDL file. The syntax + of the DDL file accommodates the use of C style multi-line comments. +

        +
        + + + Class Definitions +

        +
        + + The class definition is used within the DDL file to declare a collection of verbs, + attributes or messages that may be applied to one or more CDEV device instances. +

        +
        + + + Verb Definitions +

        +
        + + The following examples shows the syntax for declaring a class definition that contains + only a list of verbs. +

        + + Figure 2: + + CDEV DDL class definition containing a list of verbs +
        + + + +
        + + +
        
        + 
        + 
        +class stdio
        +   {
        +   verbs { get, set, monitorOn, monitorOff }
        +   }
        +			
        +
        +
        + +

        + + +

        + In the above example, the "stdio" class is defined and it is declared to contain four + verbs: get, set, monitorOn and monitorOff. Any other class that is derived from this + class, or any device that is instantiated from this class will inherit these four verbs. +

        +
        + + + Class Inheritance +

        +
        + + The CDEV DDL file supports the notion of inheriting one class from another class. The + pre-existing class is called the super-class, while the class that is inheriting from the + pre-existing class is called the sub-class. To specify inheritance within the CDEV DDL + file, the syntax is similar to the syntax used in C++. The name of the new class is + followed by a colon, which is followed by the name of the super-class. +

        + In order to support the possibility of a colon as a character in the class name, a space + must separate the name of the class and the colon. +

        + In the next example, the "magnetIO" class is defined. This class inherits from the + "stdio" class, and receives the verbs get, set, monitorOn, and monitorOff. To this list of + verbs, it adds a new verb: "reset". +

        + +

        + + Figure 3: + + CDEV DDL class definition using inheritance +
        + + + +
        + + +
        
        +class stdio
        +   {
        +   verbs { get, set, monitorOn, monitorOff }
        +   }
        + 
        +class magnetIO : stdio
        +   {
        +   verbs { reset }
        +   }
        +			
        +
        +
        + +

        + + +

        +
        + + + Attribute + Definitions +

        +
        + + Class definitions are also used to define attributes. An attribute is a component of a + CDEV device that can be combined with a verb to define a message. When an + attribute is declared within a class, CDEV will assume that the attribute supports each + of the verbs that exist within the class. +

        +
        + + + Attribute Service + Data +

        +
        + + When the attribute is defined, the user must define the name of the service that will + receive the messages associated with it, and any service data that is associated with + it. This service data is defined using the tag names that are declared in the tags + section of the service definition. +

        + The following example declares the class "element". This class inherits its verbs from + the "stdio" class. Each attribute is associated with a service name and is followed by + service data. +

        + +

        + + Figure 4: + + CDEV DDL class definition containing a list of attributes +
        + + + +
        + + +
        
        +/***************************** 
        + * Definition of service X 
        + *****************************/
        +service x
        +   {
        +   tags { tag1, tag2 }
        +   }
        + 
        +/*****************************
        + * Definition of stdio class
        + *****************************/
        +class stdio
        +   {
        +   verbs { get, set, monitorOn, monitorOff }
        +   }
        + 
        +/*****************************
        + * Definition of element class
        + *****************************/
        +class element : stdio
        +   {
        +   attributes 
        +      {
        +      value1 x {tag1=1.0, tag2=Value};
        +      }
        +   }
        +			
        +
        +
        + +

        + + +

        + Service data also supports the notion of expression replacement. If the character + string "<>" appears in the service data, it will be replaced with the instance name of + the device that is instantiated from this class. +

        +
        + + + Message + Definitions +

        +
        + + A message definition can be declared within a CDEV DDL class definition to define + one word atomic commands. Unlike attributes and verbs, a message is a stand-alone + instruction that can be sent to a device. +

        + The structure of a message definition is similar to the attribute definition. The entries + in this section contain the name of the service and special service data that is + associated with the message. +

        + The following example shows a class that contains a single message definition. Note + that the class does not define any verbs or attributes. +

        + +

        + + Figure 5: + + CDEV DDL class definition containing a list of messages +
        + + + +
        + + +
        
        +/***************************** 
        + * Definition of service X 
        + *****************************/
        +service x
        +   {
        +   tags { tag1, tag2 }
        +   }
        + 
        +/*****************************
        + * Definition of element class
        + *****************************/
        +class element
        +   {
        +   messages 
        +      {
        +      on x {tag1=<>.Val, tag2=Text};
        +      }
        +   }
        +			
        +
        +
        + +

        + + +

        +
        + + + Device Instances +

        +
        + + The device instances section is where devices are created from class definitions. + Each device that is instantiated from a class inherits all of the verbs, attributes and + messages from that class, as well as from each class that it inherits from. +

        + The syntax for instantiating a device is as follows: the name of the class, followed by a + colon, followed by the list of device names that are being defined. The following figure + shows the syntax for defining a list of devices of the "element" class. +

        + +

        + + Figure 6: + + CDEV DDL class definition to instantiate a list of devices +
        + + + +
        + + +
        
        +/*****************************
        + * Instantiation of devices
        + *****************************/
        + 
        +element :
        +   device1
        +   device2
        +   device3;
        +			
        +
        +
        + +

        +
        
        + 
        +	
        +
        + + + Device Name + Substitution +

        +
        + + As described earlier, angle braces "<>" in the service data definition for an attribute + will be replaced with the name of its associated device. A name substitution + technique is available that allows the DDL writer to specify that a different device + name should be inserted. The substitution device name is specified in conjunction + with the actual device name when the device is instanciated. +

        + The following example illustrates the syntax for instantiating a device and specifing a + substitute name for it. In this example, the string "device1" will be substituted wherever + the string "dev1" would normally be used. +

        + +

        + + Figure 7: + + Implementing device name substitution in a CDEV DDL file +
        + + + +
        + + +
        
        +/*****************************
        + * Device name substitution
        + *****************************/
        + 
        +element :
        +   dev1 {device1}
        +   device2
        +   device3;
        +			
        +
        +
        + +

        + + +

        +
        + + + Device Name + Aliasing +

        +
        + + Device name aliasing is a more powerful alternative to device name substitution. A + device's alias may be used in applications to obtain and communicate with its + corresponding device. Device name aliases are specified in the DDL file on an + individual basis by using the alias keyword. +

        + The syntax for adding an alias to a device is illustrated in the example below. In this + example, the alias "dev1" can be used interchangably with the actual device name + "device1". +

        + +

        + + Figure 8: + + Implementing device name aliasing in a CDEV DDL file +
        + + + +
        + + +
        
        +/*****************************
        + * Device name aliasing
        + *****************************/
        + 
        + 
        + 
        + 
        +alias dev1 device1
        +			
        +
        +
        + +

        +
        
        + 
        +	
        +
        + + + Defining + cdevCollections +

        +
        + + A cdevCollection device can be implemented in one of two ways; the developer can + create an empty cdevCollection dynamically and add devices to it, or a collection entry + can be placed in the CDEV DDL file that identifies the collection and its constituent + devices. The syntax for defining a cdevCollection device in the CDEV DDL file is as + follows. +

        + + Figure 9: + + cdevCollection Definition in the CDEV DDL File +
        + + + +
        + + +
        
        +collection cDevice1 : 
        +device0, 
        +device1, 
        +device2 
        +;
        + 
        +collection cDevice2 : 
        +device3 
        +device4 
        +device5
        +;
        +			
        +
        +
        + +

        + + +

        + In the example above two cdevCollections are defined. A cdevCollection definition is + started by using the keyword "collection", followed by a space and then the name of + the collection. Note that the name of the collection must be unique and cannot be + shared with any other device in the CDEV system. +

        + The device name is followed by a white space character (which is required), and + then a colon, followed by another white space character and then the list of devices. + The device names that are in the list may be separated by either white space of a + comma delimiter. The list of devices is terminated by a semicolon. +

        + The current implementation of the CDEV DDL is order dependent. Because of this, + the developer should place the collection definitions after the definitions of all devices + and aliases. +

        +
        + + + #include Directive +

        +
        + + The #include directive is supported within the CDEV DDL file syntax. This directive is + used to include the contents of another DDL file within the current DDL file. The + syntax is the same as its C language counterpart. +

        + +

        + + Figure 10: + + Using the #include directive in a CDEV DDL file +
        + + + +
        + + +
        
        +#include "filename.ddl"
        +			
        +
        +
        + +

        +
        
        + 
        +	
        + + +

        +
        + + + Sample DDL +

        +
        + + The following sample DDL file demonstrates all current features of the Device + Definition Language. +

        + +

        + + Figure 11: + + Sample complete DDL file +
        + + + +
        + + +
        
        +/*****************************************************************
        + * Service Definitions:
        + * This section contains the definitions for individual services.
        + *****************************************************************/
        + 
        +/*****************************************************************
        + * ca Service (channel access)
        + * The library caService.so will be loaded and called whenever a
        + * call to this service needs to be executed.
        + *
        + * This services support the following special tags:
        + *   PV       = Process Variable: this tag is used to specify the
        + *              actual name of the attribute that is being 
        + *              defined.
        + *   READONLY = This is a logical tag that indicates if the 
        + *              attribute is readonly (1) or read/write (0).
        + *****************************************************************/
        +service ca {
        +   tags { PV, READONLY }
        +   }
        + 
        +/*****************************************************************
        + * Class Definitions
        + * This section contains the definition for individual classes.
        + *****************************************************************/
        + 
        +/*****************************************************************
        + * stdio Class:
        + * This class defines the basic set of verbs that will be 
        + * supported by all other classes in this DDL file.  The verbs
        + * declared in this class are:
        + *     get        = Get the value of an attribute of a device
        + *     set        = Set the value of an attribute of a device
        + *     monitorOn  = Monitor changes of an attribute's value
        + *     monitorOff = End monitoring changes of an attribute's value
        + *****************************************************************/
        +class stdio {
        +   verbs { get, set, monitorOn, monitorOff }
        +   }
        + 
        +			
        +
        +
        + +

        + + Figure 11: + Sample complete DDL file (continued) +
        + + + +
        + + +
        
        +/*****************************************************************
        + * magnet Class:
        + * This class inherits its list of verbs from the stdio class.  It
        + * then adds a list of attributes that these verbs may operate
        + * on.  The following attributes are specified.
        + *
        + *    current  : The current attribute will be serviced by ca.
        + *    bdl      : The bdl attribute will be serviced by ca.
        + *    length   : The length attribute will be serviced by ca.
        + *
        + * This class also supports the messages "on" and "off".  For 
        + * illustration purposes, these messages will operate on the val
        + * field, and therefore, have the same service data.
        + *****************************************************************/
        +class magnet : stdio
        +   {
        +   attributes {
        +      current ca {PV=<>.VAL, READONLY=0};
        +      bdl     ca {PV=BDL_<>.VAL, READONLY=0};
        +      length  ca {PV=LEN_<>.VAL, READONLY=1};
        +      }
        +   messages {
        +      on  ca {PV=<>.VAL, READONLY=0};
        +      off ca {PV=<>.VAL, READONLY=0};
        +      }   
        +   }
        + 
        +/*****************************************************************
        + * Device Instances:
        + * This section contains the instantiations of individual devices.
        + *****************************************************************/
        + 
        +/*****************************************************************
        + * The following is a list of devices that are memebers of the
        + * magnet class.  That means that each of these devices supports
        + * all of the attributes, verbs and messages that are defined by 
        + * the magnet class and the stdio class that it inherits from.
        + *****************************************************************/
        +magnet :
        +   MQB1S01
        +   MQB1S02
        +   MQB1S03
        +   MQB1S04
        + 
        +/*****************************************************************
        + * End of Device Definition File
        + *****************************************************************/
        +			
        +
        +
        + +

        +
        + + 3. +

        +
        + + + Using the cdevSystem Object +

        +
        + + + Overview of the + cdevSystem Class +

        +
        + + The cdevSystem C++ class can be described as a communications junction between + a CDEV application and CDEV services. The cdevSystem object is responsible for + interpreting the device definition file, dynamically loading CDEV services upon + request, detecting and responding to I/O events, and providing a mechanism for + polling services for updates. +

        + Currently, only the default cdevSystem object may be used within an application. + Ultimately, multiple cdevSystem objects may be created, and each of them will + maintain individual copies of CDEV services and devices within them. +

        + Most CDEV classes that are accessed directly by applications have static factories + (special constructors). Any CDEV object that is constructed by one of these factories + is automatically a member of the default cdevSystem. +

        +
        + + + Public Functions + of the + cdevSystem Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + attachRef +

        +
        + + static cdevSystem& attachRef(char *name, char *prefix); +

        + + Obtains a reference to a new or existing cdevSystem object + that has the specified name. The prefix parameter is optional, + but, if provided will be prepended to the name of each device + that is requested through the named cdevSystem object before + it is found in the device definition file. +

        +
        + + + attachPtr +

        +
        + + static cdevSystem* attachPtr(char *name, char *prefix); +

        + + Obtains a pointer to a new or existing cdevSystem object that + has the specified name. The prefix parameter is optional, but, if + provided will be prepended to the name of each device that is + requested through the named cdevSystem object before it is + found in the device definition file. +

        +
        + + + defaultSystem +

        +
        + + static cdevSystem &defaultSystem (void); +

        + + Obtains a reference to the default cdevSystem object. In most + applications this mechanism is used to access the cdevSystem + object. +

        +
        + + + getDevice +

        +
        + + cdevDevice* getDevice (char *device); +

        + + Retrieves a pointer to a cdevDevice object by name. The object + that is returned by this function will be owned and controlled by + the cdevSystem object that created it. This means that flush, + poll and pend commands must be routed through the owning + cdevSystem object in order to effect this cdevDevice object. +

        +
        + + + getRequestObject +

        +
        + + int getRequestObject ( char *device, char *msg, +

        + cdevRequestObject &req); +

        + + Retrieves a reference to a cdevRequestObject from a specified + device name and message name. The object that is produced + by this function will be owned and controlled by the + cdevSystem object that created it. This means that flush, poll + and pend commands must be routed through the owning + cdevSystem object in order to effect this cdevRequestObject. + Returns CDEV_SUCCESS or an enumerated error code. +

        +
        + + + name +

        +
        + + char *name (void); +

        + + Returns the name of this cdevSystem object. +

        +
        + + + prefix +

        +
        + + char *prefix (void); +

        + + Retrieves a pointer to the prefix string that is currently being + used by the cdevSystem object. See the attachPtr entry for a + description of the prefix string. +

        +
        + + + prefix +

        +
        + + void prefix (char *pre); +

        + + Changes the prefix string that is being used by the cdevSystem + object. See the attachPtr entry for a description of the prefix + string. +

        +
        + + + flush +

        +
        + + int flush (void); +

        + + Flushes any pending outbound requests to their respective + services. +

        +
        + + + poll +

        +
        + + int poll (void); +

        + + Directly polls each of the cdevSystem's underlying services for + activity, and delivers any asynchronous callbacks that are + ready. +

        +
        + + + pend +

        +
        + + int pend (int fd); +

        + + Waits for a default period of time for the specified file descriptor + to have an I/O event. If the fd parameter is not provided, the + cdevSystem object will wait for an I/O event on any of its + contained file descriptors. When an event occurs on one of the + file descriptors, the cdevSystem object will call the respective + cdevService to process the event and dispatch any + asynchronous callbacks that are ready. +

        +
        + + + pend +

        +
        + + int pend (double seconds, int fd); +

        + + Processes all I/O events that occur on the file descriptor during + the specified period of time. If the fd parameter is not provided, + the cdevSystem object will wait for I/O events on all of its + contained file descriptors. When an event occurs on one of the + file descriptors, the cdevSystem object will call the respective + cdevService to process the event and dispatch any + asynchronous callbacks that are ready. +

        +
        + + + getFd +

        +
        + + int getFd (int fd[], int &numFD); +

        + + Retrieves a list of file descriptors that are contained within the + cdevSystem object. The fd array must be preallocated, and the + maximum number of elements should be specified in the + numFD parameter. Upon completion, the fd array will be + populated with the list of file descriptors, and the numFD + parameter will contain the actual count. +

        +
        + + + addFdChanged Callback +

        +
        + + +

        + int addFdChangedCallback (cdevFdChangedCallback cbk, +

        + void*userarg) +

        + + Adds a new function to be called each time a service + announces to the system that it has opened or closed a file + descriptor. The function will be called with 3 arguments: +

        + + void (*cdevFdChangedCallback) (int fd, int opened, +

        + void *userarg) +

        + + The first argument specifies the file descriptor, the second is 1 + for opened, 0 for closed, and the last argument is the user + specified argument. +

        +
        + + + autoErrorOn +

        +
        + + int autoErrorOn (void); +

        + + Informs the cdevSystem object that it should use its internal + default error handler to process any error messages that are + generated by objects within its control. This is the default + operating condition for the cdevSystem object. +

        +
        + + + autoErrorOff +

        +
        + + int autoErrorOff (void); +

        + + Informs the cdevSystem object that it should use the user + supplied error handling function to process any error messages + that are generated by objects within its control. +

        +
        + + + reportError +

        +
        + + int reportError ( int severity, char *name, +

        + cdevRequestObject *obj, +

        + char *formatString,...); +

        + + Emits an error message. The severity field indicates the + severity of the error, the name string identifies the object that + generated the error, the obj parameter is the + cdevRequestObject that was in use when the error occurred, + and the formatString and additional parameters (...) should be + formatted in the same manner as the parameters used by + printf. +

        + The integer used by severity should have one of the following + values indicating the severity of the error that has occurred. +

        + + + + + + + + + +
        + + CDEV_SEVERITY_INFO: +

        +
        + + No error. +

        +
        + + CDEV_SEVERITY_WARN: +

        +
        + + An error occurred that should + not impact continued + processing. +

        +
        + + CDEV_SEVERITY_ERROR: +

        +
        + + An error occurred and should be + corrected before continuing. +

        +
        + + CDEV_SEVERITY_SEVERE: +

        +
        + + A severe or fatal error has + occurred and CDEV cannot + continue normal execution. +

        +
        +
        + + + setErrorHandler +

        +
        + + void setErrorHandler (cdevErrorHandler handler); +

        + + Used to to install a user specified error handler. This error + handler will be called when an error occurs if the autoErrorOff + method has been used to disable the default error handler. The + user provided error handler should have the following + prototype: +

        + void handler (int severity, char *text, cdevRequestObject *obj); +

        + The severity parameter will contain one of the integers + specified in the reportError documentation, the text parameter + will contain the text of the error, and the obj parameter will + contain the cdevRequestObject that was in use when the error + occurred. +

        +
        + + + setThreshold +

        +
        + + void setThreshold (int errorThreshold); +

        + + Used to specify the level of severity at which errors should be + submitted to the error handler. The value of errorThreshold + should be one of the severity levels specified in the reportError + method. +

        +
        +
        + + + Sample Code +

        +
        + + The following sample application shows the use of the three methods for obtain a + cdevSystem object. For examples of how to use the flush, poll and pend methods, see + the documentation for the cdevDevice object. +

        + +

        + + Figure 12: + + Methods for obtaining a cdevSystem object +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        + 
        +void main()
        +   {
        +   // ************************************************************
        +   // * The first and most common approach is to directly request
        +   // *   a reference to the default cdevSystem.
        +   // ************************************************************
        +   cdevSystem & default = cdevSystem::defaultSystem();
        +   
        +   // ************************************************************
        +   // * Get a pointer to the name of the default cdevSystem.
        +   // ************************************************************
        +   char * sysName = default.name();
        + 
        +   // ************************************************************
        +   // * Use the attachRef method to obtain a reference to the 
        +   // * default cdevSystem by name.
        +   // ************************************************************
        +   cdevSystem & default2 = cdevSystem::attachRef(sysName);
        + 
        +   // ************************************************************
        +   // * Finally, use the attachPtr method to obtain a pointer to
        +   // * the default cdevSystem by name.  Additionally, set the
        +   // * prefix for the default system to "TEST".
        +   // ************************************************************
        +   cdevSystem * default3 = cdevSystem::attachPtr(sysName, "TEST");
        +   
        +   // ************************************************************
        +   // * Output the name and prefix for all three systems.
        +   // ************************************************************
        +   printf("%s:%s\\n", default.name(), default.prefix());
        +   printf("%s:%s\\n", default1.name(), default1.prefix());   
        +   printf("%s:%s\\n", default2->name(), default2->prefix());
        +   }
        +			
        +
        +
        + +

        + + The following sample application illustrates how to install a user specified error + handler into the default cdevSystem object. +

        + +

        + + Figure 13: + + Installing a user specified error handler +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        + 
        +// ****************************************************************
        +// * This the default error handler.  It simply outputs the error.
        +// ****************************************************************
        +void myHandler(int severity, char *text, cdevRequestObject &obj)
        +   {
        +   if(severity>0)
        +      {
        +      fprintf(stderr, "ERROR (%i): %s\\n", severity, text);
        +      }   
        +   else    fprintf(INFORMATION: %s\\n", text);
        +   }
        + 
        +void main()
        +   {
        +   // ************************************************************
        +   // * Obtain a reference to the default cdevSystem.
        +   // ************************************************************
        +   cdevSystem & default = cdevSystem::defaultSystem();
        +   
        +   // ************************************************************
        +   // * Call the setErrorHandler method to install the new
        +   // * errorHandler.
        +   // ************************************************************
        +   default.setErrorHandler(myHandler);
        + 
        +   // ************************************************************
        +   // * Turn off auto error handling to tell the system to use
        +   // * the new user specified error handing function.
        +   // ************************************************************
        +   default.autoErrorOff();
        +   }
        +			
        +
        +
        + +

        +
        + + 4. +

        +
        + + + Using the cdevDevice Object +

        +
        + + + Overview of the + cdevDevice Class +

        +
        + + The cdevDevice C++ class is the user's primary interface to CDEV. In fact, it is + possible to develop complete CDEV applications using only cdevDevice and cdevData + objects. The cdevDevice class defines the basic interface that all applications must + use to transmit messages to a CDEV service. +

        + A cdevDevice may be created using the static member functions attachPtr or + attachRef. If one of these methods is used, the device will be created within the + context of the default cdevSystem. If the application wishes to create a device within a + cdevSystem other than the default, it must use the getDevice method of the desired + cdevSystem object. +

        + A cdevDevice object is bound by name to a specific device when it is instantiated. + However, the underlying service is not selected until a message is specified with a + send command. Therefore, simply creating a device does not ensure that the device + name is valid, nor that it supports a given message. +

        + Messages may be sent to a device using one of the three send member functions, + these are: send, sendNoBlock, and sendCallback. The syntax and functionality of + these methods is described in the section below. +

        + Input and output to the specified send methods is managed through the use of + cdevData objects. Unlike the cdevDevice object which is bound to a specific system, + the cdevData object is completely independent. These objects store the data values + (called properties) that are sent to and received from devices. The application may + indicate the properties that it wishes to receive as output from the cdevDevice object + by specifying them in a special cdevData object called the context. +

        + Examples at the end of this section will illustrate the correct ways to implement these + operations. +

        +
        + + + Public Functions + of the cdevDevice + Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + attachRef +

        +
        + + static cdevDevice& attachRef (char *name); +

        + + Obtains a reference to a cdevDevice object by name. By + default, the new object will be managed by the default + cdevSystem. +

        +
        + + + attachPtr +

        +
        + + static cdevDevice* attachPtr (char *name); +

        + + Obtains a pointer to a cdevDevice object specified by name. By + default, the new object will be managed by the default + cdevSystem. +

        +
        + + + detach +

        +
        + + static void detach (cdevDevice& dev); +

        + + Removes a referenced cdevDevice object from its associated + cdevSystem object. Ordinary applications should never use this + command. +

        +
        + + + detach +

        +
        + + static void detach (cdevDevice* dev); +

        + + Detaches the cdevDevice object specified by dev from its + associated cdevSystem object. Ordinary applications should + never use this command. +

        +
        + + + getRequestObject +

        +
        + + cdevRequestObject* getRequestObject (char *msg); +

        + + Obtains a service specific request object. This function uses + the name of the device specified within the cdevDevice object, + and the message provided by the caller to determine which + CDEV service will be used to service this request. The service + is then loaded (if necessary), and is contacted to provided a + request object for the device/message combination. This + cdevRequestObject will then be used to communicate with the + service directly. +

        +
        + + + name +

        +
        + + const char *name (void) const; +

        + + Returns the name of the device. +

        +
        + + + system +

        +
        + + cdevSystem& system (void) const; +

        + + Obtains a reference to the underlying cdevSystem object that + manages this device. +

        +
        + + + setContext +

        +
        + + int setContext (cdevData& cxt); +

        + + Used to insert a cdevData object containing tagged values that + control optional behavior of the underlying device. The context + is often used to specify which properties (value, status, + severity) a device returns in response to a "get" message. It is + important to note that any change made to the context of a + cdevDevice will automatically be propagated to all + cdevRequestObjects created from that device. Therefore, any + message specific context settings should be specified directly + to the cdevRequestObject, rather than to the cdevDevice. +

        +
        + + + getContext +

        +
        + + cdevData & getContext (void); +

        + + Retrieves a reference to the cdevData object that contains the + context for a specific device. +

        +
        + + + setPrivate +

        +
        + + void setPrivate (void * data); +

        + + Associates a user specified data object with this cdevDevice + object. The pointer can be retrieved later using the getPrivate + method. +

        +
        + + + getPrivate +

        +
        + + void * getPrivate (void); +

        + + Retrieves a pointer to a data object that was placed in this + cdevDevice object using the setPrivate function. +

        +
        + + + send +

        +
        + + int send (char *msg, cdevData &out, cdevData& result); +

        + int send (char *msg, cdevData *out, cdevData& result); +

        + int send (char *msg, cdevData &out, cdevData* result); +

        + int send (char *msg, cdevData *out, cdevData* result); +

        + + The send function is the standard method for synchronously + communicating with a device. The caller provides the message + as a character string in the msg parameter. The out cdevData + object contains any property values that the device will need to + perform the task. The result cdevData object will contain the + output properties that resulted from the call. This function will + return one of the error code defined in cdevErrCode.h. +

        +
        + + +

        + + Figure 14: + + Return codes generated by the send method +
        + + + +
        + + +
        
        +CDEV_SUCCESS:       The message was processed successfully.
        +CDEV_ERROR:         Failed to process message.
        +CDEV_INVALIDOBJ:    Invalid CDEV request object used.
        +CDEV_INVALIDARG:    Invalid argument passed to CDEV call.
        +CDEV_INVALIDSVC:    Wrong service during dynamic loading.
        +CDEV_NOTCONNECTED:  Not connected to low level network 
        +                    service.
        +CDEV_IOFAILED:      Low level network service IO failed.
        +CDEV_CONFLICT:      Conflicts of data types or tags.
        +CDEV_NOTFOUND:      Cannot find specified data in cdevData.
        +CDEV_TIMEOUT:       Time out.
        +CDEV_CONVERT:       cdevData conversion error.
        +CDEV_OUTOFRANGE:    Value out of range for device attribute.
        +CDEV_NOACCESS:      Insufficient access to perform request.
        +CDEV_ACCESSCHANGED: Change in access permission of device.
        +CDEV_DISCONNECTED:  The service has lost contact with the 
        +                    device.
        +CDEV_RECONNECTED:   The service has regained contact with the 
        +                    device.
        +			
        +
        +
        + +

        + + + + + +
        + + + sendNoBlock +

        +
        + + int sendNoBlock(char *msg, cdevData &out, cdevData &result); +

        + int sendNoBlock(char *msg, cdevData *out, cdevData &result); +

        + int sendNoBlock(char *msg, cdevData &out, cdevData *result); +

        + int sendNoBlock(char *msg, cdevData *out, cdevData *result); +

        + + The sendNoBlock method uses the same parameters and + syntax as the send method. However, rather than waiting for + the underlying service to respond to the request, this function + will return immediately. The caller must utilize some + synchronization method such as a cdevGroup object to detect + when this transaction has been completed, or test for new data + within the result data object. +

        +
        + + + sendCallback +

        +
        + + int sendCallback ( char *msg, cdevData &out, +

        + cdevCallback &callback); +

        + int sendCallback ( char *msg, cdevData *out, +

        + cdevCallback &callback); +

        + + The sendCallback function is the standard method for + asynchronously communicating with a device. Rather than + providing a result cdevData object, this method requires the + user to provide the address of a cdevCallback object. This + object contains a user supplied pointer and the address of a + function to call when the message has been successfully + processed. +

        +
        +
        + + + Sample Code +

        +
        + + The following sample applications illustrate many of the uses of the cdevDevice + object. Additionally, these examples show in depth usage of the cdevData object and + the concept of context. +

        +
        + + + Attaching to a + cdevDevice Object +

        +
        + + Within a cdevSystem object, a cdevDevice is created only once for any specified + device name. After that, all requests for that device are given a pointer to the same + cdevDevice object. This technique is called attaching to a device. +

        + There are two approaches to attaching to a cdevDevice; through a specific + cdevSystem object, or through the cdevDevice interface. Attaching to the device using + the cdevSystem object has the benefit of making it possible to manage the device + through a system other than the default system. Using the cdevDevice interface + directly always places the new device in the default system, but has the benefit of + reducing the complexity of the source code by hiding the use of the cdevSystem + object. +

        + The next example illustrates how to attach to a cdevDevice using the attachRef and + the attachPtr methods. The attachRef method allows the caller to obtain a reference to + the cdevDevice object, while the attachPtr method allows the user to obtain a pointer + to the same object. This example also demonstrates the long hand approach for + retrieving a cdevDevice pointer from the system object. +

        + +

        + + Figure 15: + + Attaching to a cdevDevice object +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        + 
        +void main()
        +   {
        +   // ************************************************************
        +   // * Use the attachPtr and attachRef methods to attach to 
        +   // * devices "MQB1S01" && "MQB1S02".
        +   // ************************************************************
        +   cdevDevice * devicePtr = cdevDevice::attachPtr("MQB1S01");
        +   cdevDevice & deviceRef = cdevDevice::attachRef("MQB1S02");
        + 
        +   // ************************************************************
        +   // * To use the long-hand approach, obtain a pointer to the
        +   // * default cdevSystem (or any other cdevSystem object).
        +   // ************************************************************
        +   cdevSystem & default = cdevSystem::defaultSystem();
        +   
        +   // ************************************************************
        +   // * Next, use the getDevice method of the system to obtain
        +   // * a pointer to the specific device (MQB1S03).
        +   // ************************************************************
        +   cdevDevice * dev = default.getDevice("MQB1S03");
        +   }
        +			
        +
        +
        + +

        +
        + + + Getting and + Setting Context for + a cdevDevice +

        +
        + + In CDEV, context refers to a collection of options that may be used to alter the way a + CDEV device responds to a specific message. How context information effects the + bahvior of a device is defined by the associated cdevService. Context may be used to + set any number of I/O options, such as timeouts, data acquisition specifications, or + flags to control optional return data. The context is stored and retrieved in the form of + a cdevData object containing a collection of tagged data items (called properties). +

        + The example below illustrates how the caller may obtain a copy of the context of a + device, install a new context for a specific call, and then restore the previous context to + the device. +

        + Note: Whenever the context of a device is directly manipulated, each of its underlying + cdevRequestObjects are updated to reflect the new change. Therefore, altering the + context directly in the cdevDevice is not recommended. The preferred approach is to + obtain a copy of the cdevRequestObject and alter the context there. +

        + +

        + + Figure 16: + + Altering the context of a cdevDevice object +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   // ************************************************************
        +   // * Obtain a pointer to the cdevDevice "MQB1S01"
        +   // ************************************************************
        +   cdevDevice * devicePtr = cdevDevice::attachPtr("MQB1S01");
        +   cdevData oldContext, newContext;
        + 
        +   // ************************************************************
        +   // * Indicate in the newContext cdevData object that devices
        +   // * should return their value, status and severity information
        +   // ************************************************************
        +   newContext.insert("value", 1);
        +   newContext.insert("status", 1);
        +   newContext.insert("severity", 1);
        + 
        +   // ************************************************************
        +   // * Preserve the contexts of the original device context, and 
        +   // * then install the new device context.
        +   // ************************************************************
        +   oldContext = devicePtr->getContext();
        +   devicePtr->setContext(newContext);
        + 
        +   // ************************************************************
        +   // * After performing the context specific operations, restore
        +   // * the old context to the device.
        +   // ************************************************************
        +   devicePtr->setContext(oldContext);
        +   }
        +			
        +
        +
        + +

        + + +

        +
        + + + Sending Messages + to a Device + Synchronously +

        +
        + + In most CDEV applications, the caller will want to send a message to a device and + then wait until a response is received. In order to do this, the send method of the + cdevDevice object should be used. The send method receives three parameters; the + message to be sent, a cdevData object containing data required by the device, and a + cdevData object to receive the data returned by the device. +

        + The following example demonstrates reading an attribute of a device and handling + each class of error inline. A return code of CDEV_SUCCESS indicates that the + message was successfully transmitted and processed. +

        + +

        + + Figure 17: + + Using the send method of a cdevDevice object +
        + + + +
        + + +
        
        +#include <cdevDevice.h>
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   // ************************************************************
        +   // * Obtain a pointer to the cdevDevice "MQB1S01"
        +   // ************************************************************
        +   cdevDevice * device = cdevDevice::attachPtr("MQB1S01");
        +   cdevData input, output;
        +   double value = 0.0;
        + 
        +   // ************************************************************
        +   // * Use the send method to obtain the value from the device.
        +   // * Because there is no outbound data, the parameter is NULL.
        +   // ************************************************************
        +   switch(device->send("get bdl", NULL, &output)) 
        +      {
        +      // **** Message transmitted and processed successfuly. ****
        +      case CDEV_SUCCESS:
        +         output.get("value", &value);
        +         printf("Value of MQB1S01 is %f\\n", value);
        +         break;
        +      
        +      // ****** Unknown device or device/message mismatch ******
        +      case CDEV_INVALIDOBJ:
        +         printf("Unknown device or device/message mismatch\\n");
        +         break;
        + 
        +      // * Communications error between application and service *
        +      case CDEV_NOTCONNECTED:
        +      case CDEV_IOFAILED:
        +      case CDEV_TIMEOUT:
        +         printf("Communications error while sending\\n");
        +         break;
        + 
        +      // ******************* Generic error **********************
        +      case CDEV_ERROR:
        +      case default:
        +         printf("Unable to send message\\n");
        +         break;
        +      }
        + 
        +   // ************************************************************
        +   // * Increment the value, and use the "set bdl" command
        +   // ************************************************************   
        +   value += 1.0;
        +   input.insert("value", value);
        +   device->send("set bdl", &input, NULL);
        +   }
        +			
        +
        +
        + +

        +
        + + + Sending Messages + to a Device + Asynchronously +

        +
        + + There are two methods provided by the cdevDevice object for sending messages + asynchronously; sendNoBlock and sendCallback. +

        +
        + + + Using + sendNoBlock +

        +
        + + The sendNoBlock method is identical in interface to the send method, however, if it is + unable to immediately transmit to and receive a response from the device, it will not + wait. In order to determine if a sendNoBlock operation has completed successfully, the + caller must poll the cdevSystem object, implement a grouping scheme using the + cdevGroup object, or explicitly test for new data in the result data object. +

        +
        + + + Managing + sendNoBlock + Messages with + the cdevSystem + object +

        +
        + + To manage asynchronous messages using the cdevSystem object, the caller should + use the pend or poll method. These methods will submit the message to the + underlying device, and will wait for a period of time for a response to arrive. If all + messages have not been processed during the specified (or default) period of time, + these methods will return a CDEV_TIMEOUT status code. If all transactions have + been processed, these methods will return a CDEV_SUCCESS status code. +

        +
        + + + Grouping + sendNoBlock + Messages with + cdevGroup +

        +
        + + An alternative way to manage messages transmitted with sendNoBlock is to create + and start a cdevGroup object prior to sending the first message. The application then + transmits all of the messages that it wishes to manage within a single group. Once all + messages have been transmitted, the caller will end the cdevGroup and then may call + the pend member function of the cdevGroup object until the return value is + CDEV_SUCCESS. The caller should always specify a discrete amount of time to wait + when using the pend operation, otherwise, the application can enter an indefinite wait. +

        + Note: Once a cdevGroup object has been started, it will remain open until its end + method is executed OR until the pend method of the cdevGroup object is executed. If + a sendNoBlock is executed after the group has been ended, it will not be managed by + that group. +

        + The example below illustrates how to transmit multiple messages to a device using the + sendNoBlock method and the cdevGroup object. +

        + +

        + + Figure 18: + + Using sendNoBlock to communicate with a cdevDevice +
        + + + +
        + + +
        
        +#include <cdevGroup.h>
        +#include <cdevDevice.h>
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   // ************************************************************
        +   // * Obtain a pointer to the cdevDevice "MQB1S01" and "MQB1S02"
        +   // ************************************************************
        +   cdevDevice * device1 = cdevDevice::attachPtr("MQB1S01");
        +   cdevDevice * device2 = cdevDevice::attachPtr("MQB1S02");
        +   cdevGroup    group;
        +   cdevData     output1, output2;
        + 
        +   // ************************************************************
        +   // * Start the cdevGroup object to group all of the requests.
        +   // ************************************************************
        +   group.start();
        +			
        +
        +
        + +

        + + Figure 18: + Using sendNoBlock to communicate with a cdevDevice (continued) +
        + + + +
        + + +
        
        +   // ************************************************************
        +   // * Use the sendNoBlock command to transmit the messages to
        +   // * the selected devices.  The "get VAL" message requires no
        +   // * input, so the outbound cdevData object is NULL.
        +   // ************************************************************
        +   device1->sendNoBlock("get VAL", NULL, &output1);
        +   device2->sendNoBlock("get VAL", NULL, &output2);
        + 
        +   // ************************************************************
        +   // * Use the end method to terminate the group.
        +   // ************************************************************
        +   group.end();
        + 
        +   // ************************************************************
        +   // * Use the pend method of the group to wait for 1 second
        +   // * for all of the messages to be processed.  The allFinished
        +   // * method can be used to obtain the completioon status of 
        +   // * the group (0=NOT DONE, 1=DONE).
        +   // *
        +   // * As a simple example, this function will wait no more than 
        +   // * 5 seconds for all messages to be processed.
        +   // ************************************************************
        +      {
        +      group.pend(1.0);
        +      }   
        +   }
        +			
        +
        +
        + +

        +
        + + + Using deferred + groups for + repeating lists of + operations +

        +
        + + A cdevGroup may be placed into a deferred mode prior to starting it, and in this case + messages will not be transmitted until the group is flushed. After all operations within + the group have completed, the group may be flushed again, causing the same set of + operations to be executed again. See the reference manual for details. +

        +
        + + + Using + sendCallback +

        +
        + + The sendCallback method provides the second mechanism for transmitting messages + asynchronously. This method is used in CDEV for a variety of purposes, the most + common of these is to establish monitors on a specific cdevDevice attribute. Once the + monitor has been established, the user specified callback function will be contacted + whenever the property's value is altered. +

        + This method is more complex than the others because it REQUIRES the caller to + utilize a cdevSystem object in order to poll the underlying services, and it requires the + caller to predefine a cdevCallbackFunction to be executed when the message has + been processed. +

        + The cdevCallbackFunction has a very specific prototype that the caller must comply + with. The user specified callback function must be of type void, and must receive the + following parameters. +

        + + + + + + + + + +
        + + 1. +

        +
        + + int status: This is equivalent to the return status of a synchronous send call. It + should receive one of the error codes that are defined in cdevErrCode.h. +

        +
        + + 2. +

        +
        + + void * arg: This is a pointer to data that was specified by the user when creating + the cdevCallback object. +

        +
        + + 3. +

        +
        + + cdevRequestObject & obj: This is the cdevRequestObject that the system used + to transmit the message to the device. +

        +
        + + 4. +

        +
        + + cdevData & data: This is the cdevData object that contains the output generated + by the device when it processed the message. +

        +
        + + The cdevCallbackFunction and a user provided argument are passed to the + sendCallback method through the use of the cdevCallback object. The cdevCallback + object is a simple container class. +

        + +

        + + Figure 19: + + Using the sendCallback method of a cdevDevice object +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#incldue <cdevRequestObject.h>
        +#include <cdevCallback.h>
        +#include <cdevData.h>
        + 
        +// ****************************************************************
        +// * callback:
        +// * This is the callback function that will be called when the 
        +// * message has been processed to completion.  This function is 
        +// * disregarding CDEV_DISCONNECTED and CDEV_RECONNECTED messages.
        +// ****************************************************************
        +void callback(int status, 
        +            void * arg, 
        +            cdevRequestObject & req, 
        +            cdevData & data)
        +   {
        +   double result;   
        +   int & userFlag = *arg;
        +   
        +   // ************************************************************
        +   // * Save the completion status and print the result
        +   // ************************************************************
        +   if(status!=CDEV_DISCONNECTED && status!=CDEV_RECONNECTED) 
        +      {      
        +      userFlag = status;
        +      data.get("value", &result);      
        +      printf("I have received value %f", result);   
        +      }
        +   }
        + 
        +void main()
        +   {
        +   // ************************************************************
        +   // * Integer flag for detecting callback completion
        +   // ************************************************************
        +   int userFlag = 100;   
        + 
        +   // ************************************************************
        +   // * Obtain a reference to the default system.
        +   // ************************************************************
        +   cdevSystem & default = cdevSystem::defaultSystem();
        +   
        +   // ************************************************************
        +   // * Obtain a pointer to the device "MQB1S01".
        +   // ************************************************************
        +   cdevDevice * device = default.getDevice("MQB1S01");
        + 
        + 
        +			
        +
        +
        + +

        + + Figure 19: + Using the sendCallback method of a cdevDevice object (continued) +
        + + + +
        + + +
        
        +   // ************************************************************
        +   // * Construct the cdevCallback object that will be used to
        +   // * specify the callback function and the user argument.
        +   // ************************************************************
        +   cdevCallback cb(callback, &userFlag);
        + 
        +   // ************************************************************
        +   // * Transmit the message to the device using the sendCallback
        +   // * mechanism.  Since the message requires no outbound data, 
        +   // * the outbound cdevData object is NULL.
        +   // ************************************************************
        +   if(device->sendCallback("get current", NULL, cb)==CDEV_SUCCESS)
        +      {
        +      // *********************************************************
        +      // * Now, poll the cdevSystem object until the message has
        +      // * been successfully processed.
        +      // *********************************************************
        +      while(userFlag==100) default.poll();
        +      }
        +   }
        +			
        +
        +
        + +

        + + +

        + +

        +
        + + 5. +

        +
        + + + Using the cdevRequestObject Object +

        +
        + + + Overview of the + cdevRequestObject + Class +

        +
        + + The cdevRequestObject C++ class is the provides the user with a higher performance + interface to devices in CDEV. Each time a cdevDevice receives a message string, it + must parse the message and then connect to the appropriate service. The + cdevRequestObject allows the user to bind a device name to a message and then + connect to the underlying service only once. Thereafter, the cdevRequestObject will + remain connected to the service and can process its associated message with much + higher efficiency. +

        + A cdevRequestObject may be created using the static member functions attachPtr or + attachRef. If one of these methods is used, the object will be created within the + context of the default cdevSystem. If the application wishes to create a device within a + cdevSystem other than the default, it must first obtain a pointer to the associated + cdevDevice object from the desired system, and then use the getRequestObject + method of that cdevDevice. +

        + The message associated with a cdevRequestObject may be sent to a device using + one of the three send member functions, these are: send, sendNoBlock, and + sendCallback. The syntax and functionality of these methods is described in the + section below. +

        + Input and output to the specified send methods is managed through the use of + cdevData objects. Unlike the cdevRequestObject object which is bound to a specific + system, the cdevData object is completely independent. These objects store the data + values (called properties) that are sent to and received from devices. The application + may indicate the properties that it wishes to receive as output from the + cdevRequestObject object by specifying them in a special cdevData object called the + context. +

        + Examples at the end of this section will illustrate the correct ways to implement these + operations. +

        +
        + + + Public Member + Functions of the + cdevRequestObject + Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + attachRef +

        +
        + + static cdevRequestObject& attachRef (char *device, char * msg); +

        + + Obtains a reference to a cdevRequestObject object by + specifying the name of the device and the message string. By + default, the new object will be managed by the default + cdevSystem. +

        +
        + + + attachRef +

        +
        + + static cdevRequestObject& attachRef (cdevDevice &dev, char * msg); +

        + + Obtains a reference to a cdevRequestObject object by + providing a reference to the associated cdevDevice object and + the message string. By default, the new object will be managed + by the default cdevSystem. +

        +
        + + + attachPtr +

        +
        + + static cdevRequestObject* attachPtr (char *device, char * msg); +

        + + Obtains a pointer to a cdevRequestObject by specifying the + name of the device and the message string. By default, the new + object will be managed by the default cdevSystem. +

        +
        + + + attachPtr +

        +
        + + static cdevRequestObject* attachPtr (cdevDevice &dev, char * msg); +

        + + Obtains a pointer to a cdevRequestObject by providing a + reference to the associated cdevDevice object and the + message string. By default, the new object will be managed by + the default cdevSystem. +

        +
        + + + detach +

        +
        + + static void detach (cdevRequestObject& dev); +

        + + Removes a referenced cdevRequestObject object from its + associated cdevSystem object. Ordinary applications should + never use this command. +

        +
        + + + detach +

        +
        + + static void detach (cdevRequestObject* dev); +

        + + Detaches the cdevRequestObject object specified by dev from + its associated cdevSystem object. Ordinary applications should + never use this command. +

        +
        + + + message +

        +
        + + char *message (void) const; +

        + + Retrieves the message string that is associated with this + cdevRequestObject. +

        +
        + + + device +

        +
        + + cdevDevice &device (void) const; +

        + + Retrieves a reference to the cdevDevice object that is + associated with this cdevRequestObject. +

        +
        + + + system +

        +
        + + cdevSystem& system (void) const; +

        + + Retrieves a reference to the underlying cdevSystem object that + manages this cdevRequestObject. +

        +
        + + + service +

        +
        + + cdevService& service (void) const; +

        + + Retrieves a reference to the underlying cdevService object that + this cdevRequestObject is attached to. +

        +
        + + + getState +

        +
        + + int getState (void); +

        + + Obtains the state of the underlying device. This function returns + one of the following values as defined in cdevErrCode.h. +

        + + + + + + + +
        + + CDEV_STATE_CONNECTED: +

        +
        + + Object is connected. +

        +
        + + CDEV_STATE_NOTCONNECTED: +

        +
        + + Object is not connected. +

        +
        + + CDEV_STATE_INVALID: +

        +
        + + Object is invalid. +

        + +

        +
        + + The service developer is responsible for implementing this + function correctly in the service related cdevRequestObject. +

        +
        + + + getAccess +

        +
        + + int getAccess (void); +

        + + Obtains access control information about the underlying + device. This function returns one of the following values as + defined in cdevErrCode.h. +

        + + + + + + + +
        + + CDEV_ACCESS_NONE: +

        +
        + + No access to attribute. +

        +
        + + CDEV_ACCESS_READONLY: +

        +
        + + Read-only access. +

        +
        + + CDEV_ACCESS_WRITE: +

        +
        + + Read-write access. +

        +
        + + The service developer is responsible for implementing this + function correctly in the service related cdevRequestObject. +

        +
        + + + setContext +

        +
        + + int setContext (cdevData& cxt); +

        + + Used to insert a cdevData object containing tagged values that + control optional behavior of the underlying device. The context + is often used to specify which properties (value, status, + severity) a device returns in response to a "get" message. The + service developer may override the default behavior of this + method to better accomodate the requirements of the service. +

        +
        + + + getContext +

        +
        + + cdevData & getContext (void); +

        + + Retrieves a reference to the cdevData object that contains the + context for a specific cdevRequestObject. The service + developer may override the default behavior of this method to + better accomodate the requirements of the service. +

        +
        + + + getPrivate +

        +
        + + void * getPrivate (void); +

        + + Retrieves a pointer to a data object that was placed in this + object using the setPrivate function. +

        +
        + + + setPrivate +

        +
        + + void setPrivate (void * data); +

        + + Associates a user specified data object with this + cdevRequestObject. The pointer can be retrieved later using + the getPrivate method. +

        +
        + + + send +

        +
        + + int send (cdevData &out, cdevData& result); +

        + int send (cdevData *out, cdevData& result); +

        + int send (cdevData &out, cdevData* result); +

        + int send (cdevData *out, cdevData* result); +

        + + The send function is the standard method for synchronously + communicating with a device. The out cdevData object + contains any property values that the device will need to + perform the task. The result cdevData object will contain the + output properties that resulted from the call. The service + developer is responsible for implementing this method in the + service specified cdevRequestObject. This function will return + one of the error code defined in cdevErrCode.h. +

        + +

        +
        + + Figure 20: + + Return codes generated by the send method +
        + + + +
        + + +
        
        +CDEV_SUCCESS:       The message was processed successfully.
        +CDEV_ERROR:         Failed to process message.
        +CDEV_INVALIDOBJ:    Invalid CDEV request object used.
        +CDEV_INVALIDARG:    Invalid argument passed to CDEV call.
        +CDEV_INVALIDSVC:    Wrong service during dynamic loading.
        +CDEV_NOTCONNECTED:  Not connected to low level network 
        +                    service.
        +CDEV_IOFAILED:      Low level network service IO failed.
        +CDEV_CONFLICT:      Conflicts of data types or tags.
        +CDEV_NOTFOUND:      Cannot find specified data in cdevData.
        +CDEV_TIMEOUT:       Time out.
        +CDEV_CONVERT:       cdevData conversion error.
        +CDEV_OUTOFRANGE:    Value out of range for device attribute.
        +CDEV_NOACCESS:      Insufficient access to perform request.
        +CDEV_ACCESSCHANGED: Change in access permission of device.
        +CDEV_DISCONNECTED:  The service has lost contact with the 
        +                    device.
        +CDEV_RECONNECTED:   The service has regained contact with the 
        +                    device.
        +			
        +
        +
        + +

        + + + + + +
        + + + sendNoBlock +

        +
        + + int sendNoBlock (cdevData &out, cdevData &result); +

        + int sendNoBlock (cdevData *out, cdevData &result); +

        + int sendNoBlock (cdevData &out, cdevData *result); +

        + int sendNoBlock (cdevData *out, cdevData *result); +

        + + The sendNoBlock method uses the same parameters and + syntax as the send method. However, rather than waiting for + the underlying service to respond to the request, this function + will return immediately.The caller may use a cdevGroup object + in order to detect when the transaction has been completed. + The service developer is responsible for implementing this + method in the service's cdevRequestObject. +

        +
        + + + sendCallback +

        +
        + + int sendCallback (cdevData &out, cdevCallback &callback); +

        + int sendCallback (cdevData *out, cdevCallback &callback); +

        +
        + + The sendCallback function is the standard method for asynchronously communicating + with a device. Rather than providing a result cdevData object, this method requires the + user to provide the address of a cdevCallback object. This object contains a user + supplied pointer and the address of a function to call when the message has been + successfully processed. The service developer is responsible for implementing this + method in the service specified cdevRequestObject. +

        +
        + + + Sample Code +

        +
        + + The following sample applications illustrate many of the uses of the + cdevRequestObject object. Additionally, these examples show in depth usage of the + cdevData object and the concept of context. +

        +
        + + + Attaching to a + cdevRequestObject + Object +

        +
        + + Within a cdevSystem object, a cdevRequestObject is created only once for any + specified device name / message string combination. After that, all requests for that + combination are given a pointer to the same cdevRequestObject object. This + technique is called attaching to a cdevRequestObject. +

        + There are two approaches to attaching to a cdevRequestObject; through a specific + cdevDevice object, or through the cdevRequestObject interface. Attaching to the + device using the cdevDevice object has the benefit of making it possible to manage + the cdevRequestObject using the cdevSystem object associated with that device, + rather than using the default system. Using the cdevRequestObject interface directly + always places the new request object into the default system, but has the benefit of + reducing the complexity of the source code by hiding the use of the cdevDevice and + the cdevSystem objects. +

        + The example below illustrates how to attach to a cdevRequestObject with a device + named "MQB1S01" and the message "get VAL" using the cdevDevice interface. +

        + +

        + + Figure 21: + + Obtaining a cdevRequestObject from a cdevDevice object +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevRequestObject.h>
        + 
        +void main()
        +   {
        +   // ************************************************************
        +   // * LONG-HAND METHOD
        +   // * The first step in this approach is to obtain a pointer or
        +   // * reference to the desired system.  For this example, the
        +   // * defaultSystem will be used.
        +   // ************************************************************
        +   cdevSystem & default = cdevSystem::defaultSystem();
        +   
        +   // ************************************************************
        +   // * Next, use the getDevice method of the system to obtain
        +   // * a pointer to the specific device.
        +   // ************************************************************
        +   cdevDevice * device = default.getDevice("MQB1S01");
        + 
        +   // ************************************************************
        +   // * Finally, use the getRequestObject method of the cdevDevice
        +   // * class to obtain a cdevRequestObject for the message
        +   // * "get VAL" on device "MQB1S01".
        +   // ************************************************************
        +   cdevRequestObject *req = device->getRequestObject("get bdl");
        + 
        +   // ************************************************************
        +   // * SHORT-HAND METHOD
        +   // * The following shortcut code directly creates a 
        +   // * cdevRequestObject and installs it in the default 
        +   // * cdevSystem object.
        +   // ************************************************************
        +   cdevRequestObject *req1 =
        +      cdevRequestObject::attachPtr("MQB1S01", "get bdl");
        +   }
        + 
        +			
        +
        +
        + +

        +
        + + + Getting and Setting + Context for a + cdevRequestObject +

        +
        + + In CDEV, context refers to a collection of options that may be used to alter the way a + CDEV device responds to a specific message. How context information effects the + bahvior of a device is defined by the associated cdevService. Context may be used to + set any number of I/O options, such as timeouts, data acquisition specifications, or + flags to control optional return data. The context is stored and retrieved in the form of + a cdevData object containing a collection of tagged data items (called properties). +

        + The example below illustrates how the caller may obtain a copy of the context of a + cdevRequestObject, install a new context for a specific call, and then restore the + previous context to the object. +

        + +

        + + Figure 22: + + Altering the context of a cdevRequestObject object +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevRequestObject.h>
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevData oldContext, newContext;
        +   // ************************************************************
        +   // * Obtain a cdevRequestObject for "MQB1S01" / "get bdl"
        +   // ************************************************************
        +   cdevRequestObject *req = 
        +      cdevRequestObject::attachPtr("MQB1S01", "get bdl");
        + 
        +   // ************************************************************
        +   // * Indicate in the newContext cdevData object that this
        +   // * device should return its value, status and severity
        +   // ************************************************************
        +   newContext.insert("value", 1);
        +   newContext.insert("status", 1);
        +   newContext.insert("severity", 1);
        + 
        +   // ************************************************************
        +   // * Preserve the contexts of the original device context, and 
        +   // * then install the new device context.
        +   // ************************************************************
        +   oldContext = req->getContext();
        +   req->setContext(newContext);
        + 
        +   // ************************************************************
        +   // * After performing the context specific operations, restore
        +   // * the old context to the device.
        +   // ************************************************************
        +   req->setContext(oldContext);
        +   }
        +			
        +
        +
        + +

        + + +

        +
        + + + Sending Messages + to a Device + Synchronously +

        +
        + + In most CDEV applications, the caller will want to send a message to a device and + then wait until a response is received. In order to do this, the send method of the + cdevRequestObject object may be used. The send method receives two parameters; + a cdevData object containing data required by the device, and a cdevData object to + receive the data returned by the device. +

        + The following example demonstrates how to read an attribute of a device, and handle + each class of error inline. A return code of CDEV_SUCCESS indicates that the + message was successfully transmitted and processed. +

        + +

        + + Figure 23: + + Using the send method of a cdevRequestObject object +
        + + + +
        + + +
        
        +#include <cdevRequestObject.h>
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   // ************************************************************
        +   // * Obtain a cdevRequestObject for "MQB1S01" / "get bdl"
        +   // ************************************************************
        +   cdevRequestObject *req = 
        +      cdevRequestObject::attachPtr("MQB1S01", "get bdl");
        +   cdevData input, output;
        +   double value = 0.0;
        + 
        +   // ************************************************************
        +   // * Use the send method to obtain the value from the device.
        +   // * Since there is no outbound data, the parameter is NULL
        +   // ************************************************************
        +   switch(req->send(NULL, &output)) 
        +      {
        +      // **** Message transmitted and processed successfuly. ****
        +      case CDEV_SUCCESS:
        +         output.get("value", &value);
        +         printf("Value of MQB1S01 is %f\\n", value);
        +         break;
        +      
        +      // ******* Unknown device or device/message mismatch ******
        +      case CDEV_INVALIDOBJ:
        +         printf("Unknown device or device/message mismatch\\n");
        +         break;
        + 
        +      // * Communications error between application and service *
        +      case CDEV_NOTCONNECTED:
        +      case CDEV_IOFAILED:
        +      case CDEV_TIMEOUT:
        +         printf("Communications error while sending\\n");
        +         break;      
        + 
        +      // ************ A generic error has occurred *************
        +      case CDEV_ERROR:
        +      case default:
        +         printf("Unable to send message\\n");
        +         break;
        +      }
        +   }
        +			
        +
        +
        + +

        +
        + + + Sending Messages + to a Device + Asynchronously +

        +
        + + There are two methods provided by the cdevRequestObject object for sending + messages asynchronously; sendNoBlock and sendCallback. +

        +
        + + + Using + sendNoBlock +

        +
        + + The sendNoBlock method is identical in interface to the send method, however, if it is + unable to immediately transmit to and receive a response from the device, it will not + wait. In order to determine if a sendNoBlock operation has completed successfully, the + caller must poll the cdevSystem object, use the cdevGroup object, or explicitly test for + new data in the result object. +

        +
        + + + Managing + sendNoBlock + Messages with + the cdevSystem + object +

        +
        + + To manage asynchronous messages using the cdevSystem object, the caller should + use the pend or poll method. These methods will submit the message to the + underlying device, and will wait for a period of time for a response to arrive. If all + messages have not been processed during the specified (or default) period of time, + these methods will return a CDEV_TIMEOUT status code. If all transactions have + been processed, these methods will return a CDEV_SUCCESS status code. +

        +
        + + + Grouping + sendNoBlock + Messages with + cdevGroup +

        +
        + + An alternative way to manage messages transmitted with sendNoBlock, is to create + and start a cdevGroup object prior to sending the first message. The application will + then transmit all of the messages that it wishes to manage within a single group. Once + all messages have been transmitted, the caller will end the cdevGroup and then may + call the pend member function of the cdevGroup object until the return value is + CDEV_SUCCESS. The caller should always specify a discrete amount of time to wait + when using the pend operation, otherwise, the application can enter an indefinite wait. +

        + Note: Once a cdevGroup object has been started, it will remain open until its end + method is executed OR until the pend method of the cdevGroup object is executed. If + a sendNoBlock is executed after the group has been ended, it will not be managed by + that group. +

        + +

        + + Figure 24: + + Using sendNoBlock to communicate with a cdevRequestObject +
        + + + +
        + + +
        
        +#include <cdevGroup.h>
        +#include <cdevRequestObject.h>
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevRequestObject *req1, *req2;
        +   cdevGroup          group;
        +   cdevData           output1, output2;
        +   // ************************************************************
        +   // * Obtain cdevRequestObjects for "MQB1S01" and "MQB1S02"
        +   // ************************************************************
        +   req1 = cdevRequestObject::attachPtr("MQB1S01", "get bdl");
        +   req2 = cdevRequestObject::attachPtr("MQB1S02", "get bdl");
        + 
        +   // ************************************************************
        +   // * Start the cdevGroup object to group all of the requests.
        +   // ************************************************************
        +   group.start();
        +			
        +
        +
        + +

        + + Figure 24: + Using sendNoBlock to communicate with a cdevRequestObject (continued) +
        + + + +
        + + +
        
        +   // ************************************************************
        +   // * Use the sendNoBlock command to transmit the messages to
        +   // * the selected devices.  The "get bdl" message requires no
        +   // * input, so the outbound cdevData object is NULL.
        +   // ************************************************************
        +   req1->sendNoBlock(NULL, &output1);
        +   req2->sendNoBlock(NULL, &output2);
        + 
        +   // ************************************************************
        +   // * Use the end method to terminate the group.
        +   // ************************************************************
        +   group.end();
        + 
        +   // ************************************************************
        +   // * Use the pend method of the group to wait for 1 second
        +   // * for all of the messages to be processed.  The allFinished
        +   // * method can be used to obtain the completion status of 
        +   // * the group (0=NOT DONE, 1=DONE).
        +   // *
        +   // * As a simple example, this function will wait no more than 
        +   // * 5 seconds for all messages to be processed.
        +   // ************************************************************
        +      {
        +      group.pend(1.0);
        +      }   
        +   }
        +			
        +
        +
        + +

        +
        + + + Using deferred + groups for + repeating lists of + operations +

        +
        + + A cdevGroup may be placed into a deferred mode prior to starting it, and in this case + messages will not be transmitted until the group is flushed. After all operations within + the group have completed, the group may be flushed again, causing the same set of + operations to be executed again. +

        +
        + + + Using + sendCallback +

        +
        + + The sendCallback method provides the second mechanism for transmitting messages + asynchronously. This method is used in CDEV for a variety of purposes, the most + common of these is to establish monitors on a specific device property. Once the + monitor has been established, the user specified callback function will be contacted + whenever the property's value is altered. +

        + This method is more complex than the others because it requires the caller to utilize a + cdevSystem object in order to poll the underlying services, and it requires the caller to + predefine a cdevCallbackFunction to be executed when the message has been + processed. +

        + The cdevCallbackFunction has a very specific prototype that the caller must comply + with. The user specified callback function must be of type void, and must receive the + following parameters. +

        + + + + + + + + + +
        + + 1. +

        +
        + + int status: This is equivalent to the return status of a synchronous send call. It + should receive one of the values as defined in cdevErrCode.h. +

        +
        + + 2. +

        +
        + + void * arg: This is a pointer to data that was specified by the user when creating + the cdevCallback object. +

        +
        + + 3. +

        +
        + + cdevRequestObject & obj: This is the cdevRequestObject that the system used + to transmit the message to the device. +

        +
        + + 4. +

        +
        + + cdevData & data: This is the cdevData object that contains the output generated + by the device when it processed the message. +

        +
        + + The cdevCallbackFunction and a user provided argument are passed to the + sendCallback method through the use of the cdevCallback object. The cdevCallback + object is a simple container class. +

        + +

        + + Figure 25: + + Using the sendCallback method of a cdevRequestObject object +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevRequestObject.h>
        +#include <cdevCallback.h>
        +#include <cdevData.h>
        + 
        +// ****************************************************************
        +// * callback:
        +// * This is the callback function that will be called when the 
        +// * message has been processed to completion.  This function is 
        +// * disregarding CDEV_DISCONNECTED and CDEV_RECONNECTED messages.
        +// ****************************************************************
        +void callback(int status, 
        +            void * arg, 
        +            cdevRequestObject & req, 
        +            cdevData & data)
        +   {
        +   double result;   
        +   int & userFlag = *arg;
        +   
        +   // ************************************************************
        +   // * Save the completion status and print the result
        +   // ************************************************************
        +   if(status!=CDEV_DISCONNECTED && status!=CDEV_RECONNECTED) 
        +      {      
        +      userFlag = status;
        +      data.get("value", &result);      
        +      printf("I have received value %f", result);   
        +      }
        +   }
        + 
        +void main()
        +   {
        +   // ************************************************************
        +   // * Integer flag for detecting callback completion
        +   // ************************************************************
        +   int userFlag = 100;
        +   
        +   // ************************************************************
        +   // * Obtain a reference to the default system.
        +   // ************************************************************
        +   cdevSystem & default = cdevSystem::defaultSystem();
        + 
        +   // ************************************************************
        +   // * Obtain a cdevRequestObject for "MQB1S01" / "get bdl".
        +   // ************************************************************
        +   cdevRequestObject * req = 
        +      default.getDevice("MQB1S01")->getRequestObject("get bdl");
        +			
        +
        +
        + +

        + + Figure 25: + Using the sendCallback method of a cdevRequestObject object (continued) +
        + + + +
        + + +
        
        +   // ************************************************************
        +   // * Construct the cdevCallback object that will be used to
        +   // * specify the callback function and the user argument.
        +   // ************************************************************
        +   cdevCallback cb(callback, &userFlag);
        + 
        +   // ************************************************************
        +   // * Transmit the message to the device using the sendCallback
        +   // * mechanism.  Since the message requires no outbound data, 
        +   // * the outbound cdevData object is NULL.
        +   // ************************************************************
        +   if(req->sendCallback(NULL, cb)==CDEV_SUCCESS)
        +      {
        +      // *********************************************************
        +      // * Now, poll the cdevSystem object until the message has
        +      // * been successfully processed.
        +      // *********************************************************
        +      while(userFlag==100) default.poll();
        +      }
        +   }
        +			
        +
        +
        + +

        + + +

        + +

        + +

        +
        + + 6. +

        +
        + + + Using the cdevData Object +

        +
        + + + Overview of the + cdevData Class +

        +
        + + The cdevData C++ class is a self describing data object. This class is the primary + mechanism for data interchange within the CDEV system. The cdevData object is + capable of storing and retrieving tagged data items of all the primitive data types, as + well as character strings and time stamps. These data items may be scalar or multi- + dimensional arrays. +

        +
        + + + cdevData Tags +

        +
        + + A tag is a unique 32 bit integer that may be defined by the CDEV system, individual + services or by an application. Each tag integer has a corresponding character string + identifier. By using the character string identifier to obtain the integer tag, applications + and services are insulated from problems caused by internal tag renumbering. +

        +
        + + + XDR Packaging of + cdevData Objects +

        +
        + + In addition to storing data, the cdevData object can also encapsulate its contents into + an XDR buffer for portable transport between platforms. The buffer can then be + decoded and reassembled into a cdevData when it has been received. To ensure best + performance, the XDR mechanism only transports the tag integer values, rather than + the tag character string values. Therefore, client/server applications using the XDR + transport must verify that they are using the same version of CDEV in order to avoid + tag number mismatches. +

        +
        + + + Public Functions + of the cdevData + Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + tagC2I +

        +
        + + static int tagC2I (char *ctag, int *tag); +

        + + Converts a character string tag name to its unique integer + identifier. The function returns CDEV_SUCCESS if the + conversion was successful, otherwise it returns + CDEV_ERROR. +

        +
        + + + tagI2C +

        +
        + + static int tagI2C (int tag, char * &ctag); +

        + + Converts a unique integer tag number to its related character + string tag. The function returns CDEV_SUCCESS if the + conversion was successful, otherwise it returns + CDEV_ERROR. +

        +
        + + + insertTag +

        +
        + + static void insertTag(int tag, char *ctag); +

        + + Adds a new, unique tag identifier to the static table of tags. Both + the tag integer and the character string must be unique. + Returns CDEV_SUCCESS on success, or CDEV_ERROR on + failure. +

        +
        + + + operator = +

        +
        + + cdevData & operator = (cdevData & data); +

        + + This is the assignment operator for the class. It will copy the + exact contents of the cdevData object specified by data to the + current cdevData object. +

        +
        + + + Cast operators +

        +
        + + operator char (void); +

        + operator short (void); +

        + operator unsigned short (void); +

        + operator int (void); +

        + operator unsigned int (void); +

        + operator long (void); +

        + operator unsigned long (void); +

        + operator float (void); +

        + operator double (void); +

        + + Directly extracts a scalar value that is stored in the "value" data + item, and returns it as the value of the current cdevData object. +

        +
        + + + asciiDump +

        +
        + + void asciiDump (FILE * fp); +

        + + Outputs the complete contents of the cdevData object to a file. + If no file pointer is specified, then stdout will be used. +

        +
        + + + xdrSize +

        +
        + + int xdrSize (size_t * bufLen, size_t * elementCount); +

        + + Calculates the size of the buffer (bufLen) that will be required to + store this cdevData object as represented by XDR. The total + number of data items (elementCount) that will be placed in the + buffer is also calculated. The values obtained from this function + may be passed to the xdrExport method in order to use a pre- + allocated data buffer. +

        +
        + + + xdrExport +

        +
        + + int xdrExport (char ** buf, size_t * bufLen); +

        + + Allocates a buffer (buf) of sufficient size to hold the XDR + representation of this cdevData object. It will then translate all + data items stored within the object to XDR and write this data to + the buffer. The size of the allocated buffer will be provided to + the caller in the bufLen variable. +

        +
        + + + xdrExport +

        +
        + + int xdrExport (char * buf, size_t bufLen, size_t count); +

        + + Populates the preallocated buffer (buf) with the XDR + representation of the contents of this cdevData object. The + buffer length (bufLen) and number of elements (count) must + have been calculated in advance using the xdrSize method. +

        +
        + + + xdrImport +

        +
        + + int xdrImport (char * buf, size_t bufLen); +

        + + Decodes the caller supplied buffer (buf) from XDR + representation and populates the cdevData object with the + contents. The caller must specify the number of bytes in the + XDR buffer (bufLen). +

        +
        + + + remove +

        +
        + + void remove(void); +

        + void remove(int tag); +

        + void remove(char * ctag); +

        + + Removes the data item specified by the unique tag name or + integer from this cdevData object. If the tag is not specified, + then all data items will be removed from the object. +

        +
        + + + changeTag +

        +
        + + int changeTag(int oldTag, int newTag); +

        + int changeTag(int oldTag, char *c_newTag); +

        + int changeTag(char *c_oldTag, int newTag); +

        + int changeTag(char *c_oldTag, char *c_newTag); +

        + + Retags a data item that is currently stored in the cdevData + object from "oldTag" to "newTag". By using this method the data + can be renamed internally without having to perform a copy or + removal. This function is overloaded to support any + permutation of character string tag or integer tag identifier. +

        +
        + + + getType +

        +
        + + cdevDataTypes getType(int tag); +

        + cdevDataTypes getType(char *ctag); +

        + + Retrieves the enumerated data type of the specified tagged + data item within this cdevData object. The following + enumerated types are defined in the file cdevTypes.h. +

        + + + + + + + + + + + + + + + + + + + + + +
        + + CDEV_BYTE +

        +
        + + 8 bit unsigned character +

        +
        + + CDEV_INT16 +

        +
        + + 16 bit signed integer +

        +
        + + CDEV_UINT16 +

        +
        + + 16 bit unsigned integer +

        +
        + + CDEV_INT32 +

        +
        + + 32 bit signed integer +

        +
        + + CDEV_UINT32 +

        +
        + + 32 bit unsigned integer +

        +
        + + CDEV_FLOAT +

        +
        + + single precision floating point +

        +
        + + CDEV_DOUBLE +

        +
        + + double precision floating point +

        +
        + + CDEV_STRING +

        +
        + + NULL terminated character string +

        +
        + + CDEV_TIMESTAMP +

        +
        + + CDEV time stamp +

        +
        + + CDEV_INVALID +

        +
        + + invalid or unknown data type +

        +
        +
        + + + getDim +

        +
        + + int getDim(int tag, size_t *dim); +

        + int getDim(char *ctag, size_t *dim); +

        + + Retrieves the number of dimensions in a data item that is an + array. If dim is 0, then the data item is scalar, otherwise, the + data item is a "dim" dimensional array. This function is + overloaded to support either the integer tag or character string + tag. +

        +
        + + + getElems +

        +
        + + int getElems(int tag, size_t *elems); +

        + int getElems(char *ctag, size_t *elems); +

        + + Retrieves the number of data elements in all dimensions of a + multi-dimensional array. If elems is 1, then the data item is + scalar, otherwise, the data item is an array of "elems" elements. + This function is overloaded to support either the integer tag or + character string tag. +

        +
        + + + getBounds +

        +
        + + int getBounds( int tag, +

        + cdevBounds * bounds, +

        + size_t numBounds); +

        + int getBounds( char * ctag, +

        + cdevBounds * bounds, +

        + size_t numBounds); +

        + + Obtains the bounding dimensions of the array specified by the + caller provided tag. The cdevBounds structure contains two + integers: offset and length. The length variable represents the + number of data elements in that dimension of the array. The + offset integer is provided for use in specifying the position of + arrays that are sub-sets of the actual data. A version of this + function is available that uses an array of integers rather than + the cdevBounds structure. This function is overloaded to + support either the integer tag or character string tag. +

        +
        + + + setBounds +

        +
        + + int setBounds( int tag, +

        + cdevBounds * bounds, +

        + size_t numBounds); +

        + int setBounds( char * ctag, +

        + cdevBounds * bounds, +

        + size_t numBounds); +

        + + Specifies the bounding dimensions of a multi-dimensional array + of data. In order to use this function, the number of dimensions + in the array must be specified as a parameter to the insert + command when placing the data into the cdevData object. The + cdevBounds structure contains two integers: offset and length. + The length variable represents the number of data elements in + that dimension of the array. The offset integer is provided for + use in specifying the position of arrays that are sub-sets of the + actual data. A version of this function is available that uses an + array of integers rather than the cdevBounds structure. This + function is overloaded to support either the integer tag or + character string tag. +

        +
        + + + insert (scalar) +

        +
        + + int insert (int tag, BYTE data); +

        + int insert (int tag, short data); +

        + int insert (int tag, unsigned short data); +

        + int insert (int tag, int data); +

        + int insert (int tag, unsigned int data); +

        + int insert (int tag, long data); +

        + int insert (int tag, unsigned long data); +

        + int insert (int tag, float data); +

        + int insert (int tag, double data); +

        + int insert (int tag, cdev_TS_STAMP data); +

        + + These methods allow the user to insert a single data item into + the cdevData object using the specified tag. If another data + item already occupies that tag within the cdevData object, the + new data item will override the old one. Although only the + integer tag prototypes are shown, these functions are + overloaded to support both the integer and character string + data tags. +

        +
        + + + insert (array) +

        +
        + + int insert (int tag, BYTE * data, size_t len, size_t ndim); +

        + int insert (int tag, short * data, size_t len, size_t ndim); +

        + int insert (int tag, unsigned short * data, size_t len, size_t ndim); +

        + int insert (int tag, int * data, size_t len, size_t ndim); +

        + int insert (int tag, unsigned int * data, size_t len, size_t ndim); +

        + int insert (int tag, long * data, size_t len, size_t ndim); +

        + int insert (int tag, unsigned long * data, size_t len, size_t ndim); +

        + int insert (int tag, float * data, size_t len, size_t ndim); +

        + int insert (int tag, double * data, size_t len, size_t ndim); +

        + + These methods allow the user to insert array data items into the + cdevData object using the specified tag. The len parameter is + used to specify the total number of items in the array. The ndim + parameter is used to specify the number of dimensions in the + array (1 by default). Although only the integer tag prototypes + are shown, these functions are overloaded to support both the + integer and character string data tags. +

        +
        + + + insert (character string) +

        +
        + + +

        + int insert (int tag, char * data); +

        + int insert (int tag, char ** data, size_t len, size_t ndim); +

        + + These methods are used to add NULL terminated character + strings to the cdevData object. These methods differ from the + others because a single character string is treated as a scalar + value. The len parameter (where used) specifies the total + number of character strings in the array. The ndim parameter is + used to specify the number of dimensions in the array (1 by + default). Although only the integer tag prototypes are shown, + these functions are overloaded to support both the integer and + character string data tags. +

        +
        + + + get +

        +
        + + int get(int tag, BYTE * data); +

        + int get(int tag, short * data); +

        + int get(int tag, unsigned short * data); +

        + int get(int tag, int * data); +

        + int get(int tag, unsigned int * data); +

        + int get(int tag, long * data); +

        + int get(int tag, unsigned long * data); +

        + int get(int tag, float * data); +

        + int get(int tag, double * data); +

        + int get(int tag, cdev_TS_STAMP * data); +

        + + These methods are used to retrieve scalar values and arrays + that are stored in the cdevData object. When retrieving an + array, it is the caller's responsibility to call the getElems method + to obtain the number of elements and then pre-allocate the + buffer to receive the data. If the receiving data type does not + match the data type stored in the cdevData object, then the + data will be converted to the new type when it is extracted. + Although only the integer tag prototypes are shown, these + functions are overloaded to support both the integer and + character string data tags. +

        +
        + + + get (character string) +

        +
        + + +

        + int get(int tag, char * data, size_t len); +

        + int get(int tag, char ** data); +

        + + These methods are used to retrieve character strings and + arrays of character strings from a cdevData object. When + obtaining a single character string, the length of the allocated + buffer must be specified in the len parameter. When obtaining + an array of character strings, the caller must pre-allocate the + POINTERS for each element in the array. The cdevData object + will allocate sufficient memory to each of the pointers to hold + the individual character strings. It then becomes the + responsibility of the caller to free the memory assigned to those + pointers. If the receiving data type does not match the data + type stored in the cdevData object, then the data will be + converted to the new type when it is extracted. Although only + the integer tag prototypes are shown, these functions are + overloaded to support both the integer and character string + data tags. +

        +
        + + + find +

        +
        + + int find(int tag, void* &data); +

        + int find(char * ctag, void* &data); +

        + + Retrieves a pointer to the data within the cdevData object. The + caller is responsible for ensuring that the receiving pointer is of + the correct data type for the data within the object. This function + is overloaded to support both integer and character string tag + identifiers. +

        +
        +
        + + + Sample Code +

        +
        + + The following sample program shows the steps necessary to add a new tag character + string and tag integer to the global CDEV tag table. This method is most frequently + used by the CDEV system and CDEV services. +

        + +

        + + Figure 26: + + Using insertTag to add a new tag +
        + + + +
        + + +
        
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   // ************************************************************
        +   // * Unique tag number and character string
        +   // ************************************************************
        +   int    tag     = 100;
        +   char * tagName = "testTag";   
        +   
        +   // ************************************************************
        +   // * Insert the new tag
        +   // ************************************************************
        +   cdevData::insertTag(tag, tagName);
        +   printf("Inserted tag %s as tag number %i\\n", tagName, tag);
        +   }
        +			
        +
        +
        + +

        + + +

        + The following sample application illustrates the steps necessary to convert between + character string and integer tag values using the tagI2C and tagC2I methods. +

        + +

        + + Figure 27: + + Using tagC2I and tagI2C to determine cdevData tag identifiers +
        + + + +
        + + +
        
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   int    tag;
        +   char * tagName;
        +   // ************************************************************
        +   // * Insert a new tag into cdevData to illustrate this function
        +   // ************************************************************
        +   cdevData::insertTag(100, "testTag");
        +   
        +   // ************************************************************
        +   // * Now use the command tagI2C to obtain the character string
        +   // * name of the tag from the tag number.
        +   // ************************************************************
        +   cdevData::tagI2C(100, tagName);
        + 
        +   // ************************************************************
        +   // * Using the newly obtained character string, call tagC2I to
        +   // * obtain the integer tag value.
        +   // ************************************************************
        +   cdevData::tagC2I(tagName, &tag);
        + 
        +   printf("Tag name %s is tag number %i", tagName, tag);
        +   }
        +			
        +
        +
        + +

        + + +

        + The following sample application shows the steps necessary to place scalar data into + a cdevData object using the insert method and then retrieve the data using the get + method. +

        + +

        + + Figure 28: + + Inserting and retrieving scalar data items using a cdevData object +
        + + + +
        + + +
        
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevData data;
        +   int      x;
        +   double   y;
        +   
        +   // ************************************************************
        +   // Insert a short integer as the "value" property.
        +   // ************************************************************
        +   data.insert("value", (short int)1);
        + 
        +   // ************************************************************
        +   // * Insert a double as the "status" property
        +   // ************************************************************
        +			
        +
        +
        + +

        + + Figure 28: + Inserting and retrieving scalar data items using a cdevData object (continued) +
        + + + +
        + + +
        
        +   data.insert("status", (double)2.0);
        + 
        +   // ************************************************************
        +   // * Get the short stored in the "value" property as a double
        +   // ************************************************************
        +   data.get("value", &y);
        +   printf("value is %f\\n", y);
        + 
        +   // ************************************************************
        +   // * Get the double stored in the "status" property as an int
        +   // ************************************************************
        +   data.get("status", &x);
        +   printf("status is %i\\n", x);   
        +   }
        +			
        +
        +
        + +

        + + +

        + The following example illustrates the proper usage of the changeTag method to alter + the tag identifier of a data item stored in the cdevData object. +

        + +

        + + Figure 29: + + Using the changeTag method of the cdevData object +
        + + + +
        + + +
        
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevData  data;
        +   short int x;
        +   
        +   // ************************************************************
        +   // Insert a short integer as the "value" property.
        +   // ************************************************************
        +   data.insert("value", (short int)1);
        + 
        +   // ************************************************************
        +   // * Use the changeTag method to convert the tag identifier 
        +   // * for the data item from "value" to "status".
        +   // ************************************************************
        +   data.changeTag("value", "status");
        + 
        +   // ************************************************************
        +   // * Use the get method to retrieve the short integer from the
        +   // * "status" property.
        +   // ************************************************************
        +   data.get("status", &x);
        +   printf("Retrieved %i from the status property\\n", x);
        +   }
        +			
        +
        +
        + +

        + + +

        + The following sample application illustrates how to use the cdevData object to insert + and retrieve a 1 dimensional array of doubles. +

        + +

        + + Figure 30: + + Using one-dimensional arrays with cdevData objects +
        + + + +
        + + +
        
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevData  data;
        +   size_t    count;
        +   double    inArray[5] = {1.0, 2.0, 3.0, 4.0, 5.0};   
        +   double   *outArray;
        + 
        +   // ************************************************************
        +   // * Use the insert method to add the array to the value 
        +   // * property of the cdevData object.
        +   // ************************************************************
        +   data.insert("value", inArray, 5);
        + 
        +   // ************************************************************
        +   // * Now we will extract the data that we just inserted.
        +   // * First, use the getElems method to determine the number of
        +   // * elements in the array.
        +   // ************************************************************
        +   data.getElems("value", &count);
        + 
        +   // ************************************************************
        +   // * Next allocate an array of doubles sufficient to hold 
        +   // * the array stored in the cdevData object.
        +   // ************************************************************
        +   outArray = new double[count];
        + 
        +   // ************************************************************
        +   // * Finally, retrieve the data from the cdevData object using
        +   // * the get method.
        +   // ************************************************************
        +   data.get("value", outArray);
        + 
        +   // ************************************************************
        +   // * Output the result and then free any locally allocated
        +   // * memory.
        +   // ************************************************************
        +      {
        +      printf("Element %i is %f\\n", i, outArray[i]);
        +      }
        +   delete outArray;
        +   }
        +			
        +
        +
        + +

        + + +

        + The following example illustrates the correct method for inserting and retrieving a + multi-dimensional array of doubles. This sample program also demonstrates the use + of the getBounds and setBounds function calls, and how they are used to define the + bounding dimensions for a multi-dimensional array. +

        + +

        + + Figure 31: + + Using multi-dimensional arrays with cdevData objects +
        + + + +
        + + +
        
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevData   data;
        +   int        i;
        +   size_t     nElems=1;
        +   size_t     nDim  =1;
        +   cdevBounds inbounds[2];
        +   double     inarray[2][5] =
        +   {
        +   {0.0, 1.0, 2.0, 3.0, 4.0},
        +   {5.0, 6.0, 7.0, 8.0, 9.0}
        +   };
        + 
        +   double     * outarray;
        +   cdevBounds * outbounds;
        + 
        +   // ############################################################
        +   // # Inserting multi-dimensional data into a cdevData object.
        +   // ############################################################
        +   
        +   // ************************************************************
        +   // * Set the length of each dimension of the array within the
        +   // * cdevBounds structure.  Also, set the offset to 0 for each
        +   // * dimension to specify that this array begins at the origen;
        +   // ************************************************************
        + 
        +   inbounds[0].offset = 0;   // Offset of first dimension
        +   inbounds[0].length = 2;   // Length of first dimension
        +   
        +   inbounds[1].offset = 0;   // Offset of second dimension
        +   inbounds[1].length = 5;   // Length of second dimension
        +   
        +   // ************************************************************
        +   // * Use the insert method to add the array to the value
        +   // * property of the cdevData object.  The third parameter 
        +   // * specifies the exact number of elements that will be added,
        +   // * while the fourth parameter specifies that this will be a
        +   // * two dimensional array.
        +   // ************************************************************
        +   data.insert("value", (double *)inarray, 10, 2);
        +   
        +   // ************************************************************
        +   // * Use the setBounds method to specify the bounding 
        +   // * dimensions of the multi-dimensional array.
        +   // ************************************************************
        +   data.setBounds("value", inbounds, 2);
        +			
        +
        +
        + +

        + + Figure 31: + Using multi-dimensional arrays with cdevData objects (continued) +
        + + + +
        + + +
        
        +   // ############################################################
        +   // # Retrieving multi-dimensional data from a cdevData object.
        +   // ############################################################
        +   
        +   // ************************************************************
        +   // * Call the getDim method to obtain the number of dimensions
        +   // * in the array.
        +   // ************************************************************
        +   data.getDim("value", &nDim);
        +   
        +   // ************************************************************
        +   // * Allocate a cdevBounds structure of sufficient size to
        +   // * hold all dimensions of the array.
        +   // ************************************************************
        +   outbounds = new cdevBounds[nDim];
        +   
        +   // ************************************************************
        +   // * Use the getBounds methods to obtain the bounding 
        +   // * dimensions of the array.
        +   // ************************************************************
        +   data.getBounds("value", outbounds, 2);
        +   
        +   // ************************************************************
        +   // * Calculate the number of elements in the complete array.
        +   // * This step is shown for illustrative purposes only.  The 
        +   // * result of this operation should be the same value that 
        +   // * would be returned by the getElems method.
        +   // ************************************************************
        +   
        +   // ************************************************************
        +   // * Allocate an outbound buffer of sufficient size to hold
        +   // * the data in all dimensions of the array.
        +   // ************************************************************
        +   outarray = new double[nElems];
        +   
        +   // ************************************************************
        +   // * Use the get method to obtain the data from the cdevData
        +   // * object.
        +   // ************************************************************
        +   data.get("value", outarray);
        +   
        +   // ************************************************************
        +   // * Output the data retrieved.
        +   // ************************************************************
        +   
        +   delete(outbounds);
        +   delete(outarray);
        +   }
        +			
        +
        +
        + +

        + + The following example shows the correct method to insert and retrieve a character + string using a cdevData object. The treatment of character strings in CDEV differs + from ordinary values, because a character string is an array that is treated as a scalar. + Therefore, the structure of the get method for a character string is unique. +

        + +

        + + Figure 32: + + Using character strings with cdevData objects +
        + + + +
        + + +
        
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevData data;
        +   char * inString = "This is my test string";
        +   char   outString[50];
        +   
        +   // ************************************************************
        +   // * Use the insert method to insert the character string into
        +   // * the cdevData object.
        +   // ************************************************************
        +   data.insert("value", inString);
        +   
        +   // ************************************************************
        +   // * Next, use the get function to retrieve the string.  The 
        +   // * maximum length of the string to be retrieved is specified
        +   // * by the third parameter (50).
        +   // ************************************************************
        +   data.get("value", outString, 50);
        +   
        +   printf("String is: %s\\n", outString);
        +   }
        +			
        +
        +
        + +

        + + +

        + The next example illustrates the correct method for retrieving an array of character + strings. This is a very special case because, with normal arrays, the caller must pre- + allocate the array that the data will be read into when the get method is caller. With an + array of character strings, the user is responsible for allocating only the array of + POINTERS that each string will be assigned to. The get method will then allocate + sufficient memory to each pointer to store the data. +

        + When finished using the array, the user is responsible for freeing the memory + assigned to each individual POINTER, and then freeing the array of pointers. +

        + +

        + + Figure 33: + + Using character string arrays with cdevData objects +
        + + + +
        + + +
        
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevData data;
        +   char **  outString;
        +   size_t   nElems;
        +   int      i;
        + 
        +			
        +
        +
        + +

        + + Figure 33: + Using character string arrays with cdevData objects (continued) +
        + + + +
        + + +
        
        +   char *   inStrings[10] =
        +      {
        +      "string 0",
        +      "string 1",
        +      "string 2",
        +      "string 3",
        +      "string 4",
        +      "string 5",
        +      "string 6",
        +      "string 7",
        +      "string 8",
        +      "string 9"
        +      };
        +      
        +   // ############################################################
        +   // # Inserting character string arrays
        +   // ############################################################
        +   
        +   // ************************************************************
        +   // * Place the array of character strings into the cdevData 
        +   // * object using the insert command. (by default, ndim=1)
        +   // ************************************************************
        +   data.insert("value", inStrings, 10);
        +   
        +   // ############################################################
        +   // # Retrieving character string arrays
        +   // ############################################################
        +   
        +   // ************************************************************
        +   // * Use the getElems function to determine the total number
        +   // * of STRINGS that will be retrieved.
        +   // ************************************************************
        +   data.getElems("value", &nElems);
        +   
        +   // ************************************************************
        +   // * Allocate an array of pointers, 1 for each element.
        +   // ************************************************************
        +   outString = new char *[nElems];
        +   
        +   // ************************************************************
        +   // * Use the get method to retrive the data from cdevData.
        +   // ************************************************************
        +   data.get("value", outString);
        +   
        +   // ************************************************************
        +   // * Output the data recieved from the cdevData object.
        +   // ************************************************************
        +      printf("String %i: %s\\n", i, outString[i]);
        +			
        +
        +
        + +

        + + Figure 33: + Using character string arrays with cdevData objects (continued) +
        + + + +
        + + +
        
        +   // ************************************************************
        +   // * Free the memory allocated by cdevData.
        +   // ************************************************************
        +      if(outString[i]!=NULL) delete outString[i];
        +   
        +   // ************************************************************
        +   // * Free the locally allocated array of pointers.
        +   // ************************************************************
        +   delete outString;
        +   }
        +			
        +
        +
        + +

        + + +

        + The next sample application shows how to use the find method of the cdevData + object. The find method can be used to obtain a memory pointer to the data array + within the cdevData object without allocating any new memory. However, because the + find method does not perform any data type conversions, the caller is responsible for + ensuring that a pointer to the correct data type is used. +

        + This example shows how to use the find method as an alternative approach for + obtaining an array of character strings. +

        + +

        + + Figure 34: + + Using the find method of the cdevData object +
        + + + +
        + + +
        
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   char * inStrings[10] =
        +      {
        +      "string 0",
        +      "string 1",
        +      "string 2",
        +      "string 3",
        +      "string 4",
        +      "string 5",
        +      "string 6",
        +      "string 7",
        +      "string 8",
        +      "string 9"
        +      };
        +   cdevData      data;
        +   cdevDataTypes datatype;
        +   char **       outString;
        +   size_t        nElems;
        +   int           i;
        +      
        +   // ************************************************************
        +   // * Place the array of character strings into the cdevData 
        +   // * object using the insert command.
        +   // ************************************************************
        +   data.insert("value", inStrings, 10);
        +			
        +
        +
        + +

        + + Figure 34: + Using the find method of the cdevData object (continued) +
        + + + +
        + + +
        
        +   // ############################################################
        +   // # Retrieving a pointer to the data using the find method
        +   // ############################################################
        +   
        +   // ************************************************************
        +   // * For this example, we are going to ensure that the value
        +   // * we are obtaining is an array of strings.
        +   // * The getType method will be caller to ensure that the
        +   // * data type of the value is CDEV_STRING, and then the
        +   // * getElems method will be called to make sure that their
        +   // * is more than one string in the cdevData object.
        +   // ************************************************************
        +   datatype = data.getType("value");
        +   data.getElems("value", &nElems);
        +      
        +   if(datatype==CDEV_STRING && nElems>0)
        +      {
        +      // ********************************************************
        +      // * Call find to obtain a copy of the data.
        +      // ********************************************************
        +      data.find("value", (void *&)outString);
        + 
        +      // ********************************************************
        +      // * Output the data recieved from the cdevData object.
        +      // ********************************************************
        +      while(outString[i]!=NULL) 
        +         printf("String %i: %s\\n", i++, outString[i]);
        +      }
        +   }
        +			
        +
        +
        + +

        + + +

        + +

        +
        + + 7. +

        +
        + + + Using the cdevDirectory Device +

        +
        + + + cdevDirectory + Device +

        +
        + + The cdevDirectory device is a cdevDevice object that provides an interface to directory + services within CDEV. Directory services allow an application to obtain data that is + specified in the device definition file (DDL file). Information in the DDL file identifies + services, devices and messages that are supported by CDEV. +

        +
        + + + Attaching to the + cdevDirectory +

        +
        + + The cdevDirectory device can be accessed in the same manner as any other CDEV + device. Their are two methods for obtaining a cdevDirectory device. The first + approach is to get a pointer or reference to a cdevDevice object with the device name + set to cdevDirectory: "cdevDevice::attachPtr("cdevDirectory")" . +

        + The second approach allows the caller to obtain a pointer to the directory object from + the system object. +

        + The example below illustrates using the system object to obtain a pointer to a + cdevDirectory device. +

        + + +

        + + Figure 35: + + Attaching to the cdevDirectory device +
        + + + +
        + + +
        
        +// ***************************************************************
        +// * Include required CDEV header files
        +// ***************************************************************
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        + 
        +void main()
        +   {
        +   // ***********************************************************
        +   // * Obtain a reference to the default cdevSystem object
        +   // ***********************************************************
        +   cdevSystem & system = cdevSystem::defaultSystem();
        + 
        +   // ***********************************************************
        +   // * Obtain a pointer to the "cdevDirectory" device using the
        +   // * getDevice member function of the default cdevSystem
        +   // * object.
        +   // ***********************************************************
        +   cdevDevice * directory = system.getDevice("cdevDirectory");
        +   .
        +   .
        +   .
        +   }
        +			
        +
        +
        + +

        + + +

        +
        + + + Messages + Supported by + cdevDirectory +

        +
        + + An application communicates with the cdevDirectory device through the use of + predefined message strings. The following messages are supported by the + cdevDirectory device. +

        + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + query: Identify the devices that are members of a DDL class. +

        +
        + + 2. +

        +
        + + queryClass: Identify the DDL class from which a device is instantiated. +

        +
        + + 3. +

        +
        + + queryAttributes: Identify all attributes supported by a device or a DDL class. +

        +
        + + 4. +

        +
        + + queryMessages: Identify all messages supported by a device or DDL class. +

        +
        + + 5. +

        +
        + + queryVerbs: Identify all verbs supported by a device or DDL class. +

        +
        + + 6. +

        +
        + + service: Identify the service that is used by a device/message pair. +

        +
        + + 7. +

        +
        + + serviceData: Identify service data specified for a device/message pair. +

        +
        + + 8. +

        +
        + + update: Add information to the cdevDirectory data structure. +

        +
        + + 9. +

        +
        + + validate: Verify that a device or DDL class contains certain properties. +

        +
        +
        + + + "query" +

        +
        + + The "query" message is submitted to the cdevDirectory object in order to obtain a list + of matching devices that are instantiated from a specified DDL class. The class name + is specified as an absolute string. The device name may be specified either as an + absolute string or as a regular expression. +

        + The request is submitted to the cdevDirectory device through its send, sendCallback, + or sendNoBlock interface. The following table shows the inputs that must be placed in + the inbound cdevData object prior to submitting the command, and the outputs that + can be retrieved when the command is completed. +

        + +

        + + Figure 36: + + cdevData Input/Output associated with a "query" message + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + Tag Name +
        +
        + + Data Type +
        +
        + + Content +
        +
        + + Message Input +
        +
        + + device +
        +
        + + character string +
        +
        + + Regular expression identifying the device names + that should be retrieved. +
        +
        + + +
        +
        + + class +
        +
        + + character string +
        +
        + + Name of the DDL class that the devices should + be instantiated from. +
        +
        + + Message Output +
        +
        + + value +
        +
        + + array of strings +
        +
        + + Names of matching devices +
        +
        +

        + + The following figure shows the source code necessary to request the names of all + devices that are members of the DDL class "magnet". +

        + + Figure 37: + + Using the "query" Message with a cdevDirectory device +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   // ***********************************************************
        +   // * Use the shorthand method to obtain a pointer to the
        +   // * cdevDirectory device within the default system.
        +   // ***********************************************************
        +   cdevDevice *dir = cdevDevice::attachPtr("cdevDirectory");
        +   cdevData input, output;
        + 
        +   // ***********************************************************
        +   // * Insert the name of the DDL class and the regular 
        +   // * expression for the device.
        +   // ***********************************************************
        +   input.insert("class", "magnet");
        +   input.insert("device", ".*");
        + 
        +   // ***********************************************************
        +   // * Submit the request to the cdevDirectory object using the
        +   // * send command.
        +   // ***********************************************************
        +   if(dir->send("query", input, output)==CDEV_SUCCESS)
        +      {
        +      // ********************************************************
        +      // * If the command was successful, obtain a pointer to the
        +      // * list of names and output them on stdout.
        +      // ********************************************************
        +      char ** ptr;
        +      output.find("value", ptr);
        +      while(*ptr!=NULL) fprintf(stdout, "%s\\n", ptr++);
        +      }
        +   }
        +			
        +
        +
        + +

        +
        + + + "queryClass" +

        +
        + + The "queryClass" message is submitted to the cdevDirectory object in order to identify + the name of the DDL class that a device is instantiated from. +

        + The request is submitted to the cdevDirectory device through its send, sendCallback, + or sendNoBlock interface. The following table shows the inputs that must be placed in + the inbound cdevData object prior to submitting the command, and the outputs that + can be retrieved when the command is completed. +

        + +

        + + Figure 38: + + cdevData input/output associated with a "queryClass" message + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + Tag Name +
        +
        + + Data Type +
        +
        + + Content +
        +
        + + Message Input +
        +
        + + device +
        +
        + + character string +
        +
        + + Name of the device to be queried. +
        +
        + + Message Output +
        +
        + + value +
        +
        + + character string +
        +
        + + Names of the associated class +
        +
        +

        + + The following figure shows the source code necessary to determine the name of the + DDL class from which the device "MQB1S01" is derived. +

        + +

        + + Figure 39: + + Using the "queryClass" message with a cdevDirectory device +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevDevice *dir = cdevDevice::attachPtr("cdevDirectory");
        +   cdevData input, output;
        + 
        +   // ***********************************************************
        +   // * Insert the name of the DDL class.
        +   // ***********************************************************
        +   input.insert("device", "MQB1S01");
        + 
        +   // ***********************************************************
        +   // * Submit the request to the cdevDirectory object.
        +   // ***********************************************************
        +   if(dir->send("queryClass", input, output)==CDEV_SUCCESS)
        +      {
        +      // *******************************************************
        +      // * If successful, output the name of the DDL class.
        +      // *******************************************************
        +      char * ptr;
        +      output.find("value", ptr);
        +      fprintf(stdout, "MQB1S01 is a %s\\n", value);
        +      }
        +   }
        +			
        +
        +
        + +

        +
        + + + "queryAttributes" +

        +
        + + The "queryAttributes" message is submitted to the cdevDirectory object in order to + obtain a list of all attributes that are contained within a specified device or DDL class. +

        + The request is submitted to the cdevDirectory device through its send, sendCallback, + or sendNoBlock interface. The following table shows the inputs that must be placed in + the inbound cdevData object prior to submitting the command, and the outputs that + can be retrieved when the command is completed. +

        + +

        + + Figure 40: + + cdevData input/output associated with a "queryAttributes" message + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + Tag Name +
        +
        + + Data Type +
        +
        + + Content +
        +
        + + Message Input +
        +
        + + device or +
        +
        + + character string +
        +
        + + Name of the device to be queried. +
        +
        + + +
        +
        + + class +
        +
        + + character string +
        +
        + + Name of the DDL class to be queried. +
        +
        + + Message Output +
        +
        + + value +
        +
        + + array of strings +
        +
        + + Names of matching attributes +
        +
        +

        + + The following figure shows the source code necessary to request the names of all + attributes that are defined within the DDL class "magnet". +

        + +

        + + Figure 41: + + Using the "queryAttributes" message with a cdevDirectory device +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevDevice *dir = cdevDevice::attachPtr("cdevDirectory");
        +   cdevData input, output;
        + 
        +   // ***********************************************************
        +   // * Insert the name of the DDL class.
        +   // ***********************************************************
        +   input.insert("class", "magnet");
        + 
        +   // ***********************************************************
        +   // * Submit the request to the cdevDirectory object using the
        +   // * send command.
        +   // ***********************************************************
        +   if(dir->send("queryAttributes", input, output)==CDEV_SUCCESS)
        +      {
        +      // *******************************************************
        +      // * If the command was successful, obtain a pointer to 
        +      // * the list of attributes and output them on stdout.
        +      // *******************************************************
        +      char ** ptr;
        +      output.find("value", ptr);
        +      while(*ptr!=NULL) fprintf(stdout, "%s\\n", ptr++);
        +      }
        +   }
        +			
        +
        +
        + +

        +
        + + + "queryMessages" +

        +
        + + The "queryMessages" message is submitted to the cdevDirectory object in order to + obtain a list of all messages that are contained within a specified device or DDL class. +

        + The request is submitted to the cdevDirectory device through its send, sendCallback, + or sendNoBlock interface. The following table shows the inputs that must be placed in + the inbound cdevData object prior to submitting the command, and the outputs that + can be retrieved when the command is completed. +

        + +

        + + Figure 42: + + cdevData input/output associated with a "queryMessages" message + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + Tag Name +
        +
        + + Data Type +
        +
        + + Content +
        +
        + + Message Input +
        +
        + + device or +
        +
        + + character string +
        +
        + + Name of the device to be queried. +
        +
        + + +
        +
        + + class +
        +
        + + character string +
        +
        + + Name of the DDL class to be queried. +
        +
        + + Message Output +
        +
        + + value +
        +
        + + array of strings +
        +
        + + Names of matching messages +
        +
        +

        + + The following figure shows the source code necessary to request the names of all + messages that are defined within the DDL class "magnet". +

        + +

        + + Figure 43: + + Using the "queryMessages" message with a cdevDirectory device +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevDevice *dir = cdevDevice::attachPtr("cdevDirectory");
        +   cdevData input, output;
        + 
        +   // ***********************************************************
        +   // * Insert the name of the DDL class.
        +   // ***********************************************************
        +   input.insert("class", "magnet");
        + 
        +   // ***********************************************************
        +   // * Submit the request to the cdevDirectory object using the
        +   // * send command, and output the result if successful.
        +   // ***********************************************************
        +   if(dir->send("queryMessages", input, output)==CDEV_SUCCESS)
        +      {
        +      char ** ptr;
        +      output.find("value", ptr);
        +      while(*ptr!=NULL) fprintf(stdout, "%s\\n", ptr++);
        +      }
        +   }
        +			
        +
        +
        + +

        +
        + + + "queryVerbs" +

        +
        + + The "queryVerbs" message is submitted to the cdevDirectory object in order to obtain + a list of all verbs that are contained within a specified device or DDL class. +

        + The request is submitted to the cdevDirectory device through its send, sendCallback, + or sendNoBlock interface. The following table shows the inputs that must be placed in + the inbound cdevData object prior to submitting the command, and the outputs that + can be retrieved when the command is completed. +

        + +

        + + Figure 44: + + cdevData input/output associated with a "queryVerbs" message + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + Tag Name +
        +
        + + Data Type +
        +
        + + Content +
        +
        + + Message Input +
        +
        + + device or +
        +
        + + character string +
        +
        + + Name of the device to be queried. +
        +
        + + +
        +
        + + class +
        +
        + + character string +
        +
        + + Name of the DDL class to be queried. +
        +
        + + Message Output +
        +
        + + value +
        +
        + + character strings +
        +
        + + Names of matching verbs. +
        +
        +

        + + The following figure shows the source code necessary to request the names of all + verbs that are defined within the DDL class "magnet". +

        + +

        + + Figure 45: + + Using the "queryVerbs" message with a cdevDirectory device +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevDevice *dir = cdevDevice::attachPtr("cdevDirectory");
        +   cdevData input;
        +   cdevData output;
        + 
        +   // ***********************************************************
        +   // * Insert the name of the DDL class.
        +   // ***********************************************************
        +   input.insert("class", "magnet");
        + 
        +   // ***********************************************************
        +   // * Submit the request to the cdevDirectory object using the
        +   // * send command, and output the result if successful.
        +   // ***********************************************************
        +   if(dir->send("queryVerbs", input, output)==CDEV_SUCCESS)
        +      {
        +      char ** ptr;
        +      output.find("value", ptr);
        +      while(*ptr!=NULL) fprintf(stdout, "%s\\n", ptr++);
        +      }
        +   }
        +			
        +
        +
        + +

        +
        + + + "service" +

        +
        + + The "service" message is submitted to the cdevDirectory object in order to identify + which CDEV service will respond to a specified device / message combination. The + caller specifies the device name and the message string in the input cdevData object + and can retrieve the result from the value entry in the resulting output cdevData object. + This message will normally only be used internally by CDEV. +

        + The request is submitted to the cdevDirectory device through its send, sendCallback, + or sendNoBlock interface. The following table shows the inputs that must be placed in + the inbound cdevData object prior to submitting the command, and the outputs that + can be retrieved when the command is completed. +

        + +

        + + Figure 46: + + cdevData input/output associated with a "service" message + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + Tag Name +
        +
        + + Data Type +
        +
        + + Content +
        +
        + + Message Input +
        +
        + + device +
        +
        + + character string +
        +
        + + Name of the CDEV device. +
        +
        + + +
        +
        + + message +
        +
        + + character string +
        +
        + + Name of the message. +
        +
        + + Message Output +
        +
        + + value +
        +
        + + character string +
        +
        + + Name of the service that will respond to the + specified device and message. +
        +
        +

        + + The following figure shows the source code necessary to resolve the name of the + service that will respond to the device "DEV1" and the message "get VAL". +

        + +

        + + Figure 47: + + Using the "service" message with a cdevDirectory device +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevDevice *dir = cdevDevice::attachPtr("cdevDirectory");
        +   cdevData input, output;
        +   
        +   // ************************************************************
        +   // * Insert the name of the device and message to be resolved.
        +   // ************************************************************
        +   input.insert("device", "DEV1");
        +   input.insert("message", "get VAL");
        + 
        +   // ************************************************************
        +   // Submit the request to the cdevDirectory object using the
        +   // send command, and output the result if successful.
        +   // ************************************************************
        +   if(dir->send("service", input, output)==CDEV_SUCCESS)
        +      {
        +      char * ptr;
        +      output.find("value", ptr);
        +      fprintf(stdout, "Service name is:%s\\n", ptr);
        +      }
        +   }
        +			
        +
        +
        + +

        +
        + + + "serviceData" +

        +
        + + The "serviceData" message is submitted to the cdevDirectory object in order to obtain + service specific data that is associated with a device or a message. The information + will be returned to the caller in the output cdevData object in the form of tagged data + items. This message will normally only be used in the development of a new CDEV + service. +

        + The request is submitted to the cdevDirectory device through its send, sendCallback, + or sendNoBlock interface. The following table shows the inputs that must be placed in + the inbound cdevData object prior to submitting the command, and the outputs that + can be retrieved when the command is completed. +

        + +

        + + Figure 48: + + cdevData input/output associated with a "serviceData" message + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + Tag Name +
        +
        + + Data Type +
        +
        + + Content +
        +
        + + Message Input +
        +
        + + device +
        +
        + + character string +
        +
        + + Name of the CDEV device. +
        +
        + + +
        +
        + + message +
        +
        + + character string +
        +
        + + Name of the message. +
        +
        + + Message Output +
        +
        + + (service + specific) +
        +
        + + character string +
        +
        + + Data items specified in the service data section + for the specified device / message combination. +
        +
        +

        + + The following figure shows the source code necessary to obtain the serviceData + associated with the device "DEV1" and the message "get VAL". +

        + +

        + + Figure 49: + + Using the "serviceData" message with a cdevDirectory device +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevDevice *dir = cdevDevice::attachPtr("cdevDirectory");
        +   cdevData input, output;
        + 
        +   // ***********************************************************
        +   // * Insert the name of the device and message to be resolved.
        +   // ***********************************************************
        +   input.insert("device", "DEV1");
        +   input.insert("message", "get VAL");
        + 
        +   // ***********************************************************
        +   // * Submit the request to the cdevDirectory object using the
        +   // * send command, and output the result (using asciiDump) if 
        +   // * successful.
        +   // ***********************************************************
        +   if(dir->send("serviceData", input, output)==CDEV_SUCCESS)
        +      {
        +      output.asciiDump(stdout);
        +      }   
        +   }
        +			
        +
        +
        + +

        +
        + + + "update" +

        +
        + + The "update" message is submitted to the cdevDirectory object in order to add new or + updated class definitions or device instances to the internal device definition data + structures. The data that is submitted in the input cdevData object is in the same form + as a corresponding entry in the CDEV DDL file. +

        + The request is submitted to the cdevDirectory device through its send, sendCallback, + or sendNoBlock interface. The following table shows the inputs that must be placed in + the inbound cdevData object prior to submitting the command, and the outputs that + can be retrieved when the command is completed. +

        + +

        + + Figure 50: + + cdevData input/output associated with a "update" message + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + Tag Name +
        +
        + + Data Type +
        +
        + + Content +
        +
        + + Message Input +
        +
        + + value or +
        +
        + + character string +
        +
        + + ASCII text definition of a DDL class or device + instanciation. +
        +
        + + +
        +
        + + file +
        +
        + + character string +
        +
        + + Complete path to the file containing the updated + DDL information. +
        +
        + + Message Output +
        +
        + + value +
        +
        + + integer +
        +
        + + Boolean completion status of the operation. +
        +
        +

        + + The following figure shows the source code necessary to insert the class definition for + the "stdio" class into the device definition data structure using the cdevDirectory + object. +

        + +

        + + Figure 51: + + Using the "update" message with a cdevDirectory device +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevDevice *dir = cdevDevice::attachPtr("cdevDirectory");
        +   cdevData input, output;
        + 
        +   // ***********************************************************
        +   // * Class definition to insert.
        +   // *********************************************************** 
        +   char *def = "class stdio{verbs{get,set,monitorOn,monitorOff}}";
        + 
        +   // ***********************************************************
        +   // * Insert the class definition.
        +   // ***********************************************************
        +   input.insert("value", def);
        + 
        +   // ***********************************************************
        +   // * Submit the request to the cdevDirectory object.
        +   // ***********************************************************
        +   dir->send("update", input, output)
        +   }
        +			
        +
        +
        + +

        +
        + + + "validate" +

        +
        + + The "validate" message is submitted to the cdevDirectory object in order to verify that + a combination of device, DDL class, verb, attribute or message represent a valid + combination. +

        + At least one of device or DDL class must be specified when using this message. If + both are specified, the cdevDirectory object will confirm that the device is a member of + the specified DDL class. +

        + If verb, attribute or message are included, the cdevDirectory object will determine if + each of them are members of the specified device and/or DDL class. +

        + The request is submitted to the cdevDirectory device through its send, sendCallback, + or sendNoBlock interface. The following table shows the inputs that must be placed in + the inbound cdevData object prior to submitting the command, and the outputs that + can be retrieved when the command is completed. +

        + +

        + + Figure 52: + + cdevData input/output associated with a "validate" message + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + Tag Name +
        +
        + + Data Type +
        +
        + + Content +
        +
        + + Message Input +
        +
        + + device or +
        +
        + + character string +
        +
        + + Name of the CDEV device. +
        +
        + + +
        +
        + + class +
        +
        + + character string +
        +
        + + Name of the DDL class. +
        +
        + + +
        +
        + + attribute +
        +
        + + character string +
        +
        + + Name of the attribute to validate (optional) +
        +
        + + +
        +
        + + message +
        +
        + + character string +
        +
        + + Name of the message to validate (optional) +
        +
        + + +
        +
        + + verb +
        +
        + + character string +
        +
        + + Name of the verb to validate (optional) +
        +
        + + Message Output +
        +
        + + value +
        +
        + + integer +
        +
        + + Boolean completion status of the operation. +
        +
        +

        + + The following figure shows the source code necessary to determine if the verb + "monitorOn" is a member of the class "stdio". +

        + +

        + + Figure 53: + + Using the "update" message with a cdevDirectory device +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevData.h>
        + 
        +void main()
        +   {
        +   cdevDevice *dir = cdevDevice::attachPtr("cdevDirectory");
        +   cdevData input, output;
        +   int result;
        + 
        +   input.insert("class", "stdio");
        +   input.insert("verb", "monitorOn");
        + 
        +   // ***********************************************************
        +   // * Submit the request to the cdevDirectory object.
        +   // ***********************************************************
        +   dir->send("validate", input, output)
        +   result = (int)output;
        +   fprintf(stdout, "monitorOn %s in stdio", result?"IS":"IS NOT");
        +   }
        +			
        +
        +
        + +

        +
        + + 8. +

        +
        + + + Default Service Behavior for Standard Messages +

        +
        + + + Overview +

        +
        + + The CDEV library is designed to provide a standard calling interface to dissimilar + devices within a control system. This interface is accommodated through the use of + the cdevDevice methods send, sendNoBlock and sendCallback. However, because + each service can define the names and behaviors of the messages that it supports, + the user must be increasingly aware of which service may process its messages. +

        + In order to reduce the required knowledge of the user, and to improve the consistency + of all services, all CDEV services should provide well-defined support for a minimum + list of verbs. +

        + The following verbs should be implemented to provide a standard behavior in all + CDEV services: get, set, monitorOn, and monitorOff. +

        +
        + + + "get" Message +

        +
        + + The "get" verb can be joined with any attribute of a device to form a "get" message. + This message is then sent to the device in order to obtain the value of specified + properties of the attribute. The following steps should be executed in order to utilize a + "get" message. +

        + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + Obtain a pointer to the cdevDevice object for the device that you wish to address. +

        +
        + + 2. +

        +
        + + Create a message string by concatenating the attribute that you wish to address + to the "get" verb. For instance, to get the VAL attribute of a device, the message + strings should be: "get VAL". +

        +
        + + 3. +

        +
        + + Optionally, use the cdevDevice object created in step 1 and the message string + created in step 2 to obtain a pointer to a cdevRequestObject object. +

        +
        + + 4. +

        +
        + + Set the context of the cdevDevice or cdevRequestObject to indicate which + properties you wish to obtain. A non-zero value in any property indicates that its + value should be returned. If no context has been specified, the service should + return the value property by default. A complete description of the context data + object is provided in the cdevDevice documentation. +

        +
        + + 5. +

        +
        + + Use the send, sendNoBlock, or sendCallback message to submit the message + to the device. +

        +
        + + 6. +

        +
        + + Evaluate the return value from the send command to determine if the operation + completed successful. Any value other than CDEV_SUCCESS indicates that an + error occurred in handling the message. +

        +
        + + 7. +

        +
        + + If the call was completed successfully, extract the desired properties from the + resultant cdevData object. +

        +
        +
        + + + "set" Message +

        +
        + + The "set" verb can be joined with any attribute of a device to form a "set" message. + This message is then sent to the device in order to set the value property of the + attribute. The following steps should be executed in order to utilize a "set" message. +

        + + + + + + + + + + + + + +
        + + 1. +

        +
        + + Obtain a pointer to the cdevDevice object for the device that you wish to address. +

        +
        + + 2. +

        +
        + + Create a message string by concatenating the attribute that you wish to address + to the "set" verb. For instance, to set the bdl attribute of a device, the message + string should be: "set bdl". +

        +
        + + 3. +

        +
        + + Optionally, use the cdevDevice object created in step 1 and the message string + created in step 2 to obtain a pointer to a cdevRequestObject object. +

        +
        + + 4. +

        +
        + + Set the value property of the outbound cdevData object to the new value. +

        +
        + + 5. +

        +
        + + Use the send, sendNoBlock, or sendCallback message to submit the message + to the device. +

        +
        + + 6. +

        +
        + + Evaluate the return value from the specific send command to determine if the + message was transmitted successful. Any value other than CDEV_SUCCESS + indicates that the message was not transmitted successfully. +

        +
        + + In the following example, the "get" message will be used to obtain the properties + value, status and severity from the bdl attribute of device MQB1S01, the "set" + message will then be used to copy the value property to the bdl attribute of device + MQB1S02. +

        + +

        + + Figure 54: + + Default behavior of the "get" and "set" messages +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevRequestObject.h>
        +#include <cdevData.h>
        + 
        +// ****************************************************************
        +// * The printError function will be used to output any error that
        +// * that occurs during the processing of the "get" or "set"
        +// * messages.
        +// ****************************************************************
        +int printError ( int errCode )
        +   {
        +   switch(errCode) 
        +      {   
        +      // ******* Unknown device or device/message mismatch ******
        +      case CDEV_INVALIDOBJ:
        +         printf("Unknown device or device/message mismatch\\n");
        +         break;
        + 
        +      // * Communications error between application and service *
        +      case CDEV_NOTCONNECTED:
        +      case CDEV_IOFAILED:
        +      case CDEV_TIMEOUT:
        +         printf("Communications error while sending\\n");
        +         break;
        + 
        +			
        +
        +
        + +

        + + Figure 54: + Default behavior of the "get" and "set" messages (continued) +
        + + + +
        + + +
        
        +      // ******* No data or bad data passed with message ********
        +      case CDEV_INVALIDARG:
        +      case CDEV_OUTOFRANGE:
        +      case CDEV_NOTFOUND:
        +      case CDEV_CONVERT:
        +         printf("Bad or missing value passed in message\\n");
        +         break;
        + 
        +      // ******************** Generic Error *********************
        +      case CDEV_ERROR:
        +      case default:
        +         printf("Unable to send message\\n");
        +         break;
        +      }
        +   }
        + 
        +void main()
        +   {
        +   cdevRequestObject * req1, *req2;
        +   cdevData            ctx;
        +   cdevData            output, input;
        +   double              val;
        +   int                 errorCode = CDEV_SUCCESS;
        + 
        +   // ***********************************************************
        +   // * Obtain a pointer to the cdevRequestObject for the
        +   // * "get bdl" message on device "MQB1S01".
        +   // ***********************************************************
        +   req1 = cdevRequestObject::attachPtr("MQB1S01", "get bdl");
        + 
        +   // ***********************************************************
        +   // * Place a non-zero value in the properties value, status,
        +   // * severity.
        +   // ***********************************************************
        +   ctx.set("value", 1);
        +   ctx.set("status", 1);
        +   ctx.set("severity", 1);
        +   
        +   // ***********************************************************
        +   // * Set the context of the cdevRequestObject.
        +   // ***********************************************************
        +   req1->setContext(ctx);
        + 
        +   // ***********************************************************
        +   // * Submit the message to the device and test the return 
        +   // * value to ensure that the message was processed correctly
        +   // ***********************************************************
        +   if((errorCode=req1->send(NULL, &output))==CDEV_SUCCESS) 
        +      {
        +      // ********************************************************
        +      // * Message was transmitted and processed successfuly.
        +      // ********************************************************
        +      char   stat[50], sev[255];
        +      output.get("value", &val);
        + 
        +			
        +
        +
        + +

        + + Figure 54: + Default behavior of the "get" and "set" messages +
        + + + +
        + + +
        
        +      output.get("status", stat, 50);
        +      output.get("severity", sev, 50);
        +      printf("Val:%f, status:%s, severity:%s", val, stat, sev);
        +      }   
        +   else printError(errorCode);
        + 
        +   // ***********************************************************
        +   // * Obtain a pointer to the cdevRequestObject for the
        +   // * "set bdl" message on device "MQB1S02".
        +   // ***********************************************************
        +   req2 = cdevRequestObject::attachPtr("MQB1S02", "set bdl");
        + 
        +   // ***********************************************************
        +   // * Insert the new value into the input cdevData object.
        +   // ***********************************************************
        +   input.insert("value", value);
        + 
        +   // ***********************************************************
        +   // * Submit the message "set bdl" to the device and test 
        +   // * the return value to ensure that the message was 
        +   // * processed successfully. Note that, by default, the set
        +   // * message does not generate any output.
        +   // ***********************************************************
        +   if((errorCode==req2->send(&input, NULL))==CDEV_SUCCESS) 
        +      {
        +      // ********************************************************
        +      // * Message was transmitted and processed successfuly.
        +      // ********************************************************
        +      printf("Message was transmitted successfully\\n");
        +      }
        +   else printError(errorCode);
        +   }
        +			
        +
        +
        + +

        +
        + + + "monitorOn" + Message +

        +
        + + The "monitorOn" verb can be joined with any attribute of a device to form a + "monitorOn" message. This message is tells the cdevDevice that each time one of the + monitored properties changes, it should call the user specified callback function with + the updated value. This message should always be submitted using the + sendCallback method of the cdevDevice or cdevRequestObject in order to provide + the address of the callback function. +

        + The following steps should be executed in order to submit a "monitorOn" message. +

        + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + Obtain a pointer to the cdevDevice object for the device that you wish to address. +

        +
        + + 2. +

        +
        + + Create a message string by concatenating the attribute that you wish to address + to the "monitorOn" verb. For instance, to monitor a property of the bdl attribute of a + device, the message string should be: "monitorOn bdl". +

        +
        + + 3. +

        +
        + + Optionally, use the cdevDevice object created in step 1 and the message string + created in step 2 to obtain a pointer to a cdevRequestObject object. +

        +
        + + 4. +

        +
        + + Set the context of the cdevDevice or cdevRequestObject to indicate the properties + that you wish to monitor, and the properties you wish to receive when a change + occurs. The context used by the "monitorOn" message differs from that of the + "get" message in that different non-zero values have special meanings. The + following is a list of integer values that should be supported by the context of a + "monitorOn" message. +

        + + 0 The value of this property should never be + returned. +

        + +

        + 1 This property should not be monitored, but it + should be returned as context when a monitored + value changes; e.g. a time stamp. +

        + +

        + 2 Monitor this property and call the callback function + when it changes, however, return only this property + in the resultant cdevData object. +

        + +

        + 3 Monitor this property and call the callback function + when it changes and include the value of all + properties whose context is 1 in the resultant + cdevData object. +

        + +

        +
        + + 5. +

        +
        + + Create a cdevCallback object that contains the address of the cdevCallback + function and a void pointer to any user argument that should be provided to the + callback function. +

        +
        + + 6. +

        +
        + + Use the sendCallback message to submit the message to the device. +

        +
        + + 7. +

        +
        + + Evaluate the return value from the specific sendCallback command to determine + if the message was transmitted successful. Any value other than + CDEV_SUCCESS indicates that the message was not transmitted successfully. +

        +
        + + 8. +

        +
        + + Monitor the status returned to the cdevCallbackFunction to determine if the + callback is operating correctly. Any of the following values may be returned in the + status parameter. +

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + CDEV_SUCCESS: +

        +
        + + The value has changed and the new value is + stored in the cdevData parameter. This status is + also generated when the monitorOn command + is initially issued. +

        +
        + + + CDEV_DISCONNECTED: +

        +
        + + The connection has been lost between the + application and the server. +

        +
        + + + CDEV_RECONNECTED: +

        +
        + + The connection between the application and the + server has been re-established and the updated + value is available in the cdevData parameter. +

        +
        + + + CDEV_ERROR: +

        +
        + + The message was not processed successfully. +

        +
        + + + CDEV_INVALIDOBJ: +

        +
        + + Invalid cdev request object used. +

        +
        + + + CDEV_INVALIDARG: +

        +
        + + Invalid argument passed to cdev call. +

        +
        + + + CDEV_INVALIDSVC: +

        +
        + + Wrong service during dynamic loading. +

        +
        + + + CDEV_NOTCONNECTED: +

        +
        + + Not connected to low level network service. +

        +
        + + + CDEV_IOFAILED: +

        +
        + + Low level network service IO failed. +

        +
        + + + CDEV_CONFLICT: +

        +
        + + Conflicts of data types or tags. +

        +
        + + + CDEV_NOTFOUND: +

        +
        + + Cannot find specified data in cdevData. +

        +
        + + + CDEV_TIMEOUT: +

        +
        + + Time out. +

        +
        + + + CDEV_CONVERT: +

        +
        + + cdevData conversion error. +

        +
        + + + CDEV_OUTOFRANGE: +

        +
        + + Value out of range for device attribute. +

        +
        + + + CDEV_NOACCESS: +

        +
        + + Insufficient access to perform request. +

        +
        + + + CDEV_ACCESSCHANGED: +

        +
        + + Change in access permission of device. +

        +
        +
        + + 9. +

        +
        + + Because the monitorOn command is a single message that may generate many + responses, the developer may have difficulty in determining when the last reply + has been received. In order to accomodate this, the developer may call the + cdevCallback::isTransactionDone() method to determine if the callback that is + being processed is the last one that is associated with that request. The service + developer is expected to use the cdevCallback::fireCallback method to ensure that + this parameter is set to the proper value. +

        +
        +
        + + + "monitorOff" + Message +

        +
        + + The "monitorOff" verb can be joined with any attribute of a device to form a + "monitorOff" message. This message is tells the cdevDevice to deactivate a + monitorOn command that was previously set on one or more of its attributes. +

        + This message should always be called using the sendCallback method in order to + specify the address of the callback function that was used in creating the monitor. +

        + The service checks the following things to determine which monitor is to be removed. +

        + + + + + + + + + +
        + + + device +

        +
        + + The service will locate all active monitors that + have been placed on the specified device. +

        +
        + + + attribute +

        +
        + + From the list of obtained above, the service will + locate all active monitors on the specified + attribute. +

        +
        + + + function +

        +
        + + From the list obtained above, the service will + locate all active monitors that have the specified + callback function. If this value is NULL, then all + elements from the previous list will be removed. +

        +
        + + + userarg +

        +
        + + From the list obtained above, the service will + locate and remove all monitors that have the + same user argument. If this value is NULL, then + all elements from the previous list will be + removed. +

        +
        + + The following steps should be executed in order to submit a "monitorOff" message. +

        + + + + + + + + + + + +
        + + 1. +

        +
        + + Obtain a pointer to the cdevDevice object for the device that you wish to address. +

        +
        + + 2. +

        +
        + + Create a message string by concatenating the attribute that you wish to address + to the "monitorOff" verb. For instance, to monitor a property of the bdl attribute of a + device, the message string should be: "monitorOn bdl". +

        +
        + + 3. +

        +
        + + Optionally, use the cdevDevice object created in step 1 and the message string + created in step 2 to obtain a pointer to a cdevRequestObject object. +

        +
        + + 4. +

        +
        + + Create a cdevCallback object that contains the address of the cdevCallback + function and a void pointer to the user argument that was originally provided to the + monitorOn message. +

        +
        + + 5. +

        +
        + + Use the sendCallback message to submit the message to the device. +

        +
        + + The following example illustrates how to use the "monitorOn" and "monitorOff" to + install and remove monitors. This example also demonstrates the to correct way to + utilize the cdevCallback function. +

        + +

        + + Figure 55: + + Default behavior of the "monitorOn" and "monitorOff" messages +
        + + + +
        + + +
        
        +#include <cdevSystem.h>
        +#include <cdevDevice.h>
        +#include <cdevRequestObject.h>
        +#include <cdevData.h>
        +#include <cdevCallback.h>
        + 
        +// ****************************************************************
        +// * This is the callback function that will be executed each time
        +// * one of my monitored values changes.
        +// ****************************************************************
        +void callback (int status, void * userarg, 
        +             cdevRequestObject & req, cdevData & data)
        +   {
        +   switch(status)
        +      {
        +      // *********************************************************
        +      // * If I receive one of these message then I know that 
        +      // * updated data is available in the cdevData object.
        +      // *********************************************************
        +      case CDEV_SUCCESS:
        +      case CDEV_RECONNECTED:
        +         // ******************************************************
        +         // * I will call the getType method to determine if the
        +         // * value attribuite is present in the cdevData object.
        +         // * If it is, then I will known that it is responsible
        +         // * for triggering this callback.
        +         // ******************************************************
        +         if(data.getType("value")!=CDEV_INVALID)
        +            {         
        +            // **************************************************
        +            // * I have specified that I wanted status and 
        +            // * severity to be returned as context whenever the 
        +            // * value property has changed.  Therefore, I will 
        +            // * output all of these properties.
        +            // **************************************************
        +            double * valPtr;
        +            char   * statPtr;
        +            char   * sevPtr;
        +            data.find("value",    (void *&)valPtr);
        +            data.find("status",   (void *&)statPtr);
        +            data.find("severity", (void *&)sevPtr);
        +            printf("Val:%f, status:%s, severity:%s", 
        +                  *valPtr, statPtr, sevPtr);
        +            }
        +         // ******************************************************
        +         // * I will call the getType method of the cdevData 
        +         // * object to determine if the controlHigh property is
        +         // * present. If it is, I will know that it triggered
        +         // * this callback.    
        +         // ******************************************************
        +			
        +
        +
        + +

        + + Figure 55: + Default behavior of the "monitorOn" and "monitorOff" messages (continued) +
        + + + +
        + + +
        
        +         else if(getType("controlHigh")!=CDEV_INVALID)
        +            {
        +            double * controlPtr;
        +            data.find("controlHigh", (void *&) controlPtr);
        +            printf("Control High is now %f\\n", *controlPtr);
        +            }
        +      break;
        + 
        +      // *********************************************************
        +      // * This status indicates that the connection has been lost
        +      // * between the application and the server.
        +      // *********************************************************
        +      case CDEV_DISCONNECTED:
        +         fprintf(stderr, "Connection lost to server\\n");
        +         break;
        + 
        +      // *********************************************************
        +      // * This status indicates that an error occurred while 
        +      // * installing or operating the monitor.
        +      // *********************************************************
        +      case CDEV_ERROR:
        +         fprintf(stderr, "Error while monitoring");
        +         break;
        +      }
        +   }
        + 
        +void main()
        +   {
        +   cdevSystem        * system;
        +   cdevDevice        * dev;
        +   cdevRequestObject * req;
        +   cdevData            ctx;
        + 
        +   // ***********************************************************
        +   // * Construct a cdevCallback object that has a pointer to the
        +   // * cdevCallback function and a NULL user argument.
        +   // ***********************************************************
        +   cdevCallback cb(callback, NULL);
        + 
        +   // ***********************************************************
        +   // * Obtain a pointer to the default cdevSystem in order to
        +   // * accomodate polling.
        +   // ***********************************************************
        +   system = &cdevSystem::defaultSystem();
        + 
        +   // ***********************************************************
        +   // * Obtain a pointer to the cdevDevice MQB1S01
        +   // ***********************************************************
        +   dev = cdevDevice::attachPtr("MQB1S01");
        + 
        +   // ***********************************************************
        +   // * Obtain a pointer to the cdevRequestObject for the
        +   // * "monitorOff bdl" message on device "MQB1S01".
        +   // ***********************************************************
        +   req = dev->getRequestObject("MQB1S01", "monitorOn bdl");
        +			
        +
        +
        + +

        + + Figure 55: + Default behavior of the "monitorOn" and "monitorOff" messages (continued) +
        + + + +
        + + +
        
        + 
        +   // ###########################################################
        +   // # Setup the context to indicate the data that should be 
        +   // # returned whenever one of the values is changed.
        +   // ###########################################################
        + 
        +   // ***********************************************************
        +   // * Any time the "value" property changes, I want to receive
        +   // * the "status" and "severity" properties.
        +   // ***********************************************************
        +   ctx.insert("value", 3);
        +   ctx.insert("status", 1);
        +   ctx.insert("severity", 1);
        + 
        +   // ***********************************************************
        +   // * Any time the "controlhigh" property changes, I only want
        +   // * to receive its new value.
        +   // ***********************************************************
        +   ctx.insert("controlHigh", 2);
        + 
        +   // ***********************************************************
        +   // * Set the context of the cdevRequestObject to the new 
        +   // * context.
        +   // ***********************************************************
        +   req->setContext(ctx);
        + 
        +   // ************************************************************
        +   // * Submit the "monitorOn" message using the sendCallback
        +   // * method of the cdevRequestObject.
        +   // ************************************************************
        +   if(req->sendCallback(NULL, cb)==CDEV_SUCCESS)
        +      {
        +      // ********************************************************
        +      // * Pend for 60 second.
        +      // ********************************************************
        +      system->pend(60.0);
        +      
        +      // ********************************************************
        +      // * Send a "monitorOff bdl" message to disable the monitor
        +      // * that was just installed.
        +      // ********************************************************
        +      dev->sendCallback("monitorOff bdl", NULL, cb);
        +      }
        +   else fprintf(stderr, "Failed to install monitor\\n");
        +   }
        +			
        +
        +
        + +

        +
        + diff --git a/doc/html/cdevUtilities.html b/doc/html/cdevUtilities.html new file mode 100755 index 0000000..9a8476f --- /dev/null +++ b/doc/html/cdevUtilities.html @@ -0,0 +1,589 @@ + + +CDEV Documentation + + + + + + +


        + + + +
        + + + + CDEV Utilities +

        + + Utility Applications of the Control Device Interface +

        + + +

        + Chip Watson, Jie Chen, Danjin Wu, Walt Akers +

        + +

        + Version 1.5 - December 9, 1996 +

        + +

        + TJNAF - Thomas Jefferson National Accelerator Facility +

        +
        + +


        + + + + + +
        + + + + Table of Contents +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +
        +
        + + The cdevUtil Command Line Utility +
        +
        + + +
        +
        + + Overview +
        +
        + + +
        +
        + + Location of Files +
        +
        + + +
        +
        + + Starting cdevUtil +
        +
        + + +
        +
        + + Arguments to cdevUtil +
        +
        + + +
        +
        + + Syntax of cdevUtil Commands +
        +
        + + +
        +
        + + Exiting from cdevUtil +
        +
        + + +
        +
        + + cdevUtil Internal Commands +
        +
        + + 2. +
        +
        + + The cddl Device Definition File Compiler +
        +
        + + +
        +
        + + Overview +
        +
        + + +
        +
        + + Location of Files +
        +
        + + +
        +
        + + Using the cddl Compiler +
        +
        +
        + +


        + + + + + +
        + + + + List of Figures +

        +
        + + + + Figure 1: + Submitting batch commands to cdevUtil +
        + + Figure 2: + Entering commands using cdevUtil +
        + + Figure 3: + Typical output from the cddl compiler +
        +
        + +


        + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + + The cdevUtil Command Line Utility +

        +
        + + + Overview +

        +
        + + The cdevUtil application provides cdev user's with a simple application that can be + used to communicate with cdev services. This program provides a direct interface to + most of the capabilities of cdev and is commonly used to test a newly created service + or to ensure that changes made to a DDL file are behaving as expected. +

        +
        + + + Location of Files +

        +
        + + The source code for cdevUtil is located in the $(CDEV)/src/utility directory. This + application is automatically compiled whenever the cdev library is built. The binary + executable is placed in the directory $(CDEV)/bin/$(TARGET) when the application is + compiled. Once the cdev libraries and applications are compiled, this directory should + be placed in your search path. +

        +
        + + + Starting cdevUtil +

        +
        + + The cdevUtil utility is executed from the UNIX command line by typing cdevUtil + <Return>. If the cdev binary directory is not in your path, then you will have to provide + the complete path on the command line. The CDEVDDL environment variable should + be specified prior to starting the utility because cdevUtil will use this environment + variable to locate and load the device definition file. +

        +
        + + + Arguments to + cdevUtil +

        +
        + + When starting the cdevUtil utility, the user may provide a list of strings as arguments. + Each of these strings will be treated as a single command and will be processed + before the command line prompt is displayed. Any command that is supported by + cdevUtil may be submitted as an argument, including, "debug on", "debug off", and + "quit". The syntax of individual commands is described in the section titled Syntax of + cdevUtil Commands. +

        + The following figure shows how three command line arguments can be submitted to + cdevUtil to be processed in batch mode. +

        + +

        + + Figure 1: + + Submitting batch commands to cdevUtil +
        + + + +
        + + +
        
        +host1:> cdevUtil "debug on" "IPM1S01 set VAL value=25.0" "quit"
        + 
        +Submitting batch cdev commands...
        +-------------------- DEBUG OUTPUT -------------------
        +Attempting to transmit using the following parameters
        +Device: IPM1S01
        +Verb:   set
        +Attrib: VAL
        +Tag: value = 25
        + 
        +SUCCESS: Device: IPM1S01 - Message: set VAL - Value: None
        +------------------ END DEBUG OUTPUT -----------------
        + 
        +host1:> 
        +			
        +
        +
        + +

        +
        + + + Syntax of cdevUtil + Commands +

        +
        + + The cdevUtil utility uses a simple syntax with the following format: +

        + + + +
        + + + deviceName verb attributeName tag1=xxx tag2=xxx ... +

        + +

        + + + + + + + + + +
        + + deviceName +

        +
        + + The name of the cdev device that the message should be sent + to. +

        +
        + + verb +

        +
        + + The verb component of the message string. For a channel + access device this will be get, set, monitorOn or monitorOff. +

        +
        + + attributeName +

        +
        + + The name of the cdev device attribute that the verb will be + executed on. +

        +
        + + tag=xxxx +

        +
        + + These entries are used to place information in the outbound + cdevData object. tag is the text string name of the cdevData + tag. xxxx is the value that should be placed in the tag. At this + time cdevUtil only supports the insertion of scalar values into + the cdevData object. +

        +
        + + The following example shows the commands necessary to submit a request to get the + value of a device, and then set it to a new value. +

        + + +

        + + Figure 2: + + Entering commands using cdevUtil +
        + + + +
        + + +
        
        +host1:> cdevUtil
        +> 
        +> SUCCESS: Device: IPM1S01 - Message: get VAL - Value: 0
        +> 
        +> SUCCESS: Device: IPM1S01 - Message: set VAL - Value: None
        +> 
        +host1:> 
        +				
        +
        +
        + +

        +
        +
        + + + Exiting from + cdevUtil +

        +
        + + In order to exit from cdevUtil, the user must type quit <Return>. This will remove any + monitors that might have been created and will terminate the session. +

        +
        + + + cdevUtil Internal + Commands +

        +
        + + The following commands are processed by the cdevUtil application and are not + passed through to cdev. +

        + + + + + + + + + +
        + + debug on +

        +
        + + This message tells cdevutil that the user wants extremely + verbose output. When this is flag is set, the complete contents + of the incoming and outgoing cdevData objects will be + displayed. Typically only the value field of the incoming + cdevData object is displayed. +

        +
        + + debug off +

        +
        + + This message tells cdevUtil to stop displaying verbose output. +

        +
        + + help +

        +
        + + This command causes cdevUtil to display an simple help + screen that describes its usage and internal commands. +

        +
        + + quit +

        +
        + + This command terminates the cdevUtil utility. +

        +
        +
        + + 2. +

        +
        + + + The cddl Device Definition File Compiler +

        +
        + + + Overview +

        +
        + + The cddl compiler is used to convert the ascii text device definition files into a binary, + pre-processed device definition file. The binary DDL files load as much as twenty + times faster than their ascii text based counterparts. Additionally, the cddl compiler + confirms that no syntax errors exist in the ascii data files when they are compiled. + Therefore, this tool is also effect in validating the syntax and structure of the DDL files. +

        +
        + + + Location of Files +

        +
        + + The source code for cddl is located in the $(CDEV)/src/utility directory. This + application is automatically compiled whenever the cdev library is built. The binary + executable is placed in the directory $(CDEV)/bin/$(TARGET) when the application is + compiled. Once the cdev libraries and applications are compiled, this directory should + be placed in your search path. +

        +
        + + + Using the cddl + Compiler +

        +
        + + The syntax of cddl is very similar to that of the C preprocessor. The following is a + sample command line for compiling the device definition file. +

        + + + +
        + + + cddl inputfile -o outputfile +

        + + It is important to note that the inputfile parameter must contain a complete path + specification to the device definition file. Any errors will be reported to the screen. The + following is the typical output from executing the cddl compiler. +

        + +

        + + Figure 3: + + Typical output from the cddl compiler +
        + + + +
        + + +
        
        +host1:> cddl ~mccops/ddl/master.ddl -o master.bdd
        +converted from ascii to binary ddl file!
        +host1:> 
        +				
        +
        +
        + +

        + + +

        + + +

        +
        +
        + diff --git a/doc/html/releaseNotes1_3.html b/doc/html/releaseNotes1_3.html new file mode 100755 index 0000000..ee9ef6e --- /dev/null +++ b/doc/html/releaseNotes1_3.html @@ -0,0 +1,807 @@ + + +CDEV Documentation + + + + + + +


        + + + + + +
        + + + + Table of Contents +

        +
        + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +
        +
        + + Overview +
        +
        + + 2. +
        +
        + + Documentation +
        +
        + + 3. +
        +
        + + Installation +
        +
        + + 4. +
        +
        + + Changes from 1.1 Version +
        +
        + + 5. +
        +
        + + Problems and Restrictions (general) +
        +
        + + 6. +
        +
        + + Channel Access Service Features and Restrictions +
        +
        + + 7. +
        +
        + + Customizing for a New System +
        +
        + + 8. +
        +
        + + Planned Enhancements +
        +
        + + 9. +
        +
        + + cdev Applications +
        +
        +
        + + +


        + + + +
        + + + + cdev 1.3 Release Notes +

        +
        +


        + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + + Overview +

        + + The cdev (control device) C++ library is designed to provide a standard application + programming interface (API) to one or more underlying packages, typically control system + interfaces. The implementation is in 2 layers: the uppermost layer is used directly by an + application, and provides an abstraction of the underlying package as well as many general + purpose features. The second layer (service layer) provides the interface to one or more + underlying packages, and is implemented as loadable libraries. +

        + cdev was initially developed at CEBAF with input from the EPICS collaboration, and is now + available for anyone to take and use or improve. We welcome all comments, suggestions, bug + reports, and (especially) bug fixes, including fixes for new platforms. There are many planned + enhancements, and would welcome volunteers to contribute to this project. See below for a + summary of new and planned features. +

        + You may join a cdev discussion list by sending the message +

        + subscribe cdev +

        + to the address mailserv@cebaf.gov. (Send the message HELP to the same address for + information on how to use the mail server.) The cdev web page is +

        + http://www.cebaf.gov/cdev/ +

        + cdev 1.3 is the third publically released version of cdev. +

        +
        + + 2. +

        +
        + + + Documentation +

        + + The documentation for cdev includes the following: +

        + + + + + + + + + + + + + +
        + + +

        +
        + + Introduction to cdev -- this is an update of The cdev User's Guide, complete with more + examples. It covers all the basics, and is the best place to start. +

        +
        + + +

        +
        + + A cdev Tutorial -- this document goes through how to use each of the classes in cdev, + including all public methods; extensive examples are given. +

        +
        + + +

        +
        + + cdev Reference Manual -- documents each class in cdev in alphabetical order +

        +
        + + +

        +
        + + cdev Administrator's Guide -- this is for system administrators, and those intending to + port cdev to new platforms +

        +
        + + +

        +
        + + Service Developer's Guide -- this documents a couple of additional classes needed to + create a custom service, and goes through a lengthly example demoService. +

        +
        + + +

        +
        + + cdev C Binding -- documents the C wrapper routines for cdev +

        +
        + + This documentation is also available on the web site. +

        +
        + + 3. +

        +
        + + + Installation +

        + + Sources are available in compressed tar format, and contain makefiles to build the libraries and + utilities. These have been tested on the HP, SunOS, and SGI platforms to execute correctly, and + SLAC has ported this version to VAX/VMS. Fixes have also been incorporated from an earlier + port to IBM/AIX (at CERN). As configured, cdev will build support for the EPICS channel + access service. +

        + The Makefiles have been extensively reworked since the 1.1 release, and should build + successfully on more platforms. +

        + For further information, see the README file in the topmost directory, and the cdev + Administrator's Guide in the /doc sub-directory. +

        + Support for site specific control systems must be added by the implementer. See the Service + Developer's Guide for help in getting started interfacing cdev to a new control system. In + addition, there are a number of example services included with this release. +

        +
        + + 4. +

        +
        + + + Changes from 1.1 Version +

        + + A number of changes have been made to make the source code compile correctly on a larger + variety of compilers, including VAX C++ and g++. In addition, cdev now produces more error + and warning messages through its error logging routines. The following is a list of the more + visible feature changes: +

        + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + The C binding is included in the release (previously released as an add-on to 1.1). +

        +
        + + 2. +

        +
        + + The device definitions (ddl file) may now be stored and loaded in a binary format, which + is about 20 times faster to load compared to the ascii format. A new utility program, + cddl, compiles the ddl from ascii to binary. At run-time, the file format of the ddl file is + detected automatically so that either ascii or binary may be used. +

        +
        + + 3. +

        +
        + + Shared objects are now loaded from a subdirectory of the directory pointed to by + CDEVSHOBJ, where the subdirectory name is the name of the version of cdev against + which the application is running. This makes it possible to run different applications + against different versions of cdev. If the subdirectory does not contain the needed object, + it is loaded from CDEVSHOBJ as before. +

        +
        + + 4. +

        +
        + + cdevFdChangedCallback added to cdevSystem, allowing an application to be notified + when file descriptors are opened or closed by cdev services. +

        +
        + + 5. +

        +
        + + cdevData now supports a cast to char* as well as operator= overloading. +

        +
        + + 6. +

        +
        + + cdevGroup now supports a deferred execution / re-execution mode: if a group is in this + mode, operations are remembered but not executed. Saved operations may later be + executed as a group, and re-executed without re-learning. Only asynchronous operations + are remembered. +

        +
        + + 7. +

        +
        + + A few bugs in the channel access service have been fixed. Monitoring of status without + monitoring value now works correctly. +

        +
        + + 8. +

        +
        + + The cdev/src directory now contains an extensions sub-directory. Extensions include the + tcl interface, and the ACE (Adaptive Communication Environment) based client/server + package used for building new cdev servers and services capable of passing entire + cdevData objects over the network. +

        +
        + + 9. +

        +
        + + The cdev/examples directory now contains 2 additional example services, one + implementing compound cdev devices, and the other (demoService) is a trivial service + useful as a starting point for read/write services. +

        +
        +
        + + 5. +

        +
        + + + Problems and Restrictions (general) +

        + + Restrictions: +

        + + + +
        + + +

        +
        + + cdev is not yet thread safe, and may not be safe against instantiating more that one + cdevSystem object. +

        +
        +
        + + 6. +

        +
        + + + Channel Access Service Features and Restrictions +

        + + EPICS / Channel Access version 3.12 is recommended. The following comments from the 1.1 + release still apply: +

        + Major features: +

        + + + + + + + +
        + + +

        +
        + + Supports synchronous and asynchronous send's. +

        +
        + + +

        +
        + + Fetches data in native type (type conversion done on client and not server). +

        +
        + + +

        +
        + + Provides a default name service so that if a device is not defined, then an EPICS channel + access connection is attempted with the record name set equal to the device name, and + the field name set equal to the attribute name. +

        +
        + + Restrictions: +

        + + + + + + + + + + + +
        + + +

        +
        + + Only supports set/get/monitorOn/monitorOff verbs and the pv and readonly service data + tags. Support for arbitrary messages with default data has again been postponed. +

        +
        + + +

        +
        + + Discards all exception callbacks from channel access in this version. +

        +
        + + +

        +
        + + Channel access security is not supported in this release. +

        +
        + + +

        +
        + + sendCallback does not support the same timeout feature as send. +

        +
        + + +

        +
        + + channel access fails if send is called from within a callback function (either + asynchronous methods are OK: sendNoBlock and sendCallback) +

        +
        + + Compilation options: +

        + + + + + + + +
        + + +

        +
        + + _CA_SYNC_CONN = perform connections synchronously, waiting up to 4 seconds. +

        +
        + + +

        +
        + + _CDEV_DEBUG = print verbose messages +

        +
        + + +

        +
        + + _EPICS_3_12 = if not defined, use 3.11 calls instead. +

        +
        +
        + + 7. +

        +
        + + + Customizing for a New System +

        + + To customize cdev for a new control system, a new cdev service must be written. Two services + are provided with the release: caService for EPICS channel access, and skService, a skeleton + service. The ca (channel access) service is a complex example of how to interact with a control + system which supports asychronous I/O. The skeleton service simply shows the minimal + interface a service must provide, and can be used as a starting point for building a new service. + A third example is contained in the Service Developer's Guide, and is intermediate in + complexity. +

        + Still Planned: +

        + + + +
        + + +

        +
        + + a simple service for which you need only provide synchronous read and write routines. + This will speed up integrating a simple synchronous RPC or memory image based + system. +

        +
        +
        + + 8. +

        +
        + + + Planned Enhancements +

        + + There are many enhancements planned for cdev, and releases will probably come out every 3 + months for a while. The following is a list of topics planned for summer of 1996. Work on all + of these topics is underway. +

        + + + + + + + +
        + + 1. +

        +
        + + Collection devices. Created dynamically or statically, each device would contain a list + of other devices. Messages would be repeated to all contained devices, and read results + would be collected together and returned to the caller as a vector. Implementation will + support passing the list down to the service instead of iterating in the cdev layer so that + list based services (such as SLAC's) can optimize performance. +

        +
        + + 2. +

        +
        + + Service + Server based upon passing cdevData objects between client and server. This + allows complex query/reply type operations. A prototype is already in operation at + CEBAF, although the protocol is likely to change somewhat. +

        +
        + + 3. +

        +
        + + Virtual device wrapper around the correlation measurement engine (see below). +

        +
        + + The following list has been put on the back burner, but still of interest: +

        + + + + + + + + + +
        + + 4. +

        +
        + + "Multiknob" devices. Write operations would be applied to a vector of devices with + weighting factors which may be constant, or a simple functional form, or derived by a + call to another process. Intended for tuning machines. +

        +
        + + 5. +

        +
        + + Indirect devices. The name of the actual device can be changed on the fly, and all + connections to the old device will be automatically dropped and new connections + established. Useful for changing generic displays from one device to another. +

        +
        + + 6. +

        +
        + + tcl devices. Devices implemented as tcl scripts, which may call other cdev devices (or + anything else). +

        +
        + + 7. +

        +
        + + Connection to an object oriented database. +

        +
        +
        + + 9. +

        +
        + + + cdev Applications +

        + + The following applications are available as cdev extensions from CEBAF: +

        + + + + + +
        + + 1. +

        +
        + + Correlation package, modeled after SLAC's correlation plot utility. Consists of a + correlation engine class library plus an application (XACT) which uses it. +

        +
        + + 2. +

        +
        + + Multiknob utility (like #4 above, with a GUI interface). This is based upon a prototype + of multiknob devices, and is configured by ascii files. +

        +
        + + Finally, the following EPICS tools will be ported to cdev or re-written using cdev in the next + 12 months (ports to be distributed with EPICS, not cdev, due to licensing constraints): +

        + + + + + + + + + +
        + + 1. +

        +
        + + Alarm Handler (specialized GUI tool). Porting now underway at APS. +

        +
        + + 2. +

        +
        + + General operator interface (GUI), either dm or medm or both. +

        +
        + + 3. +

        +
        + + Archiver (new, to be distributed with cdev). +

        +
        + + 4. +

        +
        + + Save / Restore tool (ditto). +

        +
        + + Other applications will soon become available from other sites, and the most current + information will be available from the cdev web site, http://www.cebaf.gov/cdev. +

        + +

        +
        + diff --git a/doc/html/releaseNotes1_4.html b/doc/html/releaseNotes1_4.html new file mode 100755 index 0000000..31a068c --- /dev/null +++ b/doc/html/releaseNotes1_4.html @@ -0,0 +1,918 @@ + + +CDEV Documentation + + + + + + +


        + + + + + +
        + + + + Table of Contents +

        +
        + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +
        +
        + + Overview +
        +
        + + 2. +
        +
        + + Documentation +
        +
        + + 3. +
        +
        + + Installation +
        +
        + + 4. +
        +
        + + Changes from 1.1 Version +
        +
        + + 5. +
        +
        + + Changes from 1.3 Version +
        +
        + + 6. +
        +
        + + Problems and Restrictions (general) +
        +
        + + 7. +
        +
        + + Channel Access Service Features and Restrictions +
        +
        + + 8. +
        +
        + + Customizing for a New System +
        +
        + + 9. +
        +
        + + Planned Enhancements +
        +
        + + 10. +
        +
        + + cdev Applications +
        +
        +
        + + +


        + + + +
        + + + + cdev 1.4 Release Notes +

        +
        +


        + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + + Overview +

        + + The cdev (control device) C++ library is designed to provide a standard application + programming interface (API) to one or more underlying packages, typically control system + interfaces. The implementation is in 2 layers: the uppermost layer is used directly by an + application, and provides an abstraction of the underlying package as well as many general + purpose features. The second layer (service layer) provides the interface to one or more + underlying packages, and is implemented as loadable libraries. +

        + cdev was initially developed at CEBAF with input from the EPICS collaboration, and is now + available for anyone to take and use or improve. We welcome all comments, suggestions, bug + reports, and (especially) bug fixes, including fixes for new platforms. There are many planned + enhancements, and would welcome volunteers to contribute to this project. See below for a + summary of new and planned features. +

        + You may join a cdev discussion list by sending the message +

        + subscribe cdev +

        + to the address mailserv@cebaf.gov. (Send the message HELP to the same address for + information on how to use the mail server.) The cdev web page is +

        + http://www.cebaf.gov/cdev/ +

        + cdev 1.4 is the third publically released version of cdev. +

        +
        + + 2. +

        +
        + + + Documentation +

        + + The documentation for cdev includes the following: +

        + + + + + + + + + + + + + +
        + + +

        +
        + + Introduction to cdev -- this is an update of The cdev User's Guide, complete with more + examples. It covers all the basics, and is the best place to start. +

        +
        + + +

        +
        + + A cdev Tutorial -- this document goes through how to use each of the classes in cdev, + including all public methods; extensive examples are given. +

        +
        + + +

        +
        + + cdev Reference Manual -- documents each class in cdev in alphabetical order +

        +
        + + +

        +
        + + cdev Administrator's Guide -- this is for system administrators, and those intending to + port cdev to new platforms +

        +
        + + +

        +
        + + Service Developer's Guide -- this documents a couple of additional classes needed to + create a custom service, and goes through a lengthly example demoService. +

        +
        + + +

        +
        + + cdev C Binding -- documents the C wrapper routines for cdev +

        +
        + + This documentation is also available on the web site. +

        +
        + + 3. +

        +
        + + + Installation +

        + + Sources are available in compressed tar format, and contain makefiles to build the libraries and + utilities. These have been tested on the HP, SunOS, and SGI platforms to execute correctly, and + SLAC has ported this version to VAX/VMS. Fixes have also been incorporated from an earlier + port to IBM/AIX (at CERN). As configured, cdev will build support for the EPICS channel + access service. +

        + The Makefiles have been extensively reworked since the 1.1 release, and should build + successfully on more platforms. +

        + For further information, see the README file in the topmost directory, and the cdev + Administrator's Guide in the /doc sub-directory. +

        + Support for site specific control systems must be added by the implementer. See the Service + Developer's Guide for help in getting started interfacing cdev to a new control system. In + addition, there are a number of example services included with this release. +

        +
        + + 4. +

        +
        + + + Changes from 1.1 Version +

        + + A number of changes have been made to make the source code compile correctly on a larger + variety of compilers, including VAX C++ and g++. In addition, cdev now produces more error + and warning messages through its error logging routines. The following is a list of the more + visible feature changes: +

        + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + The C binding is included in the release (previously released as an add-on to 1.1). +

        +
        + + 2. +

        +
        + + The device definitions (ddl file) may now be stored and loaded in a binary format, which + is about 20 times faster to load compared to the ascii format. A new utility program, + cddl, compiles the ddl from ascii to binary. At run-time, the file format of the ddl file is + detected automatically so that either ascii or binary may be used. +

        +
        + + 3. +

        +
        + + Shared objects are now loaded from a subdirectory of the directory pointed to by + CDEVSHOBJ, where the subdirectory name is the name of the version of cdev against + which the application is running. This makes it possible to run different applications + against different versions of cdev. If the subdirectory does not contain the needed object, + it is loaded from CDEVSHOBJ as before. +

        +
        + + 4. +

        +
        + + cdevFdChangedCallback added to cdevSystem, allowing an application to be notified + when file descriptors are opened or closed by cdev services. +

        +
        + + 5. +

        +
        + + cdevData now supports a cast to char* as well as operator= overloading. +

        +
        + + 6. +

        +
        + + cdevGroup now supports a deferred execution / re-execution mode: if a group is in this + mode, operations are remembered but not executed. Saved operations may later be + executed as a group, and re-executed without re-learning. Only asynchronous operations + are remembered. +

        +
        + + 7. +

        +
        + + A few bugs in the channel access service have been fixed. Monitoring of status without + monitoring value now works correctly. +

        +
        + + 8. +

        +
        + + The cdev/src directory now contains an extensions sub-directory. Extensions include the + tcl interface, and the ACE (Adaptive Communication Environment) based client/server + package used for building new cdev servers and services capable of passing entire + cdevData objects over the network. +

        +
        + + 9. +

        +
        + + The cdev/examples directory now contains 2 additional example services, one + implementing compound cdev devices, and the other (demoService) is a trivial service + useful as a starting point for read/write services. +

        +
        +
        + + 5. +

        +
        + + + Changes from 1.3 Version +

        + + Several minor changes have been introduced to the system in order to improve performance for + existing operations. +

        + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + The operator == and operator != methods whave been added to the cdevData class. + These methods allow the caller to perform a deep comparison of the contents of two + cdevData objects. +

        +
        + + 2. +

        +
        + + A cdevTagTableCallback class has been added to the cdevTagTable.h file. This class has + a pure virtual callback method that (when registered with the cdevData class) will + receive a callback each time a new tag is added to the cdev global tag table. +

        +
        + + 3. +

        +
        + + The addTagCallback method has been added to the cdevData class. This method is used + by the caller to install a cdevTagTableCallback object that will be executed each time a + new tag is added to the global tag table. +

        +
        + + 4. +

        +
        + + The delTagCallback method has been added to the cdevData class. This method + removes a cdevTagTableCallback object that was previously installed using the + cdevData::addTagCallback method. +

        +
        + + 5. +

        +
        + + The readTagTable method has been added to the cdevData class. This method allows + the caller to retrieve a list of integer tags and their corresponding character strings that + are stored in the global tag table. +

        +
        + + 6. +

        +
        + + The CDEVTAGTABLE environment variable is used to indicate the location of a file + based list of tags that will be automatically loaded when a cdev application is started. If + the variable is not specified the application will attempt to load the list from /usr/local/ + lib/cdevTagTable. If this file does not exist, then the default list of tags will be used. +

        +
        + + 7. +

        +
        + + Channel Access Service (caService) modified to call the callback function immediately + when a second monitor is installed on an channel that is already monitored. +

        +
        +
        + + 6. +

        +
        + + + Problems and Restrictions (general) +

        + + Restrictions: +

        + + + +
        + + +

        +
        + + cdev is not yet thread safe, and may not be safe against instantiating more that one + cdevSystem object. +

        +
        +
        + + 7. +

        +
        + + + Channel Access Service Features and Restrictions +

        + + EPICS / Channel Access version 3.12 is recommended. The following comments from the 1.1 + release still apply: +

        + Major features: +

        + + + + + + + +
        + + +

        +
        + + Supports synchronous and asynchronous send's. +

        +
        + + +

        +
        + + Fetches data in native type (type conversion done on client and not server). +

        +
        + + +

        +
        + + Provides a default name service so that if a device is not defined, then an EPICS channel + access connection is attempted with the record name set equal to the device name, and + the field name set equal to the attribute name. +

        +
        + + Restrictions: +

        + + + + + + + + + + + +
        + + +

        +
        + + Only supports set/get/monitorOn/monitorOff verbs and the pv and readonly service data + tags. Support for arbitrary messages with default data has again been postponed. +

        +
        + + +

        +
        + + Discards all exception callbacks from channel access in this version. +

        +
        + + +

        +
        + + Channel access security is not supported in this release. +

        +
        + + +

        +
        + + sendCallback does not support the same timeout feature as send. +

        +
        + + +

        +
        + + caService fails if send is called from within a callback function (either asynchronous + methods are OK: sendNoBlock and sendCallback) +

        +
        + + Compilation options: +

        + + + + + + + +
        + + +

        +
        + + _CA_SYNC_CONN = perform connections synchronously, waiting up to 4 seconds. +

        +
        + + +

        +
        + + _CDEV_DEBUG = print verbose messages +

        +
        + + +

        +
        + + _EPICS_3_12 = if not defined, use 3.11 calls instead. +

        +
        +
        + + 8. +

        +
        + + + Customizing for a New System +

        + + To customize cdev for a new control system, a new cdev service must be written. Two services + are provided with the release: caService for EPICS channel access, and skService, a skeleton + service. The ca (channel access) service is a complex example of how to interact with a control + system which supports asychronous I/O. The skeleton service simply shows the minimal + interface a service must provide, and can be used as a starting point for building a new service. + A third example is contained in the Service Developer's Guide, and is intermediate in + complexity. +

        + Still Planned: +

        + + + +
        + + +

        +
        + + a simple service for which you need only provide synchronous read and write routines. + This will speed up integrating a simple synchronous RPC or memory image based + system. +

        +
        +
        + + 9. +

        +
        + + + Planned Enhancements +

        + + There are many enhancements planned for cdev, and releases will probably come out every 3 + months for a while. The following is a list of topics planned for summer of 1996. Work on all + of these topics is underway. +

        + + + + + + + +
        + + 1. +

        +
        + + Collection devices. Created dynamically or statically, each device would contain a list + of other devices. Messages would be repeated to all contained devices, and read results + would be collected together and returned to the caller as a vector. Implementation will + support passing the list down to the service instead of iterating in the cdev layer so that + list based services (such as SLAC's) can optimize performance. +

        +
        + + 2. +

        +
        + + Service + Server based upon passing cdevData objects between client and server. This + allows complex query/reply type operations. A prototype is already in operation at + CEBAF, although the protocol is likely to change somewhat. +

        +
        + + 3. +

        +
        + + Virtual device wrapper around the correlation measurement engine (see below). +

        +
        + + The following list has been put on the back burner, but still of interest: +

        + + + + + + + + + +
        + + 4. +

        +
        + + "Multiknob" devices. Write operations would be applied to a vector of devices with + weighting factors which may be constant, or a simple functional form, or derived by a + call to another process. Intended for tuning machines. +

        +
        + + 5. +

        +
        + + Indirect devices. The name of the actual device can be changed on the fly, and all + connections to the old device will be automatically dropped and new connections + established. Useful for changing generic displays from one device to another. +

        +
        + + 6. +

        +
        + + tcl devices. Devices implemented as tcl scripts, which may call other cdev devices (or + anything else). +

        +
        + + 7. +

        +
        + + Connection to an object oriented database. +

        +
        +
        + + 10. +

        +
        + + + cdev Applications +

        + + The following applications are available as cdev extensions from CEBAF: +

        + + + + + +
        + + 1. +

        +
        + + Correlation package, modeled after SLAC's correlation plot utility. Consists of a + correlation engine class library plus an application (XACT) which uses it. +

        +
        + + 2. +

        +
        + + Multiknob utility (like #4 above, with a GUI interface). This is based upon a prototype + of multiknob devices, and is configured by ascii files. +

        +
        + + Finally, the following EPICS tools will be ported to cdev or re-written using cdev in the next + 12 months (ports to be distributed with EPICS, not cdev, due to licensing constraints): +

        + + + + + + + + + +
        + + 1. +

        +
        + + Alarm Handler (specialized GUI tool). Porting now underway at APS. +

        +
        + + 2. +

        +
        + + General operator interface (GUI), either dm or medm or both. +

        +
        + + 3. +

        +
        + + Archiver (new, to be distributed with cdev). +

        +
        + + 4. +

        +
        + + Save / Restore tool (ditto). +

        +
        + + Other applications will soon become available from other sites, and the most current + information will be available from the cdev web site, http://www.cebaf.gov/cdev. +

        + +

        +
        + diff --git a/doc/html/releaseNotes1_5.html b/doc/html/releaseNotes1_5.html new file mode 100755 index 0000000..79877a3 --- /dev/null +++ b/doc/html/releaseNotes1_5.html @@ -0,0 +1,1145 @@ + + +CDEV Documentation + + + + + + +


        + + + + + +
        + + + + Table of Contents +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +
        +
        + + Overview +
        +
        + + 2. +
        +
        + + Documentation +
        +
        + + 3. +
        +
        + + Installation +
        +
        + + 4. +
        +
        + + Changes from 1.1 Version +
        +
        + + 5. +
        +
        + + Changes from 1.3 Version +
        +
        + + 6. +
        +
        + + Changes from 1.4 Version +
        +
        + + 7. +
        +
        + + Problems and Restrictions (general) +
        +
        + + 8. +
        +
        + + Channel Access Service Features and Restrictions +
        +
        + + 9. +
        +
        + + Customizing for a New System +
        +
        + + 10. +
        +
        + + Planned Enhancements +
        +
        + + 11. +
        +
        + + cdev Applications +
        +
        +
        + + +


        + + + +
        + + + + cdev 1.5 Release Notes +

        +
        +


        + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + + Overview +

        + + The cdev (control device) C++ library is designed to provide a standard application + programming interface (API) to one or more underlying packages, typically control system + interfaces. The implementation is in 2 layers: the uppermost layer is used directly by an + application, and provides an abstraction of the underlying package as well as many general + purpose features. The second layer (service layer) provides the interface to one or more + underlying packages, and is implemented as loadable libraries. +

        + cdev was initially developed at CEBAF with input from the EPICS collaboration, and is now + available for anyone to take and use or improve. We welcome all comments, suggestions, bug + reports, and (especially) bug fixes, including fixes for new platforms. There are many planned + enhancements, and would welcome volunteers to contribute to this project. See below for a + summary of new and planned features. +

        + You may join a cdev discussion list by sending the message +

        + subscribe cdev +

        + to the address mailserv@cebaf.gov. (Send the message HELP to the same address for + information on how to use the mail server.) The cdev web page is +

        + http://www.cebaf.gov/cdev/ +

        + cdev 1.4 is the third publically released version of cdev. +

        +
        + + 2. +

        +
        + + + Documentation +

        + + The documentation for cdev includes the following: +

        + + + + + + + + + + + + + + + +
        + + +

        +
        + + Introduction to cdev -- this is an update of The cdev User's Guide, complete with more + examples. It covers all the basics, and is the best place to start. +

        +
        + + +

        +
        + + A cdev Tutorial -- this document goes through how to use each of the classes in cdev, + including all public methods; extensive examples are given. +

        +
        + + +

        +
        + + cdev Reference Manual -- documents each class in cdev in alphabetical order +

        +
        + + +

        +
        + + cdev Administrator's Guide -- this is for system administrators, and those intending to + port cdev to new platforms +

        +
        + + +

        +
        + + Service Developer's Guide -- this documents a couple of additional classes needed to + create a custom service, and goes through a lengthly example demoService. +

        +
        + + +

        +
        + + cdevCollection Device Requirements and Design -- This document illustrates the + structure and usage of the cdevCollection device. +

        +
        + + +

        +
        + + cdev C Binding -- documents the C wrapper routines for cdev +

        +
        + + This documentation is also available on the web site. +

        +
        + + 3. +

        +
        + + + Installation +

        + + Sources are available in compressed tar format, and contain makefiles to build the libraries and + utilities. These have been tested on the HP, SunOS, and SGI platforms to execute correctly, and + SLAC has ported this version to VAX/VMS. Fixes have also been incorporated from an earlier + port to IBM/AIX (at CERN). As configured, cdev will build support for the EPICS channel + access service. +

        + The Makefiles have been extensively reworked since the 1.1 release, and should build + successfully on more platforms. +

        + For further information, see the README file in the topmost directory, and the cdev + Administrator's Guide in the /doc sub-directory. +

        + Support for site specific control systems must be added by the implementer. See the Service + Developer's Guide for help in getting started interfacing cdev to a new control system. In + addition, there are a number of example services included with this release. +

        +
        + + 4. +

        +
        + + + Changes from 1.1 Version +

        + + A number of changes have been made to make the source code compile correctly on a larger + variety of compilers, including VAX C++ and g++. In addition, cdev now produces more error + and warning messages through its error logging routines. The following is a list of the more + visible feature changes: +

        + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + The C binding is included in the release (previously released as an add-on to 1.1). +

        +
        + + 2. +

        +
        + + The device definitions (ddl file) may now be stored and loaded in a binary format, which + is about 20 times faster to load compared to the ascii format. A new utility program, + cddl, compiles the ddl from ascii to binary. At run-time, the file format of the ddl file is + detected automatically so that either ascii or binary may be used. +

        +
        + + 3. +

        +
        + + Shared objects are now loaded from a subdirectory of the directory pointed to by + CDEVSHOBJ, where the subdirectory name is the name of the version of cdev against + which the application is running. This makes it possible to run different applications + against different versions of cdev. If the subdirectory does not contain the needed object, + it is loaded from CDEVSHOBJ as before. +

        +
        + + 4. +

        +
        + + cdevFdChangedCallback added to cdevSystem, allowing an application to be notified + when file descriptors are opened or closed by cdev services. +

        +
        + + 5. +

        +
        + + cdevData now supports a cast to char* as well as operator= overloading. +

        +
        + + 6. +

        +
        + + cdevGroup now supports a deferred execution / re-execution mode: if a group is in this + mode, operations are remembered but not executed. Saved operations may later be + executed as a group, and re-executed without re-learning. Only asynchronous operations + are remembered. +

        +
        + + 7. +

        +
        + + A few bugs in the channel access service have been fixed. Monitoring of status without + monitoring value now works correctly. +

        +
        + + 8. +

        +
        + + The cdev/src directory now contains an extensions sub-directory. Extensions include the + tcl interface, and the ACE (Adaptive Communication Environment) based client/server + package used for building new cdev servers and services capable of passing entire + cdevData objects over the network. +

        +
        + + 9. +

        +
        + + The cdev/examples directory now contains 2 additional example services, one + implementing compound cdev devices, and the other (demoService) is a trivial service + useful as a starting point for read/write services. +

        +
        +
        + + 5. +

        +
        + + + Changes from 1.3 Version +

        + + Several minor changes have been introduced to the system in order to improve performance for + existing operations. +

        + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + The operator == and operator != methods have been added to the cdevData class. + These methods allow the caller to perform a deep comparison of the contents of two + cdevData objects. +

        +
        + + 2. +

        +
        + + A cdevTagTableCallback class has been added to the cdevTagTable.h file. This class has + a pure virtual callback method that (when registered with the cdevData class) will + receive a callback each time a new tag is added to the cdev global tag table. +

        +
        + + 3. +

        +
        + + The addTagCallback method has been added to the cdevData class. This method is used + by the caller to install a cdevTagTableCallback object that will be executed each time a + new tag is added to the global tag table. +

        +
        + + 4. +

        +
        + + The delTagCallback method has been added to the cdevData class. This method + removes a cdevTagTableCallback object that was previously installed using the + cdevData::addTagCallback method. +

        +
        + + 5. +

        +
        + + The readTagTable method has been added to the cdevData class. This method allows + the caller to retrieve a list of integer tags and their corresponding character strings that + are stored in the global tag table. +

        +
        + + 6. +

        +
        + + The CDEVTAGTABLE environment variable is used to indicate the location of a file + based list of tags that will be automatically loaded when a cdev application is started. If + the variable is not specified the application will attempt to load the list from /usr/local/ + lib/cdevTagTable. If this file does not exist, then the default list of tags will be used. +

        +
        + + 7. +

        +
        + + Channel Access Service (caService) modified to call the callback function immediately + when a second monitor is installed on an channel that is already monitored. +

        +
        +
        + + 6. +

        +
        + + + Changes from 1.4 Version +

        + + Major additions have been made to the system to support new functionality. +

        + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + The cdevCollection device and cdevCollectionRequest object have been added to the + CDEV class library. These mechanisms provide the capability to send a single message + to a group of devices that may span multiple services. +

        +
        + + 2. +

        +
        + + Modifications have been made to the cdevDevice, cdevRequestObject, and cdevService + class to support the new cdevCollection hierarchy. +

        +
        + + 3. +

        +
        + + Because of binary incompatibilities between the different versions of the CDEV DDL + file. The cdevSystem will now append the version number of the current version of + CDEV (-1.5) to the name specified in th CDEVDDL environment variable before + attempting to load the file. +

        +
        + + 4. +

        +
        + + Modifications have been made to the CDEV Generic Server Engine to allow it to + manage user defined packet types using the same protocol definition. +

        +
        + + 5. +

        +
        + + ACE Version 4.0.32 is now being distributed with CDEV. +

        +
        + + 6. +

        +
        + + The cdevRequestObject::attachRef(cdevDevice &, char *message) method has been + made protected and is no longer part of the public interface. This method was always + intended to be used internally by cdev. Developers should use + cdevRequestObject::attachRef(char * device, char * message) to obtain a + cdevRequestObject reference. +

        +
        + + 7. +

        +
        + + The cdevCallback class has been expanded to provide a fireCallback method that has an + additional parameter; partialTransaction. If the service is delivering a message that is + one of many that might be generated by the request (such as monitorOn), the + partialTransaction flag should be set to non-zero. If the reply is in response to a + monotonic operation (such as "get" or "set") or if it is the last response of a multi-part + reply, the partialTransaction flag should be set to zero. +

        +
        + + 8. +

        +
        + + The isTransactionDone method has been added to the cdevCallback class to allow the + callback function to identify if the message is a monotonic response or one of many. +

        +
        +
        + + 7. +

        +
        + + + Problems and Restrictions (general) +

        + + Restrictions: +

        + + + + + + + + + + + + + + + +
        + + +

        +
        + + cdev is not yet thread safe, and may not be safe against instantiating more that one + cdevSystem object. +

        +
        + + +

        +
        + + Device names can only be added to or removed from the cdevCollection device until it + has been used once. After a cdevCollectionRequest object has been generated from a + specific cdevCollection device, the device list cannot be modified. +

        +
        + + +

        +
        + + cdevCollection devices do not support the messages "monitorOn" and "monitorOff". + Only monotonic operations are currently supported by the cdevCollection device. +

        +
        + + +

        +
        + + cdevCollection definitions must be the last things defined in the CDEV DDL file. This is + because the constituent devices must have already been defined when the + cdevCollection is defined. +

        +
        + + +

        +
        + + When the data from a cdevDevice operation is used to construct the output cdevData + object for a cdevCollection operation, only data that is scalar in nature will be used. If a + cdevDevice returns tagged data items that are arrays in its results, those data items will + not be included in the result. +

        +
        + + +

        +
        + + cdevCollection objects must be comprised of regular cdevDevice objects only. Because + the cdevCollection does not support cdevDevices that return arrays of data in their + result, a cdevCollection can not contain another cdevCollection. +

        +
        + + +

        +
        + + If a cdevCollection consists of devices from multiple services, the collection does not + guarantee the order in which the cdevDevice's requests will be serviced. Because + services perform at varying speeds, a faster service may process its devices requests + sooner than another service. +

        +
        +
        + + 8. +

        +
        + + + Channel Access Service Features and Restrictions +

        + + EPICS / Channel Access version 3.12 is recommended. The following comments from the 1.1 + release still apply: +

        + Major features: +

        + + + + + + + +
        + + +

        +
        + + Supports synchronous and asynchronous send's. +

        +
        + + +

        +
        + + Fetches data in native type (type conversion done on client and not server). +

        +
        + + +

        +
        + + Provides a default name service so that if a device is not defined, then an EPICS channel + access connection is attempted with the record name set equal to the device name, and + the field name set equal to the attribute name. +

        +
        + + Restrictions: +

        + + + + + + + + + + + +
        + + +

        +
        + + Only supports set/get/monitorOn/monitorOff verbs and the pv and readonly service data + tags. Support for arbitrary messages with default data has again been postponed. +

        +
        + + +

        +
        + + Discards all exception callbacks from channel access in this version. +

        +
        + + +

        +
        + + Channel access security is not supported in this release. +

        +
        + + +

        +
        + + sendCallback does not support the same timeout feature as send. +

        +
        + + +

        +
        + + caService fails if send is called from within a callback function (either asynchronous + methods are OK: sendNoBlock and sendCallback) +

        +
        + + Compilation options: +

        + + + + + + + +
        + + +

        +
        + + _CA_SYNC_CONN = perform connections synchronously, waiting up to 4 seconds. +

        +
        + + +

        +
        + + _CDEV_DEBUG = print verbose messages +

        +
        + + +

        +
        + + _EPICS_3_12 = if not defined, use 3.11 calls instead. +

        +
        +
        + + 9. +

        +
        + + + Customizing for a New System +

        + + To customize cdev for a new control system, a new cdev service must be written. Two services + are provided with the release: caService for EPICS channel access, and skService, a skeleton + service. The ca (channel access) service is a complex example of how to interact with a control + system which supports asychronous I/O. The skeleton service simply shows the minimal + interface a service must provide, and can be used as a starting point for building a new service. + A third example is contained in the Service Developer's Guide, and is intermediate in + complexity. +

        + Still Planned: +

        + + + +
        + + +

        +
        + + a simple service for which you need only provide synchronous read and write routines. + This will speed up integrating a simple synchronous RPC or memory image based + system. +

        +
        +
        + + 10. +

        +
        + + + Planned Enhancements +

        + + There are many enhancements planned for cdev, and releases will probably come out every 3 + months for a while. The following is a list of topics planned for summer of 1996. Work on all + of these topics is underway. +

        + + + + + + + +
        + + 1. +

        +
        + + Collection devices. Created dynamically or statically, each device would contain a list + of other devices. Messages would be repeated to all contained devices, and read results + would be collected together and returned to the caller as a vector. Implementation will + support passing the list down to the service instead of iterating in the cdev layer so that + list based services (such as SLAC's) can optimize performance. +

        +
        + + 2. +

        +
        + + Service + Server based upon passing cdevData objects between client and server. This + allows complex query/reply type operations. A prototype is already in operation at + CEBAF, although the protocol is likely to change somewhat. +

        +
        + + 3. +

        +
        + + Virtual device wrapper around the correlation measurement engine (see below). +

        +
        + + The following list has been put on the back burner, but still of interest: +

        + + + + + + + + + +
        + + 4. +

        +
        + + "Multiknob" devices. Write operations would be applied to a vector of devices with + weighting factors which may be constant, or a simple functional form, or derived by a + call to another process. Intended for tuning machines. +

        +
        + + 5. +

        +
        + + Indirect devices. The name of the actual device can be changed on the fly, and all + connections to the old device will be automatically dropped and new connections + established. Useful for changing generic displays from one device to another. +

        +
        + + 6. +

        +
        + + tcl devices. Devices implemented as tcl scripts, which may call other cdev devices (or + anything else). +

        +
        + + 7. +

        +
        + + Connection to an object oriented database. +

        +
        +
        + + 11. +

        +
        + + + cdev Applications +

        + + The following applications are available as cdev extensions from CEBAF: +

        + + + + + + + + + +
        + + 1. +

        +
        + + Correlation package, modeled after SLAC's correlation plot utility. Consists of a + correlation engine class library plus an application (XACT) which uses it. +

        +
        + + 2. +

        +
        + + Multiknob utility (like #4 above, with a GUI interface). This is based upon a prototype + of multiknob devices, and is configured by ascii files. +

        +
        + + 3. +

        +
        + + ARTEMIS Model Server. +

        +
        + + 4. +

        +
        + + CEBAF Lock Server. +

        +
        + + Finally, the following EPICS tools will be ported to cdev or re-written using cdev in the next + 12 months (ports to be distributed with EPICS, not cdev, due to licensing constraints): +

        + + + + + + + + + +
        + + 1. +

        +
        + + Alarm Handler (specialized GUI tool). Porting now underway at APS. +

        +
        + + 2. +

        +
        + + General operator interface (GUI), either dm or medm or both. +

        +
        + + 3. +

        +
        + + Archiver (new, to be distributed with cdev). +

        +
        + + 4. +

        +
        + + Save / Restore tool (ditto). +

        +
        + + Other applications will soon become available from other sites, and the most current + information will be available from the cdev web site, http://www.cebaf.gov/cdev. +

        + +

        +
        + diff --git a/doc/makehtml b/doc/makehtml new file mode 100755 index 0000000..7f9f893 --- /dev/null +++ b/doc/makehtml @@ -0,0 +1,21 @@ +#! /bin/csh + +if( -f fmbatch.dat) rm fmbatch.dat +if( -d html) rm -rf html +mkdir -p html +cp bullet.jpg html + +foreach x (`find . -name \*.doc -a ! -name \*TOC.doc -a ! -name \*LOF.doc`) + echo "Open $x" >> fmbatch.dat + echo "SaveAs ma $x html/`basename $x .doc`.mif" >> fmbatch.dat + end + +fmbatch fmbatch.dat + +cd html + +foreach x (`find . -name \*.mif -a ! -name \*TITLE.mif`) + mif2html -t 'CDEV Documentation' -o `basename $x .mif`.html `basename $x .mif`TITLE.mif \-TOC \-LOF $x + end + +rm *.mif diff --git a/doc/makehtml1 b/doc/makehtml1 new file mode 100755 index 0000000..2b4a0a9 --- /dev/null +++ b/doc/makehtml1 @@ -0,0 +1,22 @@ +#! /bin/csh + +if( -f fmbatch.dat) rm fmbatch.dat +if( !(-d html) ) mkdir -p html +cp bullet.jpg html + +foreach x ($argv) + echo "Open $x" >> fmbatch.dat + echo "SaveAs ma $x html/`basename $x .doc`.mif" >> fmbatch.dat + echo "Open `basename $x .doc`TITLE.doc" >> fmbatch.dat + echo "SaveAs ma `basename $x .doc`TITLE.doc html/`basename $x .doc`TITLE.mif" >> fmbatch.dat + end + +fmbatch fmbatch.dat + +cd html + +foreach x (`find . -name \*.mif -a ! -name \*TITLE.mif`) + mif2html -t 'CDEV Documentation' -o `basename $x .mif`.html `basename $x .mif`TITLE.mif \-TOC \-LOF $x + end + +rm *.mif diff --git a/doc/makeps b/doc/makeps new file mode 100755 index 0000000..3f61c54 --- /dev/null +++ b/doc/makeps @@ -0,0 +1,13 @@ +#! /bin/csh + +if( -f fmbatch.dat) rm fmbatch.dat +mkdir -p ps + +foreach x (`find . -name \*.book -o -name releaseNotes\*.doc`) + echo "Open $x" >> fmbatch.dat + echo "Print $x" >> fmbatch.dat + end + +fmbatch fmbatch.dat +rm fmbatch.dat +mv *.ps ps diff --git a/doc/ps/cdevAdminGuide.ps b/doc/ps/cdevAdminGuide.ps new file mode 100755 index 0000000..46d0221 --- /dev/null +++ b/doc/ps/cdevAdminGuide.ps @@ -0,0 +1,3471 @@ +%!PS-Adobe-3.0 +%%BoundingBox: (atend) +%%Pages: (atend) +%%PageOrder: (atend) +%%DocumentFonts: (atend) +%%Creator: Frame 5.0 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +% +% Frame ps_prolog 5.0, for use with Frame 5.0 products +% This ps_prolog file is Copyright (c) 1986-1995 Frame Technology +% Corporation. All rights reserved. This ps_prolog file may be +% freely copied and distributed in conjunction with documents created +% using FrameMaker, FrameMaker/SGML and FrameViewer as long as this +% copyright notice is preserved. +% +% FrameMaker users specify the proper paper size for each print job in the +% "Print" dialog's "Printer Paper Size" "Width" and "Height~ fields. If the +% printer that the PS file is sent to does not support the requested paper +% size, or if there is no paper tray of the proper size currently installed, +% then the job will not be printed. The following flag, if set to true, will +% cause the job to print on the default paper in such cases. +/FMAllowPaperSizeMismatch false def +% +% Frame products normally print colors as their true color on a color printer +% or as shades of gray, based on luminance, on a black-and white printer. The +% following flag, if set to true, forces all non-white colors to print as pure +% black. This has no effect on bitmap images. +/FMPrintAllColorsAsBlack false def +% +% Frame products can either set their own line screens or use a printer's +% default settings. Three flags below control this separately for no +% separations, spot separations and process separations. If a flag +% is true, then the default printer settings will not be changed. If it is +% false, Frame products will use their own settings from a table based on +% the printer's resolution. +/FMUseDefaultNoSeparationScreen true def +/FMUseDefaultSpotSeparationScreen true def +/FMUseDefaultProcessSeparationScreen false def +% +% For any given PostScript printer resolution, Frame products have two sets of +% screen angles and frequencies for printing process separations, which are +% recomended by Adobe. The following variable chooses the higher frequencies +% when set to true or the lower frequencies when set to false. This is only +% effective if the appropriate FMUseDefault...SeparationScreen flag is false. +/FMUseHighFrequencyScreens true def +% +% The following is a set of predefined optimal frequencies and angles for various +% common dpi settings. This is taken from "Advances in Color Separation Using +% PostScript Software Technology," from Adobe Systems (3/13/89 P.N. LPS 0043) +% and corrolated with information which is in various PPD (4.0) files. +% +% The "dpiranges" figure is the minimum dots per inch device resolution which +% can support this setting. The "low" and "high" values are controlled by the +% setting of the FMUseHighFrequencyScreens flag above. The "TDot" flags control +% the use of the "Yellow Triple Dot" feature whereby the frequency id divided by +% three, but the dot function is "trippled" giving a block of 3x3 dots per cell. +% +% PatFreq is a compromise pattern frequency for ps Level 2 printers which is close +% to the ideal WYSIWYG pattern frequency of 9 repetitions/inch but does not beat +% (too badly) against the screen frequencies of any separations for that DPI. +/dpiranges [ 2540 2400 1693 1270 1200 635 600 0 ] def +/CMLowFreqs [ 100.402 94.8683 89.2289 100.402 94.8683 66.9349 63.2456 47.4342 ] def +/YLowFreqs [ 95.25 90.0 84.65 95.25 90.0 70.5556 66.6667 50.0 ] def +/KLowFreqs [ 89.8026 84.8528 79.8088 89.8026 84.8528 74.8355 70.7107 53.033 ] def +/CLowAngles [ 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 ] def +/MLowAngles [ 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 ] def +/YLowTDot [ true true false true true false false false ] def +/CMHighFreqs [ 133.87 126.491 133.843 108.503 102.523 100.402 94.8683 63.2456 ] def +/YHighFreqs [ 127.0 120.0 126.975 115.455 109.091 95.25 90.0 60.0 ] def +/KHighFreqs [ 119.737 113.137 119.713 128.289 121.218 89.8026 84.8528 63.6395 ] def +/CHighAngles [ 71.5651 71.5651 71.5651 70.0169 70.0169 71.5651 71.5651 71.5651 ] def +/MHighAngles [ 18.4349 18.4349 18.4349 19.9831 19.9831 18.4349 18.4349 18.4349 ] def +/YHighTDot [ false false true false false true true false ] def +/PatFreq [ 10.5833 10.0 9.4055 10.5833 10.0 10.5833 10.0 9.375 ] def +% +% PostScript Level 2 printers contain an "Accurate Screens" feature which can +% improve process separation rendering at the expense of compute time. This +% flag is ignored by PostScript Level 1 printers. +/FMUseAcccurateScreens true def +% +% The following PostScript procedure defines the spot function that Frame +% products will use for process separations. You may un-comment-out one of +% the alternative functions below, or use your own. +% +% Dot function +/FMSpotFunction {abs exch abs 2 copy add 1 gt + {1 sub dup mul exch 1 sub dup mul add 1 sub } + {dup mul exch dup mul add 1 exch sub }ifelse } def +% +% Line function +% /FMSpotFunction { pop } def +% +% Elipse function +% /FMSpotFunction { dup 5 mul 8 div mul exch dup mul exch add +% sqrt 1 exch sub } def +% +% +/FMversion (5.0) def +/fMLevel1 /languagelevel where {pop languagelevel} {1} ifelse 2 lt def +/FMPColor + fMLevel1 { + false + /colorimage where {pop pop true} if + } { + true + } ifelse +def +/FrameDict 400 dict def +systemdict /errordict known not {/errordict 10 dict def + errordict /rangecheck {stop} put} if +% The readline in PS 23.0 doesn't recognize cr's as nl's on AppleTalk +FrameDict /tmprangecheck errordict /rangecheck get put +errordict /rangecheck {FrameDict /bug true put} put +FrameDict /bug false put +mark +% Some PS machines read past the CR, so keep the following 3 lines together! +currentfile 5 string readline +00 +0000000000 +cleartomark +errordict /rangecheck FrameDict /tmprangecheck get put +FrameDict /bug get { + /readline { + /gstring exch def + /gfile exch def + /gindex 0 def + { + gfile read pop + dup 10 eq {exit} if + dup 13 eq {exit} if + gstring exch gindex exch put + /gindex gindex 1 add def + } loop + pop + gstring 0 gindex getinterval true + } bind def + } if +/FMshowpage /showpage load def +/FMquit /quit load def +/FMFAILURE { + dup = flush + FMshowpage + /Helvetica findfont 12 scalefont setfont + 72 200 moveto show + 72 220 moveto show + FMshowpage + FMquit + } def +/FMVERSION { + FMversion ne { + (Frame product version does not match ps_prolog! Check installation;) + (also check ~/fminit and ./fminit for old versions) FMFAILURE + } if + } def +/FMBADEPSF { + (Adobe's PostScript Language Reference Manual, 2nd Edition, section H.2.4) + (says your EPS file is not valid, as it calls X ) + dup dup (X) search pop exch pop exch pop length + 5 -1 roll + putinterval + FMFAILURE + } def +/fmConcatProcs + { + /proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def + newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx +}def +FrameDict begin [ + /ALDsave + /FMdicttop + /FMoptop + /FMpointsize + /FMsaveobject + /b + /bitmapsave + /blut + /bpside + /bs + /bstring + /bwidth + /c + /cf + /cs + /cynu + /depth + /edown + /fh + /fillvals + /fw + /fx + /fy + /g + /gfile + /gindex + /grnt + /gryt + /gstring + /height + /hh + /i + /im + /indx + /is + /k + /kk + /landscape + /lb + /len + /llx + /lly + /m + /magu + /manualfeed + /n + /offbits + /onbits + /organgle + /orgbangle + /orgbfreq + /orgbproc + /orgbxfer + /orgfreq + /orggangle + /orggfreq + /orggproc + /orggxfer + /orgmatrix + /orgproc + /orgrangle + /orgrfreq + /orgrproc + /orgrxfer + /orgxfer + /pagesave + /paperheight + /papersizedict + /paperwidth + /pos + /pwid + /r + /rad + /redt + /sl + /str + /tran + /u + /urx + /ury + /val + /width + /width + /ws + /ww + /x + /x1 + /x2 + /xindex + /xpoint + /xscale + /xx + /y + /y1 + /y2 + /yelu + /yindex + /ypoint + /yscale + /yy +] { 0 def } forall +/FmBD {bind def} bind def +systemdict /pdfmark known { + /fMAcrobat true def + + /FmPD /pdfmark load def + + + /FmPT /show load def + + + currentdistillerparams /CoreDistVersion get 2000 ge { + + + /FmPD2 /pdfmark load def + + + + + + /FmPA { mark exch /Dest exch 5 3 roll + /View [ /XYZ null 6 -2 roll FmDC exch pop null] /DEST FmPD + }FmBD + } { + + /FmPD2 /cleartomark load def + /FmPA {pop pop pop}FmBD + } ifelse +} { + + /fMAcrobat false def + /FmPD /cleartomark load def + /FmPD2 /cleartomark load def + /FmPT /pop load def + /FmPA {pop pop pop}FmBD +} ifelse +/FmDC { + transform fMDefaultMatrix itransform cvi exch cvi exch +}FmBD +/FmBx { + dup 3 index lt {3 1 roll exch} if + 1 index 4 index lt {4 -1 roll 3 1 roll exch 4 1 roll} if +}FmBD +/FMnone 0 def +/FMcyan 1 def +/FMmagenta 2 def +/FMyellow 3 def +/FMblack 4 def +/FMcustom 5 def +/fMNegative false def +/FrameSepIs FMnone def +/FrameSepBlack 0 def +/FrameSepYellow 0 def +/FrameSepMagenta 0 def +/FrameSepCyan 0 def +/FrameSepRed 1 def +/FrameSepGreen 1 def +/FrameSepBlue 1 def +/FrameCurGray 1 def +/FrameCurPat null def +/FrameCurColors [ 0 0 0 1 0 0 0 ] def +/FrameColorEpsilon .001 def +/eqepsilon { + sub dup 0 lt {neg} if + FrameColorEpsilon le +} bind def +/FrameCmpColorsCMYK { + 2 copy 0 get exch 0 get eqepsilon { + 2 copy 1 get exch 1 get eqepsilon { + 2 copy 2 get exch 2 get eqepsilon { + 3 get exch 3 get eqepsilon + } {pop pop false} ifelse + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/FrameCmpColorsRGB { + 2 copy 4 get exch 0 get eqepsilon { + 2 copy 5 get exch 1 get eqepsilon { + 6 get exch 2 get eqepsilon + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/RGBtoCMYK { + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 3 copy + 2 copy + le { pop } { exch pop } ifelse + 2 copy + le { pop } { exch pop } ifelse + dup dup dup + 6 1 roll + 4 1 roll + 7 1 roll + sub + 6 1 roll + sub + 5 1 roll + sub + 4 1 roll +} bind def +/CMYKtoRGB { + dup dup 4 -1 roll add + 5 1 roll 3 -1 roll add + 4 1 roll add + 1 exch sub dup 0 lt {pop 0} if 3 1 roll + 1 exch sub dup 0 lt {pop 0} if exch + 1 exch sub dup 0 lt {pop 0} if exch +} bind def +/FrameSepInit { + 1.0 RealSetgray +} bind def +/FrameSetSepColor { + /FrameSepBlue exch def + /FrameSepGreen exch def + /FrameSepRed exch def + /FrameSepBlack exch def + /FrameSepYellow exch def + /FrameSepMagenta exch def + /FrameSepCyan exch def + /FrameSepIs FMcustom def + setCurrentScreen +} bind def +/FrameSetCyan { + /FrameSepBlue 1.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 1.0 def + /FrameSepIs FMcyan def + setCurrentScreen +} bind def + +/FrameSetMagenta { + /FrameSepBlue 1.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 1.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMmagenta def + setCurrentScreen +} bind def + +/FrameSetYellow { + /FrameSepBlue 0.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 1.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMyellow def + setCurrentScreen +} bind def + +/FrameSetBlack { + /FrameSepBlue 0.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 1.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMblack def + setCurrentScreen +} bind def + +/FrameNoSep { + /FrameSepIs FMnone def + setCurrentScreen +} bind def +/FrameSetSepColors { + FrameDict begin + [ exch 1 add 1 roll ] + /FrameSepColors + exch def end + } bind def +/FrameColorInSepListCMYK { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsCMYK + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/FrameColorInSepListRGB { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsRGB + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/RealSetgray /setgray load def +/RealSetrgbcolor /setrgbcolor load def +/RealSethsbcolor /sethsbcolor load def +end +/setgray { + FrameDict begin + FrameSepIs FMnone eq + { RealSetgray } + { + FrameSepIs FMblack eq + { RealSetgray } + { FrameSepIs FMcustom eq + FrameSepRed 0 eq and + FrameSepGreen 0 eq and + FrameSepBlue 0 eq and { + RealSetgray + } { + 1 RealSetgray pop + } ifelse + } ifelse + } ifelse + end +} bind def +/setrgbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetrgbcolor } + { + 3 copy [ 4 1 roll ] + FrameColorInSepListRGB + { + FrameSepBlue eq exch + FrameSepGreen eq and exch + FrameSepRed eq and + { 0 } { 1 } ifelse + } + { + FMPColor { + RealSetrgbcolor + currentcmykcolor + } { + RGBtoCMYK + } ifelse + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end +} bind def +/sethsbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSethsbcolor } + { + RealSethsbcolor + currentrgbcolor + setrgbcolor + } + ifelse + end +} bind def +FrameDict begin +/setcmykcolor where { + pop /RealSetcmykcolor /setcmykcolor load def +} { + /RealSetcmykcolor { + 4 1 roll + 3 { 3 index add 0 max 1 min 1 exch sub 3 1 roll} repeat + RealSetrgbcolor pop + } bind def +} ifelse +userdict /setcmykcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetcmykcolor } + { + 4 copy [ 5 1 roll ] + FrameColorInSepListCMYK + { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + { 0 } { 1 } ifelse + } + { + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end + } bind put +fMLevel1 { + + + + /patScreenDict 7 dict dup begin + <0f1e3c78f0e1c387> [ 45 { pop } {exch pop} .5 2 sqrt] FmBD + <0f87c3e1f0783c1e> [ 135 { pop } {exch pop} .5 2 sqrt] FmBD + [ 0 { pop } dup .5 2 ] FmBD + [ 90 { pop } dup .5 2 ] FmBD + <8142241818244281> [ 45 { 2 copy lt {exch} if pop} dup .75 2 sqrt] FmBD + <03060c183060c081> [ 45 { pop } {exch pop} .875 2 sqrt] FmBD + <8040201008040201> [ 135 { pop } {exch pop} .875 2 sqrt] FmBD + end def +} { + + /patProcDict 5 dict dup begin + <0f1e3c78f0e1c387> { 3 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <0f87c3e1f0783c1e> { 3 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + <8142241818244281> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -1 -1 moveto 9 9 lineto stroke } bind def + <03060c183060c081> { 1 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <8040201008040201> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + end def + /patDict 15 dict dup begin + /PatternType 1 def + /PaintType 2 def + /TilingType 3 def + /BBox [ 0 0 8 8 ] def + /XStep 8 def + /YStep 8 def + /PaintProc { + begin + patProcDict bstring known { + patProcDict bstring get exec + } { + 8 8 true [1 0 0 -1 0 8] bstring imagemask + } ifelse + end + } bind def + end def +} ifelse +/combineColor { + FrameSepIs FMnone eq + { + graymode fMLevel1 or not { + + [/Pattern [/DeviceCMYK]] setcolorspace + FrameCurColors 0 4 getinterval aload pop FrameCurPat setcolor + } { + FrameCurColors 3 get 1.0 ge { + FrameCurGray RealSetgray + } { + fMAcrobat not FMPColor graymode and and { + 0 1 3 { + FrameCurColors exch get + 1 FrameCurGray sub mul + } for + RealSetcmykcolor + } { + 4 1 6 { + FrameCurColors exch get + graymode { + 1 exch sub 1 FrameCurGray sub mul 1 exch sub + } { + 1.0 lt {FrameCurGray} {1} ifelse + } ifelse + } for + RealSetrgbcolor + } ifelse + } ifelse + } ifelse + } { + FrameCurColors 0 4 getinterval aload + FrameColorInSepListCMYK { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + FrameSepIs FMcustom eq and + { FrameCurGray } { 1 } ifelse + } { + FrameSepIs FMblack eq + {FrameCurGray 1.0 exch sub mul 1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop FrameCurGray 1.0 exch sub mul 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + graymode fMLevel1 or not { + + [/Pattern [/DeviceGray]] setcolorspace + FrameCurPat setcolor + } { + graymode not fMLevel1 and { + + dup 1 lt {pop FrameCurGray} if + } if + RealSetgray + } ifelse + } ifelse +} bind def +/savematrix { + orgmatrix currentmatrix pop + } bind def +/restorematrix { + orgmatrix setmatrix + } bind def +/fMDefaultMatrix matrix defaultmatrix def +/fMatrix2 matrix def +/dpi 72 0 fMDefaultMatrix dtransform + dup mul exch dup mul add sqrt def + +/freq dpi dup 72 div round dup 0 eq {pop 1} if 8 mul div def +/sangle 1 0 fMDefaultMatrix dtransform exch atan def + sangle fMatrix2 rotate + fMDefaultMatrix fMatrix2 concatmatrix + dup 0 get /sflipx exch def + 3 get /sflipy exch def +/screenIndex { + 0 1 dpiranges length 1 sub { dup dpiranges exch get 1 sub dpi le {exit} {pop} ifelse } for +} bind def +/getCyanScreen { + FMUseHighFrequencyScreens { CHighAngles CMHighFreqs} {CLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getMagentaScreen { + FMUseHighFrequencyScreens { MHighAngles CMHighFreqs } {MLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getYellowScreen { + FMUseHighFrequencyScreens { YHighTDot YHighFreqs} { YLowTDot YLowFreqs } ifelse + screenIndex dup 3 1 roll get 3 1 roll get { 3 div + {2 { 1 add 2 div 3 mul dup floor sub 2 mul 1 sub exch} repeat + FMSpotFunction } } {/FMSpotFunction load } ifelse + 0.0 exch +} bind def +/getBlackScreen { + FMUseHighFrequencyScreens { KHighFreqs } { KLowFreqs } ifelse + screenIndex get 45.0 /FMSpotFunction load +} bind def +/getSpotScreen { + getBlackScreen +} bind def +/getCompositeScreen { + getBlackScreen +} bind def +/FMSetScreen + fMLevel1 { /setscreen load + }{ { + 8 dict begin + /HalftoneType 1 def + /SpotFunction exch def + /Angle exch def + /Frequency exch def + /AccurateScreens FMUseAcccurateScreens def + currentdict end sethalftone + } bind } ifelse +def +/setDefaultScreen { + FMPColor { + orgrxfer cvx orggxfer cvx orgbxfer cvx orgxfer cvx setcolortransfer + } + { + orgxfer cvx settransfer + } ifelse + orgfreq organgle orgproc cvx setscreen +} bind def +/setCurrentScreen { + FrameSepIs FMnone eq { + FMUseDefaultNoSeparationScreen { + setDefaultScreen + } { + getCompositeScreen FMSetScreen + } ifelse + } { + FrameSepIs FMcustom eq { + FMUseDefaultSpotSeparationScreen { + setDefaultScreen + } { + getSpotScreen FMSetScreen + } ifelse + } { + FMUseDefaultProcessSeparationScreen { + setDefaultScreen + } { + FrameSepIs FMcyan eq { + getCyanScreen FMSetScreen + } { + FrameSepIs FMmagenta eq { + getMagentaScreen FMSetScreen + } { + FrameSepIs FMyellow eq { + getYellowScreen FMSetScreen + } { + getBlackScreen FMSetScreen + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse +} bind def +end + +/FMDOCUMENT { + array /FMfonts exch def + /#copies exch def + FrameDict begin + 0 ne /manualfeed exch def + /paperheight exch def + /paperwidth exch def + 0 ne /fMNegative exch def + 0 ne /edown exch def + /yscale exch def + /xscale exch def + fMLevel1 { + manualfeed {setmanualfeed} if + /FMdicttop countdictstack 1 add def + /FMoptop count def + setpapername + manualfeed {true} {papersize} ifelse + {manualpapersize} {false} ifelse + {desperatepapersize} {false} ifelse + {papersizefailure} if + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + } + {2 dict + dup /PageSize [paperwidth paperheight] put + manualfeed {dup /ManualFeed manualfeed put} if + {setpagedevice} stopped {papersizefailure} if + } + ifelse + + FMPColor { + currentcolorscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + cvlit /orgbproc exch def + /orgbangle exch def + /orgbfreq exch def + cvlit /orggproc exch def + /orggangle exch def + /orggfreq exch def + cvlit /orgrproc exch def + /orgrangle exch def + /orgrfreq exch def + currentcolortransfer + fMNegative { + 1 1 4 { + pop { 1 exch sub } fmConcatProcs 4 1 roll + } for + 4 copy + setcolortransfer + } if + cvlit /orgxfer exch def + cvlit /orgbxfer exch def + cvlit /orggxfer exch def + cvlit /orgrxfer exch def + } { + currentscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + + currenttransfer + fMNegative { + { 1 exch sub } fmConcatProcs + dup settransfer + } if + cvlit /orgxfer exch def + } ifelse + end +} def +/FMBEGINPAGE { + FrameDict begin + /pagesave save def + 3.86 setmiterlimit + /landscape exch 0 ne def + landscape { + 90 rotate 0 exch dup /pwid exch def neg translate pop + }{ + pop /pwid exch def + } ifelse + edown { [-1 0 0 1 pwid 0] concat } if + 0 0 moveto paperwidth 0 lineto paperwidth paperheight lineto + 0 paperheight lineto 0 0 lineto 1 setgray fill + xscale yscale scale + /orgmatrix matrix def + gsave +} def +/FMENDPAGE { + grestore + pagesave restore + end + showpage + } def +/FMFONTDEFINE { + FrameDict begin + findfont + ReEncode + 1 index exch + definefont + FMfonts 3 1 roll + put + end + } def +/FMFILLS { + FrameDict begin dup + array /fillvals exch def + dict /patCache exch def + end + } def +/FMFILL { + FrameDict begin + fillvals 3 1 roll put + end + } def +/FMNORMALIZEGRAPHICS { + newpath + 1 setlinewidth + 0 setlinecap + 0 0 0 sethsbcolor + 0 setgray + } bind def +/FMBEGINEPSF { + end + /FMEPSF save def + /showpage {} def +% See Adobe's "PostScript Language Reference Manual, 2nd Edition", page 714. +% "...the following operators MUST NOT be used in an EPS file:" (emphasis ours) + /banddevice {(banddevice) FMBADEPSF} def + /clear {(clear) FMBADEPSF} def + /cleardictstack {(cleardictstack) FMBADEPSF} def + /copypage {(copypage) FMBADEPSF} def + /erasepage {(erasepage) FMBADEPSF} def + /exitserver {(exitserver) FMBADEPSF} def + /framedevice {(framedevice) FMBADEPSF} def + /grestoreall {(grestoreall) FMBADEPSF} def + /initclip {(initclip) FMBADEPSF} def + /initgraphics {(initgraphics) FMBADEPSF} def + /quit {(quit) FMBADEPSF} def + /renderbands {(renderbands) FMBADEPSF} def + /setglobal {(setglobal) FMBADEPSF} def + /setpagedevice {(setpagedevice) FMBADEPSF} def + /setshared {(setshared) FMBADEPSF} def + /startjob {(startjob) FMBADEPSF} def + /lettertray {(lettertray) FMBADEPSF} def + /letter {(letter) FMBADEPSF} def + /lettersmall {(lettersmall) FMBADEPSF} def + /11x17tray {(11x17tray) FMBADEPSF} def + /11x17 {(11x17) FMBADEPSF} def + /ledgertray {(ledgertray) FMBADEPSF} def + /ledger {(ledger) FMBADEPSF} def + /legaltray {(legaltray) FMBADEPSF} def + /legal {(legal) FMBADEPSF} def + /statementtray {(statementtray) FMBADEPSF} def + /statement {(statement) FMBADEPSF} def + /executivetray {(executivetray) FMBADEPSF} def + /executive {(executive) FMBADEPSF} def + /a3tray {(a3tray) FMBADEPSF} def + /a3 {(a3) FMBADEPSF} def + /a4tray {(a4tray) FMBADEPSF} def + /a4 {(a4) FMBADEPSF} def + /a4small {(a4small) FMBADEPSF} def + /b4tray {(b4tray) FMBADEPSF} def + /b4 {(b4) FMBADEPSF} def + /b5tray {(b5tray) FMBADEPSF} def + /b5 {(b5) FMBADEPSF} def + FMNORMALIZEGRAPHICS + [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall + fx fw 2 div add fy fh 2 div add translate + rotate + fw 2 div neg fh 2 div neg translate + fw urx llx sub div fh ury lly sub div scale + llx neg lly neg translate + /FMdicttop countdictstack 1 add def + /FMoptop count def + } bind def +/FMENDEPSF { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMEPSF restore + FrameDict begin + } bind def +FrameDict begin +/setmanualfeed { +%%BeginFeature *ManualFeed True + statusdict /manualfeed true put +%%EndFeature + } bind def +/max {2 copy lt {exch} if pop} bind def +/min {2 copy gt {exch} if pop} bind def +/inch {72 mul} def +/pagedimen { + paperheight sub abs 16 lt exch + paperwidth sub abs 16 lt and + {/papername exch def} {pop} ifelse + } bind def +/setpapername { + /papersizedict 14 dict def + papersizedict begin + /papername /unknown def + /Letter 8.5 inch 11.0 inch pagedimen + /LetterSmall 7.68 inch 10.16 inch pagedimen + /Tabloid 11.0 inch 17.0 inch pagedimen + /Ledger 17.0 inch 11.0 inch pagedimen + /Legal 8.5 inch 14.0 inch pagedimen + /Statement 5.5 inch 8.5 inch pagedimen + /Executive 7.5 inch 10.0 inch pagedimen + /A3 11.69 inch 16.5 inch pagedimen + /A4 8.26 inch 11.69 inch pagedimen + /A4Small 7.47 inch 10.85 inch pagedimen + /B4 10.125 inch 14.33 inch pagedimen + /B5 7.16 inch 10.125 inch pagedimen + end + } bind def +/papersize { + papersizedict begin + /Letter {lettertray letter} def + /LetterSmall {lettertray lettersmall} def + /Tabloid {11x17tray 11x17} def + /Ledger {ledgertray ledger} def + /Legal {legaltray legal} def + /Statement {statementtray statement} def + /Executive {executivetray executive} def + /A3 {a3tray a3} def + /A4 {a4tray a4} def + /A4Small {a4tray a4small} def + /B4 {b4tray b4} def + /B5 {b5tray b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + statusdict begin stopped end + } bind def +/manualpapersize { + papersizedict begin + /Letter {letter} def + /LetterSmall {lettersmall} def + /Tabloid {11x17} def + /Ledger {ledger} def + /Legal {legal} def + /Statement {statement} def + /Executive {executive} def + /A3 {a3} def + /A4 {a4} def + /A4Small {a4small} def + /B4 {b4} def + /B5 {b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + stopped + } bind def +/desperatepapersize { + statusdict /setpageparams known + { + paperwidth paperheight 0 1 + statusdict begin + {setpageparams} stopped + end + } {true} ifelse + } bind def +/papersizefailure { + FMAllowPaperSizeMismatch not + { +(The requested paper size is not available in any currently-installed tray) +(Edit the PS file to "FMAllowPaperSizeMismatch true" to use default tray) + FMFAILURE } if + } def +/DiacriticEncoding [ +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl +/numbersign /dollar /percent /ampersand /quotesingle /parenleft +/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K +/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash +/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h +/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar +/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute +/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis +/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis +/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve +/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex +/udieresis /dagger /.notdef /cent /sterling /section /bullet +/paragraph /germandbls /registered /copyright /trademark /acute +/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef +/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown +/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef +/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde +/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright +/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis +/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl +/periodcentered /quotesinglbase /quotedblbase /perthousand +/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute +/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve +/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron +/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +] def +/ReEncode { + dup + length + dict begin + { + 1 index /FID ne + {def} + {pop pop} ifelse + } forall + 0 eq {/Encoding DiacriticEncoding def} if + currentdict + end + } bind def +FMPColor + + { + /BEGINBITMAPCOLOR { + BITMAPCOLOR} def + /BEGINBITMAPCOLORc { + BITMAPCOLORc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUECOLOR } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUECOLORc } def + /BEGINBITMAPCMYK { + BITMAPCMYK } def + /BEGINBITMAPCMYKc { + BITMAPCMYKc } def + } + + { + /BEGINBITMAPCOLOR { + BITMAPGRAY} def + /BEGINBITMAPCOLORc { + BITMAPGRAYc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUEGRAY } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUEGRAYc } def + /BEGINBITMAPCMYK { + BITMAPCMYKGRAY } def + /BEGINBITMAPCMYKc { + BITMAPCMYKGRAYc } def + } +ifelse +/K { + FMPrintAllColorsAsBlack { + dup 1 eq 2 index 1 eq and 3 index 1 eq and not + {7 {pop} repeat 0 0 0 1 0 0 0} if + } if + FrameCurColors astore + pop combineColor +} bind def +/graymode true def +fMLevel1 { + /fmGetFlip { + fMatrix2 exch get mul 0 lt { -1 } { 1 } ifelse + } FmBD +} if +/setPatternMode { + fMLevel1 { + 2 index patScreenDict exch known { + pop pop + patScreenDict exch get aload pop + freq + mul + 5 2 roll + fMatrix2 currentmatrix 1 get 0 ne { + 3 -1 roll 90 add 3 1 roll + sflipx 1 fmGetFlip sflipy 2 fmGetFlip neg mul + } { + sflipx 0 fmGetFlip sflipy 3 fmGetFlip mul + } ifelse + 0 lt {exch pop} {pop} ifelse + fMNegative { + {neg} fmConcatProcs + } if + bind + + + + systemdict /setscreen get exec + /FrameCurGray exch def + } { + /bwidth exch def + /bpside exch def + /bstring exch def + /onbits 0 def /offbits 0 def + freq sangle landscape {90 add} if + {/ypoint exch def + /xpoint exch def + /xindex xpoint 1 add 2 div bpside mul cvi def + /yindex ypoint 1 add 2 div bpside mul cvi def + bstring yindex bwidth mul xindex 8 idiv add get + 1 7 xindex 8 mod sub bitshift and 0 ne fMNegative {not} if + {/onbits onbits 1 add def 1} + {/offbits offbits 1 add def 0} + ifelse + } + setscreen + offbits offbits onbits add div fMNegative {1.0 exch sub} if + /FrameCurGray exch def + } ifelse + } { + pop pop + dup patCache exch known { + patCache exch get + } { + dup + patDict /bstring 3 -1 roll put + patDict + 9 PatFreq screenIndex get div dup matrix scale + makepattern + dup + patCache 4 -1 roll 3 -1 roll put + } ifelse + /FrameCurGray 0 def + /FrameCurPat exch def + } ifelse + /graymode false def + combineColor +} bind def +/setGrayScaleMode { + graymode not { + /graymode true def + fMLevel1 { + setCurrentScreen + } if + } if + /FrameCurGray exch def + combineColor +} bind def +/normalize { + transform round exch round exch itransform + } bind def +/dnormalize { + dtransform round exch round exch idtransform + } bind def +/lnormalize { + 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop + } bind def +/H { + lnormalize setlinewidth + } bind def +/Z { + setlinecap + } bind def + +/PFill { + graymode fMLevel1 or not { + gsave 1 setgray eofill grestore + } if +} bind def +/PStroke { + graymode fMLevel1 or not { + gsave 1 setgray stroke grestore + } if + stroke +} bind def +/X { + fillvals exch get + dup type /stringtype eq + {8 1 setPatternMode} + {setGrayScaleMode} + ifelse + } bind def +/V { + PFill gsave eofill grestore + } bind def +/Vclip { + clip + } bind def +/Vstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/N { + PStroke + } bind def +/Nclip { + strokepath clip newpath + } bind def +/Nstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/M {newpath moveto} bind def +/E {lineto} bind def +/D {curveto} bind def +/O {closepath} bind def +/L { + /n exch def + newpath + normalize + moveto + 2 1 n {pop normalize lineto} for + } bind def +/Y { + L + closepath + } bind def +/R { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + x1 y1 + x2 y1 + x2 y2 + x1 y2 + 4 Y + } bind def +/rarc + {rad + arcto + } bind def +/RR { + /rad exch def + normalize + /y2 exch def + /x2 exch def + normalize + /y1 exch def + /x1 exch def + mark + newpath + { + x1 y1 rad add moveto + x1 y2 x2 y2 rarc + x2 y2 x2 y1 rarc + x2 y1 x1 y1 rarc + x1 y1 x1 y2 rarc + closepath + } stopped {x1 y1 x2 y2 R} if + cleartomark + } bind def +/RRR { + /rad exch def + normalize /y4 exch def /x4 exch def + normalize /y3 exch def /x3 exch def + normalize /y2 exch def /x2 exch def + normalize /y1 exch def /x1 exch def + newpath + normalize moveto + mark + { + x2 y2 x3 y3 rarc + x3 y3 x4 y4 rarc + x4 y4 x1 y1 rarc + x1 y1 x2 y2 rarc + closepath + } stopped + {x1 y1 x2 y2 x3 y3 x4 y4 newpath moveto lineto lineto lineto closepath} if + cleartomark + } bind def +/C { + grestore + gsave + R + clip + setCurrentScreen +} bind def +/CP { + grestore + gsave + Y + clip + setCurrentScreen +} bind def +/F { + FMfonts exch get + FMpointsize scalefont + setfont + } bind def +/Q { + /FMpointsize exch def + F + } bind def +/T { + moveto show + } bind def +/RF { + rotate + 0 ne {-1 1 scale} if + } bind def +/TF { + gsave + moveto + RF + show + grestore + } bind def +/P { + moveto + 0 32 3 2 roll widthshow + } bind def +/PF { + gsave + moveto + RF + 0 32 3 2 roll widthshow + grestore + } bind def +/S { + moveto + 0 exch ashow + } bind def +/SF { + gsave + moveto + RF + 0 exch ashow + grestore + } bind def +/B { + moveto + 0 32 4 2 roll 0 exch awidthshow + } bind def +/BF { + gsave + moveto + RF + 0 32 4 2 roll 0 exch awidthshow + grestore + } bind def +/G { + gsave + newpath + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill fill + grestore + } bind def +/Gstrk { + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/Gclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GG { + gsave + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill + fill + grestore + } bind def +/GGclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GGstrk { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/A { + gsave + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/Aclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/Astrk { + Gstrk +} bind def +/AA { + gsave + savematrix + newpath + + 3 index 2 div add exch 4 index 2 div sub exch + + normalize 3 index 2 div sub exch 4 index 2 div add exch + translate + rotate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/AAclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/AAstrk { + GGstrk +} bind def +/BEGINPRINTCODE { + /FMdicttop countdictstack 1 add def + /FMoptop count 7 sub def + /FMsaveobject save def + userdict begin + /showpage {} def + FMNORMALIZEGRAPHICS + 3 index neg 3 index neg translate + } bind def +/ENDPRINTCODE { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMsaveobject restore + } bind def +/gn { + 0 + { 46 mul + cf read pop + 32 sub + dup 46 lt {exit} if + 46 sub add + } loop + add + } bind def +/cfs { + /str sl string def + 0 1 sl 1 sub {str exch val put} for + str def + } bind def +/ic [ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 + {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx} + {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx} + {19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} + {13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh} + {4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh} + {13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl} + {7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl} + {0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl} + {10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl} + ] def +/ms { + /sl exch def + /val 255 def + /ws cfs + /im cfs + /val 0 def + /bs cfs + /cs cfs + } bind def +400 ms +/ip { + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip { + + + bis ris copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + ris gis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + gis bis copy pop + dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip4 { + + + kis cis copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + cis mis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + mis yis copy pop + dup dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + yis kis copy pop + 3 mul is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/wh { + /len exch def + /pos exch def + ws 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/bl { + /len exch def + /pos exch def + bs 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/s1 1 string def +/fl { + /len exch def + /pos exch def + /val cf s1 readhexstring pop 0 get def + pos 1 pos len add 1 sub {im exch val put} for + pos len + } bind def +/hx { + 3 copy getinterval + cf exch readhexstring pop pop + } bind def +/wbytes { + dup dup + 8 gt { pop 8 idiv mul } + { 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse } ifelse + } bind def +/BEGINBITMAPBWc { + 1 {} COMMONBITMAPc + } bind def +/BEGINBITMAPGRAYc { + 8 {} COMMONBITMAPc + } bind def +/BEGINBITMAP2BITc { + 2 {} COMMONBITMAPc + } bind def +/COMMONBITMAPc { + + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + cvtProc + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} image + bitmapsave restore + grestore + } bind def +/BEGINBITMAPBW { + 1 {} COMMONBITMAP + } bind def +/BEGINBITMAPGRAY { + 8 {} COMMONBITMAP + } bind def +/BEGINBITMAP2BIT { + 2 {} COMMONBITMAP + } bind def +/COMMONBITMAP { + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + cvtProc + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} image + bitmapsave restore + grestore + } bind def +/ngrayt 256 array def +/nredt 256 array def +/nbluet 256 array def +/ngreent 256 array def +fMLevel1 { +/colorsetup { + currentcolortransfer + /gryt exch def + /blut exch def + /grnt exch def + /redt exch def + 0 1 255 { + /indx exch def + /cynu 1 red indx get 255 div sub def + /magu 1 green indx get 255 div sub def + /yelu 1 blue indx get 255 div sub def + /kk cynu magu min yelu min def + /u kk currentundercolorremoval exec def +% /u 0 def + nredt indx 1 0 cynu u sub max sub redt exec put + ngreent indx 1 0 magu u sub max sub grnt exec put + nbluet indx 1 0 yelu u sub max sub blut exec put + ngrayt indx 1 kk currentblackgeneration exec sub gryt exec put + } for + {255 mul cvi nredt exch get} + {255 mul cvi ngreent exch get} + {255 mul cvi nbluet exch get} + {255 mul cvi ngrayt exch get} + setcolortransfer + {pop 0} setundercolorremoval + {} setblackgeneration + } bind def +} +{ +/colorSetup2 { + [ /Indexed /DeviceRGB 255 + {dup red exch get 255 div + exch dup green exch get 255 div + exch blue exch get 255 div} + ] setcolorspace +} bind def +} ifelse +/fakecolorsetup { + /tran 256 string def + 0 1 255 {/indx exch def + tran indx + red indx get 77 mul + green indx get 151 mul + blue indx get 28 mul + add add 256 idiv put} for + currenttransfer + {255 mul cvi tran exch get 255.0 div} + exch fmConcatProcs settransfer +} bind def +/BITMAPCOLOR { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + fMLevel1 { + colorsetup + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} {is} {is} true 3 colorimage + } { + colorSetup2 + /is width depth wbytes string def + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {cf is readhexstring pop} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPCOLORc { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + fMLevel1 { + colorsetup + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} {is} {is} true 3 colorimage + } { + colorSetup2 + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {ip} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLORc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris} {gis} {bis} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYKc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip4 pop cis} {mis} {yis} {kis} true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLOR { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf gis readhexstring pop } + { cf bis readhexstring pop } + true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYK { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /mis width string def + /yis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf mis readhexstring pop } + { cf yis readhexstring pop } + { cf kis readhexstring pop } + true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUEGRAYc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris gis bis width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAYc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop cis mis yis kis width cgray} image + bitmapsave restore + grestore + } bind def +/cgray { + /ww exch def + /k exch def + /y exch def + /m exch def + /c exch def + 0 1 ww 1 sub { /i exch def c i get m i get y i get k i get CMYKtoRGB + .144 mul 3 1 roll .587 mul 3 1 roll .299 mul add add + c i 3 -1 roll floor cvi put } for + c + } bind def +/gray { + /ww exch def + /b exch def + /g exch def + /r exch def + 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul + b i get .114 mul add add r i 3 -1 roll floor cvi put } for + r + } bind def +/BITMAPTRUEGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf gis readhexstring pop + cf bis readhexstring pop width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /yis width string def + /mis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf mis readhexstring pop + cf yis readhexstring pop + cf kis readhexstring pop width cgray} image + bitmapsave restore + grestore + } bind def +/BITMAPGRAY { + 8 {fakecolorsetup} COMMONBITMAP + } bind def +/BITMAPGRAYc { + 8 {fakecolorsetup} COMMONBITMAPc + } bind def +/ENDBITMAP { + } bind def +end + /ALDmatrix matrix def ALDmatrix currentmatrix pop +/StartALD { + /ALDsave save def + savematrix + ALDmatrix setmatrix + } bind def +/InALD { + restorematrix + } bind def +/DoneALD { + ALDsave restore + } bind def +/I { setdash } bind def +/J { [] 0 setdash } bind def +%%EndProlog +%%BeginSetup +(5.0) FMVERSION +1 1 0 0 612 792 0 1 8 FMDOCUMENT +0 0 /Helvetica FMFONTDEFINE +1 0 /Times-BoldItalic FMFONTDEFINE +2 0 /Helvetica-Bold FMFONTDEFINE +3 0 /Helvetica-Oblique FMFONTDEFINE +4 0 /Courier FMFONTDEFINE +32 FMFILLS +0 0 FMFILL +1 0.1 FMFILL +2 0.3 FMFILL +3 0.5 FMFILL +4 0.7 FMFILL +5 0.9 FMFILL +6 0.97 FMFILL +7 1 FMFILL +8 <0f1e3c78f0e1c387> FMFILL +9 <0f87c3e1f0783c1e> FMFILL +10 FMFILL +11 FMFILL +12 <8142241818244281> FMFILL +13 <03060c183060c081> FMFILL +14 <8040201008040201> FMFILL +16 1 FMFILL +17 0.9 FMFILL +18 0.7 FMFILL +19 0.5 FMFILL +20 0.3 FMFILL +21 0.1 FMFILL +22 0.03 FMFILL +23 0 FMFILL +24 FMFILL +25 FMFILL +26 <3333333333333333> FMFILL +27 <0000ffff0000ffff> FMFILL +28 <7ebddbe7e7dbbd7e> FMFILL +29 FMFILL +30 <7fbfdfeff7fbfdfe> FMFILL +%%EndSetup +%%Page: "i" 1 +%%BeginPaperSize: Letter +%%EndPaperSize +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(i) 555.78 57 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 720 558 720 2 L +0.5 H +2 Z +N +72 72 558 72 2 L +N +72 504 558 504 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 32 Q +(CDEV Administrator\325) 180 662.67 T +(s) 468.38 662.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Guide) 180 624.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 12 Q +(Chip W) 180 600 T +(atson, Jie Chen, Danjin W) 218.86 600 T +(u, W) 357.22 600 T +(alt Ak) 381.41 600 T +(ers) 411.18 600 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 180 572 T +(ersion 1.5 December 9, 1996) 187.04 572 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(TJNAF - Thomas Jeff) 180 544 T +(erson National Acceler) 293.66 544 T +(ator F) 414.25 544 T +(acility) 445 544 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "i" 1 +%%Page: "ii" 2 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(ii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(TRADEMARKS:) 54 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(UNIX is a registered tr) 180 569.33 T +(ademar) 278.26 569.33 T +(k of A) 312.31 569.33 T +(T&T in the USA and other countr) 336.68 569.33 T +(ies) 481.9 569.33 T +(.) 494.53 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(VxW) 180 545.33 T +(or) 200.81 545.33 T +(ks is a register tr) 209.85 545.33 T +(ademar) 283.1 545.33 T +(k of Wind Riv) 317.15 545.33 T +(er Systems) 375.8 545.33 T +(.) 425.66 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The X Windo) 180 521.33 T +(w System is a tr) 237.65 521.33 T +(ademar) 308.12 521.33 T +(k of Massachusetts Institute of T) 342.17 521.33 T +(echnology) 484.37 521.33 T +(.) 528.95 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(OSF/Motif and Motif are tr) 180 497.33 T +(ademar) 294.94 497.33 T +(ks of Open Softw) 328.99 497.33 T +(are F) 404.99 497.33 T +(oundation, Inc.) 428.03 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ultr) 180 473.33 T +(ix and DEC are registered tr) 195.7 473.33 T +(ademar) 319.53 473.33 T +(ks of Digital Equipment Cor) 353.58 473.33 T +(por) 475.03 473.33 T +(ation.) 489.38 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(HPUX is a registered tr) 180 449.33 T +(ademar) 282.15 449.33 T +(k of He) 316.2 449.33 T +(wlett P) 347.68 449.33 T +(ac) 377.29 449.33 T +(kard.) 387.65 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(SURA/CEB) 54 344.33 T +(AF:) 105.92 344.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.44 (The Southeaster) 180 344.33 P +4.44 (n Univ) 258.62 344.33 P +4.44 (ersities Research Association \050SURA\051 oper) 291.15 344.33 P +4.44 (ates the) 499.98 344.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.01 (Contin) 180 332.33 P +2.01 (uous Electron Beam Acceler) 208.8 332.33 P +2.01 (ator F) 340.89 332.33 P +2.01 (acility \050CEBAF\051 f) 368.52 332.33 P +2.01 (or the United States) 445.59 332.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Depar) 180 320.33 T +(tment of Energy under contr) 207.63 320.33 T +(act DE-A) 331.48 320.33 T +(C05-84ER40150.) 371.19 320.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DISCLAIMER:) 54 218.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.49 (This repor) 180 218.33 P +0.49 (t w) 225.9 218.33 P +0.49 (as prepared as an account of w) 239.02 218.33 P +0.49 (or) 381.4 218.33 P +0.49 (k sponsored b) 390.44 218.33 P +0.49 (y the United States) 454.03 218.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.18 (go) 180 206.33 P +2.18 (v) 190.97 206.33 P +2.18 (er) 195.72 206.33 P +2.18 (nment. Neither the United States nor the United States Depar) 204.86 206.33 P +2.18 (tment of) 501.68 206.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.04 (Energy) 180 194.33 P +1.04 (, nor an) 210.68 194.33 P +1.04 (y of their emplo) 246.52 194.33 P +1.04 (y) 317.69 194.33 P +1.04 (ees) 322.49 194.33 P +1.04 (, mak) 338.46 194.33 P +1.04 (es an) 363.75 194.33 P +1.04 (y w) 389.1 194.33 P +1.04 (arr) 404.99 194.33 P +1.04 (anty) 417.11 194.33 P +1.04 (, e) 435.01 194.33 P +1.04 (xpress or implied, or) 446.86 194.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.83 (assumes an) 180 182.33 P +1.83 (y legal liability or responsibility f) 235.59 182.33 P +1.83 (or the accur) 383.89 182.33 P +1.83 (acy) 440.24 182.33 P +1.83 (, completeness) 454.8 182.33 P +1.83 (, or) 523.72 182.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.68 (usefulness of an) 180 170.33 P +3.68 (y inf) 260.02 170.33 P +3.68 (or) 281.74 170.33 P +3.68 (mation, appar) 290.88 170.33 P +3.68 (atus) 355.59 170.33 P +3.68 (, product or process disclosed, or) 374.34 170.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.46 (represents that its use w) 180 158.33 P +2.46 (ould not infr) 298.11 158.33 P +2.46 (inge pr) 355.42 158.33 P +2.46 (iv) 388.59 158.33 P +2.46 (ately o) 395.56 158.33 P +2.46 (wned r) 427.33 158.33 P +2.46 (ights) 459.95 158.33 P +2.46 (. Ref) 480.92 158.33 P +2.46 (erence) 509.43 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.6 (herein to an) 180 146.33 P +1.6 (y speci\336c commercial product, process) 235.85 146.33 P +1.6 (, or ser) 413.79 146.33 P +1.6 (vice b) 448.4 146.33 P +1.6 (y tr) 475.92 146.33 P +1.6 (ade name) 491.3 146.33 P +1.6 (,) 537.22 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (mar) 180 134.33 P +2.12 (k, man) 197.37 134.33 P +2.12 (uf) 229.4 134.33 P +2.12 (acturer) 237.44 134.33 P +2.12 (, or otherwise) 268.06 134.33 P +2.12 (, does not necessar) 332.17 134.33 P +2.12 (ily constitute or imply its) 425.94 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (endorsement, recommendation, or f) 180 122.33 P +1.08 (a) 341.33 122.33 P +1.08 (v) 346.69 122.33 P +1.08 (or) 351.44 122.33 P +1.08 (ing b) 360.48 122.33 P +1.08 (y the United States go) 383.03 122.33 P +1.08 (v) 485.57 122.33 P +1.08 (er) 490.32 122.33 P +1.08 (nment or) 499.46 122.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (an) 180 110.33 P +0.83 (y agency thereof) 190.97 110.33 P +0.83 (. The vie) 266.26 110.33 P +0.83 (w and opinions of the authors e) 309.67 110.33 P +0.83 (xpressed herein do) 453.3 110.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.94 (not necessar) 180 98.33 P +1.94 (ily state or re\337ect those of the United States go) 239.34 98.33 P +1.94 (v) 464.01 98.33 P +1.94 (er) 468.76 98.33 P +1.94 (nment or an) 477.9 98.33 P +1.94 (y) 535 98.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(agency thereof) 180 86.33 T +(.) 245.85 86.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DOCUMENT D) 54 668.33 T +(A) 121.37 668.33 T +(TE:) 127.69 668.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(T) 180 668.33 T +(ab) 184.91 668.33 T +(le of contents gener) 195.83 668.33 T +(ated: December 9, 1996 11:44 am) 283.56 668.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "ii" 2 +%%Page: "iii" 3 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +( T) 485.72 739 T +(ab) 492.64 739 T +(le of Contents) 502.47 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(iii) 551.34 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(T) 180 710.67 T +(ab) 187.43 710.67 T +(le of Contents) 203.63 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(T) 198 684.33 T +(ab) 202.91 684.33 T +(le of Contents) 213.83 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(iii) 551.34 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 180 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Director) 198 672.33 T +(y Str) 233.3 672.33 T +(ucture of the CDEV Distr) 254.01 672.33 T +(ib) 363.64 672.33 T +(ution) 371.22 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . .) 394.76 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Director) 198.2 660.33 T +(y Str) 233.5 660.33 T +(ucture) 254.21 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 180 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Installing and Building the CDEV Libr) 198 648.33 T +(ar) 361.86 648.33 T +(ies) 370.9 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 386.42 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ho) 198.2 636.33 T +(w to Star) 210.83 636.33 T +(t) 250.69 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 255.76 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Con\336gur) 198.2 624.33 T +(ing Static Ser) 236.14 624.33 T +(vices) 295.91 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 319.7 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Setting the Local En) 198.2 612.33 T +(vironment) 287.5 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 333.6 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Compiling the Distr) 198.2 600.33 T +(ib) 282.81 600.33 T +(ution) 290.39 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 314.14 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iii" 3 +%%Page: "iv" 4 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +( T) 54 739 T +(ab) 60.92 739 T +(le of Contents) 70.75 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(iv) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iv" 4 +%%Page: "1" 5 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. Director) 372.58 739 T +(y Str) 414.36 739 T +(ucture of the CDEV Distr) 433 739 T +(ib) 531.67 739 T +(ution) 538.49 739 T +0 10 Q +(1) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(1.) 159.32 710.67 T +(Director) 180 710.67 T +(y Structure of the CDEV Distrib) 233.82 710.67 T +(ution) 440.46 710.67 T +2 10 Q +(Director) 72 673.33 T +(y) 110.44 673.33 T +(Structure) 72 661.33 T +(./sr) 180 673.33 T +(c) 194.81 673.33 T +3 F +1.47 (The CDEV source parent director) 279.29 673.33 P +1.47 (y) 433.28 673.33 P +1.47 (, it contains mak) 437.28 673.33 P +1.47 (e\336les and) 513.73 673.33 P +1.83 (subdirector) 279.43 661.33 P +1.83 (ies with the source code necessar) 329.04 661.33 P +1.83 (y to create the) 489.13 661.33 P +(CDEV libr) 279.43 649.33 T +(ar) 323.22 649.33 T +(ies) 332.26 649.33 T +(.) 344.89 649.33 T +2 F +( . . . .) 180.7 625.33 T +(./sr) 207 625.33 T +(c/ca) 221.81 625.33 T +3 F +4.13 (Souce code pro) 279.29 625.33 P +4.13 (viding CDEV ser) 357.44 625.33 P +4.13 (vice suppor) 439.35 625.33 P +4.13 (t f) 495.01 625.33 P +4.13 (or channel) 507.18 625.33 P +(access and EPICS) 279.43 613.33 T +(.) 362.6 613.33 T +2 F +( . . . .) 180.7 589.33 T +(./sr) 207 589.33 T +(c/cde) 221.81 589.33 T +(vIO) 247.23 589.33 T +3 F +(Souce code f) 279.29 589.33 T +(or the cde) 337.36 589.33 T +(vData object and its components) 381.53 589.33 T +(.) 526.45 589.33 T +2 F +( . . . .) 180.7 565.33 T +(./sr) 207 565.33 T +(c/common) 221.81 565.33 T +3 F +2.31 (Source code f) 279.29 565.33 P +2.31 (or CDEV components that are used b) 345.3 565.33 P +2.31 (y class) 525.13 565.33 P +(inter) 279.43 553.33 T +(nals) 299.13 553.33 T +(.) 317.32 553.33 T +2 F +( . . . .) 180.7 529.33 T +(./sr) 207 529.33 T +(c/callbac) 221.81 529.33 T +(k) 263.86 529.33 T +3 F +2.1 (Source code f) 279.29 529.33 P +2.1 (or the cde) 344.89 529.33 P +2.1 (vCallbac) 393.27 529.33 P +2.1 (k object used with callbac) 431.41 529.33 P +2.1 (k) 553 529.33 P +(oper) 279.43 517.33 T +(ations and monitors) 299.34 517.33 T +(.) 386.45 517.33 T +2 F +( . . . .) 180.7 493.33 T +(./sr) 207 493.33 T +(c/de) 221.81 493.33 T +(vice) 241.67 493.33 T +3 F +4.78 (Source code f) 279.29 493.33 P +4.78 (or the cde) 350.25 493.33 P +4.78 (vDe) 403.98 493.33 P +4.78 (vice and cde) 421.46 493.33 P +4.78 (vRequestObject) 486.86 493.33 P +(objects and their associated component classes) 279.43 481.33 T +(.) 491.6 481.33 T +2 F +( . . . .) 180.7 457.33 T +(./sr) 207 457.33 T +(c/director) 221.81 457.33 T +(y) 267.48 457.33 T +3 F +(Source code f) 279.29 457.33 T +(or the cde) 340.69 457.33 T +(vDirector) 384.86 457.33 T +(y anc cde) 425.16 457.33 T +(vSvcFinder classes) 467.66 457.33 T +(.) 553.64 457.33 T +2 F +( . . . .) 180.7 433.33 T +(./sr) 207 433.33 T +(c/gr) 221.81 433.33 T +(oup) 239.95 433.33 T +3 F +(Source code f) 279.29 433.33 T +(or the cde) 340.69 433.33 T +(vGroup and cde) 384.86 433.33 T +(vT) 455.71 433.33 T +(r) 465.62 433.33 T +(anObj classes) 468.85 433.33 T +(.) 531.5 433.33 T +2 F +( . . . .) 180.7 409.33 T +(./sr) 207 409.33 T +(c/lib) 221.81 409.33 T +3 F +(Director) 279.29 409.33 T +(y f) 314.59 409.33 T +(or libr) 324.85 409.33 T +(ar) 349.75 409.33 T +(y Mak) 358.94 409.33 T +(e\336le and tempor) 385.41 409.33 T +(ar) 457.01 409.33 T +(y object \336les) 466.2 409.33 T +(.) 521.07 409.33 T +2 F +( . . . .) 180.7 385.33 T +(./sr) 207 385.33 T +(c/namesvc) 221.81 385.33 T +3 F +(Source code f) 279.29 385.33 T +(or tools used to parse the CDEV DDL \336le) 340.69 385.33 T +(.) 522.28 385.33 T +2 F +( . . . .) 180.7 361.33 T +(./sr) 207 361.33 T +(c/system) 221.81 361.33 T +3 F +0.31 (Source code f) 279.29 361.33 P +0.31 (or the cde) 341.32 361.33 P +0.31 (vSystem and cde) 386.12 361.33 P +0.31 (vSer) 463.15 361.33 P +0.31 (vice classes and) 484.01 361.33 P +(their associated components) 279.43 349.33 T +(.) 406.56 349.33 T +2 F +( . . . .) 180.7 325.33 T +(./sr) 207 325.33 T +(c/utility) 221.81 325.33 T +3 F +(Source code f) 279.29 325.33 T +(or a CDEV utility application.) 340.69 325.33 T +2 F +(./inc) 180 301.33 T +(lude) 199.81 301.33 T +3 F +4.01 (Header \336les f) 279.29 301.33 P +4.01 (or CDEV applications) 345.93 301.33 P +4.01 (, this director) 448.84 301.33 P +4.01 (y will be) 514.41 301.33 P +(populated dur) 279.43 289.33 T +(ing the \336rst e) 340.73 289.33 T +(x) 397.68 289.33 T +(ecution of mak) 402.38 289.33 T +(e) 467.21 289.33 T +2 F +(./lib) 180 265.33 T +3 F +3.85 (The CDEV libr) 279.29 265.33 P +3.85 (ar) 350.79 265.33 P +3.85 (y parent director) 359.98 265.33 P +3.85 (y) 440.22 265.33 P +3.85 (, will be populated wth) 444.22 265.33 P +(subdirector) 279.43 253.33 T +(ies f) 329.04 253.33 T +(or each target architecture) 347.08 253.33 T +(.) 463.65 253.33 T +2 F +(./bin) 180 229.33 T +3 F +3.84 (The CDEV binar) 279.29 229.33 P +3.84 (y parent director) 360.06 229.33 P +3.84 (y) 440.28 229.33 P +3.84 (, will be populated wth) 444.28 229.33 P +(subdirector) 279.43 217.33 T +(ies f) 329.04 217.33 T +(or each target architecture) 347.08 217.33 T +(.) 463.65 217.33 T +2 F +(./doc) 180 193.33 T +3 F +-0.19 (Contains most up to date v) 279.29 193.33 P +-0.19 (ersions of the CDEV documentation.) 397.03 193.33 P +2 F +(./e) 180 169.33 T +(xample) 190.97 169.33 T +3 F +(Sample applications and ser) 279.29 169.33 T +(vices that use CDEV) 405.2 169.33 T +(.) 495.65 169.33 T +2 F +(./e) 180 145.33 T +(xtensions) 190.97 145.33 T +3 F +2.66 (Softw) 279.29 145.33 P +2.66 (are e) 304.15 145.33 P +2.66 (xtensions and ser) 329.3 145.33 P +2.66 (vices f) 413.29 145.33 P +2.66 (or CDEV that are being) 443.98 145.33 P +0.33 (de) 279.43 133.33 P +0.33 (v) 290.25 133.33 P +0.33 (eloped b) 295 133.33 P +0.33 (y individual de) 333.49 133.33 P +0.33 (v) 397.2 133.33 P +0.33 (elopers) 401.95 133.33 P +0.33 (. These ser) 434.59 133.33 P +0.33 (vices add v) 488.67 133.33 P +0.33 (alue) 539.1 133.33 P +(to CDEV) 279.43 121.33 T +(, ho) 317.08 121.33 T +(w) 333.61 121.33 T +(e) 340.73 121.33 T +(v) 345.99 121.33 T +(er) 350.74 121.33 T +(, the) 359.13 121.33 T +(y are not required b) 378.39 121.33 T +(y the system.) 464.9 121.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "1" 5 +%%Page: "2" 6 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. Installing and Building the CDEV Libr) 54 739 T +(ar) 211.48 739 T +(ies) 219.62 739 T +0 10 Q +(2) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(2.) 141.32 710.67 T +(Installing and Building the CDEV Libraries) 162 710.67 T +2 10 Q +(Ho) 54 673.33 T +(w to Star) 67.18 673.33 T +(t) 109.61 673.33 T +0 F +(The f) 162 673.33 T +(ollo) 184.49 673.33 T +(wing steps should be tak) 199.9 673.33 T +(en in order to obtain and install CDEV at y) 309.2 673.33 T +(our site) 495.2 673.33 T +(.) 527.84 673.33 T +(1.) 162 656.33 T +2 F +(Obtain a cop) 180 656.33 T +(y of the CDEV distrib) 240.42 656.33 T +(ution.) 339.68 656.33 T +0 F +(A complete cop) 369.68 656.33 T +(y of the CDEV) 438.3 656.33 T +(distr) 180 644.33 T +(ib) 199.04 644.33 T +(ution ma) 206.62 644.33 T +(y be obtained b) 244.67 644.33 T +(y anon) 312.85 644.33 T +(ymous ftp at) 342.72 644.33 T +2 F +(ftp.cebaf) 399.97 644.33 T +(.go) 441.54 644.33 T +(v) 456.34 644.33 T +0 F +( in the director) 461.9 644.33 T +(y) 525.56 644.33 T +2 F +(pub/cde) 180 632.33 T +(v) 218.19 632.33 T +0 F +(.) 222.95 632.33 T +(2.) 162 608.33 T +2 F +(Unar) 180 608.33 T +(c) 202.58 608.33 T +(hive and install the distrib) 208.04 608.33 T +(ution.) 331.21 608.33 T +0 F +( The CDEV distr) 358.43 608.33 T +(ib) 430.82 608.33 T +(ution is pro) 438.4 608.33 T +(vided in a) 487.16 608.33 T +(compressed and archiv) 180 596.33 T +(ed f) 283.12 596.33 T +(or) 299.5 596.33 T +(mat. The archiv) 308.64 596.33 T +(e ma) 377.3 596.33 T +(y be decompressed using the) 399.23 596.33 T +(GNU) 180 584.33 T +3 F +(gzip) 205 584.33 T +0 F +( prog) 223.34 584.33 T +(r) 246.03 584.33 T +(am. The archiv) 249.26 584.33 T +(e ma) 315.14 584.33 T +(y then be e) 337.07 584.33 T +(xtr) 386.25 584.33 T +(acted using the UNIX) 397.26 584.33 T +3 F +(tar) 494.53 584.33 T +0 F +(command.) 180 572.33 T +2 F +(Con\336guring Static) 54 543.33 T +(Ser) 54 531.33 T +(vices) 70.22 531.33 T +0 F +(3.) 162 543.33 T +2 F +(Con\336gure static ser) 180 543.33 T +(vices \050ar) 274.01 543.33 T +(c) 314.39 543.33 T +(hive libraries\051.) 319.85 543.33 T +0 F +( If y) 387.66 543.33 T +(ou will be using the archiv) 403.58 543.33 T +(e) 517.82 543.33 T +(libr) 180 531.33 T +(ar) 193.23 531.33 T +(y v) 202.42 531.33 T +(ersion of CDEV) 214.95 531.33 T +(, y) 282.61 531.33 T +(ou m) 292.97 531.33 T +(ust tell CDEV the names of the ser) 315.1 531.33 T +(vices it will be) 468.8 531.33 T +(e) 180 519.33 T +(xpected to use) 185.26 519.33 T +(. This m) 250.15 519.33 T +(ust be done bef) 285.61 519.33 T +(ore an) 354.25 519.33 T +(y other installation procedures) 382.45 519.33 T +(.) 515.69 519.33 T +(The CDEV system pro) 180 495.33 T +(vides a w) 279.32 495.33 T +(a) 320.85 495.33 T +(y to con\336gure ser) 326.11 495.33 T +(vices so that applications can) 403.11 495.33 T +(access them b) 180 483.33 T +(y name) 244.27 483.33 T +(. F) 276.91 483.33 T +(or e) 288.28 483.33 T +(xample) 305.21 483.33 T +(, if y) 337.29 483.33 T +(ou ha) 355.43 483.33 T +(v) 380.25 483.33 T +(e the channel access ser) 385 483.33 T +(vice \050ca\051) 495.91 483.33 T +(and a locally de) 180 471.33 T +(v) 249.18 471.33 T +(eloped ser) 253.93 471.33 T +(vice \050xyz\051, y) 300.92 471.33 T +(ou can con\336gure CDEV to use these) 353.5 471.33 T +(ser) 180 459.33 T +(vices with the f) 194.19 459.33 T +(ollo) 259.47 459.33 T +(wing command.) 274.88 459.33 T +4 9 Q +(configSvc services=ca xyz headers=/usr/local/epics/include \134) 180 437 T +(/usr/local/cdev/src/ca /usr/local/cdev/src/xyz) 198 426 T +0 10 Q +-0.11 (In the abo) 180 402.33 P +-0.11 (v) 224.1 402.33 P +-0.11 (e e) 228.85 402.33 P +-0.11 (xamples) 242.34 402.33 P +-0.11 (,) 279.42 402.33 P +3 F +-0.11 (ser) 284.87 402.33 P +-0.11 (vices) 299.06 402.33 P +0 F +-0.11 ( are the names of the CDEV ser) 321.84 402.33 P +-0.11 (vices that should) 463.08 402.33 P +(be suppor) 180 390.33 T +(ted, and) 224.87 390.33 T +3 F +(headers) 263.79 390.33 T +0 F +( are the director) 299.92 390.33 T +(ies that should be searched f) 370.1 390.33 T +(or the) 497.65 390.33 T +(associated header \336les f) 180 378.33 T +(or these ser) 287.53 378.33 T +(vices) 340.63 378.33 T +(. The) 363.26 378.33 T +3 F +(con\336gSvc) 388.83 378.33 T +0 F +( scr) 432.18 378.33 T +(ipt will gener) 448.44 378.33 T +(ate a) 503.91 378.33 T +(Mak) 180 366.33 T +(e\336le and cde) 198.69 366.33 T +(vSvcCon\336g.cc in the) 255.09 366.33 T +3 F +( ./src/director) 345.68 366.33 T +(y) 403.77 366.33 T +0 F +( director) 408.77 366.33 T +(y) 445.19 366.33 T +(.) 449.19 366.33 T +2 F +(Setting the Local) 54 320.33 T +(En) 54 308.33 T +(vir) 66.38 308.33 T +(onment) 78.41 308.33 T +0 F +(4.) 162 320.33 T +2 F +-0.21 (Set CDEV required make v) 180 320.33 P +-0.21 (ariab) 304.55 320.33 P +-0.21 (les.) 328.35 320.33 P +0 F +-0.21 ( The f) 345.03 320.33 P +-0.21 (ollo) 369.88 320.33 P +-0.21 (wing en) 385.29 320.33 P +-0.21 (vironmental v) 419.34 320.33 P +-0.21 (ar) 478.33 320.33 P +-0.21 (iab) 487.37 320.33 P +-0.21 (les m) 500.51 320.33 P +-0.21 (ust) 524.09 320.33 P +(be de\336ned pr) 180 308.33 T +(ior to making the CDEV libr) 238.52 308.33 T +(ar) 359.01 308.33 T +(ies) 368.05 308.33 T +(.) 380.68 308.33 T +2 F +(CDEV) 180 284.33 T +(:) 207.38 284.33 T +0 F +(This is the root director) 314.62 284.33 T +(y of the CDEV distr) 416.62 284.33 T +(ib) 501.8 284.33 T +(ution.) 509.38 284.33 T +2 F +(CDEVDDL:) 180 260.33 T +0 F +(This is the location of the CDEV De) 314.62 260.33 T +(vice De\336nition) 471.05 260.33 T +(Language \336le) 315.12 248.33 T +(.) 375.01 248.33 T +2 F +(CDEVSHOBJ:) 180 224.33 T +0 F +(This is the director) 314.62 224.33 T +(y where the CDEV shared) 396.61 224.33 T +(libr) 315.12 212.33 T +(ar) 328.35 212.33 T +(ies and shared objects will be stored.) 337.39 212.33 T +2 F +(CDEVINCLUDE:) 180 188.33 T +0 F +-0.35 (This is the director) 314.62 188.33 P +-0.35 (y whe) 395.57 188.33 P +-0.35 (wre the CDEV header \336les) 421.14 188.33 P +(are located.) 315.12 176.33 T +2 F +(SHOBJ) 180 152.33 T +0 F +(:) 214.45 152.33 T +-0.54 (This v) 314.62 152.33 P +-0.54 (ar) 340.5 152.33 P +-0.54 (iab) 349.54 152.33 P +-0.54 (le indicates that a shar) 362.68 152.33 P +-0.54 (ab) 460.48 152.33 P +-0.54 (le object libr) 471.4 152.33 P +-0.54 (ar) 523.57 152.33 P +-0.54 (y) 532.76 152.33 P +(should be compiled. In order to gener) 315.12 140.33 T +(ate a) 480.66 140.33 T +(shar) 315.12 128.33 T +(ab) 334.47 128.33 T +(le libr) 345.39 128.33 T +(ar) 369.18 128.33 T +(y) 378.37 128.33 T +(,) 382.37 128.33 T +3 F +(SHOBJ=\323YES\323) 387.93 128.33 T +0 F +(should be) 456.56 128.33 T +(speci\336ed. This v) 315.12 116.33 T +(ar) 386.56 116.33 T +(iab) 395.6 116.33 T +(le is unde\336ned b) 408.74 116.33 T +(y def) 481.36 116.33 T +(ault.) 502.74 116.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "2" 6 +%%Page: "3" 7 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. Installing and Building the CDEV Libr) 380.88 739 T +(ar) 538.36 739 T +(ies) 546.5 739 T +0 10 Q +(3) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Compiling the) 72 713.33 T +(Distrib) 72 701.33 T +(ution) 103.47 701.33 T +0 F +(5.) 180 713.33 T +(Change director) 198 713.33 T +(ies to the CDEV distr) 269.29 713.33 T +(ib) 362.25 713.33 T +(ution ./src director) 369.83 713.33 T +(y) 449.6 713.33 T +(. This is where the) 453.6 713.33 T +(Mak) 198 701.33 T +(e\336le and Mak) 216.69 701.33 T +(e\336le) 275.96 701.33 T +(.common will be located.) 294.15 701.33 T +(6.) 180 677.33 T +(If y) 198 677.33 T +(ou ha) 211.14 677.33 T +(v) 235.96 677.33 T +(e compiled the CDEV distr) 240.71 677.33 T +(ib) 358.12 677.33 T +(ution f) 365.7 677.33 T +(or another T) 392.64 677.33 T +(ARGET in the past, y) 445.91 677.33 T +(ou) 539.64 677.33 T +(should e) 198 665.33 T +(x) 235.5 665.33 T +(ecute a \324mak) 240.2 665.33 T +(e clean\325 to remo) 296.69 665.33 T +(v) 367.68 665.33 T +(e an) 372.43 665.33 T +(y outdated object \336les) 391.74 665.33 T +(.) 488.31 665.33 T +(7.) 180 641.33 T +(If y) 198 641.33 T +(ou w) 211.14 641.33 T +(ant to change def) 232.11 641.33 T +(ault time-out v) 309.09 641.33 T +(alue and connection retr) 371.64 641.33 T +(y frequency in) 479.22 641.33 T +(channel access or EPICS) 198 629.33 T +(, y) 311.18 629.33 T +(ou should change DEF) 321.54 629.33 T +(A) 422.46 629.33 T +(UL) 428.63 629.33 T +(T_TIMEOUT and) 440.31 629.33 T +(DEF) 198 617.33 T +(A) 217.2 617.33 T +(UL) 223.37 617.33 T +(T_CONN_FREQ) 235.05 617.33 T +(UENCY v) 309.4 617.33 T +(alues in the caRequestObject.h.) 351.93 617.33 T +(8.) 180 593.33 T +(T) 198 593.33 T +(o begin compilation type the command \324mak) 202.91 593.33 T +(e all\325 or \324mak) 397.79 593.33 T +(e\325. This will compile all) 453.71 593.33 T +(libr) 198 581.33 T +(ar) 211.23 581.33 T +(ies and utility applications and place them in the appropr) 220.27 581.33 T +(iate T) 469.43 581.33 T +(ARGET) 493.24 581.33 T +(director) 198 569.33 T +(ies) 231.49 569.33 T +(.) 244.12 569.33 T +(9.) 180 545.33 T +(T) 198 545.33 T +(o remo) 202.91 545.33 T +(v) 233.88 545.33 T +(e objects after making archiv) 238.63 545.33 T +(e libr) 365.65 545.33 T +(ar) 387.22 545.33 T +(ies) 396.26 545.33 T +(,) 408.89 545.33 T +( type \324mak) 414.45 545.33 T +(e cleanObjs\325. This is) 459.82 545.33 T +(useful to mak) 198 533.33 T +(e the archiv) 257.27 533.33 T +(e libr) 308.71 533.33 T +(ar) 330.28 533.33 T +(ies and then mak) 339.32 533.33 T +(e the shared libr) 415.27 533.33 T +(ar) 486.87 533.33 T +(ies) 495.91 533.33 T +(.) 508.54 533.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "3" 7 +%%Page: "4" 8 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. Installing and Building the CDEV Libr) 54 739 T +(ar) 211.48 739 T +(ies) 219.62 739 T +0 10 Q +(4) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "4" 8 +%%Trailer +%%BoundingBox: 0 0 612 792 +%%PageOrder: Ascend +%%Pages: 8 +%%DocumentFonts: Helvetica +%%+ Times-BoldItalic +%%+ Helvetica-Bold +%%+ Helvetica-Oblique +%%+ Courier +%%EOF diff --git a/doc/ps/cdevCbinding.ps b/doc/ps/cdevCbinding.ps new file mode 100755 index 0000000..1c1e45e --- /dev/null +++ b/doc/ps/cdevCbinding.ps @@ -0,0 +1,3855 @@ +%!PS-Adobe-3.0 +%%BoundingBox: (atend) +%%Pages: (atend) +%%PageOrder: (atend) +%%DocumentFonts: (atend) +%%Creator: Frame 5.0 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +% +% Frame ps_prolog 5.0, for use with Frame 5.0 products +% This ps_prolog file is Copyright (c) 1986-1995 Frame Technology +% Corporation. All rights reserved. This ps_prolog file may be +% freely copied and distributed in conjunction with documents created +% using FrameMaker, FrameMaker/SGML and FrameViewer as long as this +% copyright notice is preserved. +% +% FrameMaker users specify the proper paper size for each print job in the +% "Print" dialog's "Printer Paper Size" "Width" and "Height~ fields. If the +% printer that the PS file is sent to does not support the requested paper +% size, or if there is no paper tray of the proper size currently installed, +% then the job will not be printed. The following flag, if set to true, will +% cause the job to print on the default paper in such cases. +/FMAllowPaperSizeMismatch false def +% +% Frame products normally print colors as their true color on a color printer +% or as shades of gray, based on luminance, on a black-and white printer. The +% following flag, if set to true, forces all non-white colors to print as pure +% black. This has no effect on bitmap images. +/FMPrintAllColorsAsBlack false def +% +% Frame products can either set their own line screens or use a printer's +% default settings. Three flags below control this separately for no +% separations, spot separations and process separations. If a flag +% is true, then the default printer settings will not be changed. If it is +% false, Frame products will use their own settings from a table based on +% the printer's resolution. +/FMUseDefaultNoSeparationScreen true def +/FMUseDefaultSpotSeparationScreen true def +/FMUseDefaultProcessSeparationScreen false def +% +% For any given PostScript printer resolution, Frame products have two sets of +% screen angles and frequencies for printing process separations, which are +% recomended by Adobe. The following variable chooses the higher frequencies +% when set to true or the lower frequencies when set to false. This is only +% effective if the appropriate FMUseDefault...SeparationScreen flag is false. +/FMUseHighFrequencyScreens true def +% +% The following is a set of predefined optimal frequencies and angles for various +% common dpi settings. This is taken from "Advances in Color Separation Using +% PostScript Software Technology," from Adobe Systems (3/13/89 P.N. LPS 0043) +% and corrolated with information which is in various PPD (4.0) files. +% +% The "dpiranges" figure is the minimum dots per inch device resolution which +% can support this setting. The "low" and "high" values are controlled by the +% setting of the FMUseHighFrequencyScreens flag above. The "TDot" flags control +% the use of the "Yellow Triple Dot" feature whereby the frequency id divided by +% three, but the dot function is "trippled" giving a block of 3x3 dots per cell. +% +% PatFreq is a compromise pattern frequency for ps Level 2 printers which is close +% to the ideal WYSIWYG pattern frequency of 9 repetitions/inch but does not beat +% (too badly) against the screen frequencies of any separations for that DPI. +/dpiranges [ 2540 2400 1693 1270 1200 635 600 0 ] def +/CMLowFreqs [ 100.402 94.8683 89.2289 100.402 94.8683 66.9349 63.2456 47.4342 ] def +/YLowFreqs [ 95.25 90.0 84.65 95.25 90.0 70.5556 66.6667 50.0 ] def +/KLowFreqs [ 89.8026 84.8528 79.8088 89.8026 84.8528 74.8355 70.7107 53.033 ] def +/CLowAngles [ 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 ] def +/MLowAngles [ 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 ] def +/YLowTDot [ true true false true true false false false ] def +/CMHighFreqs [ 133.87 126.491 133.843 108.503 102.523 100.402 94.8683 63.2456 ] def +/YHighFreqs [ 127.0 120.0 126.975 115.455 109.091 95.25 90.0 60.0 ] def +/KHighFreqs [ 119.737 113.137 119.713 128.289 121.218 89.8026 84.8528 63.6395 ] def +/CHighAngles [ 71.5651 71.5651 71.5651 70.0169 70.0169 71.5651 71.5651 71.5651 ] def +/MHighAngles [ 18.4349 18.4349 18.4349 19.9831 19.9831 18.4349 18.4349 18.4349 ] def +/YHighTDot [ false false true false false true true false ] def +/PatFreq [ 10.5833 10.0 9.4055 10.5833 10.0 10.5833 10.0 9.375 ] def +% +% PostScript Level 2 printers contain an "Accurate Screens" feature which can +% improve process separation rendering at the expense of compute time. This +% flag is ignored by PostScript Level 1 printers. +/FMUseAcccurateScreens true def +% +% The following PostScript procedure defines the spot function that Frame +% products will use for process separations. You may un-comment-out one of +% the alternative functions below, or use your own. +% +% Dot function +/FMSpotFunction {abs exch abs 2 copy add 1 gt + {1 sub dup mul exch 1 sub dup mul add 1 sub } + {dup mul exch dup mul add 1 exch sub }ifelse } def +% +% Line function +% /FMSpotFunction { pop } def +% +% Elipse function +% /FMSpotFunction { dup 5 mul 8 div mul exch dup mul exch add +% sqrt 1 exch sub } def +% +% +/FMversion (5.0) def +/fMLevel1 /languagelevel where {pop languagelevel} {1} ifelse 2 lt def +/FMPColor + fMLevel1 { + false + /colorimage where {pop pop true} if + } { + true + } ifelse +def +/FrameDict 400 dict def +systemdict /errordict known not {/errordict 10 dict def + errordict /rangecheck {stop} put} if +% The readline in PS 23.0 doesn't recognize cr's as nl's on AppleTalk +FrameDict /tmprangecheck errordict /rangecheck get put +errordict /rangecheck {FrameDict /bug true put} put +FrameDict /bug false put +mark +% Some PS machines read past the CR, so keep the following 3 lines together! +currentfile 5 string readline +00 +0000000000 +cleartomark +errordict /rangecheck FrameDict /tmprangecheck get put +FrameDict /bug get { + /readline { + /gstring exch def + /gfile exch def + /gindex 0 def + { + gfile read pop + dup 10 eq {exit} if + dup 13 eq {exit} if + gstring exch gindex exch put + /gindex gindex 1 add def + } loop + pop + gstring 0 gindex getinterval true + } bind def + } if +/FMshowpage /showpage load def +/FMquit /quit load def +/FMFAILURE { + dup = flush + FMshowpage + /Helvetica findfont 12 scalefont setfont + 72 200 moveto show + 72 220 moveto show + FMshowpage + FMquit + } def +/FMVERSION { + FMversion ne { + (Frame product version does not match ps_prolog! Check installation;) + (also check ~/fminit and ./fminit for old versions) FMFAILURE + } if + } def +/FMBADEPSF { + (Adobe's PostScript Language Reference Manual, 2nd Edition, section H.2.4) + (says your EPS file is not valid, as it calls X ) + dup dup (X) search pop exch pop exch pop length + 5 -1 roll + putinterval + FMFAILURE + } def +/fmConcatProcs + { + /proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def + newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx +}def +FrameDict begin [ + /ALDsave + /FMdicttop + /FMoptop + /FMpointsize + /FMsaveobject + /b + /bitmapsave + /blut + /bpside + /bs + /bstring + /bwidth + /c + /cf + /cs + /cynu + /depth + /edown + /fh + /fillvals + /fw + /fx + /fy + /g + /gfile + /gindex + /grnt + /gryt + /gstring + /height + /hh + /i + /im + /indx + /is + /k + /kk + /landscape + /lb + /len + /llx + /lly + /m + /magu + /manualfeed + /n + /offbits + /onbits + /organgle + /orgbangle + /orgbfreq + /orgbproc + /orgbxfer + /orgfreq + /orggangle + /orggfreq + /orggproc + /orggxfer + /orgmatrix + /orgproc + /orgrangle + /orgrfreq + /orgrproc + /orgrxfer + /orgxfer + /pagesave + /paperheight + /papersizedict + /paperwidth + /pos + /pwid + /r + /rad + /redt + /sl + /str + /tran + /u + /urx + /ury + /val + /width + /width + /ws + /ww + /x + /x1 + /x2 + /xindex + /xpoint + /xscale + /xx + /y + /y1 + /y2 + /yelu + /yindex + /ypoint + /yscale + /yy +] { 0 def } forall +/FmBD {bind def} bind def +systemdict /pdfmark known { + /fMAcrobat true def + + /FmPD /pdfmark load def + + + /FmPT /show load def + + + currentdistillerparams /CoreDistVersion get 2000 ge { + + + /FmPD2 /pdfmark load def + + + + + + /FmPA { mark exch /Dest exch 5 3 roll + /View [ /XYZ null 6 -2 roll FmDC exch pop null] /DEST FmPD + }FmBD + } { + + /FmPD2 /cleartomark load def + /FmPA {pop pop pop}FmBD + } ifelse +} { + + /fMAcrobat false def + /FmPD /cleartomark load def + /FmPD2 /cleartomark load def + /FmPT /pop load def + /FmPA {pop pop pop}FmBD +} ifelse +/FmDC { + transform fMDefaultMatrix itransform cvi exch cvi exch +}FmBD +/FmBx { + dup 3 index lt {3 1 roll exch} if + 1 index 4 index lt {4 -1 roll 3 1 roll exch 4 1 roll} if +}FmBD +/FMnone 0 def +/FMcyan 1 def +/FMmagenta 2 def +/FMyellow 3 def +/FMblack 4 def +/FMcustom 5 def +/fMNegative false def +/FrameSepIs FMnone def +/FrameSepBlack 0 def +/FrameSepYellow 0 def +/FrameSepMagenta 0 def +/FrameSepCyan 0 def +/FrameSepRed 1 def +/FrameSepGreen 1 def +/FrameSepBlue 1 def +/FrameCurGray 1 def +/FrameCurPat null def +/FrameCurColors [ 0 0 0 1 0 0 0 ] def +/FrameColorEpsilon .001 def +/eqepsilon { + sub dup 0 lt {neg} if + FrameColorEpsilon le +} bind def +/FrameCmpColorsCMYK { + 2 copy 0 get exch 0 get eqepsilon { + 2 copy 1 get exch 1 get eqepsilon { + 2 copy 2 get exch 2 get eqepsilon { + 3 get exch 3 get eqepsilon + } {pop pop false} ifelse + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/FrameCmpColorsRGB { + 2 copy 4 get exch 0 get eqepsilon { + 2 copy 5 get exch 1 get eqepsilon { + 6 get exch 2 get eqepsilon + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/RGBtoCMYK { + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 3 copy + 2 copy + le { pop } { exch pop } ifelse + 2 copy + le { pop } { exch pop } ifelse + dup dup dup + 6 1 roll + 4 1 roll + 7 1 roll + sub + 6 1 roll + sub + 5 1 roll + sub + 4 1 roll +} bind def +/CMYKtoRGB { + dup dup 4 -1 roll add + 5 1 roll 3 -1 roll add + 4 1 roll add + 1 exch sub dup 0 lt {pop 0} if 3 1 roll + 1 exch sub dup 0 lt {pop 0} if exch + 1 exch sub dup 0 lt {pop 0} if exch +} bind def +/FrameSepInit { + 1.0 RealSetgray +} bind def +/FrameSetSepColor { + /FrameSepBlue exch def + /FrameSepGreen exch def + /FrameSepRed exch def + /FrameSepBlack exch def + /FrameSepYellow exch def + /FrameSepMagenta exch def + /FrameSepCyan exch def + /FrameSepIs FMcustom def + setCurrentScreen +} bind def +/FrameSetCyan { + /FrameSepBlue 1.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 1.0 def + /FrameSepIs FMcyan def + setCurrentScreen +} bind def + +/FrameSetMagenta { + /FrameSepBlue 1.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 1.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMmagenta def + setCurrentScreen +} bind def + +/FrameSetYellow { + /FrameSepBlue 0.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 1.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMyellow def + setCurrentScreen +} bind def + +/FrameSetBlack { + /FrameSepBlue 0.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 1.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMblack def + setCurrentScreen +} bind def + +/FrameNoSep { + /FrameSepIs FMnone def + setCurrentScreen +} bind def +/FrameSetSepColors { + FrameDict begin + [ exch 1 add 1 roll ] + /FrameSepColors + exch def end + } bind def +/FrameColorInSepListCMYK { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsCMYK + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/FrameColorInSepListRGB { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsRGB + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/RealSetgray /setgray load def +/RealSetrgbcolor /setrgbcolor load def +/RealSethsbcolor /sethsbcolor load def +end +/setgray { + FrameDict begin + FrameSepIs FMnone eq + { RealSetgray } + { + FrameSepIs FMblack eq + { RealSetgray } + { FrameSepIs FMcustom eq + FrameSepRed 0 eq and + FrameSepGreen 0 eq and + FrameSepBlue 0 eq and { + RealSetgray + } { + 1 RealSetgray pop + } ifelse + } ifelse + } ifelse + end +} bind def +/setrgbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetrgbcolor } + { + 3 copy [ 4 1 roll ] + FrameColorInSepListRGB + { + FrameSepBlue eq exch + FrameSepGreen eq and exch + FrameSepRed eq and + { 0 } { 1 } ifelse + } + { + FMPColor { + RealSetrgbcolor + currentcmykcolor + } { + RGBtoCMYK + } ifelse + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end +} bind def +/sethsbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSethsbcolor } + { + RealSethsbcolor + currentrgbcolor + setrgbcolor + } + ifelse + end +} bind def +FrameDict begin +/setcmykcolor where { + pop /RealSetcmykcolor /setcmykcolor load def +} { + /RealSetcmykcolor { + 4 1 roll + 3 { 3 index add 0 max 1 min 1 exch sub 3 1 roll} repeat + RealSetrgbcolor pop + } bind def +} ifelse +userdict /setcmykcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetcmykcolor } + { + 4 copy [ 5 1 roll ] + FrameColorInSepListCMYK + { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + { 0 } { 1 } ifelse + } + { + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end + } bind put +fMLevel1 { + + + + /patScreenDict 7 dict dup begin + <0f1e3c78f0e1c387> [ 45 { pop } {exch pop} .5 2 sqrt] FmBD + <0f87c3e1f0783c1e> [ 135 { pop } {exch pop} .5 2 sqrt] FmBD + [ 0 { pop } dup .5 2 ] FmBD + [ 90 { pop } dup .5 2 ] FmBD + <8142241818244281> [ 45 { 2 copy lt {exch} if pop} dup .75 2 sqrt] FmBD + <03060c183060c081> [ 45 { pop } {exch pop} .875 2 sqrt] FmBD + <8040201008040201> [ 135 { pop } {exch pop} .875 2 sqrt] FmBD + end def +} { + + /patProcDict 5 dict dup begin + <0f1e3c78f0e1c387> { 3 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <0f87c3e1f0783c1e> { 3 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + <8142241818244281> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -1 -1 moveto 9 9 lineto stroke } bind def + <03060c183060c081> { 1 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <8040201008040201> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + end def + /patDict 15 dict dup begin + /PatternType 1 def + /PaintType 2 def + /TilingType 3 def + /BBox [ 0 0 8 8 ] def + /XStep 8 def + /YStep 8 def + /PaintProc { + begin + patProcDict bstring known { + patProcDict bstring get exec + } { + 8 8 true [1 0 0 -1 0 8] bstring imagemask + } ifelse + end + } bind def + end def +} ifelse +/combineColor { + FrameSepIs FMnone eq + { + graymode fMLevel1 or not { + + [/Pattern [/DeviceCMYK]] setcolorspace + FrameCurColors 0 4 getinterval aload pop FrameCurPat setcolor + } { + FrameCurColors 3 get 1.0 ge { + FrameCurGray RealSetgray + } { + fMAcrobat not FMPColor graymode and and { + 0 1 3 { + FrameCurColors exch get + 1 FrameCurGray sub mul + } for + RealSetcmykcolor + } { + 4 1 6 { + FrameCurColors exch get + graymode { + 1 exch sub 1 FrameCurGray sub mul 1 exch sub + } { + 1.0 lt {FrameCurGray} {1} ifelse + } ifelse + } for + RealSetrgbcolor + } ifelse + } ifelse + } ifelse + } { + FrameCurColors 0 4 getinterval aload + FrameColorInSepListCMYK { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + FrameSepIs FMcustom eq and + { FrameCurGray } { 1 } ifelse + } { + FrameSepIs FMblack eq + {FrameCurGray 1.0 exch sub mul 1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop FrameCurGray 1.0 exch sub mul 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + graymode fMLevel1 or not { + + [/Pattern [/DeviceGray]] setcolorspace + FrameCurPat setcolor + } { + graymode not fMLevel1 and { + + dup 1 lt {pop FrameCurGray} if + } if + RealSetgray + } ifelse + } ifelse +} bind def +/savematrix { + orgmatrix currentmatrix pop + } bind def +/restorematrix { + orgmatrix setmatrix + } bind def +/fMDefaultMatrix matrix defaultmatrix def +/fMatrix2 matrix def +/dpi 72 0 fMDefaultMatrix dtransform + dup mul exch dup mul add sqrt def + +/freq dpi dup 72 div round dup 0 eq {pop 1} if 8 mul div def +/sangle 1 0 fMDefaultMatrix dtransform exch atan def + sangle fMatrix2 rotate + fMDefaultMatrix fMatrix2 concatmatrix + dup 0 get /sflipx exch def + 3 get /sflipy exch def +/screenIndex { + 0 1 dpiranges length 1 sub { dup dpiranges exch get 1 sub dpi le {exit} {pop} ifelse } for +} bind def +/getCyanScreen { + FMUseHighFrequencyScreens { CHighAngles CMHighFreqs} {CLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getMagentaScreen { + FMUseHighFrequencyScreens { MHighAngles CMHighFreqs } {MLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getYellowScreen { + FMUseHighFrequencyScreens { YHighTDot YHighFreqs} { YLowTDot YLowFreqs } ifelse + screenIndex dup 3 1 roll get 3 1 roll get { 3 div + {2 { 1 add 2 div 3 mul dup floor sub 2 mul 1 sub exch} repeat + FMSpotFunction } } {/FMSpotFunction load } ifelse + 0.0 exch +} bind def +/getBlackScreen { + FMUseHighFrequencyScreens { KHighFreqs } { KLowFreqs } ifelse + screenIndex get 45.0 /FMSpotFunction load +} bind def +/getSpotScreen { + getBlackScreen +} bind def +/getCompositeScreen { + getBlackScreen +} bind def +/FMSetScreen + fMLevel1 { /setscreen load + }{ { + 8 dict begin + /HalftoneType 1 def + /SpotFunction exch def + /Angle exch def + /Frequency exch def + /AccurateScreens FMUseAcccurateScreens def + currentdict end sethalftone + } bind } ifelse +def +/setDefaultScreen { + FMPColor { + orgrxfer cvx orggxfer cvx orgbxfer cvx orgxfer cvx setcolortransfer + } + { + orgxfer cvx settransfer + } ifelse + orgfreq organgle orgproc cvx setscreen +} bind def +/setCurrentScreen { + FrameSepIs FMnone eq { + FMUseDefaultNoSeparationScreen { + setDefaultScreen + } { + getCompositeScreen FMSetScreen + } ifelse + } { + FrameSepIs FMcustom eq { + FMUseDefaultSpotSeparationScreen { + setDefaultScreen + } { + getSpotScreen FMSetScreen + } ifelse + } { + FMUseDefaultProcessSeparationScreen { + setDefaultScreen + } { + FrameSepIs FMcyan eq { + getCyanScreen FMSetScreen + } { + FrameSepIs FMmagenta eq { + getMagentaScreen FMSetScreen + } { + FrameSepIs FMyellow eq { + getYellowScreen FMSetScreen + } { + getBlackScreen FMSetScreen + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse +} bind def +end + +/FMDOCUMENT { + array /FMfonts exch def + /#copies exch def + FrameDict begin + 0 ne /manualfeed exch def + /paperheight exch def + /paperwidth exch def + 0 ne /fMNegative exch def + 0 ne /edown exch def + /yscale exch def + /xscale exch def + fMLevel1 { + manualfeed {setmanualfeed} if + /FMdicttop countdictstack 1 add def + /FMoptop count def + setpapername + manualfeed {true} {papersize} ifelse + {manualpapersize} {false} ifelse + {desperatepapersize} {false} ifelse + {papersizefailure} if + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + } + {2 dict + dup /PageSize [paperwidth paperheight] put + manualfeed {dup /ManualFeed manualfeed put} if + {setpagedevice} stopped {papersizefailure} if + } + ifelse + + FMPColor { + currentcolorscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + cvlit /orgbproc exch def + /orgbangle exch def + /orgbfreq exch def + cvlit /orggproc exch def + /orggangle exch def + /orggfreq exch def + cvlit /orgrproc exch def + /orgrangle exch def + /orgrfreq exch def + currentcolortransfer + fMNegative { + 1 1 4 { + pop { 1 exch sub } fmConcatProcs 4 1 roll + } for + 4 copy + setcolortransfer + } if + cvlit /orgxfer exch def + cvlit /orgbxfer exch def + cvlit /orggxfer exch def + cvlit /orgrxfer exch def + } { + currentscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + + currenttransfer + fMNegative { + { 1 exch sub } fmConcatProcs + dup settransfer + } if + cvlit /orgxfer exch def + } ifelse + end +} def +/FMBEGINPAGE { + FrameDict begin + /pagesave save def + 3.86 setmiterlimit + /landscape exch 0 ne def + landscape { + 90 rotate 0 exch dup /pwid exch def neg translate pop + }{ + pop /pwid exch def + } ifelse + edown { [-1 0 0 1 pwid 0] concat } if + 0 0 moveto paperwidth 0 lineto paperwidth paperheight lineto + 0 paperheight lineto 0 0 lineto 1 setgray fill + xscale yscale scale + /orgmatrix matrix def + gsave +} def +/FMENDPAGE { + grestore + pagesave restore + end + showpage + } def +/FMFONTDEFINE { + FrameDict begin + findfont + ReEncode + 1 index exch + definefont + FMfonts 3 1 roll + put + end + } def +/FMFILLS { + FrameDict begin dup + array /fillvals exch def + dict /patCache exch def + end + } def +/FMFILL { + FrameDict begin + fillvals 3 1 roll put + end + } def +/FMNORMALIZEGRAPHICS { + newpath + 1 setlinewidth + 0 setlinecap + 0 0 0 sethsbcolor + 0 setgray + } bind def +/FMBEGINEPSF { + end + /FMEPSF save def + /showpage {} def +% See Adobe's "PostScript Language Reference Manual, 2nd Edition", page 714. +% "...the following operators MUST NOT be used in an EPS file:" (emphasis ours) + /banddevice {(banddevice) FMBADEPSF} def + /clear {(clear) FMBADEPSF} def + /cleardictstack {(cleardictstack) FMBADEPSF} def + /copypage {(copypage) FMBADEPSF} def + /erasepage {(erasepage) FMBADEPSF} def + /exitserver {(exitserver) FMBADEPSF} def + /framedevice {(framedevice) FMBADEPSF} def + /grestoreall {(grestoreall) FMBADEPSF} def + /initclip {(initclip) FMBADEPSF} def + /initgraphics {(initgraphics) FMBADEPSF} def + /quit {(quit) FMBADEPSF} def + /renderbands {(renderbands) FMBADEPSF} def + /setglobal {(setglobal) FMBADEPSF} def + /setpagedevice {(setpagedevice) FMBADEPSF} def + /setshared {(setshared) FMBADEPSF} def + /startjob {(startjob) FMBADEPSF} def + /lettertray {(lettertray) FMBADEPSF} def + /letter {(letter) FMBADEPSF} def + /lettersmall {(lettersmall) FMBADEPSF} def + /11x17tray {(11x17tray) FMBADEPSF} def + /11x17 {(11x17) FMBADEPSF} def + /ledgertray {(ledgertray) FMBADEPSF} def + /ledger {(ledger) FMBADEPSF} def + /legaltray {(legaltray) FMBADEPSF} def + /legal {(legal) FMBADEPSF} def + /statementtray {(statementtray) FMBADEPSF} def + /statement {(statement) FMBADEPSF} def + /executivetray {(executivetray) FMBADEPSF} def + /executive {(executive) FMBADEPSF} def + /a3tray {(a3tray) FMBADEPSF} def + /a3 {(a3) FMBADEPSF} def + /a4tray {(a4tray) FMBADEPSF} def + /a4 {(a4) FMBADEPSF} def + /a4small {(a4small) FMBADEPSF} def + /b4tray {(b4tray) FMBADEPSF} def + /b4 {(b4) FMBADEPSF} def + /b5tray {(b5tray) FMBADEPSF} def + /b5 {(b5) FMBADEPSF} def + FMNORMALIZEGRAPHICS + [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall + fx fw 2 div add fy fh 2 div add translate + rotate + fw 2 div neg fh 2 div neg translate + fw urx llx sub div fh ury lly sub div scale + llx neg lly neg translate + /FMdicttop countdictstack 1 add def + /FMoptop count def + } bind def +/FMENDEPSF { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMEPSF restore + FrameDict begin + } bind def +FrameDict begin +/setmanualfeed { +%%BeginFeature *ManualFeed True + statusdict /manualfeed true put +%%EndFeature + } bind def +/max {2 copy lt {exch} if pop} bind def +/min {2 copy gt {exch} if pop} bind def +/inch {72 mul} def +/pagedimen { + paperheight sub abs 16 lt exch + paperwidth sub abs 16 lt and + {/papername exch def} {pop} ifelse + } bind def +/setpapername { + /papersizedict 14 dict def + papersizedict begin + /papername /unknown def + /Letter 8.5 inch 11.0 inch pagedimen + /LetterSmall 7.68 inch 10.16 inch pagedimen + /Tabloid 11.0 inch 17.0 inch pagedimen + /Ledger 17.0 inch 11.0 inch pagedimen + /Legal 8.5 inch 14.0 inch pagedimen + /Statement 5.5 inch 8.5 inch pagedimen + /Executive 7.5 inch 10.0 inch pagedimen + /A3 11.69 inch 16.5 inch pagedimen + /A4 8.26 inch 11.69 inch pagedimen + /A4Small 7.47 inch 10.85 inch pagedimen + /B4 10.125 inch 14.33 inch pagedimen + /B5 7.16 inch 10.125 inch pagedimen + end + } bind def +/papersize { + papersizedict begin + /Letter {lettertray letter} def + /LetterSmall {lettertray lettersmall} def + /Tabloid {11x17tray 11x17} def + /Ledger {ledgertray ledger} def + /Legal {legaltray legal} def + /Statement {statementtray statement} def + /Executive {executivetray executive} def + /A3 {a3tray a3} def + /A4 {a4tray a4} def + /A4Small {a4tray a4small} def + /B4 {b4tray b4} def + /B5 {b5tray b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + statusdict begin stopped end + } bind def +/manualpapersize { + papersizedict begin + /Letter {letter} def + /LetterSmall {lettersmall} def + /Tabloid {11x17} def + /Ledger {ledger} def + /Legal {legal} def + /Statement {statement} def + /Executive {executive} def + /A3 {a3} def + /A4 {a4} def + /A4Small {a4small} def + /B4 {b4} def + /B5 {b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + stopped + } bind def +/desperatepapersize { + statusdict /setpageparams known + { + paperwidth paperheight 0 1 + statusdict begin + {setpageparams} stopped + end + } {true} ifelse + } bind def +/papersizefailure { + FMAllowPaperSizeMismatch not + { +(The requested paper size is not available in any currently-installed tray) +(Edit the PS file to "FMAllowPaperSizeMismatch true" to use default tray) + FMFAILURE } if + } def +/DiacriticEncoding [ +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl +/numbersign /dollar /percent /ampersand /quotesingle /parenleft +/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K +/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash +/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h +/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar +/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute +/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis +/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis +/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve +/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex +/udieresis /dagger /.notdef /cent /sterling /section /bullet +/paragraph /germandbls /registered /copyright /trademark /acute +/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef +/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown +/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef +/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde +/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright +/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis +/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl +/periodcentered /quotesinglbase /quotedblbase /perthousand +/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute +/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve +/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron +/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +] def +/ReEncode { + dup + length + dict begin + { + 1 index /FID ne + {def} + {pop pop} ifelse + } forall + 0 eq {/Encoding DiacriticEncoding def} if + currentdict + end + } bind def +FMPColor + + { + /BEGINBITMAPCOLOR { + BITMAPCOLOR} def + /BEGINBITMAPCOLORc { + BITMAPCOLORc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUECOLOR } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUECOLORc } def + /BEGINBITMAPCMYK { + BITMAPCMYK } def + /BEGINBITMAPCMYKc { + BITMAPCMYKc } def + } + + { + /BEGINBITMAPCOLOR { + BITMAPGRAY} def + /BEGINBITMAPCOLORc { + BITMAPGRAYc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUEGRAY } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUEGRAYc } def + /BEGINBITMAPCMYK { + BITMAPCMYKGRAY } def + /BEGINBITMAPCMYKc { + BITMAPCMYKGRAYc } def + } +ifelse +/K { + FMPrintAllColorsAsBlack { + dup 1 eq 2 index 1 eq and 3 index 1 eq and not + {7 {pop} repeat 0 0 0 1 0 0 0} if + } if + FrameCurColors astore + pop combineColor +} bind def +/graymode true def +fMLevel1 { + /fmGetFlip { + fMatrix2 exch get mul 0 lt { -1 } { 1 } ifelse + } FmBD +} if +/setPatternMode { + fMLevel1 { + 2 index patScreenDict exch known { + pop pop + patScreenDict exch get aload pop + freq + mul + 5 2 roll + fMatrix2 currentmatrix 1 get 0 ne { + 3 -1 roll 90 add 3 1 roll + sflipx 1 fmGetFlip sflipy 2 fmGetFlip neg mul + } { + sflipx 0 fmGetFlip sflipy 3 fmGetFlip mul + } ifelse + 0 lt {exch pop} {pop} ifelse + fMNegative { + {neg} fmConcatProcs + } if + bind + + + + systemdict /setscreen get exec + /FrameCurGray exch def + } { + /bwidth exch def + /bpside exch def + /bstring exch def + /onbits 0 def /offbits 0 def + freq sangle landscape {90 add} if + {/ypoint exch def + /xpoint exch def + /xindex xpoint 1 add 2 div bpside mul cvi def + /yindex ypoint 1 add 2 div bpside mul cvi def + bstring yindex bwidth mul xindex 8 idiv add get + 1 7 xindex 8 mod sub bitshift and 0 ne fMNegative {not} if + {/onbits onbits 1 add def 1} + {/offbits offbits 1 add def 0} + ifelse + } + setscreen + offbits offbits onbits add div fMNegative {1.0 exch sub} if + /FrameCurGray exch def + } ifelse + } { + pop pop + dup patCache exch known { + patCache exch get + } { + dup + patDict /bstring 3 -1 roll put + patDict + 9 PatFreq screenIndex get div dup matrix scale + makepattern + dup + patCache 4 -1 roll 3 -1 roll put + } ifelse + /FrameCurGray 0 def + /FrameCurPat exch def + } ifelse + /graymode false def + combineColor +} bind def +/setGrayScaleMode { + graymode not { + /graymode true def + fMLevel1 { + setCurrentScreen + } if + } if + /FrameCurGray exch def + combineColor +} bind def +/normalize { + transform round exch round exch itransform + } bind def +/dnormalize { + dtransform round exch round exch idtransform + } bind def +/lnormalize { + 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop + } bind def +/H { + lnormalize setlinewidth + } bind def +/Z { + setlinecap + } bind def + +/PFill { + graymode fMLevel1 or not { + gsave 1 setgray eofill grestore + } if +} bind def +/PStroke { + graymode fMLevel1 or not { + gsave 1 setgray stroke grestore + } if + stroke +} bind def +/X { + fillvals exch get + dup type /stringtype eq + {8 1 setPatternMode} + {setGrayScaleMode} + ifelse + } bind def +/V { + PFill gsave eofill grestore + } bind def +/Vclip { + clip + } bind def +/Vstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/N { + PStroke + } bind def +/Nclip { + strokepath clip newpath + } bind def +/Nstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/M {newpath moveto} bind def +/E {lineto} bind def +/D {curveto} bind def +/O {closepath} bind def +/L { + /n exch def + newpath + normalize + moveto + 2 1 n {pop normalize lineto} for + } bind def +/Y { + L + closepath + } bind def +/R { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + x1 y1 + x2 y1 + x2 y2 + x1 y2 + 4 Y + } bind def +/rarc + {rad + arcto + } bind def +/RR { + /rad exch def + normalize + /y2 exch def + /x2 exch def + normalize + /y1 exch def + /x1 exch def + mark + newpath + { + x1 y1 rad add moveto + x1 y2 x2 y2 rarc + x2 y2 x2 y1 rarc + x2 y1 x1 y1 rarc + x1 y1 x1 y2 rarc + closepath + } stopped {x1 y1 x2 y2 R} if + cleartomark + } bind def +/RRR { + /rad exch def + normalize /y4 exch def /x4 exch def + normalize /y3 exch def /x3 exch def + normalize /y2 exch def /x2 exch def + normalize /y1 exch def /x1 exch def + newpath + normalize moveto + mark + { + x2 y2 x3 y3 rarc + x3 y3 x4 y4 rarc + x4 y4 x1 y1 rarc + x1 y1 x2 y2 rarc + closepath + } stopped + {x1 y1 x2 y2 x3 y3 x4 y4 newpath moveto lineto lineto lineto closepath} if + cleartomark + } bind def +/C { + grestore + gsave + R + clip + setCurrentScreen +} bind def +/CP { + grestore + gsave + Y + clip + setCurrentScreen +} bind def +/F { + FMfonts exch get + FMpointsize scalefont + setfont + } bind def +/Q { + /FMpointsize exch def + F + } bind def +/T { + moveto show + } bind def +/RF { + rotate + 0 ne {-1 1 scale} if + } bind def +/TF { + gsave + moveto + RF + show + grestore + } bind def +/P { + moveto + 0 32 3 2 roll widthshow + } bind def +/PF { + gsave + moveto + RF + 0 32 3 2 roll widthshow + grestore + } bind def +/S { + moveto + 0 exch ashow + } bind def +/SF { + gsave + moveto + RF + 0 exch ashow + grestore + } bind def +/B { + moveto + 0 32 4 2 roll 0 exch awidthshow + } bind def +/BF { + gsave + moveto + RF + 0 32 4 2 roll 0 exch awidthshow + grestore + } bind def +/G { + gsave + newpath + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill fill + grestore + } bind def +/Gstrk { + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/Gclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GG { + gsave + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill + fill + grestore + } bind def +/GGclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GGstrk { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/A { + gsave + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/Aclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/Astrk { + Gstrk +} bind def +/AA { + gsave + savematrix + newpath + + 3 index 2 div add exch 4 index 2 div sub exch + + normalize 3 index 2 div sub exch 4 index 2 div add exch + translate + rotate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/AAclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/AAstrk { + GGstrk +} bind def +/BEGINPRINTCODE { + /FMdicttop countdictstack 1 add def + /FMoptop count 7 sub def + /FMsaveobject save def + userdict begin + /showpage {} def + FMNORMALIZEGRAPHICS + 3 index neg 3 index neg translate + } bind def +/ENDPRINTCODE { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMsaveobject restore + } bind def +/gn { + 0 + { 46 mul + cf read pop + 32 sub + dup 46 lt {exit} if + 46 sub add + } loop + add + } bind def +/cfs { + /str sl string def + 0 1 sl 1 sub {str exch val put} for + str def + } bind def +/ic [ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 + {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx} + {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx} + {19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} + {13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh} + {4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh} + {13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl} + {7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl} + {0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl} + {10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl} + ] def +/ms { + /sl exch def + /val 255 def + /ws cfs + /im cfs + /val 0 def + /bs cfs + /cs cfs + } bind def +400 ms +/ip { + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip { + + + bis ris copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + ris gis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + gis bis copy pop + dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip4 { + + + kis cis copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + cis mis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + mis yis copy pop + dup dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + yis kis copy pop + 3 mul is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/wh { + /len exch def + /pos exch def + ws 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/bl { + /len exch def + /pos exch def + bs 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/s1 1 string def +/fl { + /len exch def + /pos exch def + /val cf s1 readhexstring pop 0 get def + pos 1 pos len add 1 sub {im exch val put} for + pos len + } bind def +/hx { + 3 copy getinterval + cf exch readhexstring pop pop + } bind def +/wbytes { + dup dup + 8 gt { pop 8 idiv mul } + { 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse } ifelse + } bind def +/BEGINBITMAPBWc { + 1 {} COMMONBITMAPc + } bind def +/BEGINBITMAPGRAYc { + 8 {} COMMONBITMAPc + } bind def +/BEGINBITMAP2BITc { + 2 {} COMMONBITMAPc + } bind def +/COMMONBITMAPc { + + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + cvtProc + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} image + bitmapsave restore + grestore + } bind def +/BEGINBITMAPBW { + 1 {} COMMONBITMAP + } bind def +/BEGINBITMAPGRAY { + 8 {} COMMONBITMAP + } bind def +/BEGINBITMAP2BIT { + 2 {} COMMONBITMAP + } bind def +/COMMONBITMAP { + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + cvtProc + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} image + bitmapsave restore + grestore + } bind def +/ngrayt 256 array def +/nredt 256 array def +/nbluet 256 array def +/ngreent 256 array def +fMLevel1 { +/colorsetup { + currentcolortransfer + /gryt exch def + /blut exch def + /grnt exch def + /redt exch def + 0 1 255 { + /indx exch def + /cynu 1 red indx get 255 div sub def + /magu 1 green indx get 255 div sub def + /yelu 1 blue indx get 255 div sub def + /kk cynu magu min yelu min def + /u kk currentundercolorremoval exec def +% /u 0 def + nredt indx 1 0 cynu u sub max sub redt exec put + ngreent indx 1 0 magu u sub max sub grnt exec put + nbluet indx 1 0 yelu u sub max sub blut exec put + ngrayt indx 1 kk currentblackgeneration exec sub gryt exec put + } for + {255 mul cvi nredt exch get} + {255 mul cvi ngreent exch get} + {255 mul cvi nbluet exch get} + {255 mul cvi ngrayt exch get} + setcolortransfer + {pop 0} setundercolorremoval + {} setblackgeneration + } bind def +} +{ +/colorSetup2 { + [ /Indexed /DeviceRGB 255 + {dup red exch get 255 div + exch dup green exch get 255 div + exch blue exch get 255 div} + ] setcolorspace +} bind def +} ifelse +/fakecolorsetup { + /tran 256 string def + 0 1 255 {/indx exch def + tran indx + red indx get 77 mul + green indx get 151 mul + blue indx get 28 mul + add add 256 idiv put} for + currenttransfer + {255 mul cvi tran exch get 255.0 div} + exch fmConcatProcs settransfer +} bind def +/BITMAPCOLOR { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + fMLevel1 { + colorsetup + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} {is} {is} true 3 colorimage + } { + colorSetup2 + /is width depth wbytes string def + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {cf is readhexstring pop} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPCOLORc { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + fMLevel1 { + colorsetup + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} {is} {is} true 3 colorimage + } { + colorSetup2 + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {ip} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLORc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris} {gis} {bis} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYKc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip4 pop cis} {mis} {yis} {kis} true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLOR { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf gis readhexstring pop } + { cf bis readhexstring pop } + true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYK { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /mis width string def + /yis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf mis readhexstring pop } + { cf yis readhexstring pop } + { cf kis readhexstring pop } + true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUEGRAYc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris gis bis width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAYc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop cis mis yis kis width cgray} image + bitmapsave restore + grestore + } bind def +/cgray { + /ww exch def + /k exch def + /y exch def + /m exch def + /c exch def + 0 1 ww 1 sub { /i exch def c i get m i get y i get k i get CMYKtoRGB + .144 mul 3 1 roll .587 mul 3 1 roll .299 mul add add + c i 3 -1 roll floor cvi put } for + c + } bind def +/gray { + /ww exch def + /b exch def + /g exch def + /r exch def + 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul + b i get .114 mul add add r i 3 -1 roll floor cvi put } for + r + } bind def +/BITMAPTRUEGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf gis readhexstring pop + cf bis readhexstring pop width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /yis width string def + /mis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf mis readhexstring pop + cf yis readhexstring pop + cf kis readhexstring pop width cgray} image + bitmapsave restore + grestore + } bind def +/BITMAPGRAY { + 8 {fakecolorsetup} COMMONBITMAP + } bind def +/BITMAPGRAYc { + 8 {fakecolorsetup} COMMONBITMAPc + } bind def +/ENDBITMAP { + } bind def +end + /ALDmatrix matrix def ALDmatrix currentmatrix pop +/StartALD { + /ALDsave save def + savematrix + ALDmatrix setmatrix + } bind def +/InALD { + restorematrix + } bind def +/DoneALD { + ALDsave restore + } bind def +/I { setdash } bind def +/J { [] 0 setdash } bind def +%%EndProlog +%%BeginSetup +(5.0) FMVERSION +1 1 0 0 612 792 0 1 11 FMDOCUMENT +0 0 /Helvetica FMFONTDEFINE +1 0 /Times-BoldItalic FMFONTDEFINE +2 0 /Helvetica-Bold FMFONTDEFINE +3 0 /Times-Roman FMFONTDEFINE +4 0 /Times-Bold FMFONTDEFINE +32 FMFILLS +0 0 FMFILL +1 0.1 FMFILL +2 0.3 FMFILL +3 0.5 FMFILL +4 0.7 FMFILL +5 0.9 FMFILL +6 0.97 FMFILL +7 1 FMFILL +8 <0f1e3c78f0e1c387> FMFILL +9 <0f87c3e1f0783c1e> FMFILL +10 FMFILL +11 FMFILL +12 <8142241818244281> FMFILL +13 <03060c183060c081> FMFILL +14 <8040201008040201> FMFILL +16 1 FMFILL +17 0.9 FMFILL +18 0.7 FMFILL +19 0.5 FMFILL +20 0.3 FMFILL +21 0.1 FMFILL +22 0.03 FMFILL +23 0 FMFILL +24 FMFILL +25 FMFILL +26 <3333333333333333> FMFILL +27 <0000ffff0000ffff> FMFILL +28 <7ebddbe7e7dbbd7e> FMFILL +29 FMFILL +30 <7fbfdfeff7fbfdfe> FMFILL +%%EndSetup +%%Page: "i" 1 +%%BeginPaperSize: Letter +%%EndPaperSize +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(i) 555.78 57 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 720 558 720 2 L +0.5 H +2 Z +N +72 72 558 72 2 L +N +72 504 558 504 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 32 Q +(CDEV C Binding Guide) 180 662.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 12 Q +(Chip W) 180 624 T +(atson, Jie Chen, Danjin W) 218.86 624 T +(u, W) 357.22 624 T +(alt Ak) 381.41 624 T +(ers) 411.18 624 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 180 596 T +(ersion 1.4 October 24, 1996) 187.04 596 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(TJNAF - Thomas Jeff) 180 568 T +(erson National Acceler) 293.66 568 T +(ator F) 414.25 568 T +(acility) 445 568 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "i" 1 +%%Page: "ii" 2 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(ii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(TRADEMARKS:) 54 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(UNIX is a registered tr) 180 569.33 T +(ademar) 278.26 569.33 T +(k of A) 312.31 569.33 T +(T&T in the USA and other countr) 336.68 569.33 T +(ies) 481.9 569.33 T +(.) 494.53 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(VxW) 180 545.33 T +(or) 200.81 545.33 T +(ks is a register tr) 209.85 545.33 T +(ademar) 283.1 545.33 T +(k of Wind Riv) 317.15 545.33 T +(er Systems) 375.8 545.33 T +(.) 425.66 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The X Windo) 180 521.33 T +(w System is a tr) 237.65 521.33 T +(ademar) 308.12 521.33 T +(k of Massachusetts Institute of T) 342.17 521.33 T +(echnology) 484.37 521.33 T +(.) 528.95 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(OSF/Motif and Motif are tr) 180 497.33 T +(ademar) 294.94 497.33 T +(ks of Open Softw) 328.99 497.33 T +(are F) 404.99 497.33 T +(oundation, Inc.) 428.03 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ultr) 180 473.33 T +(ix and DEC are registered tr) 195.7 473.33 T +(ademar) 319.53 473.33 T +(ks of Digital Equipment Cor) 353.58 473.33 T +(por) 475.03 473.33 T +(ation.) 489.38 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(HPUX is a registered tr) 180 449.33 T +(ademar) 282.15 449.33 T +(k of He) 316.2 449.33 T +(wlett P) 347.68 449.33 T +(ac) 377.29 449.33 T +(kard.) 387.65 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(SURA/CEB) 54 344.33 T +(AF:) 105.92 344.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.44 (The Southeaster) 180 344.33 P +4.44 (n Univ) 258.62 344.33 P +4.44 (ersities Research Association \050SURA\051 oper) 291.15 344.33 P +4.44 (ates the) 499.98 344.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.01 (Contin) 180 332.33 P +2.01 (uous Electron Beam Acceler) 208.8 332.33 P +2.01 (ator F) 340.89 332.33 P +2.01 (acility \050CEBAF\051 f) 368.52 332.33 P +2.01 (or the United States) 445.59 332.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Depar) 180 320.33 T +(tment of Energy under contr) 207.63 320.33 T +(act DE-A) 331.48 320.33 T +(C05-84ER40150.) 371.19 320.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DISCLAIMER:) 54 218.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.49 (This repor) 180 218.33 P +0.49 (t w) 225.9 218.33 P +0.49 (as prepared as an account of w) 239.02 218.33 P +0.49 (or) 381.4 218.33 P +0.49 (k sponsored b) 390.44 218.33 P +0.49 (y the United States) 454.03 218.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.18 (go) 180 206.33 P +2.18 (v) 190.97 206.33 P +2.18 (er) 195.72 206.33 P +2.18 (nment. Neither the United States nor the United States Depar) 204.86 206.33 P +2.18 (tment of) 501.68 206.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.04 (Energy) 180 194.33 P +1.04 (, nor an) 210.68 194.33 P +1.04 (y of their emplo) 246.52 194.33 P +1.04 (y) 317.69 194.33 P +1.04 (ees) 322.49 194.33 P +1.04 (, mak) 338.46 194.33 P +1.04 (es an) 363.75 194.33 P +1.04 (y w) 389.1 194.33 P +1.04 (arr) 404.99 194.33 P +1.04 (anty) 417.11 194.33 P +1.04 (, e) 435.01 194.33 P +1.04 (xpress or implied, or) 446.86 194.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.83 (assumes an) 180 182.33 P +1.83 (y legal liability or responsibility f) 235.59 182.33 P +1.83 (or the accur) 383.89 182.33 P +1.83 (acy) 440.24 182.33 P +1.83 (, completeness) 454.8 182.33 P +1.83 (, or) 523.72 182.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.68 (usefulness of an) 180 170.33 P +3.68 (y inf) 260.02 170.33 P +3.68 (or) 281.74 170.33 P +3.68 (mation, appar) 290.88 170.33 P +3.68 (atus) 355.59 170.33 P +3.68 (, product or process disclosed, or) 374.34 170.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.46 (represents that its use w) 180 158.33 P +2.46 (ould not infr) 298.11 158.33 P +2.46 (inge pr) 355.42 158.33 P +2.46 (iv) 388.59 158.33 P +2.46 (ately o) 395.56 158.33 P +2.46 (wned r) 427.33 158.33 P +2.46 (ights) 459.95 158.33 P +2.46 (. Ref) 480.92 158.33 P +2.46 (erence) 509.43 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.6 (herein to an) 180 146.33 P +1.6 (y speci\336c commercial product, process) 235.85 146.33 P +1.6 (, or ser) 413.79 146.33 P +1.6 (vice b) 448.4 146.33 P +1.6 (y tr) 475.92 146.33 P +1.6 (ade name) 491.3 146.33 P +1.6 (,) 537.22 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (mar) 180 134.33 P +2.12 (k, man) 197.37 134.33 P +2.12 (uf) 229.4 134.33 P +2.12 (acturer) 237.44 134.33 P +2.12 (, or otherwise) 268.06 134.33 P +2.12 (, does not necessar) 332.17 134.33 P +2.12 (ily constitute or imply its) 425.94 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (endorsement, recommendation, or f) 180 122.33 P +1.08 (a) 341.33 122.33 P +1.08 (v) 346.69 122.33 P +1.08 (or) 351.44 122.33 P +1.08 (ing b) 360.48 122.33 P +1.08 (y the United States go) 383.03 122.33 P +1.08 (v) 485.57 122.33 P +1.08 (er) 490.32 122.33 P +1.08 (nment or) 499.46 122.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (an) 180 110.33 P +0.83 (y agency thereof) 190.97 110.33 P +0.83 (. The vie) 266.26 110.33 P +0.83 (w and opinions of the authors e) 309.67 110.33 P +0.83 (xpressed herein do) 453.3 110.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.94 (not necessar) 180 98.33 P +1.94 (ily state or re\337ect those of the United States go) 239.34 98.33 P +1.94 (v) 464.01 98.33 P +1.94 (er) 468.76 98.33 P +1.94 (nment or an) 477.9 98.33 P +1.94 (y) 535 98.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(agency thereof) 180 86.33 T +(.) 245.85 86.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DOCUMENT D) 54 668.33 T +(A) 121.37 668.33 T +(TE:) 127.69 668.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(T) 180 668.33 T +(ab) 184.91 668.33 T +(le of contents gener) 195.83 668.33 T +(ated: October 24, 1996 3:12 pm) 283.56 668.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "ii" 2 +%%Page: "iii" 3 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +( T) 485.72 739 T +(ab) 492.64 739 T +(le of Contents) 502.47 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(iii) 551.34 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(T) 180 710.67 T +(ab) 187.43 710.67 T +(le of Contents) 203.63 710.67 T +0 0 0 1 0 0 0 K +3 12 Q +(Design Choices: 1) 180 683 T +(Comparison with C++ binding: 1) 180 669 T +(Simple message passing routines: 2) 180 655 T +(Binding a device and message 3) 180 641 T +(Monitoring and Asynchronous I/O 3) 180 627 T +(Error Reporting and Handling 5) 180 613 T +(Name Services 5) 180 599 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iii" 3 +%%Page: "iv" 4 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +( T) 54 739 T +(ab) 60.92 739 T +(le of Contents) 70.75 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(iv) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iv" 4 +%%Page: "1" 5 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 10 Q +0 X +0 0 0 1 0 0 0 K +(cdev C Binding) 72 36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1 of 5) 294.33 36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 18 Q +(cde) 247.12 708 T +(v C Binding) 272.84 708 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 12 Q +(Updated: 10/24/96) 261.17 676 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(This w) 72 644 T +(orking document describes a C binding to the cde) 104.88 644 T +(v control system interf) 342.55 644 T +(ace \050see the cde) 450.76 644 T +(v) 526.08 644 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Design Document, and the cde) 72 630 T +(v User\325) 219.34 630 T +(s Guide\051.) 254.33 630 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 14 Q +(Design Choices:) 72 594.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 12 Q +(1.) 72 574 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(All C routine names be) 90 574 T +(gin with \322cde) 201.14 574 T +(v\323 \050common de) 265.5 574 T +(vice\051.) 339.85 574 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 72 560 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Most C routines return completion status; 0==success \050allo) 90 560 T +(ws enumerated errors\051. A fe) 372.89 560 T +(w) 506.87 560 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(return inte) 90 546 T +(ger v) 139.48 546 T +(alues \050pre\336x) 163.5 546 T +(ed in this document with \322int\323\051.) 222.97 546 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 72 532 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.44 (All data passed through the interf) 90 532 P +-0.44 (ace will be in the form of inte) 247.98 532 P +-0.44 (gers, strings or a self describing) 387.01 532 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(structure. Library calls will be pro) 90 518 T +(vided to manipulate this structure.) 253.79 518 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 14 Q +(Comparison with C++ binding:) 72 482.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 12 Q +(1.) 72 462 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 462 T +(vData, cde) 106.36 462 T +(vRequestObject, and cde) 157.37 462 T +(vGroup objects will be accessed through object id\325) 276.71 462 T +(s.) 519.67 462 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 72 448 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 448 T +(vDe) 106.36 448 T +(vice will only be referenced by de) 126.05 448 T +(vice name.) 289.03 448 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 72 434 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Only a single, def) 90 434 T +(ault, cde) 175.2 434 T +(vSystem will be supported.) 215.56 434 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 72 420 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Since no function o) 90 420 T +(v) 183.48 420 T +(erloading is a) 189.3 420 T +(v) 253.72 420 T +(ailable, I/O operations on a cde) 259.42 420 T +(vData object will ha) 409.08 420 T +(v) 505.82 420 T +(e to) 511.64 420 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pass a datatype ar) 90 406 T +(gument, similar to EPICS channel access.) 174.76 406 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 72 392 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Routines which return strings will malloc the string, and the caller must free it.) 90 392 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 72 378 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.09 (Function names are generally constructed from the class name follo) 90 378 P +-0.09 (wed by the method name,) 413.81 378 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(e.g. cde) 90 364 T +(vGroupStart.) 126.68 364 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 72 350 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Creating objects will be done by routines lik) 90 350 T +(e cde) 302.87 350 T +(vGroupAllocate, which will essentially) 327.55 350 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(return a pointer to the created object.) 90 336 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8.) 72 322 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 322 T +(vSystem methods will drop \322System\323 from the name, and the notion of \322system\323 will be) 106.36 322 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(in) 90 308 T +(visible.) 98.86 308 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9.) 72 294 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 294 T +(vDe) 106.36 294 T +(vice methods will drop \322De) 126.05 294 T +(vice\323. cde) 258.4 294 T +(vRequestObject methods will use the shorter) 306.07 294 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322cde) 90 280 T +(vRequest\323.) 111.68 280 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "1" 5 +%%Page: "2" 6 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 10 Q +0 X +0 0 0 1 0 0 0 K +(C Binding User\325s Guide) 72 36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2 of 5) 294.33 36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 18 Q +(C Binding User\325) 214.57 708 T +(s Guide) 338.91 708 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 14 Q +(Simple message passing r) 72 666.67 T +(outines:) 223.03 666.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 12 Q +-0.29 (De) 72 646 P +-0.29 (vices are addressed by name, and operations are performed by sending a message string and an) 85.69 646 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.27 (additional optional data object identi\336er) 72 632 P +-0.27 (. This data object is self describing in the sense that it con-) 262.25 632 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(tains indicators of the data type \050int, \337oat, etc.\051 and size \050array lengths\051. Data returned from the) 72 618 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(control system will also be through a data object.) 72 604 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(status = cde) 90 586 T +(vSend \050char* de) 149.99 586 T +(vName, char* message,) 232.48 586 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 186 568 T +(v_data_t out, cde) 203.15 568 T +(v_data_t in\051;) 290.63 568 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +-0.15 (The data objects act as small databases able to hold multiple tagged data items. Items are inserted) 72 550 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.16 (into or e) 72 536 P +-0.16 (xtracted from the database via access routines. These access routines are also responsible) 111.5 536 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.18 (for an) 72 522 P +-0.18 (y necessary data type con) 99.96 522 P +-0.18 (v) 221.37 522 P +-0.18 (ersions. T) 227.19 522 P +-0.18 (ags are passed to the cde) 273.38 522 P +-0.18 (vData routines as inte) 390.46 522 P +-0.18 (gers, and) 494.05 522 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(are look) 72 508 T +(ed up in the tag database by specifying an ascii tag name. The most common tags are) 110.87 508 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322v) 72 494 T +(alue\323, \322timeStamp\323, \322status\323, and \322se) 83.03 494 T +(v) 262.36 494 T +(erity\323.) 268.18 494 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data object manipulation routines:) 72 476 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(cde) 90 458 T +(vDataAllocate \050cde) 107.15 458 T +(v_data_t* id\051;) 203.94 458 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 440 T +(vDataFr) 107.15 440 T +(ee \050cde) 150.25 440 T +(v_data_t id\051;) 185.05 440 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 422 T +(vDataT) 107.15 422 T +(agC2I \050char* tag, int *tagid\051;) 144.71 422 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 404 T +(vDataT) 107.15 404 T +(agI2C \050int tagid, char** tag\051;) 144.71 404 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(/* caller must fr) 294.36 404 T +(ee string */) 375.79 404 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 386 T +(vDataInsertT) 107.15 386 T +(ag \050int tag, char* ctag\051;) 175.37 386 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 368 T +(vDataInsert \050cde) 107.15 368 T +(v_data_t id, int tagid, int type, v) 192.61 368 T +(oid * data\051;) 356.17 368 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int cde) 90 350 T +(vDataInsertArray\050cde) 124.15 350 T +(v_data_t id, int tagid, int type, v) 237.94 350 T +(oid *data, size_t len, size_t) 401.5 350 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ndim\051;) 90 336 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 318 T +(vDataGet \050cde) 107.15 318 T +(v_data_t id, int tagid, int type, v) 180.61 318 T +(oid * data\051;) 344.17 318 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 300 T +(vDataFind \050cde) 107.15 300 T +(v_data_t id, int tagid, v) 185.96 300 T +(oid ** data\051;) 304.52 300 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int cde) 90 282 T +(vDataGetT) 124.15 282 T +(ype \050cde) 180.59 282 T +(v_data_t id, int tagid\051;) 222.73 282 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int cde) 90 264 T +(vDataGetDim \050cde) 124.15 264 T +(v_data_t id, int tagid\051;) 219.61 264 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int cde) 90 246 T +(vDataGetElems \050cde) 124.15 246 T +(v_data_t id, int tagid\051;) 228.95 246 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 228 T +(vDataGetBounds \050cde) 107.15 228 T +(v_data_t id, int tagid, int *bounds, int bsize\051;) 219.3 228 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 210 T +(vDataSetBounds \050cde) 107.15 210 T +(v_data_t id, int tagid, int *bounds, int bsize\051;) 216.64 210 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(v) 90 192 T +(oid cde) 95.88 192 T +(vDataRemo) 132.04 192 T +(v) 192.56 192 T +(eAll\050cde) 198.44 192 T +(v_data_t id\051;) 240.25 192 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 174 T +(vDataRemo) 107.15 174 T +(v) 167.68 174 T +(e \050cde) 173.56 174 T +(v_data_t id, int tagid\051;) 203.03 174 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 156 T +(vDataChangeT) 107.15 156 T +(ag \050cde) 184.04 156 T +(v_data_t id, int tagid, int newtagid\051;) 220.19 156 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 138 T +(vDataAsciiDump \050cde) 107.15 138 T +(v_data_t id, FILE *fp\051;) 219.29 138 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(v) 90 120 T +(oid cde) 95.88 120 T +(vDataCopy\050cde) 132.04 120 T +(v_data_t fr) 211.18 120 T +(om, cde) 267.95 120 T +(v_data_t *to\051;) 307.09 120 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(F) 72 102 T +(or e) 78.49 102 T +(xample, to read the current from a magnet named NLQ1:) 96.64 102 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 84 T +(v_data_t result;) 106.36 84 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "2" 6 +%%Page: "3" 7 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 10 Q +0 X +0 0 0 1 0 0 0 K +(C Binding User\325s Guide) 72 36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3 of 5) 294.33 36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 12 Q +(\337oat current;) 90 712 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int status, v) 90 694 T +(altag;) 144.71 694 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(status = cde) 90 676 T +(vDataAllocate \050&result\051;) 146.46 676 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(status = cde) 90 658 T +(vDataT) 146.46 658 T +(agC2I \050\322v) 181.49 658 T +(alue\323,&v) 228.84 658 T +(altag\051;) 272.2 658 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(status = cde) 90 640 T +(vSend\050\322NLQ1\323,) 146.46 640 T +(\323read current\323,NULL,result\051;) 223.93 640 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(status = cde) 90 622 T +(vDataGet\050result, v) 146.46 622 T +(altag, CDEV_FLO) 234.8 622 T +(A) 325.04 622 T +(T) 332.38 622 T +(, current\051;) 338.82 622 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The \336rst call to a de) 72 604 T +(vice automatically connects to the requested service, initializing an) 167.35 604 T +(y underly-) 488.78 604 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ing packages as needed. These routines are synchronous \050operation completes before return\051;) 72 590 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(asynchronous routines are discussed belo) 72 576 T +(w) 269.66 576 T +(.) 277.55 576 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The message \050second\051 ar) 72 558 T +(gument selects what operation and attrib) 190.74 558 T +(ute to access. Man) 384.8 558 T +(y messages) 473.27 558 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(are by con) 72 544 T +(v) 121.5 544 T +(ention of the form \322v) 127.32 544 T +(erb attrib) 228.46 544 T +(ute\323, and typical v) 271.87 544 T +(erbs include get, set, monitorOn, and) 359.68 544 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(monitorOf) 72 530 T +(f.) 122.36 530 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 14 Q +(Binding a de) 72 494.67 T +(vice and message) 147.26 494.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 12 Q +-0.08 (In order to a) 72 474 P +-0.08 (v) 130.51 474 P +-0.08 (oid the o) 136.27 474 P +-0.08 (v) 177.94 474 P +-0.08 (erhead of parsing the de) 183.76 474 P +-0.08 (vice name and message on each call, it is possible) 298.46 474 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(to get a handle which binds the de) 72 460 T +(vice and message into a request.) 235.34 460 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(status = cde) 90 442 T +(vRequestAllocate\050char* de) 149.99 442 T +(vice, char*message, CDEVREQ) 287.45 442 T +(UESTID* r) 450.64 442 T +(eqid\051;) 509.42 442 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Operations may be performed on this request object without specifying de) 72 424 T +(vice and message.) 427.64 424 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(status = cde) 90 406 T +(vRequestSend\050r) 149.99 406 T +(eqid, out, r) 231.77 406 T +(esult\051;) 287.56 406 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Request objects maintain a connection to a serv) 72 388 T +(er) 300.12 388 T +(, and the state of this connection may be) 308.96 388 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(obtained:) 72 374 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(state = cde) 90 356 T +(vRequestState \050r) 143.98 356 T +(eqid\051;) 229.4 356 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(The current access rights \050read, write, none\051 for this request object may be obtained:) 72 338 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(access = cde) 90 320 T +(vRequestAccess \050r) 151.31 320 T +(eqid\051;) 244.73 320 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Gi) 72 302 T +(v) 83.7 302 T +(en the request object, it is also possible to e) 89.52 302 T +(xtract the de) 297.32 302 T +(vice name and message:) 356.34 302 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(cde) 90 284 T +(vRequestDe) 107.15 284 T +(vice \050r) 168.29 284 T +(eqid, char** name\051; /* caller must fr) 200.39 284 T +(ee string */) 387.14 284 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 266 T +(vRequestMessage \050r) 107.15 266 T +(eqid, char** msg\051;) 209.9 266 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 14 Q +(Monitoring and Asynchr) 72 230.67 T +(onous I/O) 220.32 230.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 12 Q +(A message sent to a de) 72 210 T +(vice may result in an asynchronous reply) 181.34 210 T +(, or more than one reply) 377.2 210 T +(. In addi-) 491.72 210 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.35 (tion, abnormal conditions may occur in the de) 72 196 P +-0.35 (vice which are of interest to the application. Each of) 289.89 196 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(these results in a message back to the client which is asynchronous with respect to program e) 72 182 T +(x) 518.41 182 T +(e-) 524.23 182 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cution. Se) 72 168 T +(v) 119.7 168 T +(eral calls are pro) 125.52 168 T +(vided to deal with asynchronous data.) 204.97 168 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Asynchr) 72 148 T +(onous Messages.) 115.12 148 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(An asynchronous v) 202.12 148 T +(ersion of the message send call will send the mes-) 294.59 148 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sage, b) 72 134 T +(ut not w) 105.08 134 T +(ait for the reply) 144.3 134 T +(. T) 217.84 134 T +(w) 230.21 134 T +(o async forms are supported: one returning data to a caller\325) 238.75 134 T +(s) 521.35 134 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.16 (data object, and the other returning data to a callback function. The reply ar) 72 120 P +-0.16 (gument is replaced by) 431.98 120 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(an additional structure which speci\336ed a user callback function.) 72 106 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(status = cde) 90 88 T +(vSendNoBlock\050char* de) 149.99 88 T +(vice, char* message,) 273.48 88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "3" 7 +%%Page: "4" 8 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 10 Q +0 X +0 0 0 1 0 0 0 K +(C Binding User\325s Guide) 72 36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4 of 5) 294.33 36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 12 Q +(cde) 225 712 T +(v_data_t out, cde) 242.15 712 T +(v_data_t r) 329.63 712 T +(esult\051;) 382.4 712 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(status = cde) 90 694 T +(vSendCallback\050char* de) 149.99 694 T +(vice, char* message,) 275.48 694 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 228 676 T +(v_data_t out, CDEVCALLB) 245.15 676 T +(A) 390.46 676 T +(CK* callback\051;) 398.46 676 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Similarly for request objects:) 72 658 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(status = cde) 90 640 T +(vRequestSendNoBlock\050cde) 149.99 640 T +(v_data_t out, cde) 287.81 640 T +(v_data_t r) 375.29 640 T +(esult\051;) 428.06 640 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(status = cde) 90 622 T +(vRequestSendCallback\050cde) 149.99 622 T +(v_data_t out, CDEVCALLB) 289.81 622 T +(A) 435.12 622 T +(CK* callback\051;) 443.12 622 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Monitoring:) 72 602 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Monitoring is started and stopped by tw) 137.66 602 T +(o using the message \322monitorOn xxx\323 and) 328.87 602 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322monitorOf) 72 588 T +(f xxx\323.) 127.69 588 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(status = cde) 90 570 T +(vSendCallback\050\322de) 146.46 570 T +(viceName\323, \322monitorOn attrib) 239.47 570 T +(uteName\323,NULL, callback\051;) 385.54 570 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Synchr) 72 550 T +(onization.) 108.46 550 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(In order to synchronize with asynchronous messages, both a poll and a pend) 161.8 550 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(call are a) 72 536 T +(v) 115.07 536 T +(ailable, as well as an e) 120.77 536 T +(xplicit \337ush. A pend with 0.0 seconds w) 227.89 536 T +(aits fore) 420.77 536 T +(v) 459.46 536 T +(er) 465.28 536 T +(.) 473.94 536 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(cde) 90 518 T +(vFlush \050\051;) 107.15 518 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 500 T +(vP) 107.15 500 T +(oll \050\051;) 120.24 500 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 482 T +(vP) 107.15 482 T +(end \050\337oat seconds\051;) 120.24 482 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(If seconds==0.0, w) 72 464 T +(ait fore) 164.06 464 T +(v) 198.08 464 T +(er) 203.9 464 T +(.) 212.57 464 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Gr) 72 444 T +(ouping) 86.45 444 T +(.) 121.62 444 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Grouping of operations will be similar to that speci\336ed for EZCA, with slight v) 127.62 444 T +(aria-) 507.97 444 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(tions. The grouping calls are useful for synchronizing with a set of asynchronous calls.) 72 430 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(cde) 90 412 T +(vGr) 107.15 412 T +(oupAllocate\050GR) 127.6 412 T +(OUPID* gr) 210.56 412 T +(oupid\051;) 269.34 412 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 394 T +(vGr) 107.15 394 T +(oupStart\050gr) 127.6 394 T +(oupid\051;) 188.04 394 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 376 T +(vGr) 107.15 376 T +(oupEnd\050gr) 127.6 376 T +(oupid\051;) 183.4 376 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 358 T +(vGr) 107.15 358 T +(oupP) 127.6 358 T +(oll\050gr) 154.03 358 T +(oupid\051;) 181.81 358 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 340 T +(vGr) 107.15 340 T +(oupP) 127.6 340 T +(end\050gr) 154.03 340 T +(oupid\051;) 187.81 340 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 322 T +(vGr) 107.15 322 T +(oupAllFinished \050gr) 127.6 322 T +(oupid\051;) 224.4 322 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 304 T +(vGr) 107.15 304 T +(oupStatus \050gr) 127.6 304 T +(oupid, int *status, int *nstatus\051; /* initially nstatus = len of status */) 197.05 304 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(File Descriptors.) 72 284 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(T) 159.65 284 T +(o inte) 166.02 284 T +(grate other asynchronous systems, such as X windo) 192.84 284 T +(ws, it is often neces-) 439.84 284 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sary to obtain \336le descriptors for select operations.) 72 270 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(status = cde) 90 252 T +(vGetFD\050int fd[], int * numFD\051;) 149.99 252 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Context.) 72 232 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Operations on a de) 118.66 232 T +(vice tak) 208.67 232 T +(e place within a conte) 246.2 232 T +(xt. The conte) 350.66 232 T +(xt is maintained by the) 413.47 232 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(de) 72 218 T +(vice as a cde) 83.03 218 T +(v_data_t structure. The follo) 143.7 218 T +(wing routines are used to get and set the conte) 280.04 218 T +(xt; set-) 501.49 218 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ting items within the conte) 72 204 T +(xt is done by the cde) 199.82 204 T +(vData* routines.) 298.51 204 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(cde) 90 186 T +(vGetContext\050char *de) 107.15 186 T +(vname, cde) 220.61 186 T +(v_data_t *id\051;) 277.75 186 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 168 T +(vSetContext\050char *de) 107.15 168 T +(vname, cde) 217.94 168 T +(v_data_t id\051;) 275.09 168 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pri) 72 148 T +(v) 87.88 148 T +(ate Data.) 93.76 148 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Each de) 142.74 148 T +(vice also maintains a pri) 180.76 148 T +(v) 297.11 148 T +(ate data pointer) 302.81 148 T +(, to be used by the application) 376.31 148 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(de) 72 134 T +(v) 83.03 134 T +(eloper for an) 88.85 134 T +(y purpose desired.) 149.98 134 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(cde) 90 116 T +(vGetPri) 107.15 116 T +(v) 147.68 116 T +(ate \050char *de) 153.56 116 T +(vname, v) 220.03 116 T +(oid **data\051;) 265.91 116 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 98 T +(vSetPri) 107.15 98 T +(v) 145.02 98 T +(ate \050char *de) 150.9 98 T +(vname, v) 217.37 98 T +(oid *data\051;) 263.24 98 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(These same four routines are a) 72 80 T +(v) 218.71 80 T +(ailable for request objects:) 224.41 80 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "4" 8 +%%Page: "5" 9 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 10 Q +0 X +0 0 0 1 0 0 0 K +(C Binding User\325s Guide) 72 36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5 of 5) 294.33 36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 12 Q +(cde) 90 712 T +(vRequestGetContext \050r) 107.15 712 T +(eqid, cde) 225.9 712 T +(v_data_t *id\051;) 271.06 712 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 694 T +(vRequestSetContext \050r) 107.15 694 T +(eqid, cde) 223.24 694 T +(v_data_t id\051;) 268.39 694 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 676 T +(vRequestGetPri) 107.15 676 T +(v) 189.01 676 T +(ate \050r) 194.89 676 T +(eqid, v) 222.32 676 T +(oid **data\051;) 256.21 676 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 658 T +(vRequestSetPri) 107.15 658 T +(v) 186.35 658 T +(ate \050r) 192.23 658 T +(eqid, v) 219.66 658 T +(oid *data\051;) 253.55 658 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 14 Q +(Err) 72 622.67 T +(or Reporting and Handling) 93.52 622.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 12 Q +(This group of routines is also modeled after EZCA \050assume identical functionality\051.) 72 602 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(T) 72 584 T +(urn automatic error reporting on and of) 78.79 584 T +(f:) 266.45 584 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(cde) 90 566 T +(vA) 107.15 566 T +(utoErr) 121.21 566 T +(orOn \050\051;) 156.32 566 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 548 T +(vA) 107.15 548 T +(utoErr) 121.21 548 T +(orOff \050\051;) 156.32 548 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Set the se) 72 530 T +(v) 117.7 530 T +(erity threshold at which errors should be reported:) 123.52 530 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(cde) 90 512 T +(vSetThr) 107.15 512 T +(eshold \050int new\051;) 148.93 512 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 494 T +(vReportErr) 107.15 494 T +(or \050int se) 167.58 494 T +(v) 212.72 494 T +(erity) 218.6 494 T +(, char *name,) 241.93 494 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEVREQ) 183 476 T +(UESTID r) 242.88 476 T +(equest, char* f) 295.67 476 T +(ormat, ...\051;) 370.36 476 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 458 T +(vGetErr) 107.15 458 T +(orString \050\051;) 150.25 458 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 90 440 T +(vSetErr) 107.15 440 T +(orHandler \050function\051;) 147.59 440 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +-0.15 (Note: F) 72 422 P +-0.15 (or simplicity of use, a v) 108.01 422 P +-0.15 (ery compact set of error codes is implemented in cde) 220.41 422 P +-0.15 (v) 472.39 422 P +-0.15 (. The follo) 477.61 422 P +-0.15 (w-) 527.34 422 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ing error codes are de\336ned in the header \336le cde) 72 408 T +(vErrCode.h.) 302.63 408 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV_SUCCESS) 72 390 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(= 0) 180 390 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Success) 252 390 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV_INV) 72 372 T +(ALIDOBJ) 130.37 372 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(= 1) 180.36 372 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(In) 252 372 T +(v) 261.52 372 T +(alid cde) 267.22 372 T +(v object used) 304.57 372 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV_INV) 72 354 T +(ALID) 130.37 354 T +(ARG) 158.54 354 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(= 2) 183.88 354 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(In) 252 354 T +(v) 261.52 354 T +(alid ar) 267.22 354 T +(gument passed to cde) 297.32 354 T +(v method) 400.01 354 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV_INV) 72 336 T +(ALIDSVC) 130.37 336 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(= 3) 182.36 336 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Wrong service during dynamic loading) 252 336 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV_NO) 72 318 T +(TCONNECTED) 127.51 318 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(= 4) 207.5 318 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Not connected to lo) 252 318 T +(w-le) 346.02 318 T +(v) 367.04 318 T +(el netw) 372.86 318 T +(ork service) 407.74 318 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV_IOF) 72 300 T +(AILED) 129.11 300 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(= 5) 180 300 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Lo) 252 300 T +(w-le) 265.03 300 T +(v) 286.06 300 T +(el netw) 291.88 300 T +(ork service IO f) 326.75 300 T +(ailed) 402.26 300 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV_CONFLICT) 72 282 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(= 6) 180 282 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Con\337icting of data types or data tags) 252 282 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV_NO) 72 264 T +(TFOUND) 127.51 264 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(= 7) 180 264 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Cde) 252 264 T +(v cannot \336nd speci\336ed data or tag) 271.03 264 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV_TIMEOUT) 72 246 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(= 8) 180 246 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(T) 252 246 T +(ime out) 258.91 246 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV_CONVER) 72 228 T +(T) 159.28 228 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(= 9) 180 228 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 252 228 T +(vData con) 268.36 228 T +(v) 316.86 228 T +(ersion error) 322.68 228 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 14 Q +(Name Ser) 72 192.67 T +(vices) 130.56 192.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 12 Q +(There is a special de) 72 172 T +(vice named cde) 169.67 172 T +(vDirectory which pro) 244.01 172 T +(vides a set of query capabilities:) 347.14 172 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(status = cde) 90 154 T +(vSend\050\322cde) 146.46 154 T +(vDirectory\323, \323query\323,) 202.14 154 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 186 136 T +(v_data_t selection, cde) 202.36 136 T +(v_data_t result\051;) 311.7 136 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The selection data object speci\336es one or more tags used to select de) 72 118 T +(vice names. The result con-) 400.97 118 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(tains a list of de) 72 104 T +(vices accessed through the \322v) 147.7 104 T +(alue\323 tag.) 289.36 104 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "5" 9 +%%Trailer +%%BoundingBox: 0 0 612 792 +%%PageOrder: Ascend +%%Pages: 9 +%%DocumentFonts: Helvetica +%%+ Times-BoldItalic +%%+ Helvetica-Bold +%%+ Times-Roman +%%+ Times-Bold +%%EOF diff --git a/doc/ps/cdevCollectionDesign.ps b/doc/ps/cdevCollectionDesign.ps new file mode 100755 index 0000000..df91a51 --- /dev/null +++ b/doc/ps/cdevCollectionDesign.ps @@ -0,0 +1,11395 @@ +%!PS-Adobe-3.0 +%%BoundingBox: (atend) +%%Pages: (atend) +%%PageOrder: (atend) +%%DocumentFonts: (atend) +%%Creator: Frame 5.0 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +% +% Frame ps_prolog 5.0, for use with Frame 5.0 products +% This ps_prolog file is Copyright (c) 1986-1995 Frame Technology +% Corporation. All rights reserved. This ps_prolog file may be +% freely copied and distributed in conjunction with documents created +% using FrameMaker, FrameMaker/SGML and FrameViewer as long as this +% copyright notice is preserved. +% +% FrameMaker users specify the proper paper size for each print job in the +% "Print" dialog's "Printer Paper Size" "Width" and "Height~ fields. If the +% printer that the PS file is sent to does not support the requested paper +% size, or if there is no paper tray of the proper size currently installed, +% then the job will not be printed. The following flag, if set to true, will +% cause the job to print on the default paper in such cases. +/FMAllowPaperSizeMismatch false def +% +% Frame products normally print colors as their true color on a color printer +% or as shades of gray, based on luminance, on a black-and white printer. The +% following flag, if set to true, forces all non-white colors to print as pure +% black. This has no effect on bitmap images. +/FMPrintAllColorsAsBlack false def +% +% Frame products can either set their own line screens or use a printer's +% default settings. Three flags below control this separately for no +% separations, spot separations and process separations. If a flag +% is true, then the default printer settings will not be changed. If it is +% false, Frame products will use their own settings from a table based on +% the printer's resolution. +/FMUseDefaultNoSeparationScreen true def +/FMUseDefaultSpotSeparationScreen true def +/FMUseDefaultProcessSeparationScreen false def +% +% For any given PostScript printer resolution, Frame products have two sets of +% screen angles and frequencies for printing process separations, which are +% recomended by Adobe. The following variable chooses the higher frequencies +% when set to true or the lower frequencies when set to false. This is only +% effective if the appropriate FMUseDefault...SeparationScreen flag is false. +/FMUseHighFrequencyScreens true def +% +% The following is a set of predefined optimal frequencies and angles for various +% common dpi settings. This is taken from "Advances in Color Separation Using +% PostScript Software Technology," from Adobe Systems (3/13/89 P.N. LPS 0043) +% and corrolated with information which is in various PPD (4.0) files. +% +% The "dpiranges" figure is the minimum dots per inch device resolution which +% can support this setting. The "low" and "high" values are controlled by the +% setting of the FMUseHighFrequencyScreens flag above. The "TDot" flags control +% the use of the "Yellow Triple Dot" feature whereby the frequency id divided by +% three, but the dot function is "trippled" giving a block of 3x3 dots per cell. +% +% PatFreq is a compromise pattern frequency for ps Level 2 printers which is close +% to the ideal WYSIWYG pattern frequency of 9 repetitions/inch but does not beat +% (too badly) against the screen frequencies of any separations for that DPI. +/dpiranges [ 2540 2400 1693 1270 1200 635 600 0 ] def +/CMLowFreqs [ 100.402 94.8683 89.2289 100.402 94.8683 66.9349 63.2456 47.4342 ] def +/YLowFreqs [ 95.25 90.0 84.65 95.25 90.0 70.5556 66.6667 50.0 ] def +/KLowFreqs [ 89.8026 84.8528 79.8088 89.8026 84.8528 74.8355 70.7107 53.033 ] def +/CLowAngles [ 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 ] def +/MLowAngles [ 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 ] def +/YLowTDot [ true true false true true false false false ] def +/CMHighFreqs [ 133.87 126.491 133.843 108.503 102.523 100.402 94.8683 63.2456 ] def +/YHighFreqs [ 127.0 120.0 126.975 115.455 109.091 95.25 90.0 60.0 ] def +/KHighFreqs [ 119.737 113.137 119.713 128.289 121.218 89.8026 84.8528 63.6395 ] def +/CHighAngles [ 71.5651 71.5651 71.5651 70.0169 70.0169 71.5651 71.5651 71.5651 ] def +/MHighAngles [ 18.4349 18.4349 18.4349 19.9831 19.9831 18.4349 18.4349 18.4349 ] def +/YHighTDot [ false false true false false true true false ] def +/PatFreq [ 10.5833 10.0 9.4055 10.5833 10.0 10.5833 10.0 9.375 ] def +% +% PostScript Level 2 printers contain an "Accurate Screens" feature which can +% improve process separation rendering at the expense of compute time. This +% flag is ignored by PostScript Level 1 printers. +/FMUseAcccurateScreens true def +% +% The following PostScript procedure defines the spot function that Frame +% products will use for process separations. You may un-comment-out one of +% the alternative functions below, or use your own. +% +% Dot function +/FMSpotFunction {abs exch abs 2 copy add 1 gt + {1 sub dup mul exch 1 sub dup mul add 1 sub } + {dup mul exch dup mul add 1 exch sub }ifelse } def +% +% Line function +% /FMSpotFunction { pop } def +% +% Elipse function +% /FMSpotFunction { dup 5 mul 8 div mul exch dup mul exch add +% sqrt 1 exch sub } def +% +% +/FMversion (5.0) def +/fMLevel1 /languagelevel where {pop languagelevel} {1} ifelse 2 lt def +/FMPColor + fMLevel1 { + false + /colorimage where {pop pop true} if + } { + true + } ifelse +def +/FrameDict 400 dict def +systemdict /errordict known not {/errordict 10 dict def + errordict /rangecheck {stop} put} if +% The readline in PS 23.0 doesn't recognize cr's as nl's on AppleTalk +FrameDict /tmprangecheck errordict /rangecheck get put +errordict /rangecheck {FrameDict /bug true put} put +FrameDict /bug false put +mark +% Some PS machines read past the CR, so keep the following 3 lines together! +currentfile 5 string readline +00 +0000000000 +cleartomark +errordict /rangecheck FrameDict /tmprangecheck get put +FrameDict /bug get { + /readline { + /gstring exch def + /gfile exch def + /gindex 0 def + { + gfile read pop + dup 10 eq {exit} if + dup 13 eq {exit} if + gstring exch gindex exch put + /gindex gindex 1 add def + } loop + pop + gstring 0 gindex getinterval true + } bind def + } if +/FMshowpage /showpage load def +/FMquit /quit load def +/FMFAILURE { + dup = flush + FMshowpage + /Helvetica findfont 12 scalefont setfont + 72 200 moveto show + 72 220 moveto show + FMshowpage + FMquit + } def +/FMVERSION { + FMversion ne { + (Frame product version does not match ps_prolog! Check installation;) + (also check ~/fminit and ./fminit for old versions) FMFAILURE + } if + } def +/FMBADEPSF { + (Adobe's PostScript Language Reference Manual, 2nd Edition, section H.2.4) + (says your EPS file is not valid, as it calls X ) + dup dup (X) search pop exch pop exch pop length + 5 -1 roll + putinterval + FMFAILURE + } def +/fmConcatProcs + { + /proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def + newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx +}def +FrameDict begin [ + /ALDsave + /FMdicttop + /FMoptop + /FMpointsize + /FMsaveobject + /b + /bitmapsave + /blut + /bpside + /bs + /bstring + /bwidth + /c + /cf + /cs + /cynu + /depth + /edown + /fh + /fillvals + /fw + /fx + /fy + /g + /gfile + /gindex + /grnt + /gryt + /gstring + /height + /hh + /i + /im + /indx + /is + /k + /kk + /landscape + /lb + /len + /llx + /lly + /m + /magu + /manualfeed + /n + /offbits + /onbits + /organgle + /orgbangle + /orgbfreq + /orgbproc + /orgbxfer + /orgfreq + /orggangle + /orggfreq + /orggproc + /orggxfer + /orgmatrix + /orgproc + /orgrangle + /orgrfreq + /orgrproc + /orgrxfer + /orgxfer + /pagesave + /paperheight + /papersizedict + /paperwidth + /pos + /pwid + /r + /rad + /redt + /sl + /str + /tran + /u + /urx + /ury + /val + /width + /width + /ws + /ww + /x + /x1 + /x2 + /xindex + /xpoint + /xscale + /xx + /y + /y1 + /y2 + /yelu + /yindex + /ypoint + /yscale + /yy +] { 0 def } forall +/FmBD {bind def} bind def +systemdict /pdfmark known { + /fMAcrobat true def + + /FmPD /pdfmark load def + + + /FmPT /show load def + + + currentdistillerparams /CoreDistVersion get 2000 ge { + + + /FmPD2 /pdfmark load def + + + + + + /FmPA { mark exch /Dest exch 5 3 roll + /View [ /XYZ null 6 -2 roll FmDC exch pop null] /DEST FmPD + }FmBD + } { + + /FmPD2 /cleartomark load def + /FmPA {pop pop pop}FmBD + } ifelse +} { + + /fMAcrobat false def + /FmPD /cleartomark load def + /FmPD2 /cleartomark load def + /FmPT /pop load def + /FmPA {pop pop pop}FmBD +} ifelse +/FmDC { + transform fMDefaultMatrix itransform cvi exch cvi exch +}FmBD +/FmBx { + dup 3 index lt {3 1 roll exch} if + 1 index 4 index lt {4 -1 roll 3 1 roll exch 4 1 roll} if +}FmBD +/FMnone 0 def +/FMcyan 1 def +/FMmagenta 2 def +/FMyellow 3 def +/FMblack 4 def +/FMcustom 5 def +/fMNegative false def +/FrameSepIs FMnone def +/FrameSepBlack 0 def +/FrameSepYellow 0 def +/FrameSepMagenta 0 def +/FrameSepCyan 0 def +/FrameSepRed 1 def +/FrameSepGreen 1 def +/FrameSepBlue 1 def +/FrameCurGray 1 def +/FrameCurPat null def +/FrameCurColors [ 0 0 0 1 0 0 0 ] def +/FrameColorEpsilon .001 def +/eqepsilon { + sub dup 0 lt {neg} if + FrameColorEpsilon le +} bind def +/FrameCmpColorsCMYK { + 2 copy 0 get exch 0 get eqepsilon { + 2 copy 1 get exch 1 get eqepsilon { + 2 copy 2 get exch 2 get eqepsilon { + 3 get exch 3 get eqepsilon + } {pop pop false} ifelse + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/FrameCmpColorsRGB { + 2 copy 4 get exch 0 get eqepsilon { + 2 copy 5 get exch 1 get eqepsilon { + 6 get exch 2 get eqepsilon + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/RGBtoCMYK { + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 3 copy + 2 copy + le { pop } { exch pop } ifelse + 2 copy + le { pop } { exch pop } ifelse + dup dup dup + 6 1 roll + 4 1 roll + 7 1 roll + sub + 6 1 roll + sub + 5 1 roll + sub + 4 1 roll +} bind def +/CMYKtoRGB { + dup dup 4 -1 roll add + 5 1 roll 3 -1 roll add + 4 1 roll add + 1 exch sub dup 0 lt {pop 0} if 3 1 roll + 1 exch sub dup 0 lt {pop 0} if exch + 1 exch sub dup 0 lt {pop 0} if exch +} bind def +/FrameSepInit { + 1.0 RealSetgray +} bind def +/FrameSetSepColor { + /FrameSepBlue exch def + /FrameSepGreen exch def + /FrameSepRed exch def + /FrameSepBlack exch def + /FrameSepYellow exch def + /FrameSepMagenta exch def + /FrameSepCyan exch def + /FrameSepIs FMcustom def + setCurrentScreen +} bind def +/FrameSetCyan { + /FrameSepBlue 1.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 1.0 def + /FrameSepIs FMcyan def + setCurrentScreen +} bind def + +/FrameSetMagenta { + /FrameSepBlue 1.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 1.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMmagenta def + setCurrentScreen +} bind def + +/FrameSetYellow { + /FrameSepBlue 0.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 1.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMyellow def + setCurrentScreen +} bind def + +/FrameSetBlack { + /FrameSepBlue 0.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 1.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMblack def + setCurrentScreen +} bind def + +/FrameNoSep { + /FrameSepIs FMnone def + setCurrentScreen +} bind def +/FrameSetSepColors { + FrameDict begin + [ exch 1 add 1 roll ] + /FrameSepColors + exch def end + } bind def +/FrameColorInSepListCMYK { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsCMYK + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/FrameColorInSepListRGB { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsRGB + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/RealSetgray /setgray load def +/RealSetrgbcolor /setrgbcolor load def +/RealSethsbcolor /sethsbcolor load def +end +/setgray { + FrameDict begin + FrameSepIs FMnone eq + { RealSetgray } + { + FrameSepIs FMblack eq + { RealSetgray } + { FrameSepIs FMcustom eq + FrameSepRed 0 eq and + FrameSepGreen 0 eq and + FrameSepBlue 0 eq and { + RealSetgray + } { + 1 RealSetgray pop + } ifelse + } ifelse + } ifelse + end +} bind def +/setrgbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetrgbcolor } + { + 3 copy [ 4 1 roll ] + FrameColorInSepListRGB + { + FrameSepBlue eq exch + FrameSepGreen eq and exch + FrameSepRed eq and + { 0 } { 1 } ifelse + } + { + FMPColor { + RealSetrgbcolor + currentcmykcolor + } { + RGBtoCMYK + } ifelse + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end +} bind def +/sethsbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSethsbcolor } + { + RealSethsbcolor + currentrgbcolor + setrgbcolor + } + ifelse + end +} bind def +FrameDict begin +/setcmykcolor where { + pop /RealSetcmykcolor /setcmykcolor load def +} { + /RealSetcmykcolor { + 4 1 roll + 3 { 3 index add 0 max 1 min 1 exch sub 3 1 roll} repeat + RealSetrgbcolor pop + } bind def +} ifelse +userdict /setcmykcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetcmykcolor } + { + 4 copy [ 5 1 roll ] + FrameColorInSepListCMYK + { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + { 0 } { 1 } ifelse + } + { + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end + } bind put +fMLevel1 { + + + + /patScreenDict 7 dict dup begin + <0f1e3c78f0e1c387> [ 45 { pop } {exch pop} .5 2 sqrt] FmBD + <0f87c3e1f0783c1e> [ 135 { pop } {exch pop} .5 2 sqrt] FmBD + [ 0 { pop } dup .5 2 ] FmBD + [ 90 { pop } dup .5 2 ] FmBD + <8142241818244281> [ 45 { 2 copy lt {exch} if pop} dup .75 2 sqrt] FmBD + <03060c183060c081> [ 45 { pop } {exch pop} .875 2 sqrt] FmBD + <8040201008040201> [ 135 { pop } {exch pop} .875 2 sqrt] FmBD + end def +} { + + /patProcDict 5 dict dup begin + <0f1e3c78f0e1c387> { 3 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <0f87c3e1f0783c1e> { 3 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + <8142241818244281> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -1 -1 moveto 9 9 lineto stroke } bind def + <03060c183060c081> { 1 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <8040201008040201> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + end def + /patDict 15 dict dup begin + /PatternType 1 def + /PaintType 2 def + /TilingType 3 def + /BBox [ 0 0 8 8 ] def + /XStep 8 def + /YStep 8 def + /PaintProc { + begin + patProcDict bstring known { + patProcDict bstring get exec + } { + 8 8 true [1 0 0 -1 0 8] bstring imagemask + } ifelse + end + } bind def + end def +} ifelse +/combineColor { + FrameSepIs FMnone eq + { + graymode fMLevel1 or not { + + [/Pattern [/DeviceCMYK]] setcolorspace + FrameCurColors 0 4 getinterval aload pop FrameCurPat setcolor + } { + FrameCurColors 3 get 1.0 ge { + FrameCurGray RealSetgray + } { + fMAcrobat not FMPColor graymode and and { + 0 1 3 { + FrameCurColors exch get + 1 FrameCurGray sub mul + } for + RealSetcmykcolor + } { + 4 1 6 { + FrameCurColors exch get + graymode { + 1 exch sub 1 FrameCurGray sub mul 1 exch sub + } { + 1.0 lt {FrameCurGray} {1} ifelse + } ifelse + } for + RealSetrgbcolor + } ifelse + } ifelse + } ifelse + } { + FrameCurColors 0 4 getinterval aload + FrameColorInSepListCMYK { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + FrameSepIs FMcustom eq and + { FrameCurGray } { 1 } ifelse + } { + FrameSepIs FMblack eq + {FrameCurGray 1.0 exch sub mul 1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop FrameCurGray 1.0 exch sub mul 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + graymode fMLevel1 or not { + + [/Pattern [/DeviceGray]] setcolorspace + FrameCurPat setcolor + } { + graymode not fMLevel1 and { + + dup 1 lt {pop FrameCurGray} if + } if + RealSetgray + } ifelse + } ifelse +} bind def +/savematrix { + orgmatrix currentmatrix pop + } bind def +/restorematrix { + orgmatrix setmatrix + } bind def +/fMDefaultMatrix matrix defaultmatrix def +/fMatrix2 matrix def +/dpi 72 0 fMDefaultMatrix dtransform + dup mul exch dup mul add sqrt def + +/freq dpi dup 72 div round dup 0 eq {pop 1} if 8 mul div def +/sangle 1 0 fMDefaultMatrix dtransform exch atan def + sangle fMatrix2 rotate + fMDefaultMatrix fMatrix2 concatmatrix + dup 0 get /sflipx exch def + 3 get /sflipy exch def +/screenIndex { + 0 1 dpiranges length 1 sub { dup dpiranges exch get 1 sub dpi le {exit} {pop} ifelse } for +} bind def +/getCyanScreen { + FMUseHighFrequencyScreens { CHighAngles CMHighFreqs} {CLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getMagentaScreen { + FMUseHighFrequencyScreens { MHighAngles CMHighFreqs } {MLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getYellowScreen { + FMUseHighFrequencyScreens { YHighTDot YHighFreqs} { YLowTDot YLowFreqs } ifelse + screenIndex dup 3 1 roll get 3 1 roll get { 3 div + {2 { 1 add 2 div 3 mul dup floor sub 2 mul 1 sub exch} repeat + FMSpotFunction } } {/FMSpotFunction load } ifelse + 0.0 exch +} bind def +/getBlackScreen { + FMUseHighFrequencyScreens { KHighFreqs } { KLowFreqs } ifelse + screenIndex get 45.0 /FMSpotFunction load +} bind def +/getSpotScreen { + getBlackScreen +} bind def +/getCompositeScreen { + getBlackScreen +} bind def +/FMSetScreen + fMLevel1 { /setscreen load + }{ { + 8 dict begin + /HalftoneType 1 def + /SpotFunction exch def + /Angle exch def + /Frequency exch def + /AccurateScreens FMUseAcccurateScreens def + currentdict end sethalftone + } bind } ifelse +def +/setDefaultScreen { + FMPColor { + orgrxfer cvx orggxfer cvx orgbxfer cvx orgxfer cvx setcolortransfer + } + { + orgxfer cvx settransfer + } ifelse + orgfreq organgle orgproc cvx setscreen +} bind def +/setCurrentScreen { + FrameSepIs FMnone eq { + FMUseDefaultNoSeparationScreen { + setDefaultScreen + } { + getCompositeScreen FMSetScreen + } ifelse + } { + FrameSepIs FMcustom eq { + FMUseDefaultSpotSeparationScreen { + setDefaultScreen + } { + getSpotScreen FMSetScreen + } ifelse + } { + FMUseDefaultProcessSeparationScreen { + setDefaultScreen + } { + FrameSepIs FMcyan eq { + getCyanScreen FMSetScreen + } { + FrameSepIs FMmagenta eq { + getMagentaScreen FMSetScreen + } { + FrameSepIs FMyellow eq { + getYellowScreen FMSetScreen + } { + getBlackScreen FMSetScreen + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse +} bind def +end + +/FMDOCUMENT { + array /FMfonts exch def + /#copies exch def + FrameDict begin + 0 ne /manualfeed exch def + /paperheight exch def + /paperwidth exch def + 0 ne /fMNegative exch def + 0 ne /edown exch def + /yscale exch def + /xscale exch def + fMLevel1 { + manualfeed {setmanualfeed} if + /FMdicttop countdictstack 1 add def + /FMoptop count def + setpapername + manualfeed {true} {papersize} ifelse + {manualpapersize} {false} ifelse + {desperatepapersize} {false} ifelse + {papersizefailure} if + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + } + {2 dict + dup /PageSize [paperwidth paperheight] put + manualfeed {dup /ManualFeed manualfeed put} if + {setpagedevice} stopped {papersizefailure} if + } + ifelse + + FMPColor { + currentcolorscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + cvlit /orgbproc exch def + /orgbangle exch def + /orgbfreq exch def + cvlit /orggproc exch def + /orggangle exch def + /orggfreq exch def + cvlit /orgrproc exch def + /orgrangle exch def + /orgrfreq exch def + currentcolortransfer + fMNegative { + 1 1 4 { + pop { 1 exch sub } fmConcatProcs 4 1 roll + } for + 4 copy + setcolortransfer + } if + cvlit /orgxfer exch def + cvlit /orgbxfer exch def + cvlit /orggxfer exch def + cvlit /orgrxfer exch def + } { + currentscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + + currenttransfer + fMNegative { + { 1 exch sub } fmConcatProcs + dup settransfer + } if + cvlit /orgxfer exch def + } ifelse + end +} def +/FMBEGINPAGE { + FrameDict begin + /pagesave save def + 3.86 setmiterlimit + /landscape exch 0 ne def + landscape { + 90 rotate 0 exch dup /pwid exch def neg translate pop + }{ + pop /pwid exch def + } ifelse + edown { [-1 0 0 1 pwid 0] concat } if + 0 0 moveto paperwidth 0 lineto paperwidth paperheight lineto + 0 paperheight lineto 0 0 lineto 1 setgray fill + xscale yscale scale + /orgmatrix matrix def + gsave +} def +/FMENDPAGE { + grestore + pagesave restore + end + showpage + } def +/FMFONTDEFINE { + FrameDict begin + findfont + ReEncode + 1 index exch + definefont + FMfonts 3 1 roll + put + end + } def +/FMFILLS { + FrameDict begin dup + array /fillvals exch def + dict /patCache exch def + end + } def +/FMFILL { + FrameDict begin + fillvals 3 1 roll put + end + } def +/FMNORMALIZEGRAPHICS { + newpath + 1 setlinewidth + 0 setlinecap + 0 0 0 sethsbcolor + 0 setgray + } bind def +/FMBEGINEPSF { + end + /FMEPSF save def + /showpage {} def +% See Adobe's "PostScript Language Reference Manual, 2nd Edition", page 714. +% "...the following operators MUST NOT be used in an EPS file:" (emphasis ours) + /banddevice {(banddevice) FMBADEPSF} def + /clear {(clear) FMBADEPSF} def + /cleardictstack {(cleardictstack) FMBADEPSF} def + /copypage {(copypage) FMBADEPSF} def + /erasepage {(erasepage) FMBADEPSF} def + /exitserver {(exitserver) FMBADEPSF} def + /framedevice {(framedevice) FMBADEPSF} def + /grestoreall {(grestoreall) FMBADEPSF} def + /initclip {(initclip) FMBADEPSF} def + /initgraphics {(initgraphics) FMBADEPSF} def + /quit {(quit) FMBADEPSF} def + /renderbands {(renderbands) FMBADEPSF} def + /setglobal {(setglobal) FMBADEPSF} def + /setpagedevice {(setpagedevice) FMBADEPSF} def + /setshared {(setshared) FMBADEPSF} def + /startjob {(startjob) FMBADEPSF} def + /lettertray {(lettertray) FMBADEPSF} def + /letter {(letter) FMBADEPSF} def + /lettersmall {(lettersmall) FMBADEPSF} def + /11x17tray {(11x17tray) FMBADEPSF} def + /11x17 {(11x17) FMBADEPSF} def + /ledgertray {(ledgertray) FMBADEPSF} def + /ledger {(ledger) FMBADEPSF} def + /legaltray {(legaltray) FMBADEPSF} def + /legal {(legal) FMBADEPSF} def + /statementtray {(statementtray) FMBADEPSF} def + /statement {(statement) FMBADEPSF} def + /executivetray {(executivetray) FMBADEPSF} def + /executive {(executive) FMBADEPSF} def + /a3tray {(a3tray) FMBADEPSF} def + /a3 {(a3) FMBADEPSF} def + /a4tray {(a4tray) FMBADEPSF} def + /a4 {(a4) FMBADEPSF} def + /a4small {(a4small) FMBADEPSF} def + /b4tray {(b4tray) FMBADEPSF} def + /b4 {(b4) FMBADEPSF} def + /b5tray {(b5tray) FMBADEPSF} def + /b5 {(b5) FMBADEPSF} def + FMNORMALIZEGRAPHICS + [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall + fx fw 2 div add fy fh 2 div add translate + rotate + fw 2 div neg fh 2 div neg translate + fw urx llx sub div fh ury lly sub div scale + llx neg lly neg translate + /FMdicttop countdictstack 1 add def + /FMoptop count def + } bind def +/FMENDEPSF { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMEPSF restore + FrameDict begin + } bind def +FrameDict begin +/setmanualfeed { +%%BeginFeature *ManualFeed True + statusdict /manualfeed true put +%%EndFeature + } bind def +/max {2 copy lt {exch} if pop} bind def +/min {2 copy gt {exch} if pop} bind def +/inch {72 mul} def +/pagedimen { + paperheight sub abs 16 lt exch + paperwidth sub abs 16 lt and + {/papername exch def} {pop} ifelse + } bind def +/setpapername { + /papersizedict 14 dict def + papersizedict begin + /papername /unknown def + /Letter 8.5 inch 11.0 inch pagedimen + /LetterSmall 7.68 inch 10.16 inch pagedimen + /Tabloid 11.0 inch 17.0 inch pagedimen + /Ledger 17.0 inch 11.0 inch pagedimen + /Legal 8.5 inch 14.0 inch pagedimen + /Statement 5.5 inch 8.5 inch pagedimen + /Executive 7.5 inch 10.0 inch pagedimen + /A3 11.69 inch 16.5 inch pagedimen + /A4 8.26 inch 11.69 inch pagedimen + /A4Small 7.47 inch 10.85 inch pagedimen + /B4 10.125 inch 14.33 inch pagedimen + /B5 7.16 inch 10.125 inch pagedimen + end + } bind def +/papersize { + papersizedict begin + /Letter {lettertray letter} def + /LetterSmall {lettertray lettersmall} def + /Tabloid {11x17tray 11x17} def + /Ledger {ledgertray ledger} def + /Legal {legaltray legal} def + /Statement {statementtray statement} def + /Executive {executivetray executive} def + /A3 {a3tray a3} def + /A4 {a4tray a4} def + /A4Small {a4tray a4small} def + /B4 {b4tray b4} def + /B5 {b5tray b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + statusdict begin stopped end + } bind def +/manualpapersize { + papersizedict begin + /Letter {letter} def + /LetterSmall {lettersmall} def + /Tabloid {11x17} def + /Ledger {ledger} def + /Legal {legal} def + /Statement {statement} def + /Executive {executive} def + /A3 {a3} def + /A4 {a4} def + /A4Small {a4small} def + /B4 {b4} def + /B5 {b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + stopped + } bind def +/desperatepapersize { + statusdict /setpageparams known + { + paperwidth paperheight 0 1 + statusdict begin + {setpageparams} stopped + end + } {true} ifelse + } bind def +/papersizefailure { + FMAllowPaperSizeMismatch not + { +(The requested paper size is not available in any currently-installed tray) +(Edit the PS file to "FMAllowPaperSizeMismatch true" to use default tray) + FMFAILURE } if + } def +/DiacriticEncoding [ +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl +/numbersign /dollar /percent /ampersand /quotesingle /parenleft +/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K +/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash +/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h +/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar +/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute +/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis +/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis +/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve +/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex +/udieresis /dagger /.notdef /cent /sterling /section /bullet +/paragraph /germandbls /registered /copyright /trademark /acute +/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef +/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown +/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef +/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde +/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright +/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis +/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl +/periodcentered /quotesinglbase /quotedblbase /perthousand +/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute +/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve +/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron +/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +] def +/ReEncode { + dup + length + dict begin + { + 1 index /FID ne + {def} + {pop pop} ifelse + } forall + 0 eq {/Encoding DiacriticEncoding def} if + currentdict + end + } bind def +FMPColor + + { + /BEGINBITMAPCOLOR { + BITMAPCOLOR} def + /BEGINBITMAPCOLORc { + BITMAPCOLORc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUECOLOR } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUECOLORc } def + /BEGINBITMAPCMYK { + BITMAPCMYK } def + /BEGINBITMAPCMYKc { + BITMAPCMYKc } def + } + + { + /BEGINBITMAPCOLOR { + BITMAPGRAY} def + /BEGINBITMAPCOLORc { + BITMAPGRAYc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUEGRAY } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUEGRAYc } def + /BEGINBITMAPCMYK { + BITMAPCMYKGRAY } def + /BEGINBITMAPCMYKc { + BITMAPCMYKGRAYc } def + } +ifelse +/K { + FMPrintAllColorsAsBlack { + dup 1 eq 2 index 1 eq and 3 index 1 eq and not + {7 {pop} repeat 0 0 0 1 0 0 0} if + } if + FrameCurColors astore + pop combineColor +} bind def +/graymode true def +fMLevel1 { + /fmGetFlip { + fMatrix2 exch get mul 0 lt { -1 } { 1 } ifelse + } FmBD +} if +/setPatternMode { + fMLevel1 { + 2 index patScreenDict exch known { + pop pop + patScreenDict exch get aload pop + freq + mul + 5 2 roll + fMatrix2 currentmatrix 1 get 0 ne { + 3 -1 roll 90 add 3 1 roll + sflipx 1 fmGetFlip sflipy 2 fmGetFlip neg mul + } { + sflipx 0 fmGetFlip sflipy 3 fmGetFlip mul + } ifelse + 0 lt {exch pop} {pop} ifelse + fMNegative { + {neg} fmConcatProcs + } if + bind + + + + systemdict /setscreen get exec + /FrameCurGray exch def + } { + /bwidth exch def + /bpside exch def + /bstring exch def + /onbits 0 def /offbits 0 def + freq sangle landscape {90 add} if + {/ypoint exch def + /xpoint exch def + /xindex xpoint 1 add 2 div bpside mul cvi def + /yindex ypoint 1 add 2 div bpside mul cvi def + bstring yindex bwidth mul xindex 8 idiv add get + 1 7 xindex 8 mod sub bitshift and 0 ne fMNegative {not} if + {/onbits onbits 1 add def 1} + {/offbits offbits 1 add def 0} + ifelse + } + setscreen + offbits offbits onbits add div fMNegative {1.0 exch sub} if + /FrameCurGray exch def + } ifelse + } { + pop pop + dup patCache exch known { + patCache exch get + } { + dup + patDict /bstring 3 -1 roll put + patDict + 9 PatFreq screenIndex get div dup matrix scale + makepattern + dup + patCache 4 -1 roll 3 -1 roll put + } ifelse + /FrameCurGray 0 def + /FrameCurPat exch def + } ifelse + /graymode false def + combineColor +} bind def +/setGrayScaleMode { + graymode not { + /graymode true def + fMLevel1 { + setCurrentScreen + } if + } if + /FrameCurGray exch def + combineColor +} bind def +/normalize { + transform round exch round exch itransform + } bind def +/dnormalize { + dtransform round exch round exch idtransform + } bind def +/lnormalize { + 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop + } bind def +/H { + lnormalize setlinewidth + } bind def +/Z { + setlinecap + } bind def + +/PFill { + graymode fMLevel1 or not { + gsave 1 setgray eofill grestore + } if +} bind def +/PStroke { + graymode fMLevel1 or not { + gsave 1 setgray stroke grestore + } if + stroke +} bind def +/X { + fillvals exch get + dup type /stringtype eq + {8 1 setPatternMode} + {setGrayScaleMode} + ifelse + } bind def +/V { + PFill gsave eofill grestore + } bind def +/Vclip { + clip + } bind def +/Vstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/N { + PStroke + } bind def +/Nclip { + strokepath clip newpath + } bind def +/Nstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/M {newpath moveto} bind def +/E {lineto} bind def +/D {curveto} bind def +/O {closepath} bind def +/L { + /n exch def + newpath + normalize + moveto + 2 1 n {pop normalize lineto} for + } bind def +/Y { + L + closepath + } bind def +/R { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + x1 y1 + x2 y1 + x2 y2 + x1 y2 + 4 Y + } bind def +/rarc + {rad + arcto + } bind def +/RR { + /rad exch def + normalize + /y2 exch def + /x2 exch def + normalize + /y1 exch def + /x1 exch def + mark + newpath + { + x1 y1 rad add moveto + x1 y2 x2 y2 rarc + x2 y2 x2 y1 rarc + x2 y1 x1 y1 rarc + x1 y1 x1 y2 rarc + closepath + } stopped {x1 y1 x2 y2 R} if + cleartomark + } bind def +/RRR { + /rad exch def + normalize /y4 exch def /x4 exch def + normalize /y3 exch def /x3 exch def + normalize /y2 exch def /x2 exch def + normalize /y1 exch def /x1 exch def + newpath + normalize moveto + mark + { + x2 y2 x3 y3 rarc + x3 y3 x4 y4 rarc + x4 y4 x1 y1 rarc + x1 y1 x2 y2 rarc + closepath + } stopped + {x1 y1 x2 y2 x3 y3 x4 y4 newpath moveto lineto lineto lineto closepath} if + cleartomark + } bind def +/C { + grestore + gsave + R + clip + setCurrentScreen +} bind def +/CP { + grestore + gsave + Y + clip + setCurrentScreen +} bind def +/F { + FMfonts exch get + FMpointsize scalefont + setfont + } bind def +/Q { + /FMpointsize exch def + F + } bind def +/T { + moveto show + } bind def +/RF { + rotate + 0 ne {-1 1 scale} if + } bind def +/TF { + gsave + moveto + RF + show + grestore + } bind def +/P { + moveto + 0 32 3 2 roll widthshow + } bind def +/PF { + gsave + moveto + RF + 0 32 3 2 roll widthshow + grestore + } bind def +/S { + moveto + 0 exch ashow + } bind def +/SF { + gsave + moveto + RF + 0 exch ashow + grestore + } bind def +/B { + moveto + 0 32 4 2 roll 0 exch awidthshow + } bind def +/BF { + gsave + moveto + RF + 0 32 4 2 roll 0 exch awidthshow + grestore + } bind def +/G { + gsave + newpath + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill fill + grestore + } bind def +/Gstrk { + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/Gclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GG { + gsave + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill + fill + grestore + } bind def +/GGclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GGstrk { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/A { + gsave + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/Aclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/Astrk { + Gstrk +} bind def +/AA { + gsave + savematrix + newpath + + 3 index 2 div add exch 4 index 2 div sub exch + + normalize 3 index 2 div sub exch 4 index 2 div add exch + translate + rotate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/AAclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/AAstrk { + GGstrk +} bind def +/BEGINPRINTCODE { + /FMdicttop countdictstack 1 add def + /FMoptop count 7 sub def + /FMsaveobject save def + userdict begin + /showpage {} def + FMNORMALIZEGRAPHICS + 3 index neg 3 index neg translate + } bind def +/ENDPRINTCODE { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMsaveobject restore + } bind def +/gn { + 0 + { 46 mul + cf read pop + 32 sub + dup 46 lt {exit} if + 46 sub add + } loop + add + } bind def +/cfs { + /str sl string def + 0 1 sl 1 sub {str exch val put} for + str def + } bind def +/ic [ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 + {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx} + {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx} + {19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} + {13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh} + {4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh} + {13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl} + {7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl} + {0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl} + {10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl} + ] def +/ms { + /sl exch def + /val 255 def + /ws cfs + /im cfs + /val 0 def + /bs cfs + /cs cfs + } bind def +400 ms +/ip { + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip { + + + bis ris copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + ris gis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + gis bis copy pop + dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip4 { + + + kis cis copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + cis mis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + mis yis copy pop + dup dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + yis kis copy pop + 3 mul is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/wh { + /len exch def + /pos exch def + ws 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/bl { + /len exch def + /pos exch def + bs 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/s1 1 string def +/fl { + /len exch def + /pos exch def + /val cf s1 readhexstring pop 0 get def + pos 1 pos len add 1 sub {im exch val put} for + pos len + } bind def +/hx { + 3 copy getinterval + cf exch readhexstring pop pop + } bind def +/wbytes { + dup dup + 8 gt { pop 8 idiv mul } + { 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse } ifelse + } bind def +/BEGINBITMAPBWc { + 1 {} COMMONBITMAPc + } bind def +/BEGINBITMAPGRAYc { + 8 {} COMMONBITMAPc + } bind def +/BEGINBITMAP2BITc { + 2 {} COMMONBITMAPc + } bind def +/COMMONBITMAPc { + + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + cvtProc + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} image + bitmapsave restore + grestore + } bind def +/BEGINBITMAPBW { + 1 {} COMMONBITMAP + } bind def +/BEGINBITMAPGRAY { + 8 {} COMMONBITMAP + } bind def +/BEGINBITMAP2BIT { + 2 {} COMMONBITMAP + } bind def +/COMMONBITMAP { + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + cvtProc + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} image + bitmapsave restore + grestore + } bind def +/ngrayt 256 array def +/nredt 256 array def +/nbluet 256 array def +/ngreent 256 array def +fMLevel1 { +/colorsetup { + currentcolortransfer + /gryt exch def + /blut exch def + /grnt exch def + /redt exch def + 0 1 255 { + /indx exch def + /cynu 1 red indx get 255 div sub def + /magu 1 green indx get 255 div sub def + /yelu 1 blue indx get 255 div sub def + /kk cynu magu min yelu min def + /u kk currentundercolorremoval exec def +% /u 0 def + nredt indx 1 0 cynu u sub max sub redt exec put + ngreent indx 1 0 magu u sub max sub grnt exec put + nbluet indx 1 0 yelu u sub max sub blut exec put + ngrayt indx 1 kk currentblackgeneration exec sub gryt exec put + } for + {255 mul cvi nredt exch get} + {255 mul cvi ngreent exch get} + {255 mul cvi nbluet exch get} + {255 mul cvi ngrayt exch get} + setcolortransfer + {pop 0} setundercolorremoval + {} setblackgeneration + } bind def +} +{ +/colorSetup2 { + [ /Indexed /DeviceRGB 255 + {dup red exch get 255 div + exch dup green exch get 255 div + exch blue exch get 255 div} + ] setcolorspace +} bind def +} ifelse +/fakecolorsetup { + /tran 256 string def + 0 1 255 {/indx exch def + tran indx + red indx get 77 mul + green indx get 151 mul + blue indx get 28 mul + add add 256 idiv put} for + currenttransfer + {255 mul cvi tran exch get 255.0 div} + exch fmConcatProcs settransfer +} bind def +/BITMAPCOLOR { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + fMLevel1 { + colorsetup + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} {is} {is} true 3 colorimage + } { + colorSetup2 + /is width depth wbytes string def + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {cf is readhexstring pop} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPCOLORc { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + fMLevel1 { + colorsetup + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} {is} {is} true 3 colorimage + } { + colorSetup2 + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {ip} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLORc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris} {gis} {bis} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYKc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip4 pop cis} {mis} {yis} {kis} true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLOR { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf gis readhexstring pop } + { cf bis readhexstring pop } + true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYK { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /mis width string def + /yis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf mis readhexstring pop } + { cf yis readhexstring pop } + { cf kis readhexstring pop } + true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUEGRAYc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris gis bis width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAYc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop cis mis yis kis width cgray} image + bitmapsave restore + grestore + } bind def +/cgray { + /ww exch def + /k exch def + /y exch def + /m exch def + /c exch def + 0 1 ww 1 sub { /i exch def c i get m i get y i get k i get CMYKtoRGB + .144 mul 3 1 roll .587 mul 3 1 roll .299 mul add add + c i 3 -1 roll floor cvi put } for + c + } bind def +/gray { + /ww exch def + /b exch def + /g exch def + /r exch def + 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul + b i get .114 mul add add r i 3 -1 roll floor cvi put } for + r + } bind def +/BITMAPTRUEGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf gis readhexstring pop + cf bis readhexstring pop width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /yis width string def + /mis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf mis readhexstring pop + cf yis readhexstring pop + cf kis readhexstring pop width cgray} image + bitmapsave restore + grestore + } bind def +/BITMAPGRAY { + 8 {fakecolorsetup} COMMONBITMAP + } bind def +/BITMAPGRAYc { + 8 {fakecolorsetup} COMMONBITMAPc + } bind def +/ENDBITMAP { + } bind def +end + /ALDmatrix matrix def ALDmatrix currentmatrix pop +/StartALD { + /ALDsave save def + savematrix + ALDmatrix setmatrix + } bind def +/InALD { + restorematrix + } bind def +/DoneALD { + ALDsave restore + } bind def +/I { setdash } bind def +/J { [] 0 setdash } bind def +%%EndProlog +%%BeginSetup +(5.0) FMVERSION +1 1 0 0 612 792 0 1 11 FMDOCUMENT +0 0 /Helvetica FMFONTDEFINE +1 0 /Helvetica-Bold FMFONTDEFINE +2 0 /Helvetica-BoldOblique FMFONTDEFINE +3 0 /Helvetica-Oblique FMFONTDEFINE +4 0 /Courier-BoldOblique FMFONTDEFINE +5 0 /Courier-Bold FMFONTDEFINE +6 0 /Times-BoldItalic FMFONTDEFINE +32 FMFILLS +0 0 FMFILL +1 0.1 FMFILL +2 0.3 FMFILL +3 0.5 FMFILL +4 0.7 FMFILL +5 0.9 FMFILL +6 0.97 FMFILL +7 1 FMFILL +8 <0f1e3c78f0e1c387> FMFILL +9 <0f87c3e1f0783c1e> FMFILL +10 FMFILL +11 FMFILL +12 <8142241818244281> FMFILL +13 <03060c183060c081> FMFILL +14 <8040201008040201> FMFILL +16 1 FMFILL +17 0.9 FMFILL +18 0.7 FMFILL +19 0.5 FMFILL +20 0.3 FMFILL +21 0.1 FMFILL +22 0.03 FMFILL +23 0 FMFILL +24 FMFILL +25 FMFILL +26 <3333333333333333> FMFILL +27 <0000ffff0000ffff> FMFILL +28 <7ebddbe7e7dbbd7e> FMFILL +29 FMFILL +30 <7fbfdfeff7fbfdfe> FMFILL +%%EndSetup +%%Page: "28" 1 +%%BeginPaperSize: Letter +%%EndPaperSize +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. Restr) 54 739 T +(ictions of the cde) 85.64 739 T +(vCollection De) 152.91 739 T +(vice) 210.65 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(28) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 14 Q +0 X +0 0 0 1 0 0 0 K +(7.) 141.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Restrictions of the cde) 162 710.67 T +(vCollection De) 312.71 710.67 T +(vice) 409.74 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1.) 162 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 180 684.33 T +(vice names can only be added to or remo) 192.48 684.33 T +(v) 375.75 684.33 T +(ed from the cde) 380.5 684.33 T +(vCollection de) 449.68 684.33 T +(vice) 512.18 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(until it has been used) 180 672.33 T +2 F +(once) 277.28 672.33 T +0 F +(. After a cde) 300.47 672.33 T +(vCollectionRequest object has been) 354.09 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(gener) 180 660.33 T +(ated from a speci\336c cde) 205.47 660.33 T +(vCollection de) 310.77 660.33 T +(vice) 373.27 660.33 T +(, the de) 390.9 660.33 T +(vice list cannot be) 423.96 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(modi\336ed.) 180 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 162 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180 624.33 T +(vCollection de) 195.82 624.33 T +(vices do not suppor) 258.32 624.33 T +(t the messages \322monitorOn\323 and) 345.43 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322monitorOff) 180 612.33 T +(\323. Only monotonic oper) 230.61 612.33 T +(ations are currently suppor) 331.66 612.33 T +(ted b) 450.44 612.33 T +(y the) 472.48 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180 600.33 T +(vCollection de) 195.82 600.33 T +(vice) 258.32 600.33 T +(.) 275.95 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 162 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180 576.33 T +(vCollection de\336nitions m) 195.82 576.33 T +(ust be the last things de\336ned in the CDEV DDL \336le) 303.53 576.33 T +(.) 526.82 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.33 (This is because the constituent de) 180 564.33 P +-0.33 (vices m) 329.22 564.33 P +-0.33 (ust ha) 362.68 564.33 P +-0.33 (v) 389.38 564.33 P +-0.33 (e already been de\336ned when the) 394.13 564.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180 552.33 T +(vCollection is de\336ned.) 195.82 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 162 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(When the data from a cde) 180 528.33 T +(vDe) 294.76 528.33 T +(vice oper) 312.24 528.33 T +(ation is used to constr) 352.71 528.33 T +(uct the output) 450.13 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180 516.33 T +(vData object f) 195.82 516.33 T +(or a cde) 256.66 516.33 T +(vCollection oper) 292.49 516.33 T +(ation, only data that is scalar in nature) 364.08 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(will be used. If a cde) 180 504.33 T +(vDe) 270.3 504.33 T +(vice retur) 287.78 504.33 T +(ns tagged data items that are arr) 329.15 504.33 T +(a) 473.57 504.33 T +(ys in its) 478.83 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(results) 180 492.33 T +(, those data items will not be included in the result.) 209.3 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 162 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180 468.33 T +(vCollection objects m) 195.82 468.33 T +(ust be compr) 290.19 468.33 T +(ised of regular cde) 348.14 468.33 T +(vDe) 430.1 468.33 T +(vice objects only) 447.58 468.33 T +(.) 519.94 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Because the cde) 180 456.33 T +(vCollection does not suppor) 254.19 456.33 T +(t cde) 377.98 456.33 T +(vDe) 399.36 456.33 T +(vices that retur) 416.84 456.33 T +(n arr) 482.67 456.33 T +(a) 503.13 456.33 T +(ys of) 508.39 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(data in their result, a cde) 180 444.33 T +(vCollection can not contain another cde) 289.2 444.33 T +(vCollection.) 463.99 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 162 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(If a cde) 180 420.33 T +(vCollection consists of de) 212.5 420.33 T +(vices from m) 325.02 420.33 T +(ultiple ser) 381.59 420.33 T +(vices) 424.68 420.33 T +(, the collection does) 447.31 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(not guar) 180 408.33 T +(antee the order in which the cde) 216.59 408.33 T +(vDe) 358.59 408.33 T +(vice\325) 376.07 408.33 T +(s requests will be ser) 395.57 408.33 T +(viced.) 489.23 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Because ser) 180 396.33 T +(vices perf) 235.88 396.33 T +(or) 278.37 396.33 T +(m at v) 287.51 396.33 T +(ar) 314.49 396.33 T +(ying speeds) 323.68 396.33 T +(, a f) 376.89 396.33 T +(aster ser) 393.27 396.33 T +(vice ma) 432.47 396.33 T +(y process its) 466.62 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(de) 180 384.33 T +(vices requests sooner than another ser) 190.82 384.33 T +(vice) 363.98 384.33 T +(.) 381.61 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "28" 1 +%%Page: "27" 2 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Elementar) 367.93 739 T +(y Commands of the cde) 419.22 739 T +(vCollection) 513.99 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(27) 546.88 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 21: Remo) 180 714 T +(ving de) 249.39 714 T +(vices from a cde) 278.14 714 T +(vCollection using regular e) 343.39 714 T +(xpressions) 449.15 714 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Getting a List of) 72 549.48 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 72 537.48 T +(vices fr) 84.63 537.48 T +(om a) 119.45 537.48 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 72 525.48 T +(vCollection) 89.08 525.48 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.35 (In some cases the de) 180 549.48 P +1.35 (v) 280.14 549.48 P +1.35 (eloper ma) 284.89 549.48 P +1.35 (y w) 330.4 549.48 P +1.35 (ant to obtain a list of de) 346.6 549.48 P +1.35 (vices that constitute a) 457.79 549.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.09 (cde) 180 537.48 P +-0.09 (vCollection. This can be done b) 195.82 537.48 P +-0.09 (y using the getList method. This method will obtain) 334.7 537.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.85 (a NULL ter) 180 525.48 P +1.85 (minated list of de) 232.29 525.48 P +1.85 (vices that currently compr) 313.11 525.48 P +1.85 (ise the cde) 432.72 525.48 P +1.85 (vCollection. The) 484.46 525.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.32 (de) 180 513.48 P +0.32 (v) 190.82 513.48 P +0.32 (eloper is responsib) 195.57 513.48 P +0.32 (le f) 279.93 513.48 P +0.32 (or deleting the char) 293.3 513.48 P +0.32 (acter str) 379.76 513.48 P +0.32 (ing arr) 416.36 513.48 P +0.32 (a) 444.92 513.48 P +0.32 (y that is retur) 450.18 513.48 P +0.32 (ned b) 509.2 513.48 P +0.32 (y this) 534.34 513.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.44 (method, ho) 180 501.48 P +2.44 (w) 232.32 501.48 P +2.44 (e) 239.44 501.48 P +2.44 (v) 244.7 501.48 P +2.44 (er) 249.45 501.48 P +2.44 (, one should not delete the individual char) 257.84 501.48 P +2.44 (acter str) 459.38 501.48 P +2.44 (ings that are) 498.09 501.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(stored in the arr) 180 489.48 T +(a) 249.93 489.48 T +(y) 255.19 489.48 T +(.) 259.19 489.48 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 22: Getting a list of de) 180 456.14 T +(vices from a cde) 297.79 456.14 T +(vCollection) 363.04 456.14 T +0 0 0 1 0 0 0 K +180 575.14 558 720 C +0 0 0 1 0 0 0 K +180 575.14 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +0 X +0 0 0 1 0 0 0 K +(#include ) 197.14 698.14 T +(void main \050 void \051) 197.14 676.14 T +({) 197.14 665.14 T +(/**************************************************************) 197.14 654.14 T +( * Attach to a defined cdevCollection device and then remove) 197.14 643.14 T +( * all devices that match the specified regular expression.) 197.14 632.14 T +( **************************************************************/) 197.14 621.14 T +(cdevCollection & cDevice1 =) 197.14 610.14 T +(cdevCollection::attachRef\050\322cDevice1\323\051;) 197.14 599.14 T +(cDevice1.removeRegexp\050\322device?\323\051;) 197.14 588.14 T +180 575.14 558 711 R +1 H +0 Z +N +180 575.14 558 720 C +0 0 612 792 C +180 81 558 556.14 C +180 242.29 558 453.14 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +0 X +0 0 0 1 0 0 0 K +(#include ) 197.14 440.29 T +(void main \050 void \051) 197.14 418.29 T +({) 197.14 407.29 T +(/**************************************************************) 197.14 396.29 T +( * Attach to a cdevCollection device and then use the getList) 197.14 385.29 T +( * method to obtain the array of names that are currently) 197.14 374.29 T +( * stored in the cdevCollection and display them.) 197.14 363.29 T +( *) 197.14 352.29 T +( * Note that the list \050not the list items\051 must be deleted by) 197.14 341.29 T +( * the caller.) 197.14 330.29 T +( **************************************************************/) 197.14 319.29 T +(cdevCollection & cDevice1 =) 197.14 308.29 T +(cdevCollection::attachRef\050\322cDevice1\323\051;) 197.14 297.29 T +(char ** list = cDevice1.getList\050\051;) 197.14 275.29 T +(for\050char **s = list; *s!=NULL; s++\051 printf\050\322%s\134n\323, *s\051;) 197.14 264.29 T +(delete list;) 197.14 253.29 T +180 242.29 558 453.14 R +1 H +0 Z +N +180 81 558 556.14 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "27" 2 +%%Page: "26" 3 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Elementar) 54 739 T +(y Commands of the cde) 105.29 739 T +(vCollection) 200.06 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(26) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Remo) 54 713.33 T +(ving an) 81.58 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Arra) 54 701.33 T +(y of De) 74.36 701.33 T +(vices) 107.55 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(fr) 54 689.33 T +(om a) 61.02 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 54 677.33 T +(vCollection) 71.08 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.77 (This remo) 162 713.33 P +0.77 (v) 207.07 713.33 P +0.77 (e method allo) 211.82 713.33 P +0.77 (ws the de) 273.25 713.33 P +0.77 (v) 317.3 713.33 P +0.77 (eloper to remo) 322.05 713.33 P +0.77 (v) 387.92 713.33 P +0.77 (e an arr) 392.67 713.33 P +0.77 (a) 428.57 713.33 P +0.77 (y of de) 433.83 713.33 P +0.77 (vice names from) 465.1 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.25 (the cde) 162 701.33 P +0.25 (vCollection. In this v) 194.74 701.33 P +0.25 (ar) 284.15 701.33 P +0.25 (iation of the remo) 293.19 701.33 P +0.25 (v) 371.03 701.33 P +0.25 (e method, the caller m) 375.78 701.33 P +0.25 (ust specify the) 475.59 701.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(n) 162 689.33 T +(umber of de) 167.46 689.33 T +(vice names that are stored in the arr) 220.52 689.33 T +(a) 380.49 689.33 T +(y) 385.75 689.33 T +(.) 389.75 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 19: Remo) 162 656 T +(ving an arr) 231.39 656 T +(a) 273.82 656 T +(y of de) 278.55 656 T +(vices from a cde) 305.3 656 T +(vCollection) 370.55 656 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Remo) 54 468.62 T +(ving a NULL-) 81.58 468.62 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(T) 54 456.62 T +(erminated Arra) 59.51 456.62 T +(y) 130.44 456.62 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(of De) 54 444.62 T +(vices fr) 78.85 444.62 T +(om a) 113.67 444.62 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 54 432.62 T +(vCollection) 71.08 432.62 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.77 (This remo) 162 468.62 P +0.77 (v) 207.07 468.62 P +0.77 (e method allo) 211.82 468.62 P +0.77 (ws the de) 273.25 468.62 P +0.77 (v) 317.3 468.62 P +0.77 (eloper to remo) 322.05 468.62 P +0.77 (v) 387.92 468.62 P +0.77 (e an arr) 392.67 468.62 P +0.77 (a) 428.57 468.62 P +0.77 (y of de) 433.83 468.62 P +0.77 (vice names from) 465.1 468.62 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.23 (the cde) 162 456.62 P +1.23 (vCollection. In this v) 195.73 456.62 P +1.23 (ar) 288.07 456.62 P +1.23 (iation of the remo) 297.11 456.62 P +1.23 (v) 377.89 456.62 P +1.23 (e method, the last char) 382.64 456.62 P +1.23 (acter str) 489.16 456.62 P +1.23 (ing) 526.66 456.62 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pointer in the arr) 162 444.62 T +(a) 234.71 444.62 T +(y m) 239.97 444.62 T +(ust be NULL.) 255.98 444.62 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 20: Remo) 162 411.29 T +(ving a NULL-ter) 231.39 411.29 T +(minated arr) 294.63 411.29 T +(a) 340.06 411.29 T +(y of de) 344.79 411.29 T +(vices from a cde) 371.54 411.29 T +(vCollection) 436.79 411.29 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Remo) 54 223.91 T +(ving) 81.58 223.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 54 211.91 T +(vices fr) 66.63 211.91 T +(om a) 101.45 211.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 54 199.91 T +(vCollection) 71.08 199.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using Regular) 54 187.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Expressions) 54 175.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +2.53 (The remo) 162 223.91 P +2.53 (v) 207.16 223.91 P +2.53 (eRege) 211.91 223.91 P +2.53 (xp method uses the regular e) 241.07 223.91 P +2.53 (xpression parsing interf) 382.91 223.91 P +2.53 (ace of the) 491.03 223.91 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.11 (cde) 162 211.91 P +-0.11 (vDirector) 177.82 211.91 P +-0.11 (y de) 218.12 211.91 P +-0.11 (vice to obtain the names of all of the de) 236.61 211.91 P +-0.11 (vices that match the speci\336ed) 409.28 211.91 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.96 (e) 162 199.91 P +0.96 (xpression. This list of names will then be remo) 167.26 199.91 P +0.96 (v) 379.31 199.91 P +0.96 (ed from the cde) 384.06 199.91 P +0.96 (vCollection de) 456.13 199.91 P +0.96 (vice) 519.59 199.91 P +0.96 (.) 537.22 199.91 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.35 (The regular e) 162 187.91 P +0.35 (xpression ma) 221.88 187.91 P +0.35 (y be in either standard f) 281.39 187.91 P +0.35 (or) 387.36 187.91 P +0.35 (mat or the f) 396.5 187.91 P +0.35 (or) 447.85 187.91 P +0.35 (mat used f) 456.99 187.91 P +0.35 (or UNIX) 504.08 187.91 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.56 (\336lename e) 162 175.91 P +1.56 (xpansion. See the cde) 209.39 175.91 P +1.56 (vDirector) 312.72 175.91 P +1.56 (y documentation f) 353.02 175.91 P +1.56 (or more inf) 434.78 175.91 P +1.56 (or) 485.39 175.91 P +1.56 (mation on) 494.53 175.91 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(regular e) 162 163.91 T +(xpressions) 201.16 163.91 T +(.) 248.8 163.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4.03 (The f) 162 146.91 P +4.03 (ollo) 188.52 146.91 P +4.03 (wing code illustr) 203.93 146.91 P +4.03 (ates remo) 283.01 146.91 P +4.03 (ving all de) 331.35 146.91 P +4.03 (vices that match the e) 384.13 146.91 P +4.03 (xpression) 497.21 146.91 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322) 162 134.91 T +3 F +(de) 165.33 134.91 T +(vice?) 176.15 134.91 T +0 F +(\323 from the cde) 199.49 134.91 T +(vCollection \322) 260.88 134.91 T +3 F +(cDe) 315.89 134.91 T +(vice1) 333.37 134.91 T +0 F +(\323.) 356.71 134.91 T +0 0 0 1 0 0 0 K +162 494.29 540 720 C +0 0 0 1 0 0 0 K +162 494.29 540 653 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +0 X +0 0 0 1 0 0 0 K +(#include ) 179.14 640.14 T +(char * devices[] = {\322device0\323, \322device2\323};) 179.14 618.14 T +(void main \050 void \051) 179.14 596.14 T +({) 179.14 585.14 T +(/**************************************************************) 179.14 574.14 T +( * Attach to a defined cdevCollection device and then remove) 179.14 563.14 T +( * two cdevDevices from it.) 179.14 552.14 T +( **************************************************************/) 179.14 541.14 T +(cdevCollection & cDevice1 =) 179.14 530.14 T +(cdevCollection::attachRef\050\322cDevice1\323\051;) 179.14 519.14 T +(cDevice1.remove\0502, devices\051;) 179.14 508.14 T +162 494.29 540 653 R +1 H +0 Z +N +162 494.29 540 720 C +0 0 612 792 C +162 249.57 540 475.29 C +162 249.57 540 408.29 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +0 X +0 0 0 1 0 0 0 K +(#include ) 179.14 395.43 T +(char * devices[] = {\322device0\323, \322device2\323, NULL};) 179.14 373.43 T +(void main \050 void \051) 179.14 351.43 T +({) 179.14 340.43 T +(/**************************************************************) 179.14 329.43 T +( * Attach to a defined cdevCollection device and then remove) 179.14 318.43 T +( * a NULL terminated list of devices from it.) 179.14 307.43 T +( **************************************************************/) 179.14 296.43 T +(cdevCollection & cDevice1 =) 179.14 285.43 T +(cdevCollection::attachRef\050\322cDevice1\323\051;) 179.14 274.43 T +(cDevice1.remove\050devices\051;) 179.14 263.43 T +162 249.57 540 408.29 R +1 H +0 Z +N +162 249.57 540 475.29 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "26" 3 +%%Page: "25" 4 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Elementar) 367.93 739 T +(y Commands of the cde) 419.22 739 T +(vCollection) 513.99 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(25) 546.88 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 16: Adding a de) 180 714 T +(vice to a cde) 273.29 714 T +(vCollection using regular e) 323.54 714 T +(xpressions) 429.31 714 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Remo) 72 549.48 T +(ving a) 99.58 549.48 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.82 (Single De) 72 537.48 P +-0.82 (vice fr) 116.6 537.48 P +-0.82 (om) 145.04 537.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(a cde) 72 525.48 T +(vCollection) 97.42 525.48 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.71 (When remo) 180 549.48 P +0.71 (ving a single de) 232.24 549.48 P +0.71 (vice from a collection, the) 303.56 549.48 P +3 F +0.71 (remo) 422.73 549.48 P +0.71 (v) 445.36 549.48 P +0.71 (e \050char * name\051) 450.11 549.48 P +0 F +0.71 ( method) 521.16 549.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.27 (should be emplo) 180 537.48 P +0.27 (y) 253.61 537.48 P +0.27 (ed. This method will remo) 258.41 537.48 P +0.27 (v) 373.26 537.48 P +0.27 (e the speci\336ed de) 378.01 537.48 P +0.27 (vice name from the list) 456.89 537.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.18 (of de) 180 525.48 P +-0.18 (vice names \050if an) 201.76 525.48 P +-0.18 (y\051 that already e) 276.66 525.48 P +-0.18 (xists in the cde) 347.52 525.48 P +-0.18 (vCollection. The f) 412.83 525.48 P +-0.18 (ollo) 489.42 525.48 P +-0.18 (wing source) 504.83 525.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.25 (code illustr) 180 513.48 P +2.25 (ates ho) 229.94 513.48 P +2.25 (w to remo) 264.84 513.48 P +2.25 (v) 313.09 513.48 P +2.25 (e the cde) 317.84 513.48 P +2.25 (vDe) 363.18 513.48 P +2.25 (vice \322de) 380.66 513.48 P +2.25 (vice0\323 from the cde) 417.62 513.48 P +2.25 (vCollection) 509.1 513.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322cDe) 180 501.48 T +(vice1\323.) 200.81 501.48 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 17: Remo) 180 468.14 T +(ving a single de) 249.39 468.14 T +(vice from a cde) 311.65 468.14 T +(vCollection) 372.4 468.14 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Remo) 72 297.91 T +(ving) 99.58 297.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Multiple De) 72 285.91 T +(vices) 125.19 285.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(fr) 72 273.91 T +(om a) 79.02 273.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 72 261.91 T +(vCollection) 89.08 261.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +2.16 (There are se) 180 297.91 P +2.16 (v) 240.71 297.91 P +2.16 (er) 245.46 297.91 P +2.16 (al v) 254.25 297.91 P +2.16 (ar) 271.72 297.91 P +2.16 (iations of the remo) 280.76 297.91 P +2.16 (v) 369.36 297.91 P +2.16 (e method that will allo) 374.11 297.91 P +2.16 (w y) 478.76 297.91 P +2.16 (ou to remo) 495.72 297.91 P +2.16 (v) 547.69 297.91 P +2.16 (e) 552.44 297.91 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.07 (se) 180 285.91 P +-0.07 (v) 190.26 285.91 P +-0.07 (er) 195.01 285.91 P +-0.07 (al de) 203.8 285.91 P +-0.07 (vices from a cde) 225.11 285.91 P +-0.07 (vCollection using a single function call. This method uses a) 297.4 285.91 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.9 (v) 180 273.91 P +1.9 (ar) 184.75 273.91 P +1.9 (iab) 193.79 273.91 P +1.9 (le length argument list to allo) 206.93 273.91 P +1.9 (w the caller to pass in an arbitr) 343.54 273.91 P +1.9 (ar) 492.32 273.91 P +1.9 (y n) 501.51 273.91 P +1.9 (umber of) 516.64 273.91 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(de) 180 261.91 T +(vice names as par) 190.82 261.91 T +(ameters to the call.) 271.86 261.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 18: Remo) 180 228.57 T +(ving m) 249.39 228.57 T +(ultiple de) 275.8 228.57 T +(vices from a cde) 311.55 228.57 T +(vCollection) 376.8 228.57 T +0 0 0 1 0 0 0 K +180 575.14 558 720 C +0 0 0 1 0 0 0 K +180 575.14 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +0 X +0 0 0 1 0 0 0 K +(#include ) 197.14 698.14 T +(void main \050 void \051) 197.14 676.14 T +({) 197.14 665.14 T +(/**************************************************************) 197.14 654.14 T +( * Attach to the cdevCollection \322brandNew\323 and add a NULL) 197.14 643.14 T +( * terminated list of devices to it.) 197.14 632.14 T +( **************************************************************/) 197.14 621.14 T +(cdevCollection & brandNew =) 197.14 610.14 T +(cdevCollection::attachRef\050\322brandNew\323\051;) 197.14 599.14 T +(brandNew.addRegexp\050\322device?\323\051;) 197.14 588.14 T +180 575.14 558 711 R +1 H +0 Z +N +180 575.14 558 720 C +0 0 612 792 C +180 323.57 558 556.14 C +180 323.57 558 465.14 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +0 X +0 0 0 1 0 0 0 K +(#include ) 197.14 452.29 T +(void main \050 void \051) 197.14 430.29 T +({) 197.14 419.29 T +(/**************************************************************) 197.14 408.29 T +( * Attach to a defined cdevCollection device and then remove) 197.14 397.29 T +( * the cdevDevice \322device0\323 from it.) 197.14 386.29 T +( **************************************************************/) 197.14 375.29 T +(cdevCollection & cDevice1 =) 197.14 364.29 T +(cdevCollection::attachRef\050\322cDevice1\323\051;) 197.14 353.29 T +(cDevice1.remove\050\322device0\323\051;) 197.14 342.29 T +180 323.57 558 465.14 R +1 H +0 Z +N +180 323.57 558 556.14 C +0 0 612 792 C +180 81 558 304.57 C +180 91.15 558 225.57 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +0 X +0 0 0 1 0 0 0 K +(#include ) 197.14 212.72 T +(void main \050 void \051) 197.14 190.72 T +({) 197.14 179.72 T +(/**************************************************************) 197.14 168.72 T +( * Attach to a defined cdevCollection device and then remove) 197.14 157.72 T +( * two cdevDevices from it.) 197.14 146.72 T +( **************************************************************/) 197.14 135.72 T +(cdevCollection & cDevice1 =) 197.14 124.72 T +(cdevCollection::attachRef\050\322cDevice1\323\051;) 197.14 113.72 T +(cDevice1.remove\0502, \322device0\323, \322device2\323\051;) 197.14 102.72 T +180 91.15 558 225.57 R +1 H +0 Z +N +180 81 558 304.57 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "25" 4 +%%Page: "24" 5 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Elementar) 54 739 T +(y Commands of the cde) 105.29 739 T +(vCollection) 200.06 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(24) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +-0.62 (Ad) 54 713.33 P +-0.62 (ding an Arra) 67.23 713.33 P +-0.62 (y of) 124.68 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 54 701.33 T +(vices to a) 66.63 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 54 689.33 T +(vCollection) 71.08 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +2.68 (This add method allo) 162 713.33 P +2.68 (ws the de) 262.72 713.33 P +2.68 (v) 310.58 713.33 P +2.68 (eloper to add an arr) 315.33 713.33 P +2.68 (a) 413.23 713.33 P +2.68 (y of de) 418.49 713.33 P +2.68 (vice names to the) 453.58 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.04 (cde) 162 701.33 P +-0.04 (vCollection. In this v) 177.82 701.33 P +-0.04 (ar) 266.38 701.33 P +-0.04 (iation of the add method, the caller m) 275.42 701.33 P +-0.04 (ust specify the n) 439.61 701.33 P +-0.04 (umber) 511.66 701.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(of de) 162 689.33 T +(vice names that are stored in the arr) 183.94 689.33 T +(a) 343.91 689.33 T +(y) 349.17 689.33 T +(.) 353.17 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 14: Adding an arr) 162 656 T +(a) 261.46 656 T +(y of de) 266.19 656 T +(vices to a cde) 292.94 656 T +(vCollection) 347.7 656 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Ad) 54 468.62 T +(ding a NULL-) 67.23 468.62 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(T) 54 456.62 T +(erminated Arra) 59.51 456.62 T +(y) 130.44 456.62 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(of De) 54 444.62 T +(vices to a) 78.85 444.62 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 54 432.62 T +(vCollection) 71.08 432.62 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +2.68 (This add method allo) 162 468.62 P +2.68 (ws the de) 262.72 468.62 P +2.68 (v) 310.58 468.62 P +2.68 (eloper to add an arr) 315.33 468.62 P +2.68 (a) 413.23 468.62 P +2.68 (y of de) 418.49 468.62 P +2.68 (vice names to the) 453.58 468.62 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.29 (cde) 162 456.62 P +0.29 (vCollection. In this v) 177.82 456.62 P +0.29 (ar) 267.35 456.62 P +0.29 (iation of the add method, the last char) 276.39 456.62 P +0.29 (acter str) 445.62 456.62 P +0.29 (ing pointer in) 482.18 456.62 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the arr) 162 444.62 T +(a) 190.8 444.62 T +(y m) 196.06 444.62 T +(ust be NULL.) 212.07 444.62 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 15: Adding a NULL-ter) 162 411.29 T +(minated arr) 282.28 411.29 T +(a) 327.7 411.29 T +(y of de) 332.43 411.29 T +(vices to a cde) 359.18 411.29 T +(vCollection) 413.94 411.29 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Ad) 54 223.91 T +(ding De) 67.23 223.91 T +(vices to) 103.75 223.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(a cde) 54 211.91 T +(vCollection) 79.42 211.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using Regular) 54 199.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Expressions) 54 187.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.15 (The addRege) 162 223.91 P +4.15 (xp method uses the regular e) 226.44 223.91 P +4.15 (xpression parsing interf) 376.41 223.91 P +4.15 (ace of the) 487.78 223.91 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.11 (cde) 162 211.91 P +-0.11 (vDirector) 177.82 211.91 P +-0.11 (y de) 218.12 211.91 P +-0.11 (vice to obtain the names of all of the de) 236.61 211.91 P +-0.11 (vices that match the speci\336ed) 409.28 211.91 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.07 (e) 162 199.91 P +1.07 (xpression. This list of names will then be added to the cde) 167.26 199.91 P +1.07 (vCollection de) 434.94 199.91 P +1.07 (vice) 498.51 199.91 P +1.07 (. The) 516.14 199.91 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.92 (regular e) 162 187.91 P +1.92 (xpression ma) 203.08 187.91 P +1.92 (y be in either standard f) 264.16 187.91 P +1.92 (or) 377.96 187.91 P +1.92 (mat or the f) 387.11 187.91 P +1.92 (or) 443.15 187.91 P +1.92 (mat used f) 452.29 187.91 P +1.92 (or UNIX) 502.52 187.91 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.56 (\336lename e) 162 175.91 P +1.56 (xpansion. See the cde) 209.39 175.91 P +1.56 (vDirector) 312.72 175.91 P +1.56 (y documentation f) 353.02 175.91 P +1.56 (or more inf) 434.78 175.91 P +1.56 (or) 485.39 175.91 P +1.56 (mation on) 494.53 175.91 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(regular e) 162 163.91 T +(xpressions) 201.16 163.91 T +(.) 248.8 163.91 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The f) 162 146.91 T +(ollo) 184.49 146.91 T +(wing code illustr) 199.9 146.91 T +(ates loading all de) 270.93 146.91 T +(vices that match the e) 351.23 146.91 T +(xpression \322) 448.2 146.91 T +3 F +(de) 497.1 146.91 T +(vice?) 507.92 146.91 T +0 F +(\323.) 531.26 146.91 T +0 0 0 1 0 0 0 K +162 494.29 540 720 C +0 0 0 1 0 0 0 K +162 494.29 540 653 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +0 X +0 0 0 1 0 0 0 K +(#include ) 179.14 640.14 T +(char * devices[] = {\322device0\323, \322device1\323, \322device2\323, \322device3\323};) 179.14 618.14 T +(void main \050 void \051) 179.14 596.14 T +({) 179.14 585.14 T +(/**************************************************************) 179.14 574.14 T +( * Attach to the cdevCollection \322brandNew\323 and add four device) 179.14 563.14 T +( * names to it.) 179.14 552.14 T +( **************************************************************/) 179.14 541.14 T +(cdevCollection & brandNew =) 179.14 530.14 T +(cdevCollection::attachRef\050\322brandNew\323\051;) 179.14 519.14 T +(brandNew.add\0504, devices\051;) 179.14 508.14 T +162 494.29 540 653 R +1 H +0 Z +N +162 494.29 540 720 C +0 0 612 792 C +162 249.57 540 475.29 C +162 249.57 540 408.29 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +0 X +0 0 0 1 0 0 0 K +(#include ) 179.14 395.43 T +(char * devices[] = {\322device0\323, \322device1\323, \322device2\323, NULL};) 179.14 373.43 T +(void main \050 void \051) 179.14 351.43 T +({) 179.14 340.43 T +(/**************************************************************) 179.14 329.43 T +( * Attach to the cdevCollection \322brandNew\323 and add a NULL) 179.14 318.43 T +( * terminated list of devices to it.) 179.14 307.43 T +( **************************************************************/) 179.14 296.43 T +(cdevCollection & brandNew =) 179.14 285.43 T +(cdevCollection::attachRef\050\322brandNew\323\051;) 179.14 274.43 T +(brandNew.add\050devices\051;) 179.14 263.43 T +162 249.57 540 408.29 R +1 H +0 Z +N +162 249.57 540 475.29 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "24" 5 +%%Page: "23" 6 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Elementar) 367.93 739 T +(y Commands of the cde) 419.22 739 T +(vCollection) 513.99 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(23) 546.88 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(Ad) 72 713.33 T +(ding De) 85.23 713.33 T +(vices to) 121.75 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(a cde) 72 701.33 T +(vCollection) 97.42 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.45 (When creating an empty cde) 180 713.33 P +1.45 (vCollection de) 312.77 713.33 P +1.45 (vice) 376.71 713.33 P +1.45 (, the de) 394.34 713.33 P +1.45 (v) 430.3 713.33 P +1.45 (eloper will ha) 435.05 713.33 P +1.45 (v) 496.09 713.33 P +1.45 (e to add the) 500.84 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.67 (constituent de) 180 701.33 P +0.67 (vices to the collection using one of the v) 242.63 701.33 P +0.67 (ar) 424.53 701.33 P +0.67 (iations of the \322add\323 method.) 433.57 701.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.6 (These methods will allo) 180 689.33 P +2.6 (w the de) 291.58 689.33 P +2.6 (v) 334.28 689.33 P +2.6 (eloper to add either individual de) 339.03 689.33 P +2.6 (vices) 496.27 689.33 P +2.6 (, lists of) 518.9 689.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(de) 180 677.33 T +(vices) 190.82 677.33 T +(, or de) 213.45 677.33 T +(vices from the CDEV DDL \336le that match a speci\336c regular e) 241.5 677.33 T +(xpression.) 508.51 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.7 (It should be noted b) 180 660.33 P +2.7 (y the de) 278.44 660.33 P +2.7 (v) 319.12 660.33 P +2.7 (eloper that only cde) 323.87 660.33 P +2.7 (vDe) 418.93 660.33 P +2.7 (vices ma) 436.41 660.33 P +2.7 (y be added to a) 478.26 660.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 (cde) 180 648.33 P +2 (vCollection. The current design of the cde) 195.82 648.33 P +2 (vCollection de) 392.05 648.33 P +2 (vice does not suppor) 456.55 648.33 P +2 (t) 555.22 648.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(adding collections to a collection.) 180 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The v) 180 619.33 T +(ar) 204.76 619.33 T +(iations of the add method are descr) 213.8 619.33 T +(ibed in the f) 370.7 619.33 T +(ollo) 422.1 619.33 T +(wing sections) 437.51 619.33 T +(.) 497.38 619.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(Ad) 72 590.33 T +(ding a Single) 85.23 590.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 72 578.33 T +(vice to a) 84.63 578.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 72 566.33 T +(vCollection) 89.08 566.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.13 (When adding a single de) 180 590.33 P +0.13 (vice to a collection, the) 290.29 590.33 P +3 F +0.13 (add \050char * name\051) 394.9 590.33 P +0 F +0.13 ( method should be) 475.33 590.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.16 (emplo) 180 578.33 P +0.16 (y) 206.93 578.33 P +0.16 (ed. This method will add the speci\336ed de) 211.73 578.33 P +0.16 (vice name to the list of de) 393.2 578.33 P +0.16 (vice names) 507.27 578.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.3 (\050if an) 180 566.33 P +0.3 (y\051 that already e) 202.38 566.33 P +0.3 (xists in the cde) 274.68 566.33 P +0.3 (vCollection. The f) 341.42 566.33 P +0.3 (ollo) 418.97 566.33 P +0.3 (wing source code illustr) 434.38 566.33 P +0.3 (ates) 539.1 566.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ho) 180 554.33 T +(w to add the cde) 190.97 554.33 T +(vDe) 264.05 554.33 T +(vice \322de) 281.53 554.33 T +(vice0\323 to the cde) 316.24 554.33 T +(vCollection \322br) 389.31 554.33 T +(andNe) 453.11 554.33 T +(w\323.) 482.37 554.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 12: Adding a single de) 180 521 T +(vice to a cde) 299.3 521 T +(vCollection) 349.55 521 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Ad) 72 366.48 T +(ding Multiple) 85.23 366.48 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 72 354.48 T +(vices to a) 84.63 354.48 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 72 342.48 T +(vCollection) 89.08 342.48 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.88 (There are se) 180 366.48 P +1.88 (v) 240.14 366.48 P +1.88 (er) 244.89 366.48 P +1.88 (al v) 253.68 366.48 P +1.88 (ar) 270.87 366.48 P +1.88 (iations of the add method that will allo) 279.91 366.48 P +1.88 (w y) 459.64 366.48 P +1.88 (ou to add se) 476.31 366.48 P +1.88 (v) 536.68 366.48 P +1.88 (er) 541.43 366.48 P +1.88 (al) 550.22 366.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.23 (de) 180 354.48 P +-0.23 (vices to a cde) 190.82 354.48 P +-0.23 (vCollection using a single method. This method uses a v) 250.98 354.48 P +-0.23 (ar) 498.25 354.48 P +-0.23 (iab) 507.29 354.48 P +-0.23 (le length) 520.43 354.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.1 (argument list to allo) 180 342.48 P +1.1 (w the caller to pass in an arbitr) 269.86 342.48 P +1.1 (ar) 413.09 342.48 P +1.1 (y n) 422.28 342.48 P +1.1 (umber of de) 436.62 342.48 P +1.1 (vice names as) 491.88 342.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(par) 180 330.48 T +(ameters to the call.) 194.35 330.48 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 13: Adding m) 180 297.14 T +(ultiple de) 263.45 297.14 T +(vices to a cde) 299.2 297.14 T +(vCollection) 353.95 297.14 T +0 0 0 1 0 0 0 K +180 392.14 558 597 C +0 0 0 1 0 0 0 K +180 392.14 558 518 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +0 X +0 0 0 1 0 0 0 K +(#include ) 197.14 505.14 T +(void main \050 void \051) 197.14 494.14 T +({) 197.14 483.14 T +(/**************************************************************) 197.14 472.14 T +( * Attach to an undefined cdevCollection device and then add) 197.14 461.14 T +( * the cdevDevice \322device0\323 to it.) 197.14 450.14 T +( **************************************************************/) 197.14 439.14 T +(cdevCollection & brandNew =) 197.14 428.14 T +(cdevCollection::attachRef\050\322brandNew\323\051;) 197.14 417.14 T +(brandNew.add\050\322device0\323\051;) 197.14 406.14 T +180 392.14 558 518 R +1 H +0 Z +N +180 392.14 558 597 C +0 0 612 792 C +180 81 558 373.14 C +180 159.72 558 294.14 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +0 X +0 0 0 1 0 0 0 K +(#include ) 197.14 281.29 T +(void main \050 void \051) 197.14 259.29 T +({) 197.14 248.29 T +(/**************************************************************) 197.14 237.29 T +( * Attach to the cdevCollection \322brandNew\323 and add four device) 197.14 226.29 T +( * names to it.) 197.14 215.29 T +( **************************************************************/) 197.14 204.29 T +(cdevCollection & brandNew =) 197.14 193.29 T +(cdevCollection::attachRef\050\322brandNew\323\051;) 197.14 182.29 T +(brandNew.add\0504, \322device0\323, \322device1\323, \322device2\323, \322device3\323\051;) 197.14 171.29 T +180 159.72 558 294.14 R +1 H +0 Z +N +180 81 558 373.14 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "23" 6 +%%Page: "22" 7 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Elementar) 54 739 T +(y Commands of the cde) 105.29 739 T +(vCollection) 200.06 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(22) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 14 Q +0 X +0 0 0 1 0 0 0 K +(6.) 141.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Elementar) 162 710.67 T +(y Commands of the cde) 229.83 710.67 T +(vCollection) 387.54 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Attac) 54 673.33 T +(hing to a) 78.9 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 54 661.33 T +(vCollection) 71.08 661.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +2.77 (In order to use a cde) 162 673.33 P +2.77 (vCollection, the de) 267.27 673.33 P +2.77 (v) 354.77 673.33 P +2.77 (eloper m) 359.52 673.33 P +2.77 (ust \336rst use the attachRef or) 401.09 673.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.17 (attachPtr method to obtain a pointer to the de) 162 661.33 P +0.17 (vice) 363.76 661.33 P +0.17 (. If the de) 381.39 661.33 P +0.17 (vice name that is pro) 423.3 661.33 P +0.17 (vided) 516.1 661.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.78 (to the method is the name of a prede\336ned collection de) 162 649.33 P +0.78 (vice that e) 413 649.33 P +0.78 (xists in the CDEV) 459.85 649.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.22 (DDL \336le) 162 637.33 P +0.22 (, then it will be populated with the de) 197.63 637.33 P +0.22 (vices that are speci\336ed in the de) 360.32 637.33 P +0.22 (vice list.) 504.22 637.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.44 (If the de) 162 625.33 P +1.44 (vice name is NO) 200.72 625.33 P +1.44 (T speci\336ed in the CDEV DDL \336le) 278 625.33 P +1.44 (, then a w) 430.98 625.33 P +1.44 (ar) 478.52 625.33 P +1.44 (ning will be) 487.66 625.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(displa) 162 613.33 T +(y) 187.82 613.33 T +(ed and an empty cde) 192.62 613.33 T +(vCollection will be created.) 285.71 613.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.32 (The code belo) 162 596.33 P +1.32 (w illustr) 227.86 596.33 P +1.32 (ates ho) 262.41 596.33 P +1.32 (w to obtain a ref) 296.38 596.33 P +1.32 (erence to a cde) 372.51 596.33 P +1.32 (vCollection using the) 445.1 596.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.01 (attachRef method, and ho) 162 584.33 P +-0.01 (w to obtain a pointer to a cde) 276.9 584.33 P +-0.01 (vCollection using the attachPtr) 404.96 584.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.83 (method. In the e) 162 572.33 P +2.83 (xample) 242.46 572.33 P +2.83 (, the \322br) 274.54 572.33 P +2.83 (andNe) 314.56 572.33 P +2.83 (w\323 cde) 343.82 572.33 P +2.83 (vCollection will be created with no) 375.8 572.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.05 (constituent de) 162 560.33 P +1.05 (vices because it is not de\336ned in the CDEV DDL \336le) 225.01 560.33 P +1.05 (. The \322cDe) 464.86 560.33 P +1.05 (vice1\323) 513.33 560.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.23 (collection will be populated with the de) 162 548.33 P +1.23 (vices: \322de) 339.14 548.33 P +1.23 (vice0\323, \322de) 382.86 548.33 P +1.23 (vice1\323, and \322de) 430.47 548.33 P +1.23 (vice2\323 as) 498.76 548.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(de\336ned in the CDEV DDL \336le) 162 536.33 T +(.) 290.79 536.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 10: Attach to a cde) 162 520 T +(vCollection using attachPtr and attachRef) 267.29 520 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Detac) 54 252.62 T +(hing fr) 81.13 252.62 T +(om a) 112.04 252.62 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 54 240.62 T +(vCollection) 71.08 240.62 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.64 (Because only one cop) 162 252.62 P +4.64 (y of each cde) 274 252.62 P +4.64 (vDe) 347.1 252.62 P +4.64 (vice or cde) 364.58 252.62 P +4.64 (vCollection e) 421.9 252.62 P +4.64 (xists in the) 483.48 252.62 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.66 (cde) 162 240.62 P +0.66 (vSystem, the n) 177.82 240.62 P +0.66 (umber of ref) 245.18 240.62 P +0.66 (erences to a de) 300.11 240.62 P +0.66 (vice that are in use is tr) 370.71 240.62 P +0.66 (ac) 477.38 240.62 P +0.66 (k) 487.74 240.62 P +0.66 (ed using a) 492.54 240.62 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.16 (ref) 162 228.62 P +0.16 (erence count v) 173.37 228.62 P +0.16 (ar) 239.04 228.62 P +0.16 (iab) 248.08 228.62 P +0.16 (le) 261.22 228.62 P +0.16 (. The detach method decrements that ref) 268.85 228.62 P +0.16 (erence count. When) 450.18 228.62 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the ref) 162 216.62 T +(erence count reaches 0, the cde) 190.05 216.62 T +(vSystem ma) 332.61 216.62 T +(y delete the de) 387.32 216.62 T +(vice) 452.62 216.62 T +(.) 470.25 216.62 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The f) 162 199.62 T +(ollo) 184.49 199.62 T +(wing illustr) 199.9 199.62 T +(ation sho) 246.47 199.62 T +(ws ho) 286.9 199.62 T +(w to detach from a cde) 312.87 199.62 T +(vCollection.) 413.73 199.62 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 11: Detach from a cde) 162 183.29 T +(vCollection using detach) 280.78 183.29 T +0 0 0 1 0 0 0 K +162 278.29 540 680 C +0 0 0 1 0 0 0 K +162 278.29 540 517 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +0 X +0 0 0 1 0 0 0 K +(#include ) 179.14 502 T +(void main \050 void \051) 179.14 480 T +({) 179.14 469 T +(/***************************************************************) 179.14 458 T +( * Obtain a reference to a cdevCollection device named) 179.14 447 T +( * \322brandNew\323. Because this collection is not defined in the) 179.14 436 T +( * CDEV DDL file, it will be created with no constituent) 179.14 425 T +( * devices.) 179.14 414 T +(***************************************************************/) 179.14 392 T +(cdevCollection & brandNew =) 179.14 381 T +(cdevCollection::attachRef\050\322brandNew\323\051;) 179.14 370 T +(/***************************************************************) 179.14 348 T +( * Obtain a reference to a cdevCollection device named) 179.14 337 T +( * \322cDevice1\323. This collection is defined in the CDEV DDL file) 179.14 326 T +-0.09 ( * and will be populated with the devices: \322device0\323, \322device1\323,) 179.14 315 P +( * and \322device2\323.) 179.14 304 T +162 278.29 540 517 R +1 H +0 Z +N +162 278.29 540 680 C +0 0 612 792 C +162 81 540 259.29 C +162 86.57 540 180.29 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +0 X +0 0 0 1 0 0 0 K +(#include ) 177 165.29 T +(void main \050 void \051) 177 143.29 T +({) 177 132.29 T +(cdevCollection & cDevice1 =) 177 121.29 T +(cdevCollection::attachRef\050\322cDevice1\323\051;) 177 110.29 T +(cdevCollection::detach\050cDevice1\051;) 177 99.29 T +162 86.57 540 180.29 R +1 H +0 Z +N +162 81 540 259.29 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "22" 7 +%%Page: "21" 8 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. De\336ning cde) 360.21 739 T +(vCollections in the CDEV DDL File) 419.97 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(21) 546.88 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 14 Q +0 X +0 0 0 1 0 0 0 K +(5.) 159.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De\336ning cde) 180 710.67 T +(vCollections in the CDEV DDL File) 263.8 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w) 108.64 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.82 (A cde) 180 673.33 P +0.82 (vCollection de) 206.09 673.33 P +0.82 (vice can be implemented in one of tw) 269.41 673.33 P +0.82 (o w) 439.56 673.33 P +0.82 (a) 455.78 673.33 P +0.82 (ys; the de) 461.04 673.33 P +0.82 (v) 505.74 673.33 P +0.82 (eloper can) 510.49 673.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.23 (create an empty cde) 180 661.33 P +-0.23 (vCollection dynamically and add de) 269.61 661.33 P +-0.23 (vices to it, or a collection entr) 425.13 661.33 P +-0.23 (y) 553 661.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.96 (can be placed in the CDEV DDL \336le that identi\336es the collection and its constituent) 180 649.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.82 (de) 180 637.33 P +0.82 (vices) 190.82 637.33 P +0.82 (. The syntax f) 213.45 637.33 P +0.82 (or de\336ning a cde) 275.63 637.33 P +0.82 (vCollection de) 351.71 637.33 P +0.82 (vice in the CDEV DDL \336le is as) 415.02 637.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(f) 180 625.33 T +(ollo) 182.48 625.33 T +(ws) 197.89 625.33 T +(.) 209.96 625.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 9: cde) 180 609 T +(vCollection De\336nition in the CDEV DDL File) 234.76 609 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0.64 (In the e) 180 304.48 P +0.64 (xample abo) 214.34 304.48 P +0.64 (v) 266.51 304.48 P +0.64 (e tw) 271.26 304.48 P +0.64 (o cde) 290.14 304.48 P +0.64 (vCollections are de\336ned. A cde) 314.94 304.48 P +0.64 (vCollection de\336nition is) 455.02 304.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.36 (star) 180 292.48 P +0.36 (ted b) 197.07 292.48 P +0.36 (y using the k) 219.47 292.48 P +0.36 (e) 276.47 292.48 P +0.36 (yw) 281.83 292.48 P +0.36 (ord \322) 293.95 292.48 P +2 F +0.36 (collection) 314.87 292.48 P +0 F +0.36 (\323, f) 361.55 292.48 P +0.36 (ollo) 373.27 292.48 P +0.36 (w) 388.68 292.48 P +0.36 (ed b) 395.8 292.48 P +0.36 (y a space and then the name of) 415.42 292.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.4 (the collection. Note that the name of the collection m) 180 280.48 P +1.4 (ust be unique and cannot be) 424.81 280.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(shared with an) 180 268.48 T +(y other de) 244.88 268.48 T +(vice in the cde) 289.05 268.48 T +(v system.) 352.67 268.48 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.34 (The de) 180 251.48 P +1.34 (vice name is f) 212.17 251.48 P +1.34 (ollo) 277.03 251.48 P +1.34 (w) 292.44 251.48 P +1.34 (ed b) 299.56 251.48 P +1.34 (y a white space char) 320.16 251.48 P +1.34 (acter \050) 416.57 251.48 P +2 F +1.34 (whic) 446.26 251.48 P +1.34 (h is required) 468.39 251.48 P +0 F +1.34 (\051, and) 531.09 251.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.61 (then a colon, f) 180 239.48 P +0.61 (ollo) 244.35 239.48 P +0.61 (w) 259.76 239.48 P +0.61 (ed b) 266.88 239.48 P +0.61 (y another white space char) 286.75 239.48 P +0.61 (acter and then the list of de) 408.6 239.48 P +0.61 (vices) 532.59 239.48 P +0.61 (.) 555.22 239.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.21 (The de) 180 227.48 P +1.21 (vice names that are in the list ma) 212.04 227.48 P +1.21 (y be separ) 366.34 227.48 P +1.21 (ated b) 415.34 227.48 P +1.21 (y either white space of a) 444.14 227.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(comma) 180 215.48 T +0 F +( delimiter) 215.01 215.48 T +(. The list of de) 255.07 215.48 T +(vices is ter) 317.58 215.48 T +(minated b) 365.06 215.48 T +(y a) 408.77 215.48 T +2 F +(semicolon) 424.89 215.48 T +0 F +(.) 474.35 215.48 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.04 (The current implementation of the CDEV DDL is order dependent. Because of this) 180 198.48 P +1.04 (,) 555.22 198.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.21 (the de) 180 186.48 P +0.21 (v) 207.71 186.48 P +0.21 (eloper should place the collection de\336nitions after the de\336nitions of all de) 212.46 186.48 P +0.21 (vices) 535.22 186.48 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(and aliases) 180 174.48 T +(.) 230.43 174.48 T +0 0 0 1 0 0 0 K +180 81 558 680 C +0 0 0 1 0 0 0 K +180 335.14 558 606 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +187.43 339.57 551 602.43 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +4 9 Q +(/* service definitions */) 196.43 593.14 T +(...) 196.43 582.14 T +(/* class definitions */) 196.43 560.14 T +(...) 196.43 549.14 T +(/* device instances */) 196.43 527.14 T +(...) 196.43 516.14 T +(/* alias definitions */) 196.43 494.14 T +(...) 196.43 483.14 T +(collection cDevice1 :) 196.43 461.14 T +(device0,) 196.43 450.14 T +(device1,) 196.43 439.14 T +(device2) 196.43 428.14 T +(;) 196.43 417.14 T +(collection cDevice2 :) 196.43 395.14 T +(device3) 196.43 384.14 T +(device4) 196.43 373.14 T +(device5) 196.43 362.14 T +(;) 196.43 351.14 T +180 335.14 558 606 R +1 H +0 Z +N +180 81 558 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "21" 8 +%%Page: "20" 9 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. cde) 54 739 T +(vDefCollectionRequest Class Design) 78.25 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(20) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +1.2 (A cop) 261.29 713.33 P +1.2 (y is made of the callbac) 287.76 713.33 P +1.2 (k object that is pro) 398.06 713.33 P +1.2 (vided b) 483.88 713.33 P +1.2 (y the) 517.12 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.8 (user to ensure that it is not inadv) 261.43 701.33 P +1.8 (er) 418.31 701.33 P +1.8 (tently deleted bef) 427.6 701.33 P +1.8 (ore the) 507.07 701.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(callbac) 261.43 689.33 T +(k function has been called.) 292.35 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(c) 162 665.33 T +(lassName) 167.36 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(const char *className \050v) 261.29 665.33 T +(oid\051 const;) 374.4 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +9.66 (This method will retur) 261.29 648.33 P +9.66 (n the name of the class:) 385.54 648.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(\322cde) 261.43 636.33 T +(vDefCollectionRequest\323.) 280.58 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "20" 9 +%%Page: "19" 10 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. cde) 386.71 739 T +(vDefCollectionRequest Class Design) 410.96 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(19) 546.88 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(g) 180 713.33 T +(etState) 186.21 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int getState \050v) 279.29 713.33 T +(oid\051;) 340.74 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.63 (This method calls the getState method of all of the embedded) 279.29 696.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.45 (request objects) 279.43 684.33 P +2.45 (. The method will retur) 349.54 684.33 P +2.45 (n the most restr) 458.5 684.33 P +2.45 (ictiv) 535.47 684.33 P +2.45 (e) 552.44 684.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(state that is encountered.) 279.43 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(g) 180 648.33 T +(etAccess) 186.21 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int getAccess \050v) 279.29 648.33 T +(oid\051;) 349.62 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +-0.25 (This method calls the getAccess method of all of the embedded) 279.29 631.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.45 (request objects) 279.43 619.33 P +2.45 (. The method will retur) 349.54 619.33 P +2.45 (n the most restr) 458.5 619.33 P +2.45 (ictiv) 535.47 619.33 P +2.45 (e) 552.44 619.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(state that is encountered.) 279.43 607.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(setConte) 180 583.33 T +(xt) 222.63 583.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int setConte) 279.29 583.33 T +(xt \050cde) 332.35 583.33 T +(vData &ctx\051;) 362.06 583.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +3.45 (This method will call the setConte) 279.29 566.33 P +3.45 (xt method of all of the) 445.16 566.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.09 (embedded request objects) 279.43 554.33 P +3.09 (. This method will alw) 403.29 554.33 P +3.09 (a) 510.5 554.33 P +3.09 (ys retur) 515.76 554.33 P +3.09 (n) 552.44 554.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV_SUCCESS) 279.43 542.33 T +(.) 360.91 542.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(send) 180 518.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int send \050cde) 279.29 518.33 T +(vData & in, cde) 336.24 518.33 T +(vData & out\051;) 403.75 518.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int send \050cde) 279.29 506.33 T +(vData * in, cde) 336.24 506.33 T +(vData & out\051;) 400.97 506.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int send \050cde) 279.29 494.33 T +(vData & in, cde) 336.24 494.33 T +(vData * out\051;) 403.75 494.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int send \050cde) 279.29 482.33 T +(vData * in, cde) 336.24 482.33 T +(vData * out\051;) 400.97 482.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +3.73 (The send methods are used to synchronously tr) 279.29 465.33 P +3.73 (ansmit a) 516.48 465.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.82 (message to all of the de) 279.43 453.33 P +1.82 (vices that are embedded within the) 394.39 453.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.77 (cde) 279.43 441.33 P +0.77 (vDefCollectionRequest object. The method will emplo) 295.25 441.33 P +0.77 (y the) 535.55 441.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.86 (sendCallbac) 279.43 429.33 P +1.86 (k method to tr) 334.25 429.33 P +1.86 (ansmit the message and then will) 400.87 429.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.07 (w) 279.43 417.33 P +1.07 (ait f) 286.5 417.33 P +1.07 (or a prede\336ned per) 303.4 417.33 P +1.07 (iod \0505 seconds\051 f) 391.26 417.33 P +1.07 (or all of the request) 468.1 417.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.13 (objects to respond. The method will displa) 279.43 405.33 P +0.13 (y an error and retur) 466.09 405.33 P +0.13 (n) 552.44 405.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.58 (CDEV_ERR) 279.43 393.33 P +1.58 (OR if the request objects do not reply within the) 333.68 393.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(time per) 279.43 381.33 T +(iod.) 315.7 381.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(sendNoBloc) 180 357.33 T +(k) 238.14 357.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int sendNoBloc) 279.29 357.33 T +(k \050cde) 346.34 357.33 T +(vData & in, cde) 373.27 357.33 T +(vData & out\051;) 440.78 357.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int sendNoBloc) 279.29 345.33 T +(k \050cde) 346.34 345.33 T +(vData * in, cde) 373.27 345.33 T +(vData & out\051;) 438 345.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int sendNoBloc) 279.29 333.33 T +(k \050cde) 346.34 333.33 T +(vData & in, cde) 373.27 333.33 T +(vData * out\051;) 440.78 333.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int sendNoBloc) 279.29 321.33 T +(k \050cde) 346.34 321.33 T +(vData * in, cde) 373.27 321.33 T +(vData * out\051;) 438 321.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.12 (The sendNoBloc) 279.29 304.33 P +0.12 (k methods are used to asynchronously send a) 353.13 304.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.82 (message to all of the de) 279.43 292.33 P +1.82 (vices that are embedded within the) 394.39 292.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.57 (cde) 279.43 280.33 P +2.57 (vDefCollectionRequest object. The method relies on the) 295.25 280.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (sendCallbac) 279.43 268.33 P +0.83 (k method to tr) 334.25 268.33 P +0.83 (ansmit the request. The caller m) 397.78 268.33 P +0.83 (ust) 544.66 268.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.25 (ha) 279.43 256.33 P +0.25 (v) 290.35 256.33 P +0.25 (e estab) 295.1 256.33 P +0.25 (lished a cde) 327.95 256.33 P +0.25 (vGroup pr) 381.52 256.33 P +0.25 (ior to submitting the message) 426.38 256.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4.17 (in order to detect when all of the request objects ha) 279.43 244.33 P +4.17 (v) 547.69 244.33 P +4.17 (e) 552.44 244.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(responded.) 279.43 232.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(sendCallbac) 180 208.33 T +(k) 238.71 208.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int sendCallbac) 279.29 208.33 T +(k \050cde) 347.45 208.33 T +(vData & in, cde) 374.38 208.33 T +(vCallbac) 441.89 208.33 T +(k & callbac) 480.03 208.33 T +(k\051;) 528.18 208.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int sendCallbac) 279.29 196.33 T +(k \050cde) 347.45 196.33 T +(vData * in, cde) 374.38 196.33 T +(vCallbac) 439.11 196.33 T +(k & callbac) 477.25 196.33 T +(k\051;) 525.4 196.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +5.45 (The sendCallbac) 279.29 179.33 P +5.45 (k methods are used to asynchronously) 359.57 179.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.66 (tr) 279.43 167.33 P +1.66 (ansmit a message to all of the de) 285.44 167.33 P +1.66 (vices that are embedded) 443.51 167.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 (within the cde) 279.43 155.33 P +1 (vDefCollectionRequest object. The user de\336ned) 342.26 155.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.92 (callbac) 279.43 143.33 P +0.92 (k method will be called when all of the request objects) 310.35 143.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ha) 279.43 131.33 T +(v) 290.35 131.33 T +(e responded.) 295.1 131.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.51 (If one or more of the request objects f) 279.29 114.33 P +0.51 (ails to respond, then the) 449.24 114.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(user speci\336c callbac) 279.43 102.33 T +(k will ne) 368.7 102.33 T +(v) 403.96 102.33 T +(er be e) 408.71 102.33 T +(x) 439.54 102.33 T +(ecuted.) 444.24 102.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "19" 10 +%%Page: "18" 11 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. cde) 54 739 T +(vDefCollectionRequest Class Design) 78.25 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(18) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Attrib) 54 713.33 T +(ute) 80.46 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Over) 54 701.33 T +(vie) 76.89 701.33 T +(w of the) 90.64 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Class) 54 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendStatus) 162 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(typedef str) 261.29 713.33 T +(uct {) 308.13 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int completionCode;) 288.57 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int \336nished;) 288.57 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 288.57 677.33 T +(vData *data;) 304.39 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(} SendStatus sendStatus;) 288.57 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +-0.09 (This is a str) 261.29 648.33 P +-0.09 (ucture that is pro) 312.29 648.33 P +-0.09 (vided as the v) 386.35 648.33 P +-0.09 (oid * argument to the) 447.53 648.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.89 (callbac) 261.43 636.33 P +3.89 (k function that is used f) 292.35 636.33 P +3.89 (or the) 413.81 636.33 P +3 F +3.89 (send) 449.95 636.33 P +0 F +3.89 ( method. This) 471.63 636.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.58 (str) 261.43 624.33 P +0.58 (ucture identi\336es the cde) 272.69 624.33 P +0.58 (vData object that is to be populated) 379.75 624.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.18 (with the results and is also used to maintain a) 261.43 612.33 P +3 F +0.18 (completionCode) 467.75 612.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(and the) 261.43 600.33 T +3 F +(\336nished) 297.57 600.33 T +0 F +( semaphore) 332.03 600.33 T +(.) 384.68 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(sendChec) 162 576.33 T +(kSum) 209.59 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int sendChec) 261.29 576.33 T +(kSum;) 319.45 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.51 (Because the send method uses the sendCallbac) 261.29 559.33 P +1.51 (k method to) 484.72 559.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.97 (tr) 261.43 547.33 P +2.97 (ansmit its requests) 267.44 547.33 P +2.97 (, a callbac) 356.6 547.33 P +2.97 (k associated with an ear) 407.36 547.33 P +2.97 (lier) 526.67 547.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +12.29 (\050timed-out\051 call to send ma) 261.43 535.33 P +12.29 (y occur while the) 428.66 535.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +16.26 (cde) 261.43 523.33 P +16.26 (vDefCollectionRequest object is w) 277.25 523.33 P +16.26 (aiting. The) 477.05 523.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.57 (sendChec) 261.43 511.33 P +0.57 (kSum is used b) 306.25 511.33 P +0.57 (y the callbac) 376.13 511.33 P +0.57 (k method to ensure that) 432.65 511.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the correct request is being processed.) 261.43 499.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(requests) 162 475.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 261.29 475.33 T +(vRequestObject ** requests;) 277.11 475.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +2.12 (This is an arr) 261.29 458.33 P +2.12 (a) 325.34 458.33 P +2.12 (y of request objects that are associated with) 330.61 458.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(each of the de) 261.43 446.33 T +(vices in the collection.) 324.51 446.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(nRequests) 162 422.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int nRequests;) 261.29 422.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.12 (This is the n) 261.29 405.33 P +0.12 (umber of request objects in the requests arr) 315.46 405.33 P +0.12 (a) 509.61 405.33 P +0.12 (y \050the) 514.87 405.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(n) 261.43 393.33 T +(umber of de) 266.89 393.33 T +(vices in the collection\051.) 319.95 393.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(f) 162 369.33 T +(ormat) 165.13 369.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 261.29 369.33 T +(vData f) 277.11 369.33 T +(or) 308.49 369.33 T +(mat;) 317.63 369.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.74 (This is a cde) 261.29 352.33 P +0.74 (vData object that has the same inter) 319.33 352.33 P +0.74 (nal str) 484.09 352.33 P +0.74 (ucture) 512.21 352.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +14.74 (as the \336rst data object gener) 261.43 340.33 P +14.74 (ated b) 461.23 340.33 P +14.74 (y the) 503.58 340.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.81 (cde) 261.43 328.33 P +2.81 (vDefCollectionRequest. This cde) 277.25 328.33 P +2.81 (vData object is used to) 427.61 328.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.54 (pre-f) 261.43 316.33 P +1.54 (or) 281.69 316.33 P +1.54 (mat the user pro) 290.83 316.33 P +1.54 (vided cde) 368.1 316.33 P +1.54 (vData objects to the correct) 412.14 316.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.01 (data types in order to reduce the time e) 261.43 304.33 P +-0.01 (xpended in ref) 435.02 304.33 P +-0.01 (or) 498.07 304.33 P +-0.01 (matting) 507.21 304.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the incoming data dur) 261.43 292.33 T +(ing type promotions) 357.74 292.33 T +(.) 444.85 292.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(Method Over) 54 263.33 T +(vie) 115.22 263.33 T +(w) 128.97 263.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(of the Class) 54 251.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(constructor) 162 263.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 261.29 263.33 T +(vDefCollectionRequest) 277.11 263.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\050char **de) 261.29 251.33 T +(vices) 305.45 251.33 T +(, int nDe) 328.08 251.33 T +(vices) 365.02 251.33 T +(, char *msg, cde) 387.65 251.33 T +(vSystem& sys\051;) 459.6 251.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.94 (This is the constr) 261.29 234.33 P +4.94 (uctor f) 351.83 234.33 P +4.94 (or the cde) 384.26 234.33 P +4.94 (vDefCollectionRequest) 438.3 234.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.18 (object. It will descend the list of de) 261.43 222.33 P +-0.18 (vices that is pro) 411.58 222.33 P +-0.18 (vided and will) 480.35 222.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +5.07 (connect to the cde) 261.43 210.33 P +5.07 (vRequestObject associated with each) 358.06 210.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(de) 261.43 198.33 T +(vice) 272.25 198.33 T +(.) 289.88 198.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(destructor) 162 174.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(~cde) 261.29 174.33 T +(vDefCollectionRequest \050v) 282.95 174.33 T +(oid\051;) 395.51 174.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.36 (This is the destr) 261.29 157.33 P +0.36 (uctor f) 333.1 157.33 P +0.36 (or the class) 360.95 157.33 P +0.36 (. It will free an) 412.65 157.33 P +0.36 (y memor) 475.63 157.33 P +0.36 (y that) 515.18 157.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(w) 261.43 145.33 T +(as pre) 268.5 145.33 T +(viously allocated to the class) 295.99 145.33 T +(.) 422.56 145.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "18" 11 +%%Page: "17" 12 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. cde) 386.71 739 T +(vDefCollectionRequest Class Design) 410.96 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(17) 546.88 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.26 (If CDEV_ERR) 198 713.33 P +1.26 (OR is retur) 261.85 713.33 P +1.26 (ned when the sendCallbac) 312.97 713.33 P +1.26 (k method is used, then the) 434.4 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(user de\336ned callbac) 198 701.33 T +(k function will not be called.) 286.73 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.27 (The send method will w) 198 677.33 P +-0.27 (ait f) 301.26 677.33 P +-0.27 (or a prede\336ned per) 316.81 677.33 P +-0.27 (iod \0505 seconds\051 f) 400.65 677.33 P +-0.27 (or all of the request) 473.47 677.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.96 (objects to respond. If one or more of the request objects f) 198 665.33 P +0.96 (ails to respond within) 461.75 665.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(that per) 198 653.33 T +(iod, then the send method will f) 232.06 653.33 T +(ail and will retur) 369.61 653.33 T +(n CDEV_ERR) 439.32 653.33 T +(OR.) 501.91 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.45 (When using the sendCallbac) 198 629.33 P +0.45 (k method, if one or more of the request objects f) 326.44 629.33 P +0.45 (ails) 543 629.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(to respond, the user de\336ned callbac) 198 617.33 T +(k method will ne) 356.22 617.33 T +(v) 427.61 617.33 T +(er be called.) 432.36 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.93 (Calls to the getState and getAccess methods will poll each of the embedded) 198 593.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.62 (request objects and will retur) 198 581.33 P +3.62 (n an en) 339.99 581.33 P +3.62 (umer) 380.49 581.33 P +3.62 (ated type that re\337ects the most) 403.17 581.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(restr) 198 569.33 T +(ictiv) 218.15 569.33 T +(e state that e) 235.12 569.33 T +(xists) 292.64 569.33 T +(.) 312.49 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.82 (Calls to the setConte) 198 545.33 P +0.82 (xt method will result in the setConte) 292.99 545.33 P +0.82 (xt method being called) 455.48 545.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(f) 198 533.33 T +(or each of the embedded request objects) 200.48 533.33 T +(.) 382.1 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 8: Object Model of the cde) 180 500 T +(vDefCollectionRequest Class) 315.3 500 T +0 0 0 1 0 0 0 K +180 81 558 720 C +0 0 0 1 0 0 0 K +180 191.86 558 497 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +187.43 196.28 551 493.43 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +1 10 Q +(c) 288.21 482.88 T +(lass cde) 293.58 482.88 T +(vDefCollectionRequest) 332.89 482.88 T +187.14 480.14 550.72 480.14 2 L +N +4 9 Q +(attributes:) 195 471.28 T +5 F +(sendStatus : struct SendStatus) 207 460.28 T +(sendCheckSum : int) 207 449.28 T +(requests : cdevRequestObject **) 207 438.28 T +(nRequests : int) 207 427.28 T +(format : cdevData) 207 416.28 T +4 F +(methods:) 195 394.28 T +5 F +-0.62 (cdevDefCollectionRequest \050char **, int, char *, cdevSystem &\051) 207 383.28 P +(~cdevDefCollectionRequest \050void\051 :{virtual}) 207 372.28 T +(getState \050void\051 :{virtual} int) 207 350.28 T +(getAccess \050void\051 :{virtual} int) 207 339.28 T +(setContext \050cdevData &\051 :{virtual} int) 207 328.28 T +(send \050cdevData &, cdevData &\051 :{virtual} int) 207 317.28 T +(send \050cdevData &, cdevData *\051 :{virtual} int) 207 306.28 T +(send \050cdevData *, cdevData &\051 :{virtual} int) 207 295.28 T +(send \050cdevData *, cdevData *\051 :{virtual} int) 207 284.28 T +(sendNoBlock \050cdevData &, cdevData &\051 :{virtual} int) 207 273.28 T +(sendNoBlock \050cdevData &, cdevData *\051 :{virtual} int) 207 262.28 T +(sendNoBlock \050cdevData *, cdevData &\051 :{virtual} int) 207 251.28 T +(sendNoBlock \050cdevData *, cdevData *\051 :{virtual} int) 207 240.28 T +(sendCallback \050cdevData &, cdevCallback &\051 :{virtual} int) 207 229.28 T +(sendCallback \050cdevData *, cdevCallback &\051 :{virtual} int) 207 218.28 T +(className \050void\051 :{virtual} char *) 207 207.28 T +180 191.86 558 497 R +1 H +0 Z +N +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "17" 12 +%%Page: "16" 13 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. cde) 54 739 T +(vDefCollectionRequest Class Design) 78.25 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(16) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 14 Q +0 X +0 0 0 1 0 0 0 K +(4.) 141.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 162 710.67 T +(vDefCollectionRequest Class Design) 185.91 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Purpose of the) 54 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Class) 54 661.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.2 (The cde) 162 673.33 P +0.2 (vDefCollectionRequest object is the def) 198.04 673.33 P +0.2 (ault collection request object f) 373.08 673.33 P +0.2 (or cde) 505.33 673.33 P +0.2 (v) 533.02 673.33 P +0.2 (.) 537.22 673.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.74 (If the ser) 162 661.33 P +1.74 (vice de) 204.69 661.33 P +1.74 (v) 237.81 661.33 P +1.74 (eloper does not pro) 242.56 661.33 P +1.74 (vide a ser) 333.8 661.33 P +1.74 (vice-speci\336c collection mechanism,) 380.93 661.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(then cde) 162 649.33 T +(v will use this object to suppor) 200.06 649.33 T +(t collection request calls to the ser) 333.29 649.33 T +(vice) 484.21 649.33 T +(.) 501.84 649.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.22 (This class perf) 162 632.33 P +-0.22 (or) 225.71 632.33 P +-0.22 (ms collection oper) 234.85 632.33 P +-0.22 (ations b) 314.88 632.33 P +-0.22 (y w) 349.47 632.33 P +-0.22 (alking through the list of ser) 364.1 632.33 P +-0.22 (vice-speci\336c) 485.55 632.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.64 (request objects and e) 162 620.33 P +1.64 (x) 262.24 620.33 P +1.64 (ecuting them one at a time) 266.94 620.33 P +1.64 (. The results from the individual) 392.84 620.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.25 (request objects will then be compiled into a single cde) 162 608.33 P +0.25 (vData object that is retur) 402.35 608.33 P +0.25 (ned to) 511.95 608.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the caller) 162 596.33 T +(.) 202.07 596.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 7: Object Inher) 162 563 T +(itance Hier) 251.68 563 T +(arch) 294.6 563 T +(y of the cde) 311.83 563 T +(vDefCollectionRequest Class) 358.09 563 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Requirements of) 54 338.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the Class) 54 326.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(\245) 162 338.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.01 (This class will obtain a ser) 180 338.33 P +-0.01 (vice-speci\336c cde) 296.4 338.33 P +-0.01 (vRequestObject f) 369.45 338.33 P +-0.01 (or each de) 445.84 338.33 P +-0.01 (vice that is) 492.77 338.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(speci\336ed.) 180 326.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 302.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.56 (The methods send, sendNoBloc) 180 302.33 P +0.56 (k and sendCallbac) 323.75 302.33 P +0.56 (k will be pro) 406.92 302.33 P +0.56 (vided to allo) 461.23 302.33 P +0.56 (w the) 515.54 302.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(message to be tr) 180 290.33 T +(ansmitted to all of the embedded request objects) 254.38 290.33 T +(.) 469.9 290.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 266.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.48 (The send and sendNoBloc) 180 266.33 P +2.48 (k methods will utiliz) 305.1 266.33 P +2.48 (e the sendCallbac) 397.97 266.33 P +2.48 (k method to) 482.78 266.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.79 (tr) 180 254.33 P +2.79 (ansmit messages) 186.01 254.33 P +2.79 (. This will reduce the amount of code that is required to) 266.45 254.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(perf) 180 242.33 T +(or) 196.93 242.33 T +(m message tr) 206.07 242.33 T +(ansmission.) 266.54 242.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 218.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.15 (The class will collect all of the data from the ser) 180 218.33 P +-0.15 (vice-speci\336c request objects into a) 388.32 218.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.4 (single cde) 180 206.33 P +0.4 (vData object that will be pro) 225.12 206.33 P +0.4 (vided to the user) 349.82 206.33 P +0.4 (. The \322) 424.46 206.33 P +3 F +0.4 (resultCode) 454.17 206.33 P +0 F +0.4 (\323 tag will) 502.52 206.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.02 (contain an arr) 180 194.33 P +1.02 (a) 243.07 194.33 P +1.02 (y of completion codes that will indicate the completion status f) 248.34 194.33 P +1.02 (or) 531.11 194.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(each de) 180 182.33 T +(vice/message request.) 215.28 182.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 158.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.62 (The cde) 180 158.33 P +1.62 (vDefCollectionRequest object will maintain order inf) 217.45 158.33 P +1.62 (or) 453.12 158.33 P +1.62 (mation about the) 462.26 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.67 (individual de) 180 146.33 P +0.67 (vices) 235.95 146.33 P +0.67 (. Resultant data items will be placed in the correct order in the) 258.58 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180 134.33 T +(vData item that is retur) 195.82 134.33 T +(ned to the caller) 296.66 134.33 T +(.) 367.31 134.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 110.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.05 (If the data that is retur) 180 110.33 P +0.05 (ned b) 277.8 110.33 P +0.05 (y the individual de) 302.67 110.33 P +0.05 (vices is not homogeneous) 382.57 110.33 P +0.05 (, the data) 498.19 110.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(type will be promoted in such a w) 180 98.33 T +(a) 327.13 98.33 T +(y as to ensure that no data is lost.) 332.39 98.33 T +0 0 0 1 0 0 0 K +162 364 540 680 C +0 0 0 1 0 0 0 K +162 364 540 560 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +257.52 531 388.95 551 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +1 10 Q +(c) 262.83 538.86 T +(lass cde) 268.19 538.86 T +(vRequestObject) 307.51 538.86 T +245.96 473 400.51 493 R +7 X +V +0 X +N +(c) 254.22 480.86 T +(lass cde) 259.58 480.86 T +(vCollectionRequest) 298.9 480.86 T +323.23 531 323.23 493.14 2 L +N +323.59 520.64 314.66 503.5 331.8 503.5 3 Y +7 X +V +0 X +N +241.35 415 405.11 435 R +7 X +V +0 X +N +(c) 246.16 422.86 T +(lass cde) 251.52 422.86 T +(vDefCollectionRequest) 290.84 422.86 T +323.23 473 323.23 435.14 2 L +N +323.59 462.64 314.66 445.5 331.8 445.5 3 Y +7 X +V +0 X +N +324.35 396.29 319.35 405.57 324.35 414.86 329.35 405.57 4 Y +N +345.58 373.14 477.01 393.14 R +7 X +V +0 X +N +(cde) 361.35 380.99 T +(vRequestObject *) 378.43 380.99 T +324.35 396.28 324.35 384.14 345.78 384.14 3 L +N +90 450 2.86 3.21 342.78 384.64 G +90 450 2.86 3.21 342.78 384.64 A +162 364 540 560 R +1 H +0 Z +N +162 364 540 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "16" 13 +%%Page: "15" 14 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. cde) 385.44 739 T +(vGr) 409.69 739 T +(pCollectionRequest Class Design) 424.46 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(15) 546.88 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(sendNoBloc) 180 713.33 T +(k) 238.14 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int sendNoBloc) 279.29 713.33 T +(k \050cde) 346.34 713.33 T +(vData & in, cde) 373.27 713.33 T +(vData & out\051;) 440.78 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int sendNoBloc) 279.29 701.33 T +(k \050cde) 346.34 701.33 T +(vData * in, cde) 373.27 701.33 T +(vData & out\051;) 438 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int sendNoBloc) 279.29 689.33 T +(k \050cde) 346.34 689.33 T +(vData & in, cde) 373.27 689.33 T +(vData * out\051;) 440.78 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int sendNoBloc) 279.29 677.33 T +(k \050cde) 346.34 677.33 T +(vData * in, cde) 373.27 677.33 T +(vData * out\051;) 438 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.12 (The sendNoBloc) 279.29 660.33 P +0.12 (k methods are used to asynchronously send a) 353.13 660.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.82 (message to all of the de) 279.43 648.33 P +1.82 (vices that are embedded within the) 394.39 648.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.34 (cde) 279.43 636.33 P +2.34 (vGr) 295.25 636.33 P +2.34 (pCollectionRequest object. The method relies on the) 311.66 636.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (sendCallbac) 279.43 624.33 P +0.83 (k method to tr) 334.25 624.33 P +0.83 (ansmit the request. The caller m) 397.78 624.33 P +0.83 (ust) 544.66 624.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.25 (ha) 279.43 612.33 P +0.25 (v) 290.35 612.33 P +0.25 (e estab) 295.1 612.33 P +0.25 (lished a cde) 327.95 612.33 P +0.25 (vGroup pr) 381.52 612.33 P +0.25 (ior to submitting the message) 426.38 612.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(in order to detect when all of the collections ha) 279.43 600.33 T +(v) 484.89 600.33 T +(e responded.) 489.64 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(sendCallbac) 180 576.33 T +(k) 238.71 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int sendCallbac) 279.29 576.33 T +(k \050cde) 347.45 576.33 T +(vData & in, cde) 374.38 576.33 T +(vCallbac) 441.89 576.33 T +(k & callbac) 480.03 576.33 T +(k\051;) 528.18 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int sendCallbac) 279.29 564.33 T +(k \050cde) 347.45 564.33 T +(vData * in, cde) 374.38 564.33 T +(vCallbac) 439.11 564.33 T +(k & callbac) 477.25 564.33 T +(k\051;) 525.4 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +5.45 (The sendCallbac) 279.29 547.33 P +5.45 (k methods are used to asynchronously) 359.57 547.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.66 (tr) 279.43 535.33 P +1.66 (ansmit a message to all of the de) 285.44 535.33 P +1.66 (vices that are embedded) 443.51 535.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.76 (within the cde) 279.43 523.33 P +0.76 (vGr) 341.79 523.33 P +0.76 (pCollectionRequest object. The user de\336ned) 358.2 523.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.93 (callbac) 279.43 511.33 P +0.93 (k method will be called when all of the ser) 310.35 511.33 P +0.93 (vice-speci\336c) 503.55 511.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(collections ha) 279.43 499.33 T +(v) 339.81 499.33 T +(e responded.) 344.56 499.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4.05 (If one or more of the ser) 279.29 482.33 P +4.05 (vice-speci\336c collections f) 410.58 482.33 P +4.05 (ails to) 527.84 482.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(respond, then the user speci\336c callbac) 279.43 470.33 T +(k will ne) 449.31 470.33 T +(v) 484.57 470.33 T +(er be e) 489.32 470.33 T +(x) 520.15 470.33 T +(ecuted.) 524.85 470.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.2 (A cop) 279.29 453.33 P +1.2 (y is made of the callbac) 305.76 453.33 P +1.2 (k object that is pro) 416.06 453.33 P +1.2 (vided b) 501.88 453.33 P +1.2 (y the) 535.12 453.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.8 (user to ensure that it is not inadv) 279.43 441.33 P +1.8 (er) 436.31 441.33 P +1.8 (tently deleted bef) 445.6 441.33 P +1.8 (ore the) 525.07 441.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(callbac) 279.43 429.33 T +(k function has been called.) 310.35 429.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(c) 180 405.33 T +(lassName) 185.36 405.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(const char *className \050v) 279.29 405.33 T +(oid\051 const;) 392.4 405.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +9.66 (This method will retur) 279.29 388.33 P +9.66 (n the name of the class:) 403.54 388.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(\322cde) 279.43 376.33 T +(vGr) 298.58 376.33 T +(pCollectionRequest\323.) 314.99 376.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "15" 14 +%%Page: "14" 15 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. cde) 54 739 T +(vGr) 78.25 739 T +(pCollectionRequest Class Design) 93.01 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(14) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Method Over) 54 713.33 T +(vie) 115.22 713.33 T +(w) 128.97 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(of the Class) 54 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(constructor) 162 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 261.29 713.33 T +(vGr) 277.11 713.33 T +(pCollectionRequest) 293.52 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\050char **de) 261.29 701.33 T +(vices) 305.45 701.33 T +(, int nDe) 328.08 701.33 T +(vices) 365.02 701.33 T +(, char *msg, cde) 387.65 701.33 T +(vSystem& sys\051;) 459.6 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.7 (This is the constr) 261.29 684.33 P +4.7 (uctor f) 351.12 684.33 P +4.7 (or the cde) 383.32 684.33 P +4.7 (vGr) 436.89 684.33 P +4.7 (pCollectionRequest) 453.3 684.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.18 (object. It will descend the list of de) 261.43 672.33 P +-0.18 (vices that is pro) 411.58 672.33 P +-0.18 (vided and will) 480.35 672.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.25 (identify the cde) 261.43 660.33 P +1.25 (v ser) 330.89 660.33 P +1.25 (vices that are associated with them. The) 354.11 660.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +15.95 (constr) 261.43 648.33 P +15.95 (uctor will then create a ser) 288.81 648.33 P +15.95 (vice-speci\336c) 485.55 648.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 261.43 636.33 T +(vCollectionRequest object f) 277.25 636.33 T +(or each g) 398.11 636.33 T +(roup of de) 439.7 636.33 T +(vices) 484.43 636.33 T +(.) 507.06 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.08 (De) 261.29 619.33 P +-0.08 (vices that are not associated with a ser) 273.77 619.33 P +-0.08 (vice will be placed on) 445.83 619.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4.9 (a \324dead\325 list and will automatically be mar) 261.43 607.33 P +4.9 (k) 477.04 607.33 P +4.9 (ed with the) 481.84 607.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +10.69 (resultCode CDEV_NO) 261.43 595.33 P +10.69 (T_FOUND whene) 371.2 595.33 P +10.69 (v) 461.05 595.33 P +10.69 (er the send,) 465.8 595.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendNoBloc) 261.43 583.33 T +(k or sendCallbac) 315.14 583.33 T +(k methods are emplo) 389.41 583.33 T +(y) 482.48 583.33 T +(ed.) 487.28 583.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(destructor) 162 559.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(~cde) 261.29 559.33 T +(vGr) 282.95 559.33 T +(pCollectionRequest \050v) 299.36 559.33 T +(oid\051;) 396.92 559.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +2.59 (This is the destr) 261.29 542.33 P +2.59 (uctor f) 339.8 542.33 P +2.59 (or the class) 369.89 542.33 P +2.59 (. It will delete all of the) 426.05 542.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +5.06 (ser) 261.43 530.33 P +5.06 (vice-speci\336c cde) 275.62 530.33 P +5.06 (vCollectionRequests and will free an) 353.73 530.33 P +5.06 (y) 535 530.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(memor) 261.43 518.33 T +(y that w) 292.84 518.33 T +(as pre) 327.15 518.33 T +(viously allocated to the class) 354.64 518.33 T +(.) 481.21 518.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(g) 162 494.33 T +(etState) 168.21 494.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int getState \050v) 261.29 494.33 T +(oid\051;) 322.74 494.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.83 (This method calls the getState method of all of the ser) 261.29 477.33 P +1.83 (vice-) 518.89 477.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.24 (speci\336c cde) 261.43 465.33 P +0.24 (vCollectionRequest objects) 313.61 465.33 P +0.24 (. The method will retur) 434.3 465.33 P +0.24 (n) 534.44 465.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.13 (the most restr) 261.43 453.33 P +3.13 (ictiv) 328.97 453.33 P +3.13 (e state that is encountered from an) 345.94 453.33 P +3.13 (y its) 519.09 453.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(embedded collections) 261.43 441.33 T +(.) 357.99 441.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(g) 162 417.33 T +(etAccess) 168.21 417.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int getAccess \050v) 261.29 417.33 T +(oid\051;) 331.62 417.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.94 (This method calls the getAccess method of all of the ser) 261.29 400.33 P +0.94 (vice-) 518.89 400.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.24 (speci\336c cde) 261.43 388.33 P +0.24 (vCollectionRequest objects) 313.61 388.33 P +0.24 (. The method will retur) 434.3 388.33 P +0.24 (n) 534.44 388.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.7 (the most restr) 261.43 376.33 P +1.7 (ictiv) 326.12 376.33 P +1.7 (e state that is encountered from an) 343.09 376.33 P +1.7 (y of its) 507.69 376.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(embedded collections) 261.43 364.33 T +(.) 357.99 364.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(setConte) 162 340.33 T +(xt) 204.63 340.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int setConte) 261.29 340.33 T +(xt \050cde) 314.35 340.33 T +(vData &ctx\051;) 344.06 340.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +3.45 (This method will call the setConte) 261.29 323.33 P +3.45 (xt method of all of the) 427.16 323.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.58 (ser) 261.43 311.33 P +2.58 (vice-speci\336c cde) 275.62 311.33 P +2.58 (vCollectionRequest objects) 351.25 311.33 P +2.58 (. This method) 474.27 311.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(will alw) 261.43 299.33 T +(a) 292.94 299.33 T +(ys retur) 298.2 299.33 T +(n CDEV_SUCCESS) 331.79 299.33 T +(.) 421.61 299.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(send) 162 275.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int send \050cde) 261.29 275.33 T +(vData & in, cde) 318.24 275.33 T +(vData & out\051;) 385.75 275.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int send \050cde) 261.29 263.33 T +(vData * in, cde) 318.24 263.33 T +(vData & out\051;) 382.97 263.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int send \050cde) 261.29 251.33 T +(vData & in, cde) 318.24 251.33 T +(vData * out\051;) 385.75 251.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int send \050cde) 261.29 239.33 T +(vData * in, cde) 318.24 239.33 T +(vData * out\051;) 382.97 239.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +3.73 (The send methods are used to synchronously tr) 261.29 222.33 P +3.73 (ansmit a) 498.48 222.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.82 (message to all of the de) 261.43 210.33 P +1.82 (vices that are embedded within the) 376.39 210.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.54 (cde) 261.43 198.33 P +0.54 (vGr) 277.25 198.33 P +0.54 (pCollectionRequest object. The method will emplo) 293.66 198.33 P +0.54 (y the) 517.78 198.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.86 (sendCallbac) 261.43 186.33 P +1.86 (k method to tr) 316.25 186.33 P +1.86 (ansmit the message and then will) 382.87 186.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.14 (w) 261.43 174.33 P +-0.14 (ait f) 268.5 174.33 P +-0.14 (or a prede\336ned per) 284.18 174.33 P +-0.14 (iod \0505 seconds\051 f) 368.41 174.33 P +-0.14 (or all of the collections) 441.62 174.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.97 (to respond. The method will displa) 261.43 162.33 P +3.97 (y an error and retur) 432.72 162.33 P +3.97 (n) 534.44 162.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.52 (CDEV_ERR) 261.43 150.33 P +1.52 (OR if the collections do not reply within the time) 315.68 150.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(per) 261.43 138.33 T +(iod.) 276.03 138.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "14" 15 +%%Page: "13" 16 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. cde) 385.44 739 T +(vGr) 409.69 739 T +(pCollectionRequest Class Design) 424.46 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(13) 546.88 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(Attrib) 72 713.33 T +(ute) 98.46 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Over) 72 701.33 T +(vie) 94.89 701.33 T +(w of the) 108.64 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Class) 72 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendStatus) 180 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(typedef str) 279.29 713.33 T +(uct {) 326.13 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int completionCode;) 306.57 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int \336nished;) 306.57 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 306.57 677.33 T +(vData *data;) 322.39 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(} SendStatus sendStatus;) 306.57 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +-0.09 (This is a str) 279.29 648.33 P +-0.09 (ucture that is pro) 330.29 648.33 P +-0.09 (vided as the v) 404.35 648.33 P +-0.09 (oid * argument to the) 465.53 648.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.89 (callbac) 279.43 636.33 P +3.89 (k function that is used f) 310.35 636.33 P +3.89 (or the) 431.81 636.33 P +3 F +3.89 (send) 467.95 636.33 P +0 F +3.89 ( method. This) 489.63 636.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.58 (str) 279.43 624.33 P +0.58 (ucture identi\336es the cde) 290.69 624.33 P +0.58 (vData object that is to be populated) 397.75 624.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.18 (with the results and is also used to maintain a) 279.43 612.33 P +3 F +0.18 (completionCode) 485.75 612.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(and the) 279.43 600.33 T +3 F +(\336nished) 315.57 600.33 T +0 F +( semaphore) 350.03 600.33 T +(.) 402.68 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(sendChec) 180 576.33 T +(kSum) 227.59 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int sendChec) 279.29 576.33 T +(kSum;) 337.45 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.51 (Because the send method uses the sendCallbac) 279.29 559.33 P +1.51 (k method to) 502.72 559.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.97 (tr) 279.43 547.33 P +2.97 (ansmit its requests) 285.44 547.33 P +2.97 (, a callbac) 374.6 547.33 P +2.97 (k associated with an ear) 425.36 547.33 P +2.97 (lier) 544.67 547.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +12.29 (\050timed-out\051 call to send ma) 279.43 535.33 P +12.29 (y occur while the) 446.66 535.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +15.91 (cde) 279.43 523.33 P +15.91 (vGr) 295.25 523.33 P +15.91 (pCollectionRequest object is w) 311.66 523.33 P +15.91 (aiting. The) 495.4 523.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.57 (sendChec) 279.43 511.33 P +0.57 (kSum is used b) 324.25 511.33 P +0.57 (y the callbac) 394.13 511.33 P +0.57 (k method to ensure that) 450.65 511.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the correct request is being processed.) 279.43 499.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(collections) 180 475.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 279.29 475.33 T +(vCollectionRequest * collections;) 295.11 475.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +2.28 (This is an arr) 279.29 458.33 P +2.28 (a) 343.83 458.33 P +2.28 (y of the ser) 349.09 458.33 P +2.28 (vice-speci\336c collections) 405.71 458.33 P +2.28 (. The \336rst) 511.75 458.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.67 (entr) 279.43 446.33 P +0.67 (y in this list is a NULL collection that is used to identify all) 296.96 446.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(de) 279.43 434.33 T +(vices that are not suppor) 290.25 434.33 T +(ted b) 400.15 434.33 T +(y a ser) 422.19 434.33 T +(vice) 452.5 434.33 T +(.) 470.13 434.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(nCollections) 180 410.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int nCollections;) 279.29 410.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.9 (This is the n) 279.29 393.33 P +0.9 (umber of cde) 335.8 393.33 P +0.9 (vCollectionRequests that ha) 395.67 393.33 P +0.9 (v) 521.77 393.33 P +0.9 (e been) 526.52 393.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(allocated to the collections arr) 279.43 381.33 T +(a) 411.61 381.33 T +(y) 416.87 381.33 T +(.) 420.87 381.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(requestOr) 180 357.33 T +(der) 227.59 357.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int * requestOrder) 279.29 357.33 T +(;) 358.51 357.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +-0.22 (This is an arr) 279.29 340.33 P +-0.22 (a) 336.33 340.33 P +-0.22 (y of integers that corresponds to each de) 341.59 340.33 P +-0.22 (vice that) 520.98 340.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.62 (is in the cde) 279.43 328.33 P +0.62 (vCollection. Each entr) 334.36 328.33 P +0.62 (y contains an integer that is) 433.16 328.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.69 (the inde) 279.43 316.33 P +0.69 (x of the ser) 315.41 316.33 P +0.69 (vice-speci\336c cde) 367.26 316.33 P +0.69 (vCollectionRequest that is) 441.01 316.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.52 (associated with the individual de) 279.43 304.33 P +2.52 (vice) 432.6 304.33 P +2.52 (. This arr) 450.23 304.33 P +2.52 (a) 494.61 304.33 P +2.52 (y is used to) 499.87 304.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.77 (place the data items from the v) 279.43 292.33 P +1.77 (ar) 426.56 292.33 P +1.77 (ious de) 435.6 292.33 P +1.77 (vices in the correct) 469.32 292.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(order in the resultant cde) 279.43 280.33 T +(vData item.) 389.74 280.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(nRequests) 180 256.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int nRequests;) 279.29 256.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.84 (This is the n) 279.29 239.33 P +1.84 (umber of entr) 338.62 239.33 P +1.84 (ies in the requestOrder arr) 401.92 239.33 P +1.84 (a) 525.89 239.33 P +1.84 (y \050the) 531.15 239.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(n) 279.43 227.33 T +(umber of de) 284.89 227.33 T +(vices in the collection\051.) 337.95 227.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(f) 180 203.33 T +(ormat) 183.13 203.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 279.29 203.33 T +(vData f) 295.11 203.33 T +(or) 326.49 203.33 T +(mat;) 335.63 203.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.74 (This is a cde) 279.29 186.33 P +0.74 (vData object that has the same inter) 337.33 186.33 P +0.74 (nal str) 502.09 186.33 P +0.74 (ucture) 530.21 186.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +14.28 (as the \336rst data object retr) 279.43 174.33 P +14.28 (ie) 466.62 174.33 P +14.28 (v) 474.1 174.33 P +14.28 (ed from the) 478.85 174.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.57 (cde) 279.43 162.33 P +2.57 (vGr) 295.25 162.33 P +2.57 (pCollectionRequest. This cde) 311.66 162.33 P +2.57 (vData object is used to) 446.55 162.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.54 (pre-f) 279.43 150.33 P +1.54 (or) 299.69 150.33 P +1.54 (mat the user pro) 308.83 150.33 P +1.54 (vided cde) 386.1 150.33 P +1.54 (vData objects to the correct) 430.14 150.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.01 (data types in order to reduce the time e) 279.43 138.33 P +-0.01 (xpended in ref) 453.02 138.33 P +-0.01 (or) 516.07 138.33 P +-0.01 (matting) 525.21 138.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the incoming data dur) 279.43 126.33 T +(ing type promotions) 375.74 126.33 T +(.) 462.85 126.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "13" 16 +%%Page: "12" 17 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. cde) 54 739 T +(vGr) 78.25 739 T +(pCollectionRequest Class Design) 93.01 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(12) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(\245) 162 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.46 (If a de) 180 713.33 P +0.46 (vice does not ha) 208.42 713.33 P +0.46 (v) 282.42 713.33 P +0.46 (e an associated cde) 287.17 713.33 P +0.46 (v ser) 377.2 713.33 P +0.46 (vice) 399.63 713.33 P +0.46 (, then its \322) 417.26 713.33 P +3 F +0.46 (resultCode) 462.55 713.33 P +0 F +0.46 (\323 entr) 510.9 713.33 P +0.46 (y) 535 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(will be set to CDEV_NO) 180 701.33 T +(T_FOUND) 285.74 701.33 T +(.) 332.26 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.23 (If none of the de) 180 677.33 P +1.23 (vices can be associated with a ser) 256.9 677.33 P +1.23 (vice) 416.31 677.33 P +1.23 (, then an) 433.94 677.33 P +1.23 (y call to send,) 475.17 677.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendNoBloc) 180 665.33 T +(k or sendCallbac) 233.71 665.33 T +(k will f) 307.98 665.33 T +(ail and will retur) 334.9 665.33 T +(n CDEV_ERR) 404.61 665.33 T +(OR.) 467.2 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.26 (If CDEV_ERR) 180 641.33 P +1.26 (OR is retur) 243.85 641.33 P +1.26 (ned when the sendCallbac) 294.97 641.33 P +1.26 (k method is used, then the) 416.4 641.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(user de\336ned callbac) 180 629.33 T +(k function will not be called.) 268.73 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.17 (The send method will w) 180 605.33 P +-0.17 (ait f) 283.63 605.33 P +-0.17 (or a prede\336ned per) 299.27 605.33 P +-0.17 (iod \0505 seconds\051 f) 383.39 605.33 P +-0.17 (or all of the ser) 456.48 605.33 P +-0.17 (vice) 522.22 605.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.75 (speci\336c collection objects to retur) 180 593.33 P +1.75 (n their results) 333.98 593.33 P +1.75 (. If one or more of the ser) 397.36 593.33 P +1.75 (vice) 522.22 593.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.79 (speci\336c collections f) 180 581.33 P +0.79 (ails to respond within that per) 269.63 581.33 P +0.79 (iod, then the send method will) 403.78 581.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(f) 180 569.33 T +(ail and will retur) 182.48 569.33 T +(n CDEV_ERR) 252.19 569.33 T +(OR.) 314.78 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.16 (When using the sendCallbac) 180 545.33 P +2.16 (k method, if one or more of the ser) 313.55 545.33 P +2.16 (vice speci\336c) 483.94 545.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(collections f) 180 533.33 T +(ails to respond, the user de\336ned callbac) 231.94 533.33 T +(k method will ne) 407.94 533.33 T +(v) 479.33 533.33 T +(er be called.) 484.08 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.93 (Calls to the getState and getAccess methods will poll each of the embedded) 180 509.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.41 (collections and will retur) 180 497.33 P +1.41 (n an en) 290.61 497.33 P +1.41 (umer) 326.68 497.33 P +1.41 (ated type that re\337ects the most restr) 349.36 497.33 P +1.41 (ictiv) 517.47 497.33 P +1.41 (e) 534.44 497.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(state that e) 180 485.33 T +(xists) 229.18 485.33 T +(.) 249.03 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.82 (Calls to the setConte) 180 461.33 P +0.82 (xt method will result in the setConte) 274.99 461.33 P +0.82 (xt method being called) 437.48 461.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(f) 180 449.33 T +(or each of the embedded ser) 182.48 449.33 T +(vice-speci\336c collections) 310.63 449.33 T +(.) 414.39 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 6: Object Model of the cde) 162 416 T +(vGr) 297.3 416 T +(pCollectionRequest Class) 312.07 416 T +0 0 0 1 0 0 0 K +162 81 540 720 C +0 0 0 1 0 0 0 K +162 92.14 540 413 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +169.43 93.71 533 409.43 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +1 10 Q +(c) 269.38 398.88 T +(lass cde) 274.74 398.88 T +(vGrpCollectionRequest) 314.06 398.88 T +169.14 396.14 532.72 396.14 2 L +N +4 9 Q +(attributes:) 177 387.28 T +5 F +(sendStatus : struct SendStatus) 189 376.28 T +(sendCheckSum : int) 189 365.28 T +(collections : cdevCollectionRequest **) 189 354.28 T +(nCollections : int) 189 343.28 T +(requestOrder : int *) 189 332.28 T +(nRequests : int) 189 321.28 T +(format : cdevData) 189 310.28 T +4 F +(methods:) 177 288.28 T +5 F +-0.62 (cdevGrpCollectionRequest \050char **, int, char *, cdevSystem &\051) 189 277.28 P +(~cdevGrpCollectionRequest \050void\051 :{virtual}) 189 266.28 T +(getState \050void\051 :{virtual} int) 189 244.28 T +(getAccess \050void\051 :{virtual} int) 189 233.28 T +(setContext \050cdevData &\051 :{virtual} int) 189 222.28 T +(send \050cdevData &, cdevData &\051 :{virtual} int) 189 211.28 T +(send \050cdevData &, cdevData *\051 :{virtual} int) 189 200.28 T +(send \050cdevData *, cdevData &\051 :{virtual} int) 189 189.28 T +(send \050cdevData *, cdevData *\051 :{virtual} int) 189 178.28 T +(sendNoBlock \050cdevData &, cdevData &\051 :{virtual} int) 189 167.28 T +(sendNoBlock \050cdevData &, cdevData *\051 :{virtual} int) 189 156.28 T +(sendNoBlock \050cdevData *, cdevData &\051 :{virtual} int) 189 145.28 T +(sendNoBlock \050cdevData *, cdevData *\051 :{virtual} int) 189 134.28 T +(sendCallback \050cdevData &, cdevCallback &\051 :{virtual} int) 189 123.28 T +(sendCallback \050cdevData *, cdevCallback &\051 :{virtual} int) 189 112.28 T +(className \050void\051 :{virtual} char *) 189 101.28 T +162 92.14 540 413 R +1 H +0 Z +N +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "12" 17 +%%Page: "11" 18 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. cde) 385.44 739 T +(vGr) 409.69 739 T +(pCollectionRequest Class Design) 424.46 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(11) 546.88 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 14 Q +0 X +0 0 0 1 0 0 0 K +(3.) 159.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180 710.67 T +(vGrpCollectionRequest Class Design) 203.91 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Purpose of the) 72 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Class) 72 661.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.19 (The cde) 180 673.33 P +0.19 (vGr) 216.02 673.33 P +0.19 (pCollectionRequest class is used when the list of de) 232.43 673.33 P +0.19 (vices will be ser) 463.77 673.33 P +0.19 (viced) 534.66 673.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.2 (b) 180 661.33 P +1.2 (y more than one cde) 185.36 661.33 P +1.2 (vSer) 281.02 661.33 P +1.2 (vice) 301.88 661.33 P +1.2 (. This class will create and maintain a list of ser) 319.51 661.33 P +1.2 (vice) 540.22 661.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.71 (speci\336c cde) 180 649.33 P +2.71 (vCollectionRequest objects and will compile the results into a single) 234.65 649.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180 637.33 T +(vData object that will be retur) 195.82 637.33 T +(ned to the caller) 325.01 637.33 T +(.) 395.66 637.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 5: Object Inher) 180 621 T +(itance Hier) 269.68 621 T +(arch) 312.6 621 T +(y of the cde) 329.83 621 T +(vGr) 376.09 621 T +(pCollectionRequest Class) 390.86 621 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Requirements of) 72 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the Class) 72 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(\245) 180 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.33 (This class will break the list of de) 198 396.33 P +1.33 (vices into g) 352.61 396.33 P +1.33 (roups that will be associated with) 405.18 396.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(individual ser) 198 384.33 T +(vices) 256.65 384.33 T +(.) 279.28 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.08 (A ser) 198 360.33 P +0.08 (vice-speci\336c cde) 221.72 360.33 P +0.08 (vCollectionRequest will be created and maintained f) 294.85 360.33 P +0.08 (or each) 524.57 360.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(of the individual g) 198 348.33 T +(roups of de) 275.72 348.33 T +(vices) 325.45 348.33 T +(.) 348.08 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.56 (The methods send, sendNoBloc) 198 324.33 P +0.56 (k and sendCallbac) 341.75 324.33 P +0.56 (k will be pro) 424.92 324.33 P +0.56 (vided to allo) 479.23 324.33 P +0.56 (w the) 533.54 324.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(message to be tr) 198 312.33 T +(ansmitted to all of the embedded collections) 272.38 312.33 T +(.) 466.77 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.48 (The send and sendNoBloc) 198 288.33 P +2.48 (k methods will utiliz) 323.1 288.33 P +2.48 (e the sendCallbac) 415.97 288.33 P +2.48 (k method to) 500.78 288.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.79 (tr) 198 276.33 P +2.79 (ansmit messages) 204.01 276.33 P +2.79 (. This will reduce the amount of code that is required to) 284.45 276.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(perf) 198 264.33 T +(or) 214.93 264.33 T +(m message tr) 224.07 264.33 T +(ansmission.) 284.54 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.46 (The class will collect all of the data from the ser) 198 240.33 P +1.46 (vice-speci\336c collections into a) 422.46 240.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.4 (single cde) 198 228.33 P +0.4 (vData object that will be pro) 243.12 228.33 P +0.4 (vided to the user) 367.82 228.33 P +0.4 (. The \322) 442.46 228.33 P +3 F +0.4 (resultCode) 472.17 228.33 P +0 F +0.4 (\323 tag will) 520.52 228.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.02 (contain an arr) 198 216.33 P +1.02 (a) 261.08 216.33 P +1.02 (y of completion codes that will indicate the completion status f) 266.33 216.33 P +1.02 (or) 549.11 216.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(each de) 198 204.33 T +(vice/message request.) 233.28 204.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 180.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.45 (The cde) 198 180.33 P +1.45 (vGr) 235.28 180.33 P +1.45 (pCollectionRequest object will maintain order inf) 251.69 180.33 P +1.45 (or) 471.48 180.33 P +1.45 (mation about the) 480.61 180.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.97 (individual de) 198 168.33 P +0.97 (vices that e) 254.25 168.33 P +0.97 (xist in the v) 306.48 168.33 P +0.97 (ar) 359.17 168.33 P +0.97 (ious ser) 368.21 168.33 P +0.97 (vice-speci\336c collections) 404.49 168.33 P +0.97 (. Resultant) 509.23 168.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.07 (data items will be placed in the correct order in the cde) 198 156.33 P +0.07 (vData item that is retur) 440.21 156.33 P +0.07 (ned) 541.32 156.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(to the caller) 198 144.33 T +(.) 249.19 144.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.5 (If the data arr) 198 120.33 P +0.5 (a) 258.88 120.33 P +0.5 (ys that are retur) 264.14 120.33 P +0.5 (ned b) 335.91 120.33 P +0.5 (y m) 361.23 120.33 P +0.5 (ultiple collections are not homogeneous) 377.74 120.33 P +0.5 (,) 555.22 120.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the data type will be promoted in such a w) 198 108.33 T +(a) 384.05 108.33 T +(y as to ensure that no data is lost.) 389.31 108.33 T +0 0 0 1 0 0 0 K +180 422 558 680 C +0 0 0 1 0 0 0 K +180 422 558 618 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +275.52 589 406.95 609 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +1 10 Q +(c) 280.83 596.86 T +(lass cde) 286.19 596.86 T +(vRequestObject) 325.51 596.86 T +263.96 531 418.51 551 R +7 X +V +0 X +N +(c) 272.22 538.86 T +(lass cde) 277.58 538.86 T +(vCollectionRequest) 316.9 538.86 T +341.23 589 341.23 551.14 2 L +N +341.59 578.64 332.66 561.5 349.8 561.5 3 Y +7 X +V +0 X +N +259.35 473 423.11 493 R +7 X +V +0 X +N +(c) 263.33 480.86 T +(lass cde) 268.69 480.86 T +(vGrpCollectionRequest) 308.01 480.86 T +341.23 531 341.23 493.14 2 L +N +341.59 520.64 332.66 503.5 349.8 503.5 3 Y +7 X +V +0 X +N +342.35 454.29 337.35 463.57 342.35 472.86 347.35 463.57 4 Y +N +363.58 431.14 495.01 451.14 R +7 X +V +0 X +N +(cde) 370.74 438.99 T +(vCollectionRequest *) 387.82 438.99 T +342.35 454.28 342.35 442.14 363.78 442.14 3 L +N +90 450 2.86 3.21 360.78 442.64 G +90 450 2.86 3.21 360.78 442.64 A +180 422 558 618 R +1 H +0 Z +N +180 422 558 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "11" 18 +%%Page: "10" 19 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. cde) 54 739 T +(vCollectionRequest Class Design) 78.25 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(10) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(\245) 261.29 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.15 (De) 279.29 713.33 P +0.15 (vice/message combinations that are not associated with) 291.77 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(a ser) 279.29 701.33 T +(vice will be ignored.) 301.82 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 261.29 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4.73 (If none of the de) 279.29 677.33 P +4.73 (vice/message combinations can be) 370.19 677.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.41 (associated with a ser) 279.29 665.33 P +1.41 (vice) 377.19 665.33 P +1.41 (, then an error message will be) 394.82 665.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(gener) 279.29 653.33 T +(ated and NULL will be retur) 304.76 653.33 T +(ned.) 426.17 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(c) 162 629.33 T +(lassName) 167.36 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(char * className \050v) 261.29 629.33 T +(oid\051;) 350.5 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +12.7 (This method retur) 261.29 612.33 P +12.7 (ns the name of the class;) 365.31 612.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.96 (\322) 261.43 600.33 P +3 F +2.96 (cde) 264.76 600.33 P +2.96 (vCollectionRequest) 280.58 600.33 P +0 F +2.96 (\323. If the de) 366.72 600.33 P +2.96 (v) 420.33 600.33 P +2.96 (eloper inher) 425.08 600.33 P +2.96 (its a ser) 480.99 600.33 P +2.96 (vice) 522.22 600.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.26 (speci\336c cde) 261.43 588.33 P +-0.26 (vCollectionRequest, then this method should not be) 313.11 588.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(altered or o) 261.43 576.33 T +(v) 311.86 576.33 T +(err) 316.61 576.33 T +(idden.) 328.98 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "10" 19 +%%Page: "9" 20 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. cde) 400.72 739 T +(vCollectionRequest Class Design) 424.96 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(9) 552.44 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(Method Over) 72 713.33 T +(vie) 133.22 713.33 T +(w) 146.97 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(of the Class) 72 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(constructor) 180 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 279.29 713.33 T +(vCollectionRequest\050) 295.11 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(char **de) 395.86 713.33 T +(vices) 436.69 713.33 T +(, int nDe) 459.32 713.33 T +(vices) 496.26 713.33 T +(,) 518.89 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(char * msg, cde) 395.86 701.33 T +(vSystem & system\051;) 465.03 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.08 (This is the constr) 279.29 684.33 P +1.08 (uctor f) 358.26 684.33 P +1.08 (or the cde) 386.83 684.33 P +1.08 (vCollectionRequest class) 433.17 684.33 P +1.08 (. It) 545.8 684.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(has the f) 279.43 672.33 T +(ollo) 317.49 672.33 T +(wing proper) 332.9 672.33 T +(ties) 385.54 672.33 T +(.) 400.95 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 654.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.1 (This method is) 297.29 654.33 P +2 F +0.1 (pr) 365.39 654.33 P +0.1 (otected) 375.19 654.33 P +0 F +0.1 ( to pre) 410.75 654.33 P +0.1 (v) 439 654.33 P +0.1 (ent the direct instantiation) 443.75 654.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.95 (of ne) 297.29 642.33 P +3.95 (w) 323.27 642.33 P +3 F +3.95 (cde) 337.22 642.33 P +3.95 (vCollectionRequests) 353.04 642.33 P +0 F +3.95 (. Ne) 444.03 642.33 P +3.95 (w instances of the) 466.12 642.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +2.4 (cde) 297.29 630.33 P +2.4 (vCollectionRequest objects are) 313.11 630.33 P +0 F +2.4 (created b) 460.93 630.33 P +2.4 (y using the) 504.83 630.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +1.63 (attachPtr) 297.29 618.33 P +0 F +1.63 ( or) 337.31 618.33 P +3 F +1.63 (attachRef) 355.02 618.33 P +0 F +1.63 ( method of the) 397.82 618.33 P +3 F +1.63 (cde) 471.04 618.33 P +1.63 (vRequestObject) 486.86 618.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.62 (class which will call the local) 297.29 606.33 P +3 F +0.62 (attachPtr) 429.35 606.33 P +0 F +0.62 ( method to create a) 469.37 606.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ne) 297.29 594.33 T +(w object if necessar) 308.21 594.33 T +(y) 396.32 594.33 T +(.) 400.32 594.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.74 (The constr) 297.29 576.33 P +0.74 (uctor is called b) 345.42 576.33 P +0.74 (y the cde) 416.92 576.33 P +0.74 (vCollection object and) 458.69 576.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.22 (is pro) 297.29 564.33 P +2.22 (vided with a list and count of de) 323.8 564.33 P +2.22 (vices that will be) 478.55 564.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.06 (included in the collection and the message that will be sent) 297.29 552.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(to them.) 297.29 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 522.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +6.39 (The) 297.29 522.33 P +3 F +6.39 (cde) 323.68 522.33 P +6.39 (vSystem) 339.5 522.33 P +0 F +6.39 ( ref) 377.84 522.33 P +6.39 (erence that is pro) 398.38 522.33 P +6.39 (vided is the) 494.65 522.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +1.7 (cde) 297.29 510.33 P +1.7 (vSystem) 313.11 510.33 P +0 F +1.7 ( instance that will be used to) 351.45 510.33 P +3 F +1.7 (poll) 491.77 510.33 P +0 F +1.7 (,) 507.33 510.33 P +3 F +1.7 (pend) 514.6 510.33 P +0 F +1.7 ( and) 536.84 510.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(\337ush) 297.29 498.33 T +0 F +( the) 318.41 498.33 T +3 F +(cde) 337.87 498.33 T +(vCollectionRequest) 353.69 498.33 T +0 F +( object.) 439.83 498.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(destructor) 180 474.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(vir) 279.29 474.33 T +(tual ~cde) 290.24 474.33 T +(vCollectionRequest \050v) 330.8 474.33 T +(oid\051;) 427.8 474.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +-0.11 (This is the destr) 279.29 457.33 P +-0.11 (uctor f) 349.7 457.33 P +-0.11 (or a cde) 377.08 457.33 P +-0.11 (vCollectionRequest object. It has) 412.7 457.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the f) 279.43 445.33 T +(ollo) 298.59 445.33 T +(wing proper) 314 445.33 T +(ties) 366.64 445.33 T +(.) 382.05 445.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 421.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +14.64 (This method is protected to pre) 297.29 421.33 P +14.64 (v) 508.03 421.33 P +14.64 (ent the) 512.78 421.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +0.54 (cde) 297.29 409.33 P +0.54 (vCollectionRequest) 313.11 409.33 P +0 F +0.54 ( object from being destro) 399.25 409.33 P +0.54 (y) 511.17 409.33 P +0.54 (ed b) 515.97 409.33 P +0.54 (y the) 535.78 409.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.29 (application. This method should only be called b) 297.29 397.33 P +3.29 (y the) 533.03 397.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 297.29 385.33 T +(vSystem) 313.11 385.33 T +0 F +( object when the application is ter) 351.45 385.33 T +(minating.) 499.55 385.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 361.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.07 (Because the) 297.29 361.33 P +3 F +-0.07 (cde) 355.51 361.33 P +-0.07 (vCollectionRequest) 371.33 361.33 P +0 F +-0.07 ( object will nor) 457.47 361.33 P +-0.07 (mally be) 520.84 361.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.79 (ref) 297.29 349.33 P +0.79 (erred to as a) 308.66 349.33 P +3 F +0.79 (cde) 370.72 349.33 P +0.79 (vRequestObject) 386.54 349.33 P +0 F +0.79 ( object, this destr) 457.68 349.33 P +0.79 (uctor) 535.77 349.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.29 (is vir) 297.29 337.33 P +2.29 (tual to ensure that the) 320.53 337.33 P +2 F +2.29 (\324most senior\325) 431.5 337.33 P +0 F +2.29 ( destr) 496.03 337.33 P +2.29 (uctor is) 523.48 337.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(called \336rst.) 297.29 325.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(attac) 180 301.33 T +(hPtr) 203.24 301.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 279.29 301.33 T +(vCollectionRequest * attachPtr) 295.11 301.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\050) 299.29 289.33 T +(cde) 302.62 289.33 T +(vCollection &col, char *msg, cde) 318.44 289.33 T +(vSystem &sys\051;) 461.52 289.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.3 (This method is used b) 279.29 272.33 P +1.3 (y the cde) 382.1 272.33 P +1.3 (vCollection object to obtain a) 424.97 272.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ne) 279.43 260.33 T +(w cde) 290.35 260.33 T +(vCollectionRequest object.) 316.17 260.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 236.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.23 (This method will obtain a cop) 297.29 236.33 P +1.23 (y of the de) 432.09 236.33 P +1.23 (vice names from) 482.18 236.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (the cde) 297.29 224.33 P +2.12 (vCollection object and will poll the cde) 331.9 224.33 P +2.12 (vDirector) 512.7 224.33 P +2.12 (y) 553 224.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +5.22 (object to deter) 297.29 212.33 P +5.22 (mine which ser) 371.34 212.33 P +5.22 (vice each of them is) 448.76 212.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(associated with.) 297.29 200.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 176.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.32 (If the de) 297.29 176.33 P +0.32 (vices are all from a single ser) 333.77 176.33 P +0.32 (vice) 465.49 176.33 P +0.32 (, this method will) 483.12 176.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(retur) 297.29 164.33 T +(n a ser) 318.1 164.33 T +(vice speci\336c collection request object.) 348.97 164.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 140.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.27 (If the de) 297.29 140.33 P +-0.27 (vices are from a v) 332.58 140.33 P +-0.27 (ar) 410.14 140.33 P +-0.27 (iety of ser) 419.18 140.33 P +-0.27 (vices) 462.28 140.33 P +-0.27 (, this method will) 484.91 140.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +5.63 (retur) 297.29 128.33 P +5.63 (n a cde) 318.1 128.33 P +5.63 (vGr) 361.85 128.33 P +5.63 (pCollectionRequest that contains the) 378.26 128.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ser) 297.29 116.33 T +(vice speci\336c collection request objects) 311.48 116.33 T +(.) 480.28 116.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "9" 20 +%%Page: "8" 21 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. cde) 54 739 T +(vCollectionRequest Class Design) 78.25 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(8) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 14 Q +0 X +0 0 0 1 0 0 0 K +(2.) 141.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 162 710.67 T +(vCollectionRequest Class Design) 185.91 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Purpose of the) 54 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Class) 54 661.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.16 (The cde) 162 673.33 P +4.16 (vCollectionRequest class is an abstr) 201.99 673.33 P +4.16 (act base class from which other) 379.14 673.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.99 (cde) 162 661.33 P +0.99 (vCollectionRequest objects a re der) 177.82 661.33 P +0.99 (iv) 339.77 661.33 P +0.99 (ed. It pro) 346.74 661.33 P +0.99 (vides a protected constr) 388.04 661.33 P +0.99 (uctor and) 497.32 661.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.16 (destr) 162 649.33 P +-0.16 (uctor that are used to initializ) 184.38 649.33 P +-0.16 (e its inter) 310.7 649.33 P +-0.16 (nals) 351.19 649.33 P +-0.16 (, ho) 369.38 649.33 P +-0.16 (w) 385.75 649.33 P +-0.16 (e) 392.87 649.33 P +-0.16 (v) 398.13 649.33 P +-0.16 (er) 402.88 649.33 P +-0.16 (, the pr) 411.27 649.33 P +-0.16 (imar) 442.23 649.33 P +-0.16 (y mechanism that) 461.96 649.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(is used to obtain a cde) 162 637.33 T +(vCollectionRequest object is the) 261.76 637.33 T +3 F +(attachPtr) 406.82 637.33 T +0 F +( method.) 446.84 637.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 3: Object Inher) 162 621 T +(itance Hier) 251.68 621 T +(arch) 294.6 621 T +(y of the cde) 311.83 621 T +(vCollectionRequest Class) 358.09 621 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Requirements of) 54 496.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the Class) 54 484.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(\245) 162 496.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.96 (This class will pro) 180 496.33 P +2.96 (vide a mechanism f) 267.07 496.33 P +2.96 (or the caller to obtain a pointer to a) 361.79 496.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.62 (cde) 180 484.33 P +2.62 (vCollectionRequest der) 195.82 484.33 P +2.62 (iv) 301.96 484.33 P +2.62 (ed object that can be used as an interf) 308.93 484.33 P +2.62 (ace to a) 499.17 484.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(collection of de) 180 472.33 T +(vices) 246.4 472.33 T +(.) 269.03 472.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 448.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The de) 180 448.33 T +(vice/message combinations ma) 210.83 448.33 T +(y f) 350.02 448.33 T +(all into a v) 360.28 448.33 T +(ar) 405.05 448.33 T +(iety of ser) 414.09 448.33 T +(vices) 457.74 448.33 T +(.) 480.37 448.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 424.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.11 (The der) 180 424.33 P +-0.11 (iv) 214.5 424.33 P +-0.11 (ed class will pro) 221.47 424.33 P +-0.11 (vide def) 291.57 424.33 P +-0.11 (ault suppor) 326.19 424.33 P +-0.11 (t f) 375.95 424.33 P +-0.11 (or the methods send, sendCallbac) 383.89 424.33 P +-0.11 (k) 535 424.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(and sendNoBloc) 180 412.33 T +(k.) 253.17 412.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 388.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.84 (The send and sendNoBloc) 180 388.33 P +1.84 (k methods will rely on the sendCallbac) 303.16 388.33 P +1.84 (k method to) 484.07 388.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(tr) 180 376.33 T +(ansmit their request and receiv) 186.01 376.33 T +(e a reply) 322.48 376.33 T +(.) 359.83 376.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 352.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.06 (Each data item that is retur) 180 352.33 P +0.06 (ned b) 300.07 352.33 P +0.06 (y the individual de) 324.95 352.33 P +0.06 (vices m) 404.88 352.33 P +0.06 (ust be scalar in nature) 438.74 352.33 P +0.06 (.) 537.22 352.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Non-scalar results retur) 180 340.33 T +(ned b) 284.16 340.33 T +(y a de) 308.98 340.33 T +(vice will be discarded.) 335.92 340.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 316.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.35 (If the scalar data that is retur) 180 316.33 P +1.35 (ned b) 315.08 316.33 P +1.35 (y m) 341.25 316.33 P +1.35 (ultiple de) 358.61 316.33 P +1.35 (vices is not homogeneous) 399.68 316.33 P +1.35 (, the) 519.19 316.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(data type will be promoted in such a w) 180 304.33 T +(a) 349.37 304.33 T +(y as to ensure that no data is lost.) 354.63 304.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 280.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.19 (A special tagged data item, \322resultCode\323 will be added to the cde) 180 280.33 P +-0.19 (vGlobalT) 463.83 280.33 P +-0.19 (agT) 502.64 280.33 P +-0.19 (ab) 518.67 280.33 P +-0.19 (le) 529.59 280.33 P +-0.19 (.) 537.22 280.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.34 (This data item will hold an ordered arr) 180 268.33 P +2.34 (a) 363.53 268.33 P +2.34 (y of the completion codes that w) 368.79 268.33 P +2.34 (ere) 525.55 268.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(retur) 180 256.33 T +(ned to the callbac) 200.81 256.33 T +(k function in the) 278.99 256.33 T +3 F +(status) 351.81 256.33 T +0 F +( par) 378.49 256.33 T +(ameter) 395.62 256.33 T +(.) 426.24 256.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 4: Object Model of the cde) 162 223 T +(vCollectionRequest Class) 297.3 223 T +0 0 0 1 0 0 0 K +162 522 540 680 C +0 0 0 1 0 0 0 K +162 522 540 618 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +285.86 589 417.29 609 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +1 10 Q +(c) 291.17 596.86 T +(lass cde) 296.53 596.86 T +(vRequestObject) 335.85 596.86 T +273.73 531 428.28 551 R +7 X +V +0 X +N +(c) 281.98 538.86 T +(lass cde) 287.35 538.86 T +(vCollectionRequest) 326.67 538.86 T +350.64 589 350.64 551.14 2 L +N +350.99 578.64 342.07 561.5 359.21 561.5 3 Y +7 X +V +0 X +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +162 522 540 618 R +1 H +0 Z +N +162 522 540 680 C +0 0 612 792 C +162 81 540 503 C +162 83.43 540 220 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +169.43 87.86 533 216.43 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +1 10 Q +(c) 278.27 205.88 T +(lass cde) 283.63 205.88 T +(vCollectionRequest) 322.95 205.88 T +169.14 203.14 532.72 203.14 2 L +N +4 9 Q +(attributes:) 179.14 194.28 T +5 F +(RESULT_CODE_TAG: int) 191.15 183.28 T +4 F +(methods:) 179.14 161.28 T +5 F +(cdevCollectionRequest \050char **, int, char *, cdevSystem &\051) 191.15 150.28 T +(~cdevCollectionRequest \050void\051 :{virtual}) 191.15 139.28 T +-0.31 (attachPtr \050...\051 :{static} cdevCollectionRequest) 191.15 117.28 P +(*) 191.15 106.28 T +(className \050void\051 :{virtual} char *) 191.15 95.28 T +162 83.43 540 220 R +1 H +0 Z +N +162 81 540 503 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "8" 21 +%%Page: "7" 22 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. cde) 434.23 739 T +(vCollection Class Design) 458.48 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(7) 552.44 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.16 (If the remo) 297.29 713.33 P +2.16 (v) 349.26 713.33 P +2.16 (e method f) 354.01 713.33 P +2.16 (ails to remo) 405.27 713.33 P +2.16 (v) 461.12 713.33 P +2.16 (e an) 465.87 713.33 P +2.16 (y of the de) 487.34 713.33 P +2.16 (vice) 540.22 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.89 (name str) 297.29 701.33 P +1.89 (ings from the list, then the error code that w) 338.23 701.33 P +1.89 (as) 547.44 701.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.74 (gener) 297.29 689.33 P +2.74 (ated b) 322.76 689.33 P +2.74 (y the call to) 353.1 689.33 P +3 F +2.74 (remo) 417.43 689.33 P +2.74 (v) 440.06 689.33 P +2.74 (e \050char * name\051) 444.81 689.33 P +0 F +2.74 ( will be) 521.95 689.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(retur) 297.29 677.33 T +(ned.) 318.1 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.52 (If an error occurs while remo) 297.29 653.33 P +0.52 (ving a name from the list, the) 426.46 653.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.01 (method will contin) 297.29 641.33 P +-0.01 (ue with the ne) 376.63 641.33 P +-0.01 (xt name until the last name) 438.56 641.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(is reached.) 297.29 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.35 (If no errors occur while remo) 297.29 605.33 P +0.35 (ving names from the list, then) 425.61 605.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(CDEV_SUCCESS) 297.29 593.33 T +0 F +( will be retur) 378.97 593.33 T +(ned to the caller) 433.12 593.33 T +(.) 503.77 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(remo) 180 569.33 T +(ve) 204.25 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int remo) 279.29 569.33 T +(v) 315.26 569.33 T +(e \050int n) 320.01 569.33 T +(um, char **names\051;) 350.48 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +2.71 (This method will attempt to remo) 279.29 552.33 P +2.71 (v) 437.2 552.33 P +2.71 (e) 441.95 552.33 P +3 F +2.71 (n) 453 552.33 P +2.71 (um) 458.46 552.33 P +0 F +2.71 ( de) 472.35 552.33 P +2.71 (vice names as) 488.66 552.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.04 (speci\336ed in the) 279.43 540.33 P +3 F +2.04 (names) 355.02 540.33 P +0 F +2.04 ( arr) 385.04 540.33 P +2.04 (a) 401.97 540.33 P +2.04 (y from the list using the) 407.23 540.33 P +3 F +2.04 (remo) 525.06 540.33 P +2.04 (v) 547.69 540.33 P +2.04 (e) 552.44 540.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.23 (\050char *name\051) 279.43 528.33 P +0 F +1.23 ( method of the) 338.45 528.33 P +3 F +1.23 (cde) 410.1 528.33 P +1.23 (vCollection) 425.92 528.33 P +0 F +1.23 (. This method has) 474.82 528.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.15 (the same proper) 279.43 516.33 P +1.15 (ties as the) 354.94 516.33 P +3 F +1.15 (remo) 406.75 516.33 P +1.15 (v) 429.38 516.33 P +1.15 (e \050int n) 434.13 516.33 P +1.15 (um, char * name) 466.89 516.33 P +1.15 (,...\051) 543.55 516.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(method.) 279.43 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(remo) 180 480.33 T +(ve) 204.25 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int remo) 279.29 480.33 T +(v) 315.26 480.33 T +(e \050char **names\051;) 320.01 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +3.01 (This method will attempt to remo) 279.29 463.33 P +3.01 (v) 438.68 463.33 P +3.01 (e each de) 443.43 463.33 P +3.01 (vice name as) 493.07 463.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.32 (speci\336ed in the NULL ter) 279.43 451.33 P +2.32 (minated) 398.44 451.33 P +3 F +2.32 (names) 439.1 451.33 P +0 F +2.32 ( arr) 469.11 451.33 P +2.32 (a) 486.33 451.33 P +2.32 (y from the list) 491.59 451.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.94 (using the) 279.43 439.33 P +3 F +0.94 (remo) 324.66 439.33 P +0.94 (v) 347.29 439.33 P +0.94 (e \050char *name\051) 352.04 439.33 P +0 F +0.94 ( method of the) 420.05 439.33 P +3 F +0.94 (cde) 490.5 439.33 P +0.94 (vCollection) 506.32 439.33 P +0 F +0.94 (.) 555.22 439.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.58 (This method has the same proper) 279.43 427.33 P +0.58 (ties as the) 432.23 427.33 P +3 F +0.58 (remo) 482.32 427.33 P +0.58 (v) 504.95 427.33 P +0.58 (e \050int n) 509.7 427.33 P +0.58 (um,) 541.33 427.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(char * name) 279.43 415.33 T +(,...\051) 333.19 415.33 T +0 F +( method.) 347.64 415.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(remo) 180 374.33 T +(veReg) 204.25 374.33 T +(e) 234.36 374.33 T +(xp) 239.77 374.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int remo) 279.29 374.33 T +(v) 315.26 374.33 T +(eRege) 320.01 374.33 T +(xp \050char *rege) 349.17 374.33 T +(xp\051;) 411.67 374.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +-0.03 (This method will quer) 279.29 357.33 P +-0.03 (y the system name ser) 373.98 357.33 P +-0.03 (v) 474.76 357.33 P +-0.03 (er f) 479.51 357.33 P +-0.03 (or the list of all) 493.64 357.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.89 (names in the) 279.43 345.33 P +3 F +1.89 (cde) 345.14 345.33 P +1.89 (vDirector) 360.95 345.33 P +1.89 (y) 401.26 345.33 P +0 F +1.89 ( that match the speci\336ed regular) 406.26 345.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.57 (e) 279.43 333.33 P +1.57 (xpression. the arr) 284.69 333.33 P +1.57 (a) 364.98 333.33 P +1.57 (y of names will be remo) 370.24 333.33 P +1.57 (v) 482.96 333.33 P +1.57 (ed from the list) 487.71 333.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.95 (using the) 279.43 321.33 P +3 F +1.95 (remo) 326.69 321.33 P +1.95 (v) 349.32 321.33 P +1.95 (e \050int n) 354.07 321.33 P +1.95 (um, char ** names\051) 388.45 321.33 P +0 F +1.95 (method and the) 484.61 321.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(result of this oper) 279.43 309.33 T +(ation will be retur) 356.03 309.33 T +(ned.) 431.86 309.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "7" 22 +%%Page: "6" 23 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. cde) 54 739 T +(vCollection Class Design) 78.25 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(6) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(ad) 162 713.33 T +(d) 173.57 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int add \050int n) 261.29 713.33 T +(um, char **names\051;) 316.22 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.46 (This method will attempt to add) 261.29 696.33 P +3 F +1.46 (n) 411.2 696.33 P +1.46 (um) 416.65 696.33 P +0 F +1.46 ( de) 430.55 696.33 P +1.46 (vice names from the) 445.6 696.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +0.9 (names) 261.43 684.33 P +0 F +0.9 ( arr) 291.44 684.33 P +0.9 (a) 307.25 684.33 P +0.9 (y to the list using the) 312.51 684.33 P +3 F +0.9 (add \050char *name\051) 411.88 684.33 P +0 F +0.9 ( method of) 490.94 684.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.6 (the) 261.43 672.33 P +3 F +1.6 (cde) 279.71 672.33 P +1.6 (vCollection) 295.53 672.33 P +0 F +1.6 (. This method has the same proper) 344.43 672.33 P +1.6 (ties as) 509.5 672.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the) 261.43 660.33 T +3 F +(add \050int n) 278.11 660.33 T +(um, char * \336rstname) 319.7 660.33 T +(,...\051) 409.02 660.33 T +0 F +( method.) 423.47 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(ad) 162 636.33 T +(d) 173.57 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int add \050char **names\051;) 261.29 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.72 (This method will attempt to add each de) 261.29 619.33 P +1.72 (vice name from the) 449.8 619.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.36 (NULL ter) 261.43 607.33 P +1.36 (minated) 303.05 607.33 P +3 F +1.36 (names) 342.76 607.33 P +0 F +1.36 ( arr) 372.77 607.33 P +1.36 (a) 389.03 607.33 P +1.36 (y to the list using the) 394.29 607.33 P +3 F +1.36 (add \050char) 496.4 607.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.34 (*name\051) 261.43 595.33 P +0 F +2.34 ( method of the) 293.66 595.33 P +3 F +2.34 (cde) 369.75 595.33 P +2.34 (vCollection) 385.57 595.33 P +0 F +2.34 (. This method has the) 434.47 595.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.15 (same proper) 261.43 583.33 P +3.15 (ties as the) 321.11 583.33 P +3 F +3.15 (add \050int n) 378.91 583.33 P +3.15 (um, char * \336rstname) 426.79 583.33 P +3.15 (,...\051) 525.55 583.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(method.) 261.43 571.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(ad) 162 547.33 T +(dReg) 173.57 547.33 T +(e) 198.67 547.33 T +(xp) 204.08 547.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int addRege) 261.29 547.33 T +(xp \050char *rege) 314.91 547.33 T +(xp\051;) 377.41 547.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +-0.03 (This method will quer) 261.29 530.33 P +-0.03 (y the system name ser) 355.98 530.33 P +-0.03 (v) 456.76 530.33 P +-0.03 (er f) 461.51 530.33 P +-0.03 (or the list of all) 475.64 530.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.89 (names in the) 261.43 518.33 P +3 F +1.89 (cde) 327.14 518.33 P +1.89 (vDirector) 342.95 518.33 P +1.89 (y) 383.26 518.33 P +0 F +1.89 ( that match the speci\336ed regular) 388.26 518.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.03 (e) 261.43 506.33 P +1.03 (xpression. the arr) 266.69 506.33 P +1.03 (a) 345.91 506.33 P +1.03 (y of names will be added to the list using) 351.17 506.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.48 (the) 261.43 494.33 P +3 F +0.48 (add \050int n) 278.59 494.33 P +0.48 (um, char ** names\051) 321.14 494.33 P +0 F +0.48 (method and the result of this) 411.42 494.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(oper) 261.43 482.33 T +(ation will be retur) 281.34 482.33 T +(ned.) 357.17 482.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(remo) 162 458.33 T +(ve) 186.25 458.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int remo) 261.29 458.33 T +(v) 297.26 458.33 T +(e \050char *name\051;) 302.01 458.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.43 (This method will remo) 261.29 441.33 P +0.43 (v) 359.67 441.33 P +0.43 (e the speci\336ed de) 364.42 441.33 P +0.43 (vice name from list of) 443.8 441.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.94 (de) 261.43 429.33 P +0.94 (vice names that is stored in the) 272.25 429.33 P +3 F +0.94 (cde) 419.48 429.33 P +0.94 (vCollection) 435.3 429.33 P +0 F +0.94 ( object. This) 484.2 429.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(method has the f) 261.43 417.33 T +(ollo) 335.62 417.33 T +(wing proper) 351.03 417.33 T +(ties) 403.67 417.33 T +(.) 419.08 417.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 261.29 393.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.09 (If a) 279.29 393.33 P +3 F +0.09 (cde) 296.14 393.33 P +0.09 (vCollectionRequest) 311.96 393.33 P +0 F +0.09 ( object has been instantiated f) 398.1 393.33 P +0.09 (or) 531.11 393.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.12 (this) 279.29 381.33 P +3 F +1.12 (cde) 298.75 381.33 P +1.12 (vCollection) 314.57 381.33 P +0 F +1.12 ( de) 363.47 381.33 P +1.12 (vice) 378.19 381.33 P +1.12 (, then the oper) 395.82 381.33 P +1.12 (ation will f) 463.58 381.33 P +1.12 (ail and) 509.42 381.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(CDEV_INV) 279.29 369.33 T +(ALIDOP) 328.5 369.33 T +0 F +( will be retur) 366.28 369.33 T +(ned.) 420.43 369.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 261.29 345.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.46 (If the name pro) 279.29 345.33 P +0.46 (vided is NULL or empty) 347.78 345.33 P +0.46 (, then the oper) 452.55 345.33 P +0.46 (ation) 518.32 345.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(will f) 279.29 333.33 T +(ail and) 298.43 333.33 T +1 F +(CDEV_W) 330.67 333.33 T +(ARNING) 372.85 333.33 T +0 F +( will be retur) 412.29 333.33 T +(ned.) 466.44 333.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 261.29 309.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.14 (If the name speci\336ed does not e) 279.29 309.33 P +2.14 (xist in the collection of) 433.6 309.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.29 (names) 279.29 297.33 P +1.29 (, then the oper) 309.15 297.33 P +1.29 (ation will f) 377.4 297.33 P +1.29 (ail and) 423.57 297.33 P +1 F +1.29 (CDEV_W) 458.38 297.33 P +1.29 (ARNING) 500.56 297.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(will be retur) 279.29 285.33 T +(ned.) 330.66 285.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 261.29 261.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.16 (If the name speci\336ed e) 279.29 261.33 P +3.16 (xists in the list, then it will be) 392.25 261.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(remo) 279.29 249.33 T +(v) 301.92 249.33 T +(ed and) 306.67 249.33 T +1 F +(CDEV_SUCCESS) 340.03 249.33 T +0 F +( will be retur) 421.71 249.33 T +(ned.) 475.86 249.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(remo) 162 225.33 T +(ve) 186.25 225.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int remo) 261.29 225.33 T +(v) 297.26 225.33 T +(e \050int n) 302.01 225.33 T +(um, char *name) 332.48 225.33 T +(,...\051;) 402.91 225.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.08 (This method will attempt to remo) 261.29 208.33 P +1.08 (v) 411.04 208.33 P +1.08 (e a list of n) 415.79 208.33 P +1.08 (um names from) 468.38 208.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the) 261.43 196.33 T +3 F +(cde) 278.11 196.33 T +(vCollection) 293.93 196.33 T +0 F +(. This method has the f) 342.83 196.33 T +(ollo) 444.25 196.33 T +(wing proper) 459.66 196.33 T +(ties) 512.3 196.33 T +(.) 527.71 196.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 261.29 172.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.09 (If a) 279.29 172.33 P +3 F +0.09 (cde) 296.14 172.33 P +0.09 (vCollectionRequest) 311.96 172.33 P +0 F +0.09 ( object has been instantiated f) 398.1 172.33 P +0.09 (or) 531.11 172.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.12 (this) 279.29 160.33 P +3 F +1.12 (cde) 298.75 160.33 P +1.12 (vCollection) 314.57 160.33 P +0 F +1.12 ( de) 363.47 160.33 P +1.12 (vice) 378.19 160.33 P +1.12 (, then the oper) 395.82 160.33 P +1.12 (ation will f) 463.58 160.33 P +1.12 (ail and) 509.42 160.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(CDEV_INV) 279.29 148.33 T +(ALIDOP) 328.5 148.33 T +0 F +( will be retur) 366.28 148.33 T +(ned.) 420.43 148.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 261.29 124.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.89 (This method will call the) 279.29 124.33 P +3 F +0.89 (remo) 392.65 124.33 P +0.89 (v) 415.28 124.33 P +0.89 (e \050char *name\051) 420.03 124.33 P +0 F +0.89 (method f) 491.61 124.33 P +0.89 (or) 531.11 124.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(each name that is speci\336ed.) 279.29 112.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "6" 23 +%%Page: "5" 24 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. cde) 434.23 739 T +(vCollection Class Design) 458.48 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(5) 552.44 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.51 (When the) 297.29 713.33 P +3 F +0.51 (refCount) 343.89 713.33 P +0 F +0.51 ( proper) 382.24 713.33 P +0.51 (ty is decremented to 0, then the) 414.84 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 297.29 701.33 T +(vCollection) 313.11 701.33 T +0 F +( object will be deleted.) 362.01 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(c) 180 677.33 T +(lassName) 185.36 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(char * className \050v) 279.29 677.33 T +(oid\051;) 368.5 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.41 (This method retur) 279.29 660.33 P +0.41 (ns the name of the class; \322) 358.71 660.33 P +3 F +0.41 (cde) 478.42 660.33 P +0.41 (vCollection) 494.24 660.33 P +0 F +0.41 (\323. If) 543.14 660.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.66 (the de) 279.43 648.33 P +1.66 (v) 308.6 648.33 P +1.66 (eloper inher) 313.35 648.33 P +1.66 (its a ser) 367.96 648.33 P +1.66 (vice speci\336c cde) 406.59 648.33 P +1.66 (vCollection, then) 482.42 648.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(this method should not be altered or o) 279.43 636.33 T +(v) 447.15 636.33 T +(err) 451.9 636.33 T +(idden.) 464.27 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(ad) 180 612.33 T +(d) 191.57 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int add \050char *name\051;) 279.29 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.21 (This method will add the individual name to the list of de) 279.29 595.33 P +1.21 (vice) 540.22 595.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.33 (names that are in the cde) 279.43 583.33 P +2.33 (vCollection. This method has the) 403.62 583.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(f) 279.43 571.33 T +(ollo) 281.91 571.33 T +(wing proper) 297.32 571.33 T +(ties) 349.96 571.33 T +(.) 365.37 571.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 547.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.09 (If a) 297.29 547.33 P +3 F +0.09 (cde) 314.14 547.33 P +0.09 (vCollectionRequest) 329.96 547.33 P +0 F +0.09 ( object has been instantiated f) 416.1 547.33 P +0.09 (or) 549.11 547.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.12 (this) 297.29 535.33 P +3 F +1.12 (cde) 316.75 535.33 P +1.12 (vCollection) 332.57 535.33 P +0 F +1.12 ( de) 381.47 535.33 P +1.12 (vice) 396.19 535.33 P +1.12 (, then the oper) 413.82 535.33 P +1.12 (ation will f) 481.58 535.33 P +1.12 (ail and) 527.42 535.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(CDEV_INV) 297.29 523.33 T +(ALIDOP) 346.5 523.33 T +0 F +( will be retur) 384.28 523.33 T +(ned.) 438.43 523.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 499.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.46 (If the name pro) 297.29 499.33 P +0.46 (vided is NULL or empty) 365.78 499.33 P +0.46 (, then the oper) 470.55 499.33 P +0.46 (ation) 536.32 499.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(will f) 297.29 487.33 T +(ail and) 316.43 487.33 T +1 F +(CDEV_INV) 348.67 487.33 T +(ALIDOP) 397.88 487.33 T +0 F +( will be retur) 435.66 487.33 T +(ned.) 489.81 487.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 463.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.45 (If the name speci\336ed already e) 297.29 463.33 P +2.45 (xists in the collection of) 445.4 463.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.29 (names) 297.29 451.33 P +1.29 (, then the oper) 327.15 451.33 P +1.29 (ation will f) 395.4 451.33 P +1.29 (ail and) 441.57 451.33 P +1 F +1.29 (CDEV_W) 476.38 451.33 P +1.29 (ARNING) 518.56 451.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(will be retur) 297.29 439.33 T +(ned.) 348.66 439.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 415.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.02 (If the name speci\336ed is not already in the list, then the) 297.29 415.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.79 (method will append the de) 297.29 403.33 P +0.79 (vice name to the end of the list) 416.86 403.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(and retur) 297.29 391.33 T +(n) 337.56 391.33 T +1 F +(CDEV_SUCCESS) 345.9 391.33 T +0 F +(.) 427.38 391.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(ad) 180 367.33 T +(d) 191.57 367.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int add \050int n) 279.29 367.33 T +(um, char *\336rstname) 334.22 367.33 T +(,...\051;) 420.76 367.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.93 (This method will attempt to add a list of n) 279.29 350.33 P +1.93 (um names to the) 477.73 350.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 279.43 338.33 T +(vCollection. This method has the f) 295.25 338.33 T +(ollo) 445.57 338.33 T +(wing proper) 460.98 338.33 T +(ties) 513.62 338.33 T +(.) 529.03 338.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 314.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.09 (If a) 297.29 314.33 P +3 F +0.09 (cde) 314.14 314.33 P +0.09 (vCollectionRequest) 329.96 314.33 P +0 F +0.09 ( object has been instantiated f) 416.1 314.33 P +0.09 (or) 549.11 314.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.12 (this) 297.29 302.33 P +3 F +1.12 (cde) 316.75 302.33 P +1.12 (vCollection) 332.57 302.33 P +0 F +1.12 ( de) 381.47 302.33 P +1.12 (vice) 396.19 302.33 P +1.12 (, then the oper) 413.82 302.33 P +1.12 (ation will f) 481.58 302.33 P +1.12 (ail and) 527.42 302.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(CDEV_INV) 297.29 290.33 T +(ALIDOP) 346.5 290.33 T +0 F +( will be retur) 384.28 290.33 T +(ned.) 438.43 290.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 266.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.02 (This method will call the) 297.29 266.33 P +3 F +-0.02 (add \050char *name\051) 406.11 266.33 P +0 F +-0.02 (method f) 486.08 266.33 P +-0.02 (or each) 524.67 266.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(name that is speci\336ed.) 297.29 254.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 230.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.39 (If the add method f) 297.29 230.33 P +2.39 (ails to add an) 389.95 230.33 P +2.39 (y of the de) 456.46 230.33 P +2.39 (vice name) 510.04 230.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.22 (str) 297.29 218.33 P +-0.22 (ings to the list, then the error code that w) 308.55 218.33 P +-0.22 (as gener) 487.04 218.33 P +-0.22 (ated b) 525.62 218.33 P +-0.22 (y) 553 218.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the call to) 297.29 206.33 T +3 F +(add \050char * name\051) 342.87 206.33 T +0 F +( will be retur) 422.9 206.33 T +(ned.) 477.05 206.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 182.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.58 (If an error occurs while adding a name to the list, the) 297.29 182.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.01 (method will contin) 297.29 170.33 P +-0.01 (ue with the ne) 376.63 170.33 P +-0.01 (xt name until the last name) 438.56 170.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(is reached.) 297.29 158.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 134.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.62 (If no errors occur while adding names to the list, then) 297.29 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(CDEV_SUCCESS) 297.29 122.33 T +0 F +( will be retur) 378.97 122.33 T +(ned to the caller) 433.12 122.33 T +(.) 503.77 122.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "5" 24 +%%Page: "4" 25 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. cde) 54 739 T +(vCollection Class Design) 78.25 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(4) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +9.93 (method will call the) 279.29 713.33 P +3 F +9.93 (attachPtr) 406.26 713.33 P +0 F +9.93 ( method of the) 446.28 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +2.22 (cde) 279.29 701.33 P +2.22 (vCollectionRequest) 295.11 701.33 P +0 F +2.22 ( in order to obtain a ne) 381.25 701.33 P +2.22 (w request) 494.43 701.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(object.) 279.29 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(attac) 162 665.33 T +(hRef/attac) 185.24 665.33 T +(hPtr) 233.48 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 261.29 665.33 T +(vCollection & attachRef) 277.11 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\050char * name\051;) 381.04 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 261.29 653.33 T +(vCollection & attachRef) 277.11 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\050char * name) 381.04 653.33 T +(, cde) 438.13 653.33 T +(vSystem & sys\051;) 459.51 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 261.29 641.33 T +(vCollection * attachPtr) 277.11 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\050char * name\051;) 375.48 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 261.29 629.33 T +(vCollection * attachPtr) 277.11 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\050char * name) 375.48 629.33 T +(, cde) 432.57 629.33 T +(vSystem &sys\051;) 453.95 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.86 (These methods are used to obtain a pointer or ref) 261.29 612.33 P +0.86 (erence to a) 488.26 612.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.12 (cde) 261.43 600.33 P +-0.12 (vCollection object. The name v) 277.25 600.33 P +-0.12 (ar) 413.25 600.33 P +-0.12 (iab) 422.29 600.33 P +-0.12 (le speci\336es the name of) 435.43 600.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.29 (the collection to be attached. These method ha) 261.43 588.33 P +0.29 (v) 471.19 588.33 P +0.29 (e the f) 475.94 588.33 P +0.29 (ollo) 504.03 588.33 P +0.29 (wing) 519.44 588.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(proper) 261.43 576.33 T +(ties) 290.73 576.33 T +(.) 306.14 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 261.29 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.1 (All functionality f) 279.29 552.33 P +0.1 (or these methods is stored in the) 351.43 552.33 P +3 F +0.1 (attachPtr) 499.98 552.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.54 (\050char *, cde) 279.29 540.33 P +0.54 (vSystem &\051) 331.19 540.33 P +0 F +0.54 ( method. All other methods will call) 382.85 540.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(this one) 279.29 528.33 T +(.) 314.16 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 261.29 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.56 (The method will \336rst deter) 279.29 504.33 P +1.56 (mine if the de) 400.24 504.33 P +1.56 (vice has already) 464.64 504.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.1 (been created. If it has been created and its) 279.29 492.33 P +3 F +2.1 (className) 490.55 492.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +8.19 (method retur) 279.29 480.33 P +8.19 (ns \322) 344.42 480.33 P +3 F +8.19 (cde) 369.29 480.33 P +8.19 (vCollection) 385.11 480.33 P +0 F +8.19 (\323, then the e) 434.01 480.33 P +8.19 (xisting) 511.66 480.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +6.87 (cde) 279.29 468.33 P +6.87 (vCollection) 295.11 468.33 P +0 F +6.87 ( will be retur) 344.01 468.33 P +6.87 (ned. If a non-collection) 418.77 468.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +6.76 (cde) 279.29 456.33 P +6.76 (vDe) 295.11 456.33 P +6.76 (vice) 312.59 456.33 P +0 F +6.76 ( of the same name has already been) 330.37 456.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(constr) 279.29 444.33 T +(ucted, then NULL will be retur) 306.67 444.33 T +(ned.) 438.64 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 261.29 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.2 (If a de) 279.29 420.33 P +1.2 (vice with the speci\336ed name has not already been) 309.18 420.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.67 (created, then the method will search the) 279.29 408.33 P +3 F +0.67 (cde) 464.06 408.33 P +0.67 (vDirector) 479.88 408.33 P +0.67 (y) 520.18 408.33 P +0 F +0.67 ( f) 525.18 408.33 P +0.67 (or) 531.11 408.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +5.86 (the speci\336ed name) 279.29 396.33 P +5.86 (. If the de) 374.78 396.33 P +5.86 (vice name is in the) 433.76 396.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +2.95 (cde) 279.29 384.33 P +2.95 (vDirector) 295.11 384.33 P +2.95 (y) 335.41 384.33 P +0 F +2.95 ( AND is of class \322) 340.41 384.33 P +3 F +2.95 (collection) 431.85 384.33 P +0 F +2.95 (\323, then a ne) 473.53 384.33 P +2.95 (w) 532.78 384.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +1.19 (cde) 279.29 372.33 P +1.19 (vCollection) 295.11 372.33 P +0 F +1.19 ( will be instantiated and retur) 344.01 372.33 P +1.19 (ned. If a non-) 477.49 372.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.38 (collection) 279.29 360.33 P +3 F +3.38 (cde) 327.13 360.33 P +3.38 (vDe) 342.95 360.33 P +3.38 (vice) 360.43 360.33 P +0 F +3.38 ( of the same name e) 378.21 360.33 P +3.38 (xists in the) 485.99 360.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 279.29 348.33 T +(vDirector) 295.11 348.33 T +(y) 335.41 348.33 T +0 F +(, then NULL will be retur) 339.41 348.33 T +(ned.) 446.92 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 261.29 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +5.28 (If a de) 279.29 324.33 P +5.28 (vice with the speci\336ed name has not been) 317.36 324.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.27 (instantiated and does not e) 279.29 312.33 P +0.27 (xist in the) 400.15 312.33 P +3 F +0.27 (cde) 445.98 312.33 P +0.27 (vDirector) 461.8 312.33 P +0.27 (y) 502.1 312.33 P +0 F +0.27 (, then a) 506.1 312.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +5.57 (ne) 279.29 300.33 P +5.57 (w) 290.21 300.33 P +5.57 (, empty) 296.83 300.33 P +3 F +5.57 (cde) 343.53 300.33 P +5.57 (vCollection) 359.35 300.33 P +0 F +5.57 ( will be created with the) 408.25 300.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(speci\336ed name) 279.29 288.33 T +(.) 346.39 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 261.29 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.16 (If NULL is retur) 279.29 264.33 P +-0.16 (ned to one of the) 346.3 264.33 P +3 F +-0.16 (attachRef) 423.34 264.33 P +0 F +-0.16 ( methods) 466.14 264.33 P +-0.16 (, then a) 506.96 264.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.23 (ref) 279.29 252.33 P +-0.23 (erence to a) 290.66 252.33 P +3 F +-0.23 (cde) 342.79 252.33 P +-0.23 (vErrorCollection) 358.61 252.33 P +0 F +-0.23 ( object will be retur) 429.73 252.33 P +-0.23 (ned to) 512.43 252.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the caller) 279.29 240.33 T +(.) 319.36 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 261.29 216.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +5.23 (The) 279.29 216.33 P +3 F +5.23 (refCount) 304.53 216.33 P +0 F +5.23 ( proper) 342.88 216.33 P +5.23 (ty of the) 380.19 216.33 P +3 F +5.23 (cde) 434.25 216.33 P +5.23 (vCollection) 450.07 216.33 P +0 F +5.23 ( will be) 498.97 216.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.36 (incremented each time a cop) 279.29 204.33 P +0.36 (y of the) 408.81 204.33 P +3 F +0.36 (cde) 445.46 204.33 P +0.36 (vCollection) 461.28 204.33 P +0 F +0.36 ( object) 510.18 204.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(is obtained b) 279.29 192.33 T +(y the application.) 335.79 192.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(detac) 162 168.33 T +(h) 188.02 168.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(int detach \050cde) 261.29 168.33 T +(vCollection & col\051;) 326.58 168.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(int detach \050cde) 261.29 156.33 T +(vCollection * col\051;) 326.58 156.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +2.12 (This method is called to detach a pointer or ref) 261.29 139.33 P +2.12 (erence to a) 485.73 139.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 261.43 127.33 T +(vCollection object. It has the f) 277.25 127.33 T +(ollo) 407.57 127.33 T +(wing proper) 422.98 127.33 T +(ties) 475.62 127.33 T +(.) 491.03 127.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 261.29 103.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.6 (This method decrements the) 279.29 103.33 P +3 F +3.6 (refCount) 423.19 103.33 P +0 F +3.6 ( proper) 461.54 103.33 P +3.6 (ty of the) 497.22 103.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 279.29 91.33 T +(vCollection) 295.11 91.33 T +0 F +( object.) 344.01 91.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "4" 25 +%%Page: "3" 26 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. cde) 434.23 739 T +(vCollection Class Design) 458.48 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(3) 552.44 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(Method Over) 72 713.33 T +(vie) 133.22 713.33 T +(w) 146.97 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(of the Class) 72 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180 713.33 T +(vCollection) 197.08 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 279.29 713.33 T +(vCollection \050char * name) 295.11 713.33 T +(, cde) 403.88 713.33 T +(vSystem & system\051;) 425.26 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.03 (This is the constr) 279.29 696.33 P +1.03 (uctor f) 358.11 696.33 P +1.03 (or the cde) 386.63 696.33 P +1.03 (vCollection class) 432.86 696.33 P +1.03 (. It has the) 508.21 696.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(f) 279.43 684.33 T +(ollo) 281.91 684.33 T +(wing proper) 297.32 684.33 T +(ties) 349.96 684.33 T +(.) 365.37 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 666.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.8 (This method is) 297.29 666.33 P +2 F +0.8 (pr) 367.48 666.33 P +0.8 (otected) 377.27 666.33 P +0 F +0.8 ( to pre) 412.83 666.33 P +0.8 (v) 442.48 666.33 P +0.8 (ent) 447.23 666.33 P +3 F +0.8 (cde) 464.7 666.33 P +0.8 (vCollections) 480.52 666.33 P +0 F +0.8 ( from) 534.42 666.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.2 (being instantiated directly) 297.29 654.33 P +2.2 (. Ne) 413.52 654.33 P +2.2 (w) 433.86 654.33 P +3 F +2.2 (cde) 446.06 654.33 P +2.2 (vCollection) 461.88 654.33 P +0 F +2.2 ( instances) 510.78 654.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.7 (are created b) 297.29 642.33 P +0.7 (y using the) 357.42 642.33 P +3 F +0.7 (attachPtr) 410.67 642.33 P +0 F +0.7 ( or) 450.69 642.33 P +3 F +0.7 (attachRef) 466.54 642.33 P +0 F +0.7 ( method of) 509.34 642.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the) 297.29 630.33 T +3 F +(cde) 313.97 630.33 T +(vCollection) 329.79 630.33 T +0 F +( class) 378.69 630.33 T +(.) 404.1 630.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.59 (The name that is pro) 297.29 612.33 P +2.59 (vided to the) 399.19 612.33 P +3 F +2.59 (cde) 461.43 612.33 P +2.59 (vCollection) 477.25 612.33 P +0 F +2.59 ( is the) 526.15 612.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.37 (de) 297.29 600.33 P +1.37 (vice name that CDEV will use to ref) 308.11 600.33 P +1.37 (er to it. The name) 474.14 600.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.93 (m) 297.29 588.33 P +1.93 (ust be unique within the CDEV system of objects and) 305.52 588.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.26 (cannot be the same as the name of an) 297.29 576.33 P +-0.26 (y regular) 465.75 576.33 P +3 F +-0.26 (cde) 506.92 576.33 P +-0.26 (vDe) 522.74 576.33 P +-0.26 (vice) 540.22 576.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(that e) 297.29 564.33 T +(xists in the CDEV DDL \336le) 322.01 564.33 T +(.) 438 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 546.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +6.39 (The) 297.29 546.33 P +3 F +6.39 (cde) 323.68 546.33 P +6.39 (vSystem) 339.5 546.33 P +0 F +6.39 ( ref) 377.84 546.33 P +6.39 (erence that is pro) 398.38 546.33 P +6.39 (vided is the) 494.65 546.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +1.7 (cde) 297.29 534.33 P +1.7 (vSystem) 313.11 534.33 P +0 F +1.7 ( instance that will be used to) 351.45 534.33 P +3 F +1.7 (poll) 491.77 534.33 P +0 F +1.7 (,) 507.33 534.33 P +3 F +1.7 (pend) 514.6 534.33 P +0 F +1.7 ( and) 536.84 534.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(\337ush) 297.29 522.33 T +0 F +( the) 318.41 522.33 T +3 F +(cde) 337.87 522.33 T +(vCollection) 353.69 522.33 T +0 F +( object.) 402.59 522.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.88 (If the name pro) 297.29 504.33 P +0.88 (vided is the name of a) 367.04 504.33 P +3 F +0.88 (cde) 472.94 504.33 P +0.88 (vCollection) 488.76 504.33 P +0 F +0.88 ( that) 537.66 504.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.23 (has been speci\336ed in the) 297.29 492.33 P +3 F +1.23 (CDEV DDL) 416.83 492.33 P +0 F +1.23 ( \336le) 468.62 492.33 P +1.23 (, then the list of) 485.26 492.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +5.11 (de) 297.29 480.33 P +5.11 (vices will be populated from the names that are) 308.11 480.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.01 (speci\336ed. Otherwise) 297.29 468.33 P +-0.01 (, an empty) 387.16 468.33 P +3 F +-0.01 (cde) 436.61 468.33 P +-0.01 (vCollection) 452.43 468.33 P +0 F +-0.01 ( instance will) 501.33 468.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(be created.) 297.29 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(~cde) 180 432.33 T +(vCollection) 202.92 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(vir) 279.29 432.33 T +(tual ~cde) 290.24 432.33 T +(vCollection \050v) 330.8 432.33 T +(oid\051;) 390.56 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.96 (This is the destr) 279.29 415.33 P +1.96 (uctor f) 355.9 415.33 P +1.96 (or a cde) 385.35 415.33 P +1.96 (vCollection object. It has the) 425.1 415.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(f) 279.43 403.33 T +(ollo) 281.91 403.33 T +(wing proper) 297.32 403.33 T +(ties) 349.96 403.33 T +(.) 365.37 403.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 379.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.91 (This method is protected to pre) 297.29 379.33 P +2.91 (v) 449.36 379.33 P +2.91 (ent the) 454.11 379.33 P +3 F +2.91 (cde) 493.28 379.33 P +2.91 (vCollection) 509.1 379.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.71 (object from being destro) 297.29 367.33 P +4.71 (y) 418.39 367.33 P +4.71 (ed b) 423.19 367.33 P +4.71 (y the application. This) 447.16 367.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.87 (method should only be called b) 297.29 355.33 P +1.87 (y the) 444.3 355.33 P +3 F +1.87 (cde) 472.51 355.33 P +1.87 (vSystem) 488.33 355.33 P +0 F +1.87 ( object) 526.67 355.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(when the application is ter) 297.29 343.33 T +(minating.) 413.15 343.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 319.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.1 (Because the) 297.29 319.33 P +3 F +-0.1 (cde) 355.46 319.33 P +-0.1 (vCollection) 371.28 319.33 P +0 F +-0.1 ( object will nor) 420.18 319.33 P +-0.1 (mally be ref) 483.48 319.33 P +-0.1 (erred) 534.66 319.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.1 (to as a) 297.29 307.33 P +3 F +3.1 (cde) 339.39 307.33 P +3.1 (vDe) 355.2 307.33 P +3.1 (vice) 372.68 307.33 P +0 F +3.1 ( object, this destr) 390.46 307.33 P +3.1 (uctor is vir) 475.5 307.33 P +3.1 (tual to) 527.66 307.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ensure that the) 297.29 295.33 T +2 F +(\324most senior\325) 366.78 295.33 T +0 F +( destr) 429.02 295.33 T +(uctor is called \336rst.) 454.18 295.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 271.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 (This method will delete all de) 297.29 271.33 P +2 (vice name str) 435.36 271.33 P +2 (ings that are) 498.97 271.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(associated with the) 297.29 259.33 T +3 F +(cde) 385.11 259.33 T +(vCollection) 400.93 259.33 T +0 F +( object.) 449.83 259.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(g) 180 235.33 T +(etRequestObject) 186.21 235.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(vir) 279.29 235.33 T +(tual int getRequestObject \050) 290.24 235.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(char *msg,) 408.63 235.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 351.57 223.33 T +(vRequestObject* &req\051;) 367.39 223.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.06 (This method is called in order to obtain the cde) 279.29 206.33 P +0.06 (vRequestObject) 486.86 206.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.85 (associated with the speci\336ed de) 279.43 194.33 P +2.85 (vice/msg combination. This) 431.71 194.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.48 (method retur) 279.43 182.33 P +2.48 (ns CDEV_SUCCESS if the cde) 338.85 182.33 P +2.48 (vRequestObject) 486.86 182.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.67 (w) 279.43 170.33 P +3.67 (as successfully obtained. This method has the f) 286.5 170.33 P +3.67 (ollo) 522.03 170.33 P +3.67 (wing) 537.44 170.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(proper) 279.43 158.33 T +(ties) 308.73 158.33 T +(.) 324.14 158.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 134.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.57 (The) 297.29 134.33 P +3 F +0.57 (cde) 317.86 134.33 P +0.57 (vRequestObject) 333.68 134.33 P +0 F +0.57 ( pointer that is retur) 404.83 134.33 P +0.57 (ned is actually) 493.5 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(a pointer to a) 297.29 122.33 T +3 F +(cde) 358.44 122.33 T +(vCollectionRequest) 374.26 122.33 T +0 F +( object.) 460.4 122.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 98.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.77 (If a) 297.29 98.33 P +3 F +0.77 (cde) 315.51 98.33 P +0.77 (vCollectionRequest) 331.33 98.33 P +0 F +0.77 ( already e) 417.47 98.33 P +0.77 (xists f) 462.62 98.33 P +0.77 (or the speci\336ed) 488.65 98.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.35 (de) 297.29 86.33 P +0.35 (vice/msg combination, it will be retur) 308.11 86.33 P +0.35 (ned. Otherwise) 470.73 86.33 P +0.35 (, the) 538.18 86.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "3" 26 +%%Page: "2" 27 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. cde) 54 739 T +(vCollection Class Design) 78.25 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(2) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(\245) 162 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (When a de) 180 713.33 P +0.83 (vice name str) 229.73 713.33 P +0.83 (ing is added to the) 291 713.33 P +3 F +0.83 (cde) 379.67 713.33 P +0.83 (vCollection) 395.49 713.33 P +0 F +0.83 ( object using the) 444.39 713.33 P +3 F +0.83 (add) 523.32 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.89 (method, the method mak) 180 701.33 P +0.89 (es a cop) 293.08 701.33 P +0.89 (y of the str) 332.36 701.33 P +0.89 (ing. The or) 381.86 701.33 P +0.89 (iginal str) 431.59 701.33 P +0.89 (ing remains the) 469.86 701.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(proper) 180 689.33 T +(ty of the caller) 209.3 689.33 T +(.) 271.05 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.66 (When a de) 180 665.33 P +0.66 (vice name str) 229.38 665.33 P +0.66 (ing is remo) 290.31 665.33 P +0.66 (v) 340.39 665.33 P +0.66 (ed from the) 345.14 665.33 P +3 F +0.66 (cde) 400.48 665.33 P +0.66 (vCollection) 416.3 665.33 P +0 F +0.66 ( object using the) 465.2 665.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.25 (remo) 180 653.33 P +0.25 (v) 202.63 653.33 P +0.25 (e method, the str) 207.38 653.33 P +0.25 (ing that w) 283.32 653.33 P +0.25 (as gener) 326.47 653.33 P +0.25 (ated when the de) 365.52 653.33 P +0.25 (vice name w) 442.69 653.33 P +0.25 (as added) 498.61 653.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(will be automatically deleted.) 180 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.66 (When the) 180 617.33 P +3 F +0.66 (cde) 226.91 617.33 P +0.66 (vCollection) 242.73 617.33 P +0 F +0.66 ( object is destro) 291.63 617.33 P +0.66 (y) 363.35 617.33 P +0.66 (ed, it is responsib) 368.15 617.33 P +0.66 (le f) 447.75 617.33 P +0.66 (or deleting an) 461.45 617.33 P +0.66 (y of) 523.22 617.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the de) 180 605.33 T +(vice name str) 207.5 605.33 T +(ings that it has allocated.) 267.11 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +8.11 (The) 180 581.33 P +3 F +8.11 (getRequestObject) 208.12 581.33 P +0 F +8.11 ( method of a) 288.16 581.33 P +3 F +8.11 (cde) 378.99 581.33 P +8.11 (vCollection) 394.81 581.33 P +0 F +8.11 ( object retur) 443.71 581.33 P +8.11 (ns a) 512.99 581.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +0.93 (cde) 180 569.33 P +0.93 (vCollectionRequest) 195.82 569.33 P +0 F +0.93 ( object. This object inher) 281.96 569.33 P +0.93 (its from \050and is in the f) 394.22 569.33 P +0.93 (or) 497.88 569.33 P +0.93 (m of\051 a) 507.02 569.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 180 557.33 T +(vRequestObject) 195.82 557.33 T +0 F +( object.) 266.96 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 162 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4.7 (A) 180 533.33 P +3 F +4.7 (cde) 194.15 533.33 P +4.7 (vCollection) 209.98 533.33 P +0 F +4.7 ( object inher) 258.88 533.33 P +4.7 (its its) 322.9 533.33 P +3 F +4.7 (send, sendCallbac) 357.88 533.33 P +4.7 (k and sendNoBloc) 444.64 533.33 P +4.7 (k) 535 533.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.35 (functionality from the) 180 521.33 P +3 F +1.35 (cde) 279.08 521.33 P +1.35 (vDe) 294.9 521.33 P +1.35 (vice) 312.38 521.33 P +0 F +1.35 ( object. This functionality should be automatic) 330.16 521.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.43 (because the) 180 509.33 P +3 F +1.43 (cde) 240.12 509.33 P +1.43 (vDe) 255.94 509.33 P +1.43 (vice) 273.42 509.33 P +0 F +1.43 ( object calls the) 291.2 509.33 P +3 F +1.43 (getRequestObject) 368.63 509.33 P +0 F +1.43 ( method to obtain a) 448.67 509.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(request object f) 180 497.33 T +(or the de) 248.07 497.33 T +(vice/message combination associated with the request.) 287.24 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 2: Object Model of the cde) 162 464 T +(vCollection Class) 297.3 464 T +0 0 0 1 0 0 0 K +162 81 540 720 C +0 0 0 1 0 0 0 K +162 106.57 540 461 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +170.86 188.14 534.43 449.57 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +1 10 Q +(c) 299.42 439.02 T +(lass cde) 304.78 439.02 T +(vCollection) 344.1 439.02 T +338.35 169.72 333.35 179.01 338.35 188.29 343.35 179.01 4 Y +N +359.57 150.86 491 165.14 R +7 X +V +0 X +N +(c) 387.94 155.74 T +(lass cde) 393.3 155.74 T +(vSList) 432.62 155.74 T +338.35 169.71 338.35 157.57 359.78 157.57 3 L +N +381.35 131.72 376.35 141.01 381.35 150.29 386.35 141.01 4 Y +N +402.57 113.57 534 127.86 R +7 X +V +0 X +N +(c) 423.95 118.45 T +(har * de) 429.41 118.45 T +(viceName) 465.94 118.45 T +381.35 131.71 381.35 119.57 402.78 119.57 3 L +N +90 450 2.86 3.21 399.78 120.07 G +90 450 2.86 3.21 399.78 120.07 A +170.57 436.28 534.15 436.28 2 L +N +4 9 Q +(methods:) 180.57 427.43 T +5 F +(cdevCollection \050char *, cdevSystem &\051) 192.58 416.43 T +(~cdevCollection \050void\051 :{virtual}) 192.58 405.43 T +(getRequestObject \050char *, cdevRequestObject *&\051 :{virtual} int) 192.58 394.43 T +-0.26 (attachRef \050char *\051 :{static} cdevCollection &) 192.58 372.43 P +-0.26 (attachPtr \050char *\051 :{static} cdevCollection *) 192.58 361.43 P +-0.51 (attachRef \050char *, cdevSystem &\051 :{static} cdevCollection *) 192.58 350.43 P +-0.51 (attachPtr \050char *, cdevSystem &\051 :{static} cdevCollection &) 192.58 339.43 P +(detach \050cdevCollection &\051 :{static} void) 192.58 328.43 T +(detach \050cdevCollection *\051 :{static} void) 192.58 317.43 T +(className \050void\051 :{virtual} char *) 192.58 306.43 T +(add \050char *\051 : int) 192.58 295.43 T +(add \050int, char *, ...\051 : int) 192.58 284.43 T +(add \050int, char **\051 : int) 192.58 273.43 T +(add \050char **\051 : int) 192.58 262.43 T +(addRegexp \050char *\051 : int) 192.58 251.43 T +(remove \050char *\051 : int) 192.58 240.43 T +(remove \050int, char *, ...\051 : int) 192.58 229.43 T +(remove \050int, char **\051 : int) 192.58 218.43 T +(remove \050char **\051 : int) 192.58 207.43 T +(removeRegexp \050char *\051 : int) 192.58 196.43 T +162 106.57 540 461 R +1 H +0 Z +N +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "2" 27 +%%Page: "1" 28 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. cde) 434.23 739 T +(vCollection Class Design) 458.48 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1) 552.44 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 14 Q +0 X +0 0 0 1 0 0 0 K +(1.) 159.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180 710.67 T +(vCollection Class Design) 203.91 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Purpose of the) 72 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Class) 72 661.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +-0.21 (The cde) 180 673.33 P +-0.21 (vCollection class pro) 215.62 673.33 P +-0.21 (vides a mechanism f) 306.74 673.33 P +-0.21 (or sending a message to a collection) 396.95 673.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.08 (of named de) 180 661.33 P +0.08 (vices) 235.46 661.33 P +0.08 (. The object inher) 258.08 661.33 P +0.08 (itance hier) 335.74 661.33 P +0.08 (arch) 381.86 661.33 P +0.08 (y of the cde) 401.01 661.33 P +0.08 (vCollection is descr) 452.65 661.33 P +0.08 (ibed) 539.1 661.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(in the f) 180 649.33 T +(ollo) 209.72 649.33 T +(wing object diag) 225.13 649.33 T +(r) 296.73 649.33 T +(am.) 299.96 649.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 1: Object Inher) 180 616 T +(itance Hier) 269.68 616 T +(arch) 312.6 616 T +(y of the cde) 329.83 616 T +(vCollection Class) 376.09 616 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Requirements of) 72 412.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the Class) 72 400.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(\245) 180 412.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.44 (A) 198 412.19 P +3 F +0.44 (cde) 207.89 412.19 P +0.44 (vCollection) 223.71 412.19 P +0 F +0.44 ( is a) 272.61 412.19 P +3 F +0.44 (cde) 295.07 412.19 P +0.44 (vDe) 310.89 412.19 P +0.44 (vice) 328.36 412.19 P +0 F +0.44 ( and is a named entity within the CDEV system) 346.14 412.19 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(of objects) 198 400.19 T +(.) 240.65 400.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 376.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.29 (The name of the) 198 376.19 P +3 F +2.29 (cde) 282.76 376.19 P +2.29 (vCollection) 298.58 376.19 P +0 F +2.29 ( m) 347.48 376.19 P +2.29 (ust be unique within the CDEV system of) 360.78 376.19 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(objects) 198 364.19 T +(.) 229.53 364.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 340.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.55 (Only one instance of a named) 198 340.19 P +3 F +2.55 (cde) 348.91 340.19 P +2.55 (vCollection) 364.73 340.19 P +0 F +2.55 ( ma) 413.63 340.19 P +2.55 (y e) 432.55 340.19 P +2.55 (xist within an e) 448.14 340.19 P +2.55 (x) 521.06 340.19 P +2.55 (ecuting) 525.76 340.19 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(application.) 198 328.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 304.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.49 (The) 198 304.19 P +3 F +1.49 (cde) 219.5 304.19 P +1.49 (vCollection) 235.32 304.19 P +0 F +1.49 ( object contains a single link) 284.22 304.19 P +1.49 (ed list of de) 415.95 304.19 P +1.49 (vice names) 471.26 304.19 P +1.49 (. These) 523.16 304.19 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(de) 198 292.19 T +(vice names de\336ne the collection.) 208.82 292.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 268.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.27 (A) 198 268.19 P +3 F +3.27 (cde) 210.71 268.19 P +3.27 (vCollection) 226.54 268.19 P +0 F +3.27 ( object ma) 275.43 268.19 P +3.27 (y be de\336ned in the) 327.79 268.19 P +3 F +3.27 (CDEV DDL) 428.62 268.19 P +0 F +3.27 ( \336le or ma) 482.44 268.19 P +3.27 (y be) 535.84 268.19 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(dynamically created at r) 198 256.19 T +(un-time) 303.74 256.19 T +(.) 336.93 256.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 232.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.4 (The) 198 232.19 P +3 F +1.4 (CDEV DDL) 219.41 232.19 P +0 F +1.4 ( de\336nition of a) 271.37 232.19 P +3 F +1.4 (cde) 342.02 232.19 P +1.4 (vCollection) 357.84 232.19 P +0 F +1.4 ( object contains the names of all) 406.74 232.19 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 (de) 198 220.19 P +0 (vice names that compr) 208.82 220.19 P +0 (ise the object. Ho) 309.54 220.19 P +0 (w) 386.64 220.19 P +0 (e) 393.76 220.19 P +0 (v) 399.02 220.19 P +0 (er) 403.77 220.19 P +0 (, names ma) 412.16 220.19 P +0 (y be added to this list) 464.09 220.19 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(after it has been instantiated.) 198 208.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 184.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.02 (De) 198 184.19 P +1.02 (vice names ma) 210.48 184.19 P +1.02 (y be added to or remo) 279.46 184.19 P +1.02 (v) 382.26 184.19 P +1.02 (ed from a) 387.01 184.19 P +3 F +1.02 (cde) 435.1 184.19 P +1.02 (vCollection) 450.92 184.19 P +0 F +1.02 ( object using) 499.82 184.19 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the) 198 172.19 T +3 F +(add) 214.68 172.19 T +0 F +( and) 231.36 172.19 T +3 F +(remo) 253.6 172.19 T +(v) 276.23 172.19 T +(e) 280.98 172.19 T +0 F +( methods of the) 286.54 172.19 T +3 F +(cde) 358.25 172.19 T +(vCollection) 374.07 172.19 T +0 F +( class) 422.97 172.19 T +(.) 448.38 172.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 148.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.95 (The component de) 198 148.19 P +2.95 (vice names of a) 286.97 148.19 P +3 F +2.95 (cde) 371.57 148.19 P +2.95 (vCollection) 387.39 148.19 P +0 F +2.95 ( object ma) 436.29 148.19 P +2.95 (y be added or) 488.01 148.19 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.55 (remo) 198 136.19 P +0.55 (v) 220.63 136.19 P +0.55 (ed until the \336rst message has been sent to the) 225.38 136.19 P +3 F +0.55 (cde) 438.26 136.19 P +0.55 (vCollection) 454.08 136.19 P +0 F +0.55 (, after which) 502.98 136.19 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the collection of de) 198 124.19 T +(vice names cannot be modi\336ed.) 281.08 124.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 100.19 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(A de) 198 100.19 T +(vice name can only occur once within a) 218.27 100.19 T +3 F +(cde) 395.01 100.19 T +(vCollection) 410.83 100.19 T +0 F +( object.) 459.73 100.19 T +0 0 0 1 0 0 0 K +180 437.86 558 680 C +0 0 0 1 0 0 0 K +180 437.86 558 613 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +264.43 586 395.86 606 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +1 10 Q +(c) 288.98 593.86 T +(lass cde) 294.34 593.86 T +(vDe) 333.66 593.86 T +(vice) 351.85 593.86 T +262.43 528 393.86 548 R +7 X +V +0 X +N +(c) 278.85 535.86 T +(lass cde) 284.21 535.86 T +(vCollection) 323.53 535.86 T +329.21 586 329.21 548.14 2 L +N +329.56 575.64 320.64 558.5 337.78 558.5 3 Y +7 X +V +0 X +N +279.92 509.58 274.92 518.86 279.92 528.15 284.92 518.86 4 Y +N +301.14 486.43 432.57 506.43 R +7 X +V +0 X +N +(c) 329.51 494.29 T +(lass cde) 334.87 494.29 T +(vSList) 374.19 494.29 T +279.92 509.57 279.92 497.43 301.35 497.43 3 L +N +322.92 468.01 317.92 477.29 322.92 486.58 327.92 477.29 4 Y +N +344.14 444.86 475.57 464.86 R +7 X +V +0 X +N +(c) 365.52 452.71 T +(har * de) 370.98 452.71 T +(viceName) 407.51 452.71 T +322.92 468 322.92 455.86 344.35 455.86 3 L +N +90 450 2.86 3.21 341.35 456.36 G +90 450 2.86 3.21 341.35 456.36 A +180 437.86 558 613 R +1 H +0 Z +N +180 437.86 558 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "1" 28 +%%Page: "4" 29 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(4) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 14 Q +0 X +0 0 0 1 0 0 0 K +(List of Figures) 162 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(Figure 1.) 162 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object Inheritance Hierarchy of the cdevCollection Class) 216 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................) 467.04 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 534.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 2.) 162 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object Model of the cdevCollection Class) 216 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(................................................) 400.32 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 534.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 3.) 162 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object Inheritance Hierarchy of the cdevCollectionRequest Class) 216 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..........) 505.96 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 534.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 4.) 162 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object Model of the cdevCollectionRequest Class) 216 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................) 436.46 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 534.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 5.) 162 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object Inheritance Hierarchy of the cdevGrpCollectionRequest Class) 216 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..) 522.64 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 528.88 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 6.) 162 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object Model of the cdevGrpCollectionRequest Class) 216 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........................) 453.14 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 528.88 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 7.) 162 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object Inheritance Hierarchy of the cdevDefCollectionRequest Class) 216 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...) 519.86 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 528.88 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 8.) 162 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object Model of the cdevDefCollectionRequest Class) 216 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........................) 453.14 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 528.88 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 9.) 162 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdevCollection Definition in the CDEV DDL File) 216 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.....................................) 425.34 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 10.) 162 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Attach to a cdevCollection using attachPtr and attachRef) 216 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(......................) 467.04 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(22) 528.88 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 11.) 162 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Detach from a cdevCollection using detach) 216 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........................................) 408.66 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(22) 528.88 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 12.) 162 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Adding a single device to a cdevCollection) 216 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(............................................) 405.88 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(23) 528.88 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 13.) 162 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Adding multiple devices to a cdevCollection) 216 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........................................) 408.66 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(23) 528.88 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 14.) 162 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Adding an array of devices to a cdevCollection) 216 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(......................................) 422.56 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(24) 528.88 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 15.) 162 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Adding a NULL-terminated array of devices to a cdevCollection) 216 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........) 497.62 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(24) 528.88 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 16.) 162 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Adding a device to a cdevCollection using regular expressions) 216 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.............) 492.06 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(25) 528.88 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 17.) 162 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Removing a single device from a cdevCollection) 216 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................) 430.9 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(25) 528.88 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 18.) 162 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Removing multiple devices from a cdevCollection) 216 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.................................) 436.46 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(25) 528.88 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 19.) 162 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Removing an array of devices from a cdevCollection) 216 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.............................) 447.58 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(26) 528.88 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 20.) 162 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Removing a NULL-terminated array of devices from a cdevCollection) 216 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..) 522.64 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(26) 528.88 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 21.) 162 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Removing devices from a cdevCollection using regular expressions) 216 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.....) 514.3 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(27) 528.88 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 22.) 162 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Getting a list of devices from a cdevCollection) 216 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................................) 419.78 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(27) 528.88 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "4" 29 +%%Page: "3" 30 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(3) 552.44 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 14 Q +0 X +0 0 0 1 0 0 0 K +(T) 180 710.67 T +(ab) 187.43 710.67 T +(le of Contents) 203.63 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 198 684.33 T +(vCollection Class Design) 213.82 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 325.26 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pur) 198.2 672.33 T +(pose of the Class) 214.06 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Requirements of the Class) 198.2 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 316.92 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Method Ov) 198.2 648.33 T +(er) 246.86 648.33 T +(vie) 256.05 648.33 T +(w of the Class) 268.63 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 333.6 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 180 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 198 636.33 T +(vCollectionRequest Class Design) 213.82 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 364.18 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pur) 198.2 624.33 T +(pose of the Class) 214.06 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Requirements of the Class) 198.2 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 316.92 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Method Ov) 198.2 600.33 T +(er) 246.86 600.33 T +(vie) 256.05 600.33 T +(w of the Class) 268.63 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 333.6 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 180 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 198 588.33 T +(vGr) 213.82 588.33 T +(pCollectionRequest Class Design) 230.23 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 380.86 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pur) 198.2 576.33 T +(pose of the Class) 214.06 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Requirements of the Class) 198.2 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 316.92 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Attr) 198.2 552.33 T +(ib) 213.91 552.33 T +(ute Ov) 221.49 552.33 T +(er) 250.7 552.33 T +(vie) 259.89 552.33 T +(w of the Class) 272.47 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 336.38 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Method Ov) 198.2 540.33 T +(er) 246.86 540.33 T +(vie) 256.05 540.33 T +(w of the Class) 268.63 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 333.6 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 546.88 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 180 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 198 528.33 T +(vDefCollectionRequest Class Design) 213.82 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 378.08 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pur) 198.2 516.33 T +(pose of the Class) 214.06 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Requirements of the Class) 198.2 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 316.92 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Attr) 198.2 492.33 T +(ib) 213.91 492.33 T +(ute Ov) 221.49 492.33 T +(er) 250.7 492.33 T +(vie) 259.89 492.33 T +(w of the Class) 272.47 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 336.38 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 546.88 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Method Ov) 198.2 480.33 T +(er) 246.86 480.33 T +(vie) 256.05 480.33 T +(w of the Class) 268.63 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 333.6 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 546.88 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 180 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De\336ning cde) 198 468.33 T +(vCollections in the CDEV DDL File) 253.28 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . .) 408.66 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 546.88 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 456.33 T +(er) 210.73 456.33 T +(vie) 219.92 456.33 T +(w) 232.5 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 546.88 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 180 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Elementar) 198 444.33 T +(y Commands of the cde) 243.87 444.33 T +(vCollection) 349.17 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . .) 400.32 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(22) 546.88 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Attaching to a cde) 198.2 432.33 T +(vCollection) 277.95 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 328.04 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(22) 546.88 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Detaching from a cde) 198.2 420.33 T +(vCollection) 292.94 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 341.94 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(22) 546.88 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Adding De) 198.2 408.33 T +(vices to a cde) 244.59 408.33 T +(vCollection) 305.43 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 355.84 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(23) 546.88 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Adding a Single De) 198.2 396.33 T +(vice to a cde) 283.5 396.33 T +(vCollection) 339.34 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . .) 389.2 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(23) 546.88 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Adding Multiple De) 198.2 384.33 T +(vices to a cde) 281.82 384.33 T +(vCollection) 342.66 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . .) 391.98 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(23) 546.88 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Adding an Arr) 198.2 372.33 T +(a) 259.24 372.33 T +(y of De) 264.5 372.33 T +(vices to a cde) 295.88 372.33 T +(vCollection) 356.72 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . .) 405.88 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(24) 546.88 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Adding a NULL-T) 198.2 360.33 T +(er) 274.25 360.33 T +(minated Arr) 283.39 360.33 T +(a) 334.97 360.33 T +(y of De) 340.23 360.33 T +(vices to a cde) 371.61 360.33 T +(vCollection) 432.45 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . .) 483.72 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(24) 546.88 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Adding De) 198.2 348.33 T +(vices to a cde) 244.59 348.33 T +(vCollection Using Regular Expressions) 305.43 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . .) 478.16 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(24) 546.88 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Remo) 198.2 336.33 T +(ving a Single De) 224.72 336.33 T +(vice from a cde) 297.23 336.33 T +(vCollection) 364.73 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . .) 414.22 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(25) 546.88 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Remo) 198.2 324.33 T +(ving Multiple De) 224.72 324.33 T +(vices from a cde) 295.55 324.33 T +(vCollection) 368.05 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . .) 417 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(25) 546.88 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Remo) 198.2 312.33 T +(ving an Arr) 224.72 312.33 T +(a) 272.97 312.33 T +(y of De) 278.23 312.33 T +(vices from a cde) 309.61 312.33 T +(vCollection) 382.11 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . .) 433.68 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(26) 546.88 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Remo) 198.2 300.33 T +(ving a NULL-T) 224.72 300.33 T +(er) 287.98 300.33 T +(minated Arr) 297.12 300.33 T +(a) 348.7 300.33 T +(y of De) 353.96 300.33 T +(vices from a cde) 385.34 300.33 T +(vCollection) 457.84 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . .) 508.74 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(26) 546.88 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Remo) 198.2 288.33 T +(ving De) 224.72 288.33 T +(vices from a cde) 258.32 288.33 T +(vCollection Using Regular Expressions) 330.82 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . .) 503.18 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(26) 546.88 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Getting a List of De) 198.2 276.33 T +(vices from a cde) 283.5 276.33 T +(vCollection) 356 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . .) 405.88 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(27) 546.88 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 180 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Restr) 198 264.33 T +(ictions of the cde) 222.04 264.33 T +(vCollection De) 296.78 264.33 T +(vice) 360.94 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 380.86 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 546.88 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "3" 30 +%%Page: "ii" 31 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(ii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(TRADEMARKS:) 54 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(UNIX is a registered tr) 180 569.33 T +(ademar) 278.26 569.33 T +(k of A) 312.31 569.33 T +(T&T in the USA and other countr) 336.68 569.33 T +(ies) 481.9 569.33 T +(.) 494.53 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(VxW) 180 545.33 T +(or) 200.81 545.33 T +(ks is a register tr) 209.85 545.33 T +(ademar) 283.1 545.33 T +(k of Wind Riv) 317.15 545.33 T +(er Systems) 375.8 545.33 T +(.) 425.66 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The X Windo) 180 521.33 T +(w System is a tr) 237.65 521.33 T +(ademar) 308.12 521.33 T +(k of Massachusetts Institute of T) 342.17 521.33 T +(echnology) 484.37 521.33 T +(.) 528.95 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(OSF/Motif and Motif are tr) 180 497.33 T +(ademar) 294.94 497.33 T +(ks of Open Softw) 328.99 497.33 T +(are F) 404.99 497.33 T +(oundation, Inc.) 428.03 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ultr) 180 473.33 T +(ix and DEC are registered tr) 195.7 473.33 T +(ademar) 319.53 473.33 T +(ks of Digital Equipment Cor) 353.58 473.33 T +(por) 475.03 473.33 T +(ation.) 489.38 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(HPUX is a registered tr) 180 449.33 T +(ademar) 282.15 449.33 T +(k of He) 316.2 449.33 T +(wlett P) 347.68 449.33 T +(ac) 377.29 449.33 T +(kard.) 387.65 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(SURA/CEB) 54 344.33 T +(AF:) 105.92 344.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.44 (The Southeaster) 180 344.33 P +4.44 (n Univ) 258.62 344.33 P +4.44 (ersities Research Association \050SURA\051 oper) 291.15 344.33 P +4.44 (ates the) 499.98 344.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.01 (Contin) 180 332.33 P +2.01 (uous Electron Beam Acceler) 208.8 332.33 P +2.01 (ator F) 340.89 332.33 P +2.01 (acility \050CEBAF\051 f) 368.52 332.33 P +2.01 (or the United States) 445.59 332.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Depar) 180 320.33 T +(tment of Energy under contr) 207.63 320.33 T +(act DE-A) 331.48 320.33 T +(C05-84ER40150.) 371.19 320.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(DISCLAIMER:) 54 218.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.49 (This repor) 180 218.33 P +0.49 (t w) 225.9 218.33 P +0.49 (as prepared as an account of w) 239.02 218.33 P +0.49 (or) 381.4 218.33 P +0.49 (k sponsored b) 390.44 218.33 P +0.49 (y the United States) 454.03 218.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.18 (go) 180 206.33 P +2.18 (v) 190.97 206.33 P +2.18 (er) 195.72 206.33 P +2.18 (nment. Neither the United States nor the United States Depar) 204.86 206.33 P +2.18 (tment of) 501.68 206.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.04 (Energy) 180 194.33 P +1.04 (, nor an) 210.68 194.33 P +1.04 (y of their emplo) 246.52 194.33 P +1.04 (y) 317.69 194.33 P +1.04 (ees) 322.49 194.33 P +1.04 (, mak) 338.46 194.33 P +1.04 (es an) 363.75 194.33 P +1.04 (y w) 389.1 194.33 P +1.04 (arr) 404.99 194.33 P +1.04 (anty) 417.11 194.33 P +1.04 (, e) 435.01 194.33 P +1.04 (xpress or implied, or) 446.86 194.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.83 (assumes an) 180 182.33 P +1.83 (y legal liability or responsibility f) 235.59 182.33 P +1.83 (or the accur) 383.89 182.33 P +1.83 (acy) 440.24 182.33 P +1.83 (, completeness) 454.8 182.33 P +1.83 (, or) 523.72 182.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.68 (usefulness of an) 180 170.33 P +3.68 (y inf) 260.02 170.33 P +3.68 (or) 281.74 170.33 P +3.68 (mation, appar) 290.88 170.33 P +3.68 (atus) 355.59 170.33 P +3.68 (, product or process disclosed, or) 374.34 170.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.46 (represents that its use w) 180 158.33 P +2.46 (ould not infr) 298.11 158.33 P +2.46 (inge pr) 355.42 158.33 P +2.46 (iv) 388.59 158.33 P +2.46 (ately o) 395.56 158.33 P +2.46 (wned r) 427.33 158.33 P +2.46 (ights) 459.95 158.33 P +2.46 (. Ref) 480.92 158.33 P +2.46 (erence) 509.43 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.6 (herein to an) 180 146.33 P +1.6 (y speci\336c commercial product, process) 235.85 146.33 P +1.6 (, or ser) 413.79 146.33 P +1.6 (vice b) 448.4 146.33 P +1.6 (y tr) 475.92 146.33 P +1.6 (ade name) 491.3 146.33 P +1.6 (,) 537.22 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (mar) 180 134.33 P +2.12 (k, man) 197.37 134.33 P +2.12 (uf) 229.4 134.33 P +2.12 (acturer) 237.44 134.33 P +2.12 (, or otherwise) 268.06 134.33 P +2.12 (, does not necessar) 332.17 134.33 P +2.12 (ily constitute or imply its) 425.94 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (endorsement, recommendation, or f) 180 122.33 P +1.08 (a) 341.33 122.33 P +1.08 (v) 346.69 122.33 P +1.08 (or) 351.44 122.33 P +1.08 (ing b) 360.48 122.33 P +1.08 (y the United States go) 383.03 122.33 P +1.08 (v) 485.57 122.33 P +1.08 (er) 490.32 122.33 P +1.08 (nment or) 499.46 122.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (an) 180 110.33 P +0.83 (y agency thereof) 190.97 110.33 P +0.83 (. The vie) 266.26 110.33 P +0.83 (w and opinions of the authors e) 309.67 110.33 P +0.83 (xpressed herein do) 453.3 110.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.94 (not necessar) 180 98.33 P +1.94 (ily state or re\337ect those of the United States go) 239.34 98.33 P +1.94 (v) 464.01 98.33 P +1.94 (er) 468.76 98.33 P +1.94 (nment or an) 477.9 98.33 P +1.94 (y) 535 98.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(agency thereof) 180 86.33 T +(.) 245.85 86.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(DOCUMENT D) 54 668.33 T +(A) 121.37 668.33 T +(TE:) 127.69 668.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(T) 180 668.33 T +(ab) 184.91 668.33 T +(le of contents gener) 195.83 668.33 T +(ated: December 9, 1996 11:44 am) 283.56 668.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "ii" 31 +%%Page: "i" 32 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(i) 555.78 57 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 720 558 720 2 L +0.5 H +2 Z +N +72 72 558 72 2 L +N +72 504 558 504 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +6 32 Q +(cdevCollection Device) 198 662.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Requirements and Design) 198 624.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 12 Q +(W) 198 586 T +(alt Ak) 208.85 586 T +(ers) 238.62 586 T +(, Chip W) 255.11 586 T +(atson, Jie Chen) 300.64 586 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 198 558 T +(ersion 1.5 December 9, 1996) 205.04 558 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(TJNAF - Thomas Jeff) 198 530 T +(erson National Acceler) 311.66 530 T +(ator F) 432.25 530 T +(acility) 463 530 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "i" 32 +%%Trailer +%%BoundingBox: 0 0 612 792 +%%PageOrder: Descend +%%Pages: 32 +%%DocumentFonts: Helvetica +%%+ Helvetica-Bold +%%+ Helvetica-BoldOblique +%%+ Helvetica-Oblique +%%+ Courier-BoldOblique +%%+ Courier-Bold +%%+ Times-BoldItalic +%%EOF diff --git a/doc/ps/cdevGateway.ps b/doc/ps/cdevGateway.ps new file mode 100755 index 0000000..b332f81 --- /dev/null +++ b/doc/ps/cdevGateway.ps @@ -0,0 +1,4664 @@ +%!PS-Adobe-3.0 +%%BoundingBox: (atend) +%%Pages: (atend) +%%PageOrder: (atend) +%%DocumentFonts: (atend) +%%Creator: Frame 5.0 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +% +% Frame ps_prolog 5.0, for use with Frame 5.0 products +% This ps_prolog file is Copyright (c) 1986-1995 Frame Technology +% Corporation. All rights reserved. This ps_prolog file may be +% freely copied and distributed in conjunction with documents created +% using FrameMaker, FrameMaker/SGML and FrameViewer as long as this +% copyright notice is preserved. +% +% FrameMaker users specify the proper paper size for each print job in the +% "Print" dialog's "Printer Paper Size" "Width" and "Height~ fields. If the +% printer that the PS file is sent to does not support the requested paper +% size, or if there is no paper tray of the proper size currently installed, +% then the job will not be printed. The following flag, if set to true, will +% cause the job to print on the default paper in such cases. +/FMAllowPaperSizeMismatch false def +% +% Frame products normally print colors as their true color on a color printer +% or as shades of gray, based on luminance, on a black-and white printer. The +% following flag, if set to true, forces all non-white colors to print as pure +% black. This has no effect on bitmap images. +/FMPrintAllColorsAsBlack false def +% +% Frame products can either set their own line screens or use a printer's +% default settings. Three flags below control this separately for no +% separations, spot separations and process separations. If a flag +% is true, then the default printer settings will not be changed. If it is +% false, Frame products will use their own settings from a table based on +% the printer's resolution. +/FMUseDefaultNoSeparationScreen true def +/FMUseDefaultSpotSeparationScreen true def +/FMUseDefaultProcessSeparationScreen false def +% +% For any given PostScript printer resolution, Frame products have two sets of +% screen angles and frequencies for printing process separations, which are +% recomended by Adobe. The following variable chooses the higher frequencies +% when set to true or the lower frequencies when set to false. This is only +% effective if the appropriate FMUseDefault...SeparationScreen flag is false. +/FMUseHighFrequencyScreens true def +% +% The following is a set of predefined optimal frequencies and angles for various +% common dpi settings. This is taken from "Advances in Color Separation Using +% PostScript Software Technology," from Adobe Systems (3/13/89 P.N. LPS 0043) +% and corrolated with information which is in various PPD (4.0) files. +% +% The "dpiranges" figure is the minimum dots per inch device resolution which +% can support this setting. The "low" and "high" values are controlled by the +% setting of the FMUseHighFrequencyScreens flag above. The "TDot" flags control +% the use of the "Yellow Triple Dot" feature whereby the frequency id divided by +% three, but the dot function is "trippled" giving a block of 3x3 dots per cell. +% +% PatFreq is a compromise pattern frequency for ps Level 2 printers which is close +% to the ideal WYSIWYG pattern frequency of 9 repetitions/inch but does not beat +% (too badly) against the screen frequencies of any separations for that DPI. +/dpiranges [ 2540 2400 1693 1270 1200 635 600 0 ] def +/CMLowFreqs [ 100.402 94.8683 89.2289 100.402 94.8683 66.9349 63.2456 47.4342 ] def +/YLowFreqs [ 95.25 90.0 84.65 95.25 90.0 70.5556 66.6667 50.0 ] def +/KLowFreqs [ 89.8026 84.8528 79.8088 89.8026 84.8528 74.8355 70.7107 53.033 ] def +/CLowAngles [ 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 ] def +/MLowAngles [ 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 ] def +/YLowTDot [ true true false true true false false false ] def +/CMHighFreqs [ 133.87 126.491 133.843 108.503 102.523 100.402 94.8683 63.2456 ] def +/YHighFreqs [ 127.0 120.0 126.975 115.455 109.091 95.25 90.0 60.0 ] def +/KHighFreqs [ 119.737 113.137 119.713 128.289 121.218 89.8026 84.8528 63.6395 ] def +/CHighAngles [ 71.5651 71.5651 71.5651 70.0169 70.0169 71.5651 71.5651 71.5651 ] def +/MHighAngles [ 18.4349 18.4349 18.4349 19.9831 19.9831 18.4349 18.4349 18.4349 ] def +/YHighTDot [ false false true false false true true false ] def +/PatFreq [ 10.5833 10.0 9.4055 10.5833 10.0 10.5833 10.0 9.375 ] def +% +% PostScript Level 2 printers contain an "Accurate Screens" feature which can +% improve process separation rendering at the expense of compute time. This +% flag is ignored by PostScript Level 1 printers. +/FMUseAcccurateScreens true def +% +% The following PostScript procedure defines the spot function that Frame +% products will use for process separations. You may un-comment-out one of +% the alternative functions below, or use your own. +% +% Dot function +/FMSpotFunction {abs exch abs 2 copy add 1 gt + {1 sub dup mul exch 1 sub dup mul add 1 sub } + {dup mul exch dup mul add 1 exch sub }ifelse } def +% +% Line function +% /FMSpotFunction { pop } def +% +% Elipse function +% /FMSpotFunction { dup 5 mul 8 div mul exch dup mul exch add +% sqrt 1 exch sub } def +% +% +/FMversion (5.0) def +/fMLevel1 /languagelevel where {pop languagelevel} {1} ifelse 2 lt def +/FMPColor + fMLevel1 { + false + /colorimage where {pop pop true} if + } { + true + } ifelse +def +/FrameDict 400 dict def +systemdict /errordict known not {/errordict 10 dict def + errordict /rangecheck {stop} put} if +% The readline in PS 23.0 doesn't recognize cr's as nl's on AppleTalk +FrameDict /tmprangecheck errordict /rangecheck get put +errordict /rangecheck {FrameDict /bug true put} put +FrameDict /bug false put +mark +% Some PS machines read past the CR, so keep the following 3 lines together! +currentfile 5 string readline +00 +0000000000 +cleartomark +errordict /rangecheck FrameDict /tmprangecheck get put +FrameDict /bug get { + /readline { + /gstring exch def + /gfile exch def + /gindex 0 def + { + gfile read pop + dup 10 eq {exit} if + dup 13 eq {exit} if + gstring exch gindex exch put + /gindex gindex 1 add def + } loop + pop + gstring 0 gindex getinterval true + } bind def + } if +/FMshowpage /showpage load def +/FMquit /quit load def +/FMFAILURE { + dup = flush + FMshowpage + /Helvetica findfont 12 scalefont setfont + 72 200 moveto show + 72 220 moveto show + FMshowpage + FMquit + } def +/FMVERSION { + FMversion ne { + (Frame product version does not match ps_prolog! Check installation;) + (also check ~/fminit and ./fminit for old versions) FMFAILURE + } if + } def +/FMBADEPSF { + (Adobe's PostScript Language Reference Manual, 2nd Edition, section H.2.4) + (says your EPS file is not valid, as it calls X ) + dup dup (X) search pop exch pop exch pop length + 5 -1 roll + putinterval + FMFAILURE + } def +/fmConcatProcs + { + /proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def + newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx +}def +FrameDict begin [ + /ALDsave + /FMdicttop + /FMoptop + /FMpointsize + /FMsaveobject + /b + /bitmapsave + /blut + /bpside + /bs + /bstring + /bwidth + /c + /cf + /cs + /cynu + /depth + /edown + /fh + /fillvals + /fw + /fx + /fy + /g + /gfile + /gindex + /grnt + /gryt + /gstring + /height + /hh + /i + /im + /indx + /is + /k + /kk + /landscape + /lb + /len + /llx + /lly + /m + /magu + /manualfeed + /n + /offbits + /onbits + /organgle + /orgbangle + /orgbfreq + /orgbproc + /orgbxfer + /orgfreq + /orggangle + /orggfreq + /orggproc + /orggxfer + /orgmatrix + /orgproc + /orgrangle + /orgrfreq + /orgrproc + /orgrxfer + /orgxfer + /pagesave + /paperheight + /papersizedict + /paperwidth + /pos + /pwid + /r + /rad + /redt + /sl + /str + /tran + /u + /urx + /ury + /val + /width + /width + /ws + /ww + /x + /x1 + /x2 + /xindex + /xpoint + /xscale + /xx + /y + /y1 + /y2 + /yelu + /yindex + /ypoint + /yscale + /yy +] { 0 def } forall +/FmBD {bind def} bind def +systemdict /pdfmark known { + /fMAcrobat true def + + /FmPD /pdfmark load def + + + /FmPT /show load def + + + currentdistillerparams /CoreDistVersion get 2000 ge { + + + /FmPD2 /pdfmark load def + + + + + + /FmPA { mark exch /Dest exch 5 3 roll + /View [ /XYZ null 6 -2 roll FmDC exch pop null] /DEST FmPD + }FmBD + } { + + /FmPD2 /cleartomark load def + /FmPA {pop pop pop}FmBD + } ifelse +} { + + /fMAcrobat false def + /FmPD /cleartomark load def + /FmPD2 /cleartomark load def + /FmPT /pop load def + /FmPA {pop pop pop}FmBD +} ifelse +/FmDC { + transform fMDefaultMatrix itransform cvi exch cvi exch +}FmBD +/FmBx { + dup 3 index lt {3 1 roll exch} if + 1 index 4 index lt {4 -1 roll 3 1 roll exch 4 1 roll} if +}FmBD +/FMnone 0 def +/FMcyan 1 def +/FMmagenta 2 def +/FMyellow 3 def +/FMblack 4 def +/FMcustom 5 def +/fMNegative false def +/FrameSepIs FMnone def +/FrameSepBlack 0 def +/FrameSepYellow 0 def +/FrameSepMagenta 0 def +/FrameSepCyan 0 def +/FrameSepRed 1 def +/FrameSepGreen 1 def +/FrameSepBlue 1 def +/FrameCurGray 1 def +/FrameCurPat null def +/FrameCurColors [ 0 0 0 1 0 0 0 ] def +/FrameColorEpsilon .001 def +/eqepsilon { + sub dup 0 lt {neg} if + FrameColorEpsilon le +} bind def +/FrameCmpColorsCMYK { + 2 copy 0 get exch 0 get eqepsilon { + 2 copy 1 get exch 1 get eqepsilon { + 2 copy 2 get exch 2 get eqepsilon { + 3 get exch 3 get eqepsilon + } {pop pop false} ifelse + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/FrameCmpColorsRGB { + 2 copy 4 get exch 0 get eqepsilon { + 2 copy 5 get exch 1 get eqepsilon { + 6 get exch 2 get eqepsilon + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/RGBtoCMYK { + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 3 copy + 2 copy + le { pop } { exch pop } ifelse + 2 copy + le { pop } { exch pop } ifelse + dup dup dup + 6 1 roll + 4 1 roll + 7 1 roll + sub + 6 1 roll + sub + 5 1 roll + sub + 4 1 roll +} bind def +/CMYKtoRGB { + dup dup 4 -1 roll add + 5 1 roll 3 -1 roll add + 4 1 roll add + 1 exch sub dup 0 lt {pop 0} if 3 1 roll + 1 exch sub dup 0 lt {pop 0} if exch + 1 exch sub dup 0 lt {pop 0} if exch +} bind def +/FrameSepInit { + 1.0 RealSetgray +} bind def +/FrameSetSepColor { + /FrameSepBlue exch def + /FrameSepGreen exch def + /FrameSepRed exch def + /FrameSepBlack exch def + /FrameSepYellow exch def + /FrameSepMagenta exch def + /FrameSepCyan exch def + /FrameSepIs FMcustom def + setCurrentScreen +} bind def +/FrameSetCyan { + /FrameSepBlue 1.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 1.0 def + /FrameSepIs FMcyan def + setCurrentScreen +} bind def + +/FrameSetMagenta { + /FrameSepBlue 1.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 1.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMmagenta def + setCurrentScreen +} bind def + +/FrameSetYellow { + /FrameSepBlue 0.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 1.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMyellow def + setCurrentScreen +} bind def + +/FrameSetBlack { + /FrameSepBlue 0.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 1.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMblack def + setCurrentScreen +} bind def + +/FrameNoSep { + /FrameSepIs FMnone def + setCurrentScreen +} bind def +/FrameSetSepColors { + FrameDict begin + [ exch 1 add 1 roll ] + /FrameSepColors + exch def end + } bind def +/FrameColorInSepListCMYK { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsCMYK + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/FrameColorInSepListRGB { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsRGB + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/RealSetgray /setgray load def +/RealSetrgbcolor /setrgbcolor load def +/RealSethsbcolor /sethsbcolor load def +end +/setgray { + FrameDict begin + FrameSepIs FMnone eq + { RealSetgray } + { + FrameSepIs FMblack eq + { RealSetgray } + { FrameSepIs FMcustom eq + FrameSepRed 0 eq and + FrameSepGreen 0 eq and + FrameSepBlue 0 eq and { + RealSetgray + } { + 1 RealSetgray pop + } ifelse + } ifelse + } ifelse + end +} bind def +/setrgbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetrgbcolor } + { + 3 copy [ 4 1 roll ] + FrameColorInSepListRGB + { + FrameSepBlue eq exch + FrameSepGreen eq and exch + FrameSepRed eq and + { 0 } { 1 } ifelse + } + { + FMPColor { + RealSetrgbcolor + currentcmykcolor + } { + RGBtoCMYK + } ifelse + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end +} bind def +/sethsbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSethsbcolor } + { + RealSethsbcolor + currentrgbcolor + setrgbcolor + } + ifelse + end +} bind def +FrameDict begin +/setcmykcolor where { + pop /RealSetcmykcolor /setcmykcolor load def +} { + /RealSetcmykcolor { + 4 1 roll + 3 { 3 index add 0 max 1 min 1 exch sub 3 1 roll} repeat + RealSetrgbcolor pop + } bind def +} ifelse +userdict /setcmykcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetcmykcolor } + { + 4 copy [ 5 1 roll ] + FrameColorInSepListCMYK + { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + { 0 } { 1 } ifelse + } + { + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end + } bind put +fMLevel1 { + + + + /patScreenDict 7 dict dup begin + <0f1e3c78f0e1c387> [ 45 { pop } {exch pop} .5 2 sqrt] FmBD + <0f87c3e1f0783c1e> [ 135 { pop } {exch pop} .5 2 sqrt] FmBD + [ 0 { pop } dup .5 2 ] FmBD + [ 90 { pop } dup .5 2 ] FmBD + <8142241818244281> [ 45 { 2 copy lt {exch} if pop} dup .75 2 sqrt] FmBD + <03060c183060c081> [ 45 { pop } {exch pop} .875 2 sqrt] FmBD + <8040201008040201> [ 135 { pop } {exch pop} .875 2 sqrt] FmBD + end def +} { + + /patProcDict 5 dict dup begin + <0f1e3c78f0e1c387> { 3 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <0f87c3e1f0783c1e> { 3 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + <8142241818244281> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -1 -1 moveto 9 9 lineto stroke } bind def + <03060c183060c081> { 1 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <8040201008040201> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + end def + /patDict 15 dict dup begin + /PatternType 1 def + /PaintType 2 def + /TilingType 3 def + /BBox [ 0 0 8 8 ] def + /XStep 8 def + /YStep 8 def + /PaintProc { + begin + patProcDict bstring known { + patProcDict bstring get exec + } { + 8 8 true [1 0 0 -1 0 8] bstring imagemask + } ifelse + end + } bind def + end def +} ifelse +/combineColor { + FrameSepIs FMnone eq + { + graymode fMLevel1 or not { + + [/Pattern [/DeviceCMYK]] setcolorspace + FrameCurColors 0 4 getinterval aload pop FrameCurPat setcolor + } { + FrameCurColors 3 get 1.0 ge { + FrameCurGray RealSetgray + } { + fMAcrobat not FMPColor graymode and and { + 0 1 3 { + FrameCurColors exch get + 1 FrameCurGray sub mul + } for + RealSetcmykcolor + } { + 4 1 6 { + FrameCurColors exch get + graymode { + 1 exch sub 1 FrameCurGray sub mul 1 exch sub + } { + 1.0 lt {FrameCurGray} {1} ifelse + } ifelse + } for + RealSetrgbcolor + } ifelse + } ifelse + } ifelse + } { + FrameCurColors 0 4 getinterval aload + FrameColorInSepListCMYK { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + FrameSepIs FMcustom eq and + { FrameCurGray } { 1 } ifelse + } { + FrameSepIs FMblack eq + {FrameCurGray 1.0 exch sub mul 1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop FrameCurGray 1.0 exch sub mul 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + graymode fMLevel1 or not { + + [/Pattern [/DeviceGray]] setcolorspace + FrameCurPat setcolor + } { + graymode not fMLevel1 and { + + dup 1 lt {pop FrameCurGray} if + } if + RealSetgray + } ifelse + } ifelse +} bind def +/savematrix { + orgmatrix currentmatrix pop + } bind def +/restorematrix { + orgmatrix setmatrix + } bind def +/fMDefaultMatrix matrix defaultmatrix def +/fMatrix2 matrix def +/dpi 72 0 fMDefaultMatrix dtransform + dup mul exch dup mul add sqrt def + +/freq dpi dup 72 div round dup 0 eq {pop 1} if 8 mul div def +/sangle 1 0 fMDefaultMatrix dtransform exch atan def + sangle fMatrix2 rotate + fMDefaultMatrix fMatrix2 concatmatrix + dup 0 get /sflipx exch def + 3 get /sflipy exch def +/screenIndex { + 0 1 dpiranges length 1 sub { dup dpiranges exch get 1 sub dpi le {exit} {pop} ifelse } for +} bind def +/getCyanScreen { + FMUseHighFrequencyScreens { CHighAngles CMHighFreqs} {CLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getMagentaScreen { + FMUseHighFrequencyScreens { MHighAngles CMHighFreqs } {MLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getYellowScreen { + FMUseHighFrequencyScreens { YHighTDot YHighFreqs} { YLowTDot YLowFreqs } ifelse + screenIndex dup 3 1 roll get 3 1 roll get { 3 div + {2 { 1 add 2 div 3 mul dup floor sub 2 mul 1 sub exch} repeat + FMSpotFunction } } {/FMSpotFunction load } ifelse + 0.0 exch +} bind def +/getBlackScreen { + FMUseHighFrequencyScreens { KHighFreqs } { KLowFreqs } ifelse + screenIndex get 45.0 /FMSpotFunction load +} bind def +/getSpotScreen { + getBlackScreen +} bind def +/getCompositeScreen { + getBlackScreen +} bind def +/FMSetScreen + fMLevel1 { /setscreen load + }{ { + 8 dict begin + /HalftoneType 1 def + /SpotFunction exch def + /Angle exch def + /Frequency exch def + /AccurateScreens FMUseAcccurateScreens def + currentdict end sethalftone + } bind } ifelse +def +/setDefaultScreen { + FMPColor { + orgrxfer cvx orggxfer cvx orgbxfer cvx orgxfer cvx setcolortransfer + } + { + orgxfer cvx settransfer + } ifelse + orgfreq organgle orgproc cvx setscreen +} bind def +/setCurrentScreen { + FrameSepIs FMnone eq { + FMUseDefaultNoSeparationScreen { + setDefaultScreen + } { + getCompositeScreen FMSetScreen + } ifelse + } { + FrameSepIs FMcustom eq { + FMUseDefaultSpotSeparationScreen { + setDefaultScreen + } { + getSpotScreen FMSetScreen + } ifelse + } { + FMUseDefaultProcessSeparationScreen { + setDefaultScreen + } { + FrameSepIs FMcyan eq { + getCyanScreen FMSetScreen + } { + FrameSepIs FMmagenta eq { + getMagentaScreen FMSetScreen + } { + FrameSepIs FMyellow eq { + getYellowScreen FMSetScreen + } { + getBlackScreen FMSetScreen + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse +} bind def +end + +/FMDOCUMENT { + array /FMfonts exch def + /#copies exch def + FrameDict begin + 0 ne /manualfeed exch def + /paperheight exch def + /paperwidth exch def + 0 ne /fMNegative exch def + 0 ne /edown exch def + /yscale exch def + /xscale exch def + fMLevel1 { + manualfeed {setmanualfeed} if + /FMdicttop countdictstack 1 add def + /FMoptop count def + setpapername + manualfeed {true} {papersize} ifelse + {manualpapersize} {false} ifelse + {desperatepapersize} {false} ifelse + {papersizefailure} if + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + } + {2 dict + dup /PageSize [paperwidth paperheight] put + manualfeed {dup /ManualFeed manualfeed put} if + {setpagedevice} stopped {papersizefailure} if + } + ifelse + + FMPColor { + currentcolorscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + cvlit /orgbproc exch def + /orgbangle exch def + /orgbfreq exch def + cvlit /orggproc exch def + /orggangle exch def + /orggfreq exch def + cvlit /orgrproc exch def + /orgrangle exch def + /orgrfreq exch def + currentcolortransfer + fMNegative { + 1 1 4 { + pop { 1 exch sub } fmConcatProcs 4 1 roll + } for + 4 copy + setcolortransfer + } if + cvlit /orgxfer exch def + cvlit /orgbxfer exch def + cvlit /orggxfer exch def + cvlit /orgrxfer exch def + } { + currentscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + + currenttransfer + fMNegative { + { 1 exch sub } fmConcatProcs + dup settransfer + } if + cvlit /orgxfer exch def + } ifelse + end +} def +/FMBEGINPAGE { + FrameDict begin + /pagesave save def + 3.86 setmiterlimit + /landscape exch 0 ne def + landscape { + 90 rotate 0 exch dup /pwid exch def neg translate pop + }{ + pop /pwid exch def + } ifelse + edown { [-1 0 0 1 pwid 0] concat } if + 0 0 moveto paperwidth 0 lineto paperwidth paperheight lineto + 0 paperheight lineto 0 0 lineto 1 setgray fill + xscale yscale scale + /orgmatrix matrix def + gsave +} def +/FMENDPAGE { + grestore + pagesave restore + end + showpage + } def +/FMFONTDEFINE { + FrameDict begin + findfont + ReEncode + 1 index exch + definefont + FMfonts 3 1 roll + put + end + } def +/FMFILLS { + FrameDict begin dup + array /fillvals exch def + dict /patCache exch def + end + } def +/FMFILL { + FrameDict begin + fillvals 3 1 roll put + end + } def +/FMNORMALIZEGRAPHICS { + newpath + 1 setlinewidth + 0 setlinecap + 0 0 0 sethsbcolor + 0 setgray + } bind def +/FMBEGINEPSF { + end + /FMEPSF save def + /showpage {} def +% See Adobe's "PostScript Language Reference Manual, 2nd Edition", page 714. +% "...the following operators MUST NOT be used in an EPS file:" (emphasis ours) + /banddevice {(banddevice) FMBADEPSF} def + /clear {(clear) FMBADEPSF} def + /cleardictstack {(cleardictstack) FMBADEPSF} def + /copypage {(copypage) FMBADEPSF} def + /erasepage {(erasepage) FMBADEPSF} def + /exitserver {(exitserver) FMBADEPSF} def + /framedevice {(framedevice) FMBADEPSF} def + /grestoreall {(grestoreall) FMBADEPSF} def + /initclip {(initclip) FMBADEPSF} def + /initgraphics {(initgraphics) FMBADEPSF} def + /quit {(quit) FMBADEPSF} def + /renderbands {(renderbands) FMBADEPSF} def + /setglobal {(setglobal) FMBADEPSF} def + /setpagedevice {(setpagedevice) FMBADEPSF} def + /setshared {(setshared) FMBADEPSF} def + /startjob {(startjob) FMBADEPSF} def + /lettertray {(lettertray) FMBADEPSF} def + /letter {(letter) FMBADEPSF} def + /lettersmall {(lettersmall) FMBADEPSF} def + /11x17tray {(11x17tray) FMBADEPSF} def + /11x17 {(11x17) FMBADEPSF} def + /ledgertray {(ledgertray) FMBADEPSF} def + /ledger {(ledger) FMBADEPSF} def + /legaltray {(legaltray) FMBADEPSF} def + /legal {(legal) FMBADEPSF} def + /statementtray {(statementtray) FMBADEPSF} def + /statement {(statement) FMBADEPSF} def + /executivetray {(executivetray) FMBADEPSF} def + /executive {(executive) FMBADEPSF} def + /a3tray {(a3tray) FMBADEPSF} def + /a3 {(a3) FMBADEPSF} def + /a4tray {(a4tray) FMBADEPSF} def + /a4 {(a4) FMBADEPSF} def + /a4small {(a4small) FMBADEPSF} def + /b4tray {(b4tray) FMBADEPSF} def + /b4 {(b4) FMBADEPSF} def + /b5tray {(b5tray) FMBADEPSF} def + /b5 {(b5) FMBADEPSF} def + FMNORMALIZEGRAPHICS + [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall + fx fw 2 div add fy fh 2 div add translate + rotate + fw 2 div neg fh 2 div neg translate + fw urx llx sub div fh ury lly sub div scale + llx neg lly neg translate + /FMdicttop countdictstack 1 add def + /FMoptop count def + } bind def +/FMENDEPSF { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMEPSF restore + FrameDict begin + } bind def +FrameDict begin +/setmanualfeed { +%%BeginFeature *ManualFeed True + statusdict /manualfeed true put +%%EndFeature + } bind def +/max {2 copy lt {exch} if pop} bind def +/min {2 copy gt {exch} if pop} bind def +/inch {72 mul} def +/pagedimen { + paperheight sub abs 16 lt exch + paperwidth sub abs 16 lt and + {/papername exch def} {pop} ifelse + } bind def +/setpapername { + /papersizedict 14 dict def + papersizedict begin + /papername /unknown def + /Letter 8.5 inch 11.0 inch pagedimen + /LetterSmall 7.68 inch 10.16 inch pagedimen + /Tabloid 11.0 inch 17.0 inch pagedimen + /Ledger 17.0 inch 11.0 inch pagedimen + /Legal 8.5 inch 14.0 inch pagedimen + /Statement 5.5 inch 8.5 inch pagedimen + /Executive 7.5 inch 10.0 inch pagedimen + /A3 11.69 inch 16.5 inch pagedimen + /A4 8.26 inch 11.69 inch pagedimen + /A4Small 7.47 inch 10.85 inch pagedimen + /B4 10.125 inch 14.33 inch pagedimen + /B5 7.16 inch 10.125 inch pagedimen + end + } bind def +/papersize { + papersizedict begin + /Letter {lettertray letter} def + /LetterSmall {lettertray lettersmall} def + /Tabloid {11x17tray 11x17} def + /Ledger {ledgertray ledger} def + /Legal {legaltray legal} def + /Statement {statementtray statement} def + /Executive {executivetray executive} def + /A3 {a3tray a3} def + /A4 {a4tray a4} def + /A4Small {a4tray a4small} def + /B4 {b4tray b4} def + /B5 {b5tray b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + statusdict begin stopped end + } bind def +/manualpapersize { + papersizedict begin + /Letter {letter} def + /LetterSmall {lettersmall} def + /Tabloid {11x17} def + /Ledger {ledger} def + /Legal {legal} def + /Statement {statement} def + /Executive {executive} def + /A3 {a3} def + /A4 {a4} def + /A4Small {a4small} def + /B4 {b4} def + /B5 {b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + stopped + } bind def +/desperatepapersize { + statusdict /setpageparams known + { + paperwidth paperheight 0 1 + statusdict begin + {setpageparams} stopped + end + } {true} ifelse + } bind def +/papersizefailure { + FMAllowPaperSizeMismatch not + { +(The requested paper size is not available in any currently-installed tray) +(Edit the PS file to "FMAllowPaperSizeMismatch true" to use default tray) + FMFAILURE } if + } def +/DiacriticEncoding [ +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl +/numbersign /dollar /percent /ampersand /quotesingle /parenleft +/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K +/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash +/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h +/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar +/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute +/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis +/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis +/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve +/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex +/udieresis /dagger /.notdef /cent /sterling /section /bullet +/paragraph /germandbls /registered /copyright /trademark /acute +/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef +/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown +/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef +/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde +/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright +/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis +/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl +/periodcentered /quotesinglbase /quotedblbase /perthousand +/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute +/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve +/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron +/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +] def +/ReEncode { + dup + length + dict begin + { + 1 index /FID ne + {def} + {pop pop} ifelse + } forall + 0 eq {/Encoding DiacriticEncoding def} if + currentdict + end + } bind def +FMPColor + + { + /BEGINBITMAPCOLOR { + BITMAPCOLOR} def + /BEGINBITMAPCOLORc { + BITMAPCOLORc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUECOLOR } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUECOLORc } def + /BEGINBITMAPCMYK { + BITMAPCMYK } def + /BEGINBITMAPCMYKc { + BITMAPCMYKc } def + } + + { + /BEGINBITMAPCOLOR { + BITMAPGRAY} def + /BEGINBITMAPCOLORc { + BITMAPGRAYc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUEGRAY } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUEGRAYc } def + /BEGINBITMAPCMYK { + BITMAPCMYKGRAY } def + /BEGINBITMAPCMYKc { + BITMAPCMYKGRAYc } def + } +ifelse +/K { + FMPrintAllColorsAsBlack { + dup 1 eq 2 index 1 eq and 3 index 1 eq and not + {7 {pop} repeat 0 0 0 1 0 0 0} if + } if + FrameCurColors astore + pop combineColor +} bind def +/graymode true def +fMLevel1 { + /fmGetFlip { + fMatrix2 exch get mul 0 lt { -1 } { 1 } ifelse + } FmBD +} if +/setPatternMode { + fMLevel1 { + 2 index patScreenDict exch known { + pop pop + patScreenDict exch get aload pop + freq + mul + 5 2 roll + fMatrix2 currentmatrix 1 get 0 ne { + 3 -1 roll 90 add 3 1 roll + sflipx 1 fmGetFlip sflipy 2 fmGetFlip neg mul + } { + sflipx 0 fmGetFlip sflipy 3 fmGetFlip mul + } ifelse + 0 lt {exch pop} {pop} ifelse + fMNegative { + {neg} fmConcatProcs + } if + bind + + + + systemdict /setscreen get exec + /FrameCurGray exch def + } { + /bwidth exch def + /bpside exch def + /bstring exch def + /onbits 0 def /offbits 0 def + freq sangle landscape {90 add} if + {/ypoint exch def + /xpoint exch def + /xindex xpoint 1 add 2 div bpside mul cvi def + /yindex ypoint 1 add 2 div bpside mul cvi def + bstring yindex bwidth mul xindex 8 idiv add get + 1 7 xindex 8 mod sub bitshift and 0 ne fMNegative {not} if + {/onbits onbits 1 add def 1} + {/offbits offbits 1 add def 0} + ifelse + } + setscreen + offbits offbits onbits add div fMNegative {1.0 exch sub} if + /FrameCurGray exch def + } ifelse + } { + pop pop + dup patCache exch known { + patCache exch get + } { + dup + patDict /bstring 3 -1 roll put + patDict + 9 PatFreq screenIndex get div dup matrix scale + makepattern + dup + patCache 4 -1 roll 3 -1 roll put + } ifelse + /FrameCurGray 0 def + /FrameCurPat exch def + } ifelse + /graymode false def + combineColor +} bind def +/setGrayScaleMode { + graymode not { + /graymode true def + fMLevel1 { + setCurrentScreen + } if + } if + /FrameCurGray exch def + combineColor +} bind def +/normalize { + transform round exch round exch itransform + } bind def +/dnormalize { + dtransform round exch round exch idtransform + } bind def +/lnormalize { + 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop + } bind def +/H { + lnormalize setlinewidth + } bind def +/Z { + setlinecap + } bind def + +/PFill { + graymode fMLevel1 or not { + gsave 1 setgray eofill grestore + } if +} bind def +/PStroke { + graymode fMLevel1 or not { + gsave 1 setgray stroke grestore + } if + stroke +} bind def +/X { + fillvals exch get + dup type /stringtype eq + {8 1 setPatternMode} + {setGrayScaleMode} + ifelse + } bind def +/V { + PFill gsave eofill grestore + } bind def +/Vclip { + clip + } bind def +/Vstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/N { + PStroke + } bind def +/Nclip { + strokepath clip newpath + } bind def +/Nstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/M {newpath moveto} bind def +/E {lineto} bind def +/D {curveto} bind def +/O {closepath} bind def +/L { + /n exch def + newpath + normalize + moveto + 2 1 n {pop normalize lineto} for + } bind def +/Y { + L + closepath + } bind def +/R { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + x1 y1 + x2 y1 + x2 y2 + x1 y2 + 4 Y + } bind def +/rarc + {rad + arcto + } bind def +/RR { + /rad exch def + normalize + /y2 exch def + /x2 exch def + normalize + /y1 exch def + /x1 exch def + mark + newpath + { + x1 y1 rad add moveto + x1 y2 x2 y2 rarc + x2 y2 x2 y1 rarc + x2 y1 x1 y1 rarc + x1 y1 x1 y2 rarc + closepath + } stopped {x1 y1 x2 y2 R} if + cleartomark + } bind def +/RRR { + /rad exch def + normalize /y4 exch def /x4 exch def + normalize /y3 exch def /x3 exch def + normalize /y2 exch def /x2 exch def + normalize /y1 exch def /x1 exch def + newpath + normalize moveto + mark + { + x2 y2 x3 y3 rarc + x3 y3 x4 y4 rarc + x4 y4 x1 y1 rarc + x1 y1 x2 y2 rarc + closepath + } stopped + {x1 y1 x2 y2 x3 y3 x4 y4 newpath moveto lineto lineto lineto closepath} if + cleartomark + } bind def +/C { + grestore + gsave + R + clip + setCurrentScreen +} bind def +/CP { + grestore + gsave + Y + clip + setCurrentScreen +} bind def +/F { + FMfonts exch get + FMpointsize scalefont + setfont + } bind def +/Q { + /FMpointsize exch def + F + } bind def +/T { + moveto show + } bind def +/RF { + rotate + 0 ne {-1 1 scale} if + } bind def +/TF { + gsave + moveto + RF + show + grestore + } bind def +/P { + moveto + 0 32 3 2 roll widthshow + } bind def +/PF { + gsave + moveto + RF + 0 32 3 2 roll widthshow + grestore + } bind def +/S { + moveto + 0 exch ashow + } bind def +/SF { + gsave + moveto + RF + 0 exch ashow + grestore + } bind def +/B { + moveto + 0 32 4 2 roll 0 exch awidthshow + } bind def +/BF { + gsave + moveto + RF + 0 32 4 2 roll 0 exch awidthshow + grestore + } bind def +/G { + gsave + newpath + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill fill + grestore + } bind def +/Gstrk { + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/Gclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GG { + gsave + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill + fill + grestore + } bind def +/GGclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GGstrk { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/A { + gsave + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/Aclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/Astrk { + Gstrk +} bind def +/AA { + gsave + savematrix + newpath + + 3 index 2 div add exch 4 index 2 div sub exch + + normalize 3 index 2 div sub exch 4 index 2 div add exch + translate + rotate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/AAclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/AAstrk { + GGstrk +} bind def +/BEGINPRINTCODE { + /FMdicttop countdictstack 1 add def + /FMoptop count 7 sub def + /FMsaveobject save def + userdict begin + /showpage {} def + FMNORMALIZEGRAPHICS + 3 index neg 3 index neg translate + } bind def +/ENDPRINTCODE { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMsaveobject restore + } bind def +/gn { + 0 + { 46 mul + cf read pop + 32 sub + dup 46 lt {exit} if + 46 sub add + } loop + add + } bind def +/cfs { + /str sl string def + 0 1 sl 1 sub {str exch val put} for + str def + } bind def +/ic [ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 + {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx} + {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx} + {19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} + {13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh} + {4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh} + {13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl} + {7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl} + {0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl} + {10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl} + ] def +/ms { + /sl exch def + /val 255 def + /ws cfs + /im cfs + /val 0 def + /bs cfs + /cs cfs + } bind def +400 ms +/ip { + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip { + + + bis ris copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + ris gis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + gis bis copy pop + dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip4 { + + + kis cis copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + cis mis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + mis yis copy pop + dup dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + yis kis copy pop + 3 mul is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/wh { + /len exch def + /pos exch def + ws 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/bl { + /len exch def + /pos exch def + bs 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/s1 1 string def +/fl { + /len exch def + /pos exch def + /val cf s1 readhexstring pop 0 get def + pos 1 pos len add 1 sub {im exch val put} for + pos len + } bind def +/hx { + 3 copy getinterval + cf exch readhexstring pop pop + } bind def +/wbytes { + dup dup + 8 gt { pop 8 idiv mul } + { 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse } ifelse + } bind def +/BEGINBITMAPBWc { + 1 {} COMMONBITMAPc + } bind def +/BEGINBITMAPGRAYc { + 8 {} COMMONBITMAPc + } bind def +/BEGINBITMAP2BITc { + 2 {} COMMONBITMAPc + } bind def +/COMMONBITMAPc { + + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + cvtProc + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} image + bitmapsave restore + grestore + } bind def +/BEGINBITMAPBW { + 1 {} COMMONBITMAP + } bind def +/BEGINBITMAPGRAY { + 8 {} COMMONBITMAP + } bind def +/BEGINBITMAP2BIT { + 2 {} COMMONBITMAP + } bind def +/COMMONBITMAP { + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + cvtProc + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} image + bitmapsave restore + grestore + } bind def +/ngrayt 256 array def +/nredt 256 array def +/nbluet 256 array def +/ngreent 256 array def +fMLevel1 { +/colorsetup { + currentcolortransfer + /gryt exch def + /blut exch def + /grnt exch def + /redt exch def + 0 1 255 { + /indx exch def + /cynu 1 red indx get 255 div sub def + /magu 1 green indx get 255 div sub def + /yelu 1 blue indx get 255 div sub def + /kk cynu magu min yelu min def + /u kk currentundercolorremoval exec def +% /u 0 def + nredt indx 1 0 cynu u sub max sub redt exec put + ngreent indx 1 0 magu u sub max sub grnt exec put + nbluet indx 1 0 yelu u sub max sub blut exec put + ngrayt indx 1 kk currentblackgeneration exec sub gryt exec put + } for + {255 mul cvi nredt exch get} + {255 mul cvi ngreent exch get} + {255 mul cvi nbluet exch get} + {255 mul cvi ngrayt exch get} + setcolortransfer + {pop 0} setundercolorremoval + {} setblackgeneration + } bind def +} +{ +/colorSetup2 { + [ /Indexed /DeviceRGB 255 + {dup red exch get 255 div + exch dup green exch get 255 div + exch blue exch get 255 div} + ] setcolorspace +} bind def +} ifelse +/fakecolorsetup { + /tran 256 string def + 0 1 255 {/indx exch def + tran indx + red indx get 77 mul + green indx get 151 mul + blue indx get 28 mul + add add 256 idiv put} for + currenttransfer + {255 mul cvi tran exch get 255.0 div} + exch fmConcatProcs settransfer +} bind def +/BITMAPCOLOR { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + fMLevel1 { + colorsetup + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} {is} {is} true 3 colorimage + } { + colorSetup2 + /is width depth wbytes string def + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {cf is readhexstring pop} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPCOLORc { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + fMLevel1 { + colorsetup + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} {is} {is} true 3 colorimage + } { + colorSetup2 + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {ip} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLORc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris} {gis} {bis} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYKc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip4 pop cis} {mis} {yis} {kis} true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLOR { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf gis readhexstring pop } + { cf bis readhexstring pop } + true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYK { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /mis width string def + /yis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf mis readhexstring pop } + { cf yis readhexstring pop } + { cf kis readhexstring pop } + true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUEGRAYc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris gis bis width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAYc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop cis mis yis kis width cgray} image + bitmapsave restore + grestore + } bind def +/cgray { + /ww exch def + /k exch def + /y exch def + /m exch def + /c exch def + 0 1 ww 1 sub { /i exch def c i get m i get y i get k i get CMYKtoRGB + .144 mul 3 1 roll .587 mul 3 1 roll .299 mul add add + c i 3 -1 roll floor cvi put } for + c + } bind def +/gray { + /ww exch def + /b exch def + /g exch def + /r exch def + 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul + b i get .114 mul add add r i 3 -1 roll floor cvi put } for + r + } bind def +/BITMAPTRUEGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf gis readhexstring pop + cf bis readhexstring pop width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /yis width string def + /mis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf mis readhexstring pop + cf yis readhexstring pop + cf kis readhexstring pop width cgray} image + bitmapsave restore + grestore + } bind def +/BITMAPGRAY { + 8 {fakecolorsetup} COMMONBITMAP + } bind def +/BITMAPGRAYc { + 8 {fakecolorsetup} COMMONBITMAPc + } bind def +/ENDBITMAP { + } bind def +end + /ALDmatrix matrix def ALDmatrix currentmatrix pop +/StartALD { + /ALDsave save def + savematrix + ALDmatrix setmatrix + } bind def +/InALD { + restorematrix + } bind def +/DoneALD { + ALDsave restore + } bind def +/I { setdash } bind def +/J { [] 0 setdash } bind def +%%EndProlog +%%BeginSetup +(5.0) FMVERSION +1 1 0 0 612 792 0 1 9 FMDOCUMENT +0 0 /Helvetica FMFONTDEFINE +1 0 /Times-BoldItalic FMFONTDEFINE +2 0 /Helvetica-Bold FMFONTDEFINE +3 0 /Helvetica-Oblique FMFONTDEFINE +4 0 /Helvetica-BoldOblique FMFONTDEFINE +5 0 /Courier-BoldOblique FMFONTDEFINE +32 FMFILLS +0 0 FMFILL +1 0.1 FMFILL +2 0.3 FMFILL +3 0.5 FMFILL +4 0.7 FMFILL +5 0.9 FMFILL +6 0.97 FMFILL +7 1 FMFILL +8 <0f1e3c78f0e1c387> FMFILL +9 <0f87c3e1f0783c1e> FMFILL +10 FMFILL +11 FMFILL +12 <8142241818244281> FMFILL +13 <03060c183060c081> FMFILL +14 <8040201008040201> FMFILL +16 1 FMFILL +17 0.9 FMFILL +18 0.7 FMFILL +19 0.5 FMFILL +20 0.3 FMFILL +21 0.1 FMFILL +22 0.03 FMFILL +23 0 FMFILL +24 FMFILL +25 FMFILL +26 <3333333333333333> FMFILL +27 <0000ffff0000ffff> FMFILL +28 <7ebddbe7e7dbbd7e> FMFILL +29 FMFILL +30 <7fbfdfeff7fbfdfe> FMFILL +%%EndSetup +%%Page: "i" 1 +%%BeginPaperSize: Letter +%%EndPaperSize +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(i) 555.78 57 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 720 558 720 2 L +0.5 H +2 Z +N +72 72 558 72 2 L +N +72 504 558 504 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 32 Q +(CDEV Gatew) 198 662.67 T +(ay) 376.37 662.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(A Message Router/Concentr) 198 627.33 T +(ator f) 324.06 627.33 T +(or CDEV Clients) 346.55 627.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(W) 198 603.33 T +(alt Ak) 207.04 603.33 T +(ers) 231.85 603.33 T +(, Chip W) 245.59 603.33 T +(atson, Jie Chen) 283.53 603.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 198 579.33 T +(ersion 1.0 - F) 203.87 579.33 T +(ebr) 262.48 579.33 T +(uar) 277.08 579.33 T +(y 13, 1997) 291.83 579.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(TJNAF - Thomas Jeff) 198 555.33 T +(erson National Acceler) 292.72 555.33 T +(ator F) 393.21 555.33 T +(acility) 418.83 555.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "i" 1 +%%Page: "ii" 2 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(ii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(TRADEMARKS:) 54 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(UNIX is a registered tr) 180 569.33 T +(ademar) 278.26 569.33 T +(k of A) 312.31 569.33 T +(T&T in the USA and other countr) 336.68 569.33 T +(ies) 481.9 569.33 T +(.) 494.53 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(VxW) 180 545.33 T +(or) 200.81 545.33 T +(ks is a register tr) 209.85 545.33 T +(ademar) 283.1 545.33 T +(k of Wind Riv) 317.15 545.33 T +(er Systems) 375.8 545.33 T +(.) 425.66 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The X Windo) 180 521.33 T +(w System is a tr) 237.65 521.33 T +(ademar) 308.12 521.33 T +(k of Massachusetts Institute of T) 342.17 521.33 T +(echnology) 484.37 521.33 T +(.) 528.95 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(OSF/Motif and Motif are tr) 180 497.33 T +(ademar) 294.94 497.33 T +(ks of Open Softw) 328.99 497.33 T +(are F) 404.99 497.33 T +(oundation, Inc.) 428.03 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ultr) 180 473.33 T +(ix and DEC are registered tr) 195.7 473.33 T +(ademar) 319.53 473.33 T +(ks of Digital Equipment Cor) 353.58 473.33 T +(por) 475.03 473.33 T +(ation.) 489.38 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(HPUX is a registered tr) 180 449.33 T +(ademar) 282.15 449.33 T +(k of He) 316.2 449.33 T +(wlett P) 347.68 449.33 T +(ac) 377.29 449.33 T +(kard.) 387.65 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(SURA/CEB) 54 344.33 T +(AF:) 105.92 344.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.44 (The Southeaster) 180 344.33 P +4.44 (n Univ) 258.62 344.33 P +4.44 (ersities Research Association \050SURA\051 oper) 291.15 344.33 P +4.44 (ates the) 499.98 344.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.01 (Contin) 180 332.33 P +2.01 (uous Electron Beam Acceler) 208.8 332.33 P +2.01 (ator F) 340.89 332.33 P +2.01 (acility \050CEBAF\051 f) 368.52 332.33 P +2.01 (or the United States) 445.59 332.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Depar) 180 320.33 T +(tment of Energy under contr) 207.63 320.33 T +(act DE-A) 331.48 320.33 T +(C05-84ER40150.) 371.19 320.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DISCLAIMER:) 54 218.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.49 (This repor) 180 218.33 P +0.49 (t w) 225.9 218.33 P +0.49 (as prepared as an account of w) 239.02 218.33 P +0.49 (or) 381.4 218.33 P +0.49 (k sponsored b) 390.44 218.33 P +0.49 (y the United States) 454.03 218.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.18 (go) 180 206.33 P +2.18 (v) 190.97 206.33 P +2.18 (er) 195.72 206.33 P +2.18 (nment. Neither the United States nor the United States Depar) 204.86 206.33 P +2.18 (tment of) 501.68 206.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.04 (Energy) 180 194.33 P +1.04 (, nor an) 210.68 194.33 P +1.04 (y of their emplo) 246.52 194.33 P +1.04 (y) 317.69 194.33 P +1.04 (ees) 322.49 194.33 P +1.04 (, mak) 338.46 194.33 P +1.04 (es an) 363.75 194.33 P +1.04 (y w) 389.1 194.33 P +1.04 (arr) 404.99 194.33 P +1.04 (anty) 417.11 194.33 P +1.04 (, e) 435.01 194.33 P +1.04 (xpress or implied, or) 446.86 194.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.83 (assumes an) 180 182.33 P +1.83 (y legal liability or responsibility f) 235.59 182.33 P +1.83 (or the accur) 383.89 182.33 P +1.83 (acy) 440.24 182.33 P +1.83 (, completeness) 454.8 182.33 P +1.83 (, or) 523.72 182.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.68 (usefulness of an) 180 170.33 P +3.68 (y inf) 260.02 170.33 P +3.68 (or) 281.74 170.33 P +3.68 (mation, appar) 290.88 170.33 P +3.68 (atus) 355.59 170.33 P +3.68 (, product or process disclosed, or) 374.34 170.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.46 (represents that its use w) 180 158.33 P +2.46 (ould not infr) 298.11 158.33 P +2.46 (inge pr) 355.42 158.33 P +2.46 (iv) 388.59 158.33 P +2.46 (ately o) 395.56 158.33 P +2.46 (wned r) 427.33 158.33 P +2.46 (ights) 459.95 158.33 P +2.46 (. Ref) 480.92 158.33 P +2.46 (erence) 509.43 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.6 (herein to an) 180 146.33 P +1.6 (y speci\336c commercial product, process) 235.85 146.33 P +1.6 (, or ser) 413.79 146.33 P +1.6 (vice b) 448.4 146.33 P +1.6 (y tr) 475.92 146.33 P +1.6 (ade name) 491.3 146.33 P +1.6 (,) 537.22 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (mar) 180 134.33 P +2.12 (k, man) 197.37 134.33 P +2.12 (uf) 229.4 134.33 P +2.12 (acturer) 237.44 134.33 P +2.12 (, or otherwise) 268.06 134.33 P +2.12 (, does not necessar) 332.17 134.33 P +2.12 (ily constitute or imply its) 425.94 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (endorsement, recommendation, or f) 180 122.33 P +1.08 (a) 341.33 122.33 P +1.08 (v) 346.69 122.33 P +1.08 (or) 351.44 122.33 P +1.08 (ing b) 360.48 122.33 P +1.08 (y the United States go) 383.03 122.33 P +1.08 (v) 485.57 122.33 P +1.08 (er) 490.32 122.33 P +1.08 (nment or) 499.46 122.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (an) 180 110.33 P +0.83 (y agency thereof) 190.97 110.33 P +0.83 (. The vie) 266.26 110.33 P +0.83 (w and opinions of the authors e) 309.67 110.33 P +0.83 (xpressed herein do) 453.3 110.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.94 (not necessar) 180 98.33 P +1.94 (ily state or re\337ect those of the United States go) 239.34 98.33 P +1.94 (v) 464.01 98.33 P +1.94 (er) 468.76 98.33 P +1.94 (nment or an) 477.9 98.33 P +1.94 (y) 535 98.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(agency thereof) 180 86.33 T +(.) 245.85 86.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DOCUMENT D) 54 668.33 T +(A) 121.37 668.33 T +(TE:) 127.69 668.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(T) 180 668.33 T +(ab) 184.91 668.33 T +(le of contents gener) 195.83 668.33 T +(ated: F) 283.56 668.33 T +(ebr) 314.39 668.33 T +(uar) 328.99 668.33 T +(y 13, 1997 2:55 pm) 343.74 668.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "ii" 2 +%%Page: "iii" 3 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iii) 551.34 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(T) 180 710.67 T +(ab) 187.43 710.67 T +(le of Contents) 203.63 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV Gate) 198 684.33 T +(w) 250.04 684.33 T +(a) 257.11 684.33 T +(y Fundamentals) 262.37 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 333.6 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 672.33 T +(er) 210.73 672.33 T +(vie) 219.92 672.33 T +(w of the CDEV Gate) 232.5 672.33 T +(w) 322.34 672.33 T +(a) 329.41 672.33 T +(y) 334.67 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 341.94 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pur) 198.2 660.33 T +(pose of the CDEV Gate) 214.06 660.33 T +(w) 318.36 660.33 T +(a) 325.43 660.33 T +(y) 330.69 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 336.38 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(F) 198.2 648.33 T +(eatures of the CDEV Gate) 204.01 648.33 T +(w) 319.98 648.33 T +(a) 327.05 648.33 T +(y Ser) 332.31 648.33 T +(vice) 355.95 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 375.3 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 180 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Building the CDEV Gate) 198 636.33 T +(w) 305.07 636.33 T +(a) 312.14 636.33 T +(y Ser) 317.4 636.33 T +(vice) 341.04 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 361.4 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Location of Files) 198.2 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Steps to Building the Ser) 198.2 612.33 T +(v) 308.56 612.33 T +(er and Ser) 313.31 612.33 T +(vice) 360.3 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 378.08 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 180 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Star) 198 600.33 T +(ting the CDEV Gate) 216.74 600.33 T +(w) 304.36 600.33 T +(a) 311.43 600.33 T +(y) 316.69 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 322.48 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Star) 198.2 588.33 T +(ting the Gate) 216.94 588.33 T +(w) 274 588.33 T +(a) 281.07 588.33 T +(y Ser) 286.33 588.33 T +(v) 309.97 588.33 T +(er) 314.72 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 325.26 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Star) 198.2 576.33 T +(t-up Arguments f) 216.94 576.33 T +(or the Gate) 290.56 576.33 T +(w) 340.39 576.33 T +(a) 347.46 576.33 T +(y Ser) 352.72 576.33 T +(v) 376.36 576.33 T +(er) 381.11 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 391.98 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 180 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(T) 198 564.33 T +(roub) 202.91 564.33 T +(leshooting Ser) 222.72 564.33 T +(v) 286.94 564.33 T +(er Star) 291.69 564.33 T +(t-up) 322.1 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 341.94 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 180 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(DDL Entr) 198 552.33 T +(ies f) 239.27 552.33 T +(or the CDEV Gate) 257.31 552.33 T +(w) 337.7 552.33 T +(a) 344.77 552.33 T +(y Client) 350.03 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 383.64 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Setting Up the DDL) 198.2 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 286.34 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iii" 3 +%%Page: "iv" 4 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iv) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iv" 4 +%%Page: "v" 5 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(v) 553 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(List of Figures) 180 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(Figure 1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Simple DDL file for the Gateway Service) 234 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.................................................) 414.22 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "v" 5 +%%Page: "vi" 6 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(vi) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "vi" 6 +%%Page: "1" 7 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. CDEV Gate) 426.03 739 T +(w) 482.88 739 T +(a) 489.24 739 T +(y Fundamentals) 493.97 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1) 552.44 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(1.) 159.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV Gate) 180 710.67 T +(wa) 253.7 710.67 T +(y Fundamentals) 272.09 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w of the) 108.64 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV Gate) 72 661.33 T +(wa) 124.64 661.33 T +(y) 137.78 661.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +2.62 (The CDEV Gate) 180 673.33 P +2.62 (w) 257.3 673.33 P +2.62 (a) 264.37 673.33 P +2.62 (y is a ser) 269.63 673.33 P +2.62 (v) 317.82 673.33 P +2.62 (er that acts as an inter) 322.57 673.33 P +2.62 (mediar) 434.88 673.33 P +2.62 (y betw) 465.74 673.33 P +2.62 (een a CDEV) 497.17 673.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.35 (application and remote ser) 180 661.33 P +0.35 (vices) 299.18 661.33 P +0.35 (. A single netw) 321.81 661.33 P +0.35 (or) 387.78 661.33 P +0.35 (k connection is estab) 396.82 661.33 P +0.35 (lished betw) 491.05 661.33 P +0.35 (een) 541.32 661.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.21 (the client and the gate) 180 649.33 P +0.21 (w) 279.03 649.33 P +0.21 (a) 286.1 649.33 P +0.21 (y through which all CDEV requests will be routed. When the) 291.36 649.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.65 (gate) 180 637.33 P +0.65 (w) 199.26 637.33 P +0.65 (a) 206.33 637.33 P +0.65 (y receiv) 211.59 637.33 P +0.65 (es a request from the client, it estab) 246.44 637.33 P +0.65 (lishes the appropr) 409.17 637.33 P +0.65 (iate connection) 490.09 637.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.62 (to the actual ser) 180 625.33 P +3.62 (vice) 262.32 625.33 P +3.62 (, mak) 279.95 625.33 P +3.62 (es the request, and retur) 307.82 625.33 P +3.62 (ns the result to the client) 431.5 625.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(application.) 180 613.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Purpose of the) 72 584.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV Gate) 72 572.33 T +(wa) 124.64 572.33 T +(y) 137.78 572.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.31 (The CDEV Gate) 180 584.33 P +1.31 (w) 254.67 584.33 P +1.31 (a) 261.74 584.33 P +1.31 (y w) 267 584.33 P +1.31 (as designed to suppor) 283.16 584.33 P +1.31 (t the J) 385.88 584.33 P +1.31 (A) 415.54 584.33 P +1.31 (V) 421.51 584.33 P +1.31 (A/CDEV API. Because J) 427.38 584.33 P +1.31 (A) 539.49 584.33 P +1.31 (V) 545.46 584.33 P +1.31 (A) 551.33 584.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.55 (code m) 180 572.33 P +0.55 (ust be small in order to load and e) 213.24 572.33 P +0.55 (x) 367.99 572.33 P +0.55 (ecute ef\336ciently) 372.69 572.33 P +0.55 (, it w) 441.17 572.33 P +0.55 (as cr) 462.68 572.33 P +0.55 (itical to mo) 485.05 572.33 P +0.55 (v) 533.8 572.33 P +0.55 (e as) 538.55 572.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.4 (m) 180 560.33 P +1.4 (uch code as possib) 188.23 560.33 P +1.4 (le out of J) 277.84 560.33 P +1.4 (A) 325.21 560.33 P +1.4 (V) 331.18 560.33 P +1.4 (A and into a CDEV \322pro) 337.05 560.33 P +1.4 (xy\323 which could perf) 448.26 560.33 P +1.4 (or) 540.53 560.33 P +1.4 (m) 549.67 560.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +5.13 (connection management and dynamic libr) 180 548.33 P +5.13 (ar) 385.5 548.33 P +5.13 (y loading. This allo) 394.69 548.33 P +5.13 (ws the J) 492.75 548.33 P +5.13 (A) 539.49 548.33 P +5.13 (V) 545.46 548.33 P +5.13 (A) 551.33 548.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(application to access ne) 180 536.33 T +(w ser) 286.52 536.33 T +(vices pro) 310.71 536.33 T +(vided in C++ without adding an) 350.57 536.33 T +(y ne) 487.72 536.33 T +(w code) 506.42 536.33 T +(.) 537.95 536.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.27 (The J) 180 519.33 P +-0.27 (A) 204.54 519.33 P +-0.27 (V) 210.51 519.33 P +-0.27 (A/CDEV libr) 216.38 519.33 P +-0.27 (ar) 269.34 519.33 P +-0.27 (y locates the CDEV Gate) 278.53 519.33 P +-0.27 (w) 388.4 519.33 P +-0.27 (a) 395.47 519.33 P +-0.27 (y b) 400.73 519.33 P +-0.27 (y using a hostname and por) 413.6 519.33 P +-0.27 (t that) 536.03 519.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.15 (is pro) 180 507.33 P +1.15 (vided in an en) 205.45 507.33 P +1.15 (vironment v) 270.97 507.33 P +1.15 (ar) 323.56 507.33 P +1.15 (iab) 332.6 507.33 P +1.15 (le) 345.74 507.33 P +1.15 (. After deter) 353.37 507.33 P +1.15 (mining the location of the ser) 408.17 507.33 P +1.15 (v) 542.08 507.33 P +1.15 (er) 546.83 507.33 P +1.15 (,) 555.22 507.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.21 (J) 180 495.33 P +0.21 (A) 184.8 495.33 P +0.21 (V) 190.77 495.33 P +0.21 (A will estab) 196.64 495.33 P +0.21 (lish a connection to the gate) 247.43 495.33 P +0.21 (w) 372.78 495.33 P +0.21 (a) 379.85 495.33 P +0.21 (y and then begin tr) 385.11 495.33 P +0.21 (ansmitting its CDEV) 468.67 495.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(requests in standard CLIP \050CDEV Linear Inter) 180 483.33 T +(net Protocol\051.) 383.11 483.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.74 (The gate) 180 466.33 P +0.74 (w) 220.01 466.33 P +0.74 (a) 227.08 466.33 P +0.74 (y can also be used b) 232.34 466.33 P +0.74 (y standard C or C++ CDEV applications to perf) 327.58 466.33 P +0.74 (or) 540.53 466.33 P +0.74 (m) 549.67 466.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.13 (message routing. This approach can lessen the n) 180 454.33 P +2.13 (umber of connections to actual) 413.28 454.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.12 (control system de) 180 442.33 P +-0.12 (vices and reduce netw) 257.83 442.33 P +-0.12 (or) 356.88 442.33 P +-0.12 (k tr) 365.92 442.33 P +-0.12 (af\336c signi\336cantly) 379.59 442.33 P +-0.12 (. The gate) 451.28 442.33 P +-0.12 (w) 495.88 442.33 P +-0.12 (a) 502.95 442.33 P +-0.12 (y is located) 508.21 442.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.29 (b) 180 430.33 P +0.29 (y the gate) 185.36 430.33 P +0.29 (w) 229.67 430.33 P +0.29 (a) 236.74 430.33 P +0.29 (y ser) 242 430.33 P +0.29 (vice b) 264.26 430.33 P +0.29 (y looking up its name \050as speci\336ed in the CDEV DDL\051 in the) 290.48 430.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.02 (global name ser) 180 418.33 P +2.02 (v) 255.49 418.33 P +2.02 (er \050The current name ser) 260.24 418.33 P +2.02 (v) 379.22 418.33 P +2.02 (er is distr) 383.97 418.33 P +2.02 (ib) 428.73 418.33 P +2.02 (uted as par) 436.31 418.33 P +2.02 (t of the CDEV) 490.79 418.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Gener) 180 406.33 T +(ic Ser) 207.94 406.33 T +(v) 233.8 406.33 T +(er in the CDEV distr) 238.55 406.33 T +(ib) 327.06 406.33 T +(ution\051.) 334.64 406.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Features of the) 72 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV Gate) 72 365.33 T +(wa) 124.64 365.33 T +(y) 137.78 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ser) 72 353.33 T +(vice) 88.22 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(\245) 180 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.77 (The CDEV Gate) 198 377.33 P +0.77 (w) 271.59 377.33 P +0.77 (a) 278.66 377.33 P +0.77 (y is constr) 283.92 377.33 P +0.77 (ucted using the CDEV Gener) 330.63 377.33 P +0.77 (ic Ser) 462.81 377.33 P +0.77 (v) 489.45 377.33 P +0.77 (er Engine and) 494.2 377.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the CLIP Protocol.) 198 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.01 (Each gate) 198 341.33 P +2.01 (w) 244.84 341.33 P +2.01 (a) 251.91 341.33 P +2.01 (y ser) 257.17 341.33 P +2.01 (v) 281.15 341.33 P +2.01 (er registers its name) 285.9 341.33 P +2.01 (, host and por) 382.36 341.33 P +2.01 (t with the CDEV Name) 449.93 341.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ser) 198 329.33 T +(v) 213.86 329.33 T +(er when it is star) 218.61 329.33 T +(ted.) 291.81 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.57 (The name of the speci\336c gate) 198 305.33 P +0.57 (w) 331.84 305.33 P +0.57 (a) 338.91 305.33 P +0.57 (y to be used is associated with a CDEV de) 344.17 305.33 P +0.57 (vice/) 537.44 305.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.41 (message combination b) 198 293.33 P +0.41 (y using the \322ser) 304.21 293.33 P +0.41 (v) 374.08 293.33 P +0.41 (er\323 \336eld of the ser) 378.83 293.33 P +0.41 (vice data in the CDEV) 458.56 293.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(DDL \336le) 198 281.33 T +(. Syntax is descr) 233.41 281.33 T +(ibed later in this document.) 306.92 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.09 (The gate) 198 257.33 P +-0.09 (w) 237.18 257.33 P +-0.09 (a) 244.25 257.33 P +-0.09 (y ser) 249.51 257.33 P +-0.09 (vice will estab) 271.38 257.33 P +-0.09 (lish one connection to a named gate) 332.67 257.33 P +-0.09 (w) 492.56 257.33 P +-0.09 (a) 499.63 257.33 P +-0.09 (y to perf) 504.89 257.33 P +-0.09 (or) 540.53 257.33 P +-0.09 (m) 549.67 257.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(all tr) 198 245.33 T +(ansactions) 216.79 245.33 T +(.) 264.44 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.04 (The client application uses a special DDL \336le that redirects all signals to the) 198 221.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.51 (gate) 198 209.33 P +1.51 (w) 217.26 209.33 P +1.51 (a) 224.33 209.33 P +1.51 (y ser) 229.59 209.33 P +1.51 (vice) 253.07 209.33 P +1.51 (. This allo) 270.7 209.33 P +1.51 (ws the gate) 316.38 209.33 P +1.51 (w) 370.35 209.33 P +1.51 (a) 377.42 209.33 P +1.51 (y ser) 382.68 209.33 P +1.51 (v) 406.16 209.33 P +1.51 (er to maintain the actual control) 410.91 209.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(system connections from a centr) 198 197.33 T +(aliz) 341.84 197.33 T +(ed location.) 356.69 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.09 (The gate) 198 173.33 P +2.09 (w) 239.36 173.33 P +2.09 (a) 246.43 173.33 P +2.09 (y ser) 251.69 173.33 P +2.09 (v) 275.75 173.33 P +2.09 (er ma) 280.5 173.33 P +2.09 (y ha) 307.85 173.33 P +2.09 (v) 328.64 173.33 P +2.09 (e a standard DDL that redirects requests to the) 333.39 173.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.82 (actual ser) 198 161.33 P +1.82 (vice OR it ma) 243.47 161.33 P +1.82 (y ha) 308.63 161.33 P +1.82 (v) 329.15 161.33 P +1.82 (e a special DDL that routes requests to another) 333.9 161.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.66 (gate) 198 149.33 P +0.66 (w) 217.26 149.33 P +0.66 (a) 224.33 149.33 P +0.66 (y) 229.59 149.33 P +0.66 (. The system has currently been tested b) 233.59 149.33 P +0.66 (y routing messages through as) 418.64 149.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.71 (man) 198 137.33 P +2.71 (y as ten gate) 217.3 137.33 P +2.71 (w) 282.49 137.33 P +2.71 (a) 289.57 137.33 P +2.71 (ys bef) 294.83 137.33 P +2.71 (ore reaching the actual control system. Note that) 323.92 137.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.21 (perf) 198 125.33 P +0.21 (or) 214.93 125.33 P +0.21 (mance begins to deg) 224.07 125.33 P +0.21 (r) 317.43 125.33 P +0.21 (ade substantially after routing through \336v) 320.66 125.33 P +0.21 (e gate) 501.54 125.33 P +0.21 (w) 529.35 125.33 P +0.21 (a) 536.42 125.33 P +0.21 (ys -) 541.68 125.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(b) 198 113.33 T +(ut is still reasonab) 203.36 113.33 T +(le) 283.19 113.33 T +(.) 290.82 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "1" 7 +%%Page: "2" 8 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. Building the CDEV Gate) 54 739 T +(w) 160.37 739 T +(a) 166.73 739 T +(y Ser) 171.47 739 T +(vice) 192.74 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(2) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(2.) 141.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Building the CDEV Gate) 162 710.67 T +(wa) 320.48 710.67 T +(y Ser) 338.88 710.67 T +(vice) 373.26 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Location of Files) 54 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +2.07 (The source code f) 162 673.33 P +2.07 (or the Gate) 247.95 673.33 P +2.07 (w) 301.91 673.33 P +2.07 (a) 308.98 673.33 P +2.07 (y Ser) 314.24 673.33 P +2.07 (vice is pro) 339.95 673.33 P +2.07 (vided with the CDEV distr) 388.95 673.33 P +2.07 (ib) 510.74 673.33 P +2.07 (ution) 518.32 673.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.35 (star) 162 661.33 P +3.35 (ting with v) 179.07 661.33 P +3.35 (ersion 1.5. The source code is located in the director) 229.98 661.33 P +3.35 (y $CDEV/) 492.75 661.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.68 (applications/cde) 162 649.33 P +0.68 (vGate) 233.4 649.33 P +0.68 (w) 259.88 649.33 P +0.68 (a) 266.95 649.33 P +0.68 (y) 272.21 649.33 P +0.68 (. The f) 276.21 649.33 P +0.68 (ollo) 305.62 649.33 P +0.68 (wing steps should be tak) 321.03 649.33 P +0.68 (en to b) 433.06 649.33 P +0.68 (uild the Gate) 464.81 649.33 P +0.68 (w) 522.67 649.33 P +0.68 (a) 529.74 649.33 P +0.68 (y) 535 649.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ser) 162 637.33 T +(v) 177.86 637.33 T +(er and Ser) 182.61 637.33 T +(vice) 229.6 637.33 T +(.) 247.23 637.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Steps to Building) 54 608.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the Ser) 54 596.33 T +(ver and) 88 596.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ser) 54 584.33 T +(vice) 70.22 584.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(1.) 162 608.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Obtain and install the CDEV distr) 180 608.33 T +(ib) 326.32 608.33 T +(ution - V) 333.9 608.33 T +(ersion 1.5 or higher) 370.34 608.33 T +(.) 455.99 608.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 162 584.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(F) 180 584.33 T +(ollo) 185.81 584.33 T +(w the installation steps to b) 201.22 584.33 T +(uild CDEV on y) 321.08 584.33 T +(our system. This includes setting) 388.68 584.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(all of the en) 180 572.33 T +(vironment v) 231.5 572.33 T +(ar) 282.93 572.33 T +(iab) 291.97 572.33 T +(les required b) 305.11 572.33 T +(y CDEV) 365.49 572.33 T +(.) 399.8 572.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 162 548.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(F) 180 548.33 T +(ollo) 185.81 548.33 T +(w the installation steps to b) 201.22 548.33 T +(uild the CDEV Gener) 321.08 548.33 T +(ic Ser) 414.6 548.33 T +(v) 440.46 548.33 T +(er and deplo) 445.21 548.33 T +(y the) 500.5 548.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV Name Ser) 180 536.33 T +(v) 255.87 536.33 T +(er) 260.62 536.33 T +(.) 269.01 536.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 162 512.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(There is a collection of platf) 180 512.33 T +(or) 301.42 512.33 T +(m speci\336c mak) 310.56 512.33 T +(e\336les in the director) 376.48 512.33 T +(y) 463.48 512.33 T +3 F +($CDEV/) 471.26 512.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(e) 180 500.33 T +(xtensions/cde) 185.26 500.33 T +(vGener) 246.1 500.33 T +(icSer) 279.04 500.33 T +(v) 302.12 500.33 T +(er/include/mak) 306.87 500.33 T +(einclude) 371.69 500.33 T +0 F +(. Link the mak) 408.78 500.33 T +(e\336le that is) 470.83 500.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(appropr) 180 488.33 T +(iate to y) 214.61 488.33 T +(our architecture to the \336le Mak) 249.43 488.33 T +(e\336le) 383.73 488.33 T +(.OS in THA) 401.92 488.33 T +(T director) 451.29 488.33 T +(y) 493.82 488.33 T +(.) 497.82 488.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(F) 180 464.33 T +(or e) 185.81 464.33 T +(xample) 202.74 464.33 T +(, to link to the mak) 234.82 464.33 T +(e\336le f) 315.77 464.33 T +(or HP-UX, y) 339.37 464.33 T +(ou w) 392.51 464.33 T +(ould type the f) 413.53 464.33 T +(ollo) 476.05 464.33 T +(wing) 491.46 464.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(command.) 180.12 452.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(cd $CDEV/e) 180 428.33 T +(xtensions/cde) 235.98 428.33 T +(vGenericSer) 302.52 428.33 T +(ver/makeinc) 361.54 428.33 T +(lude) 419.15 428.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ln -s Make\336le) 180 416.33 T +(.hpux Make\336le) 243 416.33 T +(.OS) 312.11 416.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(5.) 162 392.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Change director) 180 392.33 T +(ies to) 251.29 392.33 T +3 F +($CDEV/applications/cde) 277.97 392.33 T +(vGate) 385.49 392.33 T +(w) 411.97 392.33 T +(a) 419.04 392.33 T +(y) 424.3 392.33 T +0 F +(.) 428.3 392.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 162 368.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.05 (T) 180 368.33 P +-0.05 (ype mak) 184.91 368.33 P +-0.05 (e to compile and link the CDEV Gate) 222.46 368.33 P +-0.05 (w) 384.79 368.33 P +-0.05 (a) 391.86 368.33 P +-0.05 (y Ser) 397.12 368.33 P +-0.05 (vice shared object and the) 420.71 368.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV Gate) 180 356.33 T +(w) 232.04 356.33 T +(a) 239.11 356.33 T +(y Ser) 244.37 356.33 T +(v) 268.01 356.33 T +(er) 272.76 356.33 T +(. Note that y) 281.15 356.33 T +(ou m) 334.87 356.33 T +(ust be using GNU mak) 357 356.33 T +(e in order to b) 457.39 356.33 T +(uild) 518.89 356.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(this distr) 180 344.33 T +(ib) 217.38 344.33 T +(ution.) 224.96 344.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.27 (Upon completion the Mak) 162 320.33 P +0.27 (e\336le will gener) 275.99 320.33 P +0.27 (ate the shared object f) 339.78 320.33 P +0.27 (or the gate) 439.5 320.33 P +0.27 (w) 487.65 320.33 P +0.27 (a) 494.72 320.33 P +0.27 (y ser) 499.98 320.33 P +0.27 (vice) 522.22 320.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.33 (and will install it into y) 162 308.33 P +3.33 (our CDEVSHOBJ director) 274.59 308.33 P +3.33 (y) 396.02 308.33 P +3.33 (. The gate) 400.02 308.33 P +3.33 (w) 451.51 308.33 P +3.33 (a) 458.58 308.33 P +3.33 (y ser) 463.84 308.33 P +3.33 (v) 489.14 308.33 P +3.33 (er will be) 493.89 308.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.85 (compiled, link) 162 296.33 P +0.85 (ed and installed in the director) 223.22 296.33 P +0.85 (y $CDEV/applications/cde) 361.14 296.33 P +0.85 (vGate) 477.29 296.33 P +0.85 (w) 503.77 296.33 P +0.85 (a) 510.84 296.33 P +0.85 (y/bin/) 516.1 296.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ARCH/cde) 162 284.33 T +(vGate) 208.93 284.33 T +(w) 235.41 284.33 T +(a) 242.48 284.33 T +(y) 247.74 284.33 T +(. At this point y) 251.74 284.33 T +(ou are ready to star) 317.13 284.33 T +(t the gate) 404.24 284.33 T +(w) 445.74 284.33 T +(a) 452.81 284.33 T +(y ser) 458.07 284.33 T +(v) 480.04 284.33 T +(er) 484.79 284.33 T +(.) 493.18 284.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "2" 8 +%%Page: "3" 9 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Star) 436.67 739 T +(ting the CDEV Gate) 463.55 739 T +(w) 542.4 739 T +(a) 548.77 739 T +(y) 553.5 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(3) 552.44 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(3.) 159.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Star) 180 710.67 T +(ting the CDEV Gate) 207.51 710.67 T +(wa) 335.65 710.67 T +(y) 354.05 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Star) 72 673.33 T +(ting the) 91.65 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Gate) 72 661.33 T +(wa) 94.08 661.33 T +(y Ser) 107.22 661.33 T +(ver) 131.78 661.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(The f) 180 673.33 T +(ollo) 202.49 673.33 T +(wing steps should be tak) 217.9 673.33 T +(en to e) 327.2 673.33 T +(x) 357.48 673.33 T +(ecute the cde) 362.18 673.33 T +(vGate) 421.92 673.33 T +(w) 448.4 673.33 T +(a) 455.47 673.33 T +(y) 460.73 673.33 T +(.) 464.73 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 180 656.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.09 (Ensure that the required CDEV and CDEV Gener) 198 656.33 P +-0.09 (ic Ser) 415.98 656.33 P +-0.09 (v) 441.75 656.33 P +-0.09 (er en) 446.5 656.33 P +-0.09 (vironment v) 469 656.33 P +-0.09 (ar) 520.35 656.33 P +-0.09 (iab) 529.39 656.33 P +-0.09 (les) 542.53 656.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ha) 198 644.33 T +(v) 208.92 644.33 T +(e been set. These include:) 213.67 644.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEVDDL) 198 620.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(This is the name of the DDL \336le that indicates where) 324 620.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(messages should be routed. T) 324 608.33 T +(ypically) 457.31 608.33 T +(, this DDL will) 489.09 608.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(route the messages to the actual control system) 324 596.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(de) 324 584.33 T +(vices) 334.82 584.33 T +(.) 357.45 584.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEVSHOBJ) 198 567.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(This is the location of the CDEV shared object \336les) 324 567.33 T +(.) 548.39 567.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_NAME_SER) 198 550.33 T +(VER) 286.4 550.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(This is the host where the CDEV Name Ser) 324 550.33 T +(v) 516.59 550.33 T +(er is) 521.34 550.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(r) 324 538.33 T +(unning.) 327.48 538.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 180 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Mo) 198 521.33 T +(v) 211.74 521.33 T +(e to the director) 216.49 521.33 T +(y where the CDEV Gate) 286.27 521.33 T +(w) 392.78 521.33 T +(a) 399.85 521.33 T +(y Ser) 405.11 521.33 T +(v) 428.75 521.33 T +(er binar) 433.5 521.33 T +(y is located: b) 467.7 521.33 T +(y) 528.64 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.42 (def) 198 509.33 P +-0.42 (ault $CDEV/applications/cde) 211.6 509.33 P +-0.42 (vGate) 337.6 509.33 P +-0.42 (w) 364.08 509.33 P +-0.42 (a) 371.15 509.33 P +-0.42 (y/bin/ARCH, where ARCH is the name of) 376.41 509.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the host architecture) 198 497.33 T +(.) 288.45 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 180 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(T) 198 473.33 T +(ype the command ./cde) 202.91 473.33 T +(vGate) 306.55 473.33 T +(w) 333.03 473.33 T +(a) 340.1 473.33 T +(y at the command line) 345.36 473.33 T +(. This will star) 443.03 473.33 T +(t a gate) 503.99 473.33 T +(w) 537.15 473.33 T +(a) 544.22 473.33 T +(y) 549.48 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.18 (ser) 198 461.33 P +-0.18 (v) 212.19 461.33 P +-0.18 (er with the name) 216.94 461.33 P +4 F +-0.18 (Gate) 292.93 461.33 P +-0.18 (wa) 315.01 461.33 P +-0.18 (y1) 328.15 461.33 P +0 F +-0.18 (on the current host using TCP/IP por) 341.87 461.33 P +-0.18 (t 9573. This) 503.5 461.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(inf) 198 449.33 T +(or) 208.26 449.33 T +(mation can be con\336r) 217.4 449.33 T +(med b) 307.69 449.33 T +(y using the) 335.28 449.33 T +4 F +(dumpSer) 386.42 449.33 T +(ver) 429.86 449.33 T +0 F +( command that is) 444.87 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pro) 198 437.33 T +(vided with the CDEV Gener) 212.3 437.33 T +(ic Ser) 334.72 437.33 T +(v) 360.58 437.33 T +(er Engine to displa) 365.33 437.33 T +(y the contents of the) 447.85 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV Name Ser) 198 425.33 T +(v) 273.87 425.33 T +(er) 278.62 425.33 T +(.) 287.01 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(At this point the cde) 180 401.33 T +(vGate) 267.53 401.33 T +(w) 294.01 401.33 T +(a) 301.08 401.33 T +(y should be ready f) 306.34 401.33 T +(or use b) 390.53 401.33 T +(y client applications) 426.46 401.33 T +(.) 513.01 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Star) 72 372.33 T +(t-up) 91.65 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ar) 72 360.33 T +(guments f) 82.96 360.33 T +(or the) 130.54 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Gate) 72 348.33 T +(wa) 94.08 348.33 T +(y Ser) 107.22 348.33 T +(ver) 131.78 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +-0.19 (The user can specify the name of por) 180 372.33 P +-0.19 (t used b) 344.16 372.33 P +-0.19 (y the CDEV Gate) 379.16 372.33 P +-0.19 (w) 455.1 372.33 P +-0.19 (a) 462.17 372.33 P +-0.19 (y from the command) 467.43 372.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.76 (line when the ser) 180 360.33 P +3.76 (v) 267.17 360.33 P +3.76 (er is star) 271.92 360.33 P +3.76 (ted. The gate) 318.19 360.33 P +3.76 (w) 384.44 360.33 P +3.76 (a) 391.51 360.33 P +3.76 (y ser) 396.77 360.33 P +3.76 (v) 422.5 360.33 P +3.76 (er will accept the f) 427.25 360.33 P +3.76 (ollo) 522.03 360.33 P +3.76 (wing) 537.44 360.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(par) 180 348.33 T +(ameters from star) 194.35 348.33 T +(t-up) 273.1 348.33 T +(.) 289.98 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(s=) 198 331.33 T +4 F +(ser) 209.4 331.33 T +(ver name) 224.51 331.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +-0.1 (This allo) 324 331.33 P +-0.1 (ws the caller to specify the ser) 360.98 331.33 P +-0.1 (v) 494.63 331.33 P +-0.1 (er name that) 499.38 331.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(will be registered with the name ser) 324 319.33 T +(v) 481.02 319.33 T +(er) 485.77 319.33 T +(. By def) 494.16 319.33 T +(ault) 527.77 319.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the ser) 324 307.33 T +(v) 354.87 307.33 T +(er name is) 359.62 307.33 T +4 F +(Gate) 409.08 307.33 T +(wa) 431.16 307.33 T +(y1) 444.3 307.33 T +0 F +(.) 455.42 307.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(p=) 198 290.33 T +4 F +(por) 209.95 290.33 T +(t n) 226.26 290.33 T +(umber) 238.38 290.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(This allo) 324 290.33 T +(ws the caller to specify the por) 361.08 290.33 T +(t that the) 495.98 290.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ser) 324 278.33 T +(v) 338.19 278.33 T +(er will use to receiv) 342.94 278.33 T +(e incoming requests) 427.71 278.33 T +(. By) 517.04 278.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(def) 324 266.33 T +(ault the por) 337.6 266.33 T +(t used b) 388.03 266.33 T +(y the ser) 423.41 266.33 T +(v) 462.06 266.33 T +(er is) 466.81 266.33 T +4 F +(9573) 488.48 266.33 T +0 F +(.) 510.72 266.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "3" 9 +%%Page: "4" 10 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. T) 54 739 T +(roub) 68.43 739 T +(leshooting Ser) 86.26 739 T +(v) 144.05 739 T +(er Star) 148.33 739 T +(t-up) 175.7 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(4) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(4.) 141.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(T) 162 710.67 T +(r) 169.43 710.67 T +(oub) 174.6 710.67 T +(leshooting Ser) 200.12 710.67 T +(ver Star) 297.51 710.67 T +(t-up) 349.92 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +-0.13 (When the ser) 162 684.33 P +-0.13 (v) 221.51 684.33 P +-0.13 (er is star) 226.26 684.33 P +-0.13 (ted it ma) 264.73 684.33 P +-0.13 (y displa) 302.51 684.33 P +-0.13 (y one or more error conditions that will pre) 335.98 684.33 P +-0.13 (v) 521.35 684.33 P +-0.13 (ent) 526.1 684.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(it from oper) 162 672.33 T +(ating proper) 212.47 672.33 T +(ly) 265.98 672.33 T +(.) 272.2 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Err) 162 648.33 T +(or:) 176.25 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(syntax error at line:#) 261.29 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Meaning:) 162 631.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.7 (This message indicates that the CDEVDDL \336le that is being) 261.29 631.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(used b) 261.43 619.33 T +(y the gate) 291.25 619.33 T +(w) 334.97 619.33 T +(a) 342.04 619.33 T +(y is f) 347.3 619.33 T +(or) 367.56 619.33 T +(matted improper) 376.7 619.33 T +(ly) 449.65 619.33 T +(.) 455.87 619.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Solution:) 162 602.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.29 (Edit the CDEVDDL \336le and correct an) 261.29 602.33 P +1.29 (y f) 435.6 602.33 P +1.29 (or) 447.14 602.33 P +1.29 (matting errors that) 456.28 602.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ma) 261.43 590.33 T +(y e) 275.02 590.33 T +(xist.) 288.06 590.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Err) 162 566.33 T +(or:) 176.25 566.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(ERR) 261.29 566.33 T +(OR: Gate) 282.2 566.33 T +(w) 324.24 566.33 T +(a) 331.31 566.33 T +(y1 ser) 336.57 566.33 T +(v) 364.1 566.33 T +(er already e) 368.85 566.33 T +(xists in GA) 421.35 566.33 T +(TEW) 467.94 566.33 T +(A) 489.66 566.33 T +(Y domain) 495.33 566.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Meaning:) 162 549.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.27 (This message indicates that a gate) 261.29 549.33 P +1.27 (w) 421.95 549.33 P +1.27 (a) 429.02 549.33 P +1.27 (y ser) 434.28 549.33 P +1.27 (v) 457.52 549.33 P +1.27 (er with the name) 462.27 549.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.39 (Gate) 261.43 537.33 P +0.39 (w) 282.91 537.33 P +0.39 (a) 289.98 537.33 P +0.39 (y1 has already been star) 295.24 537.33 P +0.39 (ted and is currently registered) 406.71 537.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(with the CDEV Name Ser) 261.43 525.33 T +(v) 374.54 525.33 T +(er) 379.29 525.33 T +(.) 387.68 525.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Solution:) 162 508.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.99 (The gate) 261.29 508.33 P +0.99 (w) 301.55 508.33 P +0.99 (a) 308.62 508.33 P +0.99 (y will contin) 313.88 508.33 P +0.99 (ue to attempt to register itself with the) 366.88 508.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.61 (name ser) 261.43 496.33 P +1.61 (v) 305.02 496.33 P +1.61 (er e) 309.77 496.33 P +1.61 (v) 328.3 496.33 P +1.61 (er) 333.05 496.33 P +1.61 (y 30 seconds) 342.24 496.33 P +1.61 (. If the message contin) 404.22 496.33 P +1.61 (ues to) 511.15 496.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.76 (appear) 261.43 484.33 P +2.76 (, then restar) 292.06 484.33 P +2.76 (t the gate) 351.34 484.33 P +2.76 (w) 398.36 484.33 P +2.76 (a) 405.43 484.33 P +2.76 (y using the s par) 410.69 484.33 P +2.76 (ameter to) 495 484.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4.58 (specify a diff) 261.43 472.33 P +4.58 (erent ser) 325.87 472.33 P +4.58 (v) 370.21 472.33 P +4.58 (er name OR shutdo) 374.96 472.33 P +4.58 (wn the other) 475.81 472.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(gate) 261.43 460.33 T +(w) 280.69 460.33 T +(a) 287.76 460.33 T +(y that is using the same name) 293.02 460.33 T +(.) 425.71 460.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Err) 162 436.33 T +(or:) 176.25 436.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Could not comm) 261.29 436.33 T +(unicate with name ser) 333.99 436.33 T +(v) 431.55 436.33 T +(er) 436.3 436.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ERR) 261.29 424.33 T +(OR: F) 282.2 424.33 T +(ailed to e) 308.37 424.33 T +(x) 348.65 424.33 T +(ecute \322REGISTER SER) 353.35 424.33 T +(VER\323 oper) 457.88 424.33 T +(ation) 504.46 424.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Meaning:) 162 407.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.27 (This message indicates that the CDEV Name Ser) 261.29 407.33 P +0.27 (v) 482.46 407.33 P +0.27 (er could not) 487.21 407.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.44 (be accessed either because it is not r) 261.43 395.33 P +1.44 (unning or because the) 436.73 395.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.01 (CDEV_NAME_SER) 261.43 383.33 P +0.01 (VER en) 349.28 383.33 P +0.01 (vironment v) 383.55 383.33 P +0.01 (ar) 434.98 383.33 P +0.01 (iab) 444.02 383.33 P +0.01 (le does not specify) 457.16 383.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the correct host.) 261.43 371.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Solution:) 162 354.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.92 (Ensure that the CDEV_NAME_SER) 261.29 354.33 P +0.92 (VER en) 422.51 354.33 P +0.92 (vironment v) 457.69 354.33 P +0.92 (ar) 510.04 354.33 P +0.92 (iab) 519.08 354.33 P +0.92 (le) 532.22 354.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.09 (is set and indicates the host where the name ser) 261.43 342.33 P +0.09 (v) 477.11 342.33 P +0.09 (er is r) 481.86 342.33 P +0.09 (unning.) 507.2 342.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.8 (If this is correct, chec) 261.43 330.33 P +2.8 (k to ensure that the name ser) 366.37 330.33 P +2.8 (v) 513.56 330.33 P +2.8 (er is) 518.31 330.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(actually r) 261.43 318.33 T +(unning on the speci\336ed host.) 301.59 318.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Err) 162 294.33 T +(or:) 176.25 294.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Error) 261.29 294.33 T +(: Ser) 283.81 294.33 T +(v) 305.23 294.33 T +(er Gate) 309.98 294.33 T +(w) 343.13 294.33 T +(a) 350.2 294.33 T +(y1 - Unab) 355.46 294.33 T +(le to open listening soc) 398.61 294.33 T +(k) 500.13 294.33 T +(et) 504.93 294.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Meaning:) 162 277.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.31 (This message indicates that the por) 261.29 277.33 P +1.31 (t that the name ser) 426.11 277.33 P +1.31 (v) 515.05 277.33 P +1.31 (er is) 519.8 277.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.73 (attempting to use to listen f) 261.43 265.33 P +1.73 (or ne) 389.28 265.33 P +1.73 (w connections is already in) 413.6 265.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(use) 261.43 253.33 T +(.) 277.4 253.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Solution:) 162 236.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +-0.25 (Use the command line arguments to specify a diff) 261.29 236.33 P +-0.25 (erent listening) 478 236.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(por) 261.43 224.33 T +(t.) 276.28 224.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "4" 10 +%%Page: "5" 11 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. DDL Entr) 381.16 739 T +(ies f) 428.31 739 T +(or the CDEV Gate) 444.55 739 T +(w) 516.9 739 T +(a) 523.26 739 T +(y Client) 527.99 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(5) 552.44 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(5.) 159.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(DDL Entries f) 180 710.67 T +(or the CDEV Gate) 268.4 710.67 T +(wa) 384.88 710.67 T +(y Client) 403.27 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Setting Up the) 72 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(DDL) 72 661.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.66 (The f) 180 673.33 P +1.66 (ollo) 204.15 673.33 P +1.66 (wing e) 219.56 673.33 P +1.66 (xample illustr) 249.82 673.33 P +1.66 (ates ho) 309.72 673.33 P +1.66 (w to add a ser) 344.03 673.33 P +1.66 (vice entr) 413.79 673.33 P +1.66 (y to identify the CDEV) 453.54 673.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.16 (Gate) 180 661.33 P +2.16 (w) 201.48 661.33 P +2.16 (a) 208.55 661.33 P +2.16 (y Ser) 213.81 661.33 P +2.16 (vice and ho) 239.61 661.33 P +2.16 (w to use the ser) 294.91 661.33 P +2.16 (vice data to specify the ser) 374.43 661.33 P +2.16 (v) 503.91 661.33 P +2.16 (er that the) 508.66 661.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(gate) 180 649.33 T +(w) 199.26 649.33 T +(a) 206.33 649.33 T +(y ser) 211.59 649.33 T +(vice will use f) 233.56 649.33 T +(or routing messages) 292.16 649.33 T +(.) 382.6 649.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 1: Simple DDL \336le f) 180 616 T +(or the Gate) 287.26 616 T +(w) 332.11 616 T +(a) 338.47 616 T +(y Ser) 343.21 616 T +(vice) 364.48 616 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +180 81 558 680 C +0 0 0 1 0 0 0 K +180 199 558 613 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +187.43 208 551 609.43 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +5 9 Q +(/*) 196.43 600.14 T +( * This is the service definition, it tells CDEV that there is) 196.43 589.14 T +( * a service named Gateway and that it will use the cdevData) 196.43 578.14 T +-0.08 ( * tag \324server\325 to locate the gateway using the CDEV Name Server.) 196.43 567.14 P +( */) 196.43 556.14 T +(service Gateway) 196.43 545.14 T +({) 208 534.14 T +(tags {server}) 208 523.14 T +(}) 208 512.14 T +(/*) 196.43 490.14 T +( * This class definition identifies the class gatewayClass which) 196.43 479.14 T +( * supports the \322get\323,\322set\323, \322monitorOn\323 and \322monitorOff\323) 196.43 468.14 T +( * commands on attributes \322attrib0\323 and \322attrib1\323. Note that) 196.43 457.14 T +( * requests made to attrib0 will be routed through \322Gateway1\323) 196.43 446.14 T +( * and requests made to attrib1 will be routed through) 196.43 435.14 T +( * \322Gateway2\323.) 196.43 424.14 T +( */) 196.43 413.14 T +(class gatewayClass) 196.43 402.14 T +({) 208 391.14 T +(verbs {get, set, monitorOn, monitorOff}) 218.03 380.14 T +(attributes) 208 369.14 T +({) 226 358.14 T +(attrib0 Gateway {server=Gateway1};) 226 347.14 T +(attrib1 Gateway {server=Gateway2};) 226 336.14 T +(}) 226 325.14 T +(}) 196.43 314.14 T +(/*) 196.43 292.14 T +( * Finally, the CDEV DDL identifies two devices that are of type) 196.43 281.14 T +-0.09 ( * gatewayClass. Any time one of the supported messages is passed) 196.43 270.14 P +( * to one of these devices it will be routed through a CDEV) 196.43 259.14 T +( * Gateway.) 196.43 248.14 T +( */) 196.43 237.14 T +(gatewayClass : device0, device1;) 196.43 226.14 T +180 81 558 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "5" 11 +%%Trailer +%%BoundingBox: 0 0 612 792 +%%PageOrder: Ascend +%%Pages: 11 +%%DocumentFonts: Helvetica +%%+ Times-BoldItalic +%%+ Helvetica-Bold +%%+ Helvetica-Oblique +%%+ Helvetica-BoldOblique +%%+ Courier-BoldOblique +%%EOF diff --git a/doc/ps/cdevIntroduction.ps b/doc/ps/cdevIntroduction.ps new file mode 100755 index 0000000..faad3c3 --- /dev/null +++ b/doc/ps/cdevIntroduction.ps @@ -0,0 +1,20646 @@ +%!PS-Adobe-3.0 +%%BoundingBox: (atend) +%%Pages: (atend) +%%PageOrder: (atend) +%%DocumentFonts: (atend) +%%Creator: Frame 5.0 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +% +% Frame ps_prolog 5.0, for use with Frame 5.0 products +% This ps_prolog file is Copyright (c) 1986-1995 Frame Technology +% Corporation. All rights reserved. This ps_prolog file may be +% freely copied and distributed in conjunction with documents created +% using FrameMaker, FrameMaker/SGML and FrameViewer as long as this +% copyright notice is preserved. +% +% FrameMaker users specify the proper paper size for each print job in the +% "Print" dialog's "Printer Paper Size" "Width" and "Height~ fields. If the +% printer that the PS file is sent to does not support the requested paper +% size, or if there is no paper tray of the proper size currently installed, +% then the job will not be printed. The following flag, if set to true, will +% cause the job to print on the default paper in such cases. +/FMAllowPaperSizeMismatch false def +% +% Frame products normally print colors as their true color on a color printer +% or as shades of gray, based on luminance, on a black-and white printer. The +% following flag, if set to true, forces all non-white colors to print as pure +% black. This has no effect on bitmap images. +/FMPrintAllColorsAsBlack false def +% +% Frame products can either set their own line screens or use a printer's +% default settings. Three flags below control this separately for no +% separations, spot separations and process separations. If a flag +% is true, then the default printer settings will not be changed. If it is +% false, Frame products will use their own settings from a table based on +% the printer's resolution. +/FMUseDefaultNoSeparationScreen true def +/FMUseDefaultSpotSeparationScreen true def +/FMUseDefaultProcessSeparationScreen false def +% +% For any given PostScript printer resolution, Frame products have two sets of +% screen angles and frequencies for printing process separations, which are +% recomended by Adobe. The following variable chooses the higher frequencies +% when set to true or the lower frequencies when set to false. This is only +% effective if the appropriate FMUseDefault...SeparationScreen flag is false. +/FMUseHighFrequencyScreens true def +% +% The following is a set of predefined optimal frequencies and angles for various +% common dpi settings. This is taken from "Advances in Color Separation Using +% PostScript Software Technology," from Adobe Systems (3/13/89 P.N. LPS 0043) +% and corrolated with information which is in various PPD (4.0) files. +% +% The "dpiranges" figure is the minimum dots per inch device resolution which +% can support this setting. The "low" and "high" values are controlled by the +% setting of the FMUseHighFrequencyScreens flag above. The "TDot" flags control +% the use of the "Yellow Triple Dot" feature whereby the frequency id divided by +% three, but the dot function is "trippled" giving a block of 3x3 dots per cell. +% +% PatFreq is a compromise pattern frequency for ps Level 2 printers which is close +% to the ideal WYSIWYG pattern frequency of 9 repetitions/inch but does not beat +% (too badly) against the screen frequencies of any separations for that DPI. +/dpiranges [ 2540 2400 1693 1270 1200 635 600 0 ] def +/CMLowFreqs [ 100.402 94.8683 89.2289 100.402 94.8683 66.9349 63.2456 47.4342 ] def +/YLowFreqs [ 95.25 90.0 84.65 95.25 90.0 70.5556 66.6667 50.0 ] def +/KLowFreqs [ 89.8026 84.8528 79.8088 89.8026 84.8528 74.8355 70.7107 53.033 ] def +/CLowAngles [ 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 ] def +/MLowAngles [ 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 ] def +/YLowTDot [ true true false true true false false false ] def +/CMHighFreqs [ 133.87 126.491 133.843 108.503 102.523 100.402 94.8683 63.2456 ] def +/YHighFreqs [ 127.0 120.0 126.975 115.455 109.091 95.25 90.0 60.0 ] def +/KHighFreqs [ 119.737 113.137 119.713 128.289 121.218 89.8026 84.8528 63.6395 ] def +/CHighAngles [ 71.5651 71.5651 71.5651 70.0169 70.0169 71.5651 71.5651 71.5651 ] def +/MHighAngles [ 18.4349 18.4349 18.4349 19.9831 19.9831 18.4349 18.4349 18.4349 ] def +/YHighTDot [ false false true false false true true false ] def +/PatFreq [ 10.5833 10.0 9.4055 10.5833 10.0 10.5833 10.0 9.375 ] def +% +% PostScript Level 2 printers contain an "Accurate Screens" feature which can +% improve process separation rendering at the expense of compute time. This +% flag is ignored by PostScript Level 1 printers. +/FMUseAcccurateScreens true def +% +% The following PostScript procedure defines the spot function that Frame +% products will use for process separations. You may un-comment-out one of +% the alternative functions below, or use your own. +% +% Dot function +/FMSpotFunction {abs exch abs 2 copy add 1 gt + {1 sub dup mul exch 1 sub dup mul add 1 sub } + {dup mul exch dup mul add 1 exch sub }ifelse } def +% +% Line function +% /FMSpotFunction { pop } def +% +% Elipse function +% /FMSpotFunction { dup 5 mul 8 div mul exch dup mul exch add +% sqrt 1 exch sub } def +% +% +/FMversion (5.0) def +/fMLevel1 /languagelevel where {pop languagelevel} {1} ifelse 2 lt def +/FMPColor + fMLevel1 { + false + /colorimage where {pop pop true} if + } { + true + } ifelse +def +/FrameDict 400 dict def +systemdict /errordict known not {/errordict 10 dict def + errordict /rangecheck {stop} put} if +% The readline in PS 23.0 doesn't recognize cr's as nl's on AppleTalk +FrameDict /tmprangecheck errordict /rangecheck get put +errordict /rangecheck {FrameDict /bug true put} put +FrameDict /bug false put +mark +% Some PS machines read past the CR, so keep the following 3 lines together! +currentfile 5 string readline +00 +0000000000 +cleartomark +errordict /rangecheck FrameDict /tmprangecheck get put +FrameDict /bug get { + /readline { + /gstring exch def + /gfile exch def + /gindex 0 def + { + gfile read pop + dup 10 eq {exit} if + dup 13 eq {exit} if + gstring exch gindex exch put + /gindex gindex 1 add def + } loop + pop + gstring 0 gindex getinterval true + } bind def + } if +/FMshowpage /showpage load def +/FMquit /quit load def +/FMFAILURE { + dup = flush + FMshowpage + /Helvetica findfont 12 scalefont setfont + 72 200 moveto show + 72 220 moveto show + FMshowpage + FMquit + } def +/FMVERSION { + FMversion ne { + (Frame product version does not match ps_prolog! Check installation;) + (also check ~/fminit and ./fminit for old versions) FMFAILURE + } if + } def +/FMBADEPSF { + (Adobe's PostScript Language Reference Manual, 2nd Edition, section H.2.4) + (says your EPS file is not valid, as it calls X ) + dup dup (X) search pop exch pop exch pop length + 5 -1 roll + putinterval + FMFAILURE + } def +/fmConcatProcs + { + /proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def + newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx +}def +FrameDict begin [ + /ALDsave + /FMdicttop + /FMoptop + /FMpointsize + /FMsaveobject + /b + /bitmapsave + /blut + /bpside + /bs + /bstring + /bwidth + /c + /cf + /cs + /cynu + /depth + /edown + /fh + /fillvals + /fw + /fx + /fy + /g + /gfile + /gindex + /grnt + /gryt + /gstring + /height + /hh + /i + /im + /indx + /is + /k + /kk + /landscape + /lb + /len + /llx + /lly + /m + /magu + /manualfeed + /n + /offbits + /onbits + /organgle + /orgbangle + /orgbfreq + /orgbproc + /orgbxfer + /orgfreq + /orggangle + /orggfreq + /orggproc + /orggxfer + /orgmatrix + /orgproc + /orgrangle + /orgrfreq + /orgrproc + /orgrxfer + /orgxfer + /pagesave + /paperheight + /papersizedict + /paperwidth + /pos + /pwid + /r + /rad + /redt + /sl + /str + /tran + /u + /urx + /ury + /val + /width + /width + /ws + /ww + /x + /x1 + /x2 + /xindex + /xpoint + /xscale + /xx + /y + /y1 + /y2 + /yelu + /yindex + /ypoint + /yscale + /yy +] { 0 def } forall +/FmBD {bind def} bind def +systemdict /pdfmark known { + /fMAcrobat true def + + /FmPD /pdfmark load def + + + /FmPT /show load def + + + currentdistillerparams /CoreDistVersion get 2000 ge { + + + /FmPD2 /pdfmark load def + + + + + + /FmPA { mark exch /Dest exch 5 3 roll + /View [ /XYZ null 6 -2 roll FmDC exch pop null] /DEST FmPD + }FmBD + } { + + /FmPD2 /cleartomark load def + /FmPA {pop pop pop}FmBD + } ifelse +} { + + /fMAcrobat false def + /FmPD /cleartomark load def + /FmPD2 /cleartomark load def + /FmPT /pop load def + /FmPA {pop pop pop}FmBD +} ifelse +/FmDC { + transform fMDefaultMatrix itransform cvi exch cvi exch +}FmBD +/FmBx { + dup 3 index lt {3 1 roll exch} if + 1 index 4 index lt {4 -1 roll 3 1 roll exch 4 1 roll} if +}FmBD +/FMnone 0 def +/FMcyan 1 def +/FMmagenta 2 def +/FMyellow 3 def +/FMblack 4 def +/FMcustom 5 def +/fMNegative false def +/FrameSepIs FMnone def +/FrameSepBlack 0 def +/FrameSepYellow 0 def +/FrameSepMagenta 0 def +/FrameSepCyan 0 def +/FrameSepRed 1 def +/FrameSepGreen 1 def +/FrameSepBlue 1 def +/FrameCurGray 1 def +/FrameCurPat null def +/FrameCurColors [ 0 0 0 1 0 0 0 ] def +/FrameColorEpsilon .001 def +/eqepsilon { + sub dup 0 lt {neg} if + FrameColorEpsilon le +} bind def +/FrameCmpColorsCMYK { + 2 copy 0 get exch 0 get eqepsilon { + 2 copy 1 get exch 1 get eqepsilon { + 2 copy 2 get exch 2 get eqepsilon { + 3 get exch 3 get eqepsilon + } {pop pop false} ifelse + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/FrameCmpColorsRGB { + 2 copy 4 get exch 0 get eqepsilon { + 2 copy 5 get exch 1 get eqepsilon { + 6 get exch 2 get eqepsilon + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/RGBtoCMYK { + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 3 copy + 2 copy + le { pop } { exch pop } ifelse + 2 copy + le { pop } { exch pop } ifelse + dup dup dup + 6 1 roll + 4 1 roll + 7 1 roll + sub + 6 1 roll + sub + 5 1 roll + sub + 4 1 roll +} bind def +/CMYKtoRGB { + dup dup 4 -1 roll add + 5 1 roll 3 -1 roll add + 4 1 roll add + 1 exch sub dup 0 lt {pop 0} if 3 1 roll + 1 exch sub dup 0 lt {pop 0} if exch + 1 exch sub dup 0 lt {pop 0} if exch +} bind def +/FrameSepInit { + 1.0 RealSetgray +} bind def +/FrameSetSepColor { + /FrameSepBlue exch def + /FrameSepGreen exch def + /FrameSepRed exch def + /FrameSepBlack exch def + /FrameSepYellow exch def + /FrameSepMagenta exch def + /FrameSepCyan exch def + /FrameSepIs FMcustom def + setCurrentScreen +} bind def +/FrameSetCyan { + /FrameSepBlue 1.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 1.0 def + /FrameSepIs FMcyan def + setCurrentScreen +} bind def + +/FrameSetMagenta { + /FrameSepBlue 1.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 1.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMmagenta def + setCurrentScreen +} bind def + +/FrameSetYellow { + /FrameSepBlue 0.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 1.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMyellow def + setCurrentScreen +} bind def + +/FrameSetBlack { + /FrameSepBlue 0.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 1.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMblack def + setCurrentScreen +} bind def + +/FrameNoSep { + /FrameSepIs FMnone def + setCurrentScreen +} bind def +/FrameSetSepColors { + FrameDict begin + [ exch 1 add 1 roll ] + /FrameSepColors + exch def end + } bind def +/FrameColorInSepListCMYK { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsCMYK + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/FrameColorInSepListRGB { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsRGB + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/RealSetgray /setgray load def +/RealSetrgbcolor /setrgbcolor load def +/RealSethsbcolor /sethsbcolor load def +end +/setgray { + FrameDict begin + FrameSepIs FMnone eq + { RealSetgray } + { + FrameSepIs FMblack eq + { RealSetgray } + { FrameSepIs FMcustom eq + FrameSepRed 0 eq and + FrameSepGreen 0 eq and + FrameSepBlue 0 eq and { + RealSetgray + } { + 1 RealSetgray pop + } ifelse + } ifelse + } ifelse + end +} bind def +/setrgbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetrgbcolor } + { + 3 copy [ 4 1 roll ] + FrameColorInSepListRGB + { + FrameSepBlue eq exch + FrameSepGreen eq and exch + FrameSepRed eq and + { 0 } { 1 } ifelse + } + { + FMPColor { + RealSetrgbcolor + currentcmykcolor + } { + RGBtoCMYK + } ifelse + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end +} bind def +/sethsbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSethsbcolor } + { + RealSethsbcolor + currentrgbcolor + setrgbcolor + } + ifelse + end +} bind def +FrameDict begin +/setcmykcolor where { + pop /RealSetcmykcolor /setcmykcolor load def +} { + /RealSetcmykcolor { + 4 1 roll + 3 { 3 index add 0 max 1 min 1 exch sub 3 1 roll} repeat + RealSetrgbcolor pop + } bind def +} ifelse +userdict /setcmykcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetcmykcolor } + { + 4 copy [ 5 1 roll ] + FrameColorInSepListCMYK + { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + { 0 } { 1 } ifelse + } + { + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end + } bind put +fMLevel1 { + + + + /patScreenDict 7 dict dup begin + <0f1e3c78f0e1c387> [ 45 { pop } {exch pop} .5 2 sqrt] FmBD + <0f87c3e1f0783c1e> [ 135 { pop } {exch pop} .5 2 sqrt] FmBD + [ 0 { pop } dup .5 2 ] FmBD + [ 90 { pop } dup .5 2 ] FmBD + <8142241818244281> [ 45 { 2 copy lt {exch} if pop} dup .75 2 sqrt] FmBD + <03060c183060c081> [ 45 { pop } {exch pop} .875 2 sqrt] FmBD + <8040201008040201> [ 135 { pop } {exch pop} .875 2 sqrt] FmBD + end def +} { + + /patProcDict 5 dict dup begin + <0f1e3c78f0e1c387> { 3 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <0f87c3e1f0783c1e> { 3 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + <8142241818244281> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -1 -1 moveto 9 9 lineto stroke } bind def + <03060c183060c081> { 1 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <8040201008040201> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + end def + /patDict 15 dict dup begin + /PatternType 1 def + /PaintType 2 def + /TilingType 3 def + /BBox [ 0 0 8 8 ] def + /XStep 8 def + /YStep 8 def + /PaintProc { + begin + patProcDict bstring known { + patProcDict bstring get exec + } { + 8 8 true [1 0 0 -1 0 8] bstring imagemask + } ifelse + end + } bind def + end def +} ifelse +/combineColor { + FrameSepIs FMnone eq + { + graymode fMLevel1 or not { + + [/Pattern [/DeviceCMYK]] setcolorspace + FrameCurColors 0 4 getinterval aload pop FrameCurPat setcolor + } { + FrameCurColors 3 get 1.0 ge { + FrameCurGray RealSetgray + } { + fMAcrobat not FMPColor graymode and and { + 0 1 3 { + FrameCurColors exch get + 1 FrameCurGray sub mul + } for + RealSetcmykcolor + } { + 4 1 6 { + FrameCurColors exch get + graymode { + 1 exch sub 1 FrameCurGray sub mul 1 exch sub + } { + 1.0 lt {FrameCurGray} {1} ifelse + } ifelse + } for + RealSetrgbcolor + } ifelse + } ifelse + } ifelse + } { + FrameCurColors 0 4 getinterval aload + FrameColorInSepListCMYK { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + FrameSepIs FMcustom eq and + { FrameCurGray } { 1 } ifelse + } { + FrameSepIs FMblack eq + {FrameCurGray 1.0 exch sub mul 1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop FrameCurGray 1.0 exch sub mul 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + graymode fMLevel1 or not { + + [/Pattern [/DeviceGray]] setcolorspace + FrameCurPat setcolor + } { + graymode not fMLevel1 and { + + dup 1 lt {pop FrameCurGray} if + } if + RealSetgray + } ifelse + } ifelse +} bind def +/savematrix { + orgmatrix currentmatrix pop + } bind def +/restorematrix { + orgmatrix setmatrix + } bind def +/fMDefaultMatrix matrix defaultmatrix def +/fMatrix2 matrix def +/dpi 72 0 fMDefaultMatrix dtransform + dup mul exch dup mul add sqrt def + +/freq dpi dup 72 div round dup 0 eq {pop 1} if 8 mul div def +/sangle 1 0 fMDefaultMatrix dtransform exch atan def + sangle fMatrix2 rotate + fMDefaultMatrix fMatrix2 concatmatrix + dup 0 get /sflipx exch def + 3 get /sflipy exch def +/screenIndex { + 0 1 dpiranges length 1 sub { dup dpiranges exch get 1 sub dpi le {exit} {pop} ifelse } for +} bind def +/getCyanScreen { + FMUseHighFrequencyScreens { CHighAngles CMHighFreqs} {CLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getMagentaScreen { + FMUseHighFrequencyScreens { MHighAngles CMHighFreqs } {MLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getYellowScreen { + FMUseHighFrequencyScreens { YHighTDot YHighFreqs} { YLowTDot YLowFreqs } ifelse + screenIndex dup 3 1 roll get 3 1 roll get { 3 div + {2 { 1 add 2 div 3 mul dup floor sub 2 mul 1 sub exch} repeat + FMSpotFunction } } {/FMSpotFunction load } ifelse + 0.0 exch +} bind def +/getBlackScreen { + FMUseHighFrequencyScreens { KHighFreqs } { KLowFreqs } ifelse + screenIndex get 45.0 /FMSpotFunction load +} bind def +/getSpotScreen { + getBlackScreen +} bind def +/getCompositeScreen { + getBlackScreen +} bind def +/FMSetScreen + fMLevel1 { /setscreen load + }{ { + 8 dict begin + /HalftoneType 1 def + /SpotFunction exch def + /Angle exch def + /Frequency exch def + /AccurateScreens FMUseAcccurateScreens def + currentdict end sethalftone + } bind } ifelse +def +/setDefaultScreen { + FMPColor { + orgrxfer cvx orggxfer cvx orgbxfer cvx orgxfer cvx setcolortransfer + } + { + orgxfer cvx settransfer + } ifelse + orgfreq organgle orgproc cvx setscreen +} bind def +/setCurrentScreen { + FrameSepIs FMnone eq { + FMUseDefaultNoSeparationScreen { + setDefaultScreen + } { + getCompositeScreen FMSetScreen + } ifelse + } { + FrameSepIs FMcustom eq { + FMUseDefaultSpotSeparationScreen { + setDefaultScreen + } { + getSpotScreen FMSetScreen + } ifelse + } { + FMUseDefaultProcessSeparationScreen { + setDefaultScreen + } { + FrameSepIs FMcyan eq { + getCyanScreen FMSetScreen + } { + FrameSepIs FMmagenta eq { + getMagentaScreen FMSetScreen + } { + FrameSepIs FMyellow eq { + getYellowScreen FMSetScreen + } { + getBlackScreen FMSetScreen + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse +} bind def +end + +/FMDOCUMENT { + array /FMfonts exch def + /#copies exch def + FrameDict begin + 0 ne /manualfeed exch def + /paperheight exch def + /paperwidth exch def + 0 ne /fMNegative exch def + 0 ne /edown exch def + /yscale exch def + /xscale exch def + fMLevel1 { + manualfeed {setmanualfeed} if + /FMdicttop countdictstack 1 add def + /FMoptop count def + setpapername + manualfeed {true} {papersize} ifelse + {manualpapersize} {false} ifelse + {desperatepapersize} {false} ifelse + {papersizefailure} if + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + } + {2 dict + dup /PageSize [paperwidth paperheight] put + manualfeed {dup /ManualFeed manualfeed put} if + {setpagedevice} stopped {papersizefailure} if + } + ifelse + + FMPColor { + currentcolorscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + cvlit /orgbproc exch def + /orgbangle exch def + /orgbfreq exch def + cvlit /orggproc exch def + /orggangle exch def + /orggfreq exch def + cvlit /orgrproc exch def + /orgrangle exch def + /orgrfreq exch def + currentcolortransfer + fMNegative { + 1 1 4 { + pop { 1 exch sub } fmConcatProcs 4 1 roll + } for + 4 copy + setcolortransfer + } if + cvlit /orgxfer exch def + cvlit /orgbxfer exch def + cvlit /orggxfer exch def + cvlit /orgrxfer exch def + } { + currentscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + + currenttransfer + fMNegative { + { 1 exch sub } fmConcatProcs + dup settransfer + } if + cvlit /orgxfer exch def + } ifelse + end +} def +/FMBEGINPAGE { + FrameDict begin + /pagesave save def + 3.86 setmiterlimit + /landscape exch 0 ne def + landscape { + 90 rotate 0 exch dup /pwid exch def neg translate pop + }{ + pop /pwid exch def + } ifelse + edown { [-1 0 0 1 pwid 0] concat } if + 0 0 moveto paperwidth 0 lineto paperwidth paperheight lineto + 0 paperheight lineto 0 0 lineto 1 setgray fill + xscale yscale scale + /orgmatrix matrix def + gsave +} def +/FMENDPAGE { + grestore + pagesave restore + end + showpage + } def +/FMFONTDEFINE { + FrameDict begin + findfont + ReEncode + 1 index exch + definefont + FMfonts 3 1 roll + put + end + } def +/FMFILLS { + FrameDict begin dup + array /fillvals exch def + dict /patCache exch def + end + } def +/FMFILL { + FrameDict begin + fillvals 3 1 roll put + end + } def +/FMNORMALIZEGRAPHICS { + newpath + 1 setlinewidth + 0 setlinecap + 0 0 0 sethsbcolor + 0 setgray + } bind def +/FMBEGINEPSF { + end + /FMEPSF save def + /showpage {} def +% See Adobe's "PostScript Language Reference Manual, 2nd Edition", page 714. +% "...the following operators MUST NOT be used in an EPS file:" (emphasis ours) + /banddevice {(banddevice) FMBADEPSF} def + /clear {(clear) FMBADEPSF} def + /cleardictstack {(cleardictstack) FMBADEPSF} def + /copypage {(copypage) FMBADEPSF} def + /erasepage {(erasepage) FMBADEPSF} def + /exitserver {(exitserver) FMBADEPSF} def + /framedevice {(framedevice) FMBADEPSF} def + /grestoreall {(grestoreall) FMBADEPSF} def + /initclip {(initclip) FMBADEPSF} def + /initgraphics {(initgraphics) FMBADEPSF} def + /quit {(quit) FMBADEPSF} def + /renderbands {(renderbands) FMBADEPSF} def + /setglobal {(setglobal) FMBADEPSF} def + /setpagedevice {(setpagedevice) FMBADEPSF} def + /setshared {(setshared) FMBADEPSF} def + /startjob {(startjob) FMBADEPSF} def + /lettertray {(lettertray) FMBADEPSF} def + /letter {(letter) FMBADEPSF} def + /lettersmall {(lettersmall) FMBADEPSF} def + /11x17tray {(11x17tray) FMBADEPSF} def + /11x17 {(11x17) FMBADEPSF} def + /ledgertray {(ledgertray) FMBADEPSF} def + /ledger {(ledger) FMBADEPSF} def + /legaltray {(legaltray) FMBADEPSF} def + /legal {(legal) FMBADEPSF} def + /statementtray {(statementtray) FMBADEPSF} def + /statement {(statement) FMBADEPSF} def + /executivetray {(executivetray) FMBADEPSF} def + /executive {(executive) FMBADEPSF} def + /a3tray {(a3tray) FMBADEPSF} def + /a3 {(a3) FMBADEPSF} def + /a4tray {(a4tray) FMBADEPSF} def + /a4 {(a4) FMBADEPSF} def + /a4small {(a4small) FMBADEPSF} def + /b4tray {(b4tray) FMBADEPSF} def + /b4 {(b4) FMBADEPSF} def + /b5tray {(b5tray) FMBADEPSF} def + /b5 {(b5) FMBADEPSF} def + FMNORMALIZEGRAPHICS + [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall + fx fw 2 div add fy fh 2 div add translate + rotate + fw 2 div neg fh 2 div neg translate + fw urx llx sub div fh ury lly sub div scale + llx neg lly neg translate + /FMdicttop countdictstack 1 add def + /FMoptop count def + } bind def +/FMENDEPSF { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMEPSF restore + FrameDict begin + } bind def +FrameDict begin +/setmanualfeed { +%%BeginFeature *ManualFeed True + statusdict /manualfeed true put +%%EndFeature + } bind def +/max {2 copy lt {exch} if pop} bind def +/min {2 copy gt {exch} if pop} bind def +/inch {72 mul} def +/pagedimen { + paperheight sub abs 16 lt exch + paperwidth sub abs 16 lt and + {/papername exch def} {pop} ifelse + } bind def +/setpapername { + /papersizedict 14 dict def + papersizedict begin + /papername /unknown def + /Letter 8.5 inch 11.0 inch pagedimen + /LetterSmall 7.68 inch 10.16 inch pagedimen + /Tabloid 11.0 inch 17.0 inch pagedimen + /Ledger 17.0 inch 11.0 inch pagedimen + /Legal 8.5 inch 14.0 inch pagedimen + /Statement 5.5 inch 8.5 inch pagedimen + /Executive 7.5 inch 10.0 inch pagedimen + /A3 11.69 inch 16.5 inch pagedimen + /A4 8.26 inch 11.69 inch pagedimen + /A4Small 7.47 inch 10.85 inch pagedimen + /B4 10.125 inch 14.33 inch pagedimen + /B5 7.16 inch 10.125 inch pagedimen + end + } bind def +/papersize { + papersizedict begin + /Letter {lettertray letter} def + /LetterSmall {lettertray lettersmall} def + /Tabloid {11x17tray 11x17} def + /Ledger {ledgertray ledger} def + /Legal {legaltray legal} def + /Statement {statementtray statement} def + /Executive {executivetray executive} def + /A3 {a3tray a3} def + /A4 {a4tray a4} def + /A4Small {a4tray a4small} def + /B4 {b4tray b4} def + /B5 {b5tray b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + statusdict begin stopped end + } bind def +/manualpapersize { + papersizedict begin + /Letter {letter} def + /LetterSmall {lettersmall} def + /Tabloid {11x17} def + /Ledger {ledger} def + /Legal {legal} def + /Statement {statement} def + /Executive {executive} def + /A3 {a3} def + /A4 {a4} def + /A4Small {a4small} def + /B4 {b4} def + /B5 {b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + stopped + } bind def +/desperatepapersize { + statusdict /setpageparams known + { + paperwidth paperheight 0 1 + statusdict begin + {setpageparams} stopped + end + } {true} ifelse + } bind def +/papersizefailure { + FMAllowPaperSizeMismatch not + { +(The requested paper size is not available in any currently-installed tray) +(Edit the PS file to "FMAllowPaperSizeMismatch true" to use default tray) + FMFAILURE } if + } def +/DiacriticEncoding [ +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl +/numbersign /dollar /percent /ampersand /quotesingle /parenleft +/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K +/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash +/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h +/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar +/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute +/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis +/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis +/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve +/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex +/udieresis /dagger /.notdef /cent /sterling /section /bullet +/paragraph /germandbls /registered /copyright /trademark /acute +/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef +/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown +/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef +/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde +/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright +/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis +/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl +/periodcentered /quotesinglbase /quotedblbase /perthousand +/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute +/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve +/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron +/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +] def +/ReEncode { + dup + length + dict begin + { + 1 index /FID ne + {def} + {pop pop} ifelse + } forall + 0 eq {/Encoding DiacriticEncoding def} if + currentdict + end + } bind def +FMPColor + + { + /BEGINBITMAPCOLOR { + BITMAPCOLOR} def + /BEGINBITMAPCOLORc { + BITMAPCOLORc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUECOLOR } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUECOLORc } def + /BEGINBITMAPCMYK { + BITMAPCMYK } def + /BEGINBITMAPCMYKc { + BITMAPCMYKc } def + } + + { + /BEGINBITMAPCOLOR { + BITMAPGRAY} def + /BEGINBITMAPCOLORc { + BITMAPGRAYc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUEGRAY } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUEGRAYc } def + /BEGINBITMAPCMYK { + BITMAPCMYKGRAY } def + /BEGINBITMAPCMYKc { + BITMAPCMYKGRAYc } def + } +ifelse +/K { + FMPrintAllColorsAsBlack { + dup 1 eq 2 index 1 eq and 3 index 1 eq and not + {7 {pop} repeat 0 0 0 1 0 0 0} if + } if + FrameCurColors astore + pop combineColor +} bind def +/graymode true def +fMLevel1 { + /fmGetFlip { + fMatrix2 exch get mul 0 lt { -1 } { 1 } ifelse + } FmBD +} if +/setPatternMode { + fMLevel1 { + 2 index patScreenDict exch known { + pop pop + patScreenDict exch get aload pop + freq + mul + 5 2 roll + fMatrix2 currentmatrix 1 get 0 ne { + 3 -1 roll 90 add 3 1 roll + sflipx 1 fmGetFlip sflipy 2 fmGetFlip neg mul + } { + sflipx 0 fmGetFlip sflipy 3 fmGetFlip mul + } ifelse + 0 lt {exch pop} {pop} ifelse + fMNegative { + {neg} fmConcatProcs + } if + bind + + + + systemdict /setscreen get exec + /FrameCurGray exch def + } { + /bwidth exch def + /bpside exch def + /bstring exch def + /onbits 0 def /offbits 0 def + freq sangle landscape {90 add} if + {/ypoint exch def + /xpoint exch def + /xindex xpoint 1 add 2 div bpside mul cvi def + /yindex ypoint 1 add 2 div bpside mul cvi def + bstring yindex bwidth mul xindex 8 idiv add get + 1 7 xindex 8 mod sub bitshift and 0 ne fMNegative {not} if + {/onbits onbits 1 add def 1} + {/offbits offbits 1 add def 0} + ifelse + } + setscreen + offbits offbits onbits add div fMNegative {1.0 exch sub} if + /FrameCurGray exch def + } ifelse + } { + pop pop + dup patCache exch known { + patCache exch get + } { + dup + patDict /bstring 3 -1 roll put + patDict + 9 PatFreq screenIndex get div dup matrix scale + makepattern + dup + patCache 4 -1 roll 3 -1 roll put + } ifelse + /FrameCurGray 0 def + /FrameCurPat exch def + } ifelse + /graymode false def + combineColor +} bind def +/setGrayScaleMode { + graymode not { + /graymode true def + fMLevel1 { + setCurrentScreen + } if + } if + /FrameCurGray exch def + combineColor +} bind def +/normalize { + transform round exch round exch itransform + } bind def +/dnormalize { + dtransform round exch round exch idtransform + } bind def +/lnormalize { + 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop + } bind def +/H { + lnormalize setlinewidth + } bind def +/Z { + setlinecap + } bind def + +/PFill { + graymode fMLevel1 or not { + gsave 1 setgray eofill grestore + } if +} bind def +/PStroke { + graymode fMLevel1 or not { + gsave 1 setgray stroke grestore + } if + stroke +} bind def +/X { + fillvals exch get + dup type /stringtype eq + {8 1 setPatternMode} + {setGrayScaleMode} + ifelse + } bind def +/V { + PFill gsave eofill grestore + } bind def +/Vclip { + clip + } bind def +/Vstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/N { + PStroke + } bind def +/Nclip { + strokepath clip newpath + } bind def +/Nstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/M {newpath moveto} bind def +/E {lineto} bind def +/D {curveto} bind def +/O {closepath} bind def +/L { + /n exch def + newpath + normalize + moveto + 2 1 n {pop normalize lineto} for + } bind def +/Y { + L + closepath + } bind def +/R { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + x1 y1 + x2 y1 + x2 y2 + x1 y2 + 4 Y + } bind def +/rarc + {rad + arcto + } bind def +/RR { + /rad exch def + normalize + /y2 exch def + /x2 exch def + normalize + /y1 exch def + /x1 exch def + mark + newpath + { + x1 y1 rad add moveto + x1 y2 x2 y2 rarc + x2 y2 x2 y1 rarc + x2 y1 x1 y1 rarc + x1 y1 x1 y2 rarc + closepath + } stopped {x1 y1 x2 y2 R} if + cleartomark + } bind def +/RRR { + /rad exch def + normalize /y4 exch def /x4 exch def + normalize /y3 exch def /x3 exch def + normalize /y2 exch def /x2 exch def + normalize /y1 exch def /x1 exch def + newpath + normalize moveto + mark + { + x2 y2 x3 y3 rarc + x3 y3 x4 y4 rarc + x4 y4 x1 y1 rarc + x1 y1 x2 y2 rarc + closepath + } stopped + {x1 y1 x2 y2 x3 y3 x4 y4 newpath moveto lineto lineto lineto closepath} if + cleartomark + } bind def +/C { + grestore + gsave + R + clip + setCurrentScreen +} bind def +/CP { + grestore + gsave + Y + clip + setCurrentScreen +} bind def +/F { + FMfonts exch get + FMpointsize scalefont + setfont + } bind def +/Q { + /FMpointsize exch def + F + } bind def +/T { + moveto show + } bind def +/RF { + rotate + 0 ne {-1 1 scale} if + } bind def +/TF { + gsave + moveto + RF + show + grestore + } bind def +/P { + moveto + 0 32 3 2 roll widthshow + } bind def +/PF { + gsave + moveto + RF + 0 32 3 2 roll widthshow + grestore + } bind def +/S { + moveto + 0 exch ashow + } bind def +/SF { + gsave + moveto + RF + 0 exch ashow + grestore + } bind def +/B { + moveto + 0 32 4 2 roll 0 exch awidthshow + } bind def +/BF { + gsave + moveto + RF + 0 32 4 2 roll 0 exch awidthshow + grestore + } bind def +/G { + gsave + newpath + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill fill + grestore + } bind def +/Gstrk { + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/Gclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GG { + gsave + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill + fill + grestore + } bind def +/GGclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GGstrk { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/A { + gsave + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/Aclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/Astrk { + Gstrk +} bind def +/AA { + gsave + savematrix + newpath + + 3 index 2 div add exch 4 index 2 div sub exch + + normalize 3 index 2 div sub exch 4 index 2 div add exch + translate + rotate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/AAclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/AAstrk { + GGstrk +} bind def +/BEGINPRINTCODE { + /FMdicttop countdictstack 1 add def + /FMoptop count 7 sub def + /FMsaveobject save def + userdict begin + /showpage {} def + FMNORMALIZEGRAPHICS + 3 index neg 3 index neg translate + } bind def +/ENDPRINTCODE { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMsaveobject restore + } bind def +/gn { + 0 + { 46 mul + cf read pop + 32 sub + dup 46 lt {exit} if + 46 sub add + } loop + add + } bind def +/cfs { + /str sl string def + 0 1 sl 1 sub {str exch val put} for + str def + } bind def +/ic [ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 + {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx} + {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx} + {19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} + {13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh} + {4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh} + {13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl} + {7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl} + {0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl} + {10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl} + ] def +/ms { + /sl exch def + /val 255 def + /ws cfs + /im cfs + /val 0 def + /bs cfs + /cs cfs + } bind def +400 ms +/ip { + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip { + + + bis ris copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + ris gis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + gis bis copy pop + dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip4 { + + + kis cis copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + cis mis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + mis yis copy pop + dup dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + yis kis copy pop + 3 mul is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/wh { + /len exch def + /pos exch def + ws 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/bl { + /len exch def + /pos exch def + bs 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/s1 1 string def +/fl { + /len exch def + /pos exch def + /val cf s1 readhexstring pop 0 get def + pos 1 pos len add 1 sub {im exch val put} for + pos len + } bind def +/hx { + 3 copy getinterval + cf exch readhexstring pop pop + } bind def +/wbytes { + dup dup + 8 gt { pop 8 idiv mul } + { 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse } ifelse + } bind def +/BEGINBITMAPBWc { + 1 {} COMMONBITMAPc + } bind def +/BEGINBITMAPGRAYc { + 8 {} COMMONBITMAPc + } bind def +/BEGINBITMAP2BITc { + 2 {} COMMONBITMAPc + } bind def +/COMMONBITMAPc { + + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + cvtProc + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} image + bitmapsave restore + grestore + } bind def +/BEGINBITMAPBW { + 1 {} COMMONBITMAP + } bind def +/BEGINBITMAPGRAY { + 8 {} COMMONBITMAP + } bind def +/BEGINBITMAP2BIT { + 2 {} COMMONBITMAP + } bind def +/COMMONBITMAP { + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + cvtProc + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} image + bitmapsave restore + grestore + } bind def +/ngrayt 256 array def +/nredt 256 array def +/nbluet 256 array def +/ngreent 256 array def +fMLevel1 { +/colorsetup { + currentcolortransfer + /gryt exch def + /blut exch def + /grnt exch def + /redt exch def + 0 1 255 { + /indx exch def + /cynu 1 red indx get 255 div sub def + /magu 1 green indx get 255 div sub def + /yelu 1 blue indx get 255 div sub def + /kk cynu magu min yelu min def + /u kk currentundercolorremoval exec def +% /u 0 def + nredt indx 1 0 cynu u sub max sub redt exec put + ngreent indx 1 0 magu u sub max sub grnt exec put + nbluet indx 1 0 yelu u sub max sub blut exec put + ngrayt indx 1 kk currentblackgeneration exec sub gryt exec put + } for + {255 mul cvi nredt exch get} + {255 mul cvi ngreent exch get} + {255 mul cvi nbluet exch get} + {255 mul cvi ngrayt exch get} + setcolortransfer + {pop 0} setundercolorremoval + {} setblackgeneration + } bind def +} +{ +/colorSetup2 { + [ /Indexed /DeviceRGB 255 + {dup red exch get 255 div + exch dup green exch get 255 div + exch blue exch get 255 div} + ] setcolorspace +} bind def +} ifelse +/fakecolorsetup { + /tran 256 string def + 0 1 255 {/indx exch def + tran indx + red indx get 77 mul + green indx get 151 mul + blue indx get 28 mul + add add 256 idiv put} for + currenttransfer + {255 mul cvi tran exch get 255.0 div} + exch fmConcatProcs settransfer +} bind def +/BITMAPCOLOR { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + fMLevel1 { + colorsetup + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} {is} {is} true 3 colorimage + } { + colorSetup2 + /is width depth wbytes string def + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {cf is readhexstring pop} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPCOLORc { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + fMLevel1 { + colorsetup + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} {is} {is} true 3 colorimage + } { + colorSetup2 + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {ip} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLORc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris} {gis} {bis} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYKc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip4 pop cis} {mis} {yis} {kis} true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLOR { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf gis readhexstring pop } + { cf bis readhexstring pop } + true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYK { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /mis width string def + /yis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf mis readhexstring pop } + { cf yis readhexstring pop } + { cf kis readhexstring pop } + true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUEGRAYc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris gis bis width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAYc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop cis mis yis kis width cgray} image + bitmapsave restore + grestore + } bind def +/cgray { + /ww exch def + /k exch def + /y exch def + /m exch def + /c exch def + 0 1 ww 1 sub { /i exch def c i get m i get y i get k i get CMYKtoRGB + .144 mul 3 1 roll .587 mul 3 1 roll .299 mul add add + c i 3 -1 roll floor cvi put } for + c + } bind def +/gray { + /ww exch def + /b exch def + /g exch def + /r exch def + 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul + b i get .114 mul add add r i 3 -1 roll floor cvi put } for + r + } bind def +/BITMAPTRUEGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf gis readhexstring pop + cf bis readhexstring pop width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /yis width string def + /mis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf mis readhexstring pop + cf yis readhexstring pop + cf kis readhexstring pop width cgray} image + bitmapsave restore + grestore + } bind def +/BITMAPGRAY { + 8 {fakecolorsetup} COMMONBITMAP + } bind def +/BITMAPGRAYc { + 8 {fakecolorsetup} COMMONBITMAPc + } bind def +/ENDBITMAP { + } bind def +end + /ALDmatrix matrix def ALDmatrix currentmatrix pop +/StartALD { + /ALDsave save def + savematrix + ALDmatrix setmatrix + } bind def +/InALD { + restorematrix + } bind def +/DoneALD { + ALDsave restore + } bind def +/I { setdash } bind def +/J { [] 0 setdash } bind def +%%EndProlog +%%BeginSetup +(5.0) FMVERSION +1 1 0 0 612 792 0 1 12 FMDOCUMENT +0 0 /Helvetica FMFONTDEFINE +1 0 /Times-BoldItalic FMFONTDEFINE +2 0 /Helvetica-Bold FMFONTDEFINE +3 0 /Helvetica-Oblique FMFONTDEFINE +4 0 /Courier FMFONTDEFINE +5 0 /Courier-Oblique FMFONTDEFINE +6 0 /Courier-Bold FMFONTDEFINE +32 FMFILLS +0 0 FMFILL +1 0.1 FMFILL +2 0.3 FMFILL +3 0.5 FMFILL +4 0.7 FMFILL +5 0.9 FMFILL +6 0.97 FMFILL +7 1 FMFILL +8 <0f1e3c78f0e1c387> FMFILL +9 <0f87c3e1f0783c1e> FMFILL +10 FMFILL +11 FMFILL +12 <8142241818244281> FMFILL +13 <03060c183060c081> FMFILL +14 <8040201008040201> FMFILL +16 1 FMFILL +17 0.9 FMFILL +18 0.7 FMFILL +19 0.5 FMFILL +20 0.3 FMFILL +21 0.1 FMFILL +22 0.03 FMFILL +23 0 FMFILL +24 FMFILL +25 FMFILL +26 <3333333333333333> FMFILL +27 <0000ffff0000ffff> FMFILL +28 <7ebddbe7e7dbbd7e> FMFILL +29 FMFILL +30 <7fbfdfeff7fbfdfe> FMFILL +%%EndSetup +%%Page: "i" 1 +%%BeginPaperSize: Letter +%%EndPaperSize +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(i) 555.78 57 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 720 558 720 2 L +0.5 H +2 Z +N +72 72 558 72 2 L +N +72 504 558 504 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 32 Q +(Introduction to CDEV) 180 662.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 12 Q +(Over) 180 638 T +(vie) 207.47 638 T +(w of the Contr) 223.97 638 T +(ol De) 304.39 638 T +(vice Interface) 333.55 638 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(Chip W) 180 610 T +(atson, Jie Chen, Danjin W) 218.86 610 T +(u, W) 357.22 610 T +(alt Ak) 381.41 610 T +(ers) 411.18 610 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 180 582 T +(ersion 1.5 December 9, 1996) 187.04 582 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(TJNAF - Thomas Jeff) 180 554 T +(erson National Acceler) 293.66 554 T +(ator F) 414.25 554 T +(acility) 445 554 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "i" 1 +%%Page: "ii" 2 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(ii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(TRADEMARKS:) 54 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(UNIX is a registered tr) 180 569.33 T +(ademar) 278.26 569.33 T +(k of A) 312.31 569.33 T +(T&T in the USA and other countr) 336.68 569.33 T +(ies) 481.9 569.33 T +(.) 494.53 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(VxW) 180 545.33 T +(or) 200.81 545.33 T +(ks is a register tr) 209.85 545.33 T +(ademar) 283.1 545.33 T +(k of Wind Riv) 317.15 545.33 T +(er Systems) 375.8 545.33 T +(.) 425.66 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The X Windo) 180 521.33 T +(w System is a tr) 237.65 521.33 T +(ademar) 308.12 521.33 T +(k of Massachusetts Institute of T) 342.17 521.33 T +(echnology) 484.37 521.33 T +(.) 528.95 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(OSF/Motif and Motif are tr) 180 497.33 T +(ademar) 294.94 497.33 T +(ks of Open Softw) 328.99 497.33 T +(are F) 404.99 497.33 T +(oundation, Inc.) 428.03 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ultr) 180 473.33 T +(ix and DEC are registered tr) 195.7 473.33 T +(ademar) 319.53 473.33 T +(ks of Digital Equipment Cor) 353.58 473.33 T +(por) 475.03 473.33 T +(ation.) 489.38 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(HPUX is a registered tr) 180 449.33 T +(ademar) 282.15 449.33 T +(k of He) 316.2 449.33 T +(wlett P) 347.68 449.33 T +(ac) 377.29 449.33 T +(kard.) 387.65 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(SURA/CEB) 54 344.33 T +(AF:) 105.92 344.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.44 (The Southeaster) 180 344.33 P +4.44 (n Univ) 258.62 344.33 P +4.44 (ersities Research Association \050SURA\051 oper) 291.15 344.33 P +4.44 (ates the) 499.98 344.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.01 (Contin) 180 332.33 P +2.01 (uous Electron Beam Acceler) 208.8 332.33 P +2.01 (ator F) 340.89 332.33 P +2.01 (acility \050CEBAF\051 f) 368.52 332.33 P +2.01 (or the United States) 445.59 332.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Depar) 180 320.33 T +(tment of Energy under contr) 207.63 320.33 T +(act DE-A) 331.48 320.33 T +(C05-84ER40150.) 371.19 320.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DISCLAIMER:) 54 218.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.49 (This repor) 180 218.33 P +0.49 (t w) 225.9 218.33 P +0.49 (as prepared as an account of w) 239.02 218.33 P +0.49 (or) 381.4 218.33 P +0.49 (k sponsored b) 390.44 218.33 P +0.49 (y the United States) 454.03 218.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.18 (go) 180 206.33 P +2.18 (v) 190.97 206.33 P +2.18 (er) 195.72 206.33 P +2.18 (nment. Neither the United States nor the United States Depar) 204.86 206.33 P +2.18 (tment of) 501.68 206.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.04 (Energy) 180 194.33 P +1.04 (, nor an) 210.68 194.33 P +1.04 (y of their emplo) 246.52 194.33 P +1.04 (y) 317.69 194.33 P +1.04 (ees) 322.49 194.33 P +1.04 (, mak) 338.46 194.33 P +1.04 (es an) 363.75 194.33 P +1.04 (y w) 389.1 194.33 P +1.04 (arr) 404.99 194.33 P +1.04 (anty) 417.11 194.33 P +1.04 (, e) 435.01 194.33 P +1.04 (xpress or implied, or) 446.86 194.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.83 (assumes an) 180 182.33 P +1.83 (y legal liability or responsibility f) 235.59 182.33 P +1.83 (or the accur) 383.89 182.33 P +1.83 (acy) 440.24 182.33 P +1.83 (, completeness) 454.8 182.33 P +1.83 (, or) 523.72 182.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.68 (usefulness of an) 180 170.33 P +3.68 (y inf) 260.02 170.33 P +3.68 (or) 281.74 170.33 P +3.68 (mation, appar) 290.88 170.33 P +3.68 (atus) 355.59 170.33 P +3.68 (, product or process disclosed, or) 374.34 170.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.46 (represents that its use w) 180 158.33 P +2.46 (ould not infr) 298.11 158.33 P +2.46 (inge pr) 355.42 158.33 P +2.46 (iv) 388.59 158.33 P +2.46 (ately o) 395.56 158.33 P +2.46 (wned r) 427.33 158.33 P +2.46 (ights) 459.95 158.33 P +2.46 (. Ref) 480.92 158.33 P +2.46 (erence) 509.43 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.6 (herein to an) 180 146.33 P +1.6 (y speci\336c commercial product, process) 235.85 146.33 P +1.6 (, or ser) 413.79 146.33 P +1.6 (vice b) 448.4 146.33 P +1.6 (y tr) 475.92 146.33 P +1.6 (ade name) 491.3 146.33 P +1.6 (,) 537.22 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (mar) 180 134.33 P +2.12 (k, man) 197.37 134.33 P +2.12 (uf) 229.4 134.33 P +2.12 (acturer) 237.44 134.33 P +2.12 (, or otherwise) 268.06 134.33 P +2.12 (, does not necessar) 332.17 134.33 P +2.12 (ily constitute or imply its) 425.94 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (endorsement, recommendation, or f) 180 122.33 P +1.08 (a) 341.33 122.33 P +1.08 (v) 346.69 122.33 P +1.08 (or) 351.44 122.33 P +1.08 (ing b) 360.48 122.33 P +1.08 (y the United States go) 383.03 122.33 P +1.08 (v) 485.57 122.33 P +1.08 (er) 490.32 122.33 P +1.08 (nment or) 499.46 122.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (an) 180 110.33 P +0.83 (y agency thereof) 190.97 110.33 P +0.83 (. The vie) 266.26 110.33 P +0.83 (w and opinions of the authors e) 309.67 110.33 P +0.83 (xpressed herein do) 453.3 110.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.94 (not necessar) 180 98.33 P +1.94 (ily state or re\337ect those of the United States go) 239.34 98.33 P +1.94 (v) 464.01 98.33 P +1.94 (er) 468.76 98.33 P +1.94 (nment or an) 477.9 98.33 P +1.94 (y) 535 98.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(agency thereof) 180 86.33 T +(.) 245.85 86.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DOCUMENT D) 54 668.33 T +(A) 121.37 668.33 T +(TE:) 127.69 668.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(T) 180 668.33 T +(ab) 184.91 668.33 T +(le of ontents gener) 195.83 668.33 T +(ated: December 9, 1996 11:45 am) 278.56 668.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "ii" 2 +%%Page: "iii" 3 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iii) 551.34 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(T) 180 710.67 T +(ab) 187.43 710.67 T +(le of Contents) 203.63 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(List of Figures) 198 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(v) 553 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 180 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Introduction) 198 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 252.98 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(What is CDEV) 198 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(La) 198 648.33 T +(y) 208.82 648.33 T +(er) 213.62 648.33 T +(ing and Abstr) 222.66 648.33 T +(action) 281.48 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Inf) 198 636.33 T +(or) 208.82 636.33 T +(mation Hiding) 217.96 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198 624.33 T +(vice Object) 210.48 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Standard Messages) 198 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 289.12 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data Object) 198 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 252.98 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 180 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Basic Oper) 198 588.33 T +(ations on De) 247.36 588.33 T +(vices and Data) 303.2 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 369.74 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 180 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Asychronous Oper) 198 576.33 T +(ations) 280.71 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Callbac) 198 564.33 T +(k Object) 231.14 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(System Object) 198 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Group Object) 198 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Request Object) 198 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(File Descr) 198 516.33 T +(iptors and \322select\323) 243.15 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 325.26 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 180 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Error Handling) 198 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 180 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name Resolution) 198 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 198 480.33 T +(vDirector) 213.82 480.33 T +(y Object) 254.12 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ser) 198 468.33 T +(vice De\336nition) 213.86 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 546.88 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198 456.33 T +(vice Class De\336nition) 210.48 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 303.02 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15) 546.88 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Instance De\336nition) 198 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Aliases) 198 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 230.74 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 180 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Channel Access Ser) 198 420.33 T +(vice) 288.89 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 546.88 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iii" 3 +%%Page: "iv" 4 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iv) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iv" 4 +%%Page: "v" 5 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +( List of Figures) 498.98 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(v) 553 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(List of Figures) 180 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(Figure 1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample usage of the send method of a cdevDevice) 234 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(................................) 461.48 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 2.) 180 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Overview of cdevData operations) 234 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(............................................................) 383.64 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 3.) 180 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Three forms of the send command) 234 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..........................................................) 389.2 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 4.) 180 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Overview of the cdevCallback object and the cdevCallbackFunction) 234 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(......) 533.76 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 5.) 180 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Structure of the cdevCallback object) 234 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................................................) 394.76 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 6.) 180 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Usage of the pend method in the cdevSystem object) 234 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..............................) 467.04 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 7.) 180 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Synchronization methods in the cdevSystem object) 234 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(................................) 461.48 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 8.) 180 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample usage of the cdevGroup object) 234 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................................) 408.66 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 9.) 180 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample usage of the cdevRequestObject object) 234 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.....................................) 447.58 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 10.) 180 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Structure of the cdevRequestObject object) 234 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..............................................) 422.56 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 11.) 180 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(File descriptor routines of the cdevSystem object) 234 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(....................................) 450.36 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 12.) 180 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using CDEV file descriptors with the UNIX select function) 234 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(....................) 489.28 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 13.) 180 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Error handling mechanisms provided by the cdevSystem object) 234 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........) 514.3 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 14.) 180 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Enumerated severity codes generated by CDEV) 234 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................) 447.58 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 15.) 180 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Enumerated error codes generated by CDEV) 234 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................................) 433.68 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 546.88 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 16.) 180 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Obtaining a reference to the cdevDirectory device) 234 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(................................) 455.92 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 17.) 180 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Virtual form of the data in a cdevDirectory) 234 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.............................................) 419.78 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 18.) 180 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Syntax of the #include directive) 234 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..............................................................) 372.52 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 546.88 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 19.) 180 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample service definition) 234 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................................................................) 347.5 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 546.88 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 20.) 180 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample service definition) 234 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................................................................) 347.5 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15) 546.88 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 21.) 180 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample inherited class definition) 234 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(............................................................) 378.08 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 22.) 180 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Multiple instances of the magnet class) 234 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................................) 403.1 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 23.) 180 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Alias device name) 234 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..................................................................................) 316.92 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "v" 5 +%%Page: "vi" 6 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +( List of Figures) 54 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(vi) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "vi" 6 +%%Page: "1" 7 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. Introduction) 500.97 739 T +0 10 Q +(1) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(1.) 159.32 710.67 T +(Intr) 180 710.67 T +(oduction) 202.27 710.67 T +2 10 Q +(What is CDEV) 72 673.33 T +0 F +1.09 (The CDEV \050common de) 180 673.33 P +1.09 (vice\051 C++ class libr) 289.11 673.33 P +1.09 (ar) 376.73 673.33 P +1.09 (y is an object-or) 385.92 673.33 P +1.09 (iented fr) 459.92 673.33 P +1.09 (ame) 497.04 673.33 P +1.09 (w) 516.29 673.33 P +1.09 (or) 523.41 673.33 P +1.09 (k that) 532.45 673.33 P +1.76 (pro) 180 661.33 P +1.76 (vides a standard interf) 194.3 661.33 P +1.76 (ace betw) 297.65 661.33 P +1.76 (een an application and one or more under) 339.33 661.33 P +1.76 (lying) 537.44 661.33 P +4.52 (control pac) 180 649.33 P +4.52 (kages or systems) 233.23 649.33 P +4.52 (. Each under) 319.92 649.33 P +4.52 (lying pac) 385.81 649.33 P +4.52 (kage \050called a ser) 429.59 649.33 P +4.52 (vice\051 is) 522.37 649.33 P +1.18 (dynamically loaded at r) 180 637.33 P +1.18 (un-time) 285.96 637.33 P +1.18 (, allo) 319.15 637.33 P +1.18 (wing an application to access a ne) 341.31 637.33 P +1.18 (w ser) 500.52 637.33 P +1.18 (vice b) 525.9 637.33 P +1.18 (y) 553 637.33 P +-0.09 (name without re-compilation or re-linking. A major f) 180 625.33 P +-0.09 (eature of CDEV is its ability to hide) 404.68 625.33 P +2.93 (the implementation details of a par) 180 613.33 P +2.93 (ticular de) 347.88 613.33 P +2.93 (vice from the high le) 391.08 613.33 P +2.93 (v) 491.96 613.33 P +2.93 (el application) 496.71 613.33 P +0.07 (de) 180 601.33 P +0.07 (v) 190.82 601.33 P +0.07 (eloper) 195.57 601.33 P +0.07 (. This allo) 222.86 601.33 P +0.07 (ws ser) 265.63 601.33 P +0.07 (v) 294.89 601.33 P +0.07 (er implementation choices to be changed without breaking) 299.64 601.33 P +0.9 (high le) 180 589.33 P +0.9 (v) 210.06 589.33 P +0.9 (el client applications) 214.81 589.33 P +0.9 (. Additionally) 305.93 589.33 P +0.9 (, because the application is una) 362.52 589.33 P +0.9 (w) 506.89 589.33 P +0.9 (are of the) 513.96 589.33 P +4.86 (under) 180 577.33 P +4.86 (lying ser) 205.72 577.33 P +4.86 (vice\325) 248.11 577.33 P +4.86 (s speci\336c implementation, CDEV is a po) 267.61 577.33 P +4.86 (w) 473.91 577.33 P +4.86 (erful v) 481.03 577.33 P +4.86 (ehicle f) 512.87 577.33 P +4.86 (or) 549.11 577.33 P +(de) 180 565.33 T +(v) 190.82 565.33 T +(eloping por) 195.57 565.33 T +(tab) 245.44 565.33 T +(le applications) 259.14 565.33 T +(.) 322.35 565.33 T +-0.25 (The basic CDEV interf) 180 548.33 P +-0.25 (ace can be descr) 277.88 548.33 P +-0.25 (ibed through a) 353.43 548.33 P +3 F +-0.25 (de) 419.4 548.33 P +-0.25 (vice) 430.22 548.33 P +0 F +-0.25 (/) 448 548.33 P +3 F +-0.25 (message) 450.78 548.33 P +0 F +-0.25 ( par) 491.35 548.33 P +-0.25 (adigm. The) 508.23 548.33 P +3 F +2.36 (de) 180 536.33 P +2.36 (vice) 190.82 536.33 P +0 F +2.36 ( is not necessar) 208.6 536.33 P +2.36 (ily a ph) 285.85 536.33 P +2.36 (ysical object, r) 321.94 536.33 P +2.36 (ather) 389.9 536.33 P +2.36 (, it is a cde) 412.19 536.33 P +2.36 (vDe) 469.11 536.33 P +2.36 (vice object that) 486.59 536.33 P +1.42 (pro) 180 524.33 P +1.42 (vides a standard interf) 194.3 524.33 P +1.42 (ace to CDEV) 296.64 524.33 P +1.42 (. The application uses this interf) 356.03 524.33 P +1.42 (ace to send) 503.46 524.33 P +4.12 (messages to the de) 180 512.33 P +4.12 (vice) 279.32 512.33 P +4.12 (. When the cde) 296.95 512.33 P +4.12 (vDe) 376.26 512.33 P +4.12 (vice receiv) 393.74 512.33 P +4.12 (es this message it will) 444.84 512.33 P +1.36 (dynamically load the appropr) 180 500.33 P +1.36 (iate ser) 312.05 500.33 P +1.36 (vice \050as de\336ned in the CDEV de) 346.49 500.33 P +1.36 (vice de\336nition) 496.06 500.33 P +2.96 (\336le\051, and f) 180 488.33 P +2.96 (orw) 229.54 488.33 P +2.96 (ard the message to it. The ser) 245.49 488.33 P +2.96 (vice ma) 396.41 488.33 P +2.96 (y then perf) 433.52 488.33 P +2.96 (or) 486.39 488.33 P +2.96 (m an) 495.54 488.33 P +2.96 (y action) 520.58 488.33 P +(necessar) 180 476.33 T +(y to satisfy the application\325) 220.87 476.33 T +(s request.) 337.09 476.33 T +0.13 (The CDEV API is optimiz) 180 459.33 P +0.13 (ed f) 291.52 459.33 P +0.13 (or repetitiv) 308.03 459.33 P +0.13 (e oper) 354.6 459.33 P +0.13 (ations) 382.98 459.33 P +0.13 (, in par) 409.51 459.33 P +0.13 (ticular f) 440.74 459.33 P +0.13 (or monitor) 472.8 459.33 P +0.13 (ing v) 518.1 459.33 P +0.13 (alue) 539.1 459.33 P +3.2 (changes within a ser) 180 447.33 P +3.2 (v) 281.04 447.33 P +3.2 (er) 285.79 447.33 P +3.2 (. Asychronous oper) 294.18 447.33 P +3.2 (ations with callbac) 386.62 447.33 P +3.2 (ks are suppor) 473.95 447.33 P +3.2 (ted,) 541.32 447.33 P +0.11 (including asychronous error noti\336cation. Speci\336cally) 180 435.33 P +0.11 (, CDEV suppor) 408.4 435.33 P +0.11 (ts most f) 475.71 435.33 P +0.11 (eatures of) 513.42 435.33 P +(channel access \050the EPICS comm) 180 423.33 T +(unications protocol\051.) 331.62 423.33 T +2 F +(La) 72 394.33 T +(y) 83.47 394.33 T +(ering and) 88.93 394.33 T +(Abstraction) 72 382.33 T +0 F +1.59 (The CDEV libr) 180 394.33 P +1.59 (ar) 246.98 394.33 P +1.59 (y pro) 256.17 394.33 P +1.59 (vides a standard interf) 279.84 394.33 P +1.59 (ace to one or more under) 382.68 394.33 P +1.59 (lying control) 503.06 394.33 P +0.95 (pac) 180 382.33 P +0.95 (kages or systems) 195.92 382.33 P +0.95 (. Currently CDEV pro) 275.48 382.33 P +0.95 (vides suppor) 372.1 382.33 P +0.95 (t f) 430.14 382.33 P +0.95 (or EPICS channel access) 439.13 382.33 P +0.95 (,) 555.22 382.33 P +0.54 (tcl scr) 180 370.33 P +0.54 (ipts) 206.8 370.33 P +0.54 (, the A) 222.21 370.33 P +0.54 (CE comm) 251.9 370.33 P +0.54 (unications pac) 296.22 370.33 P +0.54 (kage \050a C++ class libr) 360.48 370.33 P +0.54 (ar) 459.23 370.33 P +0.54 (y o) 468.42 370.33 P +0.54 (v) 482.15 370.33 P +0.54 (er TCP/IP\051. The) 486.9 370.33 P +0.59 (A) 180 358.33 P +0.59 (CE pac) 186.37 358.33 P +0.59 (kage is used to comm) 219.55 358.33 P +0.59 (unicate with an on-line acceler) 319.08 358.33 P +0.59 (ator modeling pac) 455.85 358.33 P +0.59 (kage) 536.32 358.33 P +0.92 (and with COD) 180 346.33 P +0.92 (A, the CEBAF On-line Data Acquisition system. Access to the EPICS) 243.68 346.33 P +0.07 (archiv) 180 334.33 P +0.07 (e data will be added in a later release) 206.42 334.33 P +0.07 (. All data will be a) 372.46 334.33 P +0.07 (v) 450.41 334.33 P +0.07 (ailab) 455.16 334.33 P +0.07 (le through a single) 476.08 334.33 P +(API \050application prog) 180 322.33 T +(r) 272.72 322.33 T +(amming interf) 275.95 322.33 T +(ace\051.) 336.22 322.33 T +2 F +(Inf) 72 293.33 T +(ormation Hiding) 84.02 293.33 T +0 F +-0.24 (The ability to hide the implementation details of a par) 180 293.33 P +-0.24 (ticular de) 412.23 293.33 P +-0.24 (vice \050such as the choice) 452.26 293.33 P +3.9 (of records in EPICS\051 from the high le) 180 281.33 P +3.9 (v) 369.85 281.33 P +3.9 (el application de) 374.6 281.33 P +3.9 (v) 454.36 281.33 P +3.9 (eloper) 459.11 281.33 P +3.9 (, allo) 486.4 281.33 P +3.9 (ws ser) 511.27 281.33 P +3.9 (v) 544.36 281.33 P +3.9 (er) 549.11 281.33 P +4.84 (implementation choices to be changed without breaking all high le) 180 269.33 P +4.84 (v) 514.51 269.33 P +4.84 (el client) 519.26 269.33 P +0.46 (applications) 180 257.33 P +0.46 (. F) 232.65 257.33 P +0.46 (or e) 244.48 257.33 P +0.46 (xample) 261.86 257.33 P +0.46 (, se) 293.94 257.33 P +0.46 (v) 310.22 257.33 P +0.46 (er) 314.97 257.33 P +0.46 (al records ma) 323.76 257.33 P +0.46 (y be merged into a ne) 384.94 257.33 P +0.46 (w custom record) 483.74 257.33 P +(without changing applications which access those records through the CDEV API.) 180 245.33 T +2 F +(De) 72 216.33 T +(vice Object) 84.63 216.33 T +0 F +1.61 (The basic idea behind CDEV is that all I/O is perf) 180 216.33 P +1.61 (or) 412.56 216.33 P +1.61 (med b) 421.7 216.33 P +1.61 (y sending messages to) 450.9 216.33 P +0.4 (de) 180 204.33 P +0.4 (vices) 190.82 204.33 P +0.4 (. A de) 213.45 204.33 P +0.4 (vice is a named entity in the control system which can respond to a set) 240.07 204.33 P +1.71 (of messages such as) 180 192.33 P +3 F +1.71 (on) 283.53 192.33 P +0 F +1.71 ( or) 294.65 192.33 P +3 F +1.71 (off) 312.51 192.33 P +0 F +1.71 ( or) 323.63 192.33 P +3 F +1.71 (get current) 341.49 192.33 P +0 F +1.71 (. Fur) 391 192.33 P +1.71 (ther) 413.67 192.33 P +1.71 (, a de) 430.4 192.33 P +1.71 (vice is a vir) 458.53 192.33 P +1.71 (tual entity) 513.49 192.33 P +3.22 (potentially spanning m) 180 180.33 P +3.22 (ultiple ser) 285.83 180.33 P +3.22 (v) 332.14 180.33 P +3.22 (ers and ser) 336.89 180.33 P +3.22 (vices such as channel access) 393.65 180.33 P +3.22 (, an) 538.1 180.33 P +(archiv) 180 168.33 T +(er) 206.42 168.33 T +(, and a static database) 214.81 168.33 T +(.) 315.28 168.33 T +2.1 (Each de) 180 151.33 P +2.1 (vice and message pair is mapped to a unique ser) 218.49 151.33 P +2.1 (vice \050such as channel) 455.55 151.33 P +0.61 (access\051 and ser) 180 139.33 P +0.61 (vice dependent data \050such as the process v) 252.09 139.33 P +0.61 (ar) 448.97 139.33 P +0.61 (iab) 458.01 139.33 P +0.61 (le name in EPICS\051.) 471.15 139.33 P +0.03 (This mapping is k) 180 127.33 P +0.03 (ept in a name ser) 257.69 127.33 P +0.03 (vice) 335.36 127.33 P +0.03 (, and is ultimately initializ) 352.99 127.33 P +0.03 (ed from an ASCII \336le) 462.99 127.33 P +0.03 (.) 555.22 127.33 P +1.17 (The designer/maintainer of the ser) 180 115.33 P +1.17 (v) 337.26 115.33 P +1.17 (er w) 342.01 115.33 P +1.17 (ould typically be the person responsib) 361.97 115.33 P +1.17 (le f) 534.9 115.33 P +1.17 (or) 549.11 115.33 P +(k) 180 103.33 T +(eeping the mapping current.) 184.8 103.33 T +FMENDPAGE +%%EndPage: "1" 7 +%%Page: "2" 8 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. Introduction) 54 739 T +0 10 Q +(2) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +2 10 Q +(Standar) 54 713.33 T +(d) 91.03 713.33 T +(Messa) 54 701.33 T +(g) 84.47 701.33 T +(es) 90.68 701.33 T +0 F +0.72 (Most de) 162 713.33 P +0.72 (vices will implement a n) 197.99 713.33 P +0.72 (umber of attr) 305.81 713.33 P +0.72 (ib) 364.1 713.33 P +0.72 (utes which ma) 371.68 713.33 P +0.72 (y be read or wr) 436.74 713.33 P +0.72 (itten. In) 506.48 713.33 P +1.32 (order to f) 162 701.33 P +1.32 (acilitate de) 204.37 701.33 P +1.32 (v) 253.19 701.33 P +1.32 (eloping gener) 257.94 701.33 P +1.32 (ic applications) 320 701.33 P +1.32 (, the f) 383.98 701.33 P +1.32 (ollo) 411.34 701.33 P +1.32 (wing standard messages) 426.75 701.33 P +(are recommended f) 162 689.33 T +(or de) 248.4 689.33 T +(vices) 270.89 689.33 T +(, where) 293.52 689.33 T +3 F +(attr) 329.09 689.33 T +(ib) 343.69 689.33 T +0 F +( is some attr) 351.47 689.33 T +(ib) 406.08 689.33 T +(ute of the de) 413.66 689.33 T +(vice:) 468.96 689.33 T +4 9 Q +(set) 180 673 T +5 F +(attrib) 201.6 673 T +4 F +( => Set the value of the attribute) 234 673 T +(get) 180 662 T +5 F +(attrib) 201.6 662 T +4 F +( => Get the value of the attribute) 234 662 T +-0.51 (monitorOn) 180 651 P +5 F +-0.51 (attrib) 233.49 651 P +4 F +-0.51 ( => Start monitoring the value of the attribute) 265.89 651 P +-0.14 (monitorOff) 180 640 P +5 F +-0.14 (attrib) 239.26 640 P +4 F +-0.14 ( => Stop monitoring the value of the attribute) 271.66 640 P +2 10 Q +(Data Object) 54 611.33 T +0 F +0.91 (The message sent to the de) 162 611.33 P +0.91 (vice ma) 290.21 611.33 P +0.91 (y ha) 325.27 611.33 P +0.91 (v) 344.89 611.33 P +0.91 (e an associated data object. F) 349.64 611.33 P +0.91 (or e) 487.3 611.33 P +0.91 (xample) 505.14 611.33 P +0.91 (,) 537.22 611.33 P +-0.23 (the message) 162 599.33 P +3 F +-0.23 (set current) 221.57 599.33 P +0 F +-0.23 ( will ha) 268.59 599.33 P +-0.23 (v) 298.49 599.33 P +-0.23 (e an associated) 303.24 599.33 P +3 F +-0.23 (v) 375.38 599.33 P +-0.23 (alue) 380.13 599.33 P +0 F +-0.23 ( f) 399.03 599.33 P +-0.23 (or the ne) 404.06 599.33 P +-0.23 (w current setting. This) 442.87 599.33 P +(v) 162 587.33 T +(alue is passed as an additional argument on the send call.) 166.75 587.33 T +2.64 (Data retur) 162 570.33 P +2.64 (ned from the ser) 209.35 570.33 P +2.64 (v) 290.38 570.33 P +2.64 (er to the client ma) 295.13 570.33 P +2.64 (y contain m) 384.87 570.33 P +2.64 (ultiple tagged v) 441.18 570.33 P +2.64 (alues) 513.47 570.33 P +2.64 (,) 537.22 570.33 P +1.92 (including) 162 558.33 P +3 F +1.92 (v) 206.16 558.33 P +1.92 (alue) 210.91 558.33 P +0 F +1.92 (,) 229.66 558.33 P +3 F +1.92 (status) 237.14 558.33 P +0 F +1.92 (, and) 263.67 558.33 P +3 F +1.92 ( timestamp) 287.83 558.33 P +0 F +1.92 (. Each of these items is e) 338.3 558.33 P +1.92 (xtr) 461.23 558.33 P +1.92 (acted from the) 472.24 558.33 P +1.5 (retur) 162 546.33 P +1.5 (ned data object b) 182.81 546.33 P +1.5 (y specifying a name or an integer tag. An) 263.83 546.33 P +1.5 (y data object ma) 457.43 546.33 P +1.5 (y) 535 546.33 P +2.68 (contain an arbitr) 162 534.33 P +2.68 (ar) 238.97 534.33 P +2.68 (y n) 248.16 534.33 P +2.68 (umber of tagged entr) 264.08 534.33 P +2.68 (ies) 365.11 534.33 P +2.68 (, allo) 377.74 534.33 P +2.68 (wing consider) 401.4 534.33 P +2.68 (ab) 465.11 534.33 P +2.68 (le \337e) 476.03 534.33 P +2.68 (xibility in) 499.54 534.33 P +(de\336ning future clients and ser) 162 522.33 T +(v) 292.92 522.33 T +(ers) 297.67 522.33 T +(.) 311.41 522.33 T +3 F +0.83 (Ac) 162 505.33 P +0.83 (kno) 173.47 505.33 P +0.83 (wledgment: This w) 189.44 505.33 P +0.83 (or) 273.8 505.33 P +0.83 (k der) 282.84 505.33 P +0.83 (iv) 306.04 505.33 P +0.83 (es some of its ideas about de) 313.01 505.33 P +0.83 (vices and messages) 447.75 505.33 P +1.38 (from w) 162 493.33 P +1.38 (or) 193.28 493.33 P +1.38 (k done at Argonne b) 202.32 493.33 P +1.38 (y Claude Saunders on a de) 297.69 493.33 P +1.38 (vice or) 425.46 493.33 P +1.38 (iented la) 456.43 493.33 P +1.38 (y) 495.31 493.33 P +1.38 (er abo) 500.11 493.33 P +1.38 (v) 529.69 493.33 P +1.38 (e) 534.44 493.33 P +0.22 (channel access) 162 481.33 P +0.22 (. Much additional analysis & design w) 230.99 481.33 P +0.22 (or) 398.36 481.33 P +0.22 (k has been done b) 407.39 481.33 P +0.22 (y members) 490.33 481.33 P +(of the EPICS collabor) 162 469.33 T +(ation.) 257.5 469.33 T +FMENDPAGE +%%EndPage: "2" 8 +%%Page: "3" 9 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. Basic Operations on Devices and Data) 393.43 739 T +0 10 Q +(3) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(2.) 159.32 710.67 T +(Basic Operations on De) 180 710.67 T +(vices and Data) 337.72 710.67 T +0 10 Q +0.44 (The basic user deals only with the de) 180 684.33 P +0.44 (vice and data objects) 347.28 684.33 P +0.44 (. The de) 442.38 684.33 P +0.44 (vice is created b) 479.64 684.33 P +0.44 (y) 553 684.33 P +0.54 (name) 180 672.33 P +0.54 (, and I/O consists of sending messages to this de) 204.86 672.33 P +0.54 (vice) 427.34 672.33 P +0.54 (. The de) 444.97 672.33 P +0.54 (vice object is the) 482.45 672.33 P +0.8 (simplest I/O object to use: a single de) 180 660.33 P +0.8 (vice \050magnet, vie) 351.47 660.33 P +0.8 (w) 428.45 660.33 P +0.8 (er) 435.57 660.33 P +0.8 (, etc.\051 ma) 443.96 660.33 P +0.8 (y be completely) 486.93 660.33 P +0.36 (controlled from a single de) 180 648.33 P +0.36 (vice object, with data being passed b) 298.39 648.33 P +0.36 (y 2 data objects \050one) 463.75 648.33 P +0.2 (f) 180 636.33 P +0.2 (or output, another f) 182.48 636.33 P +0.2 (or retur) 267.27 636.33 P +0.2 (ned results; dataless commands w) 299.95 636.33 P +0.2 (ould not require either\051.) 454.03 636.33 P +0.55 (The f) 180 624.33 P +0.55 (ollo) 203.04 624.33 P +0.55 (wing sample code reads the magnet current from one magnet, and sets the) 218.45 624.33 P +(magnet current f) 180 612.33 T +(or a second magnet to that v) 252.51 612.33 T +(alue:) 379 612.33 T +3 9 Q +(Figure 1: Sample usage of the send method of a cde) 180 579 T +(vDe) 391.85 579 T +(vice) 407.58 579 T +0 10 Q +2.25 (The send call, which is synchronous) 180 340.33 P +2.25 (, tak) 351.15 340.33 P +2.25 (es 3 arguments) 372.1 340.33 P +2.25 (, and retur) 445.37 340.33 P +2.25 (ns an integer) 495.69 340.33 P +(status:) 180 328.33 T +6 9 Q +(int send\050char* msg, cdevData& out, cdevData& result\051;) 198 312 T +0 10 Q +0.22 (Lik) 180 295.33 P +0.22 (e all CDEV calls) 192.58 295.33 P +0.22 (, a retur) 264.78 295.33 P +0.22 (n code of 0 means success \050error handling is descr) 299.94 295.33 P +0.22 (ibed in) 528.32 295.33 P +0.19 (a later section\051. The \336rst argument to) 180 283.33 P +3 F +0.19 (send) 347.52 283.33 P +0 F +0.19 ( is a char) 369.2 283.33 P +0.19 (acter str) 410.25 283.33 P +0.19 (ing message) 446.71 283.33 P +0.19 (. The de) 503.45 283.33 P +0.19 (vice) 540.22 283.33 P +0.41 (name and this str) 180 271.33 P +0.41 (ing uniquely deter) 258.08 271.33 P +0.41 (mine the under) 338.07 271.33 P +0.41 (lying ser) 405.74 271.33 P +0.41 (vice to use) 443.68 271.33 P +0.41 (, and whate) 492.14 271.33 P +0.41 (v) 544.36 271.33 P +0.41 (er) 549.11 271.33 P +2.06 (addressing data that ser) 180 259.33 P +2.06 (vice needs to locate the ser) 293.77 259.33 P +2.06 (v) 426.1 259.33 P +2.06 (er) 430.85 259.33 P +2.06 (. The \336rst) 439.24 259.33 P +3 F +2.06 (send) 489.89 259.33 P +0 F +2.06 ( oper) 511.57 259.33 P +2.06 (ation) 536.32 259.33 P +0.57 (automatically connects to the requested ser) 180 247.33 P +0.57 (vice) 376.01 247.33 P +0.57 (, initializing an) 393.64 247.33 P +0.57 (y under) 457.42 247.33 P +0.57 (lying pac) 491.49 247.33 P +0.57 (kages) 531.32 247.33 P +(as needed.) 180 235.33 T +0.11 (The second and third arguments are outbound and result data of type cde) 180 218.33 P +0.11 (vData. This) 507.32 218.33 P +1.75 (is a composite data object which ma) 180 206.33 P +1.75 (y contain an arbitr) 350.82 206.33 P +1.75 (ar) 435.44 206.33 P +1.75 (y n) 444.63 206.33 P +1.75 (umber of data v) 459.62 206.33 P +1.75 (alues) 534.1 206.33 P +1.45 (tagged with an integer tag. The data is self-descr) 180 194.33 P +1.45 (ibing to the e) 407.95 194.33 P +1.45 (xtent that cde) 469.25 194.33 P +1.45 (vData) 531.88 194.33 P +2.38 (k) 180 182.33 P +2.38 (eeps tr) 184.8 182.33 P +2.38 (ac) 217.65 182.33 P +2.38 (k of the data type) 228.01 182.33 P +2.38 (, and can automatically con) 314.12 182.33 P +2.38 (v) 444.63 182.33 P +2.38 (er) 449.38 182.33 P +2.38 (t betw) 458.67 182.33 P +2.38 (een data types) 487.63 182.33 P +0.85 (through C++ function o) 180 170.33 P +0.85 (v) 284.13 170.33 P +0.85 (er) 288.88 170.33 P +0.85 (loading or b) 297.92 170.33 P +0.85 (y e) 351.67 170.33 P +0.85 (xplicit direction from the caller) 365.56 170.33 P +0.85 (. The integer) 500.16 170.33 P +-0.05 (tags are not kno) 180 158.33 P +-0.05 (wn to the user at compile time \050i.e) 251.42 158.33 P +-0.05 (., no header \336les required\051, and can) 400.43 158.33 P +0.77 (be ref) 180 146.33 P +0.77 (erred to b) 206.04 146.33 P +0.77 (y char) 250.19 146.33 P +0.77 (acter str) 278.09 146.33 P +0.77 (ing equiv) 315.14 146.33 P +0.77 (alents) 355.68 146.33 P +0.77 (. The cde) 382.21 146.33 P +0.77 (vData class k) 425.14 146.33 P +0.77 (eeps tr) 485.95 146.33 P +0.77 (ac) 517.19 146.33 P +0.77 (k of all) 527.55 146.33 P +2.33 (integer tags and their char) 180 134.33 P +2.33 (acter str) 305.4 134.33 P +2.33 (ing equiv) 344.01 134.33 P +2.33 (alents) 386.11 134.33 P +2.33 (. Char) 412.64 134.33 P +2.33 (acter str) 442.11 134.33 P +2.33 (ing tags ma) 480.71 134.33 P +2.33 (y be) 536.77 134.33 P +1.8 (con) 180 122.33 P +1.8 (v) 195.92 122.33 P +1.8 (er) 200.67 122.33 P +1.8 (ted to integer tags at r) 209.96 122.33 P +1.8 (un time to impro) 316.38 122.33 P +1.8 (v) 393.31 122.33 P +1.8 (e perf) 398.06 122.33 P +1.8 (or) 425.13 122.33 P +1.8 (mance) 434.27 122.33 P +1.8 (. The f) 464.13 122.33 P +1.8 (ollo) 495.77 122.33 P +1.8 (wing code) 511.18 122.33 P +(demonstr) 180 110.33 T +(ates ho) 221.58 110.33 T +(w to inser) 254.23 110.33 T +(t v) 297.42 110.33 T +(alues into and e) 307.73 110.33 T +(xtr) 378.03 110.33 T +(act v) 389.04 110.33 T +(alues from a cde) 409.91 110.33 T +(vData object:) 483.53 110.33 T +180 81 558 691 C +180 371 558 576 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +125.07 371 612.93 576 R +7 X +0 0 0 1 0 0 0 K +V +186.17 379.09 561.88 570.52 R +0 X +V +0.5 H +2 Z +N +182.4 382.24 554.91 573.67 R +7 X +V +0 X +N +184.62 388.62 552.24 571.47 R +7 X +V +6 9 Q +0 X +(void main \050\051) 184.62 565.47 T +({) 202.62 554.47 T +(// *************************************************************) 202.62 543.47 T +(// * Get references to the 2 devices) 202.62 532.47 T +(// *************************************************************) 202.62 521.47 T +(cdevDevice& mag1 = cdevDevice::attachRef \050\322Magnet1\323\051;) 202.62 510.48 T +(cdevDevice& mag2 = cdevDevice::attachRef \050\322Magnet2\323\051;) 202.62 499.48 T +(cdevData result;) 202.62 488.48 T +(// *************************************************************) 202.62 466.48 T +(// * Get the current from the first magnet and use it to set) 202.62 455.48 T +(// * the current on the second.) 202.62 444.48 T +(// *************************************************************) 202.62 433.48 T +(mag1.send\050\322get current\323, NULL, result\051;) 202.62 422.48 T +(mag2.send\050\322set current\323, result, NULL\051;) 202.62 411.48 T +(}) 202.62 400.48 T +180 81 558 691 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "3" 9 +%%Page: "4" 10 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. Basic Operations on Devices and Data) 54 739 T +0 10 Q +(4) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +3 F +(Figure 2: Ov) 162 714 T +(er) 213.79 714 T +(vie) 222.07 714 T +(w of cde) 233.39 714 T +(vData oper) 266.63 714 T +(ations) 310.56 714 T +0 10 Q +1.55 (The last line abo) 162 527.48 P +1.55 (v) 239.89 527.48 P +1.55 (e demonstr) 244.64 527.48 P +1.55 (ates using oper) 296.11 527.48 P +1.55 (ator o) 367.49 527.48 P +1.55 (v) 394.47 527.48 P +1.55 (er) 399.22 527.48 P +1.55 (loading to e) 408.26 527.48 P +1.55 (xtr) 462.77 527.48 P +1.55 (act the \322v) 473.78 527.48 P +1.55 (alue\323) 517.77 527.48 P +1.2 (item from the data object; i.e) 162 515.48 P +1.2 (., the char) 294.01 515.48 P +1.2 (acter tag \322v) 340.78 515.48 P +1.2 (alue\323 is the def) 392.94 515.48 P +1.2 (ault tag to use in) 461.83 515.48 P +0.19 (e) 162 503.48 P +0.19 (xtr) 167.26 503.48 P +0.19 (acting a data item f) 178.27 503.48 P +0.19 (or the \322=\323 function o) 263.22 503.48 P +0.19 (v) 350.83 503.48 P +0.19 (er) 355.58 503.48 P +0.19 (load. This f) 364.61 503.48 P +0.19 (or) 413.61 503.48 P +0.19 (m is a) 422.75 503.48 P +0.19 (v) 449.6 503.48 P +0.19 (ailab) 454.35 503.48 P +0.19 (le f) 475.27 503.48 P +0.19 (or all scalar) 488.5 503.48 P +(types suppor) 162 491.48 T +(ted b) 219.65 491.48 T +(y cde) 241.69 491.48 T +(vData.) 265.29 491.48 T +1.2 (Most I/O oper) 162 474.48 P +1.2 (ations use the \322v) 224.87 474.48 P +1.2 (alue\323 tag to tr) 301.58 474.48 P +1.2 (ansmit a single v) 363.99 474.48 P +1.2 (alue \050scalar or arr) 441.79 474.48 P +1.2 (a) 523.63 474.48 P +1.2 (y\051.) 528.89 474.48 P +2.22 (Other commonly used tags are \322status\323 and \322time\323 \050a POSIX time str) 162 462.48 P +2.22 (uct\051. These) 487.76 462.48 P +-0.12 (tagged data items are optionally retur) 162 450.48 P +-0.12 (ned b) 326.71 450.48 P +-0.12 (y some ser) 351.41 450.48 P +-0.12 (v) 400.36 450.48 P +-0.12 (ers under the control of the I/O) 405.11 450.48 P +(conte) 162 438.48 T +(xt \050see belo) 186.16 438.48 T +(w f) 237.7 438.48 T +(or changing the def) 250.18 438.48 T +(ault conte) 335.49 438.48 T +(xt\051.) 378.55 438.48 T +1.93 (In this release) 162 421.48 P +1.93 (, cde) 227.95 421.48 P +1.93 (vData suppor) 251.26 421.48 P +1.93 (ts the f) 313.06 421.48 P +1.93 (ollo) 346.63 421.48 P +1.93 (wing data types:) 362.04 421.48 P +3 F +1.93 (unsigned char) 442.86 421.48 P +1.93 (, shor) 507.1 421.48 P +1.93 (t,) 534.44 421.48 P +0.45 (unsigned shor) 162 409.48 P +0.45 (t, int, unsigned int, long, unsigned long, \337oat, doub) 225.66 409.48 P +0.45 (le) 451.95 409.48 P +0 F +0.45 (,) 459.58 409.48 P +3 F +0.45 (char) 465.59 409.48 P +0.45 (acter str) 484.94 409.48 P +0.45 (ings) 521.66 409.48 P +0 F +(and) 162 397.48 T +3 F +(time stamp) 181.46 397.48 T +(.) 230.01 397.48 T +0 F +(All data types ma) 235.57 397.48 T +(y be either scalar or m) 311.97 397.48 T +(ulti-dimensional arr) 410.79 397.48 T +(a) 495.15 397.48 T +(ys) 500.41 397.48 T +(.) 510.26 397.48 T +162 81 540 720 C +162 558.14 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.52 558.14 542.48 711 R +7 X +0 0 0 1 0 0 0 K +V +166.55 561.71 542.27 703.86 R +0 X +V +0.5 H +2 Z +N +163.12 565.14 538.13 706.57 R +7 X +V +0 X +N +165.84 568.86 535.13 703.14 R +7 X +V +6 9 Q +0 X +(cdevData d1, d2;) 165.84 697.14 T +(int valtag;) 165.84 686.14 T +(float x, x2;) 165.84 675.14 T +(int status;) 165.84 664.14 T +(...) 165.84 653.14 T +(d1.tagC2I\050\322value\323,&valtag\051; // get the integer tag for \322value\323) 165.84 642.14 T +(...) 165.84 631.14 T +(d1.insert\050\322value\323,37.9\051; // insert using a character tag) 165.84 620.14 T +(device.send\050\322message\323,d1,d2\051; // send d1, get back d2) 165.84 609.14 T +(d2.get\050valtag,&x\051; // get \322value\323 from d2 into x) 165.84 598.14 T +(d2.get\050\322status\323,&status\051; // extract the \322status\323) 165.84 587.14 T +(x2 = d2; // get \322value\323 into x2 \050= overload\051) 165.84 576.14 T +162 81 540 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "4" 10 +%%Page: "5" 11 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 449.45 739 T +0 10 Q +(5) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(3.) 159.32 710.67 T +(Asyc) 180 710.67 T +(hr) 213.32 710.67 T +(onous Operations) 227.04 710.67 T +0 10 Q +1.79 (In addition to the synchronous send, there are 2 asynchronous f) 180 684.33 P +1.79 (or) 480 684.33 P +1.79 (ms f) 489.14 684.33 P +1.79 (or sending) 509.52 684.33 P +(messages) 180 672.33 T +(. The class de\336nition f) 225.42 672.33 T +(or all three f) 321.83 672.33 T +(or) 374.33 672.33 T +(ms is giv) 383.47 672.33 T +(en belo) 422.11 672.33 T +(w) 454.76 672.33 T +(.) 461.38 672.33 T +3 9 Q +(Figure 3: Three f) 180 639 T +(or) 248.76 639 T +(ms of the send command) 256.99 639 T +0 10 Q +1.17 (The second f) 180 506.76 P +1.17 (or) 239.86 506.76 P +1.17 (m, sendNoBloc) 249 506.76 P +1.17 (k, tak) 317.78 506.76 P +1.17 (es the same arguments as send b) 342.65 506.76 P +1.17 (ut completes) 500.13 506.76 P +1.21 (asynchronously) 180 494.76 P +1.21 (. That is) 248.47 494.76 P +1.21 (, the result will be in) 286.3 494.76 P +1.21 (v) 379.94 494.76 P +1.21 (alid until some synchronizing action is) 384.69 494.76 P +2.44 (tak) 180 482.76 P +2.44 (en \050discussed belo) 193.14 482.76 P +2.44 (w\051. The third f) 281.25 482.76 P +2.44 (or) 349.41 482.76 P +2.44 (m retur) 358.55 482.76 P +2.44 (ns the result to a callbac) 392.91 482.76 P +2.44 (k function) 512.76 482.76 P +0.66 (speci\336ed as par) 180 470.76 P +0.66 (t of the callbac) 251.76 470.76 P +0.66 (k argument. F) 318.03 470.76 P +0.66 (or each of these asychronous calls) 380.75 470.76 P +0.66 (, the) 537.88 470.76 P +0.19 (message ma) 180 458.76 P +0.19 (y be b) 237.13 458.76 P +0.19 (uff) 264.56 458.76 P +0.19 (ered b) 275.38 458.76 P +0.19 (y the under) 303.73 458.76 P +0.19 (lying ser) 354.3 458.76 P +0.19 (vice) 392.02 458.76 P +0.19 (, so that upon retur) 409.65 458.76 P +0.19 (n from the call) 494.62 458.76 P +-0.02 (there is no guar) 180 446.76 P +-0.02 (antee that the message has e) 249.32 446.76 P +-0.02 (v) 380.66 446.76 P +-0.02 (en been sent y) 385.41 446.76 P +-0.02 (et. T) 450.74 446.76 P +-0.02 (r) 469.53 446.76 P +-0.02 (ansmission ma) 472.76 446.76 P +-0.02 (y be) 539.12 446.76 P +2.28 (f) 180 434.76 P +2.28 (orced with a \337ush call using the cde) 182.48 434.76 P +2.28 (vSystem object descr) 355.97 434.76 P +2.28 (ibed belo) 455.71 434.76 P +2.28 (w) 498.42 434.76 P +2.28 (. A \337ush is) 505.04 434.76 P +(automatically perf) 180 422.76 T +(or) 258.06 422.76 T +(med if pend is called.) 267.2 422.76 T +2 F +(Callbac) 72 393.76 T +(k Object) 107.37 393.76 T +0 F +0.85 (The callbac) 180 393.76 P +0.85 (k object is a simple object containing 2 items: a function pointer) 231.78 393.76 P +0.85 (, and an) 520.17 393.76 P +1.21 (arbitr) 180 381.76 P +1.21 (ar) 202.68 381.76 P +1.21 (y user argument. As an e) 211.87 381.76 P +1.21 (xample) 329.33 381.76 P +1.21 (, the f) 361.41 381.76 P +1.21 (ollo) 388.55 381.76 P +1.21 (wing code fr) 403.96 381.76 P +1.21 (agment demonstr) 460.18 381.76 P +1.21 (ates) 539.1 381.76 P +1.85 (monitor) 180 369.76 P +1.85 (ing the magnet current asynchronously \050the third argument to the callbac) 213.49 369.76 P +1.85 (k) 553 369.76 P +(function is discussed later\051:) 180 357.76 T +3 9 Q +(Figure 4: Ov) 180 324.43 T +(er) 231.79 324.43 T +(vie) 240.07 324.43 T +(w of the cde) 251.39 324.43 T +(vCallbac) 299.65 324.43 T +(k object and the cde) 333.97 324.43 T +(vCallbac) 414.25 324.43 T +(kFunction) 448.58 324.43 T +180 419.43 558 691 C +180 537.43 558 636 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.63 537.43 560.37 636 R +7 X +0 0 0 1 0 0 0 K +V +184.44 541.71 560.15 628.86 R +0 X +V +0.5 H +2 Z +N +181.01 545.14 555.3 631.57 R +7 X +V +0 X +N +183.72 549.57 551.58 628.14 R +7 X +V +6 9 Q +0 X +(class cdevDevice:) 183.72 622.14 T +({) 183.72 611.14 T +(public:) 183.72 600.14 T +(int send \050char* msg, cdevData& out, cdevData& result\051;) 201.72 589.14 T +(int sendNoBlock \050char* msg, cdevData& out, cdevData& result\051;) 201.72 578.14 T +(int sendCallback \050char* msg, cdevData& out, cdevCallback cb\051;) 201.72 567.14 T +(};) 183.72 556.14 T +180 419.43 558 691 C +0 0 612 792 C +180 81 558 400.43 C +180 130 558 321.43 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.52 130 560.48 321.43 R +7 X +0 0 0 1 0 0 0 K +V +184.55 135.71 560.27 314.29 R +0 X +V +0.5 H +2 Z +N +181.12 139.14 555.41 317 R +7 X +V +0 X +N +183.84 142.14 551.7 313.57 R +7 X +V +6 9 Q +0 X +(// declare the callback func) 183.84 307.57 T +(cdevCallbackFunction gotit;) 183.84 296.57 T +(// create callback object) 183.84 274.57 T +(cdevCallback callbk\050gotit, myarg\051;) 183.84 263.57 T +(...) 183.84 252.57 T +(mag1.sendCallback\050\322monitorOn current\323,NULL,callbk\051;) 183.84 241.57 T +(...) 183.84 230.57 T +(void gotit\050int status, void* userarg, cdevRequestObject& reqobj,) 183.84 208.57 T +(cdevData& result\051) 237.84 197.57 T +({) 201.84 186.57 T +(float f = result;) 201.84 175.57 T +(printf\050\322new value is %f\134n\323,f\051;) 201.84 164.57 T +(}) 201.84 153.57 T +180 81 558 400.43 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "5" 11 +%%Page: "6" 12 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 54 739 T +0 10 Q +(6) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 10 Q +(The f) 162 713.33 T +(ollo) 184.49 713.33 T +(wing code de\336nes the callbac) 199.9 713.33 T +(k \050the cde) 330.32 713.33 T +(vRequestObject is descr) 373.93 713.33 T +(ibed belo) 482.45 713.33 T +(w\051:) 522.88 713.33 T +3 9 Q +(Figure 5: Str) 162 680 T +(ucture of the cde) 214.15 680 T +(vCallbac) 280.93 680 T +(k object) 315.25 680 T +2 10 Q +(System Object) 54 511.05 T +0 F +0.1 (W) 162 511.05 P +0.1 (aiting f) 171.04 511.05 P +0.1 (or completion of asychronous oper) 200.3 511.05 P +0.1 (ations ma) 354.02 511.05 P +0.1 (y be accomplished in one of tw) 397.18 511.05 P +0.1 (o) 534.44 511.05 P +1.36 (w) 162 499.05 P +1.36 (a) 169.07 499.05 P +1.36 (ys: \0501\051 using g) 174.33 499.05 P +1.36 (roups) 241.1 499.05 P +1.36 (, and \0502\051 using the system object. The system object k) 265.96 499.05 P +1.36 (eeps) 518.32 499.05 P +2.71 (tr) 162 487.05 P +2.71 (ac) 168.01 487.05 P +2.71 (k of all de) 178.37 487.05 P +2.71 (vices) 229 487.05 P +2.71 (, and contains methods f) 251.63 487.05 P +2.71 (or \337ushing, polling, and pending f) 371.11 487.05 P +2.71 (or) 531.11 487.05 P +(asychronous oper) 162 475.05 T +(ations) 241.38 475.05 T +(.) 267.91 475.05 T +3 9 Q +(Figure 6: Usage of the pend method in the cde) 162 441.71 T +(vSystem object) 349.84 441.71 T +0 10 Q +(The f) 162 313.76 T +(ollo) 184.49 313.76 T +(wing class interf) 199.9 313.76 T +(ace sho) 270.73 313.76 T +(ws the f) 305.6 313.76 T +(or) 339.76 313.76 T +(ms f) 348.9 313.76 T +(or each synchronization method:) 367.49 313.76 T +3 9 Q +(Figure 7: Synchronization methods in the cde) 162 280.43 T +(vSystem object) 344.82 280.43 T +3 10 Q +1.33 (\337ush) 162 135.33 P +0 F +1.33 (: Flush all pending output to the netw) 183.12 135.33 P +1.33 (or) 355.75 135.33 P +1.33 (k f) 364.79 135.33 P +1.33 (or those ser) 376.38 135.33 P +1.33 (vices that perf) 432.13 135.33 P +1.33 (or) 496.74 135.33 P +1.33 (m send) 505.88 135.33 P +(b) 162 123.33 T +(uff) 167.36 123.33 T +(er) 178.18 123.33 T +(ing.) 187.22 123.33 T +3 F +0.58 (poll:) 162 106.33 P +0 F +0.58 ( Flush all pending output, and process all receiv) 180.34 106.33 P +0.58 (ed replies \050including dispatching) 395.97 106.33 P +(callbac) 162 94.33 T +(ks) 192.92 94.33 T +(, if an) 202.77 94.33 T +(y\051. An) 227.08 94.33 T +(y receiv) 253.05 94.33 T +(ed monitor callbac) 287.25 94.33 T +(ks will be deliv) 368.19 94.33 T +(ered as w) 431.84 94.33 T +(ell.) 475.09 94.33 T +162 536.71 540 720 C +162 547.71 540 677 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.63 547.71 542.37 677 R +7 X +0 0 0 1 0 0 0 K +V +166.44 550.57 542.15 669.86 R +0 X +V +0.5 H +2 Z +N +163.01 554 537.3 672.57 R +7 X +V +0 X +N +165.72 557.71 533.58 669.14 R +7 X +V +6 9 Q +0 X +(typedef void \050*cdevCallbackFunction\051\050int status, void* userarg,) 165.72 663.14 T +( cdevRequestObject& reqobj,) 345.72 652.14 T +( cdevData& result\051;) 345.72 641.14 T +(class cdevCallback) 165.72 630.14 T +({) 165.72 619.14 T +(public:) 165.72 608.14 T +(cdevCallback \050cdevCallbackFunction func, void* userarg\051;) 183.72 597.14 T +(cdevCallbackFunction function;) 183.72 586.14 T +(void* userarg;) 183.72 575.14 T +(}) 165.72 564.14 T +162 536.71 540 720 C +0 0 612 792 C +162 81 540 517.71 C +162 344.43 540 438.71 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.52 344.43 542.48 438.71 R +7 X +0 0 0 1 0 0 0 K +V +166.55 347.28 542.27 431.57 R +0 X +V +0.5 H +2 Z +N +163.12 350.71 537.41 434.28 R +7 X +V +0 X +N +165.84 353.71 533.7 430.86 R +7 X +V +6 9 Q +0 X +(// get default system) 165.84 424.86 T +(cdevSystem& sys = cdevSystem::defaultSystem\050\051;) 165.84 413.86 T +(...) 165.84 402.86 T +(mag1.sendNoBlock\050\322on\323,...\051; // async op\050s\051) 165.84 391.86 T +(mag2.sendNoBlock\050\322on\323,...\051; // async op\050s\051) 165.84 380.86 T +(...) 165.84 369.86 T +(sys.pend\050\051; // wait for all I/O to complete) 165.84 358.86 T +162 81 540 517.71 C +0 0 612 792 C +162 81 540 517.71 C +162 166 540 277.43 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.63 166 542.37 277.43 R +7 X +0 0 0 1 0 0 0 K +V +166.44 168.14 542.15 270.28 R +0 X +V +0.5 H +2 Z +N +163.01 171.57 537.3 273 R +7 X +V +0 X +N +165.72 174.57 533.58 269.57 R +7 X +V +6 9 Q +0 X +(class cdevSystem) 165.72 263.57 T +({) 165.72 252.57 T +(public:) 165.72 241.57 T +(int) 183.72 230.57 T +(flush\050\051;) 205.32 230.57 T +(int) 183.72 219.57 T +(poll\050\051;) 205.32 219.57 T +(int) 183.72 208.57 T +(pend\050\051;) 205.32 208.57 T +(}) 165.72 197.57 T +162 81 540 517.71 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "6" 12 +%%Page: "7" 13 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 449.45 739 T +0 10 Q +(7) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +3 F +1.4 (pend) 180 713.33 P +0 F +1.4 (: Flush all pending output, and process all replies f) 202.24 713.33 P +1.4 (or the speci\336ed n) 436.88 713.33 P +1.4 (umber of) 517.14 713.33 P +0.18 (seconds) 180 701.33 P +0.18 (. If the time argument is omitted, w) 217.09 701.33 P +0.18 (ait until all replies ha) 371.05 701.33 P +0.18 (v) 462.16 701.33 P +0.18 (e been receiv) 466.91 701.33 P +0.18 (ed. If a) 527.06 701.33 P +(monitor oper) 180 689.33 T +(ation w) 236.03 689.33 T +(as star) 267.56 689.33 T +(ted, this w) 297.97 689.33 T +(aits f) 342.84 689.33 T +(or the connection \050\336rst callbac) 363.66 689.33 T +(k\051 only) 496.29 689.33 T +(.) 524.74 689.33 T +2 F +(Gr) 72 660.33 T +(oup Object) 83.47 660.33 T +0 F +2.11 (An alter) 180 660.33 P +2.11 (nativ) 216.82 660.33 P +2.11 (e mechanism f) 237.69 660.33 P +2.11 (or w) 306.62 660.33 P +2.11 (aiting f) 327.46 660.33 P +2.11 (or asychronous calls is through the use of) 358.73 660.33 P +0.79 (g) 180 648.33 P +0.79 (roups) 185.46 648.33 P +0.79 (. A g) 210.32 648.33 P +0.79 (roup k) 232.37 648.33 P +0.79 (eeps tr) 260.74 648.33 P +0.79 (ac) 292 648.33 P +0.79 (k off all I/O oper) 302.36 648.33 P +0.79 (ations star) 376 648.33 P +0.79 (ted from the time the g) 423.32 648.33 P +0.79 (roup is) 527.2 648.33 P +0.89 (star) 180 636.33 P +0.89 (ted until the g) 197.07 636.33 P +0.89 (roup is ended. Groups ma) 259.67 636.33 P +0.89 (y be nested or o) 378.53 636.33 P +0.89 (v) 453.64 636.33 P +0.89 (er) 458.39 636.33 P +0.89 (lapped, and suppor) 467.43 636.33 P +0.89 (t) 555.22 636.33 P +(the same \337ush/poll/pend oper) 180 624.33 T +(ations as the system object. F) 311.08 624.33 T +(or e) 443.06 624.33 T +(xample:) 459.99 624.33 T +3 9 Q +(Figure 8: Sample usage of the cde) 180 591 T +(vGroup object) 319.81 591 T +3 10 Q +0.06 (Note: Allo) 180 311.33 P +0.06 (wing nested or o) 223.26 311.33 P +0.06 (v) 296.66 311.33 P +0.06 (er) 301.41 311.33 P +0.06 (lapped g) 310.45 311.33 P +0.06 (roups allo) 348.77 311.33 P +0.06 (ws libr) 392.03 311.33 P +0.06 (ar) 420.32 311.33 P +0.06 (y calls to star) 429.51 311.33 P +0.06 (t or stop g) 488.44 311.33 P +0.06 (roups) 532.99 311.33 P +(without needing to kno) 180 299.33 T +(w if another g) 279.91 299.33 T +(roup is already activ) 339.84 299.33 T +(e) 428.51 299.33 T +(.) 433.92 299.33 T +0 F +1.84 (Groups ma) 180 282.33 P +1.84 (y be oper) 231 282.33 P +1.84 (ated in one of tw) 276.28 282.33 P +1.84 (o modes) 356.93 282.33 P +1.84 (. Immediate mode \050def) 396.98 282.33 P +1.84 (ault\051 causes) 502.25 282.33 P +2.84 (g) 180 270.33 P +2.84 (rouped oper) 185.46 270.33 P +2.84 (ations to be immediately e) 242.12 270.33 P +2.84 (x) 369.32 270.33 P +2.84 (ecuted, and the g) 374.02 270.33 P +2.84 (roup is just used f) 459.7 270.33 P +2.84 (or) 549.11 270.33 P +1.11 (completion synchronization. Def) 180 258.33 P +1.11 (erred mode causes messages to be held bac) 323.64 258.33 P +1.11 (k until) 530.77 258.33 P +0.12 (the g) 180 246.33 P +0.12 (roup is ended and the oper) 202.26 246.33 P +0.12 (ations are \337ushed. After the oper) 322.28 246.33 P +0.12 (ations are complete) 467.87 246.33 P +0.12 (,) 555.22 246.33 P +0.48 (he g) 180 234.33 P +0.48 (roup of oper) 199.84 234.33 P +0.48 (ations ma) 254.63 234.33 P +0.48 (y be \337ushed again \050without re-posting\051, allo) 298.16 234.33 P +0.48 (wing the g) 491.55 234.33 P +0.48 (roup) 537.99 234.33 P +(to function as a list manager/e) 180 222.33 T +(x) 313.1 222.33 T +(ecutor) 317.8 222.33 T +(.) 345.09 222.33 T +2 F +(Request Object) 72 193.33 T +0 F +0.47 (Occasionally) 180 193.33 P +0.47 (, an I/O oper) 235.68 193.33 P +0.47 (ation ma) 292.58 193.33 P +0.47 (y need to be repeated ma) 331.1 193.33 P +0.47 (y times) 447.11 193.33 P +0.47 (. In this case) 479.1 193.33 P +0.47 (, it is) 536.5 193.33 P +0.88 (not ef\336cient to parse the message each time to deter) 180 181.33 P +0.88 (mine which ser) 421.09 181.33 P +0.88 (v) 489.84 181.33 P +0.88 (er to use) 494.59 181.33 P +0.88 (. It is) 535.11 181.33 P +0.06 (possib) 180 169.33 P +0.06 (le to b) 208.7 169.33 P +0.06 (ypass this parsing b) 235.86 169.33 P +0.06 (y creating a request object. The request object is lik) 324.21 169.33 P +0.06 (e) 552.44 169.33 P +-0.03 (the de) 180 157.33 P +-0.03 (vice object, e) 207.47 157.33 P +-0.03 (xcept that the message str) 265.46 157.33 P +-0.03 (ing is speci\336ed at creation time) 382.75 157.33 P +-0.03 (, and the) 519.15 157.33 P +0.98 (request object is theref) 180 145.33 P +0.98 (ore speci\336c to the par) 283.8 145.33 P +0.98 (ticular under) 383.71 145.33 P +0.98 (lying ser) 439.86 145.33 P +0.98 (vice to which that) 478.36 145.33 P +(message m) 180 133.33 T +(ust be directed.) 231.58 133.33 T +1.29 (In the case of EPICS channel access) 180 116.33 P +1.29 (, the request object opens and maintains the) 352.15 116.33 P +1.02 (channel to the EPICS process v) 180 104.33 P +1.02 (ar) 326.02 104.33 P +1.02 (iab) 335.05 104.33 P +1.02 (le) 348.2 104.33 P +1.02 (. The request object is NO) 355.83 104.33 P +1.02 (T the same as an) 476.67 104.33 P +1.34 (EPICS channel, in that the request object binds a de) 180 92.33 P +1.34 (vice and a message) 423.59 92.33 P +1.34 (, and the) 516.39 92.33 P +180 219 558 667 C +180 342 558 588 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.52 342 560.48 588 R +7 X +0 0 0 1 0 0 0 K +V +184.55 345 560.27 580.86 R +0 X +V +0.5 H +2 Z +N +181.12 347.86 555.41 583.57 R +7 X +V +0 X +N +183.84 350.85 551.7 580.14 R +7 X +V +6 9 Q +0 X +(cdevGroup g1, g2;) 183.84 574.14 T +(...) 183.84 563.14 T +(g1.start\050\051;) 183.84 552.14 T +(mag1.sendCallback\050...\051;) 183.84 541.14 T +(mag2.sendCallback\050...\051;) 183.84 530.14 T +(g2.start\050\051;) 183.84 519.14 T +(bpm1.sendNoBlock\050...\051;) 183.84 508.14 T +(bpm2.sendNoBlock\050...\051;) 183.84 497.14 T +(g1.end\050\051;) 183.84 486.14 T +(mag3.sendCallback\050...\051;) 183.84 475.14 T +(bpm3.sendNoBlock\050...\051;) 183.84 464.14 T +(g2.end\050\051;) 183.84 453.14 T +(g1.pend\0504.0\051;) 183.84 442.14 T +(// at this point operations on mag1, mag2, bpm1, & bpm2 are done) 183.84 431.14 T +(// or have timed out \050error handling discussed later\051.) 183.84 420.14 T +(...) 183.84 409.14 T +(// mag3 and bpm3 may not be finished yet, pend on the second) 183.84 398.14 T +(// group to wait for their completion) 183.84 387.14 T +(g2.pend\050\051;) 183.84 376.14 T +180 219 558 667 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "7" 13 +%%Page: "8" 14 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 54 739 T +0 10 Q +(8) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 10 Q +1.04 (message implies a direction. If the message is considered to be of the f) 162 713.33 P +1.04 (or) 489.84 713.33 P +1.04 (m) 498.98 713.33 P +3 F +1.04 (v) 511.14 713.33 P +1.04 (erb) 515.89 713.33 P +0 F +1.04 ( +) 530.34 713.33 P +3 F +-0.16 (attr) 162 701.33 P +-0.16 (ib) 176.6 701.33 P +-0.16 (ute) 184.18 701.33 P +0 F +-0.16 (then the EPICS channel essentially binds de) 200.7 701.33 P +-0.16 (vice and attr) 396.21 701.33 P +-0.16 (ib) 450.52 701.33 P +-0.16 (ute b) 458.1 701.33 P +-0.16 (ut not v) 479.98 701.33 P +-0.16 (erb) 512.21 701.33 P +-0.16 (. In) 526.26 701.33 P +0.04 (some future release of CDEV) 162 689.33 P +0.04 (, a more channel lik) 290.98 689.33 P +0.04 (e object ma) 377.65 689.33 P +0.04 (y be included if there is a) 429.13 689.33 P +0.37 (demand f) 162 677.33 P +0.37 (or it. If tw) 203.76 677.33 P +0.37 (o cde) 245.32 677.33 P +0.37 (vRequestObjects ref) 269.85 677.33 P +0.37 (erence the same EPICS channel, only a) 360.5 677.33 P +(single channel access connection is estab) 162 665.33 T +(lished.) 348 665.33 T +1.56 (The f) 162 648.33 P +1.56 (ollo) 186.05 648.33 P +1.56 (wing code demonstr) 201.46 648.33 P +1.56 (ates sending a set of data v) 293.96 648.33 P +1.56 (alues to a single magnet) 425.37 648.33 P +(using a request object. Note that the send call omits the message argument:) 162 636.33 T +3 9 Q +(Figure 9: Sample usage of the cde) 162 620 T +(vRequestObject object) 301.81 620 T +0 10 Q +0.2 (In most cases) 162 457.05 P +0.2 (, the de) 223.94 457.05 P +0.2 (vice object will create the request object to perf) 257.39 457.05 P +0.2 (or) 466.54 457.05 P +0.2 (m a requested) 475.68 457.05 P +0.59 (I/O oper) 162 445.05 P +0.59 (ation. All 3 f) 198.62 445.05 P +0.59 (or) 252.35 445.05 P +0.59 (ms of send are suppor) 261.49 445.05 P +0.59 (ted b) 363.75 445.05 P +0.59 (y the request object, with a calling) 386.38 445.05 P +-0.25 (syntax identical to the de) 162 433.05 P +-0.25 (vice calls without the message argument. The interf) 270.76 433.05 P +-0.25 (ace to the) 496.58 433.05 P +(request object is giv) 162 421.05 T +(en belo) 250.12 421.05 T +(w:) 282.77 421.05 T +3 9 Q +(Figure 10: Str) 162 387.71 T +(ucture of the cde) 219.16 387.71 T +(vRequestObject object) 285.93 387.71 T +0 10 Q +0.13 (When an asynchronous oper) 162 214.05 P +0.13 (ation completes) 290.12 214.05 P +0.13 (, the rele) 360.12 214.05 P +0.13 (v) 398.99 214.05 P +0.13 (ant request object is passed to) 403.74 214.05 P +1.47 (the user\325) 162 202.05 P +1.47 (s callbac) 201.32 202.05 P +1.47 (k routine) 241.49 202.05 P +1.47 (. This allo) 281.16 202.05 P +1.47 (ws the user to e) 326.74 202.05 P +1.47 (xtr) 402.9 202.05 P +1.47 (act the message str) 413.91 202.05 P +1.47 (ing and) 505.73 202.05 P +(de) 162 190.05 T +(vice name from the request object if necessar) 172.82 190.05 T +(y or desired.) 374.87 190.05 T +2 F +(File Descriptor) 54 161.05 T +(s) 123.87 161.05 T +(and \322select\323) 54 149.05 T +0 F +0.4 (An alter) 162 161.05 P +0.4 (nativ) 197.11 161.05 P +0.4 (e mechanism f) 217.98 161.05 P +0.4 (or dealing with asynchronous oper) 283.49 161.05 P +0.4 (ations is to directly test) 437.26 161.05 P +3.76 (the \336le descr) 162 149.05 P +3.76 (iptors being used. This interf) 226.36 149.05 P +3.76 (ace is currently implemented in the) 366.7 149.05 P +(cde) 162 137.05 T +(vSystem class) 177.82 137.05 T +(. The per) 241.57 137.05 T +(tinent methods ha) 281.99 137.05 T +(v) 361.28 137.05 T +(e the f) 366.03 137.05 T +(ollo) 393.53 137.05 T +(wing f) 408.94 137.05 T +(or) 434.76 137.05 T +(m:) 443.9 137.05 T +162 186.71 540 720 C +162 487.71 540 617 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.72 487.71 542.28 617 R +7 X +0 0 0 1 0 0 0 K +V +166.35 490.57 542.07 609.86 R +0 X +V +0.5 H +2 Z +N +162.92 494.71 537.21 612.57 R +7 X +V +0 X +N +165.64 497.71 533.49 609.14 R +7 X +V +6 9 Q +0 X +(cdevRequestObject& mag1BDL =) 165.64 603.14 T +(cdevRequestObject::attachRef\050\322mag1\323,\323set BDL\323\051;) 183.64 592.14 T +(cdevData mydata;) 165.64 581.14 T +(...) 165.64 570.14 T +(for \050i=0;i<100;i++\051) 165.64 559.14 T +({) 183.64 548.14 T +(mydata = i*10; // 10 amp steps) 183.64 537.14 T +(mag1BDL.send\050mydata,NULL\051; // ignore errors for now) 183.64 526.14 T +(sleep\0501\051;) 183.64 515.14 T +(}) 183.64 504.14 T +162 186.71 540 720 C +0 0 612 792 C +162 186.71 540 720 C +162 244.71 540 384.71 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.63 244.71 542.37 384.71 R +7 X +0 0 0 1 0 0 0 K +V +166.44 247.57 542.15 377.57 R +0 X +V +0.5 H +2 Z +N +163.01 251 537.3 380.29 R +7 X +V +0 X +N +165.72 254 533.58 376.86 R +7 X +V +6 9 Q +0 X +(class cdevRequestObject) 165.72 370.86 T +({) 165.72 359.86 T +(public:) 165.72 348.86 T +(char* message\050\051; // returns the message string) 183.72 337.86 T +(cdevDevice& device\050\051; // returns the device object) 183.72 326.86 T +(int state\050\051; // connected/disconnected/) 183.72 315.86 T +(int access\050\051; // read/write/none) 183.72 304.86 T +(int send\050cdevData& out, cdevData& result\051;) 183.72 293.86 T +(int sendNoBlock\050cdevData& out, cdevData& result\051;) 183.72 282.86 T +(int sendCallback\050cdevData& out, cdevCallback callback\051;) 183.72 271.86 T +(}) 165.72 260.86 T +162 186.71 540 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "8" 14 +%%Page: "9" 15 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 449.45 739 T +0 10 Q +(9) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +3 9 Q +(Figure 11: File descr) 180 714 T +(iptor routines of the cde) 264.66 714 T +(vSystem object) 358.44 714 T +0 10 Q +1.42 (The getFd method will populate a user allocated arr) 180 559.58 P +1.42 (a) 419.16 559.58 P +1.42 (y of integers \050fd\051 with the \336le) 424.42 559.58 P +0.36 (descr) 180 547.58 P +0.36 (iptors currently in use b) 204.6 547.58 P +0.36 (y the cde) 309.19 547.58 P +0.36 (vSystem object. The n) 350.18 547.58 P +0.36 (umber of \336le descr) 450.08 547.58 P +0.36 (iptors) 533.55 547.58 P +0.5 (that w) 180 535.58 P +0.5 (ere allocated b) 207.08 535.58 P +0.5 (y the user is speci\336ed in the n) 273.46 535.58 P +0.5 (umFD v) 408.58 535.58 P +0.5 (ar) 443.82 535.58 P +0.5 (iab) 452.86 535.58 P +0.5 (le) 466 535.58 P +0.5 (. Upon completion,) 473.63 535.58 P +-0.19 (the n) 180 523.58 P +-0.19 (umFD v) 201.95 523.58 P +-0.19 (ar) 236.5 523.58 P +-0.19 (iab) 245.54 523.58 P +-0.19 (le will be set to the n) 258.68 523.58 P +-0.19 (umber of \336le descr) 348.01 523.58 P +-0.19 (iptors actually copied into the) 429.83 523.58 P +0.52 (fd arr) 180 511.58 P +0.52 (a) 203.76 511.58 P +0.52 (y) 209.02 511.58 P +0.52 (. An error is retur) 213.02 511.58 P +0.52 (ned if the b) 290.39 511.58 P +0.52 (uff) 341.25 511.58 P +0.52 (er is not suf\336cient to store the complete set of) 352.07 511.58 P +(\336le descr) 180 499.58 T +(iptors) 220.16 499.58 T +(.) 244.46 499.58 T +0.03 (The addFdChangedCallbac) 180 482.58 P +0.03 (k method allo) 302.11 482.58 P +0.03 (ws the user to specify a function to be called) 361.5 482.58 P +(each time a \336le descr) 180 470.58 T +(iptor is added \050opened=1\051 or closed \050opened=0\051.) 274.63 470.58 T +(The f) 180 453.58 T +(ollo) 202.49 453.58 T +(wing code illustr) 217.9 453.58 T +(ates the usage of the UNIX select call:) 288.93 453.58 T +180 81 558 720 C +180 573.25 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.52 573.25 560.48 711 R +7 X +0 0 0 1 0 0 0 K +V +183.3 584.54 559.02 705.11 R +0 X +V +0.5 H +2 Z +N +181.75 588.29 556.04 707.82 R +7 X +V +0 X +N +183.84 596.53 551.7 703.14 R +7 X +V +6 9 Q +0 X +(typedef void \050*cdevFdChangedCallback\051\050int fd, int opened,) 183.84 697.14 T +( void* userarg\051) 255.84 686.14 T +(class cdevSystem) 183.84 675.14 T +({) 183.84 664.14 T +(public:) 183.84 653.14 T +(...) 201.84 642.14 T +(int getFd\050int fd[], int &numFD\051;) 201.84 631.14 T +(int addFdChangedCallback\050cdevFdChangedCallback cbk, void* arg\051;) 201.84 620.14 T +(}) 183.84 609.14 T +180 81 558 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "9" 15 +%%Page: "10" 16 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 54 739 T +0 10 Q +(10) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +3 F +(Figure 12: Using CDEV \336le descr) 162 714 T +(iptors with the UNIX select function) 296.68 714 T +162 81 540 720 C +162 213.85 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.57 213.85 542.43 711 R +7 X +0 0 0 1 0 0 0 K +V +166.5 216.71 542.22 703.86 R +0 X +V +0.5 H +2 Z +N +163.07 220.14 537.36 706.57 R +7 X +V +0 X +N +165.79 223.14 533.65 703.14 R +7 X +V +6 9 Q +0 X +(int myFD[5];) 165.79 697.14 T +(void mySelectLoop \050 cdevSystem & system \051) 165.79 675.14 T +({) 183.79 664.14 T +(int fd[20];) 183.79 653.14 T +(int numFD = 15, nfds;) 183.79 642.14 T +(fd_set rfds; // Ready file descriptors) 183.79 631.14 T +(fd_set afds; // Active file descriptors) 183.79 620.14 T +(// Copy the file descriptors I am already using to the list) 183.79 598.14 T +(memcpy\050fd, myFD, sizeof\050myFD\051\051;) 183.79 587.14 T +(// Get the file descriptors in use by the cdevSystem object) 183.79 565.14 T +(system.getFd\050&fd[5], numFD\051;) 183.79 554.14 T +(// Add in the 5 previously defined file descriptors) 183.79 532.14 T +(numFD += 5;) 183.79 521.14 T +(// Zero the active file descriptors) 183.79 499.14 T +(FD_ZERO\050&afds\051;) 183.79 488.14 T +(// Setup the active file descriptors) 183.79 466.14 T +(for\050int i=0; i\323 into which the de) 242.31 244.91 T +(vice name will be substituted.) 354.29 244.91 T +-0.15 (Example: Suppose there are a set of magnets f) 180 227.91 P +-0.15 (or which it is possib) 387.51 227.91 P +-0.15 (le to read and wr) 473.4 227.91 P +-0.15 (ite) 547.44 227.91 P +0.46 (bdl \050integ) 180 215.91 P +0.46 (r) 221.49 215.91 P +0.46 (al \336eld\051, and current \050amps\051. That is) 224.72 215.91 P +0.46 (, the messages \322get bdl\323, \322get current\323,) 385.17 215.91 P +0.32 (\322set bdl\323, etc. are v) 180 203.91 P +0.32 (alid. Also) 263.86 203.91 P +0.32 (, each magnet responds to the commands \322on\323 and \322off) 304.36 203.91 P +0.32 (\323.) 551.89 203.91 P +-0.22 (Fur) 180 191.91 P +-0.22 (ther suppose that the beamline position and length of the magnet are a) 195.4 191.91 P +-0.22 (v) 506.09 191.91 P +-0.22 (ailab) 510.84 191.91 P +-0.22 (le in a) 531.76 191.91 P +(static database \050assume read/wr) 180 179.91 T +(ite\051.) 324.65 179.91 T +180 557.57 558 720 C +180 603.57 558 665 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +178.64 603.57 559.36 665 R +7 X +0 0 0 1 0 0 0 K +V +183.43 606.43 559.15 657.86 R +0 X +V +0.5 H +2 Z +N +180 609.86 554.29 660.57 R +7 X +V +0 X +N +182.71 613.57 550.57 657.14 R +7 X +V +6 9 Q +0 X +(service ca) 182.71 651.14 T +({) 200.71 640.14 T +(tags {pv, default}) 200.71 629.14 T +(}) 200.71 618.14 T +180 557.57 558 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "15" 21 +%%Page: "16" 22 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Name Resolution) 54 739 T +0 10 Q +(16) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 10 Q +(Here is a complete class de\336nition:) 162 713.33 T +3 9 Q +(Figure 21: Sample inher) 162 680 T +(ited class de\336nition) 260.68 680 T +0 10 Q +0.68 (Note the semicolon at the end of each line of attr) 162 406.33 P +0.68 (ib) 384.02 406.33 P +0.68 (utes or messages \050e) 391.6 406.33 P +0.68 (xcept f) 483.92 406.33 P +0.68 (or the) 513.75 406.33 P +0.36 (last line\051. Note also that the process v) 162 394.33 P +0.36 (ar) 330.99 394.33 P +0.36 (iab) 340.03 394.33 P +0.36 (le name has a place holder into which the) 353.17 394.33 P +0.17 (de) 162 382.33 P +0.17 (vice name will be substituted. More sophisticated name mangling is en) 172.82 382.33 P +0.17 (visaged, b) 486.11 382.33 P +0.17 (ut) 531.66 382.33 P +(not f) 162 370.33 T +(or this release) 181.16 370.33 T +(. Syntax is still open to re) 243.81 370.33 T +(vision.) 354.67 370.33 T +2 F +(Instance De\336nition) 54 341.33 T +0 F +1.8 (Instances of a class are giv) 162 341.33 P +1.8 (en b) 291.39 341.33 P +1.8 (y f) 312.45 341.33 P +1.8 (ollo) 324.52 341.33 P +1.8 (wing the class name with a list of instance) 339.93 341.33 P +4.03 (names) 162 329.33 P +4.03 (. De) 191.86 329.33 P +4.03 (vice names ma) 213.93 329.33 P +4.03 (y be separ) 288.92 329.33 P +4.03 (ated b) 343.56 329.33 P +4.03 (y whitespace char) 375.19 329.33 P +4.03 (acters \050including) 463.17 329.33 P +(ne) 162 317.33 T +(wline\051 or b) 172.92 317.33 T +(y commas) 218.84 317.33 T +(.) 264.25 317.33 T +3 9 Q +(Figure 22: Multiple instances of the magnet class) 162 284 T +0 10 Q +1.2 (Combined with the pre) 162 223.19 P +1.2 (vious de\336nition, the message \322on\323 sent to magnet m2 w) 265.33 223.19 P +1.2 (ould) 521.1 223.19 P +(select the process v) 162 211.19 T +(ar) 250.12 211.19 T +(iab) 259.16 211.19 T +(le \322m2CSR.v) 272.3 211.19 T +(al\323 with \3221\323 as the v) 328.72 211.19 T +(alue to wr) 412.94 211.19 T +(ite) 456.44 211.19 T +(.) 466.85 211.19 T +2 F +(Aliases) 54 182.19 T +0 F +1.39 (Sometimes it is con) 162 182.19 P +1.39 (v) 252.67 182.19 P +1.39 (enient to ref) 257.42 182.19 P +1.39 (er to a de) 312.72 182.19 P +1.39 (vice b) 358.85 182.19 P +1.39 (y more than one name) 386.17 182.19 P +1.39 (. The DDL) 491.64 182.19 P +(syntax suppor) 162 170.19 T +(ts simple aliases) 224.65 170.19 T +(, one per line) 297.85 170.19 T +(.) 355.51 170.19 T +3 9 Q +(Figure 23: Alias de) 162 136.86 T +(vice name) 239.26 136.86 T +162 367 540 720 C +162 437 540 677 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.93 437 542.07 677 R +7 X +0 0 0 1 0 0 0 K +V +166.14 439.85 541.86 669.86 R +0 X +V +0.5 H +2 Z +N +162.71 444 537 672.57 R +7 X +V +0 X +N +165.43 447.71 533.29 669.14 R +7 X +V +6 9 Q +0 X +(class stdio) 165.43 663.14 T +({) 183.43 652.14 T +(verbs {get, set, monitorOn, monitorOff}) 183.43 641.14 T +(}) 183.43 630.14 T +(class magnet : stdio) 165.43 608.14 T +({) 183.43 597.14 T +(attributes) 183.43 586.14 T +({) 201.43 575.14 T +(bdl) 201.43 564.14 T +(ca {pv=<>.bdl};) 223.03 564.14 T +(current ca {pv=<>.val};) 201.43 553.14 T +(zpos) 201.43 542.14 T +( os {path=<>/phy/z};) 223.03 542.14 T +(length) 201.43 531.14 T +( os {path=<>/phy/len}) 233.83 531.14 T +(}) 201.43 520.14 T +(messages) 183.43 509.14 T +({) 201.43 498.14 T +(on) 201.43 487.14 T +(ca {pv=<>CSR.val, default=1};) 219.43 487.14 T +(off) 201.43 476.14 T +(ca {pv=<>CSR.val, default=0};) 224.83 476.14 T +(}) 201.43 465.14 T +(}) 183.43 454.14 T +162 367 540 720 C +0 0 612 792 C +162 207.86 540 348 C +162 253.86 540 281 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +160.29 253.86 541.71 281 R +7 X +0 0 0 1 0 0 0 K +V +165.79 256 541.5 273.85 R +0 X +V +0.5 H +2 Z +N +162.36 259.43 536.65 276.57 R +7 X +V +0 X +N +165.07 263.14 532.93 273.14 R +7 X +V +6 9 Q +0 X +(magnet : m1 m2 m3;) 165.07 267.14 T +162 207.86 540 348 C +0 0 612 792 C +162 81 540 188.86 C +162 106.71 540 133.86 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +160.29 106.71 541.71 133.86 R +7 X +0 0 0 1 0 0 0 K +V +165.79 108.86 541.5 126.71 R +0 X +V +0.5 H +2 Z +N +162.36 112.28 536.65 129.43 R +7 X +V +0 X +N +165.07 116 532.93 126 R +7 X +V +6 9 Q +0 X +(alias myname m1) 165.07 120 T +162 81 540 188.86 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "16" 22 +%%Page: "17" 23 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Name Resolution) 478.97 739 T +0 10 Q +(17) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "17" 23 +%%Page: "18" 24 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Channel Access Service) 54 739 T +0 10 Q +(18) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(6.) 141.32 710.67 T +(Channel Access Ser) 162 710.67 T +(vice) 296.75 710.67 T +0 10 Q +(EPICS / Channel Access v) 162 684.33 T +(ersion 3.12 is recommended.) 280.13 684.33 T +(F) 162 667.33 T +(eatures:) 167.81 667.33 T +(\245) 180 650.33 T +(Suppor) 189 650.33 T +(ts synchronous and asynchronous send\325) 221.64 650.33 T +(s) 399.56 650.33 T +(.) 404.41 650.33 T +(\245) 180 636.33 T +(T) 189 636.33 T +(r) 193.91 636.33 T +(ac) 197.14 636.33 T +(ks \336le descr) 207.5 636.33 T +(iptor registr) 260.44 636.33 T +(ation.) 310.35 636.33 T +(\245) 180 622.33 T +(F) 189 622.33 T +(etches data in nativ) 194.81 622.33 T +(e type \050type con) 280.72 622.33 T +(v) 351.67 622.33 T +(ersion done on client and not ser) 356.42 622.33 T +(v) 501.8 622.33 T +(er\051.) 506.55 622.33 T +(\245) 180 608.33 T +1.96 (Pro) 189 608.33 P +1.96 (vides a def) 204.41 608.33 P +1.96 (ault name ser) 256.38 608.33 P +1.96 (vice so that if a de) 321.18 608.33 P +1.96 (vice is not de\336ned, then an) 411.26 608.33 P +0.13 (EPICS channel access connection is attempted with the record name set equal) 189 596.33 P +(to the de) 189 584.33 T +(vice name) 227.62 584.33 T +(, and the \336eld name set equal to the attr) 273.04 584.33 T +(ib) 449.41 584.33 T +(ute name) 456.99 584.33 T +(.) 498.53 584.33 T +(Restr) 162 567.33 T +(ictions:) 186.04 567.33 T +(\245) 180 550.33 T +2.52 (Only suppor) 189 550.33 P +2.52 (ts set/get/monitorOn/monitorOff v) 245.83 550.33 P +2.52 (erbs and the pv and readonly) 397.89 550.33 P +-0.27 (tags) 189 538.33 P +-0.27 (. Suppor) 207.75 538.33 P +-0.27 (t f) 245.68 538.33 P +-0.27 (or arbitr) 253.44 538.33 P +-0.27 (ar) 287.52 538.33 P +-0.27 (y messages with def) 296.71 538.33 P +-0.27 (ault data will be in the ne) 386.18 538.33 P +-0.27 (xt release) 494.29 538.33 P +-0.27 (.) 537.22 538.33 P +(\245) 180 524.33 T +(Discards all e) 189 524.33 T +(xception callbac) 248.71 524.33 T +(ks from channel access in this v) 319.65 524.33 T +(ersion.) 460.56 524.33 T +(\245) 180 510.33 T +(Channel access secur) 189 510.33 T +(ity is not suppor) 287.52 510.33 T +(ted in this release) 357.95 510.33 T +(.) 436.17 510.33 T +(Compilation options:) 162 493.33 T +(\245) 180 476.33 T +3.21 (_CA_SYNC_CONN = perf) 189 476.33 P +3.21 (or) 311.54 476.33 P +3.21 (m connections synchronously) 320.68 476.33 P +3.21 (, w) 457.27 476.33 P +3.21 (aiting up to 4) 473.11 476.33 P +(seconds) 189 464.33 T +(.) 226.09 464.33 T +(\245) 180 450.33 T +(_CDEV_DEB) 189 450.33 T +(UG = pr) 248.36 450.33 T +(int v) 283.8 450.33 T +(erbose messages) 301.89 450.33 T +(\245) 180 436.33 T +(_EPICS_3_12 = if not de\336ned, use 3.11 calls instead.) 189 436.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "18" 24 +%%Page: "i" 25 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(i) 555.78 57 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 720 558 720 2 L +0.5 H +2 Z +N +72 72 558 72 2 L +N +72 504 558 504 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 32 Q +(Introduction to CDEV) 180 662.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 12 Q +(Over) 180 638 T +(vie) 207.47 638 T +(w of the Contr) 223.97 638 T +(ol De) 304.39 638 T +(vice Interface) 333.55 638 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(Chip W) 180 610 T +(atson, Jie Chen, Danjin W) 218.86 610 T +(u, W) 357.22 610 T +(alt Ak) 381.41 610 T +(ers) 411.18 610 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 180 582 T +(ersion 1.5 December 9, 1996) 187.04 582 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(TJNAF - Thomas Jeff) 180 554 T +(erson National Acceler) 293.66 554 T +(ator F) 414.25 554 T +(acility) 445 554 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "i" 25 +%%Page: "ii" 26 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(ii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(TRADEMARKS:) 54 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(UNIX is a registered tr) 180 569.33 T +(ademar) 278.26 569.33 T +(k of A) 312.31 569.33 T +(T&T in the USA and other countr) 336.68 569.33 T +(ies) 481.9 569.33 T +(.) 494.53 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(VxW) 180 545.33 T +(or) 200.81 545.33 T +(ks is a register tr) 209.85 545.33 T +(ademar) 283.1 545.33 T +(k of Wind Riv) 317.15 545.33 T +(er Systems) 375.8 545.33 T +(.) 425.66 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The X Windo) 180 521.33 T +(w System is a tr) 237.65 521.33 T +(ademar) 308.12 521.33 T +(k of Massachusetts Institute of T) 342.17 521.33 T +(echnology) 484.37 521.33 T +(.) 528.95 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(OSF/Motif and Motif are tr) 180 497.33 T +(ademar) 294.94 497.33 T +(ks of Open Softw) 328.99 497.33 T +(are F) 404.99 497.33 T +(oundation, Inc.) 428.03 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ultr) 180 473.33 T +(ix and DEC are registered tr) 195.7 473.33 T +(ademar) 319.53 473.33 T +(ks of Digital Equipment Cor) 353.58 473.33 T +(por) 475.03 473.33 T +(ation.) 489.38 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(HPUX is a registered tr) 180 449.33 T +(ademar) 282.15 449.33 T +(k of He) 316.2 449.33 T +(wlett P) 347.68 449.33 T +(ac) 377.29 449.33 T +(kard.) 387.65 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(SURA/CEB) 54 344.33 T +(AF:) 105.92 344.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.44 (The Southeaster) 180 344.33 P +4.44 (n Univ) 258.62 344.33 P +4.44 (ersities Research Association \050SURA\051 oper) 291.15 344.33 P +4.44 (ates the) 499.98 344.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.01 (Contin) 180 332.33 P +2.01 (uous Electron Beam Acceler) 208.8 332.33 P +2.01 (ator F) 340.89 332.33 P +2.01 (acility \050CEBAF\051 f) 368.52 332.33 P +2.01 (or the United States) 445.59 332.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Depar) 180 320.33 T +(tment of Energy under contr) 207.63 320.33 T +(act DE-A) 331.48 320.33 T +(C05-84ER40150.) 371.19 320.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DISCLAIMER:) 54 218.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.49 (This repor) 180 218.33 P +0.49 (t w) 225.9 218.33 P +0.49 (as prepared as an account of w) 239.02 218.33 P +0.49 (or) 381.4 218.33 P +0.49 (k sponsored b) 390.44 218.33 P +0.49 (y the United States) 454.03 218.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.18 (go) 180 206.33 P +2.18 (v) 190.97 206.33 P +2.18 (er) 195.72 206.33 P +2.18 (nment. Neither the United States nor the United States Depar) 204.86 206.33 P +2.18 (tment of) 501.68 206.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.04 (Energy) 180 194.33 P +1.04 (, nor an) 210.68 194.33 P +1.04 (y of their emplo) 246.52 194.33 P +1.04 (y) 317.69 194.33 P +1.04 (ees) 322.49 194.33 P +1.04 (, mak) 338.46 194.33 P +1.04 (es an) 363.75 194.33 P +1.04 (y w) 389.1 194.33 P +1.04 (arr) 404.99 194.33 P +1.04 (anty) 417.11 194.33 P +1.04 (, e) 435.01 194.33 P +1.04 (xpress or implied, or) 446.86 194.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.83 (assumes an) 180 182.33 P +1.83 (y legal liability or responsibility f) 235.59 182.33 P +1.83 (or the accur) 383.89 182.33 P +1.83 (acy) 440.24 182.33 P +1.83 (, completeness) 454.8 182.33 P +1.83 (, or) 523.72 182.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.68 (usefulness of an) 180 170.33 P +3.68 (y inf) 260.02 170.33 P +3.68 (or) 281.74 170.33 P +3.68 (mation, appar) 290.88 170.33 P +3.68 (atus) 355.59 170.33 P +3.68 (, product or process disclosed, or) 374.34 170.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.46 (represents that its use w) 180 158.33 P +2.46 (ould not infr) 298.11 158.33 P +2.46 (inge pr) 355.42 158.33 P +2.46 (iv) 388.59 158.33 P +2.46 (ately o) 395.56 158.33 P +2.46 (wned r) 427.33 158.33 P +2.46 (ights) 459.95 158.33 P +2.46 (. Ref) 480.92 158.33 P +2.46 (erence) 509.43 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.6 (herein to an) 180 146.33 P +1.6 (y speci\336c commercial product, process) 235.85 146.33 P +1.6 (, or ser) 413.79 146.33 P +1.6 (vice b) 448.4 146.33 P +1.6 (y tr) 475.92 146.33 P +1.6 (ade name) 491.3 146.33 P +1.6 (,) 537.22 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (mar) 180 134.33 P +2.12 (k, man) 197.37 134.33 P +2.12 (uf) 229.4 134.33 P +2.12 (acturer) 237.44 134.33 P +2.12 (, or otherwise) 268.06 134.33 P +2.12 (, does not necessar) 332.17 134.33 P +2.12 (ily constitute or imply its) 425.94 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (endorsement, recommendation, or f) 180 122.33 P +1.08 (a) 341.33 122.33 P +1.08 (v) 346.69 122.33 P +1.08 (or) 351.44 122.33 P +1.08 (ing b) 360.48 122.33 P +1.08 (y the United States go) 383.03 122.33 P +1.08 (v) 485.57 122.33 P +1.08 (er) 490.32 122.33 P +1.08 (nment or) 499.46 122.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (an) 180 110.33 P +0.83 (y agency thereof) 190.97 110.33 P +0.83 (. The vie) 266.26 110.33 P +0.83 (w and opinions of the authors e) 309.67 110.33 P +0.83 (xpressed herein do) 453.3 110.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.94 (not necessar) 180 98.33 P +1.94 (ily state or re\337ect those of the United States go) 239.34 98.33 P +1.94 (v) 464.01 98.33 P +1.94 (er) 468.76 98.33 P +1.94 (nment or an) 477.9 98.33 P +1.94 (y) 535 98.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(agency thereof) 180 86.33 T +(.) 245.85 86.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DOCUMENT D) 54 668.33 T +(A) 121.37 668.33 T +(TE:) 127.69 668.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(T) 180 668.33 T +(ab) 184.91 668.33 T +(le of ontents gener) 195.83 668.33 T +(ated: December 9, 1996 11:45 am) 278.56 668.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "ii" 26 +%%Page: "iii" 27 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iii) 551.34 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(T) 180 710.67 T +(ab) 187.43 710.67 T +(le of Contents) 203.63 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(List of Figures) 198 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(v) 553 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 180 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Introduction) 198 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 252.98 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(What is CDEV) 198 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(La) 198 648.33 T +(y) 208.82 648.33 T +(er) 213.62 648.33 T +(ing and Abstr) 222.66 648.33 T +(action) 281.48 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Inf) 198 636.33 T +(or) 208.82 636.33 T +(mation Hiding) 217.96 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198 624.33 T +(vice Object) 210.48 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Standard Messages) 198 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 289.12 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data Object) 198 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 252.98 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 180 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Basic Oper) 198 588.33 T +(ations on De) 247.36 588.33 T +(vices and Data) 303.2 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 369.74 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 180 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Asychronous Oper) 198 576.33 T +(ations) 280.71 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Callbac) 198 564.33 T +(k Object) 231.14 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(System Object) 198 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Group Object) 198 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Request Object) 198 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(File Descr) 198 516.33 T +(iptors and \322select\323) 243.15 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 325.26 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 180 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Error Handling) 198 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 180 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name Resolution) 198 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 198 480.33 T +(vDirector) 213.82 480.33 T +(y Object) 254.12 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ser) 198 468.33 T +(vice De\336nition) 213.86 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 546.88 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198 456.33 T +(vice Class De\336nition) 210.48 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 303.02 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15) 546.88 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Instance De\336nition) 198 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Aliases) 198 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 230.74 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 180 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Channel Access Ser) 198 420.33 T +(vice) 288.89 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 546.88 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iii" 27 +%%Page: "iv" 28 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iv) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iv" 28 +%%Page: "v" 29 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +( List of Figures) 498.98 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(v) 553 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(List of Figures) 180 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(Figure 1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample usage of the send method of a cdevDevice) 234 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(................................) 461.48 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 2.) 180 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Overview of cdevData operations) 234 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(............................................................) 383.64 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 3.) 180 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Three forms of the send command) 234 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..........................................................) 389.2 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 4.) 180 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Overview of the cdevCallback object and the cdevCallbackFunction) 234 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(......) 533.76 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 5.) 180 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Structure of the cdevCallback object) 234 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................................................) 394.76 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 6.) 180 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Usage of the pend method in the cdevSystem object) 234 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..............................) 467.04 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 7.) 180 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Synchronization methods in the cdevSystem object) 234 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(................................) 461.48 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 8.) 180 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample usage of the cdevGroup object) 234 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................................) 408.66 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 9.) 180 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample usage of the cdevRequestObject object) 234 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.....................................) 447.58 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 10.) 180 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Structure of the cdevRequestObject object) 234 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..............................................) 422.56 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 11.) 180 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(File descriptor routines of the cdevSystem object) 234 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(....................................) 450.36 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 12.) 180 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using CDEV file descriptors with the UNIX select function) 234 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(....................) 489.28 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 13.) 180 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Error handling mechanisms provided by the cdevSystem object) 234 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........) 514.3 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 14.) 180 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Enumerated severity codes generated by CDEV) 234 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................) 447.58 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 15.) 180 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Enumerated error codes generated by CDEV) 234 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................................) 433.68 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 546.88 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 16.) 180 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Obtaining a reference to the cdevDirectory device) 234 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(................................) 455.92 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 17.) 180 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Virtual form of the data in a cdevDirectory) 234 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.............................................) 419.78 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 18.) 180 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Syntax of the #include directive) 234 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..............................................................) 372.52 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 546.88 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 19.) 180 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample service definition) 234 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................................................................) 347.5 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 546.88 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 20.) 180 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample service definition) 234 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................................................................) 347.5 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15) 546.88 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 21.) 180 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample inherited class definition) 234 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(............................................................) 378.08 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 22.) 180 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Multiple instances of the magnet class) 234 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................................) 403.1 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 23.) 180 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Alias device name) 234 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..................................................................................) 316.92 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "v" 29 +%%Page: "vi" 30 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +( List of Figures) 54 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(vi) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "vi" 30 +%%Page: "1" 31 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. Introduction) 500.97 739 T +0 10 Q +(1) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(1.) 159.32 710.67 T +(Intr) 180 710.67 T +(oduction) 202.27 710.67 T +2 10 Q +(What is CDEV) 72 673.33 T +0 F +1.09 (The CDEV \050common de) 180 673.33 P +1.09 (vice\051 C++ class libr) 289.11 673.33 P +1.09 (ar) 376.73 673.33 P +1.09 (y is an object-or) 385.92 673.33 P +1.09 (iented fr) 459.92 673.33 P +1.09 (ame) 497.04 673.33 P +1.09 (w) 516.29 673.33 P +1.09 (or) 523.41 673.33 P +1.09 (k that) 532.45 673.33 P +1.76 (pro) 180 661.33 P +1.76 (vides a standard interf) 194.3 661.33 P +1.76 (ace betw) 297.65 661.33 P +1.76 (een an application and one or more under) 339.33 661.33 P +1.76 (lying) 537.44 661.33 P +4.52 (control pac) 180 649.33 P +4.52 (kages or systems) 233.23 649.33 P +4.52 (. Each under) 319.92 649.33 P +4.52 (lying pac) 385.81 649.33 P +4.52 (kage \050called a ser) 429.59 649.33 P +4.52 (vice\051 is) 522.37 649.33 P +1.18 (dynamically loaded at r) 180 637.33 P +1.18 (un-time) 285.96 637.33 P +1.18 (, allo) 319.15 637.33 P +1.18 (wing an application to access a ne) 341.31 637.33 P +1.18 (w ser) 500.52 637.33 P +1.18 (vice b) 525.9 637.33 P +1.18 (y) 553 637.33 P +-0.09 (name without re-compilation or re-linking. A major f) 180 625.33 P +-0.09 (eature of CDEV is its ability to hide) 404.68 625.33 P +2.93 (the implementation details of a par) 180 613.33 P +2.93 (ticular de) 347.88 613.33 P +2.93 (vice from the high le) 391.08 613.33 P +2.93 (v) 491.96 613.33 P +2.93 (el application) 496.71 613.33 P +0.07 (de) 180 601.33 P +0.07 (v) 190.82 601.33 P +0.07 (eloper) 195.57 601.33 P +0.07 (. This allo) 222.86 601.33 P +0.07 (ws ser) 265.63 601.33 P +0.07 (v) 294.89 601.33 P +0.07 (er implementation choices to be changed without breaking) 299.64 601.33 P +0.9 (high le) 180 589.33 P +0.9 (v) 210.06 589.33 P +0.9 (el client applications) 214.81 589.33 P +0.9 (. Additionally) 305.93 589.33 P +0.9 (, because the application is una) 362.52 589.33 P +0.9 (w) 506.89 589.33 P +0.9 (are of the) 513.96 589.33 P +4.86 (under) 180 577.33 P +4.86 (lying ser) 205.72 577.33 P +4.86 (vice\325) 248.11 577.33 P +4.86 (s speci\336c implementation, CDEV is a po) 267.61 577.33 P +4.86 (w) 473.91 577.33 P +4.86 (erful v) 481.03 577.33 P +4.86 (ehicle f) 512.87 577.33 P +4.86 (or) 549.11 577.33 P +(de) 180 565.33 T +(v) 190.82 565.33 T +(eloping por) 195.57 565.33 T +(tab) 245.44 565.33 T +(le applications) 259.14 565.33 T +(.) 322.35 565.33 T +-0.25 (The basic CDEV interf) 180 548.33 P +-0.25 (ace can be descr) 277.88 548.33 P +-0.25 (ibed through a) 353.43 548.33 P +3 F +-0.25 (de) 419.4 548.33 P +-0.25 (vice) 430.22 548.33 P +0 F +-0.25 (/) 448 548.33 P +3 F +-0.25 (message) 450.78 548.33 P +0 F +-0.25 ( par) 491.35 548.33 P +-0.25 (adigm. The) 508.23 548.33 P +3 F +2.36 (de) 180 536.33 P +2.36 (vice) 190.82 536.33 P +0 F +2.36 ( is not necessar) 208.6 536.33 P +2.36 (ily a ph) 285.85 536.33 P +2.36 (ysical object, r) 321.94 536.33 P +2.36 (ather) 389.9 536.33 P +2.36 (, it is a cde) 412.19 536.33 P +2.36 (vDe) 469.11 536.33 P +2.36 (vice object that) 486.59 536.33 P +1.42 (pro) 180 524.33 P +1.42 (vides a standard interf) 194.3 524.33 P +1.42 (ace to CDEV) 296.64 524.33 P +1.42 (. The application uses this interf) 356.03 524.33 P +1.42 (ace to send) 503.46 524.33 P +4.12 (messages to the de) 180 512.33 P +4.12 (vice) 279.32 512.33 P +4.12 (. When the cde) 296.95 512.33 P +4.12 (vDe) 376.26 512.33 P +4.12 (vice receiv) 393.74 512.33 P +4.12 (es this message it will) 444.84 512.33 P +1.36 (dynamically load the appropr) 180 500.33 P +1.36 (iate ser) 312.05 500.33 P +1.36 (vice \050as de\336ned in the CDEV de) 346.49 500.33 P +1.36 (vice de\336nition) 496.06 500.33 P +2.96 (\336le\051, and f) 180 488.33 P +2.96 (orw) 229.54 488.33 P +2.96 (ard the message to it. The ser) 245.49 488.33 P +2.96 (vice ma) 396.41 488.33 P +2.96 (y then perf) 433.52 488.33 P +2.96 (or) 486.39 488.33 P +2.96 (m an) 495.54 488.33 P +2.96 (y action) 520.58 488.33 P +(necessar) 180 476.33 T +(y to satisfy the application\325) 220.87 476.33 T +(s request.) 337.09 476.33 T +0.13 (The CDEV API is optimiz) 180 459.33 P +0.13 (ed f) 291.52 459.33 P +0.13 (or repetitiv) 308.03 459.33 P +0.13 (e oper) 354.6 459.33 P +0.13 (ations) 382.98 459.33 P +0.13 (, in par) 409.51 459.33 P +0.13 (ticular f) 440.74 459.33 P +0.13 (or monitor) 472.8 459.33 P +0.13 (ing v) 518.1 459.33 P +0.13 (alue) 539.1 459.33 P +3.2 (changes within a ser) 180 447.33 P +3.2 (v) 281.04 447.33 P +3.2 (er) 285.79 447.33 P +3.2 (. Asychronous oper) 294.18 447.33 P +3.2 (ations with callbac) 386.62 447.33 P +3.2 (ks are suppor) 473.95 447.33 P +3.2 (ted,) 541.32 447.33 P +0.11 (including asychronous error noti\336cation. Speci\336cally) 180 435.33 P +0.11 (, CDEV suppor) 408.4 435.33 P +0.11 (ts most f) 475.71 435.33 P +0.11 (eatures of) 513.42 435.33 P +(channel access \050the EPICS comm) 180 423.33 T +(unications protocol\051.) 331.62 423.33 T +2 F +(La) 72 394.33 T +(y) 83.47 394.33 T +(ering and) 88.93 394.33 T +(Abstraction) 72 382.33 T +0 F +1.59 (The CDEV libr) 180 394.33 P +1.59 (ar) 246.98 394.33 P +1.59 (y pro) 256.17 394.33 P +1.59 (vides a standard interf) 279.84 394.33 P +1.59 (ace to one or more under) 382.68 394.33 P +1.59 (lying control) 503.06 394.33 P +0.95 (pac) 180 382.33 P +0.95 (kages or systems) 195.92 382.33 P +0.95 (. Currently CDEV pro) 275.48 382.33 P +0.95 (vides suppor) 372.1 382.33 P +0.95 (t f) 430.14 382.33 P +0.95 (or EPICS channel access) 439.13 382.33 P +0.95 (,) 555.22 382.33 P +0.54 (tcl scr) 180 370.33 P +0.54 (ipts) 206.8 370.33 P +0.54 (, the A) 222.21 370.33 P +0.54 (CE comm) 251.9 370.33 P +0.54 (unications pac) 296.22 370.33 P +0.54 (kage \050a C++ class libr) 360.48 370.33 P +0.54 (ar) 459.23 370.33 P +0.54 (y o) 468.42 370.33 P +0.54 (v) 482.15 370.33 P +0.54 (er TCP/IP\051. The) 486.9 370.33 P +0.59 (A) 180 358.33 P +0.59 (CE pac) 186.37 358.33 P +0.59 (kage is used to comm) 219.55 358.33 P +0.59 (unicate with an on-line acceler) 319.08 358.33 P +0.59 (ator modeling pac) 455.85 358.33 P +0.59 (kage) 536.32 358.33 P +0.92 (and with COD) 180 346.33 P +0.92 (A, the CEBAF On-line Data Acquisition system. Access to the EPICS) 243.68 346.33 P +0.07 (archiv) 180 334.33 P +0.07 (e data will be added in a later release) 206.42 334.33 P +0.07 (. All data will be a) 372.46 334.33 P +0.07 (v) 450.41 334.33 P +0.07 (ailab) 455.16 334.33 P +0.07 (le through a single) 476.08 334.33 P +(API \050application prog) 180 322.33 T +(r) 272.72 322.33 T +(amming interf) 275.95 322.33 T +(ace\051.) 336.22 322.33 T +2 F +(Inf) 72 293.33 T +(ormation Hiding) 84.02 293.33 T +0 F +-0.24 (The ability to hide the implementation details of a par) 180 293.33 P +-0.24 (ticular de) 412.23 293.33 P +-0.24 (vice \050such as the choice) 452.26 293.33 P +3.9 (of records in EPICS\051 from the high le) 180 281.33 P +3.9 (v) 369.85 281.33 P +3.9 (el application de) 374.6 281.33 P +3.9 (v) 454.36 281.33 P +3.9 (eloper) 459.11 281.33 P +3.9 (, allo) 486.4 281.33 P +3.9 (ws ser) 511.27 281.33 P +3.9 (v) 544.36 281.33 P +3.9 (er) 549.11 281.33 P +4.84 (implementation choices to be changed without breaking all high le) 180 269.33 P +4.84 (v) 514.51 269.33 P +4.84 (el client) 519.26 269.33 P +0.46 (applications) 180 257.33 P +0.46 (. F) 232.65 257.33 P +0.46 (or e) 244.48 257.33 P +0.46 (xample) 261.86 257.33 P +0.46 (, se) 293.94 257.33 P +0.46 (v) 310.22 257.33 P +0.46 (er) 314.97 257.33 P +0.46 (al records ma) 323.76 257.33 P +0.46 (y be merged into a ne) 384.94 257.33 P +0.46 (w custom record) 483.74 257.33 P +(without changing applications which access those records through the CDEV API.) 180 245.33 T +2 F +(De) 72 216.33 T +(vice Object) 84.63 216.33 T +0 F +1.61 (The basic idea behind CDEV is that all I/O is perf) 180 216.33 P +1.61 (or) 412.56 216.33 P +1.61 (med b) 421.7 216.33 P +1.61 (y sending messages to) 450.9 216.33 P +0.4 (de) 180 204.33 P +0.4 (vices) 190.82 204.33 P +0.4 (. A de) 213.45 204.33 P +0.4 (vice is a named entity in the control system which can respond to a set) 240.07 204.33 P +1.71 (of messages such as) 180 192.33 P +3 F +1.71 (on) 283.53 192.33 P +0 F +1.71 ( or) 294.65 192.33 P +3 F +1.71 (off) 312.51 192.33 P +0 F +1.71 ( or) 323.63 192.33 P +3 F +1.71 (get current) 341.49 192.33 P +0 F +1.71 (. Fur) 391 192.33 P +1.71 (ther) 413.67 192.33 P +1.71 (, a de) 430.4 192.33 P +1.71 (vice is a vir) 458.53 192.33 P +1.71 (tual entity) 513.49 192.33 P +3.22 (potentially spanning m) 180 180.33 P +3.22 (ultiple ser) 285.83 180.33 P +3.22 (v) 332.14 180.33 P +3.22 (ers and ser) 336.89 180.33 P +3.22 (vices such as channel access) 393.65 180.33 P +3.22 (, an) 538.1 180.33 P +(archiv) 180 168.33 T +(er) 206.42 168.33 T +(, and a static database) 214.81 168.33 T +(.) 315.28 168.33 T +2.1 (Each de) 180 151.33 P +2.1 (vice and message pair is mapped to a unique ser) 218.49 151.33 P +2.1 (vice \050such as channel) 455.55 151.33 P +0.61 (access\051 and ser) 180 139.33 P +0.61 (vice dependent data \050such as the process v) 252.09 139.33 P +0.61 (ar) 448.97 139.33 P +0.61 (iab) 458.01 139.33 P +0.61 (le name in EPICS\051.) 471.15 139.33 P +0.03 (This mapping is k) 180 127.33 P +0.03 (ept in a name ser) 257.69 127.33 P +0.03 (vice) 335.36 127.33 P +0.03 (, and is ultimately initializ) 352.99 127.33 P +0.03 (ed from an ASCII \336le) 462.99 127.33 P +0.03 (.) 555.22 127.33 P +1.17 (The designer/maintainer of the ser) 180 115.33 P +1.17 (v) 337.26 115.33 P +1.17 (er w) 342.01 115.33 P +1.17 (ould typically be the person responsib) 361.97 115.33 P +1.17 (le f) 534.9 115.33 P +1.17 (or) 549.11 115.33 P +(k) 180 103.33 T +(eeping the mapping current.) 184.8 103.33 T +FMENDPAGE +%%EndPage: "1" 31 +%%Page: "2" 32 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. Introduction) 54 739 T +0 10 Q +(2) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +2 10 Q +(Standar) 54 713.33 T +(d) 91.03 713.33 T +(Messa) 54 701.33 T +(g) 84.47 701.33 T +(es) 90.68 701.33 T +0 F +0.72 (Most de) 162 713.33 P +0.72 (vices will implement a n) 197.99 713.33 P +0.72 (umber of attr) 305.81 713.33 P +0.72 (ib) 364.1 713.33 P +0.72 (utes which ma) 371.68 713.33 P +0.72 (y be read or wr) 436.74 713.33 P +0.72 (itten. In) 506.48 713.33 P +1.32 (order to f) 162 701.33 P +1.32 (acilitate de) 204.37 701.33 P +1.32 (v) 253.19 701.33 P +1.32 (eloping gener) 257.94 701.33 P +1.32 (ic applications) 320 701.33 P +1.32 (, the f) 383.98 701.33 P +1.32 (ollo) 411.34 701.33 P +1.32 (wing standard messages) 426.75 701.33 P +(are recommended f) 162 689.33 T +(or de) 248.4 689.33 T +(vices) 270.89 689.33 T +(, where) 293.52 689.33 T +3 F +(attr) 329.09 689.33 T +(ib) 343.69 689.33 T +0 F +( is some attr) 351.47 689.33 T +(ib) 406.08 689.33 T +(ute of the de) 413.66 689.33 T +(vice:) 468.96 689.33 T +4 9 Q +(set) 180 673 T +5 F +(attrib) 201.6 673 T +4 F +( => Set the value of the attribute) 234 673 T +(get) 180 662 T +5 F +(attrib) 201.6 662 T +4 F +( => Get the value of the attribute) 234 662 T +-0.51 (monitorOn) 180 651 P +5 F +-0.51 (attrib) 233.49 651 P +4 F +-0.51 ( => Start monitoring the value of the attribute) 265.89 651 P +-0.14 (monitorOff) 180 640 P +5 F +-0.14 (attrib) 239.26 640 P +4 F +-0.14 ( => Stop monitoring the value of the attribute) 271.66 640 P +2 10 Q +(Data Object) 54 611.33 T +0 F +0.91 (The message sent to the de) 162 611.33 P +0.91 (vice ma) 290.21 611.33 P +0.91 (y ha) 325.27 611.33 P +0.91 (v) 344.89 611.33 P +0.91 (e an associated data object. F) 349.64 611.33 P +0.91 (or e) 487.3 611.33 P +0.91 (xample) 505.14 611.33 P +0.91 (,) 537.22 611.33 P +-0.23 (the message) 162 599.33 P +3 F +-0.23 (set current) 221.57 599.33 P +0 F +-0.23 ( will ha) 268.59 599.33 P +-0.23 (v) 298.49 599.33 P +-0.23 (e an associated) 303.24 599.33 P +3 F +-0.23 (v) 375.38 599.33 P +-0.23 (alue) 380.13 599.33 P +0 F +-0.23 ( f) 399.03 599.33 P +-0.23 (or the ne) 404.06 599.33 P +-0.23 (w current setting. This) 442.87 599.33 P +(v) 162 587.33 T +(alue is passed as an additional argument on the send call.) 166.75 587.33 T +2.64 (Data retur) 162 570.33 P +2.64 (ned from the ser) 209.35 570.33 P +2.64 (v) 290.38 570.33 P +2.64 (er to the client ma) 295.13 570.33 P +2.64 (y contain m) 384.87 570.33 P +2.64 (ultiple tagged v) 441.18 570.33 P +2.64 (alues) 513.47 570.33 P +2.64 (,) 537.22 570.33 P +1.92 (including) 162 558.33 P +3 F +1.92 (v) 206.16 558.33 P +1.92 (alue) 210.91 558.33 P +0 F +1.92 (,) 229.66 558.33 P +3 F +1.92 (status) 237.14 558.33 P +0 F +1.92 (, and) 263.67 558.33 P +3 F +1.92 ( timestamp) 287.83 558.33 P +0 F +1.92 (. Each of these items is e) 338.3 558.33 P +1.92 (xtr) 461.23 558.33 P +1.92 (acted from the) 472.24 558.33 P +1.5 (retur) 162 546.33 P +1.5 (ned data object b) 182.81 546.33 P +1.5 (y specifying a name or an integer tag. An) 263.83 546.33 P +1.5 (y data object ma) 457.43 546.33 P +1.5 (y) 535 546.33 P +2.68 (contain an arbitr) 162 534.33 P +2.68 (ar) 238.97 534.33 P +2.68 (y n) 248.16 534.33 P +2.68 (umber of tagged entr) 264.08 534.33 P +2.68 (ies) 365.11 534.33 P +2.68 (, allo) 377.74 534.33 P +2.68 (wing consider) 401.4 534.33 P +2.68 (ab) 465.11 534.33 P +2.68 (le \337e) 476.03 534.33 P +2.68 (xibility in) 499.54 534.33 P +(de\336ning future clients and ser) 162 522.33 T +(v) 292.92 522.33 T +(ers) 297.67 522.33 T +(.) 311.41 522.33 T +3 F +0.83 (Ac) 162 505.33 P +0.83 (kno) 173.47 505.33 P +0.83 (wledgment: This w) 189.44 505.33 P +0.83 (or) 273.8 505.33 P +0.83 (k der) 282.84 505.33 P +0.83 (iv) 306.04 505.33 P +0.83 (es some of its ideas about de) 313.01 505.33 P +0.83 (vices and messages) 447.75 505.33 P +1.38 (from w) 162 493.33 P +1.38 (or) 193.28 493.33 P +1.38 (k done at Argonne b) 202.32 493.33 P +1.38 (y Claude Saunders on a de) 297.69 493.33 P +1.38 (vice or) 425.46 493.33 P +1.38 (iented la) 456.43 493.33 P +1.38 (y) 495.31 493.33 P +1.38 (er abo) 500.11 493.33 P +1.38 (v) 529.69 493.33 P +1.38 (e) 534.44 493.33 P +0.22 (channel access) 162 481.33 P +0.22 (. Much additional analysis & design w) 230.99 481.33 P +0.22 (or) 398.36 481.33 P +0.22 (k has been done b) 407.39 481.33 P +0.22 (y members) 490.33 481.33 P +(of the EPICS collabor) 162 469.33 T +(ation.) 257.5 469.33 T +FMENDPAGE +%%EndPage: "2" 32 +%%Page: "3" 33 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. Basic Operations on Devices and Data) 393.43 739 T +0 10 Q +(3) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(2.) 159.32 710.67 T +(Basic Operations on De) 180 710.67 T +(vices and Data) 337.72 710.67 T +0 10 Q +0.44 (The basic user deals only with the de) 180 684.33 P +0.44 (vice and data objects) 347.28 684.33 P +0.44 (. The de) 442.38 684.33 P +0.44 (vice is created b) 479.64 684.33 P +0.44 (y) 553 684.33 P +0.54 (name) 180 672.33 P +0.54 (, and I/O consists of sending messages to this de) 204.86 672.33 P +0.54 (vice) 427.34 672.33 P +0.54 (. The de) 444.97 672.33 P +0.54 (vice object is the) 482.45 672.33 P +0.8 (simplest I/O object to use: a single de) 180 660.33 P +0.8 (vice \050magnet, vie) 351.47 660.33 P +0.8 (w) 428.45 660.33 P +0.8 (er) 435.57 660.33 P +0.8 (, etc.\051 ma) 443.96 660.33 P +0.8 (y be completely) 486.93 660.33 P +0.36 (controlled from a single de) 180 648.33 P +0.36 (vice object, with data being passed b) 298.39 648.33 P +0.36 (y 2 data objects \050one) 463.75 648.33 P +0.2 (f) 180 636.33 P +0.2 (or output, another f) 182.48 636.33 P +0.2 (or retur) 267.27 636.33 P +0.2 (ned results; dataless commands w) 299.95 636.33 P +0.2 (ould not require either\051.) 454.03 636.33 P +0.55 (The f) 180 624.33 P +0.55 (ollo) 203.04 624.33 P +0.55 (wing sample code reads the magnet current from one magnet, and sets the) 218.45 624.33 P +(magnet current f) 180 612.33 T +(or a second magnet to that v) 252.51 612.33 T +(alue:) 379 612.33 T +3 9 Q +(Figure 1: Sample usage of the send method of a cde) 180 579 T +(vDe) 391.85 579 T +(vice) 407.58 579 T +0 10 Q +2.25 (The send call, which is synchronous) 180 340.33 P +2.25 (, tak) 351.15 340.33 P +2.25 (es 3 arguments) 372.1 340.33 P +2.25 (, and retur) 445.37 340.33 P +2.25 (ns an integer) 495.69 340.33 P +(status:) 180 328.33 T +6 9 Q +(int send\050char* msg, cdevData& out, cdevData& result\051;) 198 312 T +0 10 Q +0.22 (Lik) 180 295.33 P +0.22 (e all CDEV calls) 192.58 295.33 P +0.22 (, a retur) 264.78 295.33 P +0.22 (n code of 0 means success \050error handling is descr) 299.94 295.33 P +0.22 (ibed in) 528.32 295.33 P +0.19 (a later section\051. The \336rst argument to) 180 283.33 P +3 F +0.19 (send) 347.52 283.33 P +0 F +0.19 ( is a char) 369.2 283.33 P +0.19 (acter str) 410.25 283.33 P +0.19 (ing message) 446.71 283.33 P +0.19 (. The de) 503.45 283.33 P +0.19 (vice) 540.22 283.33 P +0.41 (name and this str) 180 271.33 P +0.41 (ing uniquely deter) 258.08 271.33 P +0.41 (mine the under) 338.07 271.33 P +0.41 (lying ser) 405.74 271.33 P +0.41 (vice to use) 443.68 271.33 P +0.41 (, and whate) 492.14 271.33 P +0.41 (v) 544.36 271.33 P +0.41 (er) 549.11 271.33 P +2.06 (addressing data that ser) 180 259.33 P +2.06 (vice needs to locate the ser) 293.77 259.33 P +2.06 (v) 426.1 259.33 P +2.06 (er) 430.85 259.33 P +2.06 (. The \336rst) 439.24 259.33 P +3 F +2.06 (send) 489.89 259.33 P +0 F +2.06 ( oper) 511.57 259.33 P +2.06 (ation) 536.32 259.33 P +0.57 (automatically connects to the requested ser) 180 247.33 P +0.57 (vice) 376.01 247.33 P +0.57 (, initializing an) 393.64 247.33 P +0.57 (y under) 457.42 247.33 P +0.57 (lying pac) 491.49 247.33 P +0.57 (kages) 531.32 247.33 P +(as needed.) 180 235.33 T +0.11 (The second and third arguments are outbound and result data of type cde) 180 218.33 P +0.11 (vData. This) 507.32 218.33 P +1.75 (is a composite data object which ma) 180 206.33 P +1.75 (y contain an arbitr) 350.82 206.33 P +1.75 (ar) 435.44 206.33 P +1.75 (y n) 444.63 206.33 P +1.75 (umber of data v) 459.62 206.33 P +1.75 (alues) 534.1 206.33 P +1.45 (tagged with an integer tag. The data is self-descr) 180 194.33 P +1.45 (ibing to the e) 407.95 194.33 P +1.45 (xtent that cde) 469.25 194.33 P +1.45 (vData) 531.88 194.33 P +2.38 (k) 180 182.33 P +2.38 (eeps tr) 184.8 182.33 P +2.38 (ac) 217.65 182.33 P +2.38 (k of the data type) 228.01 182.33 P +2.38 (, and can automatically con) 314.12 182.33 P +2.38 (v) 444.63 182.33 P +2.38 (er) 449.38 182.33 P +2.38 (t betw) 458.67 182.33 P +2.38 (een data types) 487.63 182.33 P +0.85 (through C++ function o) 180 170.33 P +0.85 (v) 284.13 170.33 P +0.85 (er) 288.88 170.33 P +0.85 (loading or b) 297.92 170.33 P +0.85 (y e) 351.67 170.33 P +0.85 (xplicit direction from the caller) 365.56 170.33 P +0.85 (. The integer) 500.16 170.33 P +-0.05 (tags are not kno) 180 158.33 P +-0.05 (wn to the user at compile time \050i.e) 251.42 158.33 P +-0.05 (., no header \336les required\051, and can) 400.43 158.33 P +0.77 (be ref) 180 146.33 P +0.77 (erred to b) 206.04 146.33 P +0.77 (y char) 250.19 146.33 P +0.77 (acter str) 278.09 146.33 P +0.77 (ing equiv) 315.14 146.33 P +0.77 (alents) 355.68 146.33 P +0.77 (. The cde) 382.21 146.33 P +0.77 (vData class k) 425.14 146.33 P +0.77 (eeps tr) 485.95 146.33 P +0.77 (ac) 517.19 146.33 P +0.77 (k of all) 527.55 146.33 P +2.33 (integer tags and their char) 180 134.33 P +2.33 (acter str) 305.4 134.33 P +2.33 (ing equiv) 344.01 134.33 P +2.33 (alents) 386.11 134.33 P +2.33 (. Char) 412.64 134.33 P +2.33 (acter str) 442.11 134.33 P +2.33 (ing tags ma) 480.71 134.33 P +2.33 (y be) 536.77 134.33 P +1.8 (con) 180 122.33 P +1.8 (v) 195.92 122.33 P +1.8 (er) 200.67 122.33 P +1.8 (ted to integer tags at r) 209.96 122.33 P +1.8 (un time to impro) 316.38 122.33 P +1.8 (v) 393.31 122.33 P +1.8 (e perf) 398.06 122.33 P +1.8 (or) 425.13 122.33 P +1.8 (mance) 434.27 122.33 P +1.8 (. The f) 464.13 122.33 P +1.8 (ollo) 495.77 122.33 P +1.8 (wing code) 511.18 122.33 P +(demonstr) 180 110.33 T +(ates ho) 221.58 110.33 T +(w to inser) 254.23 110.33 T +(t v) 297.42 110.33 T +(alues into and e) 307.73 110.33 T +(xtr) 378.03 110.33 T +(act v) 389.04 110.33 T +(alues from a cde) 409.91 110.33 T +(vData object:) 483.53 110.33 T +180 81 558 691 C +180 371 558 576 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +125.07 371 612.93 576 R +7 X +0 0 0 1 0 0 0 K +V +186.17 379.09 561.88 570.52 R +0 X +V +0.5 H +2 Z +N +182.4 382.24 554.91 573.67 R +7 X +V +0 X +N +184.62 388.62 552.24 571.47 R +7 X +V +6 9 Q +0 X +(void main \050\051) 184.62 565.47 T +({) 202.62 554.47 T +(// *************************************************************) 202.62 543.47 T +(// * Get references to the 2 devices) 202.62 532.47 T +(// *************************************************************) 202.62 521.47 T +(cdevDevice& mag1 = cdevDevice::attachRef \050\322Magnet1\323\051;) 202.62 510.48 T +(cdevDevice& mag2 = cdevDevice::attachRef \050\322Magnet2\323\051;) 202.62 499.48 T +(cdevData result;) 202.62 488.48 T +(// *************************************************************) 202.62 466.48 T +(// * Get the current from the first magnet and use it to set) 202.62 455.48 T +(// * the current on the second.) 202.62 444.48 T +(// *************************************************************) 202.62 433.48 T +(mag1.send\050\322get current\323, NULL, result\051;) 202.62 422.48 T +(mag2.send\050\322set current\323, result, NULL\051;) 202.62 411.48 T +(}) 202.62 400.48 T +180 81 558 691 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "3" 33 +%%Page: "4" 34 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. Basic Operations on Devices and Data) 54 739 T +0 10 Q +(4) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +3 F +(Figure 2: Ov) 162 714 T +(er) 213.79 714 T +(vie) 222.07 714 T +(w of cde) 233.39 714 T +(vData oper) 266.63 714 T +(ations) 310.56 714 T +0 10 Q +1.55 (The last line abo) 162 527.48 P +1.55 (v) 239.89 527.48 P +1.55 (e demonstr) 244.64 527.48 P +1.55 (ates using oper) 296.11 527.48 P +1.55 (ator o) 367.49 527.48 P +1.55 (v) 394.47 527.48 P +1.55 (er) 399.22 527.48 P +1.55 (loading to e) 408.26 527.48 P +1.55 (xtr) 462.77 527.48 P +1.55 (act the \322v) 473.78 527.48 P +1.55 (alue\323) 517.77 527.48 P +1.2 (item from the data object; i.e) 162 515.48 P +1.2 (., the char) 294.01 515.48 P +1.2 (acter tag \322v) 340.78 515.48 P +1.2 (alue\323 is the def) 392.94 515.48 P +1.2 (ault tag to use in) 461.83 515.48 P +0.19 (e) 162 503.48 P +0.19 (xtr) 167.26 503.48 P +0.19 (acting a data item f) 178.27 503.48 P +0.19 (or the \322=\323 function o) 263.22 503.48 P +0.19 (v) 350.83 503.48 P +0.19 (er) 355.58 503.48 P +0.19 (load. This f) 364.61 503.48 P +0.19 (or) 413.61 503.48 P +0.19 (m is a) 422.75 503.48 P +0.19 (v) 449.6 503.48 P +0.19 (ailab) 454.35 503.48 P +0.19 (le f) 475.27 503.48 P +0.19 (or all scalar) 488.5 503.48 P +(types suppor) 162 491.48 T +(ted b) 219.65 491.48 T +(y cde) 241.69 491.48 T +(vData.) 265.29 491.48 T +1.2 (Most I/O oper) 162 474.48 P +1.2 (ations use the \322v) 224.87 474.48 P +1.2 (alue\323 tag to tr) 301.58 474.48 P +1.2 (ansmit a single v) 363.99 474.48 P +1.2 (alue \050scalar or arr) 441.79 474.48 P +1.2 (a) 523.63 474.48 P +1.2 (y\051.) 528.89 474.48 P +2.22 (Other commonly used tags are \322status\323 and \322time\323 \050a POSIX time str) 162 462.48 P +2.22 (uct\051. These) 487.76 462.48 P +-0.12 (tagged data items are optionally retur) 162 450.48 P +-0.12 (ned b) 326.71 450.48 P +-0.12 (y some ser) 351.41 450.48 P +-0.12 (v) 400.36 450.48 P +-0.12 (ers under the control of the I/O) 405.11 450.48 P +(conte) 162 438.48 T +(xt \050see belo) 186.16 438.48 T +(w f) 237.7 438.48 T +(or changing the def) 250.18 438.48 T +(ault conte) 335.49 438.48 T +(xt\051.) 378.55 438.48 T +1.93 (In this release) 162 421.48 P +1.93 (, cde) 227.95 421.48 P +1.93 (vData suppor) 251.26 421.48 P +1.93 (ts the f) 313.06 421.48 P +1.93 (ollo) 346.63 421.48 P +1.93 (wing data types:) 362.04 421.48 P +3 F +1.93 (unsigned char) 442.86 421.48 P +1.93 (, shor) 507.1 421.48 P +1.93 (t,) 534.44 421.48 P +0.45 (unsigned shor) 162 409.48 P +0.45 (t, int, unsigned int, long, unsigned long, \337oat, doub) 225.66 409.48 P +0.45 (le) 451.95 409.48 P +0 F +0.45 (,) 459.58 409.48 P +3 F +0.45 (char) 465.59 409.48 P +0.45 (acter str) 484.94 409.48 P +0.45 (ings) 521.66 409.48 P +0 F +(and) 162 397.48 T +3 F +(time stamp) 181.46 397.48 T +(.) 230.01 397.48 T +0 F +(All data types ma) 235.57 397.48 T +(y be either scalar or m) 311.97 397.48 T +(ulti-dimensional arr) 410.79 397.48 T +(a) 495.15 397.48 T +(ys) 500.41 397.48 T +(.) 510.26 397.48 T +162 81 540 720 C +162 558.14 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.52 558.14 542.48 711 R +7 X +0 0 0 1 0 0 0 K +V +166.55 561.71 542.27 703.86 R +0 X +V +0.5 H +2 Z +N +163.12 565.14 538.13 706.57 R +7 X +V +0 X +N +165.84 568.86 535.13 703.14 R +7 X +V +6 9 Q +0 X +(cdevData d1, d2;) 165.84 697.14 T +(int valtag;) 165.84 686.14 T +(float x, x2;) 165.84 675.14 T +(int status;) 165.84 664.14 T +(...) 165.84 653.14 T +(d1.tagC2I\050\322value\323,&valtag\051; // get the integer tag for \322value\323) 165.84 642.14 T +(...) 165.84 631.14 T +(d1.insert\050\322value\323,37.9\051; // insert using a character tag) 165.84 620.14 T +(device.send\050\322message\323,d1,d2\051; // send d1, get back d2) 165.84 609.14 T +(d2.get\050valtag,&x\051; // get \322value\323 from d2 into x) 165.84 598.14 T +(d2.get\050\322status\323,&status\051; // extract the \322status\323) 165.84 587.14 T +(x2 = d2; // get \322value\323 into x2 \050= overload\051) 165.84 576.14 T +162 81 540 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "4" 34 +%%Page: "5" 35 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 449.45 739 T +0 10 Q +(5) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(3.) 159.32 710.67 T +(Asyc) 180 710.67 T +(hr) 213.32 710.67 T +(onous Operations) 227.04 710.67 T +0 10 Q +1.79 (In addition to the synchronous send, there are 2 asynchronous f) 180 684.33 P +1.79 (or) 480 684.33 P +1.79 (ms f) 489.14 684.33 P +1.79 (or sending) 509.52 684.33 P +(messages) 180 672.33 T +(. The class de\336nition f) 225.42 672.33 T +(or all three f) 321.83 672.33 T +(or) 374.33 672.33 T +(ms is giv) 383.47 672.33 T +(en belo) 422.11 672.33 T +(w) 454.76 672.33 T +(.) 461.38 672.33 T +3 9 Q +(Figure 3: Three f) 180 639 T +(or) 248.76 639 T +(ms of the send command) 256.99 639 T +0 10 Q +1.17 (The second f) 180 506.76 P +1.17 (or) 239.86 506.76 P +1.17 (m, sendNoBloc) 249 506.76 P +1.17 (k, tak) 317.78 506.76 P +1.17 (es the same arguments as send b) 342.65 506.76 P +1.17 (ut completes) 500.13 506.76 P +1.21 (asynchronously) 180 494.76 P +1.21 (. That is) 248.47 494.76 P +1.21 (, the result will be in) 286.3 494.76 P +1.21 (v) 379.94 494.76 P +1.21 (alid until some synchronizing action is) 384.69 494.76 P +2.44 (tak) 180 482.76 P +2.44 (en \050discussed belo) 193.14 482.76 P +2.44 (w\051. The third f) 281.25 482.76 P +2.44 (or) 349.41 482.76 P +2.44 (m retur) 358.55 482.76 P +2.44 (ns the result to a callbac) 392.91 482.76 P +2.44 (k function) 512.76 482.76 P +0.66 (speci\336ed as par) 180 470.76 P +0.66 (t of the callbac) 251.76 470.76 P +0.66 (k argument. F) 318.03 470.76 P +0.66 (or each of these asychronous calls) 380.75 470.76 P +0.66 (, the) 537.88 470.76 P +0.19 (message ma) 180 458.76 P +0.19 (y be b) 237.13 458.76 P +0.19 (uff) 264.56 458.76 P +0.19 (ered b) 275.38 458.76 P +0.19 (y the under) 303.73 458.76 P +0.19 (lying ser) 354.3 458.76 P +0.19 (vice) 392.02 458.76 P +0.19 (, so that upon retur) 409.65 458.76 P +0.19 (n from the call) 494.62 458.76 P +-0.02 (there is no guar) 180 446.76 P +-0.02 (antee that the message has e) 249.32 446.76 P +-0.02 (v) 380.66 446.76 P +-0.02 (en been sent y) 385.41 446.76 P +-0.02 (et. T) 450.74 446.76 P +-0.02 (r) 469.53 446.76 P +-0.02 (ansmission ma) 472.76 446.76 P +-0.02 (y be) 539.12 446.76 P +2.28 (f) 180 434.76 P +2.28 (orced with a \337ush call using the cde) 182.48 434.76 P +2.28 (vSystem object descr) 355.97 434.76 P +2.28 (ibed belo) 455.71 434.76 P +2.28 (w) 498.42 434.76 P +2.28 (. A \337ush is) 505.04 434.76 P +(automatically perf) 180 422.76 T +(or) 258.06 422.76 T +(med if pend is called.) 267.2 422.76 T +2 F +(Callbac) 72 393.76 T +(k Object) 107.37 393.76 T +0 F +0.85 (The callbac) 180 393.76 P +0.85 (k object is a simple object containing 2 items: a function pointer) 231.78 393.76 P +0.85 (, and an) 520.17 393.76 P +1.21 (arbitr) 180 381.76 P +1.21 (ar) 202.68 381.76 P +1.21 (y user argument. As an e) 211.87 381.76 P +1.21 (xample) 329.33 381.76 P +1.21 (, the f) 361.41 381.76 P +1.21 (ollo) 388.55 381.76 P +1.21 (wing code fr) 403.96 381.76 P +1.21 (agment demonstr) 460.18 381.76 P +1.21 (ates) 539.1 381.76 P +1.85 (monitor) 180 369.76 P +1.85 (ing the magnet current asynchronously \050the third argument to the callbac) 213.49 369.76 P +1.85 (k) 553 369.76 P +(function is discussed later\051:) 180 357.76 T +3 9 Q +(Figure 4: Ov) 180 324.43 T +(er) 231.79 324.43 T +(vie) 240.07 324.43 T +(w of the cde) 251.39 324.43 T +(vCallbac) 299.65 324.43 T +(k object and the cde) 333.97 324.43 T +(vCallbac) 414.25 324.43 T +(kFunction) 448.58 324.43 T +180 419.43 558 691 C +180 537.43 558 636 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.63 537.43 560.37 636 R +7 X +0 0 0 1 0 0 0 K +V +184.44 541.71 560.15 628.86 R +0 X +V +0.5 H +2 Z +N +181.01 545.14 555.3 631.57 R +7 X +V +0 X +N +183.72 549.57 551.58 628.14 R +7 X +V +6 9 Q +0 X +(class cdevDevice:) 183.72 622.14 T +({) 183.72 611.14 T +(public:) 183.72 600.14 T +(int send \050char* msg, cdevData& out, cdevData& result\051;) 201.72 589.14 T +(int sendNoBlock \050char* msg, cdevData& out, cdevData& result\051;) 201.72 578.14 T +(int sendCallback \050char* msg, cdevData& out, cdevCallback cb\051;) 201.72 567.14 T +(};) 183.72 556.14 T +180 419.43 558 691 C +0 0 612 792 C +180 81 558 400.43 C +180 130 558 321.43 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.52 130 560.48 321.43 R +7 X +0 0 0 1 0 0 0 K +V +184.55 135.71 560.27 314.29 R +0 X +V +0.5 H +2 Z +N +181.12 139.14 555.41 317 R +7 X +V +0 X +N +183.84 142.14 551.7 313.57 R +7 X +V +6 9 Q +0 X +(// declare the callback func) 183.84 307.57 T +(cdevCallbackFunction gotit;) 183.84 296.57 T +(// create callback object) 183.84 274.57 T +(cdevCallback callbk\050gotit, myarg\051;) 183.84 263.57 T +(...) 183.84 252.57 T +(mag1.sendCallback\050\322monitorOn current\323,NULL,callbk\051;) 183.84 241.57 T +(...) 183.84 230.57 T +(void gotit\050int status, void* userarg, cdevRequestObject& reqobj,) 183.84 208.57 T +(cdevData& result\051) 237.84 197.57 T +({) 201.84 186.57 T +(float f = result;) 201.84 175.57 T +(printf\050\322new value is %f\134n\323,f\051;) 201.84 164.57 T +(}) 201.84 153.57 T +180 81 558 400.43 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "5" 35 +%%Page: "6" 36 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 54 739 T +0 10 Q +(6) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 10 Q +(The f) 162 713.33 T +(ollo) 184.49 713.33 T +(wing code de\336nes the callbac) 199.9 713.33 T +(k \050the cde) 330.32 713.33 T +(vRequestObject is descr) 373.93 713.33 T +(ibed belo) 482.45 713.33 T +(w\051:) 522.88 713.33 T +3 9 Q +(Figure 5: Str) 162 680 T +(ucture of the cde) 214.15 680 T +(vCallbac) 280.93 680 T +(k object) 315.25 680 T +2 10 Q +(System Object) 54 511.05 T +0 F +0.1 (W) 162 511.05 P +0.1 (aiting f) 171.04 511.05 P +0.1 (or completion of asychronous oper) 200.3 511.05 P +0.1 (ations ma) 354.02 511.05 P +0.1 (y be accomplished in one of tw) 397.18 511.05 P +0.1 (o) 534.44 511.05 P +1.36 (w) 162 499.05 P +1.36 (a) 169.07 499.05 P +1.36 (ys: \0501\051 using g) 174.33 499.05 P +1.36 (roups) 241.1 499.05 P +1.36 (, and \0502\051 using the system object. The system object k) 265.96 499.05 P +1.36 (eeps) 518.32 499.05 P +2.71 (tr) 162 487.05 P +2.71 (ac) 168.01 487.05 P +2.71 (k of all de) 178.37 487.05 P +2.71 (vices) 229 487.05 P +2.71 (, and contains methods f) 251.63 487.05 P +2.71 (or \337ushing, polling, and pending f) 371.11 487.05 P +2.71 (or) 531.11 487.05 P +(asychronous oper) 162 475.05 T +(ations) 241.38 475.05 T +(.) 267.91 475.05 T +3 9 Q +(Figure 6: Usage of the pend method in the cde) 162 441.71 T +(vSystem object) 349.84 441.71 T +0 10 Q +(The f) 162 313.76 T +(ollo) 184.49 313.76 T +(wing class interf) 199.9 313.76 T +(ace sho) 270.73 313.76 T +(ws the f) 305.6 313.76 T +(or) 339.76 313.76 T +(ms f) 348.9 313.76 T +(or each synchronization method:) 367.49 313.76 T +3 9 Q +(Figure 7: Synchronization methods in the cde) 162 280.43 T +(vSystem object) 344.82 280.43 T +3 10 Q +1.33 (\337ush) 162 135.33 P +0 F +1.33 (: Flush all pending output to the netw) 183.12 135.33 P +1.33 (or) 355.75 135.33 P +1.33 (k f) 364.79 135.33 P +1.33 (or those ser) 376.38 135.33 P +1.33 (vices that perf) 432.13 135.33 P +1.33 (or) 496.74 135.33 P +1.33 (m send) 505.88 135.33 P +(b) 162 123.33 T +(uff) 167.36 123.33 T +(er) 178.18 123.33 T +(ing.) 187.22 123.33 T +3 F +0.58 (poll:) 162 106.33 P +0 F +0.58 ( Flush all pending output, and process all receiv) 180.34 106.33 P +0.58 (ed replies \050including dispatching) 395.97 106.33 P +(callbac) 162 94.33 T +(ks) 192.92 94.33 T +(, if an) 202.77 94.33 T +(y\051. An) 227.08 94.33 T +(y receiv) 253.05 94.33 T +(ed monitor callbac) 287.25 94.33 T +(ks will be deliv) 368.19 94.33 T +(ered as w) 431.84 94.33 T +(ell.) 475.09 94.33 T +162 536.71 540 720 C +162 547.71 540 677 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.63 547.71 542.37 677 R +7 X +0 0 0 1 0 0 0 K +V +166.44 550.57 542.15 669.86 R +0 X +V +0.5 H +2 Z +N +163.01 554 537.3 672.57 R +7 X +V +0 X +N +165.72 557.71 533.58 669.14 R +7 X +V +6 9 Q +0 X +(typedef void \050*cdevCallbackFunction\051\050int status, void* userarg,) 165.72 663.14 T +( cdevRequestObject& reqobj,) 345.72 652.14 T +( cdevData& result\051;) 345.72 641.14 T +(class cdevCallback) 165.72 630.14 T +({) 165.72 619.14 T +(public:) 165.72 608.14 T +(cdevCallback \050cdevCallbackFunction func, void* userarg\051;) 183.72 597.14 T +(cdevCallbackFunction function;) 183.72 586.14 T +(void* userarg;) 183.72 575.14 T +(}) 165.72 564.14 T +162 536.71 540 720 C +0 0 612 792 C +162 81 540 517.71 C +162 344.43 540 438.71 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.52 344.43 542.48 438.71 R +7 X +0 0 0 1 0 0 0 K +V +166.55 347.28 542.27 431.57 R +0 X +V +0.5 H +2 Z +N +163.12 350.71 537.41 434.28 R +7 X +V +0 X +N +165.84 353.71 533.7 430.86 R +7 X +V +6 9 Q +0 X +(// get default system) 165.84 424.86 T +(cdevSystem& sys = cdevSystem::defaultSystem\050\051;) 165.84 413.86 T +(...) 165.84 402.86 T +(mag1.sendNoBlock\050\322on\323,...\051; // async op\050s\051) 165.84 391.86 T +(mag2.sendNoBlock\050\322on\323,...\051; // async op\050s\051) 165.84 380.86 T +(...) 165.84 369.86 T +(sys.pend\050\051; // wait for all I/O to complete) 165.84 358.86 T +162 81 540 517.71 C +0 0 612 792 C +162 81 540 517.71 C +162 166 540 277.43 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.63 166 542.37 277.43 R +7 X +0 0 0 1 0 0 0 K +V +166.44 168.14 542.15 270.28 R +0 X +V +0.5 H +2 Z +N +163.01 171.57 537.3 273 R +7 X +V +0 X +N +165.72 174.57 533.58 269.57 R +7 X +V +6 9 Q +0 X +(class cdevSystem) 165.72 263.57 T +({) 165.72 252.57 T +(public:) 165.72 241.57 T +(int) 183.72 230.57 T +(flush\050\051;) 205.32 230.57 T +(int) 183.72 219.57 T +(poll\050\051;) 205.32 219.57 T +(int) 183.72 208.57 T +(pend\050\051;) 205.32 208.57 T +(}) 165.72 197.57 T +162 81 540 517.71 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "6" 36 +%%Page: "7" 37 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 449.45 739 T +0 10 Q +(7) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +3 F +1.4 (pend) 180 713.33 P +0 F +1.4 (: Flush all pending output, and process all replies f) 202.24 713.33 P +1.4 (or the speci\336ed n) 436.88 713.33 P +1.4 (umber of) 517.14 713.33 P +0.18 (seconds) 180 701.33 P +0.18 (. If the time argument is omitted, w) 217.09 701.33 P +0.18 (ait until all replies ha) 371.05 701.33 P +0.18 (v) 462.16 701.33 P +0.18 (e been receiv) 466.91 701.33 P +0.18 (ed. If a) 527.06 701.33 P +(monitor oper) 180 689.33 T +(ation w) 236.03 689.33 T +(as star) 267.56 689.33 T +(ted, this w) 297.97 689.33 T +(aits f) 342.84 689.33 T +(or the connection \050\336rst callbac) 363.66 689.33 T +(k\051 only) 496.29 689.33 T +(.) 524.74 689.33 T +2 F +(Gr) 72 660.33 T +(oup Object) 83.47 660.33 T +0 F +2.11 (An alter) 180 660.33 P +2.11 (nativ) 216.82 660.33 P +2.11 (e mechanism f) 237.69 660.33 P +2.11 (or w) 306.62 660.33 P +2.11 (aiting f) 327.46 660.33 P +2.11 (or asychronous calls is through the use of) 358.73 660.33 P +0.79 (g) 180 648.33 P +0.79 (roups) 185.46 648.33 P +0.79 (. A g) 210.32 648.33 P +0.79 (roup k) 232.37 648.33 P +0.79 (eeps tr) 260.74 648.33 P +0.79 (ac) 292 648.33 P +0.79 (k off all I/O oper) 302.36 648.33 P +0.79 (ations star) 376 648.33 P +0.79 (ted from the time the g) 423.32 648.33 P +0.79 (roup is) 527.2 648.33 P +0.89 (star) 180 636.33 P +0.89 (ted until the g) 197.07 636.33 P +0.89 (roup is ended. Groups ma) 259.67 636.33 P +0.89 (y be nested or o) 378.53 636.33 P +0.89 (v) 453.64 636.33 P +0.89 (er) 458.39 636.33 P +0.89 (lapped, and suppor) 467.43 636.33 P +0.89 (t) 555.22 636.33 P +(the same \337ush/poll/pend oper) 180 624.33 T +(ations as the system object. F) 311.08 624.33 T +(or e) 443.06 624.33 T +(xample:) 459.99 624.33 T +3 9 Q +(Figure 8: Sample usage of the cde) 180 591 T +(vGroup object) 319.81 591 T +3 10 Q +0.06 (Note: Allo) 180 311.33 P +0.06 (wing nested or o) 223.26 311.33 P +0.06 (v) 296.66 311.33 P +0.06 (er) 301.41 311.33 P +0.06 (lapped g) 310.45 311.33 P +0.06 (roups allo) 348.77 311.33 P +0.06 (ws libr) 392.03 311.33 P +0.06 (ar) 420.32 311.33 P +0.06 (y calls to star) 429.51 311.33 P +0.06 (t or stop g) 488.44 311.33 P +0.06 (roups) 532.99 311.33 P +(without needing to kno) 180 299.33 T +(w if another g) 279.91 299.33 T +(roup is already activ) 339.84 299.33 T +(e) 428.51 299.33 T +(.) 433.92 299.33 T +0 F +1.84 (Groups ma) 180 282.33 P +1.84 (y be oper) 231 282.33 P +1.84 (ated in one of tw) 276.28 282.33 P +1.84 (o modes) 356.93 282.33 P +1.84 (. Immediate mode \050def) 396.98 282.33 P +1.84 (ault\051 causes) 502.25 282.33 P +2.84 (g) 180 270.33 P +2.84 (rouped oper) 185.46 270.33 P +2.84 (ations to be immediately e) 242.12 270.33 P +2.84 (x) 369.32 270.33 P +2.84 (ecuted, and the g) 374.02 270.33 P +2.84 (roup is just used f) 459.7 270.33 P +2.84 (or) 549.11 270.33 P +1.11 (completion synchronization. Def) 180 258.33 P +1.11 (erred mode causes messages to be held bac) 323.64 258.33 P +1.11 (k until) 530.77 258.33 P +0.12 (the g) 180 246.33 P +0.12 (roup is ended and the oper) 202.26 246.33 P +0.12 (ations are \337ushed. After the oper) 322.28 246.33 P +0.12 (ations are complete) 467.87 246.33 P +0.12 (,) 555.22 246.33 P +0.48 (he g) 180 234.33 P +0.48 (roup of oper) 199.84 234.33 P +0.48 (ations ma) 254.63 234.33 P +0.48 (y be \337ushed again \050without re-posting\051, allo) 298.16 234.33 P +0.48 (wing the g) 491.55 234.33 P +0.48 (roup) 537.99 234.33 P +(to function as a list manager/e) 180 222.33 T +(x) 313.1 222.33 T +(ecutor) 317.8 222.33 T +(.) 345.09 222.33 T +2 F +(Request Object) 72 193.33 T +0 F +0.47 (Occasionally) 180 193.33 P +0.47 (, an I/O oper) 235.68 193.33 P +0.47 (ation ma) 292.58 193.33 P +0.47 (y need to be repeated ma) 331.1 193.33 P +0.47 (y times) 447.11 193.33 P +0.47 (. In this case) 479.1 193.33 P +0.47 (, it is) 536.5 193.33 P +0.88 (not ef\336cient to parse the message each time to deter) 180 181.33 P +0.88 (mine which ser) 421.09 181.33 P +0.88 (v) 489.84 181.33 P +0.88 (er to use) 494.59 181.33 P +0.88 (. It is) 535.11 181.33 P +0.06 (possib) 180 169.33 P +0.06 (le to b) 208.7 169.33 P +0.06 (ypass this parsing b) 235.86 169.33 P +0.06 (y creating a request object. The request object is lik) 324.21 169.33 P +0.06 (e) 552.44 169.33 P +-0.03 (the de) 180 157.33 P +-0.03 (vice object, e) 207.47 157.33 P +-0.03 (xcept that the message str) 265.46 157.33 P +-0.03 (ing is speci\336ed at creation time) 382.75 157.33 P +-0.03 (, and the) 519.15 157.33 P +0.98 (request object is theref) 180 145.33 P +0.98 (ore speci\336c to the par) 283.8 145.33 P +0.98 (ticular under) 383.71 145.33 P +0.98 (lying ser) 439.86 145.33 P +0.98 (vice to which that) 478.36 145.33 P +(message m) 180 133.33 T +(ust be directed.) 231.58 133.33 T +1.29 (In the case of EPICS channel access) 180 116.33 P +1.29 (, the request object opens and maintains the) 352.15 116.33 P +1.02 (channel to the EPICS process v) 180 104.33 P +1.02 (ar) 326.02 104.33 P +1.02 (iab) 335.05 104.33 P +1.02 (le) 348.2 104.33 P +1.02 (. The request object is NO) 355.83 104.33 P +1.02 (T the same as an) 476.67 104.33 P +1.34 (EPICS channel, in that the request object binds a de) 180 92.33 P +1.34 (vice and a message) 423.59 92.33 P +1.34 (, and the) 516.39 92.33 P +180 219 558 667 C +180 342 558 588 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.52 342 560.48 588 R +7 X +0 0 0 1 0 0 0 K +V +184.55 345 560.27 580.86 R +0 X +V +0.5 H +2 Z +N +181.12 347.86 555.41 583.57 R +7 X +V +0 X +N +183.84 350.85 551.7 580.14 R +7 X +V +6 9 Q +0 X +(cdevGroup g1, g2;) 183.84 574.14 T +(...) 183.84 563.14 T +(g1.start\050\051;) 183.84 552.14 T +(mag1.sendCallback\050...\051;) 183.84 541.14 T +(mag2.sendCallback\050...\051;) 183.84 530.14 T +(g2.start\050\051;) 183.84 519.14 T +(bpm1.sendNoBlock\050...\051;) 183.84 508.14 T +(bpm2.sendNoBlock\050...\051;) 183.84 497.14 T +(g1.end\050\051;) 183.84 486.14 T +(mag3.sendCallback\050...\051;) 183.84 475.14 T +(bpm3.sendNoBlock\050...\051;) 183.84 464.14 T +(g2.end\050\051;) 183.84 453.14 T +(g1.pend\0504.0\051;) 183.84 442.14 T +(// at this point operations on mag1, mag2, bpm1, & bpm2 are done) 183.84 431.14 T +(// or have timed out \050error handling discussed later\051.) 183.84 420.14 T +(...) 183.84 409.14 T +(// mag3 and bpm3 may not be finished yet, pend on the second) 183.84 398.14 T +(// group to wait for their completion) 183.84 387.14 T +(g2.pend\050\051;) 183.84 376.14 T +180 219 558 667 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "7" 37 +%%Page: "8" 38 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 54 739 T +0 10 Q +(8) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 10 Q +1.04 (message implies a direction. If the message is considered to be of the f) 162 713.33 P +1.04 (or) 489.84 713.33 P +1.04 (m) 498.98 713.33 P +3 F +1.04 (v) 511.14 713.33 P +1.04 (erb) 515.89 713.33 P +0 F +1.04 ( +) 530.34 713.33 P +3 F +-0.16 (attr) 162 701.33 P +-0.16 (ib) 176.6 701.33 P +-0.16 (ute) 184.18 701.33 P +0 F +-0.16 (then the EPICS channel essentially binds de) 200.7 701.33 P +-0.16 (vice and attr) 396.21 701.33 P +-0.16 (ib) 450.52 701.33 P +-0.16 (ute b) 458.1 701.33 P +-0.16 (ut not v) 479.98 701.33 P +-0.16 (erb) 512.21 701.33 P +-0.16 (. In) 526.26 701.33 P +0.04 (some future release of CDEV) 162 689.33 P +0.04 (, a more channel lik) 290.98 689.33 P +0.04 (e object ma) 377.65 689.33 P +0.04 (y be included if there is a) 429.13 689.33 P +0.37 (demand f) 162 677.33 P +0.37 (or it. If tw) 203.76 677.33 P +0.37 (o cde) 245.32 677.33 P +0.37 (vRequestObjects ref) 269.85 677.33 P +0.37 (erence the same EPICS channel, only a) 360.5 677.33 P +(single channel access connection is estab) 162 665.33 T +(lished.) 348 665.33 T +1.56 (The f) 162 648.33 P +1.56 (ollo) 186.05 648.33 P +1.56 (wing code demonstr) 201.46 648.33 P +1.56 (ates sending a set of data v) 293.96 648.33 P +1.56 (alues to a single magnet) 425.37 648.33 P +(using a request object. Note that the send call omits the message argument:) 162 636.33 T +3 9 Q +(Figure 9: Sample usage of the cde) 162 620 T +(vRequestObject object) 301.81 620 T +0 10 Q +0.2 (In most cases) 162 457.05 P +0.2 (, the de) 223.94 457.05 P +0.2 (vice object will create the request object to perf) 257.39 457.05 P +0.2 (or) 466.54 457.05 P +0.2 (m a requested) 475.68 457.05 P +0.59 (I/O oper) 162 445.05 P +0.59 (ation. All 3 f) 198.62 445.05 P +0.59 (or) 252.35 445.05 P +0.59 (ms of send are suppor) 261.49 445.05 P +0.59 (ted b) 363.75 445.05 P +0.59 (y the request object, with a calling) 386.38 445.05 P +-0.25 (syntax identical to the de) 162 433.05 P +-0.25 (vice calls without the message argument. The interf) 270.76 433.05 P +-0.25 (ace to the) 496.58 433.05 P +(request object is giv) 162 421.05 T +(en belo) 250.12 421.05 T +(w:) 282.77 421.05 T +3 9 Q +(Figure 10: Str) 162 387.71 T +(ucture of the cde) 219.16 387.71 T +(vRequestObject object) 285.93 387.71 T +0 10 Q +0.13 (When an asynchronous oper) 162 214.05 P +0.13 (ation completes) 290.12 214.05 P +0.13 (, the rele) 360.12 214.05 P +0.13 (v) 398.99 214.05 P +0.13 (ant request object is passed to) 403.74 214.05 P +1.47 (the user\325) 162 202.05 P +1.47 (s callbac) 201.32 202.05 P +1.47 (k routine) 241.49 202.05 P +1.47 (. This allo) 281.16 202.05 P +1.47 (ws the user to e) 326.74 202.05 P +1.47 (xtr) 402.9 202.05 P +1.47 (act the message str) 413.91 202.05 P +1.47 (ing and) 505.73 202.05 P +(de) 162 190.05 T +(vice name from the request object if necessar) 172.82 190.05 T +(y or desired.) 374.87 190.05 T +2 F +(File Descriptor) 54 161.05 T +(s) 123.87 161.05 T +(and \322select\323) 54 149.05 T +0 F +0.4 (An alter) 162 161.05 P +0.4 (nativ) 197.11 161.05 P +0.4 (e mechanism f) 217.98 161.05 P +0.4 (or dealing with asynchronous oper) 283.49 161.05 P +0.4 (ations is to directly test) 437.26 161.05 P +3.76 (the \336le descr) 162 149.05 P +3.76 (iptors being used. This interf) 226.36 149.05 P +3.76 (ace is currently implemented in the) 366.7 149.05 P +(cde) 162 137.05 T +(vSystem class) 177.82 137.05 T +(. The per) 241.57 137.05 T +(tinent methods ha) 281.99 137.05 T +(v) 361.28 137.05 T +(e the f) 366.03 137.05 T +(ollo) 393.53 137.05 T +(wing f) 408.94 137.05 T +(or) 434.76 137.05 T +(m:) 443.9 137.05 T +162 186.71 540 720 C +162 487.71 540 617 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.72 487.71 542.28 617 R +7 X +0 0 0 1 0 0 0 K +V +166.35 490.57 542.07 609.86 R +0 X +V +0.5 H +2 Z +N +162.92 494.71 537.21 612.57 R +7 X +V +0 X +N +165.64 497.71 533.49 609.14 R +7 X +V +6 9 Q +0 X +(cdevRequestObject& mag1BDL =) 165.64 603.14 T +(cdevRequestObject::attachRef\050\322mag1\323,\323set BDL\323\051;) 183.64 592.14 T +(cdevData mydata;) 165.64 581.14 T +(...) 165.64 570.14 T +(for \050i=0;i<100;i++\051) 165.64 559.14 T +({) 183.64 548.14 T +(mydata = i*10; // 10 amp steps) 183.64 537.14 T +(mag1BDL.send\050mydata,NULL\051; // ignore errors for now) 183.64 526.14 T +(sleep\0501\051;) 183.64 515.14 T +(}) 183.64 504.14 T +162 186.71 540 720 C +0 0 612 792 C +162 186.71 540 720 C +162 244.71 540 384.71 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.63 244.71 542.37 384.71 R +7 X +0 0 0 1 0 0 0 K +V +166.44 247.57 542.15 377.57 R +0 X +V +0.5 H +2 Z +N +163.01 251 537.3 380.29 R +7 X +V +0 X +N +165.72 254 533.58 376.86 R +7 X +V +6 9 Q +0 X +(class cdevRequestObject) 165.72 370.86 T +({) 165.72 359.86 T +(public:) 165.72 348.86 T +(char* message\050\051; // returns the message string) 183.72 337.86 T +(cdevDevice& device\050\051; // returns the device object) 183.72 326.86 T +(int state\050\051; // connected/disconnected/) 183.72 315.86 T +(int access\050\051; // read/write/none) 183.72 304.86 T +(int send\050cdevData& out, cdevData& result\051;) 183.72 293.86 T +(int sendNoBlock\050cdevData& out, cdevData& result\051;) 183.72 282.86 T +(int sendCallback\050cdevData& out, cdevCallback callback\051;) 183.72 271.86 T +(}) 165.72 260.86 T +162 186.71 540 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "8" 38 +%%Page: "9" 39 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 449.45 739 T +0 10 Q +(9) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +3 9 Q +(Figure 11: File descr) 180 714 T +(iptor routines of the cde) 264.66 714 T +(vSystem object) 358.44 714 T +0 10 Q +1.42 (The getFd method will populate a user allocated arr) 180 559.58 P +1.42 (a) 419.16 559.58 P +1.42 (y of integers \050fd\051 with the \336le) 424.42 559.58 P +0.36 (descr) 180 547.58 P +0.36 (iptors currently in use b) 204.6 547.58 P +0.36 (y the cde) 309.19 547.58 P +0.36 (vSystem object. The n) 350.18 547.58 P +0.36 (umber of \336le descr) 450.08 547.58 P +0.36 (iptors) 533.55 547.58 P +0.5 (that w) 180 535.58 P +0.5 (ere allocated b) 207.08 535.58 P +0.5 (y the user is speci\336ed in the n) 273.46 535.58 P +0.5 (umFD v) 408.58 535.58 P +0.5 (ar) 443.82 535.58 P +0.5 (iab) 452.86 535.58 P +0.5 (le) 466 535.58 P +0.5 (. Upon completion,) 473.63 535.58 P +-0.19 (the n) 180 523.58 P +-0.19 (umFD v) 201.95 523.58 P +-0.19 (ar) 236.5 523.58 P +-0.19 (iab) 245.54 523.58 P +-0.19 (le will be set to the n) 258.68 523.58 P +-0.19 (umber of \336le descr) 348.01 523.58 P +-0.19 (iptors actually copied into the) 429.83 523.58 P +0.52 (fd arr) 180 511.58 P +0.52 (a) 203.76 511.58 P +0.52 (y) 209.02 511.58 P +0.52 (. An error is retur) 213.02 511.58 P +0.52 (ned if the b) 290.39 511.58 P +0.52 (uff) 341.25 511.58 P +0.52 (er is not suf\336cient to store the complete set of) 352.07 511.58 P +(\336le descr) 180 499.58 T +(iptors) 220.16 499.58 T +(.) 244.46 499.58 T +0.03 (The addFdChangedCallbac) 180 482.58 P +0.03 (k method allo) 302.11 482.58 P +0.03 (ws the user to specify a function to be called) 361.5 482.58 P +(each time a \336le descr) 180 470.58 T +(iptor is added \050opened=1\051 or closed \050opened=0\051.) 274.63 470.58 T +(The f) 180 453.58 T +(ollo) 202.49 453.58 T +(wing code illustr) 217.9 453.58 T +(ates the usage of the UNIX select call:) 288.93 453.58 T +180 81 558 720 C +180 573.25 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.52 573.25 560.48 711 R +7 X +0 0 0 1 0 0 0 K +V +183.3 584.54 559.02 705.11 R +0 X +V +0.5 H +2 Z +N +181.75 588.29 556.04 707.82 R +7 X +V +0 X +N +183.84 596.53 551.7 703.14 R +7 X +V +6 9 Q +0 X +(typedef void \050*cdevFdChangedCallback\051\050int fd, int opened,) 183.84 697.14 T +( void* userarg\051) 255.84 686.14 T +(class cdevSystem) 183.84 675.14 T +({) 183.84 664.14 T +(public:) 183.84 653.14 T +(...) 201.84 642.14 T +(int getFd\050int fd[], int &numFD\051;) 201.84 631.14 T +(int addFdChangedCallback\050cdevFdChangedCallback cbk, void* arg\051;) 201.84 620.14 T +(}) 183.84 609.14 T +180 81 558 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "9" 39 +%%Page: "10" 40 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 54 739 T +0 10 Q +(10) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +3 F +(Figure 12: Using CDEV \336le descr) 162 714 T +(iptors with the UNIX select function) 296.68 714 T +162 81 540 720 C +162 213.85 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.57 213.85 542.43 711 R +7 X +0 0 0 1 0 0 0 K +V +166.5 216.71 542.22 703.86 R +0 X +V +0.5 H +2 Z +N +163.07 220.14 537.36 706.57 R +7 X +V +0 X +N +165.79 223.14 533.65 703.14 R +7 X +V +6 9 Q +0 X +(int myFD[5];) 165.79 697.14 T +(void mySelectLoop \050 cdevSystem & system \051) 165.79 675.14 T +({) 183.79 664.14 T +(int fd[20];) 183.79 653.14 T +(int numFD = 15, nfds;) 183.79 642.14 T +(fd_set rfds; // Ready file descriptors) 183.79 631.14 T +(fd_set afds; // Active file descriptors) 183.79 620.14 T +(// Copy the file descriptors I am already using to the list) 183.79 598.14 T +(memcpy\050fd, myFD, sizeof\050myFD\051\051;) 183.79 587.14 T +(// Get the file descriptors in use by the cdevSystem object) 183.79 565.14 T +(system.getFd\050&fd[5], numFD\051;) 183.79 554.14 T +(// Add in the 5 previously defined file descriptors) 183.79 532.14 T +(numFD += 5;) 183.79 521.14 T +(// Zero the active file descriptors) 183.79 499.14 T +(FD_ZERO\050&afds\051;) 183.79 488.14 T +(// Setup the active file descriptors) 183.79 466.14 T +(for\050int i=0; i\323 into which the de) 242.31 244.91 T +(vice name will be substituted.) 354.29 244.91 T +-0.15 (Example: Suppose there are a set of magnets f) 180 227.91 P +-0.15 (or which it is possib) 387.51 227.91 P +-0.15 (le to read and wr) 473.4 227.91 P +-0.15 (ite) 547.44 227.91 P +0.46 (bdl \050integ) 180 215.91 P +0.46 (r) 221.49 215.91 P +0.46 (al \336eld\051, and current \050amps\051. That is) 224.72 215.91 P +0.46 (, the messages \322get bdl\323, \322get current\323,) 385.17 215.91 P +0.32 (\322set bdl\323, etc. are v) 180 203.91 P +0.32 (alid. Also) 263.86 203.91 P +0.32 (, each magnet responds to the commands \322on\323 and \322off) 304.36 203.91 P +0.32 (\323.) 551.89 203.91 P +-0.22 (Fur) 180 191.91 P +-0.22 (ther suppose that the beamline position and length of the magnet are a) 195.4 191.91 P +-0.22 (v) 506.09 191.91 P +-0.22 (ailab) 510.84 191.91 P +-0.22 (le in a) 531.76 191.91 P +(static database \050assume read/wr) 180 179.91 T +(ite\051.) 324.65 179.91 T +180 557.57 558 720 C +180 603.57 558 665 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +178.64 603.57 559.36 665 R +7 X +0 0 0 1 0 0 0 K +V +183.43 606.43 559.15 657.86 R +0 X +V +0.5 H +2 Z +N +180 609.86 554.29 660.57 R +7 X +V +0 X +N +182.71 613.57 550.57 657.14 R +7 X +V +6 9 Q +0 X +(service ca) 182.71 651.14 T +({) 200.71 640.14 T +(tags {pv, default}) 200.71 629.14 T +(}) 200.71 618.14 T +180 557.57 558 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "15" 45 +%%Page: "16" 46 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Name Resolution) 54 739 T +0 10 Q +(16) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 10 Q +(Here is a complete class de\336nition:) 162 713.33 T +3 9 Q +(Figure 21: Sample inher) 162 680 T +(ited class de\336nition) 260.68 680 T +0 10 Q +0.68 (Note the semicolon at the end of each line of attr) 162 406.33 P +0.68 (ib) 384.02 406.33 P +0.68 (utes or messages \050e) 391.6 406.33 P +0.68 (xcept f) 483.92 406.33 P +0.68 (or the) 513.75 406.33 P +0.36 (last line\051. Note also that the process v) 162 394.33 P +0.36 (ar) 330.99 394.33 P +0.36 (iab) 340.03 394.33 P +0.36 (le name has a place holder into which the) 353.17 394.33 P +0.17 (de) 162 382.33 P +0.17 (vice name will be substituted. More sophisticated name mangling is en) 172.82 382.33 P +0.17 (visaged, b) 486.11 382.33 P +0.17 (ut) 531.66 382.33 P +(not f) 162 370.33 T +(or this release) 181.16 370.33 T +(. Syntax is still open to re) 243.81 370.33 T +(vision.) 354.67 370.33 T +2 F +(Instance De\336nition) 54 341.33 T +0 F +1.8 (Instances of a class are giv) 162 341.33 P +1.8 (en b) 291.39 341.33 P +1.8 (y f) 312.45 341.33 P +1.8 (ollo) 324.52 341.33 P +1.8 (wing the class name with a list of instance) 339.93 341.33 P +4.03 (names) 162 329.33 P +4.03 (. De) 191.86 329.33 P +4.03 (vice names ma) 213.93 329.33 P +4.03 (y be separ) 288.92 329.33 P +4.03 (ated b) 343.56 329.33 P +4.03 (y whitespace char) 375.19 329.33 P +4.03 (acters \050including) 463.17 329.33 P +(ne) 162 317.33 T +(wline\051 or b) 172.92 317.33 T +(y commas) 218.84 317.33 T +(.) 264.25 317.33 T +3 9 Q +(Figure 22: Multiple instances of the magnet class) 162 284 T +0 10 Q +1.2 (Combined with the pre) 162 223.19 P +1.2 (vious de\336nition, the message \322on\323 sent to magnet m2 w) 265.33 223.19 P +1.2 (ould) 521.1 223.19 P +(select the process v) 162 211.19 T +(ar) 250.12 211.19 T +(iab) 259.16 211.19 T +(le \322m2CSR.v) 272.3 211.19 T +(al\323 with \3221\323 as the v) 328.72 211.19 T +(alue to wr) 412.94 211.19 T +(ite) 456.44 211.19 T +(.) 466.85 211.19 T +2 F +(Aliases) 54 182.19 T +0 F +1.39 (Sometimes it is con) 162 182.19 P +1.39 (v) 252.67 182.19 P +1.39 (enient to ref) 257.42 182.19 P +1.39 (er to a de) 312.72 182.19 P +1.39 (vice b) 358.85 182.19 P +1.39 (y more than one name) 386.17 182.19 P +1.39 (. The DDL) 491.64 182.19 P +(syntax suppor) 162 170.19 T +(ts simple aliases) 224.65 170.19 T +(, one per line) 297.85 170.19 T +(.) 355.51 170.19 T +3 9 Q +(Figure 23: Alias de) 162 136.86 T +(vice name) 239.26 136.86 T +162 367 540 720 C +162 437 540 677 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.93 437 542.07 677 R +7 X +0 0 0 1 0 0 0 K +V +166.14 439.85 541.86 669.86 R +0 X +V +0.5 H +2 Z +N +162.71 444 537 672.57 R +7 X +V +0 X +N +165.43 447.71 533.29 669.14 R +7 X +V +6 9 Q +0 X +(class stdio) 165.43 663.14 T +({) 183.43 652.14 T +(verbs {get, set, monitorOn, monitorOff}) 183.43 641.14 T +(}) 183.43 630.14 T +(class magnet : stdio) 165.43 608.14 T +({) 183.43 597.14 T +(attributes) 183.43 586.14 T +({) 201.43 575.14 T +(bdl) 201.43 564.14 T +(ca {pv=<>.bdl};) 223.03 564.14 T +(current ca {pv=<>.val};) 201.43 553.14 T +(zpos) 201.43 542.14 T +( os {path=<>/phy/z};) 223.03 542.14 T +(length) 201.43 531.14 T +( os {path=<>/phy/len}) 233.83 531.14 T +(}) 201.43 520.14 T +(messages) 183.43 509.14 T +({) 201.43 498.14 T +(on) 201.43 487.14 T +(ca {pv=<>CSR.val, default=1};) 219.43 487.14 T +(off) 201.43 476.14 T +(ca {pv=<>CSR.val, default=0};) 224.83 476.14 T +(}) 201.43 465.14 T +(}) 183.43 454.14 T +162 367 540 720 C +0 0 612 792 C +162 207.86 540 348 C +162 253.86 540 281 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +160.29 253.86 541.71 281 R +7 X +0 0 0 1 0 0 0 K +V +165.79 256 541.5 273.85 R +0 X +V +0.5 H +2 Z +N +162.36 259.43 536.65 276.57 R +7 X +V +0 X +N +165.07 263.14 532.93 273.14 R +7 X +V +6 9 Q +0 X +(magnet : m1 m2 m3;) 165.07 267.14 T +162 207.86 540 348 C +0 0 612 792 C +162 81 540 188.86 C +162 106.71 540 133.86 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +160.29 106.71 541.71 133.86 R +7 X +0 0 0 1 0 0 0 K +V +165.79 108.86 541.5 126.71 R +0 X +V +0.5 H +2 Z +N +162.36 112.28 536.65 129.43 R +7 X +V +0 X +N +165.07 116 532.93 126 R +7 X +V +6 9 Q +0 X +(alias myname m1) 165.07 120 T +162 81 540 188.86 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "16" 46 +%%Page: "17" 47 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Name Resolution) 478.97 739 T +0 10 Q +(17) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "17" 47 +%%Page: "18" 48 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Channel Access Service) 54 739 T +0 10 Q +(18) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(6.) 141.32 710.67 T +(Channel Access Ser) 162 710.67 T +(vice) 296.75 710.67 T +0 10 Q +(EPICS / Channel Access v) 162 684.33 T +(ersion 3.12 is recommended.) 280.13 684.33 T +(F) 162 667.33 T +(eatures:) 167.81 667.33 T +(\245) 180 650.33 T +(Suppor) 189 650.33 T +(ts synchronous and asynchronous send\325) 221.64 650.33 T +(s) 399.56 650.33 T +(.) 404.41 650.33 T +(\245) 180 636.33 T +(T) 189 636.33 T +(r) 193.91 636.33 T +(ac) 197.14 636.33 T +(ks \336le descr) 207.5 636.33 T +(iptor registr) 260.44 636.33 T +(ation.) 310.35 636.33 T +(\245) 180 622.33 T +(F) 189 622.33 T +(etches data in nativ) 194.81 622.33 T +(e type \050type con) 280.72 622.33 T +(v) 351.67 622.33 T +(ersion done on client and not ser) 356.42 622.33 T +(v) 501.8 622.33 T +(er\051.) 506.55 622.33 T +(\245) 180 608.33 T +1.96 (Pro) 189 608.33 P +1.96 (vides a def) 204.41 608.33 P +1.96 (ault name ser) 256.38 608.33 P +1.96 (vice so that if a de) 321.18 608.33 P +1.96 (vice is not de\336ned, then an) 411.26 608.33 P +0.13 (EPICS channel access connection is attempted with the record name set equal) 189 596.33 P +(to the de) 189 584.33 T +(vice name) 227.62 584.33 T +(, and the \336eld name set equal to the attr) 273.04 584.33 T +(ib) 449.41 584.33 T +(ute name) 456.99 584.33 T +(.) 498.53 584.33 T +(Restr) 162 567.33 T +(ictions:) 186.04 567.33 T +(\245) 180 550.33 T +2.52 (Only suppor) 189 550.33 P +2.52 (ts set/get/monitorOn/monitorOff v) 245.83 550.33 P +2.52 (erbs and the pv and readonly) 397.89 550.33 P +-0.27 (tags) 189 538.33 P +-0.27 (. Suppor) 207.75 538.33 P +-0.27 (t f) 245.68 538.33 P +-0.27 (or arbitr) 253.44 538.33 P +-0.27 (ar) 287.52 538.33 P +-0.27 (y messages with def) 296.71 538.33 P +-0.27 (ault data will be in the ne) 386.18 538.33 P +-0.27 (xt release) 494.29 538.33 P +-0.27 (.) 537.22 538.33 P +(\245) 180 524.33 T +(Discards all e) 189 524.33 T +(xception callbac) 248.71 524.33 T +(ks from channel access in this v) 319.65 524.33 T +(ersion.) 460.56 524.33 T +(\245) 180 510.33 T +(Channel access secur) 189 510.33 T +(ity is not suppor) 287.52 510.33 T +(ted in this release) 357.95 510.33 T +(.) 436.17 510.33 T +(Compilation options:) 162 493.33 T +(\245) 180 476.33 T +3.21 (_CA_SYNC_CONN = perf) 189 476.33 P +3.21 (or) 311.54 476.33 P +3.21 (m connections synchronously) 320.68 476.33 P +3.21 (, w) 457.27 476.33 P +3.21 (aiting up to 4) 473.11 476.33 P +(seconds) 189 464.33 T +(.) 226.09 464.33 T +(\245) 180 450.33 T +(_CDEV_DEB) 189 450.33 T +(UG = pr) 248.36 450.33 T +(int v) 283.8 450.33 T +(erbose messages) 301.89 450.33 T +(\245) 180 436.33 T +(_EPICS_3_12 = if not de\336ned, use 3.11 calls instead.) 189 436.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "18" 48 +%%Page: "i" 49 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(i) 555.78 57 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 720 558 720 2 L +0.5 H +2 Z +N +72 72 558 72 2 L +N +72 504 558 504 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 32 Q +(Introduction to CDEV) 180 662.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 12 Q +(Over) 180 638 T +(vie) 207.47 638 T +(w of the Contr) 223.97 638 T +(ol De) 304.39 638 T +(vice Interface) 333.55 638 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(Chip W) 180 610 T +(atson, Jie Chen, Danjin W) 218.86 610 T +(u, W) 357.22 610 T +(alt Ak) 381.41 610 T +(ers) 411.18 610 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 180 582 T +(ersion 1.5 December 9, 1996) 187.04 582 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(TJNAF - Thomas Jeff) 180 554 T +(erson National Acceler) 293.66 554 T +(ator F) 414.25 554 T +(acility) 445 554 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "i" 49 +%%Page: "ii" 50 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(ii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(TRADEMARKS:) 54 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(UNIX is a registered tr) 180 569.33 T +(ademar) 278.26 569.33 T +(k of A) 312.31 569.33 T +(T&T in the USA and other countr) 336.68 569.33 T +(ies) 481.9 569.33 T +(.) 494.53 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(VxW) 180 545.33 T +(or) 200.81 545.33 T +(ks is a register tr) 209.85 545.33 T +(ademar) 283.1 545.33 T +(k of Wind Riv) 317.15 545.33 T +(er Systems) 375.8 545.33 T +(.) 425.66 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The X Windo) 180 521.33 T +(w System is a tr) 237.65 521.33 T +(ademar) 308.12 521.33 T +(k of Massachusetts Institute of T) 342.17 521.33 T +(echnology) 484.37 521.33 T +(.) 528.95 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(OSF/Motif and Motif are tr) 180 497.33 T +(ademar) 294.94 497.33 T +(ks of Open Softw) 328.99 497.33 T +(are F) 404.99 497.33 T +(oundation, Inc.) 428.03 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ultr) 180 473.33 T +(ix and DEC are registered tr) 195.7 473.33 T +(ademar) 319.53 473.33 T +(ks of Digital Equipment Cor) 353.58 473.33 T +(por) 475.03 473.33 T +(ation.) 489.38 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(HPUX is a registered tr) 180 449.33 T +(ademar) 282.15 449.33 T +(k of He) 316.2 449.33 T +(wlett P) 347.68 449.33 T +(ac) 377.29 449.33 T +(kard.) 387.65 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(SURA/CEB) 54 344.33 T +(AF:) 105.92 344.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.44 (The Southeaster) 180 344.33 P +4.44 (n Univ) 258.62 344.33 P +4.44 (ersities Research Association \050SURA\051 oper) 291.15 344.33 P +4.44 (ates the) 499.98 344.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.01 (Contin) 180 332.33 P +2.01 (uous Electron Beam Acceler) 208.8 332.33 P +2.01 (ator F) 340.89 332.33 P +2.01 (acility \050CEBAF\051 f) 368.52 332.33 P +2.01 (or the United States) 445.59 332.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Depar) 180 320.33 T +(tment of Energy under contr) 207.63 320.33 T +(act DE-A) 331.48 320.33 T +(C05-84ER40150.) 371.19 320.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DISCLAIMER:) 54 218.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.49 (This repor) 180 218.33 P +0.49 (t w) 225.9 218.33 P +0.49 (as prepared as an account of w) 239.02 218.33 P +0.49 (or) 381.4 218.33 P +0.49 (k sponsored b) 390.44 218.33 P +0.49 (y the United States) 454.03 218.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.18 (go) 180 206.33 P +2.18 (v) 190.97 206.33 P +2.18 (er) 195.72 206.33 P +2.18 (nment. Neither the United States nor the United States Depar) 204.86 206.33 P +2.18 (tment of) 501.68 206.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.04 (Energy) 180 194.33 P +1.04 (, nor an) 210.68 194.33 P +1.04 (y of their emplo) 246.52 194.33 P +1.04 (y) 317.69 194.33 P +1.04 (ees) 322.49 194.33 P +1.04 (, mak) 338.46 194.33 P +1.04 (es an) 363.75 194.33 P +1.04 (y w) 389.1 194.33 P +1.04 (arr) 404.99 194.33 P +1.04 (anty) 417.11 194.33 P +1.04 (, e) 435.01 194.33 P +1.04 (xpress or implied, or) 446.86 194.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.83 (assumes an) 180 182.33 P +1.83 (y legal liability or responsibility f) 235.59 182.33 P +1.83 (or the accur) 383.89 182.33 P +1.83 (acy) 440.24 182.33 P +1.83 (, completeness) 454.8 182.33 P +1.83 (, or) 523.72 182.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.68 (usefulness of an) 180 170.33 P +3.68 (y inf) 260.02 170.33 P +3.68 (or) 281.74 170.33 P +3.68 (mation, appar) 290.88 170.33 P +3.68 (atus) 355.59 170.33 P +3.68 (, product or process disclosed, or) 374.34 170.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.46 (represents that its use w) 180 158.33 P +2.46 (ould not infr) 298.11 158.33 P +2.46 (inge pr) 355.42 158.33 P +2.46 (iv) 388.59 158.33 P +2.46 (ately o) 395.56 158.33 P +2.46 (wned r) 427.33 158.33 P +2.46 (ights) 459.95 158.33 P +2.46 (. Ref) 480.92 158.33 P +2.46 (erence) 509.43 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.6 (herein to an) 180 146.33 P +1.6 (y speci\336c commercial product, process) 235.85 146.33 P +1.6 (, or ser) 413.79 146.33 P +1.6 (vice b) 448.4 146.33 P +1.6 (y tr) 475.92 146.33 P +1.6 (ade name) 491.3 146.33 P +1.6 (,) 537.22 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (mar) 180 134.33 P +2.12 (k, man) 197.37 134.33 P +2.12 (uf) 229.4 134.33 P +2.12 (acturer) 237.44 134.33 P +2.12 (, or otherwise) 268.06 134.33 P +2.12 (, does not necessar) 332.17 134.33 P +2.12 (ily constitute or imply its) 425.94 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (endorsement, recommendation, or f) 180 122.33 P +1.08 (a) 341.33 122.33 P +1.08 (v) 346.69 122.33 P +1.08 (or) 351.44 122.33 P +1.08 (ing b) 360.48 122.33 P +1.08 (y the United States go) 383.03 122.33 P +1.08 (v) 485.57 122.33 P +1.08 (er) 490.32 122.33 P +1.08 (nment or) 499.46 122.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (an) 180 110.33 P +0.83 (y agency thereof) 190.97 110.33 P +0.83 (. The vie) 266.26 110.33 P +0.83 (w and opinions of the authors e) 309.67 110.33 P +0.83 (xpressed herein do) 453.3 110.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.94 (not necessar) 180 98.33 P +1.94 (ily state or re\337ect those of the United States go) 239.34 98.33 P +1.94 (v) 464.01 98.33 P +1.94 (er) 468.76 98.33 P +1.94 (nment or an) 477.9 98.33 P +1.94 (y) 535 98.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(agency thereof) 180 86.33 T +(.) 245.85 86.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DOCUMENT D) 54 668.33 T +(A) 121.37 668.33 T +(TE:) 127.69 668.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(T) 180 668.33 T +(ab) 184.91 668.33 T +(le of ontents gener) 195.83 668.33 T +(ated: December 9, 1996 11:45 am) 278.56 668.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "ii" 50 +%%Page: "iii" 51 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iii) 551.34 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(T) 180 710.67 T +(ab) 187.43 710.67 T +(le of Contents) 203.63 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(List of Figures) 198 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(v) 553 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 180 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Introduction) 198 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 252.98 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(What is CDEV) 198 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(La) 198 648.33 T +(y) 208.82 648.33 T +(er) 213.62 648.33 T +(ing and Abstr) 222.66 648.33 T +(action) 281.48 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Inf) 198 636.33 T +(or) 208.82 636.33 T +(mation Hiding) 217.96 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198 624.33 T +(vice Object) 210.48 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Standard Messages) 198 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 289.12 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data Object) 198 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 252.98 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 180 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Basic Oper) 198 588.33 T +(ations on De) 247.36 588.33 T +(vices and Data) 303.2 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 369.74 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 180 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Asychronous Oper) 198 576.33 T +(ations) 280.71 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Callbac) 198 564.33 T +(k Object) 231.14 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(System Object) 198 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Group Object) 198 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Request Object) 198 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(File Descr) 198 516.33 T +(iptors and \322select\323) 243.15 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 325.26 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 180 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Error Handling) 198 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 180 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name Resolution) 198 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 198 480.33 T +(vDirector) 213.82 480.33 T +(y Object) 254.12 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ser) 198 468.33 T +(vice De\336nition) 213.86 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 546.88 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198 456.33 T +(vice Class De\336nition) 210.48 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 303.02 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15) 546.88 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Instance De\336nition) 198 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Aliases) 198 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 230.74 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 180 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Channel Access Ser) 198 420.33 T +(vice) 288.89 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 546.88 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iii" 51 +%%Page: "iv" 52 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iv) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iv" 52 +%%Page: "v" 53 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +( List of Figures) 498.98 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(v) 553 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(List of Figures) 180 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(Figure 1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample usage of the send method of a cdevDevice) 234 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(................................) 461.48 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 2.) 180 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Overview of cdevData operations) 234 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(............................................................) 383.64 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 3.) 180 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Three forms of the send command) 234 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..........................................................) 389.2 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 4.) 180 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Overview of the cdevCallback object and the cdevCallbackFunction) 234 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(......) 533.76 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 5.) 180 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Structure of the cdevCallback object) 234 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................................................) 394.76 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 6.) 180 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Usage of the pend method in the cdevSystem object) 234 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..............................) 467.04 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 7.) 180 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Synchronization methods in the cdevSystem object) 234 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(................................) 461.48 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 8.) 180 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample usage of the cdevGroup object) 234 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................................) 408.66 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 9.) 180 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample usage of the cdevRequestObject object) 234 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.....................................) 447.58 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 10.) 180 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Structure of the cdevRequestObject object) 234 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..............................................) 422.56 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 11.) 180 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(File descriptor routines of the cdevSystem object) 234 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(....................................) 450.36 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 12.) 180 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using CDEV file descriptors with the UNIX select function) 234 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(....................) 489.28 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 13.) 180 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Error handling mechanisms provided by the cdevSystem object) 234 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........) 514.3 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 14.) 180 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Enumerated severity codes generated by CDEV) 234 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................) 447.58 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 15.) 180 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Enumerated error codes generated by CDEV) 234 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................................) 433.68 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 546.88 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 16.) 180 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Obtaining a reference to the cdevDirectory device) 234 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(................................) 455.92 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 17.) 180 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Virtual form of the data in a cdevDirectory) 234 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.............................................) 419.78 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 18.) 180 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Syntax of the #include directive) 234 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..............................................................) 372.52 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 546.88 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 19.) 180 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample service definition) 234 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................................................................) 347.5 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 546.88 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 20.) 180 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample service definition) 234 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................................................................) 347.5 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15) 546.88 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 21.) 180 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample inherited class definition) 234 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(............................................................) 378.08 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 22.) 180 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Multiple instances of the magnet class) 234 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................................) 403.1 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 23.) 180 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Alias device name) 234 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..................................................................................) 316.92 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "v" 53 +%%Page: "vi" 54 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +( List of Figures) 54 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(vi) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "vi" 54 +%%Page: "1" 55 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. Introduction) 500.97 739 T +0 10 Q +(1) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(1.) 159.32 710.67 T +(Intr) 180 710.67 T +(oduction) 202.27 710.67 T +2 10 Q +(What is CDEV) 72 673.33 T +0 F +1.09 (The CDEV \050common de) 180 673.33 P +1.09 (vice\051 C++ class libr) 289.11 673.33 P +1.09 (ar) 376.73 673.33 P +1.09 (y is an object-or) 385.92 673.33 P +1.09 (iented fr) 459.92 673.33 P +1.09 (ame) 497.04 673.33 P +1.09 (w) 516.29 673.33 P +1.09 (or) 523.41 673.33 P +1.09 (k that) 532.45 673.33 P +1.76 (pro) 180 661.33 P +1.76 (vides a standard interf) 194.3 661.33 P +1.76 (ace betw) 297.65 661.33 P +1.76 (een an application and one or more under) 339.33 661.33 P +1.76 (lying) 537.44 661.33 P +4.52 (control pac) 180 649.33 P +4.52 (kages or systems) 233.23 649.33 P +4.52 (. Each under) 319.92 649.33 P +4.52 (lying pac) 385.81 649.33 P +4.52 (kage \050called a ser) 429.59 649.33 P +4.52 (vice\051 is) 522.37 649.33 P +1.18 (dynamically loaded at r) 180 637.33 P +1.18 (un-time) 285.96 637.33 P +1.18 (, allo) 319.15 637.33 P +1.18 (wing an application to access a ne) 341.31 637.33 P +1.18 (w ser) 500.52 637.33 P +1.18 (vice b) 525.9 637.33 P +1.18 (y) 553 637.33 P +-0.09 (name without re-compilation or re-linking. A major f) 180 625.33 P +-0.09 (eature of CDEV is its ability to hide) 404.68 625.33 P +2.93 (the implementation details of a par) 180 613.33 P +2.93 (ticular de) 347.88 613.33 P +2.93 (vice from the high le) 391.08 613.33 P +2.93 (v) 491.96 613.33 P +2.93 (el application) 496.71 613.33 P +0.07 (de) 180 601.33 P +0.07 (v) 190.82 601.33 P +0.07 (eloper) 195.57 601.33 P +0.07 (. This allo) 222.86 601.33 P +0.07 (ws ser) 265.63 601.33 P +0.07 (v) 294.89 601.33 P +0.07 (er implementation choices to be changed without breaking) 299.64 601.33 P +0.9 (high le) 180 589.33 P +0.9 (v) 210.06 589.33 P +0.9 (el client applications) 214.81 589.33 P +0.9 (. Additionally) 305.93 589.33 P +0.9 (, because the application is una) 362.52 589.33 P +0.9 (w) 506.89 589.33 P +0.9 (are of the) 513.96 589.33 P +4.86 (under) 180 577.33 P +4.86 (lying ser) 205.72 577.33 P +4.86 (vice\325) 248.11 577.33 P +4.86 (s speci\336c implementation, CDEV is a po) 267.61 577.33 P +4.86 (w) 473.91 577.33 P +4.86 (erful v) 481.03 577.33 P +4.86 (ehicle f) 512.87 577.33 P +4.86 (or) 549.11 577.33 P +(de) 180 565.33 T +(v) 190.82 565.33 T +(eloping por) 195.57 565.33 T +(tab) 245.44 565.33 T +(le applications) 259.14 565.33 T +(.) 322.35 565.33 T +-0.25 (The basic CDEV interf) 180 548.33 P +-0.25 (ace can be descr) 277.88 548.33 P +-0.25 (ibed through a) 353.43 548.33 P +3 F +-0.25 (de) 419.4 548.33 P +-0.25 (vice) 430.22 548.33 P +0 F +-0.25 (/) 448 548.33 P +3 F +-0.25 (message) 450.78 548.33 P +0 F +-0.25 ( par) 491.35 548.33 P +-0.25 (adigm. The) 508.23 548.33 P +3 F +2.36 (de) 180 536.33 P +2.36 (vice) 190.82 536.33 P +0 F +2.36 ( is not necessar) 208.6 536.33 P +2.36 (ily a ph) 285.85 536.33 P +2.36 (ysical object, r) 321.94 536.33 P +2.36 (ather) 389.9 536.33 P +2.36 (, it is a cde) 412.19 536.33 P +2.36 (vDe) 469.11 536.33 P +2.36 (vice object that) 486.59 536.33 P +1.42 (pro) 180 524.33 P +1.42 (vides a standard interf) 194.3 524.33 P +1.42 (ace to CDEV) 296.64 524.33 P +1.42 (. The application uses this interf) 356.03 524.33 P +1.42 (ace to send) 503.46 524.33 P +4.12 (messages to the de) 180 512.33 P +4.12 (vice) 279.32 512.33 P +4.12 (. When the cde) 296.95 512.33 P +4.12 (vDe) 376.26 512.33 P +4.12 (vice receiv) 393.74 512.33 P +4.12 (es this message it will) 444.84 512.33 P +1.36 (dynamically load the appropr) 180 500.33 P +1.36 (iate ser) 312.05 500.33 P +1.36 (vice \050as de\336ned in the CDEV de) 346.49 500.33 P +1.36 (vice de\336nition) 496.06 500.33 P +2.96 (\336le\051, and f) 180 488.33 P +2.96 (orw) 229.54 488.33 P +2.96 (ard the message to it. The ser) 245.49 488.33 P +2.96 (vice ma) 396.41 488.33 P +2.96 (y then perf) 433.52 488.33 P +2.96 (or) 486.39 488.33 P +2.96 (m an) 495.54 488.33 P +2.96 (y action) 520.58 488.33 P +(necessar) 180 476.33 T +(y to satisfy the application\325) 220.87 476.33 T +(s request.) 337.09 476.33 T +0.13 (The CDEV API is optimiz) 180 459.33 P +0.13 (ed f) 291.52 459.33 P +0.13 (or repetitiv) 308.03 459.33 P +0.13 (e oper) 354.6 459.33 P +0.13 (ations) 382.98 459.33 P +0.13 (, in par) 409.51 459.33 P +0.13 (ticular f) 440.74 459.33 P +0.13 (or monitor) 472.8 459.33 P +0.13 (ing v) 518.1 459.33 P +0.13 (alue) 539.1 459.33 P +3.2 (changes within a ser) 180 447.33 P +3.2 (v) 281.04 447.33 P +3.2 (er) 285.79 447.33 P +3.2 (. Asychronous oper) 294.18 447.33 P +3.2 (ations with callbac) 386.62 447.33 P +3.2 (ks are suppor) 473.95 447.33 P +3.2 (ted,) 541.32 447.33 P +0.11 (including asychronous error noti\336cation. Speci\336cally) 180 435.33 P +0.11 (, CDEV suppor) 408.4 435.33 P +0.11 (ts most f) 475.71 435.33 P +0.11 (eatures of) 513.42 435.33 P +(channel access \050the EPICS comm) 180 423.33 T +(unications protocol\051.) 331.62 423.33 T +2 F +(La) 72 394.33 T +(y) 83.47 394.33 T +(ering and) 88.93 394.33 T +(Abstraction) 72 382.33 T +0 F +1.59 (The CDEV libr) 180 394.33 P +1.59 (ar) 246.98 394.33 P +1.59 (y pro) 256.17 394.33 P +1.59 (vides a standard interf) 279.84 394.33 P +1.59 (ace to one or more under) 382.68 394.33 P +1.59 (lying control) 503.06 394.33 P +0.95 (pac) 180 382.33 P +0.95 (kages or systems) 195.92 382.33 P +0.95 (. Currently CDEV pro) 275.48 382.33 P +0.95 (vides suppor) 372.1 382.33 P +0.95 (t f) 430.14 382.33 P +0.95 (or EPICS channel access) 439.13 382.33 P +0.95 (,) 555.22 382.33 P +0.54 (tcl scr) 180 370.33 P +0.54 (ipts) 206.8 370.33 P +0.54 (, the A) 222.21 370.33 P +0.54 (CE comm) 251.9 370.33 P +0.54 (unications pac) 296.22 370.33 P +0.54 (kage \050a C++ class libr) 360.48 370.33 P +0.54 (ar) 459.23 370.33 P +0.54 (y o) 468.42 370.33 P +0.54 (v) 482.15 370.33 P +0.54 (er TCP/IP\051. The) 486.9 370.33 P +0.59 (A) 180 358.33 P +0.59 (CE pac) 186.37 358.33 P +0.59 (kage is used to comm) 219.55 358.33 P +0.59 (unicate with an on-line acceler) 319.08 358.33 P +0.59 (ator modeling pac) 455.85 358.33 P +0.59 (kage) 536.32 358.33 P +0.92 (and with COD) 180 346.33 P +0.92 (A, the CEBAF On-line Data Acquisition system. Access to the EPICS) 243.68 346.33 P +0.07 (archiv) 180 334.33 P +0.07 (e data will be added in a later release) 206.42 334.33 P +0.07 (. All data will be a) 372.46 334.33 P +0.07 (v) 450.41 334.33 P +0.07 (ailab) 455.16 334.33 P +0.07 (le through a single) 476.08 334.33 P +(API \050application prog) 180 322.33 T +(r) 272.72 322.33 T +(amming interf) 275.95 322.33 T +(ace\051.) 336.22 322.33 T +2 F +(Inf) 72 293.33 T +(ormation Hiding) 84.02 293.33 T +0 F +-0.24 (The ability to hide the implementation details of a par) 180 293.33 P +-0.24 (ticular de) 412.23 293.33 P +-0.24 (vice \050such as the choice) 452.26 293.33 P +3.9 (of records in EPICS\051 from the high le) 180 281.33 P +3.9 (v) 369.85 281.33 P +3.9 (el application de) 374.6 281.33 P +3.9 (v) 454.36 281.33 P +3.9 (eloper) 459.11 281.33 P +3.9 (, allo) 486.4 281.33 P +3.9 (ws ser) 511.27 281.33 P +3.9 (v) 544.36 281.33 P +3.9 (er) 549.11 281.33 P +4.84 (implementation choices to be changed without breaking all high le) 180 269.33 P +4.84 (v) 514.51 269.33 P +4.84 (el client) 519.26 269.33 P +0.46 (applications) 180 257.33 P +0.46 (. F) 232.65 257.33 P +0.46 (or e) 244.48 257.33 P +0.46 (xample) 261.86 257.33 P +0.46 (, se) 293.94 257.33 P +0.46 (v) 310.22 257.33 P +0.46 (er) 314.97 257.33 P +0.46 (al records ma) 323.76 257.33 P +0.46 (y be merged into a ne) 384.94 257.33 P +0.46 (w custom record) 483.74 257.33 P +(without changing applications which access those records through the CDEV API.) 180 245.33 T +2 F +(De) 72 216.33 T +(vice Object) 84.63 216.33 T +0 F +1.61 (The basic idea behind CDEV is that all I/O is perf) 180 216.33 P +1.61 (or) 412.56 216.33 P +1.61 (med b) 421.7 216.33 P +1.61 (y sending messages to) 450.9 216.33 P +0.4 (de) 180 204.33 P +0.4 (vices) 190.82 204.33 P +0.4 (. A de) 213.45 204.33 P +0.4 (vice is a named entity in the control system which can respond to a set) 240.07 204.33 P +1.71 (of messages such as) 180 192.33 P +3 F +1.71 (on) 283.53 192.33 P +0 F +1.71 ( or) 294.65 192.33 P +3 F +1.71 (off) 312.51 192.33 P +0 F +1.71 ( or) 323.63 192.33 P +3 F +1.71 (get current) 341.49 192.33 P +0 F +1.71 (. Fur) 391 192.33 P +1.71 (ther) 413.67 192.33 P +1.71 (, a de) 430.4 192.33 P +1.71 (vice is a vir) 458.53 192.33 P +1.71 (tual entity) 513.49 192.33 P +3.22 (potentially spanning m) 180 180.33 P +3.22 (ultiple ser) 285.83 180.33 P +3.22 (v) 332.14 180.33 P +3.22 (ers and ser) 336.89 180.33 P +3.22 (vices such as channel access) 393.65 180.33 P +3.22 (, an) 538.1 180.33 P +(archiv) 180 168.33 T +(er) 206.42 168.33 T +(, and a static database) 214.81 168.33 T +(.) 315.28 168.33 T +2.1 (Each de) 180 151.33 P +2.1 (vice and message pair is mapped to a unique ser) 218.49 151.33 P +2.1 (vice \050such as channel) 455.55 151.33 P +0.61 (access\051 and ser) 180 139.33 P +0.61 (vice dependent data \050such as the process v) 252.09 139.33 P +0.61 (ar) 448.97 139.33 P +0.61 (iab) 458.01 139.33 P +0.61 (le name in EPICS\051.) 471.15 139.33 P +0.03 (This mapping is k) 180 127.33 P +0.03 (ept in a name ser) 257.69 127.33 P +0.03 (vice) 335.36 127.33 P +0.03 (, and is ultimately initializ) 352.99 127.33 P +0.03 (ed from an ASCII \336le) 462.99 127.33 P +0.03 (.) 555.22 127.33 P +1.17 (The designer/maintainer of the ser) 180 115.33 P +1.17 (v) 337.26 115.33 P +1.17 (er w) 342.01 115.33 P +1.17 (ould typically be the person responsib) 361.97 115.33 P +1.17 (le f) 534.9 115.33 P +1.17 (or) 549.11 115.33 P +(k) 180 103.33 T +(eeping the mapping current.) 184.8 103.33 T +FMENDPAGE +%%EndPage: "1" 55 +%%Page: "2" 56 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. Introduction) 54 739 T +0 10 Q +(2) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +2 10 Q +(Standar) 54 713.33 T +(d) 91.03 713.33 T +(Messa) 54 701.33 T +(g) 84.47 701.33 T +(es) 90.68 701.33 T +0 F +0.72 (Most de) 162 713.33 P +0.72 (vices will implement a n) 197.99 713.33 P +0.72 (umber of attr) 305.81 713.33 P +0.72 (ib) 364.1 713.33 P +0.72 (utes which ma) 371.68 713.33 P +0.72 (y be read or wr) 436.74 713.33 P +0.72 (itten. In) 506.48 713.33 P +1.32 (order to f) 162 701.33 P +1.32 (acilitate de) 204.37 701.33 P +1.32 (v) 253.19 701.33 P +1.32 (eloping gener) 257.94 701.33 P +1.32 (ic applications) 320 701.33 P +1.32 (, the f) 383.98 701.33 P +1.32 (ollo) 411.34 701.33 P +1.32 (wing standard messages) 426.75 701.33 P +(are recommended f) 162 689.33 T +(or de) 248.4 689.33 T +(vices) 270.89 689.33 T +(, where) 293.52 689.33 T +3 F +(attr) 329.09 689.33 T +(ib) 343.69 689.33 T +0 F +( is some attr) 351.47 689.33 T +(ib) 406.08 689.33 T +(ute of the de) 413.66 689.33 T +(vice:) 468.96 689.33 T +4 9 Q +(set) 180 673 T +5 F +(attrib) 201.6 673 T +4 F +( => Set the value of the attribute) 234 673 T +(get) 180 662 T +5 F +(attrib) 201.6 662 T +4 F +( => Get the value of the attribute) 234 662 T +-0.51 (monitorOn) 180 651 P +5 F +-0.51 (attrib) 233.49 651 P +4 F +-0.51 ( => Start monitoring the value of the attribute) 265.89 651 P +-0.14 (monitorOff) 180 640 P +5 F +-0.14 (attrib) 239.26 640 P +4 F +-0.14 ( => Stop monitoring the value of the attribute) 271.66 640 P +2 10 Q +(Data Object) 54 611.33 T +0 F +0.91 (The message sent to the de) 162 611.33 P +0.91 (vice ma) 290.21 611.33 P +0.91 (y ha) 325.27 611.33 P +0.91 (v) 344.89 611.33 P +0.91 (e an associated data object. F) 349.64 611.33 P +0.91 (or e) 487.3 611.33 P +0.91 (xample) 505.14 611.33 P +0.91 (,) 537.22 611.33 P +-0.23 (the message) 162 599.33 P +3 F +-0.23 (set current) 221.57 599.33 P +0 F +-0.23 ( will ha) 268.59 599.33 P +-0.23 (v) 298.49 599.33 P +-0.23 (e an associated) 303.24 599.33 P +3 F +-0.23 (v) 375.38 599.33 P +-0.23 (alue) 380.13 599.33 P +0 F +-0.23 ( f) 399.03 599.33 P +-0.23 (or the ne) 404.06 599.33 P +-0.23 (w current setting. This) 442.87 599.33 P +(v) 162 587.33 T +(alue is passed as an additional argument on the send call.) 166.75 587.33 T +2.64 (Data retur) 162 570.33 P +2.64 (ned from the ser) 209.35 570.33 P +2.64 (v) 290.38 570.33 P +2.64 (er to the client ma) 295.13 570.33 P +2.64 (y contain m) 384.87 570.33 P +2.64 (ultiple tagged v) 441.18 570.33 P +2.64 (alues) 513.47 570.33 P +2.64 (,) 537.22 570.33 P +1.92 (including) 162 558.33 P +3 F +1.92 (v) 206.16 558.33 P +1.92 (alue) 210.91 558.33 P +0 F +1.92 (,) 229.66 558.33 P +3 F +1.92 (status) 237.14 558.33 P +0 F +1.92 (, and) 263.67 558.33 P +3 F +1.92 ( timestamp) 287.83 558.33 P +0 F +1.92 (. Each of these items is e) 338.3 558.33 P +1.92 (xtr) 461.23 558.33 P +1.92 (acted from the) 472.24 558.33 P +1.5 (retur) 162 546.33 P +1.5 (ned data object b) 182.81 546.33 P +1.5 (y specifying a name or an integer tag. An) 263.83 546.33 P +1.5 (y data object ma) 457.43 546.33 P +1.5 (y) 535 546.33 P +2.68 (contain an arbitr) 162 534.33 P +2.68 (ar) 238.97 534.33 P +2.68 (y n) 248.16 534.33 P +2.68 (umber of tagged entr) 264.08 534.33 P +2.68 (ies) 365.11 534.33 P +2.68 (, allo) 377.74 534.33 P +2.68 (wing consider) 401.4 534.33 P +2.68 (ab) 465.11 534.33 P +2.68 (le \337e) 476.03 534.33 P +2.68 (xibility in) 499.54 534.33 P +(de\336ning future clients and ser) 162 522.33 T +(v) 292.92 522.33 T +(ers) 297.67 522.33 T +(.) 311.41 522.33 T +3 F +0.83 (Ac) 162 505.33 P +0.83 (kno) 173.47 505.33 P +0.83 (wledgment: This w) 189.44 505.33 P +0.83 (or) 273.8 505.33 P +0.83 (k der) 282.84 505.33 P +0.83 (iv) 306.04 505.33 P +0.83 (es some of its ideas about de) 313.01 505.33 P +0.83 (vices and messages) 447.75 505.33 P +1.38 (from w) 162 493.33 P +1.38 (or) 193.28 493.33 P +1.38 (k done at Argonne b) 202.32 493.33 P +1.38 (y Claude Saunders on a de) 297.69 493.33 P +1.38 (vice or) 425.46 493.33 P +1.38 (iented la) 456.43 493.33 P +1.38 (y) 495.31 493.33 P +1.38 (er abo) 500.11 493.33 P +1.38 (v) 529.69 493.33 P +1.38 (e) 534.44 493.33 P +0.22 (channel access) 162 481.33 P +0.22 (. Much additional analysis & design w) 230.99 481.33 P +0.22 (or) 398.36 481.33 P +0.22 (k has been done b) 407.39 481.33 P +0.22 (y members) 490.33 481.33 P +(of the EPICS collabor) 162 469.33 T +(ation.) 257.5 469.33 T +FMENDPAGE +%%EndPage: "2" 56 +%%Page: "3" 57 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. Basic Operations on Devices and Data) 393.43 739 T +0 10 Q +(3) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(2.) 159.32 710.67 T +(Basic Operations on De) 180 710.67 T +(vices and Data) 337.72 710.67 T +0 10 Q +0.44 (The basic user deals only with the de) 180 684.33 P +0.44 (vice and data objects) 347.28 684.33 P +0.44 (. The de) 442.38 684.33 P +0.44 (vice is created b) 479.64 684.33 P +0.44 (y) 553 684.33 P +0.54 (name) 180 672.33 P +0.54 (, and I/O consists of sending messages to this de) 204.86 672.33 P +0.54 (vice) 427.34 672.33 P +0.54 (. The de) 444.97 672.33 P +0.54 (vice object is the) 482.45 672.33 P +0.8 (simplest I/O object to use: a single de) 180 660.33 P +0.8 (vice \050magnet, vie) 351.47 660.33 P +0.8 (w) 428.45 660.33 P +0.8 (er) 435.57 660.33 P +0.8 (, etc.\051 ma) 443.96 660.33 P +0.8 (y be completely) 486.93 660.33 P +0.36 (controlled from a single de) 180 648.33 P +0.36 (vice object, with data being passed b) 298.39 648.33 P +0.36 (y 2 data objects \050one) 463.75 648.33 P +0.2 (f) 180 636.33 P +0.2 (or output, another f) 182.48 636.33 P +0.2 (or retur) 267.27 636.33 P +0.2 (ned results; dataless commands w) 299.95 636.33 P +0.2 (ould not require either\051.) 454.03 636.33 P +0.55 (The f) 180 624.33 P +0.55 (ollo) 203.04 624.33 P +0.55 (wing sample code reads the magnet current from one magnet, and sets the) 218.45 624.33 P +(magnet current f) 180 612.33 T +(or a second magnet to that v) 252.51 612.33 T +(alue:) 379 612.33 T +3 9 Q +(Figure 1: Sample usage of the send method of a cde) 180 579 T +(vDe) 391.85 579 T +(vice) 407.58 579 T +0 10 Q +2.25 (The send call, which is synchronous) 180 340.33 P +2.25 (, tak) 351.15 340.33 P +2.25 (es 3 arguments) 372.1 340.33 P +2.25 (, and retur) 445.37 340.33 P +2.25 (ns an integer) 495.69 340.33 P +(status:) 180 328.33 T +6 9 Q +(int send\050char* msg, cdevData& out, cdevData& result\051;) 198 312 T +0 10 Q +0.22 (Lik) 180 295.33 P +0.22 (e all CDEV calls) 192.58 295.33 P +0.22 (, a retur) 264.78 295.33 P +0.22 (n code of 0 means success \050error handling is descr) 299.94 295.33 P +0.22 (ibed in) 528.32 295.33 P +0.19 (a later section\051. The \336rst argument to) 180 283.33 P +3 F +0.19 (send) 347.52 283.33 P +0 F +0.19 ( is a char) 369.2 283.33 P +0.19 (acter str) 410.25 283.33 P +0.19 (ing message) 446.71 283.33 P +0.19 (. The de) 503.45 283.33 P +0.19 (vice) 540.22 283.33 P +0.41 (name and this str) 180 271.33 P +0.41 (ing uniquely deter) 258.08 271.33 P +0.41 (mine the under) 338.07 271.33 P +0.41 (lying ser) 405.74 271.33 P +0.41 (vice to use) 443.68 271.33 P +0.41 (, and whate) 492.14 271.33 P +0.41 (v) 544.36 271.33 P +0.41 (er) 549.11 271.33 P +2.06 (addressing data that ser) 180 259.33 P +2.06 (vice needs to locate the ser) 293.77 259.33 P +2.06 (v) 426.1 259.33 P +2.06 (er) 430.85 259.33 P +2.06 (. The \336rst) 439.24 259.33 P +3 F +2.06 (send) 489.89 259.33 P +0 F +2.06 ( oper) 511.57 259.33 P +2.06 (ation) 536.32 259.33 P +0.57 (automatically connects to the requested ser) 180 247.33 P +0.57 (vice) 376.01 247.33 P +0.57 (, initializing an) 393.64 247.33 P +0.57 (y under) 457.42 247.33 P +0.57 (lying pac) 491.49 247.33 P +0.57 (kages) 531.32 247.33 P +(as needed.) 180 235.33 T +0.11 (The second and third arguments are outbound and result data of type cde) 180 218.33 P +0.11 (vData. This) 507.32 218.33 P +1.75 (is a composite data object which ma) 180 206.33 P +1.75 (y contain an arbitr) 350.82 206.33 P +1.75 (ar) 435.44 206.33 P +1.75 (y n) 444.63 206.33 P +1.75 (umber of data v) 459.62 206.33 P +1.75 (alues) 534.1 206.33 P +1.45 (tagged with an integer tag. The data is self-descr) 180 194.33 P +1.45 (ibing to the e) 407.95 194.33 P +1.45 (xtent that cde) 469.25 194.33 P +1.45 (vData) 531.88 194.33 P +2.38 (k) 180 182.33 P +2.38 (eeps tr) 184.8 182.33 P +2.38 (ac) 217.65 182.33 P +2.38 (k of the data type) 228.01 182.33 P +2.38 (, and can automatically con) 314.12 182.33 P +2.38 (v) 444.63 182.33 P +2.38 (er) 449.38 182.33 P +2.38 (t betw) 458.67 182.33 P +2.38 (een data types) 487.63 182.33 P +0.85 (through C++ function o) 180 170.33 P +0.85 (v) 284.13 170.33 P +0.85 (er) 288.88 170.33 P +0.85 (loading or b) 297.92 170.33 P +0.85 (y e) 351.67 170.33 P +0.85 (xplicit direction from the caller) 365.56 170.33 P +0.85 (. The integer) 500.16 170.33 P +-0.05 (tags are not kno) 180 158.33 P +-0.05 (wn to the user at compile time \050i.e) 251.42 158.33 P +-0.05 (., no header \336les required\051, and can) 400.43 158.33 P +0.77 (be ref) 180 146.33 P +0.77 (erred to b) 206.04 146.33 P +0.77 (y char) 250.19 146.33 P +0.77 (acter str) 278.09 146.33 P +0.77 (ing equiv) 315.14 146.33 P +0.77 (alents) 355.68 146.33 P +0.77 (. The cde) 382.21 146.33 P +0.77 (vData class k) 425.14 146.33 P +0.77 (eeps tr) 485.95 146.33 P +0.77 (ac) 517.19 146.33 P +0.77 (k of all) 527.55 146.33 P +2.33 (integer tags and their char) 180 134.33 P +2.33 (acter str) 305.4 134.33 P +2.33 (ing equiv) 344.01 134.33 P +2.33 (alents) 386.11 134.33 P +2.33 (. Char) 412.64 134.33 P +2.33 (acter str) 442.11 134.33 P +2.33 (ing tags ma) 480.71 134.33 P +2.33 (y be) 536.77 134.33 P +1.8 (con) 180 122.33 P +1.8 (v) 195.92 122.33 P +1.8 (er) 200.67 122.33 P +1.8 (ted to integer tags at r) 209.96 122.33 P +1.8 (un time to impro) 316.38 122.33 P +1.8 (v) 393.31 122.33 P +1.8 (e perf) 398.06 122.33 P +1.8 (or) 425.13 122.33 P +1.8 (mance) 434.27 122.33 P +1.8 (. The f) 464.13 122.33 P +1.8 (ollo) 495.77 122.33 P +1.8 (wing code) 511.18 122.33 P +(demonstr) 180 110.33 T +(ates ho) 221.58 110.33 T +(w to inser) 254.23 110.33 T +(t v) 297.42 110.33 T +(alues into and e) 307.73 110.33 T +(xtr) 378.03 110.33 T +(act v) 389.04 110.33 T +(alues from a cde) 409.91 110.33 T +(vData object:) 483.53 110.33 T +180 81 558 691 C +180 371 558 576 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +125.07 371 612.93 576 R +7 X +0 0 0 1 0 0 0 K +V +186.17 379.09 561.88 570.52 R +0 X +V +0.5 H +2 Z +N +182.4 382.24 554.91 573.67 R +7 X +V +0 X +N +184.62 388.62 552.24 571.47 R +7 X +V +6 9 Q +0 X +(void main \050\051) 184.62 565.47 T +({) 202.62 554.47 T +(// *************************************************************) 202.62 543.47 T +(// * Get references to the 2 devices) 202.62 532.47 T +(// *************************************************************) 202.62 521.47 T +(cdevDevice& mag1 = cdevDevice::attachRef \050\322Magnet1\323\051;) 202.62 510.48 T +(cdevDevice& mag2 = cdevDevice::attachRef \050\322Magnet2\323\051;) 202.62 499.48 T +(cdevData result;) 202.62 488.48 T +(// *************************************************************) 202.62 466.48 T +(// * Get the current from the first magnet and use it to set) 202.62 455.48 T +(// * the current on the second.) 202.62 444.48 T +(// *************************************************************) 202.62 433.48 T +(mag1.send\050\322get current\323, NULL, result\051;) 202.62 422.48 T +(mag2.send\050\322set current\323, result, NULL\051;) 202.62 411.48 T +(}) 202.62 400.48 T +180 81 558 691 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "3" 57 +%%Page: "4" 58 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. Basic Operations on Devices and Data) 54 739 T +0 10 Q +(4) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +3 F +(Figure 2: Ov) 162 714 T +(er) 213.79 714 T +(vie) 222.07 714 T +(w of cde) 233.39 714 T +(vData oper) 266.63 714 T +(ations) 310.56 714 T +0 10 Q +1.55 (The last line abo) 162 527.48 P +1.55 (v) 239.89 527.48 P +1.55 (e demonstr) 244.64 527.48 P +1.55 (ates using oper) 296.11 527.48 P +1.55 (ator o) 367.49 527.48 P +1.55 (v) 394.47 527.48 P +1.55 (er) 399.22 527.48 P +1.55 (loading to e) 408.26 527.48 P +1.55 (xtr) 462.77 527.48 P +1.55 (act the \322v) 473.78 527.48 P +1.55 (alue\323) 517.77 527.48 P +1.2 (item from the data object; i.e) 162 515.48 P +1.2 (., the char) 294.01 515.48 P +1.2 (acter tag \322v) 340.78 515.48 P +1.2 (alue\323 is the def) 392.94 515.48 P +1.2 (ault tag to use in) 461.83 515.48 P +0.19 (e) 162 503.48 P +0.19 (xtr) 167.26 503.48 P +0.19 (acting a data item f) 178.27 503.48 P +0.19 (or the \322=\323 function o) 263.22 503.48 P +0.19 (v) 350.83 503.48 P +0.19 (er) 355.58 503.48 P +0.19 (load. This f) 364.61 503.48 P +0.19 (or) 413.61 503.48 P +0.19 (m is a) 422.75 503.48 P +0.19 (v) 449.6 503.48 P +0.19 (ailab) 454.35 503.48 P +0.19 (le f) 475.27 503.48 P +0.19 (or all scalar) 488.5 503.48 P +(types suppor) 162 491.48 T +(ted b) 219.65 491.48 T +(y cde) 241.69 491.48 T +(vData.) 265.29 491.48 T +1.2 (Most I/O oper) 162 474.48 P +1.2 (ations use the \322v) 224.87 474.48 P +1.2 (alue\323 tag to tr) 301.58 474.48 P +1.2 (ansmit a single v) 363.99 474.48 P +1.2 (alue \050scalar or arr) 441.79 474.48 P +1.2 (a) 523.63 474.48 P +1.2 (y\051.) 528.89 474.48 P +2.22 (Other commonly used tags are \322status\323 and \322time\323 \050a POSIX time str) 162 462.48 P +2.22 (uct\051. These) 487.76 462.48 P +-0.12 (tagged data items are optionally retur) 162 450.48 P +-0.12 (ned b) 326.71 450.48 P +-0.12 (y some ser) 351.41 450.48 P +-0.12 (v) 400.36 450.48 P +-0.12 (ers under the control of the I/O) 405.11 450.48 P +(conte) 162 438.48 T +(xt \050see belo) 186.16 438.48 T +(w f) 237.7 438.48 T +(or changing the def) 250.18 438.48 T +(ault conte) 335.49 438.48 T +(xt\051.) 378.55 438.48 T +1.93 (In this release) 162 421.48 P +1.93 (, cde) 227.95 421.48 P +1.93 (vData suppor) 251.26 421.48 P +1.93 (ts the f) 313.06 421.48 P +1.93 (ollo) 346.63 421.48 P +1.93 (wing data types:) 362.04 421.48 P +3 F +1.93 (unsigned char) 442.86 421.48 P +1.93 (, shor) 507.1 421.48 P +1.93 (t,) 534.44 421.48 P +0.45 (unsigned shor) 162 409.48 P +0.45 (t, int, unsigned int, long, unsigned long, \337oat, doub) 225.66 409.48 P +0.45 (le) 451.95 409.48 P +0 F +0.45 (,) 459.58 409.48 P +3 F +0.45 (char) 465.59 409.48 P +0.45 (acter str) 484.94 409.48 P +0.45 (ings) 521.66 409.48 P +0 F +(and) 162 397.48 T +3 F +(time stamp) 181.46 397.48 T +(.) 230.01 397.48 T +0 F +(All data types ma) 235.57 397.48 T +(y be either scalar or m) 311.97 397.48 T +(ulti-dimensional arr) 410.79 397.48 T +(a) 495.15 397.48 T +(ys) 500.41 397.48 T +(.) 510.26 397.48 T +162 81 540 720 C +162 558.14 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.52 558.14 542.48 711 R +7 X +0 0 0 1 0 0 0 K +V +166.55 561.71 542.27 703.86 R +0 X +V +0.5 H +2 Z +N +163.12 565.14 538.13 706.57 R +7 X +V +0 X +N +165.84 568.86 535.13 703.14 R +7 X +V +6 9 Q +0 X +(cdevData d1, d2;) 165.84 697.14 T +(int valtag;) 165.84 686.14 T +(float x, x2;) 165.84 675.14 T +(int status;) 165.84 664.14 T +(...) 165.84 653.14 T +(d1.tagC2I\050\322value\323,&valtag\051; // get the integer tag for \322value\323) 165.84 642.14 T +(...) 165.84 631.14 T +(d1.insert\050\322value\323,37.9\051; // insert using a character tag) 165.84 620.14 T +(device.send\050\322message\323,d1,d2\051; // send d1, get back d2) 165.84 609.14 T +(d2.get\050valtag,&x\051; // get \322value\323 from d2 into x) 165.84 598.14 T +(d2.get\050\322status\323,&status\051; // extract the \322status\323) 165.84 587.14 T +(x2 = d2; // get \322value\323 into x2 \050= overload\051) 165.84 576.14 T +162 81 540 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "4" 58 +%%Page: "5" 59 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 449.45 739 T +0 10 Q +(5) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(3.) 159.32 710.67 T +(Asyc) 180 710.67 T +(hr) 213.32 710.67 T +(onous Operations) 227.04 710.67 T +0 10 Q +1.79 (In addition to the synchronous send, there are 2 asynchronous f) 180 684.33 P +1.79 (or) 480 684.33 P +1.79 (ms f) 489.14 684.33 P +1.79 (or sending) 509.52 684.33 P +(messages) 180 672.33 T +(. The class de\336nition f) 225.42 672.33 T +(or all three f) 321.83 672.33 T +(or) 374.33 672.33 T +(ms is giv) 383.47 672.33 T +(en belo) 422.11 672.33 T +(w) 454.76 672.33 T +(.) 461.38 672.33 T +3 9 Q +(Figure 3: Three f) 180 639 T +(or) 248.76 639 T +(ms of the send command) 256.99 639 T +0 10 Q +1.17 (The second f) 180 506.76 P +1.17 (or) 239.86 506.76 P +1.17 (m, sendNoBloc) 249 506.76 P +1.17 (k, tak) 317.78 506.76 P +1.17 (es the same arguments as send b) 342.65 506.76 P +1.17 (ut completes) 500.13 506.76 P +1.21 (asynchronously) 180 494.76 P +1.21 (. That is) 248.47 494.76 P +1.21 (, the result will be in) 286.3 494.76 P +1.21 (v) 379.94 494.76 P +1.21 (alid until some synchronizing action is) 384.69 494.76 P +2.44 (tak) 180 482.76 P +2.44 (en \050discussed belo) 193.14 482.76 P +2.44 (w\051. The third f) 281.25 482.76 P +2.44 (or) 349.41 482.76 P +2.44 (m retur) 358.55 482.76 P +2.44 (ns the result to a callbac) 392.91 482.76 P +2.44 (k function) 512.76 482.76 P +0.66 (speci\336ed as par) 180 470.76 P +0.66 (t of the callbac) 251.76 470.76 P +0.66 (k argument. F) 318.03 470.76 P +0.66 (or each of these asychronous calls) 380.75 470.76 P +0.66 (, the) 537.88 470.76 P +0.19 (message ma) 180 458.76 P +0.19 (y be b) 237.13 458.76 P +0.19 (uff) 264.56 458.76 P +0.19 (ered b) 275.38 458.76 P +0.19 (y the under) 303.73 458.76 P +0.19 (lying ser) 354.3 458.76 P +0.19 (vice) 392.02 458.76 P +0.19 (, so that upon retur) 409.65 458.76 P +0.19 (n from the call) 494.62 458.76 P +-0.02 (there is no guar) 180 446.76 P +-0.02 (antee that the message has e) 249.32 446.76 P +-0.02 (v) 380.66 446.76 P +-0.02 (en been sent y) 385.41 446.76 P +-0.02 (et. T) 450.74 446.76 P +-0.02 (r) 469.53 446.76 P +-0.02 (ansmission ma) 472.76 446.76 P +-0.02 (y be) 539.12 446.76 P +2.28 (f) 180 434.76 P +2.28 (orced with a \337ush call using the cde) 182.48 434.76 P +2.28 (vSystem object descr) 355.97 434.76 P +2.28 (ibed belo) 455.71 434.76 P +2.28 (w) 498.42 434.76 P +2.28 (. A \337ush is) 505.04 434.76 P +(automatically perf) 180 422.76 T +(or) 258.06 422.76 T +(med if pend is called.) 267.2 422.76 T +2 F +(Callbac) 72 393.76 T +(k Object) 107.37 393.76 T +0 F +0.85 (The callbac) 180 393.76 P +0.85 (k object is a simple object containing 2 items: a function pointer) 231.78 393.76 P +0.85 (, and an) 520.17 393.76 P +1.21 (arbitr) 180 381.76 P +1.21 (ar) 202.68 381.76 P +1.21 (y user argument. As an e) 211.87 381.76 P +1.21 (xample) 329.33 381.76 P +1.21 (, the f) 361.41 381.76 P +1.21 (ollo) 388.55 381.76 P +1.21 (wing code fr) 403.96 381.76 P +1.21 (agment demonstr) 460.18 381.76 P +1.21 (ates) 539.1 381.76 P +1.85 (monitor) 180 369.76 P +1.85 (ing the magnet current asynchronously \050the third argument to the callbac) 213.49 369.76 P +1.85 (k) 553 369.76 P +(function is discussed later\051:) 180 357.76 T +3 9 Q +(Figure 4: Ov) 180 324.43 T +(er) 231.79 324.43 T +(vie) 240.07 324.43 T +(w of the cde) 251.39 324.43 T +(vCallbac) 299.65 324.43 T +(k object and the cde) 333.97 324.43 T +(vCallbac) 414.25 324.43 T +(kFunction) 448.58 324.43 T +180 419.43 558 691 C +180 537.43 558 636 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.63 537.43 560.37 636 R +7 X +0 0 0 1 0 0 0 K +V +184.44 541.71 560.15 628.86 R +0 X +V +0.5 H +2 Z +N +181.01 545.14 555.3 631.57 R +7 X +V +0 X +N +183.72 549.57 551.58 628.14 R +7 X +V +6 9 Q +0 X +(class cdevDevice:) 183.72 622.14 T +({) 183.72 611.14 T +(public:) 183.72 600.14 T +(int send \050char* msg, cdevData& out, cdevData& result\051;) 201.72 589.14 T +(int sendNoBlock \050char* msg, cdevData& out, cdevData& result\051;) 201.72 578.14 T +(int sendCallback \050char* msg, cdevData& out, cdevCallback cb\051;) 201.72 567.14 T +(};) 183.72 556.14 T +180 419.43 558 691 C +0 0 612 792 C +180 81 558 400.43 C +180 130 558 321.43 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.52 130 560.48 321.43 R +7 X +0 0 0 1 0 0 0 K +V +184.55 135.71 560.27 314.29 R +0 X +V +0.5 H +2 Z +N +181.12 139.14 555.41 317 R +7 X +V +0 X +N +183.84 142.14 551.7 313.57 R +7 X +V +6 9 Q +0 X +(// declare the callback func) 183.84 307.57 T +(cdevCallbackFunction gotit;) 183.84 296.57 T +(// create callback object) 183.84 274.57 T +(cdevCallback callbk\050gotit, myarg\051;) 183.84 263.57 T +(...) 183.84 252.57 T +(mag1.sendCallback\050\322monitorOn current\323,NULL,callbk\051;) 183.84 241.57 T +(...) 183.84 230.57 T +(void gotit\050int status, void* userarg, cdevRequestObject& reqobj,) 183.84 208.57 T +(cdevData& result\051) 237.84 197.57 T +({) 201.84 186.57 T +(float f = result;) 201.84 175.57 T +(printf\050\322new value is %f\134n\323,f\051;) 201.84 164.57 T +(}) 201.84 153.57 T +180 81 558 400.43 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "5" 59 +%%Page: "6" 60 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 54 739 T +0 10 Q +(6) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 10 Q +(The f) 162 713.33 T +(ollo) 184.49 713.33 T +(wing code de\336nes the callbac) 199.9 713.33 T +(k \050the cde) 330.32 713.33 T +(vRequestObject is descr) 373.93 713.33 T +(ibed belo) 482.45 713.33 T +(w\051:) 522.88 713.33 T +3 9 Q +(Figure 5: Str) 162 680 T +(ucture of the cde) 214.15 680 T +(vCallbac) 280.93 680 T +(k object) 315.25 680 T +2 10 Q +(System Object) 54 511.05 T +0 F +0.1 (W) 162 511.05 P +0.1 (aiting f) 171.04 511.05 P +0.1 (or completion of asychronous oper) 200.3 511.05 P +0.1 (ations ma) 354.02 511.05 P +0.1 (y be accomplished in one of tw) 397.18 511.05 P +0.1 (o) 534.44 511.05 P +1.36 (w) 162 499.05 P +1.36 (a) 169.07 499.05 P +1.36 (ys: \0501\051 using g) 174.33 499.05 P +1.36 (roups) 241.1 499.05 P +1.36 (, and \0502\051 using the system object. The system object k) 265.96 499.05 P +1.36 (eeps) 518.32 499.05 P +2.71 (tr) 162 487.05 P +2.71 (ac) 168.01 487.05 P +2.71 (k of all de) 178.37 487.05 P +2.71 (vices) 229 487.05 P +2.71 (, and contains methods f) 251.63 487.05 P +2.71 (or \337ushing, polling, and pending f) 371.11 487.05 P +2.71 (or) 531.11 487.05 P +(asychronous oper) 162 475.05 T +(ations) 241.38 475.05 T +(.) 267.91 475.05 T +3 9 Q +(Figure 6: Usage of the pend method in the cde) 162 441.71 T +(vSystem object) 349.84 441.71 T +0 10 Q +(The f) 162 313.76 T +(ollo) 184.49 313.76 T +(wing class interf) 199.9 313.76 T +(ace sho) 270.73 313.76 T +(ws the f) 305.6 313.76 T +(or) 339.76 313.76 T +(ms f) 348.9 313.76 T +(or each synchronization method:) 367.49 313.76 T +3 9 Q +(Figure 7: Synchronization methods in the cde) 162 280.43 T +(vSystem object) 344.82 280.43 T +3 10 Q +1.33 (\337ush) 162 135.33 P +0 F +1.33 (: Flush all pending output to the netw) 183.12 135.33 P +1.33 (or) 355.75 135.33 P +1.33 (k f) 364.79 135.33 P +1.33 (or those ser) 376.38 135.33 P +1.33 (vices that perf) 432.13 135.33 P +1.33 (or) 496.74 135.33 P +1.33 (m send) 505.88 135.33 P +(b) 162 123.33 T +(uff) 167.36 123.33 T +(er) 178.18 123.33 T +(ing.) 187.22 123.33 T +3 F +0.58 (poll:) 162 106.33 P +0 F +0.58 ( Flush all pending output, and process all receiv) 180.34 106.33 P +0.58 (ed replies \050including dispatching) 395.97 106.33 P +(callbac) 162 94.33 T +(ks) 192.92 94.33 T +(, if an) 202.77 94.33 T +(y\051. An) 227.08 94.33 T +(y receiv) 253.05 94.33 T +(ed monitor callbac) 287.25 94.33 T +(ks will be deliv) 368.19 94.33 T +(ered as w) 431.84 94.33 T +(ell.) 475.09 94.33 T +162 536.71 540 720 C +162 547.71 540 677 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.63 547.71 542.37 677 R +7 X +0 0 0 1 0 0 0 K +V +166.44 550.57 542.15 669.86 R +0 X +V +0.5 H +2 Z +N +163.01 554 537.3 672.57 R +7 X +V +0 X +N +165.72 557.71 533.58 669.14 R +7 X +V +6 9 Q +0 X +(typedef void \050*cdevCallbackFunction\051\050int status, void* userarg,) 165.72 663.14 T +( cdevRequestObject& reqobj,) 345.72 652.14 T +( cdevData& result\051;) 345.72 641.14 T +(class cdevCallback) 165.72 630.14 T +({) 165.72 619.14 T +(public:) 165.72 608.14 T +(cdevCallback \050cdevCallbackFunction func, void* userarg\051;) 183.72 597.14 T +(cdevCallbackFunction function;) 183.72 586.14 T +(void* userarg;) 183.72 575.14 T +(}) 165.72 564.14 T +162 536.71 540 720 C +0 0 612 792 C +162 81 540 517.71 C +162 344.43 540 438.71 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.52 344.43 542.48 438.71 R +7 X +0 0 0 1 0 0 0 K +V +166.55 347.28 542.27 431.57 R +0 X +V +0.5 H +2 Z +N +163.12 350.71 537.41 434.28 R +7 X +V +0 X +N +165.84 353.71 533.7 430.86 R +7 X +V +6 9 Q +0 X +(// get default system) 165.84 424.86 T +(cdevSystem& sys = cdevSystem::defaultSystem\050\051;) 165.84 413.86 T +(...) 165.84 402.86 T +(mag1.sendNoBlock\050\322on\323,...\051; // async op\050s\051) 165.84 391.86 T +(mag2.sendNoBlock\050\322on\323,...\051; // async op\050s\051) 165.84 380.86 T +(...) 165.84 369.86 T +(sys.pend\050\051; // wait for all I/O to complete) 165.84 358.86 T +162 81 540 517.71 C +0 0 612 792 C +162 81 540 517.71 C +162 166 540 277.43 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.63 166 542.37 277.43 R +7 X +0 0 0 1 0 0 0 K +V +166.44 168.14 542.15 270.28 R +0 X +V +0.5 H +2 Z +N +163.01 171.57 537.3 273 R +7 X +V +0 X +N +165.72 174.57 533.58 269.57 R +7 X +V +6 9 Q +0 X +(class cdevSystem) 165.72 263.57 T +({) 165.72 252.57 T +(public:) 165.72 241.57 T +(int) 183.72 230.57 T +(flush\050\051;) 205.32 230.57 T +(int) 183.72 219.57 T +(poll\050\051;) 205.32 219.57 T +(int) 183.72 208.57 T +(pend\050\051;) 205.32 208.57 T +(}) 165.72 197.57 T +162 81 540 517.71 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "6" 60 +%%Page: "7" 61 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 449.45 739 T +0 10 Q +(7) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +3 F +1.4 (pend) 180 713.33 P +0 F +1.4 (: Flush all pending output, and process all replies f) 202.24 713.33 P +1.4 (or the speci\336ed n) 436.88 713.33 P +1.4 (umber of) 517.14 713.33 P +0.18 (seconds) 180 701.33 P +0.18 (. If the time argument is omitted, w) 217.09 701.33 P +0.18 (ait until all replies ha) 371.05 701.33 P +0.18 (v) 462.16 701.33 P +0.18 (e been receiv) 466.91 701.33 P +0.18 (ed. If a) 527.06 701.33 P +(monitor oper) 180 689.33 T +(ation w) 236.03 689.33 T +(as star) 267.56 689.33 T +(ted, this w) 297.97 689.33 T +(aits f) 342.84 689.33 T +(or the connection \050\336rst callbac) 363.66 689.33 T +(k\051 only) 496.29 689.33 T +(.) 524.74 689.33 T +2 F +(Gr) 72 660.33 T +(oup Object) 83.47 660.33 T +0 F +2.11 (An alter) 180 660.33 P +2.11 (nativ) 216.82 660.33 P +2.11 (e mechanism f) 237.69 660.33 P +2.11 (or w) 306.62 660.33 P +2.11 (aiting f) 327.46 660.33 P +2.11 (or asychronous calls is through the use of) 358.73 660.33 P +0.79 (g) 180 648.33 P +0.79 (roups) 185.46 648.33 P +0.79 (. A g) 210.32 648.33 P +0.79 (roup k) 232.37 648.33 P +0.79 (eeps tr) 260.74 648.33 P +0.79 (ac) 292 648.33 P +0.79 (k off all I/O oper) 302.36 648.33 P +0.79 (ations star) 376 648.33 P +0.79 (ted from the time the g) 423.32 648.33 P +0.79 (roup is) 527.2 648.33 P +0.89 (star) 180 636.33 P +0.89 (ted until the g) 197.07 636.33 P +0.89 (roup is ended. Groups ma) 259.67 636.33 P +0.89 (y be nested or o) 378.53 636.33 P +0.89 (v) 453.64 636.33 P +0.89 (er) 458.39 636.33 P +0.89 (lapped, and suppor) 467.43 636.33 P +0.89 (t) 555.22 636.33 P +(the same \337ush/poll/pend oper) 180 624.33 T +(ations as the system object. F) 311.08 624.33 T +(or e) 443.06 624.33 T +(xample:) 459.99 624.33 T +3 9 Q +(Figure 8: Sample usage of the cde) 180 591 T +(vGroup object) 319.81 591 T +3 10 Q +0.06 (Note: Allo) 180 311.33 P +0.06 (wing nested or o) 223.26 311.33 P +0.06 (v) 296.66 311.33 P +0.06 (er) 301.41 311.33 P +0.06 (lapped g) 310.45 311.33 P +0.06 (roups allo) 348.77 311.33 P +0.06 (ws libr) 392.03 311.33 P +0.06 (ar) 420.32 311.33 P +0.06 (y calls to star) 429.51 311.33 P +0.06 (t or stop g) 488.44 311.33 P +0.06 (roups) 532.99 311.33 P +(without needing to kno) 180 299.33 T +(w if another g) 279.91 299.33 T +(roup is already activ) 339.84 299.33 T +(e) 428.51 299.33 T +(.) 433.92 299.33 T +0 F +1.84 (Groups ma) 180 282.33 P +1.84 (y be oper) 231 282.33 P +1.84 (ated in one of tw) 276.28 282.33 P +1.84 (o modes) 356.93 282.33 P +1.84 (. Immediate mode \050def) 396.98 282.33 P +1.84 (ault\051 causes) 502.25 282.33 P +2.84 (g) 180 270.33 P +2.84 (rouped oper) 185.46 270.33 P +2.84 (ations to be immediately e) 242.12 270.33 P +2.84 (x) 369.32 270.33 P +2.84 (ecuted, and the g) 374.02 270.33 P +2.84 (roup is just used f) 459.7 270.33 P +2.84 (or) 549.11 270.33 P +1.11 (completion synchronization. Def) 180 258.33 P +1.11 (erred mode causes messages to be held bac) 323.64 258.33 P +1.11 (k until) 530.77 258.33 P +0.12 (the g) 180 246.33 P +0.12 (roup is ended and the oper) 202.26 246.33 P +0.12 (ations are \337ushed. After the oper) 322.28 246.33 P +0.12 (ations are complete) 467.87 246.33 P +0.12 (,) 555.22 246.33 P +0.48 (he g) 180 234.33 P +0.48 (roup of oper) 199.84 234.33 P +0.48 (ations ma) 254.63 234.33 P +0.48 (y be \337ushed again \050without re-posting\051, allo) 298.16 234.33 P +0.48 (wing the g) 491.55 234.33 P +0.48 (roup) 537.99 234.33 P +(to function as a list manager/e) 180 222.33 T +(x) 313.1 222.33 T +(ecutor) 317.8 222.33 T +(.) 345.09 222.33 T +2 F +(Request Object) 72 193.33 T +0 F +0.47 (Occasionally) 180 193.33 P +0.47 (, an I/O oper) 235.68 193.33 P +0.47 (ation ma) 292.58 193.33 P +0.47 (y need to be repeated ma) 331.1 193.33 P +0.47 (y times) 447.11 193.33 P +0.47 (. In this case) 479.1 193.33 P +0.47 (, it is) 536.5 193.33 P +0.88 (not ef\336cient to parse the message each time to deter) 180 181.33 P +0.88 (mine which ser) 421.09 181.33 P +0.88 (v) 489.84 181.33 P +0.88 (er to use) 494.59 181.33 P +0.88 (. It is) 535.11 181.33 P +0.06 (possib) 180 169.33 P +0.06 (le to b) 208.7 169.33 P +0.06 (ypass this parsing b) 235.86 169.33 P +0.06 (y creating a request object. The request object is lik) 324.21 169.33 P +0.06 (e) 552.44 169.33 P +-0.03 (the de) 180 157.33 P +-0.03 (vice object, e) 207.47 157.33 P +-0.03 (xcept that the message str) 265.46 157.33 P +-0.03 (ing is speci\336ed at creation time) 382.75 157.33 P +-0.03 (, and the) 519.15 157.33 P +0.98 (request object is theref) 180 145.33 P +0.98 (ore speci\336c to the par) 283.8 145.33 P +0.98 (ticular under) 383.71 145.33 P +0.98 (lying ser) 439.86 145.33 P +0.98 (vice to which that) 478.36 145.33 P +(message m) 180 133.33 T +(ust be directed.) 231.58 133.33 T +1.29 (In the case of EPICS channel access) 180 116.33 P +1.29 (, the request object opens and maintains the) 352.15 116.33 P +1.02 (channel to the EPICS process v) 180 104.33 P +1.02 (ar) 326.02 104.33 P +1.02 (iab) 335.05 104.33 P +1.02 (le) 348.2 104.33 P +1.02 (. The request object is NO) 355.83 104.33 P +1.02 (T the same as an) 476.67 104.33 P +1.34 (EPICS channel, in that the request object binds a de) 180 92.33 P +1.34 (vice and a message) 423.59 92.33 P +1.34 (, and the) 516.39 92.33 P +180 219 558 667 C +180 342 558 588 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.52 342 560.48 588 R +7 X +0 0 0 1 0 0 0 K +V +184.55 345 560.27 580.86 R +0 X +V +0.5 H +2 Z +N +181.12 347.86 555.41 583.57 R +7 X +V +0 X +N +183.84 350.85 551.7 580.14 R +7 X +V +6 9 Q +0 X +(cdevGroup g1, g2;) 183.84 574.14 T +(...) 183.84 563.14 T +(g1.start\050\051;) 183.84 552.14 T +(mag1.sendCallback\050...\051;) 183.84 541.14 T +(mag2.sendCallback\050...\051;) 183.84 530.14 T +(g2.start\050\051;) 183.84 519.14 T +(bpm1.sendNoBlock\050...\051;) 183.84 508.14 T +(bpm2.sendNoBlock\050...\051;) 183.84 497.14 T +(g1.end\050\051;) 183.84 486.14 T +(mag3.sendCallback\050...\051;) 183.84 475.14 T +(bpm3.sendNoBlock\050...\051;) 183.84 464.14 T +(g2.end\050\051;) 183.84 453.14 T +(g1.pend\0504.0\051;) 183.84 442.14 T +(// at this point operations on mag1, mag2, bpm1, & bpm2 are done) 183.84 431.14 T +(// or have timed out \050error handling discussed later\051.) 183.84 420.14 T +(...) 183.84 409.14 T +(// mag3 and bpm3 may not be finished yet, pend on the second) 183.84 398.14 T +(// group to wait for their completion) 183.84 387.14 T +(g2.pend\050\051;) 183.84 376.14 T +180 219 558 667 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "7" 61 +%%Page: "8" 62 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 54 739 T +0 10 Q +(8) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 10 Q +1.04 (message implies a direction. If the message is considered to be of the f) 162 713.33 P +1.04 (or) 489.84 713.33 P +1.04 (m) 498.98 713.33 P +3 F +1.04 (v) 511.14 713.33 P +1.04 (erb) 515.89 713.33 P +0 F +1.04 ( +) 530.34 713.33 P +3 F +-0.16 (attr) 162 701.33 P +-0.16 (ib) 176.6 701.33 P +-0.16 (ute) 184.18 701.33 P +0 F +-0.16 (then the EPICS channel essentially binds de) 200.7 701.33 P +-0.16 (vice and attr) 396.21 701.33 P +-0.16 (ib) 450.52 701.33 P +-0.16 (ute b) 458.1 701.33 P +-0.16 (ut not v) 479.98 701.33 P +-0.16 (erb) 512.21 701.33 P +-0.16 (. In) 526.26 701.33 P +0.04 (some future release of CDEV) 162 689.33 P +0.04 (, a more channel lik) 290.98 689.33 P +0.04 (e object ma) 377.65 689.33 P +0.04 (y be included if there is a) 429.13 689.33 P +0.37 (demand f) 162 677.33 P +0.37 (or it. If tw) 203.76 677.33 P +0.37 (o cde) 245.32 677.33 P +0.37 (vRequestObjects ref) 269.85 677.33 P +0.37 (erence the same EPICS channel, only a) 360.5 677.33 P +(single channel access connection is estab) 162 665.33 T +(lished.) 348 665.33 T +1.56 (The f) 162 648.33 P +1.56 (ollo) 186.05 648.33 P +1.56 (wing code demonstr) 201.46 648.33 P +1.56 (ates sending a set of data v) 293.96 648.33 P +1.56 (alues to a single magnet) 425.37 648.33 P +(using a request object. Note that the send call omits the message argument:) 162 636.33 T +3 9 Q +(Figure 9: Sample usage of the cde) 162 620 T +(vRequestObject object) 301.81 620 T +0 10 Q +0.2 (In most cases) 162 457.05 P +0.2 (, the de) 223.94 457.05 P +0.2 (vice object will create the request object to perf) 257.39 457.05 P +0.2 (or) 466.54 457.05 P +0.2 (m a requested) 475.68 457.05 P +0.59 (I/O oper) 162 445.05 P +0.59 (ation. All 3 f) 198.62 445.05 P +0.59 (or) 252.35 445.05 P +0.59 (ms of send are suppor) 261.49 445.05 P +0.59 (ted b) 363.75 445.05 P +0.59 (y the request object, with a calling) 386.38 445.05 P +-0.25 (syntax identical to the de) 162 433.05 P +-0.25 (vice calls without the message argument. The interf) 270.76 433.05 P +-0.25 (ace to the) 496.58 433.05 P +(request object is giv) 162 421.05 T +(en belo) 250.12 421.05 T +(w:) 282.77 421.05 T +3 9 Q +(Figure 10: Str) 162 387.71 T +(ucture of the cde) 219.16 387.71 T +(vRequestObject object) 285.93 387.71 T +0 10 Q +0.13 (When an asynchronous oper) 162 214.05 P +0.13 (ation completes) 290.12 214.05 P +0.13 (, the rele) 360.12 214.05 P +0.13 (v) 398.99 214.05 P +0.13 (ant request object is passed to) 403.74 214.05 P +1.47 (the user\325) 162 202.05 P +1.47 (s callbac) 201.32 202.05 P +1.47 (k routine) 241.49 202.05 P +1.47 (. This allo) 281.16 202.05 P +1.47 (ws the user to e) 326.74 202.05 P +1.47 (xtr) 402.9 202.05 P +1.47 (act the message str) 413.91 202.05 P +1.47 (ing and) 505.73 202.05 P +(de) 162 190.05 T +(vice name from the request object if necessar) 172.82 190.05 T +(y or desired.) 374.87 190.05 T +2 F +(File Descriptor) 54 161.05 T +(s) 123.87 161.05 T +(and \322select\323) 54 149.05 T +0 F +0.4 (An alter) 162 161.05 P +0.4 (nativ) 197.11 161.05 P +0.4 (e mechanism f) 217.98 161.05 P +0.4 (or dealing with asynchronous oper) 283.49 161.05 P +0.4 (ations is to directly test) 437.26 161.05 P +3.76 (the \336le descr) 162 149.05 P +3.76 (iptors being used. This interf) 226.36 149.05 P +3.76 (ace is currently implemented in the) 366.7 149.05 P +(cde) 162 137.05 T +(vSystem class) 177.82 137.05 T +(. The per) 241.57 137.05 T +(tinent methods ha) 281.99 137.05 T +(v) 361.28 137.05 T +(e the f) 366.03 137.05 T +(ollo) 393.53 137.05 T +(wing f) 408.94 137.05 T +(or) 434.76 137.05 T +(m:) 443.9 137.05 T +162 186.71 540 720 C +162 487.71 540 617 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.72 487.71 542.28 617 R +7 X +0 0 0 1 0 0 0 K +V +166.35 490.57 542.07 609.86 R +0 X +V +0.5 H +2 Z +N +162.92 494.71 537.21 612.57 R +7 X +V +0 X +N +165.64 497.71 533.49 609.14 R +7 X +V +6 9 Q +0 X +(cdevRequestObject& mag1BDL =) 165.64 603.14 T +(cdevRequestObject::attachRef\050\322mag1\323,\323set BDL\323\051;) 183.64 592.14 T +(cdevData mydata;) 165.64 581.14 T +(...) 165.64 570.14 T +(for \050i=0;i<100;i++\051) 165.64 559.14 T +({) 183.64 548.14 T +(mydata = i*10; // 10 amp steps) 183.64 537.14 T +(mag1BDL.send\050mydata,NULL\051; // ignore errors for now) 183.64 526.14 T +(sleep\0501\051;) 183.64 515.14 T +(}) 183.64 504.14 T +162 186.71 540 720 C +0 0 612 792 C +162 186.71 540 720 C +162 244.71 540 384.71 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.63 244.71 542.37 384.71 R +7 X +0 0 0 1 0 0 0 K +V +166.44 247.57 542.15 377.57 R +0 X +V +0.5 H +2 Z +N +163.01 251 537.3 380.29 R +7 X +V +0 X +N +165.72 254 533.58 376.86 R +7 X +V +6 9 Q +0 X +(class cdevRequestObject) 165.72 370.86 T +({) 165.72 359.86 T +(public:) 165.72 348.86 T +(char* message\050\051; // returns the message string) 183.72 337.86 T +(cdevDevice& device\050\051; // returns the device object) 183.72 326.86 T +(int state\050\051; // connected/disconnected/) 183.72 315.86 T +(int access\050\051; // read/write/none) 183.72 304.86 T +(int send\050cdevData& out, cdevData& result\051;) 183.72 293.86 T +(int sendNoBlock\050cdevData& out, cdevData& result\051;) 183.72 282.86 T +(int sendCallback\050cdevData& out, cdevCallback callback\051;) 183.72 271.86 T +(}) 165.72 260.86 T +162 186.71 540 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "8" 62 +%%Page: "9" 63 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 449.45 739 T +0 10 Q +(9) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +3 9 Q +(Figure 11: File descr) 180 714 T +(iptor routines of the cde) 264.66 714 T +(vSystem object) 358.44 714 T +0 10 Q +1.42 (The getFd method will populate a user allocated arr) 180 559.58 P +1.42 (a) 419.16 559.58 P +1.42 (y of integers \050fd\051 with the \336le) 424.42 559.58 P +0.36 (descr) 180 547.58 P +0.36 (iptors currently in use b) 204.6 547.58 P +0.36 (y the cde) 309.19 547.58 P +0.36 (vSystem object. The n) 350.18 547.58 P +0.36 (umber of \336le descr) 450.08 547.58 P +0.36 (iptors) 533.55 547.58 P +0.5 (that w) 180 535.58 P +0.5 (ere allocated b) 207.08 535.58 P +0.5 (y the user is speci\336ed in the n) 273.46 535.58 P +0.5 (umFD v) 408.58 535.58 P +0.5 (ar) 443.82 535.58 P +0.5 (iab) 452.86 535.58 P +0.5 (le) 466 535.58 P +0.5 (. Upon completion,) 473.63 535.58 P +-0.19 (the n) 180 523.58 P +-0.19 (umFD v) 201.95 523.58 P +-0.19 (ar) 236.5 523.58 P +-0.19 (iab) 245.54 523.58 P +-0.19 (le will be set to the n) 258.68 523.58 P +-0.19 (umber of \336le descr) 348.01 523.58 P +-0.19 (iptors actually copied into the) 429.83 523.58 P +0.52 (fd arr) 180 511.58 P +0.52 (a) 203.76 511.58 P +0.52 (y) 209.02 511.58 P +0.52 (. An error is retur) 213.02 511.58 P +0.52 (ned if the b) 290.39 511.58 P +0.52 (uff) 341.25 511.58 P +0.52 (er is not suf\336cient to store the complete set of) 352.07 511.58 P +(\336le descr) 180 499.58 T +(iptors) 220.16 499.58 T +(.) 244.46 499.58 T +0.03 (The addFdChangedCallbac) 180 482.58 P +0.03 (k method allo) 302.11 482.58 P +0.03 (ws the user to specify a function to be called) 361.5 482.58 P +(each time a \336le descr) 180 470.58 T +(iptor is added \050opened=1\051 or closed \050opened=0\051.) 274.63 470.58 T +(The f) 180 453.58 T +(ollo) 202.49 453.58 T +(wing code illustr) 217.9 453.58 T +(ates the usage of the UNIX select call:) 288.93 453.58 T +180 81 558 720 C +180 573.25 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.52 573.25 560.48 711 R +7 X +0 0 0 1 0 0 0 K +V +183.3 584.54 559.02 705.11 R +0 X +V +0.5 H +2 Z +N +181.75 588.29 556.04 707.82 R +7 X +V +0 X +N +183.84 596.53 551.7 703.14 R +7 X +V +6 9 Q +0 X +(typedef void \050*cdevFdChangedCallback\051\050int fd, int opened,) 183.84 697.14 T +( void* userarg\051) 255.84 686.14 T +(class cdevSystem) 183.84 675.14 T +({) 183.84 664.14 T +(public:) 183.84 653.14 T +(...) 201.84 642.14 T +(int getFd\050int fd[], int &numFD\051;) 201.84 631.14 T +(int addFdChangedCallback\050cdevFdChangedCallback cbk, void* arg\051;) 201.84 620.14 T +(}) 183.84 609.14 T +180 81 558 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "9" 63 +%%Page: "10" 64 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 54 739 T +0 10 Q +(10) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +3 F +(Figure 12: Using CDEV \336le descr) 162 714 T +(iptors with the UNIX select function) 296.68 714 T +162 81 540 720 C +162 213.85 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.57 213.85 542.43 711 R +7 X +0 0 0 1 0 0 0 K +V +166.5 216.71 542.22 703.86 R +0 X +V +0.5 H +2 Z +N +163.07 220.14 537.36 706.57 R +7 X +V +0 X +N +165.79 223.14 533.65 703.14 R +7 X +V +6 9 Q +0 X +(int myFD[5];) 165.79 697.14 T +(void mySelectLoop \050 cdevSystem & system \051) 165.79 675.14 T +({) 183.79 664.14 T +(int fd[20];) 183.79 653.14 T +(int numFD = 15, nfds;) 183.79 642.14 T +(fd_set rfds; // Ready file descriptors) 183.79 631.14 T +(fd_set afds; // Active file descriptors) 183.79 620.14 T +(// Copy the file descriptors I am already using to the list) 183.79 598.14 T +(memcpy\050fd, myFD, sizeof\050myFD\051\051;) 183.79 587.14 T +(// Get the file descriptors in use by the cdevSystem object) 183.79 565.14 T +(system.getFd\050&fd[5], numFD\051;) 183.79 554.14 T +(// Add in the 5 previously defined file descriptors) 183.79 532.14 T +(numFD += 5;) 183.79 521.14 T +(// Zero the active file descriptors) 183.79 499.14 T +(FD_ZERO\050&afds\051;) 183.79 488.14 T +(// Setup the active file descriptors) 183.79 466.14 T +(for\050int i=0; i\323 into which the de) 242.31 244.91 T +(vice name will be substituted.) 354.29 244.91 T +-0.15 (Example: Suppose there are a set of magnets f) 180 227.91 P +-0.15 (or which it is possib) 387.51 227.91 P +-0.15 (le to read and wr) 473.4 227.91 P +-0.15 (ite) 547.44 227.91 P +0.46 (bdl \050integ) 180 215.91 P +0.46 (r) 221.49 215.91 P +0.46 (al \336eld\051, and current \050amps\051. That is) 224.72 215.91 P +0.46 (, the messages \322get bdl\323, \322get current\323,) 385.17 215.91 P +0.32 (\322set bdl\323, etc. are v) 180 203.91 P +0.32 (alid. Also) 263.86 203.91 P +0.32 (, each magnet responds to the commands \322on\323 and \322off) 304.36 203.91 P +0.32 (\323.) 551.89 203.91 P +-0.22 (Fur) 180 191.91 P +-0.22 (ther suppose that the beamline position and length of the magnet are a) 195.4 191.91 P +-0.22 (v) 506.09 191.91 P +-0.22 (ailab) 510.84 191.91 P +-0.22 (le in a) 531.76 191.91 P +(static database \050assume read/wr) 180 179.91 T +(ite\051.) 324.65 179.91 T +180 557.57 558 720 C +180 603.57 558 665 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +178.64 603.57 559.36 665 R +7 X +0 0 0 1 0 0 0 K +V +183.43 606.43 559.15 657.86 R +0 X +V +0.5 H +2 Z +N +180 609.86 554.29 660.57 R +7 X +V +0 X +N +182.71 613.57 550.57 657.14 R +7 X +V +6 9 Q +0 X +(service ca) 182.71 651.14 T +({) 200.71 640.14 T +(tags {pv, default}) 200.71 629.14 T +(}) 200.71 618.14 T +180 557.57 558 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "15" 69 +%%Page: "16" 70 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Name Resolution) 54 739 T +0 10 Q +(16) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 10 Q +(Here is a complete class de\336nition:) 162 713.33 T +3 9 Q +(Figure 21: Sample inher) 162 680 T +(ited class de\336nition) 260.68 680 T +0 10 Q +0.68 (Note the semicolon at the end of each line of attr) 162 406.33 P +0.68 (ib) 384.02 406.33 P +0.68 (utes or messages \050e) 391.6 406.33 P +0.68 (xcept f) 483.92 406.33 P +0.68 (or the) 513.75 406.33 P +0.36 (last line\051. Note also that the process v) 162 394.33 P +0.36 (ar) 330.99 394.33 P +0.36 (iab) 340.03 394.33 P +0.36 (le name has a place holder into which the) 353.17 394.33 P +0.17 (de) 162 382.33 P +0.17 (vice name will be substituted. More sophisticated name mangling is en) 172.82 382.33 P +0.17 (visaged, b) 486.11 382.33 P +0.17 (ut) 531.66 382.33 P +(not f) 162 370.33 T +(or this release) 181.16 370.33 T +(. Syntax is still open to re) 243.81 370.33 T +(vision.) 354.67 370.33 T +2 F +(Instance De\336nition) 54 341.33 T +0 F +1.8 (Instances of a class are giv) 162 341.33 P +1.8 (en b) 291.39 341.33 P +1.8 (y f) 312.45 341.33 P +1.8 (ollo) 324.52 341.33 P +1.8 (wing the class name with a list of instance) 339.93 341.33 P +4.03 (names) 162 329.33 P +4.03 (. De) 191.86 329.33 P +4.03 (vice names ma) 213.93 329.33 P +4.03 (y be separ) 288.92 329.33 P +4.03 (ated b) 343.56 329.33 P +4.03 (y whitespace char) 375.19 329.33 P +4.03 (acters \050including) 463.17 329.33 P +(ne) 162 317.33 T +(wline\051 or b) 172.92 317.33 T +(y commas) 218.84 317.33 T +(.) 264.25 317.33 T +3 9 Q +(Figure 22: Multiple instances of the magnet class) 162 284 T +0 10 Q +1.2 (Combined with the pre) 162 223.19 P +1.2 (vious de\336nition, the message \322on\323 sent to magnet m2 w) 265.33 223.19 P +1.2 (ould) 521.1 223.19 P +(select the process v) 162 211.19 T +(ar) 250.12 211.19 T +(iab) 259.16 211.19 T +(le \322m2CSR.v) 272.3 211.19 T +(al\323 with \3221\323 as the v) 328.72 211.19 T +(alue to wr) 412.94 211.19 T +(ite) 456.44 211.19 T +(.) 466.85 211.19 T +2 F +(Aliases) 54 182.19 T +0 F +1.39 (Sometimes it is con) 162 182.19 P +1.39 (v) 252.67 182.19 P +1.39 (enient to ref) 257.42 182.19 P +1.39 (er to a de) 312.72 182.19 P +1.39 (vice b) 358.85 182.19 P +1.39 (y more than one name) 386.17 182.19 P +1.39 (. The DDL) 491.64 182.19 P +(syntax suppor) 162 170.19 T +(ts simple aliases) 224.65 170.19 T +(, one per line) 297.85 170.19 T +(.) 355.51 170.19 T +3 9 Q +(Figure 23: Alias de) 162 136.86 T +(vice name) 239.26 136.86 T +162 367 540 720 C +162 437 540 677 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.93 437 542.07 677 R +7 X +0 0 0 1 0 0 0 K +V +166.14 439.85 541.86 669.86 R +0 X +V +0.5 H +2 Z +N +162.71 444 537 672.57 R +7 X +V +0 X +N +165.43 447.71 533.29 669.14 R +7 X +V +6 9 Q +0 X +(class stdio) 165.43 663.14 T +({) 183.43 652.14 T +(verbs {get, set, monitorOn, monitorOff}) 183.43 641.14 T +(}) 183.43 630.14 T +(class magnet : stdio) 165.43 608.14 T +({) 183.43 597.14 T +(attributes) 183.43 586.14 T +({) 201.43 575.14 T +(bdl) 201.43 564.14 T +(ca {pv=<>.bdl};) 223.03 564.14 T +(current ca {pv=<>.val};) 201.43 553.14 T +(zpos) 201.43 542.14 T +( os {path=<>/phy/z};) 223.03 542.14 T +(length) 201.43 531.14 T +( os {path=<>/phy/len}) 233.83 531.14 T +(}) 201.43 520.14 T +(messages) 183.43 509.14 T +({) 201.43 498.14 T +(on) 201.43 487.14 T +(ca {pv=<>CSR.val, default=1};) 219.43 487.14 T +(off) 201.43 476.14 T +(ca {pv=<>CSR.val, default=0};) 224.83 476.14 T +(}) 201.43 465.14 T +(}) 183.43 454.14 T +162 367 540 720 C +0 0 612 792 C +162 207.86 540 348 C +162 253.86 540 281 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +160.29 253.86 541.71 281 R +7 X +0 0 0 1 0 0 0 K +V +165.79 256 541.5 273.85 R +0 X +V +0.5 H +2 Z +N +162.36 259.43 536.65 276.57 R +7 X +V +0 X +N +165.07 263.14 532.93 273.14 R +7 X +V +6 9 Q +0 X +(magnet : m1 m2 m3;) 165.07 267.14 T +162 207.86 540 348 C +0 0 612 792 C +162 81 540 188.86 C +162 106.71 540 133.86 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +160.29 106.71 541.71 133.86 R +7 X +0 0 0 1 0 0 0 K +V +165.79 108.86 541.5 126.71 R +0 X +V +0.5 H +2 Z +N +162.36 112.28 536.65 129.43 R +7 X +V +0 X +N +165.07 116 532.93 126 R +7 X +V +6 9 Q +0 X +(alias myname m1) 165.07 120 T +162 81 540 188.86 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "16" 70 +%%Page: "17" 71 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Name Resolution) 478.97 739 T +0 10 Q +(17) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "17" 71 +%%Page: "18" 72 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Channel Access Service) 54 739 T +0 10 Q +(18) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(6.) 141.32 710.67 T +(Channel Access Ser) 162 710.67 T +(vice) 296.75 710.67 T +0 10 Q +(EPICS / Channel Access v) 162 684.33 T +(ersion 3.12 is recommended.) 280.13 684.33 T +(F) 162 667.33 T +(eatures:) 167.81 667.33 T +(\245) 180 650.33 T +(Suppor) 189 650.33 T +(ts synchronous and asynchronous send\325) 221.64 650.33 T +(s) 399.56 650.33 T +(.) 404.41 650.33 T +(\245) 180 636.33 T +(T) 189 636.33 T +(r) 193.91 636.33 T +(ac) 197.14 636.33 T +(ks \336le descr) 207.5 636.33 T +(iptor registr) 260.44 636.33 T +(ation.) 310.35 636.33 T +(\245) 180 622.33 T +(F) 189 622.33 T +(etches data in nativ) 194.81 622.33 T +(e type \050type con) 280.72 622.33 T +(v) 351.67 622.33 T +(ersion done on client and not ser) 356.42 622.33 T +(v) 501.8 622.33 T +(er\051.) 506.55 622.33 T +(\245) 180 608.33 T +1.96 (Pro) 189 608.33 P +1.96 (vides a def) 204.41 608.33 P +1.96 (ault name ser) 256.38 608.33 P +1.96 (vice so that if a de) 321.18 608.33 P +1.96 (vice is not de\336ned, then an) 411.26 608.33 P +0.13 (EPICS channel access connection is attempted with the record name set equal) 189 596.33 P +(to the de) 189 584.33 T +(vice name) 227.62 584.33 T +(, and the \336eld name set equal to the attr) 273.04 584.33 T +(ib) 449.41 584.33 T +(ute name) 456.99 584.33 T +(.) 498.53 584.33 T +(Restr) 162 567.33 T +(ictions:) 186.04 567.33 T +(\245) 180 550.33 T +2.52 (Only suppor) 189 550.33 P +2.52 (ts set/get/monitorOn/monitorOff v) 245.83 550.33 P +2.52 (erbs and the pv and readonly) 397.89 550.33 P +-0.27 (tags) 189 538.33 P +-0.27 (. Suppor) 207.75 538.33 P +-0.27 (t f) 245.68 538.33 P +-0.27 (or arbitr) 253.44 538.33 P +-0.27 (ar) 287.52 538.33 P +-0.27 (y messages with def) 296.71 538.33 P +-0.27 (ault data will be in the ne) 386.18 538.33 P +-0.27 (xt release) 494.29 538.33 P +-0.27 (.) 537.22 538.33 P +(\245) 180 524.33 T +(Discards all e) 189 524.33 T +(xception callbac) 248.71 524.33 T +(ks from channel access in this v) 319.65 524.33 T +(ersion.) 460.56 524.33 T +(\245) 180 510.33 T +(Channel access secur) 189 510.33 T +(ity is not suppor) 287.52 510.33 T +(ted in this release) 357.95 510.33 T +(.) 436.17 510.33 T +(Compilation options:) 162 493.33 T +(\245) 180 476.33 T +3.21 (_CA_SYNC_CONN = perf) 189 476.33 P +3.21 (or) 311.54 476.33 P +3.21 (m connections synchronously) 320.68 476.33 P +3.21 (, w) 457.27 476.33 P +3.21 (aiting up to 4) 473.11 476.33 P +(seconds) 189 464.33 T +(.) 226.09 464.33 T +(\245) 180 450.33 T +(_CDEV_DEB) 189 450.33 T +(UG = pr) 248.36 450.33 T +(int v) 283.8 450.33 T +(erbose messages) 301.89 450.33 T +(\245) 180 436.33 T +(_EPICS_3_12 = if not de\336ned, use 3.11 calls instead.) 189 436.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "18" 72 +%%Page: "i" 73 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(i) 555.78 57 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 720 558 720 2 L +0.5 H +2 Z +N +72 72 558 72 2 L +N +72 504 558 504 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 32 Q +(Introduction to CDEV) 180 662.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 12 Q +(Over) 180 638 T +(vie) 207.47 638 T +(w of the Contr) 223.97 638 T +(ol De) 304.39 638 T +(vice Interface) 333.55 638 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(Chip W) 180 610 T +(atson, Jie Chen, Danjin W) 218.86 610 T +(u, W) 357.22 610 T +(alt Ak) 381.41 610 T +(ers) 411.18 610 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 180 582 T +(ersion 1.5 December 9, 1996) 187.04 582 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(TJNAF - Thomas Jeff) 180 554 T +(erson National Acceler) 293.66 554 T +(ator F) 414.25 554 T +(acility) 445 554 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "i" 73 +%%Page: "ii" 74 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(ii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(TRADEMARKS:) 54 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(UNIX is a registered tr) 180 569.33 T +(ademar) 278.26 569.33 T +(k of A) 312.31 569.33 T +(T&T in the USA and other countr) 336.68 569.33 T +(ies) 481.9 569.33 T +(.) 494.53 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(VxW) 180 545.33 T +(or) 200.81 545.33 T +(ks is a register tr) 209.85 545.33 T +(ademar) 283.1 545.33 T +(k of Wind Riv) 317.15 545.33 T +(er Systems) 375.8 545.33 T +(.) 425.66 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The X Windo) 180 521.33 T +(w System is a tr) 237.65 521.33 T +(ademar) 308.12 521.33 T +(k of Massachusetts Institute of T) 342.17 521.33 T +(echnology) 484.37 521.33 T +(.) 528.95 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(OSF/Motif and Motif are tr) 180 497.33 T +(ademar) 294.94 497.33 T +(ks of Open Softw) 328.99 497.33 T +(are F) 404.99 497.33 T +(oundation, Inc.) 428.03 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ultr) 180 473.33 T +(ix and DEC are registered tr) 195.7 473.33 T +(ademar) 319.53 473.33 T +(ks of Digital Equipment Cor) 353.58 473.33 T +(por) 475.03 473.33 T +(ation.) 489.38 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(HPUX is a registered tr) 180 449.33 T +(ademar) 282.15 449.33 T +(k of He) 316.2 449.33 T +(wlett P) 347.68 449.33 T +(ac) 377.29 449.33 T +(kard.) 387.65 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(SURA/CEB) 54 344.33 T +(AF:) 105.92 344.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.44 (The Southeaster) 180 344.33 P +4.44 (n Univ) 258.62 344.33 P +4.44 (ersities Research Association \050SURA\051 oper) 291.15 344.33 P +4.44 (ates the) 499.98 344.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.01 (Contin) 180 332.33 P +2.01 (uous Electron Beam Acceler) 208.8 332.33 P +2.01 (ator F) 340.89 332.33 P +2.01 (acility \050CEBAF\051 f) 368.52 332.33 P +2.01 (or the United States) 445.59 332.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Depar) 180 320.33 T +(tment of Energy under contr) 207.63 320.33 T +(act DE-A) 331.48 320.33 T +(C05-84ER40150.) 371.19 320.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DISCLAIMER:) 54 218.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.49 (This repor) 180 218.33 P +0.49 (t w) 225.9 218.33 P +0.49 (as prepared as an account of w) 239.02 218.33 P +0.49 (or) 381.4 218.33 P +0.49 (k sponsored b) 390.44 218.33 P +0.49 (y the United States) 454.03 218.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.18 (go) 180 206.33 P +2.18 (v) 190.97 206.33 P +2.18 (er) 195.72 206.33 P +2.18 (nment. Neither the United States nor the United States Depar) 204.86 206.33 P +2.18 (tment of) 501.68 206.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.04 (Energy) 180 194.33 P +1.04 (, nor an) 210.68 194.33 P +1.04 (y of their emplo) 246.52 194.33 P +1.04 (y) 317.69 194.33 P +1.04 (ees) 322.49 194.33 P +1.04 (, mak) 338.46 194.33 P +1.04 (es an) 363.75 194.33 P +1.04 (y w) 389.1 194.33 P +1.04 (arr) 404.99 194.33 P +1.04 (anty) 417.11 194.33 P +1.04 (, e) 435.01 194.33 P +1.04 (xpress or implied, or) 446.86 194.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.83 (assumes an) 180 182.33 P +1.83 (y legal liability or responsibility f) 235.59 182.33 P +1.83 (or the accur) 383.89 182.33 P +1.83 (acy) 440.24 182.33 P +1.83 (, completeness) 454.8 182.33 P +1.83 (, or) 523.72 182.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.68 (usefulness of an) 180 170.33 P +3.68 (y inf) 260.02 170.33 P +3.68 (or) 281.74 170.33 P +3.68 (mation, appar) 290.88 170.33 P +3.68 (atus) 355.59 170.33 P +3.68 (, product or process disclosed, or) 374.34 170.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.46 (represents that its use w) 180 158.33 P +2.46 (ould not infr) 298.11 158.33 P +2.46 (inge pr) 355.42 158.33 P +2.46 (iv) 388.59 158.33 P +2.46 (ately o) 395.56 158.33 P +2.46 (wned r) 427.33 158.33 P +2.46 (ights) 459.95 158.33 P +2.46 (. Ref) 480.92 158.33 P +2.46 (erence) 509.43 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.6 (herein to an) 180 146.33 P +1.6 (y speci\336c commercial product, process) 235.85 146.33 P +1.6 (, or ser) 413.79 146.33 P +1.6 (vice b) 448.4 146.33 P +1.6 (y tr) 475.92 146.33 P +1.6 (ade name) 491.3 146.33 P +1.6 (,) 537.22 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (mar) 180 134.33 P +2.12 (k, man) 197.37 134.33 P +2.12 (uf) 229.4 134.33 P +2.12 (acturer) 237.44 134.33 P +2.12 (, or otherwise) 268.06 134.33 P +2.12 (, does not necessar) 332.17 134.33 P +2.12 (ily constitute or imply its) 425.94 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (endorsement, recommendation, or f) 180 122.33 P +1.08 (a) 341.33 122.33 P +1.08 (v) 346.69 122.33 P +1.08 (or) 351.44 122.33 P +1.08 (ing b) 360.48 122.33 P +1.08 (y the United States go) 383.03 122.33 P +1.08 (v) 485.57 122.33 P +1.08 (er) 490.32 122.33 P +1.08 (nment or) 499.46 122.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (an) 180 110.33 P +0.83 (y agency thereof) 190.97 110.33 P +0.83 (. The vie) 266.26 110.33 P +0.83 (w and opinions of the authors e) 309.67 110.33 P +0.83 (xpressed herein do) 453.3 110.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.94 (not necessar) 180 98.33 P +1.94 (ily state or re\337ect those of the United States go) 239.34 98.33 P +1.94 (v) 464.01 98.33 P +1.94 (er) 468.76 98.33 P +1.94 (nment or an) 477.9 98.33 P +1.94 (y) 535 98.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(agency thereof) 180 86.33 T +(.) 245.85 86.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DOCUMENT D) 54 668.33 T +(A) 121.37 668.33 T +(TE:) 127.69 668.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(T) 180 668.33 T +(ab) 184.91 668.33 T +(le of ontents gener) 195.83 668.33 T +(ated: December 9, 1996 11:45 am) 278.56 668.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "ii" 74 +%%Page: "iii" 75 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iii) 551.34 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(T) 180 710.67 T +(ab) 187.43 710.67 T +(le of Contents) 203.63 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(List of Figures) 198 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(v) 553 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 180 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Introduction) 198 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 252.98 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(What is CDEV) 198 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(La) 198 648.33 T +(y) 208.82 648.33 T +(er) 213.62 648.33 T +(ing and Abstr) 222.66 648.33 T +(action) 281.48 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Inf) 198 636.33 T +(or) 208.82 636.33 T +(mation Hiding) 217.96 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198 624.33 T +(vice Object) 210.48 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Standard Messages) 198 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 289.12 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data Object) 198 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 252.98 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 180 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Basic Oper) 198 588.33 T +(ations on De) 247.36 588.33 T +(vices and Data) 303.2 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 369.74 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 180 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Asychronous Oper) 198 576.33 T +(ations) 280.71 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Callbac) 198 564.33 T +(k Object) 231.14 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(System Object) 198 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Group Object) 198 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Request Object) 198 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(File Descr) 198 516.33 T +(iptors and \322select\323) 243.15 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 325.26 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 180 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Error Handling) 198 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 180 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name Resolution) 198 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 198 480.33 T +(vDirector) 213.82 480.33 T +(y Object) 254.12 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ser) 198 468.33 T +(vice De\336nition) 213.86 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 546.88 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198 456.33 T +(vice Class De\336nition) 210.48 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 303.02 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15) 546.88 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Instance De\336nition) 198 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Aliases) 198 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 230.74 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 180 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Channel Access Ser) 198 420.33 T +(vice) 288.89 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 546.88 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iii" 75 +%%Page: "iv" 76 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iv) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iv" 76 +%%Page: "v" 77 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +( List of Figures) 498.98 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(v) 553 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(List of Figures) 180 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(Figure 1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample usage of the send method of a cdevDevice) 234 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(................................) 461.48 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 2.) 180 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Overview of cdevData operations) 234 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(............................................................) 383.64 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 3.) 180 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Three forms of the send command) 234 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..........................................................) 389.2 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 4.) 180 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Overview of the cdevCallback object and the cdevCallbackFunction) 234 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(......) 533.76 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 5.) 180 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Structure of the cdevCallback object) 234 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................................................) 394.76 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 6.) 180 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Usage of the pend method in the cdevSystem object) 234 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..............................) 467.04 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 7.) 180 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Synchronization methods in the cdevSystem object) 234 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(................................) 461.48 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 8.) 180 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample usage of the cdevGroup object) 234 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................................) 408.66 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 9.) 180 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample usage of the cdevRequestObject object) 234 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.....................................) 447.58 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 10.) 180 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Structure of the cdevRequestObject object) 234 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..............................................) 422.56 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 11.) 180 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(File descriptor routines of the cdevSystem object) 234 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(....................................) 450.36 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 12.) 180 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using CDEV file descriptors with the UNIX select function) 234 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(....................) 489.28 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 13.) 180 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Error handling mechanisms provided by the cdevSystem object) 234 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........) 514.3 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 14.) 180 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Enumerated severity codes generated by CDEV) 234 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................) 447.58 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 15.) 180 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Enumerated error codes generated by CDEV) 234 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................................) 433.68 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 546.88 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 16.) 180 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Obtaining a reference to the cdevDirectory device) 234 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(................................) 455.92 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 17.) 180 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Virtual form of the data in a cdevDirectory) 234 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.............................................) 419.78 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 18.) 180 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Syntax of the #include directive) 234 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..............................................................) 372.52 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 546.88 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 19.) 180 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample service definition) 234 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................................................................) 347.5 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 546.88 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 20.) 180 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample service definition) 234 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................................................................) 347.5 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15) 546.88 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 21.) 180 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample inherited class definition) 234 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(............................................................) 378.08 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 22.) 180 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Multiple instances of the magnet class) 234 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................................) 403.1 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 23.) 180 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Alias device name) 234 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..................................................................................) 316.92 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "v" 77 +%%Page: "vi" 78 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +( List of Figures) 54 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(vi) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "vi" 78 +%%Page: "1" 79 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. Introduction) 500.97 739 T +0 10 Q +(1) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(1.) 159.32 710.67 T +(Intr) 180 710.67 T +(oduction) 202.27 710.67 T +2 10 Q +(What is CDEV) 72 673.33 T +0 F +1.09 (The CDEV \050common de) 180 673.33 P +1.09 (vice\051 C++ class libr) 289.11 673.33 P +1.09 (ar) 376.73 673.33 P +1.09 (y is an object-or) 385.92 673.33 P +1.09 (iented fr) 459.92 673.33 P +1.09 (ame) 497.04 673.33 P +1.09 (w) 516.29 673.33 P +1.09 (or) 523.41 673.33 P +1.09 (k that) 532.45 673.33 P +1.76 (pro) 180 661.33 P +1.76 (vides a standard interf) 194.3 661.33 P +1.76 (ace betw) 297.65 661.33 P +1.76 (een an application and one or more under) 339.33 661.33 P +1.76 (lying) 537.44 661.33 P +4.52 (control pac) 180 649.33 P +4.52 (kages or systems) 233.23 649.33 P +4.52 (. Each under) 319.92 649.33 P +4.52 (lying pac) 385.81 649.33 P +4.52 (kage \050called a ser) 429.59 649.33 P +4.52 (vice\051 is) 522.37 649.33 P +1.18 (dynamically loaded at r) 180 637.33 P +1.18 (un-time) 285.96 637.33 P +1.18 (, allo) 319.15 637.33 P +1.18 (wing an application to access a ne) 341.31 637.33 P +1.18 (w ser) 500.52 637.33 P +1.18 (vice b) 525.9 637.33 P +1.18 (y) 553 637.33 P +-0.09 (name without re-compilation or re-linking. A major f) 180 625.33 P +-0.09 (eature of CDEV is its ability to hide) 404.68 625.33 P +2.93 (the implementation details of a par) 180 613.33 P +2.93 (ticular de) 347.88 613.33 P +2.93 (vice from the high le) 391.08 613.33 P +2.93 (v) 491.96 613.33 P +2.93 (el application) 496.71 613.33 P +0.07 (de) 180 601.33 P +0.07 (v) 190.82 601.33 P +0.07 (eloper) 195.57 601.33 P +0.07 (. This allo) 222.86 601.33 P +0.07 (ws ser) 265.63 601.33 P +0.07 (v) 294.89 601.33 P +0.07 (er implementation choices to be changed without breaking) 299.64 601.33 P +0.9 (high le) 180 589.33 P +0.9 (v) 210.06 589.33 P +0.9 (el client applications) 214.81 589.33 P +0.9 (. Additionally) 305.93 589.33 P +0.9 (, because the application is una) 362.52 589.33 P +0.9 (w) 506.89 589.33 P +0.9 (are of the) 513.96 589.33 P +4.86 (under) 180 577.33 P +4.86 (lying ser) 205.72 577.33 P +4.86 (vice\325) 248.11 577.33 P +4.86 (s speci\336c implementation, CDEV is a po) 267.61 577.33 P +4.86 (w) 473.91 577.33 P +4.86 (erful v) 481.03 577.33 P +4.86 (ehicle f) 512.87 577.33 P +4.86 (or) 549.11 577.33 P +(de) 180 565.33 T +(v) 190.82 565.33 T +(eloping por) 195.57 565.33 T +(tab) 245.44 565.33 T +(le applications) 259.14 565.33 T +(.) 322.35 565.33 T +-0.25 (The basic CDEV interf) 180 548.33 P +-0.25 (ace can be descr) 277.88 548.33 P +-0.25 (ibed through a) 353.43 548.33 P +3 F +-0.25 (de) 419.4 548.33 P +-0.25 (vice) 430.22 548.33 P +0 F +-0.25 (/) 448 548.33 P +3 F +-0.25 (message) 450.78 548.33 P +0 F +-0.25 ( par) 491.35 548.33 P +-0.25 (adigm. The) 508.23 548.33 P +3 F +2.36 (de) 180 536.33 P +2.36 (vice) 190.82 536.33 P +0 F +2.36 ( is not necessar) 208.6 536.33 P +2.36 (ily a ph) 285.85 536.33 P +2.36 (ysical object, r) 321.94 536.33 P +2.36 (ather) 389.9 536.33 P +2.36 (, it is a cde) 412.19 536.33 P +2.36 (vDe) 469.11 536.33 P +2.36 (vice object that) 486.59 536.33 P +1.42 (pro) 180 524.33 P +1.42 (vides a standard interf) 194.3 524.33 P +1.42 (ace to CDEV) 296.64 524.33 P +1.42 (. The application uses this interf) 356.03 524.33 P +1.42 (ace to send) 503.46 524.33 P +4.12 (messages to the de) 180 512.33 P +4.12 (vice) 279.32 512.33 P +4.12 (. When the cde) 296.95 512.33 P +4.12 (vDe) 376.26 512.33 P +4.12 (vice receiv) 393.74 512.33 P +4.12 (es this message it will) 444.84 512.33 P +1.36 (dynamically load the appropr) 180 500.33 P +1.36 (iate ser) 312.05 500.33 P +1.36 (vice \050as de\336ned in the CDEV de) 346.49 500.33 P +1.36 (vice de\336nition) 496.06 500.33 P +2.96 (\336le\051, and f) 180 488.33 P +2.96 (orw) 229.54 488.33 P +2.96 (ard the message to it. The ser) 245.49 488.33 P +2.96 (vice ma) 396.41 488.33 P +2.96 (y then perf) 433.52 488.33 P +2.96 (or) 486.39 488.33 P +2.96 (m an) 495.54 488.33 P +2.96 (y action) 520.58 488.33 P +(necessar) 180 476.33 T +(y to satisfy the application\325) 220.87 476.33 T +(s request.) 337.09 476.33 T +0.13 (The CDEV API is optimiz) 180 459.33 P +0.13 (ed f) 291.52 459.33 P +0.13 (or repetitiv) 308.03 459.33 P +0.13 (e oper) 354.6 459.33 P +0.13 (ations) 382.98 459.33 P +0.13 (, in par) 409.51 459.33 P +0.13 (ticular f) 440.74 459.33 P +0.13 (or monitor) 472.8 459.33 P +0.13 (ing v) 518.1 459.33 P +0.13 (alue) 539.1 459.33 P +3.2 (changes within a ser) 180 447.33 P +3.2 (v) 281.04 447.33 P +3.2 (er) 285.79 447.33 P +3.2 (. Asychronous oper) 294.18 447.33 P +3.2 (ations with callbac) 386.62 447.33 P +3.2 (ks are suppor) 473.95 447.33 P +3.2 (ted,) 541.32 447.33 P +0.11 (including asychronous error noti\336cation. Speci\336cally) 180 435.33 P +0.11 (, CDEV suppor) 408.4 435.33 P +0.11 (ts most f) 475.71 435.33 P +0.11 (eatures of) 513.42 435.33 P +(channel access \050the EPICS comm) 180 423.33 T +(unications protocol\051.) 331.62 423.33 T +2 F +(La) 72 394.33 T +(y) 83.47 394.33 T +(ering and) 88.93 394.33 T +(Abstraction) 72 382.33 T +0 F +1.59 (The CDEV libr) 180 394.33 P +1.59 (ar) 246.98 394.33 P +1.59 (y pro) 256.17 394.33 P +1.59 (vides a standard interf) 279.84 394.33 P +1.59 (ace to one or more under) 382.68 394.33 P +1.59 (lying control) 503.06 394.33 P +0.95 (pac) 180 382.33 P +0.95 (kages or systems) 195.92 382.33 P +0.95 (. Currently CDEV pro) 275.48 382.33 P +0.95 (vides suppor) 372.1 382.33 P +0.95 (t f) 430.14 382.33 P +0.95 (or EPICS channel access) 439.13 382.33 P +0.95 (,) 555.22 382.33 P +0.54 (tcl scr) 180 370.33 P +0.54 (ipts) 206.8 370.33 P +0.54 (, the A) 222.21 370.33 P +0.54 (CE comm) 251.9 370.33 P +0.54 (unications pac) 296.22 370.33 P +0.54 (kage \050a C++ class libr) 360.48 370.33 P +0.54 (ar) 459.23 370.33 P +0.54 (y o) 468.42 370.33 P +0.54 (v) 482.15 370.33 P +0.54 (er TCP/IP\051. The) 486.9 370.33 P +0.59 (A) 180 358.33 P +0.59 (CE pac) 186.37 358.33 P +0.59 (kage is used to comm) 219.55 358.33 P +0.59 (unicate with an on-line acceler) 319.08 358.33 P +0.59 (ator modeling pac) 455.85 358.33 P +0.59 (kage) 536.32 358.33 P +0.92 (and with COD) 180 346.33 P +0.92 (A, the CEBAF On-line Data Acquisition system. Access to the EPICS) 243.68 346.33 P +0.07 (archiv) 180 334.33 P +0.07 (e data will be added in a later release) 206.42 334.33 P +0.07 (. All data will be a) 372.46 334.33 P +0.07 (v) 450.41 334.33 P +0.07 (ailab) 455.16 334.33 P +0.07 (le through a single) 476.08 334.33 P +(API \050application prog) 180 322.33 T +(r) 272.72 322.33 T +(amming interf) 275.95 322.33 T +(ace\051.) 336.22 322.33 T +2 F +(Inf) 72 293.33 T +(ormation Hiding) 84.02 293.33 T +0 F +-0.24 (The ability to hide the implementation details of a par) 180 293.33 P +-0.24 (ticular de) 412.23 293.33 P +-0.24 (vice \050such as the choice) 452.26 293.33 P +3.9 (of records in EPICS\051 from the high le) 180 281.33 P +3.9 (v) 369.85 281.33 P +3.9 (el application de) 374.6 281.33 P +3.9 (v) 454.36 281.33 P +3.9 (eloper) 459.11 281.33 P +3.9 (, allo) 486.4 281.33 P +3.9 (ws ser) 511.27 281.33 P +3.9 (v) 544.36 281.33 P +3.9 (er) 549.11 281.33 P +4.84 (implementation choices to be changed without breaking all high le) 180 269.33 P +4.84 (v) 514.51 269.33 P +4.84 (el client) 519.26 269.33 P +0.46 (applications) 180 257.33 P +0.46 (. F) 232.65 257.33 P +0.46 (or e) 244.48 257.33 P +0.46 (xample) 261.86 257.33 P +0.46 (, se) 293.94 257.33 P +0.46 (v) 310.22 257.33 P +0.46 (er) 314.97 257.33 P +0.46 (al records ma) 323.76 257.33 P +0.46 (y be merged into a ne) 384.94 257.33 P +0.46 (w custom record) 483.74 257.33 P +(without changing applications which access those records through the CDEV API.) 180 245.33 T +2 F +(De) 72 216.33 T +(vice Object) 84.63 216.33 T +0 F +1.61 (The basic idea behind CDEV is that all I/O is perf) 180 216.33 P +1.61 (or) 412.56 216.33 P +1.61 (med b) 421.7 216.33 P +1.61 (y sending messages to) 450.9 216.33 P +0.4 (de) 180 204.33 P +0.4 (vices) 190.82 204.33 P +0.4 (. A de) 213.45 204.33 P +0.4 (vice is a named entity in the control system which can respond to a set) 240.07 204.33 P +1.71 (of messages such as) 180 192.33 P +3 F +1.71 (on) 283.53 192.33 P +0 F +1.71 ( or) 294.65 192.33 P +3 F +1.71 (off) 312.51 192.33 P +0 F +1.71 ( or) 323.63 192.33 P +3 F +1.71 (get current) 341.49 192.33 P +0 F +1.71 (. Fur) 391 192.33 P +1.71 (ther) 413.67 192.33 P +1.71 (, a de) 430.4 192.33 P +1.71 (vice is a vir) 458.53 192.33 P +1.71 (tual entity) 513.49 192.33 P +3.22 (potentially spanning m) 180 180.33 P +3.22 (ultiple ser) 285.83 180.33 P +3.22 (v) 332.14 180.33 P +3.22 (ers and ser) 336.89 180.33 P +3.22 (vices such as channel access) 393.65 180.33 P +3.22 (, an) 538.1 180.33 P +(archiv) 180 168.33 T +(er) 206.42 168.33 T +(, and a static database) 214.81 168.33 T +(.) 315.28 168.33 T +2.1 (Each de) 180 151.33 P +2.1 (vice and message pair is mapped to a unique ser) 218.49 151.33 P +2.1 (vice \050such as channel) 455.55 151.33 P +0.61 (access\051 and ser) 180 139.33 P +0.61 (vice dependent data \050such as the process v) 252.09 139.33 P +0.61 (ar) 448.97 139.33 P +0.61 (iab) 458.01 139.33 P +0.61 (le name in EPICS\051.) 471.15 139.33 P +0.03 (This mapping is k) 180 127.33 P +0.03 (ept in a name ser) 257.69 127.33 P +0.03 (vice) 335.36 127.33 P +0.03 (, and is ultimately initializ) 352.99 127.33 P +0.03 (ed from an ASCII \336le) 462.99 127.33 P +0.03 (.) 555.22 127.33 P +1.17 (The designer/maintainer of the ser) 180 115.33 P +1.17 (v) 337.26 115.33 P +1.17 (er w) 342.01 115.33 P +1.17 (ould typically be the person responsib) 361.97 115.33 P +1.17 (le f) 534.9 115.33 P +1.17 (or) 549.11 115.33 P +(k) 180 103.33 T +(eeping the mapping current.) 184.8 103.33 T +FMENDPAGE +%%EndPage: "1" 79 +%%Page: "2" 80 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. Introduction) 54 739 T +0 10 Q +(2) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +2 10 Q +(Standar) 54 713.33 T +(d) 91.03 713.33 T +(Messa) 54 701.33 T +(g) 84.47 701.33 T +(es) 90.68 701.33 T +0 F +0.72 (Most de) 162 713.33 P +0.72 (vices will implement a n) 197.99 713.33 P +0.72 (umber of attr) 305.81 713.33 P +0.72 (ib) 364.1 713.33 P +0.72 (utes which ma) 371.68 713.33 P +0.72 (y be read or wr) 436.74 713.33 P +0.72 (itten. In) 506.48 713.33 P +1.32 (order to f) 162 701.33 P +1.32 (acilitate de) 204.37 701.33 P +1.32 (v) 253.19 701.33 P +1.32 (eloping gener) 257.94 701.33 P +1.32 (ic applications) 320 701.33 P +1.32 (, the f) 383.98 701.33 P +1.32 (ollo) 411.34 701.33 P +1.32 (wing standard messages) 426.75 701.33 P +(are recommended f) 162 689.33 T +(or de) 248.4 689.33 T +(vices) 270.89 689.33 T +(, where) 293.52 689.33 T +3 F +(attr) 329.09 689.33 T +(ib) 343.69 689.33 T +0 F +( is some attr) 351.47 689.33 T +(ib) 406.08 689.33 T +(ute of the de) 413.66 689.33 T +(vice:) 468.96 689.33 T +4 9 Q +(set) 180 673 T +5 F +(attrib) 201.6 673 T +4 F +( => Set the value of the attribute) 234 673 T +(get) 180 662 T +5 F +(attrib) 201.6 662 T +4 F +( => Get the value of the attribute) 234 662 T +-0.51 (monitorOn) 180 651 P +5 F +-0.51 (attrib) 233.49 651 P +4 F +-0.51 ( => Start monitoring the value of the attribute) 265.89 651 P +-0.14 (monitorOff) 180 640 P +5 F +-0.14 (attrib) 239.26 640 P +4 F +-0.14 ( => Stop monitoring the value of the attribute) 271.66 640 P +2 10 Q +(Data Object) 54 611.33 T +0 F +0.91 (The message sent to the de) 162 611.33 P +0.91 (vice ma) 290.21 611.33 P +0.91 (y ha) 325.27 611.33 P +0.91 (v) 344.89 611.33 P +0.91 (e an associated data object. F) 349.64 611.33 P +0.91 (or e) 487.3 611.33 P +0.91 (xample) 505.14 611.33 P +0.91 (,) 537.22 611.33 P +-0.23 (the message) 162 599.33 P +3 F +-0.23 (set current) 221.57 599.33 P +0 F +-0.23 ( will ha) 268.59 599.33 P +-0.23 (v) 298.49 599.33 P +-0.23 (e an associated) 303.24 599.33 P +3 F +-0.23 (v) 375.38 599.33 P +-0.23 (alue) 380.13 599.33 P +0 F +-0.23 ( f) 399.03 599.33 P +-0.23 (or the ne) 404.06 599.33 P +-0.23 (w current setting. This) 442.87 599.33 P +(v) 162 587.33 T +(alue is passed as an additional argument on the send call.) 166.75 587.33 T +2.64 (Data retur) 162 570.33 P +2.64 (ned from the ser) 209.35 570.33 P +2.64 (v) 290.38 570.33 P +2.64 (er to the client ma) 295.13 570.33 P +2.64 (y contain m) 384.87 570.33 P +2.64 (ultiple tagged v) 441.18 570.33 P +2.64 (alues) 513.47 570.33 P +2.64 (,) 537.22 570.33 P +1.92 (including) 162 558.33 P +3 F +1.92 (v) 206.16 558.33 P +1.92 (alue) 210.91 558.33 P +0 F +1.92 (,) 229.66 558.33 P +3 F +1.92 (status) 237.14 558.33 P +0 F +1.92 (, and) 263.67 558.33 P +3 F +1.92 ( timestamp) 287.83 558.33 P +0 F +1.92 (. Each of these items is e) 338.3 558.33 P +1.92 (xtr) 461.23 558.33 P +1.92 (acted from the) 472.24 558.33 P +1.5 (retur) 162 546.33 P +1.5 (ned data object b) 182.81 546.33 P +1.5 (y specifying a name or an integer tag. An) 263.83 546.33 P +1.5 (y data object ma) 457.43 546.33 P +1.5 (y) 535 546.33 P +2.68 (contain an arbitr) 162 534.33 P +2.68 (ar) 238.97 534.33 P +2.68 (y n) 248.16 534.33 P +2.68 (umber of tagged entr) 264.08 534.33 P +2.68 (ies) 365.11 534.33 P +2.68 (, allo) 377.74 534.33 P +2.68 (wing consider) 401.4 534.33 P +2.68 (ab) 465.11 534.33 P +2.68 (le \337e) 476.03 534.33 P +2.68 (xibility in) 499.54 534.33 P +(de\336ning future clients and ser) 162 522.33 T +(v) 292.92 522.33 T +(ers) 297.67 522.33 T +(.) 311.41 522.33 T +3 F +0.83 (Ac) 162 505.33 P +0.83 (kno) 173.47 505.33 P +0.83 (wledgment: This w) 189.44 505.33 P +0.83 (or) 273.8 505.33 P +0.83 (k der) 282.84 505.33 P +0.83 (iv) 306.04 505.33 P +0.83 (es some of its ideas about de) 313.01 505.33 P +0.83 (vices and messages) 447.75 505.33 P +1.38 (from w) 162 493.33 P +1.38 (or) 193.28 493.33 P +1.38 (k done at Argonne b) 202.32 493.33 P +1.38 (y Claude Saunders on a de) 297.69 493.33 P +1.38 (vice or) 425.46 493.33 P +1.38 (iented la) 456.43 493.33 P +1.38 (y) 495.31 493.33 P +1.38 (er abo) 500.11 493.33 P +1.38 (v) 529.69 493.33 P +1.38 (e) 534.44 493.33 P +0.22 (channel access) 162 481.33 P +0.22 (. Much additional analysis & design w) 230.99 481.33 P +0.22 (or) 398.36 481.33 P +0.22 (k has been done b) 407.39 481.33 P +0.22 (y members) 490.33 481.33 P +(of the EPICS collabor) 162 469.33 T +(ation.) 257.5 469.33 T +FMENDPAGE +%%EndPage: "2" 80 +%%Page: "3" 81 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. Basic Operations on Devices and Data) 393.43 739 T +0 10 Q +(3) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(2.) 159.32 710.67 T +(Basic Operations on De) 180 710.67 T +(vices and Data) 337.72 710.67 T +0 10 Q +0.44 (The basic user deals only with the de) 180 684.33 P +0.44 (vice and data objects) 347.28 684.33 P +0.44 (. The de) 442.38 684.33 P +0.44 (vice is created b) 479.64 684.33 P +0.44 (y) 553 684.33 P +0.54 (name) 180 672.33 P +0.54 (, and I/O consists of sending messages to this de) 204.86 672.33 P +0.54 (vice) 427.34 672.33 P +0.54 (. The de) 444.97 672.33 P +0.54 (vice object is the) 482.45 672.33 P +0.8 (simplest I/O object to use: a single de) 180 660.33 P +0.8 (vice \050magnet, vie) 351.47 660.33 P +0.8 (w) 428.45 660.33 P +0.8 (er) 435.57 660.33 P +0.8 (, etc.\051 ma) 443.96 660.33 P +0.8 (y be completely) 486.93 660.33 P +0.36 (controlled from a single de) 180 648.33 P +0.36 (vice object, with data being passed b) 298.39 648.33 P +0.36 (y 2 data objects \050one) 463.75 648.33 P +0.2 (f) 180 636.33 P +0.2 (or output, another f) 182.48 636.33 P +0.2 (or retur) 267.27 636.33 P +0.2 (ned results; dataless commands w) 299.95 636.33 P +0.2 (ould not require either\051.) 454.03 636.33 P +0.55 (The f) 180 624.33 P +0.55 (ollo) 203.04 624.33 P +0.55 (wing sample code reads the magnet current from one magnet, and sets the) 218.45 624.33 P +(magnet current f) 180 612.33 T +(or a second magnet to that v) 252.51 612.33 T +(alue:) 379 612.33 T +3 9 Q +(Figure 1: Sample usage of the send method of a cde) 180 579 T +(vDe) 391.85 579 T +(vice) 407.58 579 T +0 10 Q +2.25 (The send call, which is synchronous) 180 340.33 P +2.25 (, tak) 351.15 340.33 P +2.25 (es 3 arguments) 372.1 340.33 P +2.25 (, and retur) 445.37 340.33 P +2.25 (ns an integer) 495.69 340.33 P +(status:) 180 328.33 T +6 9 Q +(int send\050char* msg, cdevData& out, cdevData& result\051;) 198 312 T +0 10 Q +0.22 (Lik) 180 295.33 P +0.22 (e all CDEV calls) 192.58 295.33 P +0.22 (, a retur) 264.78 295.33 P +0.22 (n code of 0 means success \050error handling is descr) 299.94 295.33 P +0.22 (ibed in) 528.32 295.33 P +0.19 (a later section\051. The \336rst argument to) 180 283.33 P +3 F +0.19 (send) 347.52 283.33 P +0 F +0.19 ( is a char) 369.2 283.33 P +0.19 (acter str) 410.25 283.33 P +0.19 (ing message) 446.71 283.33 P +0.19 (. The de) 503.45 283.33 P +0.19 (vice) 540.22 283.33 P +0.41 (name and this str) 180 271.33 P +0.41 (ing uniquely deter) 258.08 271.33 P +0.41 (mine the under) 338.07 271.33 P +0.41 (lying ser) 405.74 271.33 P +0.41 (vice to use) 443.68 271.33 P +0.41 (, and whate) 492.14 271.33 P +0.41 (v) 544.36 271.33 P +0.41 (er) 549.11 271.33 P +2.06 (addressing data that ser) 180 259.33 P +2.06 (vice needs to locate the ser) 293.77 259.33 P +2.06 (v) 426.1 259.33 P +2.06 (er) 430.85 259.33 P +2.06 (. The \336rst) 439.24 259.33 P +3 F +2.06 (send) 489.89 259.33 P +0 F +2.06 ( oper) 511.57 259.33 P +2.06 (ation) 536.32 259.33 P +0.57 (automatically connects to the requested ser) 180 247.33 P +0.57 (vice) 376.01 247.33 P +0.57 (, initializing an) 393.64 247.33 P +0.57 (y under) 457.42 247.33 P +0.57 (lying pac) 491.49 247.33 P +0.57 (kages) 531.32 247.33 P +(as needed.) 180 235.33 T +0.11 (The second and third arguments are outbound and result data of type cde) 180 218.33 P +0.11 (vData. This) 507.32 218.33 P +1.75 (is a composite data object which ma) 180 206.33 P +1.75 (y contain an arbitr) 350.82 206.33 P +1.75 (ar) 435.44 206.33 P +1.75 (y n) 444.63 206.33 P +1.75 (umber of data v) 459.62 206.33 P +1.75 (alues) 534.1 206.33 P +1.45 (tagged with an integer tag. The data is self-descr) 180 194.33 P +1.45 (ibing to the e) 407.95 194.33 P +1.45 (xtent that cde) 469.25 194.33 P +1.45 (vData) 531.88 194.33 P +2.38 (k) 180 182.33 P +2.38 (eeps tr) 184.8 182.33 P +2.38 (ac) 217.65 182.33 P +2.38 (k of the data type) 228.01 182.33 P +2.38 (, and can automatically con) 314.12 182.33 P +2.38 (v) 444.63 182.33 P +2.38 (er) 449.38 182.33 P +2.38 (t betw) 458.67 182.33 P +2.38 (een data types) 487.63 182.33 P +0.85 (through C++ function o) 180 170.33 P +0.85 (v) 284.13 170.33 P +0.85 (er) 288.88 170.33 P +0.85 (loading or b) 297.92 170.33 P +0.85 (y e) 351.67 170.33 P +0.85 (xplicit direction from the caller) 365.56 170.33 P +0.85 (. The integer) 500.16 170.33 P +-0.05 (tags are not kno) 180 158.33 P +-0.05 (wn to the user at compile time \050i.e) 251.42 158.33 P +-0.05 (., no header \336les required\051, and can) 400.43 158.33 P +0.77 (be ref) 180 146.33 P +0.77 (erred to b) 206.04 146.33 P +0.77 (y char) 250.19 146.33 P +0.77 (acter str) 278.09 146.33 P +0.77 (ing equiv) 315.14 146.33 P +0.77 (alents) 355.68 146.33 P +0.77 (. The cde) 382.21 146.33 P +0.77 (vData class k) 425.14 146.33 P +0.77 (eeps tr) 485.95 146.33 P +0.77 (ac) 517.19 146.33 P +0.77 (k of all) 527.55 146.33 P +2.33 (integer tags and their char) 180 134.33 P +2.33 (acter str) 305.4 134.33 P +2.33 (ing equiv) 344.01 134.33 P +2.33 (alents) 386.11 134.33 P +2.33 (. Char) 412.64 134.33 P +2.33 (acter str) 442.11 134.33 P +2.33 (ing tags ma) 480.71 134.33 P +2.33 (y be) 536.77 134.33 P +1.8 (con) 180 122.33 P +1.8 (v) 195.92 122.33 P +1.8 (er) 200.67 122.33 P +1.8 (ted to integer tags at r) 209.96 122.33 P +1.8 (un time to impro) 316.38 122.33 P +1.8 (v) 393.31 122.33 P +1.8 (e perf) 398.06 122.33 P +1.8 (or) 425.13 122.33 P +1.8 (mance) 434.27 122.33 P +1.8 (. The f) 464.13 122.33 P +1.8 (ollo) 495.77 122.33 P +1.8 (wing code) 511.18 122.33 P +(demonstr) 180 110.33 T +(ates ho) 221.58 110.33 T +(w to inser) 254.23 110.33 T +(t v) 297.42 110.33 T +(alues into and e) 307.73 110.33 T +(xtr) 378.03 110.33 T +(act v) 389.04 110.33 T +(alues from a cde) 409.91 110.33 T +(vData object:) 483.53 110.33 T +180 81 558 691 C +180 371 558 576 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +125.07 371 612.93 576 R +7 X +0 0 0 1 0 0 0 K +V +186.17 379.09 561.88 570.52 R +0 X +V +0.5 H +2 Z +N +182.4 382.24 554.91 573.67 R +7 X +V +0 X +N +184.62 388.62 552.24 571.47 R +7 X +V +6 9 Q +0 X +(void main \050\051) 184.62 565.47 T +({) 202.62 554.47 T +(// *************************************************************) 202.62 543.47 T +(// * Get references to the 2 devices) 202.62 532.47 T +(// *************************************************************) 202.62 521.47 T +(cdevDevice& mag1 = cdevDevice::attachRef \050\322Magnet1\323\051;) 202.62 510.48 T +(cdevDevice& mag2 = cdevDevice::attachRef \050\322Magnet2\323\051;) 202.62 499.48 T +(cdevData result;) 202.62 488.48 T +(// *************************************************************) 202.62 466.48 T +(// * Get the current from the first magnet and use it to set) 202.62 455.48 T +(// * the current on the second.) 202.62 444.48 T +(// *************************************************************) 202.62 433.48 T +(mag1.send\050\322get current\323, NULL, result\051;) 202.62 422.48 T +(mag2.send\050\322set current\323, result, NULL\051;) 202.62 411.48 T +(}) 202.62 400.48 T +180 81 558 691 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "3" 81 +%%Page: "4" 82 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. Basic Operations on Devices and Data) 54 739 T +0 10 Q +(4) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +3 F +(Figure 2: Ov) 162 714 T +(er) 213.79 714 T +(vie) 222.07 714 T +(w of cde) 233.39 714 T +(vData oper) 266.63 714 T +(ations) 310.56 714 T +0 10 Q +1.55 (The last line abo) 162 527.48 P +1.55 (v) 239.89 527.48 P +1.55 (e demonstr) 244.64 527.48 P +1.55 (ates using oper) 296.11 527.48 P +1.55 (ator o) 367.49 527.48 P +1.55 (v) 394.47 527.48 P +1.55 (er) 399.22 527.48 P +1.55 (loading to e) 408.26 527.48 P +1.55 (xtr) 462.77 527.48 P +1.55 (act the \322v) 473.78 527.48 P +1.55 (alue\323) 517.77 527.48 P +1.2 (item from the data object; i.e) 162 515.48 P +1.2 (., the char) 294.01 515.48 P +1.2 (acter tag \322v) 340.78 515.48 P +1.2 (alue\323 is the def) 392.94 515.48 P +1.2 (ault tag to use in) 461.83 515.48 P +0.19 (e) 162 503.48 P +0.19 (xtr) 167.26 503.48 P +0.19 (acting a data item f) 178.27 503.48 P +0.19 (or the \322=\323 function o) 263.22 503.48 P +0.19 (v) 350.83 503.48 P +0.19 (er) 355.58 503.48 P +0.19 (load. This f) 364.61 503.48 P +0.19 (or) 413.61 503.48 P +0.19 (m is a) 422.75 503.48 P +0.19 (v) 449.6 503.48 P +0.19 (ailab) 454.35 503.48 P +0.19 (le f) 475.27 503.48 P +0.19 (or all scalar) 488.5 503.48 P +(types suppor) 162 491.48 T +(ted b) 219.65 491.48 T +(y cde) 241.69 491.48 T +(vData.) 265.29 491.48 T +1.2 (Most I/O oper) 162 474.48 P +1.2 (ations use the \322v) 224.87 474.48 P +1.2 (alue\323 tag to tr) 301.58 474.48 P +1.2 (ansmit a single v) 363.99 474.48 P +1.2 (alue \050scalar or arr) 441.79 474.48 P +1.2 (a) 523.63 474.48 P +1.2 (y\051.) 528.89 474.48 P +2.22 (Other commonly used tags are \322status\323 and \322time\323 \050a POSIX time str) 162 462.48 P +2.22 (uct\051. These) 487.76 462.48 P +-0.12 (tagged data items are optionally retur) 162 450.48 P +-0.12 (ned b) 326.71 450.48 P +-0.12 (y some ser) 351.41 450.48 P +-0.12 (v) 400.36 450.48 P +-0.12 (ers under the control of the I/O) 405.11 450.48 P +(conte) 162 438.48 T +(xt \050see belo) 186.16 438.48 T +(w f) 237.7 438.48 T +(or changing the def) 250.18 438.48 T +(ault conte) 335.49 438.48 T +(xt\051.) 378.55 438.48 T +1.93 (In this release) 162 421.48 P +1.93 (, cde) 227.95 421.48 P +1.93 (vData suppor) 251.26 421.48 P +1.93 (ts the f) 313.06 421.48 P +1.93 (ollo) 346.63 421.48 P +1.93 (wing data types:) 362.04 421.48 P +3 F +1.93 (unsigned char) 442.86 421.48 P +1.93 (, shor) 507.1 421.48 P +1.93 (t,) 534.44 421.48 P +0.45 (unsigned shor) 162 409.48 P +0.45 (t, int, unsigned int, long, unsigned long, \337oat, doub) 225.66 409.48 P +0.45 (le) 451.95 409.48 P +0 F +0.45 (,) 459.58 409.48 P +3 F +0.45 (char) 465.59 409.48 P +0.45 (acter str) 484.94 409.48 P +0.45 (ings) 521.66 409.48 P +0 F +(and) 162 397.48 T +3 F +(time stamp) 181.46 397.48 T +(.) 230.01 397.48 T +0 F +(All data types ma) 235.57 397.48 T +(y be either scalar or m) 311.97 397.48 T +(ulti-dimensional arr) 410.79 397.48 T +(a) 495.15 397.48 T +(ys) 500.41 397.48 T +(.) 510.26 397.48 T +162 81 540 720 C +162 558.14 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.52 558.14 542.48 711 R +7 X +0 0 0 1 0 0 0 K +V +166.55 561.71 542.27 703.86 R +0 X +V +0.5 H +2 Z +N +163.12 565.14 538.13 706.57 R +7 X +V +0 X +N +165.84 568.86 535.13 703.14 R +7 X +V +6 9 Q +0 X +(cdevData d1, d2;) 165.84 697.14 T +(int valtag;) 165.84 686.14 T +(float x, x2;) 165.84 675.14 T +(int status;) 165.84 664.14 T +(...) 165.84 653.14 T +(d1.tagC2I\050\322value\323,&valtag\051; // get the integer tag for \322value\323) 165.84 642.14 T +(...) 165.84 631.14 T +(d1.insert\050\322value\323,37.9\051; // insert using a character tag) 165.84 620.14 T +(device.send\050\322message\323,d1,d2\051; // send d1, get back d2) 165.84 609.14 T +(d2.get\050valtag,&x\051; // get \322value\323 from d2 into x) 165.84 598.14 T +(d2.get\050\322status\323,&status\051; // extract the \322status\323) 165.84 587.14 T +(x2 = d2; // get \322value\323 into x2 \050= overload\051) 165.84 576.14 T +162 81 540 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "4" 82 +%%Page: "5" 83 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 449.45 739 T +0 10 Q +(5) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(3.) 159.32 710.67 T +(Asyc) 180 710.67 T +(hr) 213.32 710.67 T +(onous Operations) 227.04 710.67 T +0 10 Q +1.79 (In addition to the synchronous send, there are 2 asynchronous f) 180 684.33 P +1.79 (or) 480 684.33 P +1.79 (ms f) 489.14 684.33 P +1.79 (or sending) 509.52 684.33 P +(messages) 180 672.33 T +(. The class de\336nition f) 225.42 672.33 T +(or all three f) 321.83 672.33 T +(or) 374.33 672.33 T +(ms is giv) 383.47 672.33 T +(en belo) 422.11 672.33 T +(w) 454.76 672.33 T +(.) 461.38 672.33 T +3 9 Q +(Figure 3: Three f) 180 639 T +(or) 248.76 639 T +(ms of the send command) 256.99 639 T +0 10 Q +1.17 (The second f) 180 506.76 P +1.17 (or) 239.86 506.76 P +1.17 (m, sendNoBloc) 249 506.76 P +1.17 (k, tak) 317.78 506.76 P +1.17 (es the same arguments as send b) 342.65 506.76 P +1.17 (ut completes) 500.13 506.76 P +1.21 (asynchronously) 180 494.76 P +1.21 (. That is) 248.47 494.76 P +1.21 (, the result will be in) 286.3 494.76 P +1.21 (v) 379.94 494.76 P +1.21 (alid until some synchronizing action is) 384.69 494.76 P +2.44 (tak) 180 482.76 P +2.44 (en \050discussed belo) 193.14 482.76 P +2.44 (w\051. The third f) 281.25 482.76 P +2.44 (or) 349.41 482.76 P +2.44 (m retur) 358.55 482.76 P +2.44 (ns the result to a callbac) 392.91 482.76 P +2.44 (k function) 512.76 482.76 P +0.66 (speci\336ed as par) 180 470.76 P +0.66 (t of the callbac) 251.76 470.76 P +0.66 (k argument. F) 318.03 470.76 P +0.66 (or each of these asychronous calls) 380.75 470.76 P +0.66 (, the) 537.88 470.76 P +0.19 (message ma) 180 458.76 P +0.19 (y be b) 237.13 458.76 P +0.19 (uff) 264.56 458.76 P +0.19 (ered b) 275.38 458.76 P +0.19 (y the under) 303.73 458.76 P +0.19 (lying ser) 354.3 458.76 P +0.19 (vice) 392.02 458.76 P +0.19 (, so that upon retur) 409.65 458.76 P +0.19 (n from the call) 494.62 458.76 P +-0.02 (there is no guar) 180 446.76 P +-0.02 (antee that the message has e) 249.32 446.76 P +-0.02 (v) 380.66 446.76 P +-0.02 (en been sent y) 385.41 446.76 P +-0.02 (et. T) 450.74 446.76 P +-0.02 (r) 469.53 446.76 P +-0.02 (ansmission ma) 472.76 446.76 P +-0.02 (y be) 539.12 446.76 P +2.28 (f) 180 434.76 P +2.28 (orced with a \337ush call using the cde) 182.48 434.76 P +2.28 (vSystem object descr) 355.97 434.76 P +2.28 (ibed belo) 455.71 434.76 P +2.28 (w) 498.42 434.76 P +2.28 (. A \337ush is) 505.04 434.76 P +(automatically perf) 180 422.76 T +(or) 258.06 422.76 T +(med if pend is called.) 267.2 422.76 T +2 F +(Callbac) 72 393.76 T +(k Object) 107.37 393.76 T +0 F +0.85 (The callbac) 180 393.76 P +0.85 (k object is a simple object containing 2 items: a function pointer) 231.78 393.76 P +0.85 (, and an) 520.17 393.76 P +1.21 (arbitr) 180 381.76 P +1.21 (ar) 202.68 381.76 P +1.21 (y user argument. As an e) 211.87 381.76 P +1.21 (xample) 329.33 381.76 P +1.21 (, the f) 361.41 381.76 P +1.21 (ollo) 388.55 381.76 P +1.21 (wing code fr) 403.96 381.76 P +1.21 (agment demonstr) 460.18 381.76 P +1.21 (ates) 539.1 381.76 P +1.85 (monitor) 180 369.76 P +1.85 (ing the magnet current asynchronously \050the third argument to the callbac) 213.49 369.76 P +1.85 (k) 553 369.76 P +(function is discussed later\051:) 180 357.76 T +3 9 Q +(Figure 4: Ov) 180 324.43 T +(er) 231.79 324.43 T +(vie) 240.07 324.43 T +(w of the cde) 251.39 324.43 T +(vCallbac) 299.65 324.43 T +(k object and the cde) 333.97 324.43 T +(vCallbac) 414.25 324.43 T +(kFunction) 448.58 324.43 T +180 419.43 558 691 C +180 537.43 558 636 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.63 537.43 560.37 636 R +7 X +0 0 0 1 0 0 0 K +V +184.44 541.71 560.15 628.86 R +0 X +V +0.5 H +2 Z +N +181.01 545.14 555.3 631.57 R +7 X +V +0 X +N +183.72 549.57 551.58 628.14 R +7 X +V +6 9 Q +0 X +(class cdevDevice:) 183.72 622.14 T +({) 183.72 611.14 T +(public:) 183.72 600.14 T +(int send \050char* msg, cdevData& out, cdevData& result\051;) 201.72 589.14 T +(int sendNoBlock \050char* msg, cdevData& out, cdevData& result\051;) 201.72 578.14 T +(int sendCallback \050char* msg, cdevData& out, cdevCallback cb\051;) 201.72 567.14 T +(};) 183.72 556.14 T +180 419.43 558 691 C +0 0 612 792 C +180 81 558 400.43 C +180 130 558 321.43 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.52 130 560.48 321.43 R +7 X +0 0 0 1 0 0 0 K +V +184.55 135.71 560.27 314.29 R +0 X +V +0.5 H +2 Z +N +181.12 139.14 555.41 317 R +7 X +V +0 X +N +183.84 142.14 551.7 313.57 R +7 X +V +6 9 Q +0 X +(// declare the callback func) 183.84 307.57 T +(cdevCallbackFunction gotit;) 183.84 296.57 T +(// create callback object) 183.84 274.57 T +(cdevCallback callbk\050gotit, myarg\051;) 183.84 263.57 T +(...) 183.84 252.57 T +(mag1.sendCallback\050\322monitorOn current\323,NULL,callbk\051;) 183.84 241.57 T +(...) 183.84 230.57 T +(void gotit\050int status, void* userarg, cdevRequestObject& reqobj,) 183.84 208.57 T +(cdevData& result\051) 237.84 197.57 T +({) 201.84 186.57 T +(float f = result;) 201.84 175.57 T +(printf\050\322new value is %f\134n\323,f\051;) 201.84 164.57 T +(}) 201.84 153.57 T +180 81 558 400.43 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "5" 83 +%%Page: "6" 84 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 54 739 T +0 10 Q +(6) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 10 Q +(The f) 162 713.33 T +(ollo) 184.49 713.33 T +(wing code de\336nes the callbac) 199.9 713.33 T +(k \050the cde) 330.32 713.33 T +(vRequestObject is descr) 373.93 713.33 T +(ibed belo) 482.45 713.33 T +(w\051:) 522.88 713.33 T +3 9 Q +(Figure 5: Str) 162 680 T +(ucture of the cde) 214.15 680 T +(vCallbac) 280.93 680 T +(k object) 315.25 680 T +2 10 Q +(System Object) 54 511.05 T +0 F +0.1 (W) 162 511.05 P +0.1 (aiting f) 171.04 511.05 P +0.1 (or completion of asychronous oper) 200.3 511.05 P +0.1 (ations ma) 354.02 511.05 P +0.1 (y be accomplished in one of tw) 397.18 511.05 P +0.1 (o) 534.44 511.05 P +1.36 (w) 162 499.05 P +1.36 (a) 169.07 499.05 P +1.36 (ys: \0501\051 using g) 174.33 499.05 P +1.36 (roups) 241.1 499.05 P +1.36 (, and \0502\051 using the system object. The system object k) 265.96 499.05 P +1.36 (eeps) 518.32 499.05 P +2.71 (tr) 162 487.05 P +2.71 (ac) 168.01 487.05 P +2.71 (k of all de) 178.37 487.05 P +2.71 (vices) 229 487.05 P +2.71 (, and contains methods f) 251.63 487.05 P +2.71 (or \337ushing, polling, and pending f) 371.11 487.05 P +2.71 (or) 531.11 487.05 P +(asychronous oper) 162 475.05 T +(ations) 241.38 475.05 T +(.) 267.91 475.05 T +3 9 Q +(Figure 6: Usage of the pend method in the cde) 162 441.71 T +(vSystem object) 349.84 441.71 T +0 10 Q +(The f) 162 313.76 T +(ollo) 184.49 313.76 T +(wing class interf) 199.9 313.76 T +(ace sho) 270.73 313.76 T +(ws the f) 305.6 313.76 T +(or) 339.76 313.76 T +(ms f) 348.9 313.76 T +(or each synchronization method:) 367.49 313.76 T +3 9 Q +(Figure 7: Synchronization methods in the cde) 162 280.43 T +(vSystem object) 344.82 280.43 T +3 10 Q +1.33 (\337ush) 162 135.33 P +0 F +1.33 (: Flush all pending output to the netw) 183.12 135.33 P +1.33 (or) 355.75 135.33 P +1.33 (k f) 364.79 135.33 P +1.33 (or those ser) 376.38 135.33 P +1.33 (vices that perf) 432.13 135.33 P +1.33 (or) 496.74 135.33 P +1.33 (m send) 505.88 135.33 P +(b) 162 123.33 T +(uff) 167.36 123.33 T +(er) 178.18 123.33 T +(ing.) 187.22 123.33 T +3 F +0.58 (poll:) 162 106.33 P +0 F +0.58 ( Flush all pending output, and process all receiv) 180.34 106.33 P +0.58 (ed replies \050including dispatching) 395.97 106.33 P +(callbac) 162 94.33 T +(ks) 192.92 94.33 T +(, if an) 202.77 94.33 T +(y\051. An) 227.08 94.33 T +(y receiv) 253.05 94.33 T +(ed monitor callbac) 287.25 94.33 T +(ks will be deliv) 368.19 94.33 T +(ered as w) 431.84 94.33 T +(ell.) 475.09 94.33 T +162 536.71 540 720 C +162 547.71 540 677 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.63 547.71 542.37 677 R +7 X +0 0 0 1 0 0 0 K +V +166.44 550.57 542.15 669.86 R +0 X +V +0.5 H +2 Z +N +163.01 554 537.3 672.57 R +7 X +V +0 X +N +165.72 557.71 533.58 669.14 R +7 X +V +6 9 Q +0 X +(typedef void \050*cdevCallbackFunction\051\050int status, void* userarg,) 165.72 663.14 T +( cdevRequestObject& reqobj,) 345.72 652.14 T +( cdevData& result\051;) 345.72 641.14 T +(class cdevCallback) 165.72 630.14 T +({) 165.72 619.14 T +(public:) 165.72 608.14 T +(cdevCallback \050cdevCallbackFunction func, void* userarg\051;) 183.72 597.14 T +(cdevCallbackFunction function;) 183.72 586.14 T +(void* userarg;) 183.72 575.14 T +(}) 165.72 564.14 T +162 536.71 540 720 C +0 0 612 792 C +162 81 540 517.71 C +162 344.43 540 438.71 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.52 344.43 542.48 438.71 R +7 X +0 0 0 1 0 0 0 K +V +166.55 347.28 542.27 431.57 R +0 X +V +0.5 H +2 Z +N +163.12 350.71 537.41 434.28 R +7 X +V +0 X +N +165.84 353.71 533.7 430.86 R +7 X +V +6 9 Q +0 X +(// get default system) 165.84 424.86 T +(cdevSystem& sys = cdevSystem::defaultSystem\050\051;) 165.84 413.86 T +(...) 165.84 402.86 T +(mag1.sendNoBlock\050\322on\323,...\051; // async op\050s\051) 165.84 391.86 T +(mag2.sendNoBlock\050\322on\323,...\051; // async op\050s\051) 165.84 380.86 T +(...) 165.84 369.86 T +(sys.pend\050\051; // wait for all I/O to complete) 165.84 358.86 T +162 81 540 517.71 C +0 0 612 792 C +162 81 540 517.71 C +162 166 540 277.43 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.63 166 542.37 277.43 R +7 X +0 0 0 1 0 0 0 K +V +166.44 168.14 542.15 270.28 R +0 X +V +0.5 H +2 Z +N +163.01 171.57 537.3 273 R +7 X +V +0 X +N +165.72 174.57 533.58 269.57 R +7 X +V +6 9 Q +0 X +(class cdevSystem) 165.72 263.57 T +({) 165.72 252.57 T +(public:) 165.72 241.57 T +(int) 183.72 230.57 T +(flush\050\051;) 205.32 230.57 T +(int) 183.72 219.57 T +(poll\050\051;) 205.32 219.57 T +(int) 183.72 208.57 T +(pend\050\051;) 205.32 208.57 T +(}) 165.72 197.57 T +162 81 540 517.71 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "6" 84 +%%Page: "7" 85 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 449.45 739 T +0 10 Q +(7) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +3 F +1.4 (pend) 180 713.33 P +0 F +1.4 (: Flush all pending output, and process all replies f) 202.24 713.33 P +1.4 (or the speci\336ed n) 436.88 713.33 P +1.4 (umber of) 517.14 713.33 P +0.18 (seconds) 180 701.33 P +0.18 (. If the time argument is omitted, w) 217.09 701.33 P +0.18 (ait until all replies ha) 371.05 701.33 P +0.18 (v) 462.16 701.33 P +0.18 (e been receiv) 466.91 701.33 P +0.18 (ed. If a) 527.06 701.33 P +(monitor oper) 180 689.33 T +(ation w) 236.03 689.33 T +(as star) 267.56 689.33 T +(ted, this w) 297.97 689.33 T +(aits f) 342.84 689.33 T +(or the connection \050\336rst callbac) 363.66 689.33 T +(k\051 only) 496.29 689.33 T +(.) 524.74 689.33 T +2 F +(Gr) 72 660.33 T +(oup Object) 83.47 660.33 T +0 F +2.11 (An alter) 180 660.33 P +2.11 (nativ) 216.82 660.33 P +2.11 (e mechanism f) 237.69 660.33 P +2.11 (or w) 306.62 660.33 P +2.11 (aiting f) 327.46 660.33 P +2.11 (or asychronous calls is through the use of) 358.73 660.33 P +0.79 (g) 180 648.33 P +0.79 (roups) 185.46 648.33 P +0.79 (. A g) 210.32 648.33 P +0.79 (roup k) 232.37 648.33 P +0.79 (eeps tr) 260.74 648.33 P +0.79 (ac) 292 648.33 P +0.79 (k off all I/O oper) 302.36 648.33 P +0.79 (ations star) 376 648.33 P +0.79 (ted from the time the g) 423.32 648.33 P +0.79 (roup is) 527.2 648.33 P +0.89 (star) 180 636.33 P +0.89 (ted until the g) 197.07 636.33 P +0.89 (roup is ended. Groups ma) 259.67 636.33 P +0.89 (y be nested or o) 378.53 636.33 P +0.89 (v) 453.64 636.33 P +0.89 (er) 458.39 636.33 P +0.89 (lapped, and suppor) 467.43 636.33 P +0.89 (t) 555.22 636.33 P +(the same \337ush/poll/pend oper) 180 624.33 T +(ations as the system object. F) 311.08 624.33 T +(or e) 443.06 624.33 T +(xample:) 459.99 624.33 T +3 9 Q +(Figure 8: Sample usage of the cde) 180 591 T +(vGroup object) 319.81 591 T +3 10 Q +0.06 (Note: Allo) 180 311.33 P +0.06 (wing nested or o) 223.26 311.33 P +0.06 (v) 296.66 311.33 P +0.06 (er) 301.41 311.33 P +0.06 (lapped g) 310.45 311.33 P +0.06 (roups allo) 348.77 311.33 P +0.06 (ws libr) 392.03 311.33 P +0.06 (ar) 420.32 311.33 P +0.06 (y calls to star) 429.51 311.33 P +0.06 (t or stop g) 488.44 311.33 P +0.06 (roups) 532.99 311.33 P +(without needing to kno) 180 299.33 T +(w if another g) 279.91 299.33 T +(roup is already activ) 339.84 299.33 T +(e) 428.51 299.33 T +(.) 433.92 299.33 T +0 F +1.84 (Groups ma) 180 282.33 P +1.84 (y be oper) 231 282.33 P +1.84 (ated in one of tw) 276.28 282.33 P +1.84 (o modes) 356.93 282.33 P +1.84 (. Immediate mode \050def) 396.98 282.33 P +1.84 (ault\051 causes) 502.25 282.33 P +2.84 (g) 180 270.33 P +2.84 (rouped oper) 185.46 270.33 P +2.84 (ations to be immediately e) 242.12 270.33 P +2.84 (x) 369.32 270.33 P +2.84 (ecuted, and the g) 374.02 270.33 P +2.84 (roup is just used f) 459.7 270.33 P +2.84 (or) 549.11 270.33 P +1.11 (completion synchronization. Def) 180 258.33 P +1.11 (erred mode causes messages to be held bac) 323.64 258.33 P +1.11 (k until) 530.77 258.33 P +0.12 (the g) 180 246.33 P +0.12 (roup is ended and the oper) 202.26 246.33 P +0.12 (ations are \337ushed. After the oper) 322.28 246.33 P +0.12 (ations are complete) 467.87 246.33 P +0.12 (,) 555.22 246.33 P +0.48 (he g) 180 234.33 P +0.48 (roup of oper) 199.84 234.33 P +0.48 (ations ma) 254.63 234.33 P +0.48 (y be \337ushed again \050without re-posting\051, allo) 298.16 234.33 P +0.48 (wing the g) 491.55 234.33 P +0.48 (roup) 537.99 234.33 P +(to function as a list manager/e) 180 222.33 T +(x) 313.1 222.33 T +(ecutor) 317.8 222.33 T +(.) 345.09 222.33 T +2 F +(Request Object) 72 193.33 T +0 F +0.47 (Occasionally) 180 193.33 P +0.47 (, an I/O oper) 235.68 193.33 P +0.47 (ation ma) 292.58 193.33 P +0.47 (y need to be repeated ma) 331.1 193.33 P +0.47 (y times) 447.11 193.33 P +0.47 (. In this case) 479.1 193.33 P +0.47 (, it is) 536.5 193.33 P +0.88 (not ef\336cient to parse the message each time to deter) 180 181.33 P +0.88 (mine which ser) 421.09 181.33 P +0.88 (v) 489.84 181.33 P +0.88 (er to use) 494.59 181.33 P +0.88 (. It is) 535.11 181.33 P +0.06 (possib) 180 169.33 P +0.06 (le to b) 208.7 169.33 P +0.06 (ypass this parsing b) 235.86 169.33 P +0.06 (y creating a request object. The request object is lik) 324.21 169.33 P +0.06 (e) 552.44 169.33 P +-0.03 (the de) 180 157.33 P +-0.03 (vice object, e) 207.47 157.33 P +-0.03 (xcept that the message str) 265.46 157.33 P +-0.03 (ing is speci\336ed at creation time) 382.75 157.33 P +-0.03 (, and the) 519.15 157.33 P +0.98 (request object is theref) 180 145.33 P +0.98 (ore speci\336c to the par) 283.8 145.33 P +0.98 (ticular under) 383.71 145.33 P +0.98 (lying ser) 439.86 145.33 P +0.98 (vice to which that) 478.36 145.33 P +(message m) 180 133.33 T +(ust be directed.) 231.58 133.33 T +1.29 (In the case of EPICS channel access) 180 116.33 P +1.29 (, the request object opens and maintains the) 352.15 116.33 P +1.02 (channel to the EPICS process v) 180 104.33 P +1.02 (ar) 326.02 104.33 P +1.02 (iab) 335.05 104.33 P +1.02 (le) 348.2 104.33 P +1.02 (. The request object is NO) 355.83 104.33 P +1.02 (T the same as an) 476.67 104.33 P +1.34 (EPICS channel, in that the request object binds a de) 180 92.33 P +1.34 (vice and a message) 423.59 92.33 P +1.34 (, and the) 516.39 92.33 P +180 219 558 667 C +180 342 558 588 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.52 342 560.48 588 R +7 X +0 0 0 1 0 0 0 K +V +184.55 345 560.27 580.86 R +0 X +V +0.5 H +2 Z +N +181.12 347.86 555.41 583.57 R +7 X +V +0 X +N +183.84 350.85 551.7 580.14 R +7 X +V +6 9 Q +0 X +(cdevGroup g1, g2;) 183.84 574.14 T +(...) 183.84 563.14 T +(g1.start\050\051;) 183.84 552.14 T +(mag1.sendCallback\050...\051;) 183.84 541.14 T +(mag2.sendCallback\050...\051;) 183.84 530.14 T +(g2.start\050\051;) 183.84 519.14 T +(bpm1.sendNoBlock\050...\051;) 183.84 508.14 T +(bpm2.sendNoBlock\050...\051;) 183.84 497.14 T +(g1.end\050\051;) 183.84 486.14 T +(mag3.sendCallback\050...\051;) 183.84 475.14 T +(bpm3.sendNoBlock\050...\051;) 183.84 464.14 T +(g2.end\050\051;) 183.84 453.14 T +(g1.pend\0504.0\051;) 183.84 442.14 T +(// at this point operations on mag1, mag2, bpm1, & bpm2 are done) 183.84 431.14 T +(// or have timed out \050error handling discussed later\051.) 183.84 420.14 T +(...) 183.84 409.14 T +(// mag3 and bpm3 may not be finished yet, pend on the second) 183.84 398.14 T +(// group to wait for their completion) 183.84 387.14 T +(g2.pend\050\051;) 183.84 376.14 T +180 219 558 667 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "7" 85 +%%Page: "8" 86 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 54 739 T +0 10 Q +(8) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 10 Q +1.04 (message implies a direction. If the message is considered to be of the f) 162 713.33 P +1.04 (or) 489.84 713.33 P +1.04 (m) 498.98 713.33 P +3 F +1.04 (v) 511.14 713.33 P +1.04 (erb) 515.89 713.33 P +0 F +1.04 ( +) 530.34 713.33 P +3 F +-0.16 (attr) 162 701.33 P +-0.16 (ib) 176.6 701.33 P +-0.16 (ute) 184.18 701.33 P +0 F +-0.16 (then the EPICS channel essentially binds de) 200.7 701.33 P +-0.16 (vice and attr) 396.21 701.33 P +-0.16 (ib) 450.52 701.33 P +-0.16 (ute b) 458.1 701.33 P +-0.16 (ut not v) 479.98 701.33 P +-0.16 (erb) 512.21 701.33 P +-0.16 (. In) 526.26 701.33 P +0.04 (some future release of CDEV) 162 689.33 P +0.04 (, a more channel lik) 290.98 689.33 P +0.04 (e object ma) 377.65 689.33 P +0.04 (y be included if there is a) 429.13 689.33 P +0.37 (demand f) 162 677.33 P +0.37 (or it. If tw) 203.76 677.33 P +0.37 (o cde) 245.32 677.33 P +0.37 (vRequestObjects ref) 269.85 677.33 P +0.37 (erence the same EPICS channel, only a) 360.5 677.33 P +(single channel access connection is estab) 162 665.33 T +(lished.) 348 665.33 T +1.56 (The f) 162 648.33 P +1.56 (ollo) 186.05 648.33 P +1.56 (wing code demonstr) 201.46 648.33 P +1.56 (ates sending a set of data v) 293.96 648.33 P +1.56 (alues to a single magnet) 425.37 648.33 P +(using a request object. Note that the send call omits the message argument:) 162 636.33 T +3 9 Q +(Figure 9: Sample usage of the cde) 162 620 T +(vRequestObject object) 301.81 620 T +0 10 Q +0.2 (In most cases) 162 457.05 P +0.2 (, the de) 223.94 457.05 P +0.2 (vice object will create the request object to perf) 257.39 457.05 P +0.2 (or) 466.54 457.05 P +0.2 (m a requested) 475.68 457.05 P +0.59 (I/O oper) 162 445.05 P +0.59 (ation. All 3 f) 198.62 445.05 P +0.59 (or) 252.35 445.05 P +0.59 (ms of send are suppor) 261.49 445.05 P +0.59 (ted b) 363.75 445.05 P +0.59 (y the request object, with a calling) 386.38 445.05 P +-0.25 (syntax identical to the de) 162 433.05 P +-0.25 (vice calls without the message argument. The interf) 270.76 433.05 P +-0.25 (ace to the) 496.58 433.05 P +(request object is giv) 162 421.05 T +(en belo) 250.12 421.05 T +(w:) 282.77 421.05 T +3 9 Q +(Figure 10: Str) 162 387.71 T +(ucture of the cde) 219.16 387.71 T +(vRequestObject object) 285.93 387.71 T +0 10 Q +0.13 (When an asynchronous oper) 162 214.05 P +0.13 (ation completes) 290.12 214.05 P +0.13 (, the rele) 360.12 214.05 P +0.13 (v) 398.99 214.05 P +0.13 (ant request object is passed to) 403.74 214.05 P +1.47 (the user\325) 162 202.05 P +1.47 (s callbac) 201.32 202.05 P +1.47 (k routine) 241.49 202.05 P +1.47 (. This allo) 281.16 202.05 P +1.47 (ws the user to e) 326.74 202.05 P +1.47 (xtr) 402.9 202.05 P +1.47 (act the message str) 413.91 202.05 P +1.47 (ing and) 505.73 202.05 P +(de) 162 190.05 T +(vice name from the request object if necessar) 172.82 190.05 T +(y or desired.) 374.87 190.05 T +2 F +(File Descriptor) 54 161.05 T +(s) 123.87 161.05 T +(and \322select\323) 54 149.05 T +0 F +0.4 (An alter) 162 161.05 P +0.4 (nativ) 197.11 161.05 P +0.4 (e mechanism f) 217.98 161.05 P +0.4 (or dealing with asynchronous oper) 283.49 161.05 P +0.4 (ations is to directly test) 437.26 161.05 P +3.76 (the \336le descr) 162 149.05 P +3.76 (iptors being used. This interf) 226.36 149.05 P +3.76 (ace is currently implemented in the) 366.7 149.05 P +(cde) 162 137.05 T +(vSystem class) 177.82 137.05 T +(. The per) 241.57 137.05 T +(tinent methods ha) 281.99 137.05 T +(v) 361.28 137.05 T +(e the f) 366.03 137.05 T +(ollo) 393.53 137.05 T +(wing f) 408.94 137.05 T +(or) 434.76 137.05 T +(m:) 443.9 137.05 T +162 186.71 540 720 C +162 487.71 540 617 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.72 487.71 542.28 617 R +7 X +0 0 0 1 0 0 0 K +V +166.35 490.57 542.07 609.86 R +0 X +V +0.5 H +2 Z +N +162.92 494.71 537.21 612.57 R +7 X +V +0 X +N +165.64 497.71 533.49 609.14 R +7 X +V +6 9 Q +0 X +(cdevRequestObject& mag1BDL =) 165.64 603.14 T +(cdevRequestObject::attachRef\050\322mag1\323,\323set BDL\323\051;) 183.64 592.14 T +(cdevData mydata;) 165.64 581.14 T +(...) 165.64 570.14 T +(for \050i=0;i<100;i++\051) 165.64 559.14 T +({) 183.64 548.14 T +(mydata = i*10; // 10 amp steps) 183.64 537.14 T +(mag1BDL.send\050mydata,NULL\051; // ignore errors for now) 183.64 526.14 T +(sleep\0501\051;) 183.64 515.14 T +(}) 183.64 504.14 T +162 186.71 540 720 C +0 0 612 792 C +162 186.71 540 720 C +162 244.71 540 384.71 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.63 244.71 542.37 384.71 R +7 X +0 0 0 1 0 0 0 K +V +166.44 247.57 542.15 377.57 R +0 X +V +0.5 H +2 Z +N +163.01 251 537.3 380.29 R +7 X +V +0 X +N +165.72 254 533.58 376.86 R +7 X +V +6 9 Q +0 X +(class cdevRequestObject) 165.72 370.86 T +({) 165.72 359.86 T +(public:) 165.72 348.86 T +(char* message\050\051; // returns the message string) 183.72 337.86 T +(cdevDevice& device\050\051; // returns the device object) 183.72 326.86 T +(int state\050\051; // connected/disconnected/) 183.72 315.86 T +(int access\050\051; // read/write/none) 183.72 304.86 T +(int send\050cdevData& out, cdevData& result\051;) 183.72 293.86 T +(int sendNoBlock\050cdevData& out, cdevData& result\051;) 183.72 282.86 T +(int sendCallback\050cdevData& out, cdevCallback callback\051;) 183.72 271.86 T +(}) 165.72 260.86 T +162 186.71 540 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "8" 86 +%%Page: "9" 87 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 449.45 739 T +0 10 Q +(9) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +3 9 Q +(Figure 11: File descr) 180 714 T +(iptor routines of the cde) 264.66 714 T +(vSystem object) 358.44 714 T +0 10 Q +1.42 (The getFd method will populate a user allocated arr) 180 559.58 P +1.42 (a) 419.16 559.58 P +1.42 (y of integers \050fd\051 with the \336le) 424.42 559.58 P +0.36 (descr) 180 547.58 P +0.36 (iptors currently in use b) 204.6 547.58 P +0.36 (y the cde) 309.19 547.58 P +0.36 (vSystem object. The n) 350.18 547.58 P +0.36 (umber of \336le descr) 450.08 547.58 P +0.36 (iptors) 533.55 547.58 P +0.5 (that w) 180 535.58 P +0.5 (ere allocated b) 207.08 535.58 P +0.5 (y the user is speci\336ed in the n) 273.46 535.58 P +0.5 (umFD v) 408.58 535.58 P +0.5 (ar) 443.82 535.58 P +0.5 (iab) 452.86 535.58 P +0.5 (le) 466 535.58 P +0.5 (. Upon completion,) 473.63 535.58 P +-0.19 (the n) 180 523.58 P +-0.19 (umFD v) 201.95 523.58 P +-0.19 (ar) 236.5 523.58 P +-0.19 (iab) 245.54 523.58 P +-0.19 (le will be set to the n) 258.68 523.58 P +-0.19 (umber of \336le descr) 348.01 523.58 P +-0.19 (iptors actually copied into the) 429.83 523.58 P +0.52 (fd arr) 180 511.58 P +0.52 (a) 203.76 511.58 P +0.52 (y) 209.02 511.58 P +0.52 (. An error is retur) 213.02 511.58 P +0.52 (ned if the b) 290.39 511.58 P +0.52 (uff) 341.25 511.58 P +0.52 (er is not suf\336cient to store the complete set of) 352.07 511.58 P +(\336le descr) 180 499.58 T +(iptors) 220.16 499.58 T +(.) 244.46 499.58 T +0.03 (The addFdChangedCallbac) 180 482.58 P +0.03 (k method allo) 302.11 482.58 P +0.03 (ws the user to specify a function to be called) 361.5 482.58 P +(each time a \336le descr) 180 470.58 T +(iptor is added \050opened=1\051 or closed \050opened=0\051.) 274.63 470.58 T +(The f) 180 453.58 T +(ollo) 202.49 453.58 T +(wing code illustr) 217.9 453.58 T +(ates the usage of the UNIX select call:) 288.93 453.58 T +180 81 558 720 C +180 573.25 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.52 573.25 560.48 711 R +7 X +0 0 0 1 0 0 0 K +V +183.3 584.54 559.02 705.11 R +0 X +V +0.5 H +2 Z +N +181.75 588.29 556.04 707.82 R +7 X +V +0 X +N +183.84 596.53 551.7 703.14 R +7 X +V +6 9 Q +0 X +(typedef void \050*cdevFdChangedCallback\051\050int fd, int opened,) 183.84 697.14 T +( void* userarg\051) 255.84 686.14 T +(class cdevSystem) 183.84 675.14 T +({) 183.84 664.14 T +(public:) 183.84 653.14 T +(...) 201.84 642.14 T +(int getFd\050int fd[], int &numFD\051;) 201.84 631.14 T +(int addFdChangedCallback\050cdevFdChangedCallback cbk, void* arg\051;) 201.84 620.14 T +(}) 183.84 609.14 T +180 81 558 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "9" 87 +%%Page: "10" 88 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Asychronous Operations) 54 739 T +0 10 Q +(10) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +3 F +(Figure 12: Using CDEV \336le descr) 162 714 T +(iptors with the UNIX select function) 296.68 714 T +162 81 540 720 C +162 213.85 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.57 213.85 542.43 711 R +7 X +0 0 0 1 0 0 0 K +V +166.5 216.71 542.22 703.86 R +0 X +V +0.5 H +2 Z +N +163.07 220.14 537.36 706.57 R +7 X +V +0 X +N +165.79 223.14 533.65 703.14 R +7 X +V +6 9 Q +0 X +(int myFD[5];) 165.79 697.14 T +(void mySelectLoop \050 cdevSystem & system \051) 165.79 675.14 T +({) 183.79 664.14 T +(int fd[20];) 183.79 653.14 T +(int numFD = 15, nfds;) 183.79 642.14 T +(fd_set rfds; // Ready file descriptors) 183.79 631.14 T +(fd_set afds; // Active file descriptors) 183.79 620.14 T +(// Copy the file descriptors I am already using to the list) 183.79 598.14 T +(memcpy\050fd, myFD, sizeof\050myFD\051\051;) 183.79 587.14 T +(// Get the file descriptors in use by the cdevSystem object) 183.79 565.14 T +(system.getFd\050&fd[5], numFD\051;) 183.79 554.14 T +(// Add in the 5 previously defined file descriptors) 183.79 532.14 T +(numFD += 5;) 183.79 521.14 T +(// Zero the active file descriptors) 183.79 499.14 T +(FD_ZERO\050&afds\051;) 183.79 488.14 T +(// Setup the active file descriptors) 183.79 466.14 T +(for\050int i=0; i\323 into which the de) 242.31 244.91 T +(vice name will be substituted.) 354.29 244.91 T +-0.15 (Example: Suppose there are a set of magnets f) 180 227.91 P +-0.15 (or which it is possib) 387.51 227.91 P +-0.15 (le to read and wr) 473.4 227.91 P +-0.15 (ite) 547.44 227.91 P +0.46 (bdl \050integ) 180 215.91 P +0.46 (r) 221.49 215.91 P +0.46 (al \336eld\051, and current \050amps\051. That is) 224.72 215.91 P +0.46 (, the messages \322get bdl\323, \322get current\323,) 385.17 215.91 P +0.32 (\322set bdl\323, etc. are v) 180 203.91 P +0.32 (alid. Also) 263.86 203.91 P +0.32 (, each magnet responds to the commands \322on\323 and \322off) 304.36 203.91 P +0.32 (\323.) 551.89 203.91 P +-0.22 (Fur) 180 191.91 P +-0.22 (ther suppose that the beamline position and length of the magnet are a) 195.4 191.91 P +-0.22 (v) 506.09 191.91 P +-0.22 (ailab) 510.84 191.91 P +-0.22 (le in a) 531.76 191.91 P +(static database \050assume read/wr) 180 179.91 T +(ite\051.) 324.65 179.91 T +180 557.57 558 720 C +180 603.57 558 665 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +178.64 603.57 559.36 665 R +7 X +0 0 0 1 0 0 0 K +V +183.43 606.43 559.15 657.86 R +0 X +V +0.5 H +2 Z +N +180 609.86 554.29 660.57 R +7 X +V +0 X +N +182.71 613.57 550.57 657.14 R +7 X +V +6 9 Q +0 X +(service ca) 182.71 651.14 T +({) 200.71 640.14 T +(tags {pv, default}) 200.71 629.14 T +(}) 200.71 618.14 T +180 557.57 558 720 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "15" 93 +%%Page: "16" 94 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Name Resolution) 54 739 T +0 10 Q +(16) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 10 Q +(Here is a complete class de\336nition:) 162 713.33 T +3 9 Q +(Figure 21: Sample inher) 162 680 T +(ited class de\336nition) 260.68 680 T +0 10 Q +0.68 (Note the semicolon at the end of each line of attr) 162 406.33 P +0.68 (ib) 384.02 406.33 P +0.68 (utes or messages \050e) 391.6 406.33 P +0.68 (xcept f) 483.92 406.33 P +0.68 (or the) 513.75 406.33 P +0.36 (last line\051. Note also that the process v) 162 394.33 P +0.36 (ar) 330.99 394.33 P +0.36 (iab) 340.03 394.33 P +0.36 (le name has a place holder into which the) 353.17 394.33 P +0.17 (de) 162 382.33 P +0.17 (vice name will be substituted. More sophisticated name mangling is en) 172.82 382.33 P +0.17 (visaged, b) 486.11 382.33 P +0.17 (ut) 531.66 382.33 P +(not f) 162 370.33 T +(or this release) 181.16 370.33 T +(. Syntax is still open to re) 243.81 370.33 T +(vision.) 354.67 370.33 T +2 F +(Instance De\336nition) 54 341.33 T +0 F +1.8 (Instances of a class are giv) 162 341.33 P +1.8 (en b) 291.39 341.33 P +1.8 (y f) 312.45 341.33 P +1.8 (ollo) 324.52 341.33 P +1.8 (wing the class name with a list of instance) 339.93 341.33 P +4.03 (names) 162 329.33 P +4.03 (. De) 191.86 329.33 P +4.03 (vice names ma) 213.93 329.33 P +4.03 (y be separ) 288.92 329.33 P +4.03 (ated b) 343.56 329.33 P +4.03 (y whitespace char) 375.19 329.33 P +4.03 (acters \050including) 463.17 329.33 P +(ne) 162 317.33 T +(wline\051 or b) 172.92 317.33 T +(y commas) 218.84 317.33 T +(.) 264.25 317.33 T +3 9 Q +(Figure 22: Multiple instances of the magnet class) 162 284 T +0 10 Q +1.2 (Combined with the pre) 162 223.19 P +1.2 (vious de\336nition, the message \322on\323 sent to magnet m2 w) 265.33 223.19 P +1.2 (ould) 521.1 223.19 P +(select the process v) 162 211.19 T +(ar) 250.12 211.19 T +(iab) 259.16 211.19 T +(le \322m2CSR.v) 272.3 211.19 T +(al\323 with \3221\323 as the v) 328.72 211.19 T +(alue to wr) 412.94 211.19 T +(ite) 456.44 211.19 T +(.) 466.85 211.19 T +2 F +(Aliases) 54 182.19 T +0 F +1.39 (Sometimes it is con) 162 182.19 P +1.39 (v) 252.67 182.19 P +1.39 (enient to ref) 257.42 182.19 P +1.39 (er to a de) 312.72 182.19 P +1.39 (vice b) 358.85 182.19 P +1.39 (y more than one name) 386.17 182.19 P +1.39 (. The DDL) 491.64 182.19 P +(syntax suppor) 162 170.19 T +(ts simple aliases) 224.65 170.19 T +(, one per line) 297.85 170.19 T +(.) 355.51 170.19 T +3 9 Q +(Figure 23: Alias de) 162 136.86 T +(vice name) 239.26 136.86 T +162 367 540 720 C +162 437 540 677 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +159.93 437 542.07 677 R +7 X +0 0 0 1 0 0 0 K +V +166.14 439.85 541.86 669.86 R +0 X +V +0.5 H +2 Z +N +162.71 444 537 672.57 R +7 X +V +0 X +N +165.43 447.71 533.29 669.14 R +7 X +V +6 9 Q +0 X +(class stdio) 165.43 663.14 T +({) 183.43 652.14 T +(verbs {get, set, monitorOn, monitorOff}) 183.43 641.14 T +(}) 183.43 630.14 T +(class magnet : stdio) 165.43 608.14 T +({) 183.43 597.14 T +(attributes) 183.43 586.14 T +({) 201.43 575.14 T +(bdl) 201.43 564.14 T +(ca {pv=<>.bdl};) 223.03 564.14 T +(current ca {pv=<>.val};) 201.43 553.14 T +(zpos) 201.43 542.14 T +( os {path=<>/phy/z};) 223.03 542.14 T +(length) 201.43 531.14 T +( os {path=<>/phy/len}) 233.83 531.14 T +(}) 201.43 520.14 T +(messages) 183.43 509.14 T +({) 201.43 498.14 T +(on) 201.43 487.14 T +(ca {pv=<>CSR.val, default=1};) 219.43 487.14 T +(off) 201.43 476.14 T +(ca {pv=<>CSR.val, default=0};) 224.83 476.14 T +(}) 201.43 465.14 T +(}) 183.43 454.14 T +162 367 540 720 C +0 0 612 792 C +162 207.86 540 348 C +162 253.86 540 281 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +160.29 253.86 541.71 281 R +7 X +0 0 0 1 0 0 0 K +V +165.79 256 541.5 273.85 R +0 X +V +0.5 H +2 Z +N +162.36 259.43 536.65 276.57 R +7 X +V +0 X +N +165.07 263.14 532.93 273.14 R +7 X +V +6 9 Q +0 X +(magnet : m1 m2 m3;) 165.07 267.14 T +162 207.86 540 348 C +0 0 612 792 C +162 81 540 188.86 C +162 106.71 540 133.86 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +160.29 106.71 541.71 133.86 R +7 X +0 0 0 1 0 0 0 K +V +165.79 108.86 541.5 126.71 R +0 X +V +0.5 H +2 Z +N +162.36 112.28 536.65 129.43 R +7 X +V +0 X +N +165.07 116 532.93 126 R +7 X +V +6 9 Q +0 X +(alias myname m1) 165.07 120 T +162 81 540 188.86 C +0 0 612 792 C +FMENDPAGE +%%EndPage: "16" 94 +%%Page: "17" 95 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Name Resolution) 478.97 739 T +0 10 Q +(17) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "17" 95 +%%Page: "18" 96 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Channel Access Service) 54 739 T +0 10 Q +(18) 54 56.33 T +0 9 Q +(Document Revision: 1) 451.97 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(6.) 141.32 710.67 T +(Channel Access Ser) 162 710.67 T +(vice) 296.75 710.67 T +0 10 Q +(EPICS / Channel Access v) 162 684.33 T +(ersion 3.12 is recommended.) 280.13 684.33 T +(F) 162 667.33 T +(eatures:) 167.81 667.33 T +(\245) 180 650.33 T +(Suppor) 189 650.33 T +(ts synchronous and asynchronous send\325) 221.64 650.33 T +(s) 399.56 650.33 T +(.) 404.41 650.33 T +(\245) 180 636.33 T +(T) 189 636.33 T +(r) 193.91 636.33 T +(ac) 197.14 636.33 T +(ks \336le descr) 207.5 636.33 T +(iptor registr) 260.44 636.33 T +(ation.) 310.35 636.33 T +(\245) 180 622.33 T +(F) 189 622.33 T +(etches data in nativ) 194.81 622.33 T +(e type \050type con) 280.72 622.33 T +(v) 351.67 622.33 T +(ersion done on client and not ser) 356.42 622.33 T +(v) 501.8 622.33 T +(er\051.) 506.55 622.33 T +(\245) 180 608.33 T +1.96 (Pro) 189 608.33 P +1.96 (vides a def) 204.41 608.33 P +1.96 (ault name ser) 256.38 608.33 P +1.96 (vice so that if a de) 321.18 608.33 P +1.96 (vice is not de\336ned, then an) 411.26 608.33 P +0.13 (EPICS channel access connection is attempted with the record name set equal) 189 596.33 P +(to the de) 189 584.33 T +(vice name) 227.62 584.33 T +(, and the \336eld name set equal to the attr) 273.04 584.33 T +(ib) 449.41 584.33 T +(ute name) 456.99 584.33 T +(.) 498.53 584.33 T +(Restr) 162 567.33 T +(ictions:) 186.04 567.33 T +(\245) 180 550.33 T +2.52 (Only suppor) 189 550.33 P +2.52 (ts set/get/monitorOn/monitorOff v) 245.83 550.33 P +2.52 (erbs and the pv and readonly) 397.89 550.33 P +-0.27 (tags) 189 538.33 P +-0.27 (. Suppor) 207.75 538.33 P +-0.27 (t f) 245.68 538.33 P +-0.27 (or arbitr) 253.44 538.33 P +-0.27 (ar) 287.52 538.33 P +-0.27 (y messages with def) 296.71 538.33 P +-0.27 (ault data will be in the ne) 386.18 538.33 P +-0.27 (xt release) 494.29 538.33 P +-0.27 (.) 537.22 538.33 P +(\245) 180 524.33 T +(Discards all e) 189 524.33 T +(xception callbac) 248.71 524.33 T +(ks from channel access in this v) 319.65 524.33 T +(ersion.) 460.56 524.33 T +(\245) 180 510.33 T +(Channel access secur) 189 510.33 T +(ity is not suppor) 287.52 510.33 T +(ted in this release) 357.95 510.33 T +(.) 436.17 510.33 T +(Compilation options:) 162 493.33 T +(\245) 180 476.33 T +3.21 (_CA_SYNC_CONN = perf) 189 476.33 P +3.21 (or) 311.54 476.33 P +3.21 (m connections synchronously) 320.68 476.33 P +3.21 (, w) 457.27 476.33 P +3.21 (aiting up to 4) 473.11 476.33 P +(seconds) 189 464.33 T +(.) 226.09 464.33 T +(\245) 180 450.33 T +(_CDEV_DEB) 189 450.33 T +(UG = pr) 248.36 450.33 T +(int v) 283.8 450.33 T +(erbose messages) 301.89 450.33 T +(\245) 180 436.33 T +(_EPICS_3_12 = if not de\336ned, use 3.11 calls instead.) 189 436.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "18" 96 +%%Trailer +%%BoundingBox: 0 0 612 792 +%%PageOrder: Ascend +%%Pages: 96 +%%DocumentFonts: Helvetica +%%+ Times-BoldItalic +%%+ Helvetica-Bold +%%+ Helvetica-Oblique +%%+ Courier +%%+ Courier-Oblique +%%+ Courier-Bold +%%EOF diff --git a/doc/ps/cdevReference.ps b/doc/ps/cdevReference.ps new file mode 100755 index 0000000..e4e0da2 --- /dev/null +++ b/doc/ps/cdevReference.ps @@ -0,0 +1,17530 @@ +%!PS-Adobe-3.0 +%%BoundingBox: (atend) +%%Pages: (atend) +%%PageOrder: (atend) +%%DocumentFonts: (atend) +%%Creator: Frame 5.0 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +% +% Frame ps_prolog 5.0, for use with Frame 5.0 products +% This ps_prolog file is Copyright (c) 1986-1995 Frame Technology +% Corporation. All rights reserved. This ps_prolog file may be +% freely copied and distributed in conjunction with documents created +% using FrameMaker, FrameMaker/SGML and FrameViewer as long as this +% copyright notice is preserved. +% +% FrameMaker users specify the proper paper size for each print job in the +% "Print" dialog's "Printer Paper Size" "Width" and "Height~ fields. If the +% printer that the PS file is sent to does not support the requested paper +% size, or if there is no paper tray of the proper size currently installed, +% then the job will not be printed. The following flag, if set to true, will +% cause the job to print on the default paper in such cases. +/FMAllowPaperSizeMismatch false def +% +% Frame products normally print colors as their true color on a color printer +% or as shades of gray, based on luminance, on a black-and white printer. The +% following flag, if set to true, forces all non-white colors to print as pure +% black. This has no effect on bitmap images. +/FMPrintAllColorsAsBlack false def +% +% Frame products can either set their own line screens or use a printer's +% default settings. Three flags below control this separately for no +% separations, spot separations and process separations. If a flag +% is true, then the default printer settings will not be changed. If it is +% false, Frame products will use their own settings from a table based on +% the printer's resolution. +/FMUseDefaultNoSeparationScreen true def +/FMUseDefaultSpotSeparationScreen true def +/FMUseDefaultProcessSeparationScreen false def +% +% For any given PostScript printer resolution, Frame products have two sets of +% screen angles and frequencies for printing process separations, which are +% recomended by Adobe. The following variable chooses the higher frequencies +% when set to true or the lower frequencies when set to false. This is only +% effective if the appropriate FMUseDefault...SeparationScreen flag is false. +/FMUseHighFrequencyScreens true def +% +% The following is a set of predefined optimal frequencies and angles for various +% common dpi settings. This is taken from "Advances in Color Separation Using +% PostScript Software Technology," from Adobe Systems (3/13/89 P.N. LPS 0043) +% and corrolated with information which is in various PPD (4.0) files. +% +% The "dpiranges" figure is the minimum dots per inch device resolution which +% can support this setting. The "low" and "high" values are controlled by the +% setting of the FMUseHighFrequencyScreens flag above. The "TDot" flags control +% the use of the "Yellow Triple Dot" feature whereby the frequency id divided by +% three, but the dot function is "trippled" giving a block of 3x3 dots per cell. +% +% PatFreq is a compromise pattern frequency for ps Level 2 printers which is close +% to the ideal WYSIWYG pattern frequency of 9 repetitions/inch but does not beat +% (too badly) against the screen frequencies of any separations for that DPI. +/dpiranges [ 2540 2400 1693 1270 1200 635 600 0 ] def +/CMLowFreqs [ 100.402 94.8683 89.2289 100.402 94.8683 66.9349 63.2456 47.4342 ] def +/YLowFreqs [ 95.25 90.0 84.65 95.25 90.0 70.5556 66.6667 50.0 ] def +/KLowFreqs [ 89.8026 84.8528 79.8088 89.8026 84.8528 74.8355 70.7107 53.033 ] def +/CLowAngles [ 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 ] def +/MLowAngles [ 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 ] def +/YLowTDot [ true true false true true false false false ] def +/CMHighFreqs [ 133.87 126.491 133.843 108.503 102.523 100.402 94.8683 63.2456 ] def +/YHighFreqs [ 127.0 120.0 126.975 115.455 109.091 95.25 90.0 60.0 ] def +/KHighFreqs [ 119.737 113.137 119.713 128.289 121.218 89.8026 84.8528 63.6395 ] def +/CHighAngles [ 71.5651 71.5651 71.5651 70.0169 70.0169 71.5651 71.5651 71.5651 ] def +/MHighAngles [ 18.4349 18.4349 18.4349 19.9831 19.9831 18.4349 18.4349 18.4349 ] def +/YHighTDot [ false false true false false true true false ] def +/PatFreq [ 10.5833 10.0 9.4055 10.5833 10.0 10.5833 10.0 9.375 ] def +% +% PostScript Level 2 printers contain an "Accurate Screens" feature which can +% improve process separation rendering at the expense of compute time. This +% flag is ignored by PostScript Level 1 printers. +/FMUseAcccurateScreens true def +% +% The following PostScript procedure defines the spot function that Frame +% products will use for process separations. You may un-comment-out one of +% the alternative functions below, or use your own. +% +% Dot function +/FMSpotFunction {abs exch abs 2 copy add 1 gt + {1 sub dup mul exch 1 sub dup mul add 1 sub } + {dup mul exch dup mul add 1 exch sub }ifelse } def +% +% Line function +% /FMSpotFunction { pop } def +% +% Elipse function +% /FMSpotFunction { dup 5 mul 8 div mul exch dup mul exch add +% sqrt 1 exch sub } def +% +% +/FMversion (5.0) def +/fMLevel1 /languagelevel where {pop languagelevel} {1} ifelse 2 lt def +/FMPColor + fMLevel1 { + false + /colorimage where {pop pop true} if + } { + true + } ifelse +def +/FrameDict 400 dict def +systemdict /errordict known not {/errordict 10 dict def + errordict /rangecheck {stop} put} if +% The readline in PS 23.0 doesn't recognize cr's as nl's on AppleTalk +FrameDict /tmprangecheck errordict /rangecheck get put +errordict /rangecheck {FrameDict /bug true put} put +FrameDict /bug false put +mark +% Some PS machines read past the CR, so keep the following 3 lines together! +currentfile 5 string readline +00 +0000000000 +cleartomark +errordict /rangecheck FrameDict /tmprangecheck get put +FrameDict /bug get { + /readline { + /gstring exch def + /gfile exch def + /gindex 0 def + { + gfile read pop + dup 10 eq {exit} if + dup 13 eq {exit} if + gstring exch gindex exch put + /gindex gindex 1 add def + } loop + pop + gstring 0 gindex getinterval true + } bind def + } if +/FMshowpage /showpage load def +/FMquit /quit load def +/FMFAILURE { + dup = flush + FMshowpage + /Helvetica findfont 12 scalefont setfont + 72 200 moveto show + 72 220 moveto show + FMshowpage + FMquit + } def +/FMVERSION { + FMversion ne { + (Frame product version does not match ps_prolog! Check installation;) + (also check ~/fminit and ./fminit for old versions) FMFAILURE + } if + } def +/FMBADEPSF { + (Adobe's PostScript Language Reference Manual, 2nd Edition, section H.2.4) + (says your EPS file is not valid, as it calls X ) + dup dup (X) search pop exch pop exch pop length + 5 -1 roll + putinterval + FMFAILURE + } def +/fmConcatProcs + { + /proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def + newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx +}def +FrameDict begin [ + /ALDsave + /FMdicttop + /FMoptop + /FMpointsize + /FMsaveobject + /b + /bitmapsave + /blut + /bpside + /bs + /bstring + /bwidth + /c + /cf + /cs + /cynu + /depth + /edown + /fh + /fillvals + /fw + /fx + /fy + /g + /gfile + /gindex + /grnt + /gryt + /gstring + /height + /hh + /i + /im + /indx + /is + /k + /kk + /landscape + /lb + /len + /llx + /lly + /m + /magu + /manualfeed + /n + /offbits + /onbits + /organgle + /orgbangle + /orgbfreq + /orgbproc + /orgbxfer + /orgfreq + /orggangle + /orggfreq + /orggproc + /orggxfer + /orgmatrix + /orgproc + /orgrangle + /orgrfreq + /orgrproc + /orgrxfer + /orgxfer + /pagesave + /paperheight + /papersizedict + /paperwidth + /pos + /pwid + /r + /rad + /redt + /sl + /str + /tran + /u + /urx + /ury + /val + /width + /width + /ws + /ww + /x + /x1 + /x2 + /xindex + /xpoint + /xscale + /xx + /y + /y1 + /y2 + /yelu + /yindex + /ypoint + /yscale + /yy +] { 0 def } forall +/FmBD {bind def} bind def +systemdict /pdfmark known { + /fMAcrobat true def + + /FmPD /pdfmark load def + + + /FmPT /show load def + + + currentdistillerparams /CoreDistVersion get 2000 ge { + + + /FmPD2 /pdfmark load def + + + + + + /FmPA { mark exch /Dest exch 5 3 roll + /View [ /XYZ null 6 -2 roll FmDC exch pop null] /DEST FmPD + }FmBD + } { + + /FmPD2 /cleartomark load def + /FmPA {pop pop pop}FmBD + } ifelse +} { + + /fMAcrobat false def + /FmPD /cleartomark load def + /FmPD2 /cleartomark load def + /FmPT /pop load def + /FmPA {pop pop pop}FmBD +} ifelse +/FmDC { + transform fMDefaultMatrix itransform cvi exch cvi exch +}FmBD +/FmBx { + dup 3 index lt {3 1 roll exch} if + 1 index 4 index lt {4 -1 roll 3 1 roll exch 4 1 roll} if +}FmBD +/FMnone 0 def +/FMcyan 1 def +/FMmagenta 2 def +/FMyellow 3 def +/FMblack 4 def +/FMcustom 5 def +/fMNegative false def +/FrameSepIs FMnone def +/FrameSepBlack 0 def +/FrameSepYellow 0 def +/FrameSepMagenta 0 def +/FrameSepCyan 0 def +/FrameSepRed 1 def +/FrameSepGreen 1 def +/FrameSepBlue 1 def +/FrameCurGray 1 def +/FrameCurPat null def +/FrameCurColors [ 0 0 0 1 0 0 0 ] def +/FrameColorEpsilon .001 def +/eqepsilon { + sub dup 0 lt {neg} if + FrameColorEpsilon le +} bind def +/FrameCmpColorsCMYK { + 2 copy 0 get exch 0 get eqepsilon { + 2 copy 1 get exch 1 get eqepsilon { + 2 copy 2 get exch 2 get eqepsilon { + 3 get exch 3 get eqepsilon + } {pop pop false} ifelse + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/FrameCmpColorsRGB { + 2 copy 4 get exch 0 get eqepsilon { + 2 copy 5 get exch 1 get eqepsilon { + 6 get exch 2 get eqepsilon + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/RGBtoCMYK { + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 3 copy + 2 copy + le { pop } { exch pop } ifelse + 2 copy + le { pop } { exch pop } ifelse + dup dup dup + 6 1 roll + 4 1 roll + 7 1 roll + sub + 6 1 roll + sub + 5 1 roll + sub + 4 1 roll +} bind def +/CMYKtoRGB { + dup dup 4 -1 roll add + 5 1 roll 3 -1 roll add + 4 1 roll add + 1 exch sub dup 0 lt {pop 0} if 3 1 roll + 1 exch sub dup 0 lt {pop 0} if exch + 1 exch sub dup 0 lt {pop 0} if exch +} bind def +/FrameSepInit { + 1.0 RealSetgray +} bind def +/FrameSetSepColor { + /FrameSepBlue exch def + /FrameSepGreen exch def + /FrameSepRed exch def + /FrameSepBlack exch def + /FrameSepYellow exch def + /FrameSepMagenta exch def + /FrameSepCyan exch def + /FrameSepIs FMcustom def + setCurrentScreen +} bind def +/FrameSetCyan { + /FrameSepBlue 1.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 1.0 def + /FrameSepIs FMcyan def + setCurrentScreen +} bind def + +/FrameSetMagenta { + /FrameSepBlue 1.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 1.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMmagenta def + setCurrentScreen +} bind def + +/FrameSetYellow { + /FrameSepBlue 0.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 1.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMyellow def + setCurrentScreen +} bind def + +/FrameSetBlack { + /FrameSepBlue 0.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 1.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMblack def + setCurrentScreen +} bind def + +/FrameNoSep { + /FrameSepIs FMnone def + setCurrentScreen +} bind def +/FrameSetSepColors { + FrameDict begin + [ exch 1 add 1 roll ] + /FrameSepColors + exch def end + } bind def +/FrameColorInSepListCMYK { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsCMYK + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/FrameColorInSepListRGB { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsRGB + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/RealSetgray /setgray load def +/RealSetrgbcolor /setrgbcolor load def +/RealSethsbcolor /sethsbcolor load def +end +/setgray { + FrameDict begin + FrameSepIs FMnone eq + { RealSetgray } + { + FrameSepIs FMblack eq + { RealSetgray } + { FrameSepIs FMcustom eq + FrameSepRed 0 eq and + FrameSepGreen 0 eq and + FrameSepBlue 0 eq and { + RealSetgray + } { + 1 RealSetgray pop + } ifelse + } ifelse + } ifelse + end +} bind def +/setrgbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetrgbcolor } + { + 3 copy [ 4 1 roll ] + FrameColorInSepListRGB + { + FrameSepBlue eq exch + FrameSepGreen eq and exch + FrameSepRed eq and + { 0 } { 1 } ifelse + } + { + FMPColor { + RealSetrgbcolor + currentcmykcolor + } { + RGBtoCMYK + } ifelse + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end +} bind def +/sethsbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSethsbcolor } + { + RealSethsbcolor + currentrgbcolor + setrgbcolor + } + ifelse + end +} bind def +FrameDict begin +/setcmykcolor where { + pop /RealSetcmykcolor /setcmykcolor load def +} { + /RealSetcmykcolor { + 4 1 roll + 3 { 3 index add 0 max 1 min 1 exch sub 3 1 roll} repeat + RealSetrgbcolor pop + } bind def +} ifelse +userdict /setcmykcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetcmykcolor } + { + 4 copy [ 5 1 roll ] + FrameColorInSepListCMYK + { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + { 0 } { 1 } ifelse + } + { + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end + } bind put +fMLevel1 { + + + + /patScreenDict 7 dict dup begin + <0f1e3c78f0e1c387> [ 45 { pop } {exch pop} .5 2 sqrt] FmBD + <0f87c3e1f0783c1e> [ 135 { pop } {exch pop} .5 2 sqrt] FmBD + [ 0 { pop } dup .5 2 ] FmBD + [ 90 { pop } dup .5 2 ] FmBD + <8142241818244281> [ 45 { 2 copy lt {exch} if pop} dup .75 2 sqrt] FmBD + <03060c183060c081> [ 45 { pop } {exch pop} .875 2 sqrt] FmBD + <8040201008040201> [ 135 { pop } {exch pop} .875 2 sqrt] FmBD + end def +} { + + /patProcDict 5 dict dup begin + <0f1e3c78f0e1c387> { 3 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <0f87c3e1f0783c1e> { 3 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + <8142241818244281> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -1 -1 moveto 9 9 lineto stroke } bind def + <03060c183060c081> { 1 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <8040201008040201> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + end def + /patDict 15 dict dup begin + /PatternType 1 def + /PaintType 2 def + /TilingType 3 def + /BBox [ 0 0 8 8 ] def + /XStep 8 def + /YStep 8 def + /PaintProc { + begin + patProcDict bstring known { + patProcDict bstring get exec + } { + 8 8 true [1 0 0 -1 0 8] bstring imagemask + } ifelse + end + } bind def + end def +} ifelse +/combineColor { + FrameSepIs FMnone eq + { + graymode fMLevel1 or not { + + [/Pattern [/DeviceCMYK]] setcolorspace + FrameCurColors 0 4 getinterval aload pop FrameCurPat setcolor + } { + FrameCurColors 3 get 1.0 ge { + FrameCurGray RealSetgray + } { + fMAcrobat not FMPColor graymode and and { + 0 1 3 { + FrameCurColors exch get + 1 FrameCurGray sub mul + } for + RealSetcmykcolor + } { + 4 1 6 { + FrameCurColors exch get + graymode { + 1 exch sub 1 FrameCurGray sub mul 1 exch sub + } { + 1.0 lt {FrameCurGray} {1} ifelse + } ifelse + } for + RealSetrgbcolor + } ifelse + } ifelse + } ifelse + } { + FrameCurColors 0 4 getinterval aload + FrameColorInSepListCMYK { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + FrameSepIs FMcustom eq and + { FrameCurGray } { 1 } ifelse + } { + FrameSepIs FMblack eq + {FrameCurGray 1.0 exch sub mul 1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop FrameCurGray 1.0 exch sub mul 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + graymode fMLevel1 or not { + + [/Pattern [/DeviceGray]] setcolorspace + FrameCurPat setcolor + } { + graymode not fMLevel1 and { + + dup 1 lt {pop FrameCurGray} if + } if + RealSetgray + } ifelse + } ifelse +} bind def +/savematrix { + orgmatrix currentmatrix pop + } bind def +/restorematrix { + orgmatrix setmatrix + } bind def +/fMDefaultMatrix matrix defaultmatrix def +/fMatrix2 matrix def +/dpi 72 0 fMDefaultMatrix dtransform + dup mul exch dup mul add sqrt def + +/freq dpi dup 72 div round dup 0 eq {pop 1} if 8 mul div def +/sangle 1 0 fMDefaultMatrix dtransform exch atan def + sangle fMatrix2 rotate + fMDefaultMatrix fMatrix2 concatmatrix + dup 0 get /sflipx exch def + 3 get /sflipy exch def +/screenIndex { + 0 1 dpiranges length 1 sub { dup dpiranges exch get 1 sub dpi le {exit} {pop} ifelse } for +} bind def +/getCyanScreen { + FMUseHighFrequencyScreens { CHighAngles CMHighFreqs} {CLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getMagentaScreen { + FMUseHighFrequencyScreens { MHighAngles CMHighFreqs } {MLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getYellowScreen { + FMUseHighFrequencyScreens { YHighTDot YHighFreqs} { YLowTDot YLowFreqs } ifelse + screenIndex dup 3 1 roll get 3 1 roll get { 3 div + {2 { 1 add 2 div 3 mul dup floor sub 2 mul 1 sub exch} repeat + FMSpotFunction } } {/FMSpotFunction load } ifelse + 0.0 exch +} bind def +/getBlackScreen { + FMUseHighFrequencyScreens { KHighFreqs } { KLowFreqs } ifelse + screenIndex get 45.0 /FMSpotFunction load +} bind def +/getSpotScreen { + getBlackScreen +} bind def +/getCompositeScreen { + getBlackScreen +} bind def +/FMSetScreen + fMLevel1 { /setscreen load + }{ { + 8 dict begin + /HalftoneType 1 def + /SpotFunction exch def + /Angle exch def + /Frequency exch def + /AccurateScreens FMUseAcccurateScreens def + currentdict end sethalftone + } bind } ifelse +def +/setDefaultScreen { + FMPColor { + orgrxfer cvx orggxfer cvx orgbxfer cvx orgxfer cvx setcolortransfer + } + { + orgxfer cvx settransfer + } ifelse + orgfreq organgle orgproc cvx setscreen +} bind def +/setCurrentScreen { + FrameSepIs FMnone eq { + FMUseDefaultNoSeparationScreen { + setDefaultScreen + } { + getCompositeScreen FMSetScreen + } ifelse + } { + FrameSepIs FMcustom eq { + FMUseDefaultSpotSeparationScreen { + setDefaultScreen + } { + getSpotScreen FMSetScreen + } ifelse + } { + FMUseDefaultProcessSeparationScreen { + setDefaultScreen + } { + FrameSepIs FMcyan eq { + getCyanScreen FMSetScreen + } { + FrameSepIs FMmagenta eq { + getMagentaScreen FMSetScreen + } { + FrameSepIs FMyellow eq { + getYellowScreen FMSetScreen + } { + getBlackScreen FMSetScreen + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse +} bind def +end + +/FMDOCUMENT { + array /FMfonts exch def + /#copies exch def + FrameDict begin + 0 ne /manualfeed exch def + /paperheight exch def + /paperwidth exch def + 0 ne /fMNegative exch def + 0 ne /edown exch def + /yscale exch def + /xscale exch def + fMLevel1 { + manualfeed {setmanualfeed} if + /FMdicttop countdictstack 1 add def + /FMoptop count def + setpapername + manualfeed {true} {papersize} ifelse + {manualpapersize} {false} ifelse + {desperatepapersize} {false} ifelse + {papersizefailure} if + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + } + {2 dict + dup /PageSize [paperwidth paperheight] put + manualfeed {dup /ManualFeed manualfeed put} if + {setpagedevice} stopped {papersizefailure} if + } + ifelse + + FMPColor { + currentcolorscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + cvlit /orgbproc exch def + /orgbangle exch def + /orgbfreq exch def + cvlit /orggproc exch def + /orggangle exch def + /orggfreq exch def + cvlit /orgrproc exch def + /orgrangle exch def + /orgrfreq exch def + currentcolortransfer + fMNegative { + 1 1 4 { + pop { 1 exch sub } fmConcatProcs 4 1 roll + } for + 4 copy + setcolortransfer + } if + cvlit /orgxfer exch def + cvlit /orgbxfer exch def + cvlit /orggxfer exch def + cvlit /orgrxfer exch def + } { + currentscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + + currenttransfer + fMNegative { + { 1 exch sub } fmConcatProcs + dup settransfer + } if + cvlit /orgxfer exch def + } ifelse + end +} def +/FMBEGINPAGE { + FrameDict begin + /pagesave save def + 3.86 setmiterlimit + /landscape exch 0 ne def + landscape { + 90 rotate 0 exch dup /pwid exch def neg translate pop + }{ + pop /pwid exch def + } ifelse + edown { [-1 0 0 1 pwid 0] concat } if + 0 0 moveto paperwidth 0 lineto paperwidth paperheight lineto + 0 paperheight lineto 0 0 lineto 1 setgray fill + xscale yscale scale + /orgmatrix matrix def + gsave +} def +/FMENDPAGE { + grestore + pagesave restore + end + showpage + } def +/FMFONTDEFINE { + FrameDict begin + findfont + ReEncode + 1 index exch + definefont + FMfonts 3 1 roll + put + end + } def +/FMFILLS { + FrameDict begin dup + array /fillvals exch def + dict /patCache exch def + end + } def +/FMFILL { + FrameDict begin + fillvals 3 1 roll put + end + } def +/FMNORMALIZEGRAPHICS { + newpath + 1 setlinewidth + 0 setlinecap + 0 0 0 sethsbcolor + 0 setgray + } bind def +/FMBEGINEPSF { + end + /FMEPSF save def + /showpage {} def +% See Adobe's "PostScript Language Reference Manual, 2nd Edition", page 714. +% "...the following operators MUST NOT be used in an EPS file:" (emphasis ours) + /banddevice {(banddevice) FMBADEPSF} def + /clear {(clear) FMBADEPSF} def + /cleardictstack {(cleardictstack) FMBADEPSF} def + /copypage {(copypage) FMBADEPSF} def + /erasepage {(erasepage) FMBADEPSF} def + /exitserver {(exitserver) FMBADEPSF} def + /framedevice {(framedevice) FMBADEPSF} def + /grestoreall {(grestoreall) FMBADEPSF} def + /initclip {(initclip) FMBADEPSF} def + /initgraphics {(initgraphics) FMBADEPSF} def + /quit {(quit) FMBADEPSF} def + /renderbands {(renderbands) FMBADEPSF} def + /setglobal {(setglobal) FMBADEPSF} def + /setpagedevice {(setpagedevice) FMBADEPSF} def + /setshared {(setshared) FMBADEPSF} def + /startjob {(startjob) FMBADEPSF} def + /lettertray {(lettertray) FMBADEPSF} def + /letter {(letter) FMBADEPSF} def + /lettersmall {(lettersmall) FMBADEPSF} def + /11x17tray {(11x17tray) FMBADEPSF} def + /11x17 {(11x17) FMBADEPSF} def + /ledgertray {(ledgertray) FMBADEPSF} def + /ledger {(ledger) FMBADEPSF} def + /legaltray {(legaltray) FMBADEPSF} def + /legal {(legal) FMBADEPSF} def + /statementtray {(statementtray) FMBADEPSF} def + /statement {(statement) FMBADEPSF} def + /executivetray {(executivetray) FMBADEPSF} def + /executive {(executive) FMBADEPSF} def + /a3tray {(a3tray) FMBADEPSF} def + /a3 {(a3) FMBADEPSF} def + /a4tray {(a4tray) FMBADEPSF} def + /a4 {(a4) FMBADEPSF} def + /a4small {(a4small) FMBADEPSF} def + /b4tray {(b4tray) FMBADEPSF} def + /b4 {(b4) FMBADEPSF} def + /b5tray {(b5tray) FMBADEPSF} def + /b5 {(b5) FMBADEPSF} def + FMNORMALIZEGRAPHICS + [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall + fx fw 2 div add fy fh 2 div add translate + rotate + fw 2 div neg fh 2 div neg translate + fw urx llx sub div fh ury lly sub div scale + llx neg lly neg translate + /FMdicttop countdictstack 1 add def + /FMoptop count def + } bind def +/FMENDEPSF { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMEPSF restore + FrameDict begin + } bind def +FrameDict begin +/setmanualfeed { +%%BeginFeature *ManualFeed True + statusdict /manualfeed true put +%%EndFeature + } bind def +/max {2 copy lt {exch} if pop} bind def +/min {2 copy gt {exch} if pop} bind def +/inch {72 mul} def +/pagedimen { + paperheight sub abs 16 lt exch + paperwidth sub abs 16 lt and + {/papername exch def} {pop} ifelse + } bind def +/setpapername { + /papersizedict 14 dict def + papersizedict begin + /papername /unknown def + /Letter 8.5 inch 11.0 inch pagedimen + /LetterSmall 7.68 inch 10.16 inch pagedimen + /Tabloid 11.0 inch 17.0 inch pagedimen + /Ledger 17.0 inch 11.0 inch pagedimen + /Legal 8.5 inch 14.0 inch pagedimen + /Statement 5.5 inch 8.5 inch pagedimen + /Executive 7.5 inch 10.0 inch pagedimen + /A3 11.69 inch 16.5 inch pagedimen + /A4 8.26 inch 11.69 inch pagedimen + /A4Small 7.47 inch 10.85 inch pagedimen + /B4 10.125 inch 14.33 inch pagedimen + /B5 7.16 inch 10.125 inch pagedimen + end + } bind def +/papersize { + papersizedict begin + /Letter {lettertray letter} def + /LetterSmall {lettertray lettersmall} def + /Tabloid {11x17tray 11x17} def + /Ledger {ledgertray ledger} def + /Legal {legaltray legal} def + /Statement {statementtray statement} def + /Executive {executivetray executive} def + /A3 {a3tray a3} def + /A4 {a4tray a4} def + /A4Small {a4tray a4small} def + /B4 {b4tray b4} def + /B5 {b5tray b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + statusdict begin stopped end + } bind def +/manualpapersize { + papersizedict begin + /Letter {letter} def + /LetterSmall {lettersmall} def + /Tabloid {11x17} def + /Ledger {ledger} def + /Legal {legal} def + /Statement {statement} def + /Executive {executive} def + /A3 {a3} def + /A4 {a4} def + /A4Small {a4small} def + /B4 {b4} def + /B5 {b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + stopped + } bind def +/desperatepapersize { + statusdict /setpageparams known + { + paperwidth paperheight 0 1 + statusdict begin + {setpageparams} stopped + end + } {true} ifelse + } bind def +/papersizefailure { + FMAllowPaperSizeMismatch not + { +(The requested paper size is not available in any currently-installed tray) +(Edit the PS file to "FMAllowPaperSizeMismatch true" to use default tray) + FMFAILURE } if + } def +/DiacriticEncoding [ +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl +/numbersign /dollar /percent /ampersand /quotesingle /parenleft +/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K +/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash +/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h +/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar +/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute +/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis +/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis +/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve +/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex +/udieresis /dagger /.notdef /cent /sterling /section /bullet +/paragraph /germandbls /registered /copyright /trademark /acute +/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef +/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown +/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef +/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde +/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright +/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis +/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl +/periodcentered /quotesinglbase /quotedblbase /perthousand +/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute +/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve +/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron +/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +] def +/ReEncode { + dup + length + dict begin + { + 1 index /FID ne + {def} + {pop pop} ifelse + } forall + 0 eq {/Encoding DiacriticEncoding def} if + currentdict + end + } bind def +FMPColor + + { + /BEGINBITMAPCOLOR { + BITMAPCOLOR} def + /BEGINBITMAPCOLORc { + BITMAPCOLORc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUECOLOR } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUECOLORc } def + /BEGINBITMAPCMYK { + BITMAPCMYK } def + /BEGINBITMAPCMYKc { + BITMAPCMYKc } def + } + + { + /BEGINBITMAPCOLOR { + BITMAPGRAY} def + /BEGINBITMAPCOLORc { + BITMAPGRAYc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUEGRAY } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUEGRAYc } def + /BEGINBITMAPCMYK { + BITMAPCMYKGRAY } def + /BEGINBITMAPCMYKc { + BITMAPCMYKGRAYc } def + } +ifelse +/K { + FMPrintAllColorsAsBlack { + dup 1 eq 2 index 1 eq and 3 index 1 eq and not + {7 {pop} repeat 0 0 0 1 0 0 0} if + } if + FrameCurColors astore + pop combineColor +} bind def +/graymode true def +fMLevel1 { + /fmGetFlip { + fMatrix2 exch get mul 0 lt { -1 } { 1 } ifelse + } FmBD +} if +/setPatternMode { + fMLevel1 { + 2 index patScreenDict exch known { + pop pop + patScreenDict exch get aload pop + freq + mul + 5 2 roll + fMatrix2 currentmatrix 1 get 0 ne { + 3 -1 roll 90 add 3 1 roll + sflipx 1 fmGetFlip sflipy 2 fmGetFlip neg mul + } { + sflipx 0 fmGetFlip sflipy 3 fmGetFlip mul + } ifelse + 0 lt {exch pop} {pop} ifelse + fMNegative { + {neg} fmConcatProcs + } if + bind + + + + systemdict /setscreen get exec + /FrameCurGray exch def + } { + /bwidth exch def + /bpside exch def + /bstring exch def + /onbits 0 def /offbits 0 def + freq sangle landscape {90 add} if + {/ypoint exch def + /xpoint exch def + /xindex xpoint 1 add 2 div bpside mul cvi def + /yindex ypoint 1 add 2 div bpside mul cvi def + bstring yindex bwidth mul xindex 8 idiv add get + 1 7 xindex 8 mod sub bitshift and 0 ne fMNegative {not} if + {/onbits onbits 1 add def 1} + {/offbits offbits 1 add def 0} + ifelse + } + setscreen + offbits offbits onbits add div fMNegative {1.0 exch sub} if + /FrameCurGray exch def + } ifelse + } { + pop pop + dup patCache exch known { + patCache exch get + } { + dup + patDict /bstring 3 -1 roll put + patDict + 9 PatFreq screenIndex get div dup matrix scale + makepattern + dup + patCache 4 -1 roll 3 -1 roll put + } ifelse + /FrameCurGray 0 def + /FrameCurPat exch def + } ifelse + /graymode false def + combineColor +} bind def +/setGrayScaleMode { + graymode not { + /graymode true def + fMLevel1 { + setCurrentScreen + } if + } if + /FrameCurGray exch def + combineColor +} bind def +/normalize { + transform round exch round exch itransform + } bind def +/dnormalize { + dtransform round exch round exch idtransform + } bind def +/lnormalize { + 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop + } bind def +/H { + lnormalize setlinewidth + } bind def +/Z { + setlinecap + } bind def + +/PFill { + graymode fMLevel1 or not { + gsave 1 setgray eofill grestore + } if +} bind def +/PStroke { + graymode fMLevel1 or not { + gsave 1 setgray stroke grestore + } if + stroke +} bind def +/X { + fillvals exch get + dup type /stringtype eq + {8 1 setPatternMode} + {setGrayScaleMode} + ifelse + } bind def +/V { + PFill gsave eofill grestore + } bind def +/Vclip { + clip + } bind def +/Vstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/N { + PStroke + } bind def +/Nclip { + strokepath clip newpath + } bind def +/Nstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/M {newpath moveto} bind def +/E {lineto} bind def +/D {curveto} bind def +/O {closepath} bind def +/L { + /n exch def + newpath + normalize + moveto + 2 1 n {pop normalize lineto} for + } bind def +/Y { + L + closepath + } bind def +/R { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + x1 y1 + x2 y1 + x2 y2 + x1 y2 + 4 Y + } bind def +/rarc + {rad + arcto + } bind def +/RR { + /rad exch def + normalize + /y2 exch def + /x2 exch def + normalize + /y1 exch def + /x1 exch def + mark + newpath + { + x1 y1 rad add moveto + x1 y2 x2 y2 rarc + x2 y2 x2 y1 rarc + x2 y1 x1 y1 rarc + x1 y1 x1 y2 rarc + closepath + } stopped {x1 y1 x2 y2 R} if + cleartomark + } bind def +/RRR { + /rad exch def + normalize /y4 exch def /x4 exch def + normalize /y3 exch def /x3 exch def + normalize /y2 exch def /x2 exch def + normalize /y1 exch def /x1 exch def + newpath + normalize moveto + mark + { + x2 y2 x3 y3 rarc + x3 y3 x4 y4 rarc + x4 y4 x1 y1 rarc + x1 y1 x2 y2 rarc + closepath + } stopped + {x1 y1 x2 y2 x3 y3 x4 y4 newpath moveto lineto lineto lineto closepath} if + cleartomark + } bind def +/C { + grestore + gsave + R + clip + setCurrentScreen +} bind def +/CP { + grestore + gsave + Y + clip + setCurrentScreen +} bind def +/F { + FMfonts exch get + FMpointsize scalefont + setfont + } bind def +/Q { + /FMpointsize exch def + F + } bind def +/T { + moveto show + } bind def +/RF { + rotate + 0 ne {-1 1 scale} if + } bind def +/TF { + gsave + moveto + RF + show + grestore + } bind def +/P { + moveto + 0 32 3 2 roll widthshow + } bind def +/PF { + gsave + moveto + RF + 0 32 3 2 roll widthshow + grestore + } bind def +/S { + moveto + 0 exch ashow + } bind def +/SF { + gsave + moveto + RF + 0 exch ashow + grestore + } bind def +/B { + moveto + 0 32 4 2 roll 0 exch awidthshow + } bind def +/BF { + gsave + moveto + RF + 0 32 4 2 roll 0 exch awidthshow + grestore + } bind def +/G { + gsave + newpath + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill fill + grestore + } bind def +/Gstrk { + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/Gclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GG { + gsave + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill + fill + grestore + } bind def +/GGclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GGstrk { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/A { + gsave + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/Aclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/Astrk { + Gstrk +} bind def +/AA { + gsave + savematrix + newpath + + 3 index 2 div add exch 4 index 2 div sub exch + + normalize 3 index 2 div sub exch 4 index 2 div add exch + translate + rotate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/AAclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/AAstrk { + GGstrk +} bind def +/BEGINPRINTCODE { + /FMdicttop countdictstack 1 add def + /FMoptop count 7 sub def + /FMsaveobject save def + userdict begin + /showpage {} def + FMNORMALIZEGRAPHICS + 3 index neg 3 index neg translate + } bind def +/ENDPRINTCODE { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMsaveobject restore + } bind def +/gn { + 0 + { 46 mul + cf read pop + 32 sub + dup 46 lt {exit} if + 46 sub add + } loop + add + } bind def +/cfs { + /str sl string def + 0 1 sl 1 sub {str exch val put} for + str def + } bind def +/ic [ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 + {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx} + {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx} + {19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} + {13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh} + {4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh} + {13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl} + {7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl} + {0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl} + {10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl} + ] def +/ms { + /sl exch def + /val 255 def + /ws cfs + /im cfs + /val 0 def + /bs cfs + /cs cfs + } bind def +400 ms +/ip { + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip { + + + bis ris copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + ris gis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + gis bis copy pop + dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip4 { + + + kis cis copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + cis mis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + mis yis copy pop + dup dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + yis kis copy pop + 3 mul is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/wh { + /len exch def + /pos exch def + ws 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/bl { + /len exch def + /pos exch def + bs 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/s1 1 string def +/fl { + /len exch def + /pos exch def + /val cf s1 readhexstring pop 0 get def + pos 1 pos len add 1 sub {im exch val put} for + pos len + } bind def +/hx { + 3 copy getinterval + cf exch readhexstring pop pop + } bind def +/wbytes { + dup dup + 8 gt { pop 8 idiv mul } + { 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse } ifelse + } bind def +/BEGINBITMAPBWc { + 1 {} COMMONBITMAPc + } bind def +/BEGINBITMAPGRAYc { + 8 {} COMMONBITMAPc + } bind def +/BEGINBITMAP2BITc { + 2 {} COMMONBITMAPc + } bind def +/COMMONBITMAPc { + + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + cvtProc + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} image + bitmapsave restore + grestore + } bind def +/BEGINBITMAPBW { + 1 {} COMMONBITMAP + } bind def +/BEGINBITMAPGRAY { + 8 {} COMMONBITMAP + } bind def +/BEGINBITMAP2BIT { + 2 {} COMMONBITMAP + } bind def +/COMMONBITMAP { + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + cvtProc + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} image + bitmapsave restore + grestore + } bind def +/ngrayt 256 array def +/nredt 256 array def +/nbluet 256 array def +/ngreent 256 array def +fMLevel1 { +/colorsetup { + currentcolortransfer + /gryt exch def + /blut exch def + /grnt exch def + /redt exch def + 0 1 255 { + /indx exch def + /cynu 1 red indx get 255 div sub def + /magu 1 green indx get 255 div sub def + /yelu 1 blue indx get 255 div sub def + /kk cynu magu min yelu min def + /u kk currentundercolorremoval exec def +% /u 0 def + nredt indx 1 0 cynu u sub max sub redt exec put + ngreent indx 1 0 magu u sub max sub grnt exec put + nbluet indx 1 0 yelu u sub max sub blut exec put + ngrayt indx 1 kk currentblackgeneration exec sub gryt exec put + } for + {255 mul cvi nredt exch get} + {255 mul cvi ngreent exch get} + {255 mul cvi nbluet exch get} + {255 mul cvi ngrayt exch get} + setcolortransfer + {pop 0} setundercolorremoval + {} setblackgeneration + } bind def +} +{ +/colorSetup2 { + [ /Indexed /DeviceRGB 255 + {dup red exch get 255 div + exch dup green exch get 255 div + exch blue exch get 255 div} + ] setcolorspace +} bind def +} ifelse +/fakecolorsetup { + /tran 256 string def + 0 1 255 {/indx exch def + tran indx + red indx get 77 mul + green indx get 151 mul + blue indx get 28 mul + add add 256 idiv put} for + currenttransfer + {255 mul cvi tran exch get 255.0 div} + exch fmConcatProcs settransfer +} bind def +/BITMAPCOLOR { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + fMLevel1 { + colorsetup + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} {is} {is} true 3 colorimage + } { + colorSetup2 + /is width depth wbytes string def + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {cf is readhexstring pop} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPCOLORc { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + fMLevel1 { + colorsetup + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} {is} {is} true 3 colorimage + } { + colorSetup2 + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {ip} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLORc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris} {gis} {bis} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYKc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip4 pop cis} {mis} {yis} {kis} true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLOR { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf gis readhexstring pop } + { cf bis readhexstring pop } + true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYK { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /mis width string def + /yis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf mis readhexstring pop } + { cf yis readhexstring pop } + { cf kis readhexstring pop } + true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUEGRAYc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris gis bis width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAYc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop cis mis yis kis width cgray} image + bitmapsave restore + grestore + } bind def +/cgray { + /ww exch def + /k exch def + /y exch def + /m exch def + /c exch def + 0 1 ww 1 sub { /i exch def c i get m i get y i get k i get CMYKtoRGB + .144 mul 3 1 roll .587 mul 3 1 roll .299 mul add add + c i 3 -1 roll floor cvi put } for + c + } bind def +/gray { + /ww exch def + /b exch def + /g exch def + /r exch def + 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul + b i get .114 mul add add r i 3 -1 roll floor cvi put } for + r + } bind def +/BITMAPTRUEGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf gis readhexstring pop + cf bis readhexstring pop width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /yis width string def + /mis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf mis readhexstring pop + cf yis readhexstring pop + cf kis readhexstring pop width cgray} image + bitmapsave restore + grestore + } bind def +/BITMAPGRAY { + 8 {fakecolorsetup} COMMONBITMAP + } bind def +/BITMAPGRAYc { + 8 {fakecolorsetup} COMMONBITMAPc + } bind def +/ENDBITMAP { + } bind def +end + /ALDmatrix matrix def ALDmatrix currentmatrix pop +/StartALD { + /ALDsave save def + savematrix + ALDmatrix setmatrix + } bind def +/InALD { + restorematrix + } bind def +/DoneALD { + ALDsave restore + } bind def +/I { setdash } bind def +/J { [] 0 setdash } bind def +%%EndProlog +%%BeginSetup +(5.0) FMVERSION +1 1 0 0 612 792 0 1 14 FMDOCUMENT +0 0 /Helvetica FMFONTDEFINE +1 0 /Times-BoldItalic FMFONTDEFINE +2 0 /Helvetica-Bold FMFONTDEFINE +3 0 /Helvetica-Oblique FMFONTDEFINE +4 0 /Courier-Bold FMFONTDEFINE +5 0 /Helvetica-BoldOblique FMFONTDEFINE +6 0 /Courier-BoldOblique FMFONTDEFINE +7 0 /Courier-Oblique FMFONTDEFINE +8 0 /Courier FMFONTDEFINE +32 FMFILLS +0 0 FMFILL +1 0.1 FMFILL +2 0.3 FMFILL +3 0.5 FMFILL +4 0.7 FMFILL +5 0.9 FMFILL +6 0.97 FMFILL +7 1 FMFILL +8 <0f1e3c78f0e1c387> FMFILL +9 <0f87c3e1f0783c1e> FMFILL +10 FMFILL +11 FMFILL +12 <8142241818244281> FMFILL +13 <03060c183060c081> FMFILL +14 <8040201008040201> FMFILL +16 1 FMFILL +17 0.9 FMFILL +18 0.7 FMFILL +19 0.5 FMFILL +20 0.3 FMFILL +21 0.1 FMFILL +22 0.03 FMFILL +23 0 FMFILL +24 FMFILL +25 FMFILL +26 <3333333333333333> FMFILL +27 <0000ffff0000ffff> FMFILL +28 <7ebddbe7e7dbbd7e> FMFILL +29 FMFILL +30 <7fbfdfeff7fbfdfe> FMFILL +%%EndSetup +%%Page: "i" 1 +%%BeginPaperSize: Letter +%%EndPaperSize +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(i) 555.78 57 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 720 558 720 2 L +0.5 H +2 Z +N +72 72 558 72 2 L +N +72 504 558 504 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 32 Q +(CDEV Ref) 180 662.67 T +(erence Guide) 321.02 662.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 12 Q +(Chip W) 180 624 T +(atson, Jie Chen, Danjin W) 218.86 624 T +(u, W) 357.22 624 T +(alt Ak) 381.41 624 T +(ers) 411.18 624 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 180 596 T +(ersion 1.5 - December 9, 1996) 187.04 596 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(TJNAF - Thomas Jeff) 180 568 T +(erson National Acceler) 293.66 568 T +(ator F) 414.25 568 T +(acility) 445 568 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "i" 1 +%%Page: "ii" 2 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(ii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(TRADEMARKS:) 54 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(UNIX is a registered tr) 180 569.33 T +(ademar) 278.26 569.33 T +(k of A) 312.31 569.33 T +(T&T in the USA and other countr) 336.68 569.33 T +(ies) 481.9 569.33 T +(.) 494.53 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(VxW) 180 545.33 T +(or) 200.81 545.33 T +(ks is a register tr) 209.85 545.33 T +(ademar) 283.1 545.33 T +(k of Wind Riv) 317.15 545.33 T +(er Systems) 375.8 545.33 T +(.) 425.66 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The X Windo) 180 521.33 T +(w System is a tr) 237.65 521.33 T +(ademar) 308.12 521.33 T +(k of Massachusetts Institute of T) 342.17 521.33 T +(echnology) 484.37 521.33 T +(.) 528.95 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(OSF/Motif and Motif are tr) 180 497.33 T +(ademar) 294.94 497.33 T +(ks of Open Softw) 328.99 497.33 T +(are F) 404.99 497.33 T +(oundation, Inc.) 428.03 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ultr) 180 473.33 T +(ix and DEC are registered tr) 195.7 473.33 T +(ademar) 319.53 473.33 T +(ks of Digital Equipment Cor) 353.58 473.33 T +(por) 475.03 473.33 T +(ation.) 489.38 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(HPUX is a registered tr) 180 449.33 T +(ademar) 282.15 449.33 T +(k of He) 316.2 449.33 T +(wlett P) 347.68 449.33 T +(ac) 377.29 449.33 T +(kard.) 387.65 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(SURA/CEB) 54 344.33 T +(AF:) 105.92 344.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.44 (The Southeaster) 180 344.33 P +4.44 (n Univ) 258.62 344.33 P +4.44 (ersities Research Association \050SURA\051 oper) 291.15 344.33 P +4.44 (ates the) 499.98 344.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.01 (Contin) 180 332.33 P +2.01 (uous Electron Beam Acceler) 208.8 332.33 P +2.01 (ator F) 340.89 332.33 P +2.01 (acility \050CEBAF\051 f) 368.52 332.33 P +2.01 (or the United States) 445.59 332.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Depar) 180 320.33 T +(tment of Energy under contr) 207.63 320.33 T +(act DE-A) 331.48 320.33 T +(C05-84ER40150.) 371.19 320.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DISCLAIMER:) 54 218.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.49 (This repor) 180 218.33 P +0.49 (t w) 225.9 218.33 P +0.49 (as prepared as an account of w) 239.02 218.33 P +0.49 (or) 381.4 218.33 P +0.49 (k sponsored b) 390.44 218.33 P +0.49 (y the United States) 454.03 218.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.18 (go) 180 206.33 P +2.18 (v) 190.97 206.33 P +2.18 (er) 195.72 206.33 P +2.18 (nment. Neither the United States nor the United States Depar) 204.86 206.33 P +2.18 (tment of) 501.68 206.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.04 (Energy) 180 194.33 P +1.04 (, nor an) 210.68 194.33 P +1.04 (y of their emplo) 246.52 194.33 P +1.04 (y) 317.69 194.33 P +1.04 (ees) 322.49 194.33 P +1.04 (, mak) 338.46 194.33 P +1.04 (es an) 363.75 194.33 P +1.04 (y w) 389.1 194.33 P +1.04 (arr) 404.99 194.33 P +1.04 (anty) 417.11 194.33 P +1.04 (, e) 435.01 194.33 P +1.04 (xpress or implied, or) 446.86 194.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.83 (assumes an) 180 182.33 P +1.83 (y legal liability or responsibility f) 235.59 182.33 P +1.83 (or the accur) 383.89 182.33 P +1.83 (acy) 440.24 182.33 P +1.83 (, completeness) 454.8 182.33 P +1.83 (, or) 523.72 182.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.68 (usefulness of an) 180 170.33 P +3.68 (y inf) 260.02 170.33 P +3.68 (or) 281.74 170.33 P +3.68 (mation, appar) 290.88 170.33 P +3.68 (atus) 355.59 170.33 P +3.68 (, product or process disclosed, or) 374.34 170.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.46 (represents that its use w) 180 158.33 P +2.46 (ould not infr) 298.11 158.33 P +2.46 (inge pr) 355.42 158.33 P +2.46 (iv) 388.59 158.33 P +2.46 (ately o) 395.56 158.33 P +2.46 (wned r) 427.33 158.33 P +2.46 (ights) 459.95 158.33 P +2.46 (. Ref) 480.92 158.33 P +2.46 (erence) 509.43 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.6 (herein to an) 180 146.33 P +1.6 (y speci\336c commercial product, process) 235.85 146.33 P +1.6 (, or ser) 413.79 146.33 P +1.6 (vice b) 448.4 146.33 P +1.6 (y tr) 475.92 146.33 P +1.6 (ade name) 491.3 146.33 P +1.6 (,) 537.22 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (mar) 180 134.33 P +2.12 (k, man) 197.37 134.33 P +2.12 (uf) 229.4 134.33 P +2.12 (acturer) 237.44 134.33 P +2.12 (, or otherwise) 268.06 134.33 P +2.12 (, does not necessar) 332.17 134.33 P +2.12 (ily constitute or imply its) 425.94 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (endorsement, recommendation, or f) 180 122.33 P +1.08 (a) 341.33 122.33 P +1.08 (v) 346.69 122.33 P +1.08 (or) 351.44 122.33 P +1.08 (ing b) 360.48 122.33 P +1.08 (y the United States go) 383.03 122.33 P +1.08 (v) 485.57 122.33 P +1.08 (er) 490.32 122.33 P +1.08 (nment or) 499.46 122.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (an) 180 110.33 P +0.83 (y agency thereof) 190.97 110.33 P +0.83 (. The vie) 266.26 110.33 P +0.83 (w and opinions of the authors e) 309.67 110.33 P +0.83 (xpressed herein do) 453.3 110.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.94 (not necessar) 180 98.33 P +1.94 (ily state or re\337ect those of the United States go) 239.34 98.33 P +1.94 (v) 464.01 98.33 P +1.94 (er) 468.76 98.33 P +1.94 (nment or an) 477.9 98.33 P +1.94 (y) 535 98.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(agency thereof) 180 86.33 T +(.) 245.85 86.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DOCUMENT D) 54 668.33 T +(A) 121.37 668.33 T +(TE:) 127.69 668.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(T) 180 668.33 T +(ab) 184.91 668.33 T +(le of contents gener) 195.83 668.33 T +(ated: December 9, 1996 11:45 am) 283.56 668.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "ii" 2 +%%Page: "iii" 3 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iii) 551.34 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(T) 180 710.67 T +(ab) 187.43 710.67 T +(le of Contents) 203.63 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 198 684.33 T +(vCallbac) 233.83 684.33 T +(k Class) 271.97 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 305.8 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 672.33 T +(er) 210.73 672.33 T +(vie) 219.92 672.33 T +(w of the cde) 232.5 672.33 T +(vCallbac) 286.12 672.33 T +(k Class) 324.26 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 358.62 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 198.2 660.33 T +(lic Methods of the cde) 215.79 660.33 T +(vCallbac) 312.76 660.33 T +(k Class) 350.9 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 386.42 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 216 648.33 T +(vCallbac) 231.82 648.33 T +(k) 269.96 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(callbac) 216 636.33 T +(kFunction) 246.92 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(user) 216 624.33 T +(arg) 235.35 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(oper) 216 612.33 T +(ator ==) 235.91 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(oper) 216 600.33 T +(ator !=) 235.91 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 266.88 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 180 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 198 588.33 T +(vCollection Class) 233.83 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 311.36 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 576.33 T +(er) 210.73 576.33 T +(vie) 219.92 576.33 T +(w of the cde) 232.5 576.33 T +(vCollection Class) 286.12 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 364.18 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 198.2 564.33 T +(lic Methods of the cde) 215.79 564.33 T +(vCollection Class) 312.76 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 391.98 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 216 552.33 T +(vCollection) 231.82 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(~cde) 216 540.33 T +(vCollection) 237.66 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 289.12 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getRequestObject) 216 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 297.46 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachRef/attachPtr) 216 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 303.02 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(detach) 216 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(className) 216 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 266.88 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(add) 216 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 233.52 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(add) 216 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 233.52 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(add) 216 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 233.52 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(add) 216 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 233.52 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(addRege) 216 432.33 T +(xp) 256.28 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 266.88 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(remo) 216 420.33 T +(v) 238.63 420.33 T +(e) 243.38 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(remo) 216 408.33 T +(v) 238.63 408.33 T +(e) 243.38 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(remo) 216 396.33 T +(v) 238.63 396.33 T +(e) 243.38 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(remo) 216 384.33 T +(v) 238.63 384.33 T +(e) 243.38 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(remo) 216 372.33 T +(v) 238.63 372.33 T +(eRege) 243.38 372.33 T +(xp) 272.54 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 180 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 198 360.33 T +(vCollectionRequest Class) 233.83 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 350.28 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 348.33 T +(er) 210.73 348.33 T +(vie) 219.92 348.33 T +(w of the cde) 232.5 348.33 T +(vCollection Request Class) 286.12 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . .) 403.1 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 198.2 336.33 T +(lic Methods of the cde) 215.79 336.33 T +(vCollection Request Class) 312.76 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . .) 430.9 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(constr) 216 324.33 T +(uctor) 243.38 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 266.88 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(destr) 216 312.33 T +(uctor) 238.38 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachPtr) 216 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(className) 216 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 266.88 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(resultCodeT) 216 276.33 T +(ag) 269.26 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 180 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 198 264.33 T +(vData Class) 233.83 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 289.12 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 252.33 T +(er) 210.73 252.33 T +(vie) 219.92 252.33 T +(w of the cde) 232.5 252.33 T +(vData Class) 286.12 252.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 341.94 252.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 252.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 198.2 240.33 T +(lic Methods of the cde) 215.79 240.33 T +(vData Class) 312.76 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 366.96 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(tagC2I) 216 228.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 228.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 228.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(tagI2C) 216 216.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 216.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 216.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(inser) 216 204.33 T +(tT) 238.07 204.33 T +(ag) 245.76 204.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 204.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 204.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(addT) 216 192.33 T +(agCallbac) 237.59 192.33 T +(k) 281.85 192.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 289.12 192.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 192.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(delT) 216 180.33 T +(agCallbac) 234.25 180.33 T +(k) 278.51 180.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 180.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 180.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(readT) 216 168.33 T +(agT) 240.92 168.33 T +(ab) 256.95 168.33 T +(le) 267.87 168.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 168.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 168.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Oper) 216 156.33 T +(ator =) 238.13 156.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 156.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 156.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Cast oper) 216 144.33 T +(ators) 259.25 144.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 144.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 546.88 144.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Oper) 216 132.33 T +(ator ==) 238.13 132.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 132.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 546.88 132.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Oper) 216 120.33 T +(ator !=) 238.13 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 266.88 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 546.88 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(asciiDump) 216 108.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 108.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 546.88 108.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(xdrSiz) 216 96.33 T +(e) 243.63 96.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 96.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 546.88 96.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(xdrExpor) 216 84.33 T +(t) 256.41 84.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 84.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 546.88 84.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iii" 3 +%%Page: "iv" 4 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iv) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(xdrExpor) 198 713.33 T +(t) 238.41 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 528.88 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(xdrImpor) 198 701.33 T +(t) 237.85 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 528.88 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(remo) 198 689.33 T +(v) 220.63 689.33 T +(e) 225.38 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 233.52 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 528.88 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(changeT) 198 677.33 T +(ag) 235.71 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 528.88 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getT) 198 665.33 T +(ype) 216.81 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 233.52 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 528.88 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getDim) 198 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 230.74 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 528.88 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getElems) 198 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 528.88 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getBounds) 198 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 528.88 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setBounds) 198 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 528.88 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(inser) 198 605.33 T +(t \050scalar\051) 220.07 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15) 528.88 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(inser) 198 593.33 T +(t \050arr) 220.07 593.33 T +(a) 241.08 593.33 T +(y\051) 246.34 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 255.76 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15) 528.88 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(inser) 198 581.33 T +(t \050char) 220.07 581.33 T +(acter str) 248.31 581.33 T +(ing\051) 284.58 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 303.02 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15) 528.88 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(get) 198 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 214.06 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 528.88 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(get \050char) 198 557.33 T +(acter str) 237.36 557.33 T +(ing\051) 273.63 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 528.88 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\336nd) 198 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 216.84 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 528.88 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 162 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 180 533.33 T +(vDe) 215.83 533.33 T +(vice Class) 233.31 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 528.88 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180.2 521.33 T +(er) 192.73 521.33 T +(vie) 201.92 521.33 T +(w of the cde) 214.5 521.33 T +(vDe) 268.12 521.33 T +(vice Class) 285.6 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 333.6 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 528.88 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 180.2 509.33 T +(lic Methods of the cde) 197.79 509.33 T +(vDe) 294.76 509.33 T +(vice Class) 312.24 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 358.62 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 528.88 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachRef) 198 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 528.88 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachPtr) 198 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 528.88 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(detach) 198 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 230.74 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 528.88 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(detach) 198 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 230.74 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 528.88 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getRequestObject) 198 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 528.88 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(name) 198 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 225.18 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 528.88 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(system) 198 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 230.74 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 528.88 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setConte) 198 413.33 T +(xt) 237.72 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 528.88 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getConte) 198 401.33 T +(xt) 238.28 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 528.88 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setPr) 198 389.33 T +(iv) 221.49 389.33 T +(ate) 228.46 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 528.88 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getPr) 198 377.33 T +(iv) 222.05 377.33 T +(ate) 229.02 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(19) 528.88 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(send) 198 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 222.4 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(19) 528.88 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendNoBloc) 198 353.33 T +(k) 251.71 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(19) 528.88 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendCallbac) 198 341.33 T +(k) 252.82 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(20) 528.88 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 162 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 180 329.33 T +(vError Class) 215.83 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180.2 317.33 T +(er) 192.73 317.33 T +(vie) 201.92 317.33 T +(w of the cde) 214.5 317.33 T +(vError Class) 268.12 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 325.26 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 180.2 305.33 T +(lic Methods of the cde) 197.79 305.33 T +(vError Class) 294.76 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 350.28 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(autoErrorOn) 198 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 255.76 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(autoErrorOff) 198 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 255.76 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(repor) 198 269.33 T +(tError) 221.74 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 200.16 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setErrorHandler) 198 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(22) 528.88 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setThreshold) 198 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(22) 528.88 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 162 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 180 221.33 T +(vGroup Class) 215.83 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(23) 528.88 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180.2 209.33 T +(er) 192.73 209.33 T +(vie) 201.92 209.33 T +(w of the cde) 214.5 209.33 T +(vGroup Class) 268.12 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 330.82 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(23) 528.88 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 180.2 197.33 T +(lic Methods of the cde) 197.79 197.33 T +(vGroup Class) 294.76 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 355.84 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(23) 528.88 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 198 185.33 T +(vGroup) 213.82 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(23) 528.88 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(star) 198 173.33 T +(t) 215.07 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 219.62 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(23) 528.88 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(end) 198 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 216.84 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(24) 528.88 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\337ush) 198 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 219.62 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(24) 528.88 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(poll) 198 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 214.06 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(24) 528.88 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pend) 198 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 222.4 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(24) 528.88 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pend) 198 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 222.4 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(24) 528.88 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(allFinished) 198 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(25) 528.88 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(status) 198 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 225.18 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(25) 528.88 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iv" 4 +%%Page: "v" 5 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(v) 553 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(e) 216 713.33 T +(x) 221.26 713.33 T +(ecDef) 225.96 713.33 T +(erred) 251.78 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(25) 546.88 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(e) 216 701.33 T +(x) 221.26 701.33 T +(ecImmediate) 225.96 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(25) 546.88 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(e) 216 689.33 T +(x) 221.26 689.33 T +(ecutionMode) 225.96 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(25) 546.88 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(readyT) 216 677.33 T +(oEx) 245.92 677.33 T +(ec) 262.85 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(25) 546.88 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8.) 180 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 198 665.33 T +(vIOConte) 233.83 665.33 T +(xt Class) 275.77 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 311.36 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(26) 546.88 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 653.33 T +(er) 210.73 653.33 T +(vie) 219.92 653.33 T +(w of the cde) 232.5 653.33 T +(vIOConte) 286.12 653.33 T +(xt Class) 328.06 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 364.18 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(26) 546.88 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 198.2 641.33 T +(lic Methods of the cde) 215.79 641.33 T +(vIOConte) 312.76 641.33 T +(xt Class) 354.7 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . .) 391.98 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(26) 546.88 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getConte) 216 629.33 T +(xt) 256.28 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(26) 546.88 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setConte) 216 617.33 T +(xt) 255.72 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(26) 546.88 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getPr) 216 605.33 T +(iv) 240.05 605.33 T +(ate) 247.02 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(26) 546.88 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setPr) 216 593.33 T +(iv) 239.49 593.33 T +(ate) 246.46 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(26) 546.88 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9.) 180 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 198 581.33 T +(vRequestObject Class) 233.83 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 333.6 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(27) 546.88 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 569.33 T +(er) 210.73 569.33 T +(vie) 219.92 569.33 T +(w of the cde) 232.5 569.33 T +(vRequestObject Class) 286.12 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 386.42 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(27) 546.88 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 198.2 557.33 T +(lic Methods of the cde) 215.79 557.33 T +(vRequestObject Class) 312.76 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . .) 414.22 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(27) 546.88 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachRef) 216 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(27) 546.88 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachRef) 216 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 546.88 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachPtr) 216 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 546.88 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachPtr) 216 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 546.88 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(detach) 216 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 546.88 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(detach) 216 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 546.88 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(message) 216 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 546.88 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(de) 216 461.33 T +(vice) 226.82 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 546.88 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(system) 216 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 546.88 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ser) 216 437.33 T +(vice) 230.19 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 546.88 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getState) 216 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 255.76 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 546.88 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getAccess) 216 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(29) 546.88 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setConte) 216 401.33 T +(xt) 255.72 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(29) 546.88 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getConte) 216 389.33 T +(xt) 256.28 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(29) 546.88 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getPr) 216 377.33 T +(iv) 240.05 377.33 T +(ate) 247.02 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(29) 546.88 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setPr) 216 365.33 T +(iv) 239.49 365.33 T +(ate) 246.46 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(29) 546.88 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(send) 216 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(29) 546.88 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendNoBloc) 216 341.33 T +(k) 269.71 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(30) 546.88 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendCallbac) 216 329.33 T +(k) 270.82 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(30) 546.88 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10.) 180 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 198 317.33 T +(vSelector Class) 233.83 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 305.8 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(31) 546.88 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 305.33 T +(er) 210.73 305.33 T +(vie) 219.92 305.33 T +(w of the cde) 232.5 305.33 T +(vSelector Class) 286.12 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 355.84 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(31) 546.88 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 198.2 293.33 T +(lic Methods of the cde) 215.79 293.33 T +(vSelector Class) 312.76 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 383.64 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(31) 546.88 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(inser) 216 281.33 T +(tEv) 238.07 281.33 T +(ent) 252.27 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 266.88 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(31) 546.88 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(remo) 216 269.33 T +(v) 238.63 269.33 T +(eEv) 243.38 269.33 T +(ent) 260.36 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(31) 546.88 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(purge) 216 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(31) 546.88 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(wr) 216 245.33 T +(itefd) 226.7 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(31) 546.88 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(readfd) 216 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(31) 546.88 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11.) 180 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 198 221.33 T +(vSer) 233.83 221.33 T +(vice Class) 254.69 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 303.02 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 546.88 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 209.33 T +(er) 210.73 209.33 T +(vie) 219.92 209.33 T +(w of the cde) 232.5 209.33 T +(vSer) 286.12 209.33 T +(vice Class) 306.98 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 353.06 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 546.88 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 198.2 197.33 T +(lic Methods of the cde) 215.79 197.33 T +(vSer) 312.76 197.33 T +(vice Class) 333.62 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 380.86 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 546.88 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\337ush) 216 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 546.88 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(poll) 216 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 233.52 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 546.88 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pend) 216 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 546.88 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pend) 216 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(33) 546.88 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getRequestObject) 216 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 297.46 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(33) 546.88 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getNameSer) 216 125.33 T +(v) 272.43 125.33 T +(er) 277.18 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 286.34 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(33) 546.88 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getCollectionRequest) 216 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 311.36 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(33) 546.88 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getFd) 216 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(33) 546.88 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(registerFd) 216 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(33) 546.88 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "v" 5 +%%Page: "vi" 6 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(vi) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(autoErrorOn) 198 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 255.76 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(34) 528.88 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(autoErrorOff) 198 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 255.76 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(34) 528.88 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(repor) 198 689.33 T +(tError) 221.74 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(34) 528.88 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setErrorHandler) 198 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(34) 528.88 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setThreshold) 198 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(35) 528.88 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(name) 198 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 225.18 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(35) 528.88 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12.) 162 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 180 641.33 T +(vSync Class) 215.83 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(36) 528.88 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180.2 629.33 T +(er) 192.73 629.33 T +(vie) 201.92 629.33 T +(w of the cde) 214.5 629.33 T +(vSync Class) 268.12 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 325.26 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(36) 528.88 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 180.2 617.33 T +(lic Methods of the cde) 197.79 617.33 T +(vSync Class) 294.76 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 350.28 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(36) 528.88 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\337ush) 198 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 219.62 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(36) 528.88 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(poll) 198 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 214.06 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(36) 528.88 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pend) 198 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 222.4 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(36) 528.88 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pend) 198 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 222.4 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(36) 528.88 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13.) 162 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 180 557.33 T +(vSystemBase Class) 215.83 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 305.8 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(37) 528.88 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180.2 545.33 T +(er) 192.73 545.33 T +(vie) 201.92 545.33 T +(w of the cde) 214.5 545.33 T +(vSystemBase Class) 268.12 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 358.62 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(37) 528.88 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 180.2 533.33 T +(lic Methods of the cde) 197.79 533.33 T +(vSystemBase Class) 294.76 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . .) 386.42 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(37) 528.88 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getRequestObject) 198 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(37) 528.88 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14.) 162 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 180 509.33 T +(vSystem Class) 215.83 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(38) 528.88 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180.2 497.33 T +(er) 192.73 497.33 T +(vie) 201.92 497.33 T +(w of the cde) 214.5 497.33 T +(vSystem Class) 268.12 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 336.38 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(38) 528.88 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 180.2 485.33 T +(lic Methods of the cde) 197.79 485.33 T +(vSystem Class) 294.76 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 361.4 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(38) 528.88 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachRef) 198 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(38) 528.88 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachPtr) 198 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(39) 528.88 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(def) 198 449.33 T +(aultSystem) 211.6 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(39) 528.88 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getDe) 198 437.33 T +(vice) 224.38 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(39) 528.88 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getRequestObject) 198 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(39) 528.88 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(name) 198 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 225.18 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(39) 528.88 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pre\336x) 198 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 225.18 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(39) 528.88 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pre\336x) 198 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 225.18 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(39) 528.88 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\337ush) 198 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 219.62 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(39) 528.88 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(poll) 198 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 214.06 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(40) 528.88 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pend) 198 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 222.4 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(40) 528.88 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pend) 198 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 222.4 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(40) 528.88 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getFd) 198 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 225.18 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(40) 528.88 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(addFdChangedCallbac) 198 317.33 T +(k) 300.07 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 305.8 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(40) 528.88 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(autoErrorOn) 198 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 255.76 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(40) 528.88 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(autoErrorOff) 198 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 255.76 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(41) 528.88 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(repor) 198 281.33 T +(tError) 221.74 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(41) 528.88 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setErrorHandler) 198 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(41) 528.88 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setThreshold) 198 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(41) 528.88 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15.) 162 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 180 245.33 T +(vT) 215.83 245.33 T +(r) 225.74 245.33 T +(anObj Class) 228.97 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(42) 528.88 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180.2 233.33 T +(er) 192.73 233.33 T +(vie) 201.92 233.33 T +(w of the cde) 214.5 233.33 T +(vT) 268.12 233.33 T +(r) 278.03 233.33 T +(anObj Class) 281.26 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 336.38 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(42) 528.88 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 180.2 221.33 T +(lic Data Proper) 197.79 221.33 T +(ties of the cde) 264.32 221.33 T +(vT) 326.28 221.33 T +(r) 336.19 221.33 T +(anObj Class) 339.42 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . .) 394.76 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(42) 528.88 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(system_) 198 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 236.3 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(42) 528.88 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(reqObj_) 198 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 236.3 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(42) 528.88 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(resultData_) 198 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(43) 528.88 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(userCallbac) 198 173.33 T +(k_) 250.59 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(43) 528.88 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 180.2 161.33 T +(lic Member Functions of the cde) 197.79 161.33 T +(vT) 339.21 161.33 T +(r) 349.12 161.33 T +(anObj Class) 352.35 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . .) 408.66 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(43) 528.88 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(status) 198 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 225.18 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(43) 528.88 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(remo) 198 137.33 T +(v) 220.63 137.33 T +(eF) 225.38 137.33 T +(romGr) 236.6 137.33 T +(ps) 265.23 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(43) 528.88 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(enab) 198 125.33 T +(leDeleteCbk) 220.04 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(43) 528.88 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(disab) 198 113.33 T +(leDeleteCbk) 221.7 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(43) 528.88 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16.) 162 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Language Speci\336cation f) 180 101.33 T +(or the cde) 289.21 101.33 T +(v DDL \336le) 333.38 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . .) 378.08 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(44) 528.88 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Language Speci\336cation) 180.2 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 286.34 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(44) 528.88 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "vi" 6 +%%Page: "vii" 7 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(vii) 548.56 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17.) 180 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Regular Expressions) 198 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 701.33 T +(er) 210.73 701.33 T +(vie) 219.92 701.33 T +(w of Regular Expressions) 232.5 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 347.5 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ordinar) 198.2 689.33 T +(y Char) 231.84 689.33 T +(acters) 261.19 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 289.12 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Special Char) 198.2 677.33 T +(acters) 255.34 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. [ \134) 216 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 230.74 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(*) 216 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 222.4 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(^) 216 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 222.4 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +($) 216 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 222.4 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(delimiter) 216 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 255.76 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(per) 216 605.33 T +(iod) 230.6 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Br) 198.2 593.33 T +(ac) 208.1 593.33 T +(k) 218.46 593.33 T +(et Expression) 223.26 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 286.34 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(br) 216 581.33 T +(ac) 224.79 581.33 T +(k) 235.15 581.33 T +(et e) 239.95 581.33 T +(xpression) 256.33 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 300.24 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(46) 546.88 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. * [ \134) 216 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(46) 546.88 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(matching list) 216 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(46) 546.88 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(non-matching list) 216 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(46) 546.88 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(collating element) 216 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(46) 546.88 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(collating symbol) 216 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 289.12 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(46) 546.88 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(noncollating char) 216 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(46) 546.88 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(equiv) 216 497.33 T +(alence class) 239.65 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 294.68 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(46) 546.88 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(r) 216 485.33 T +(ange e) 219.23 485.33 T +(xpression) 249.51 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 294.68 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(47) 546.88 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(char) 216 473.33 T +(acter class) 235.35 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(47) 546.88 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Matching Multiple Char) 198.2 461.33 T +(acters) 300.35 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 328.04 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(48) 546.88 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(RERE) 216 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(48) 546.88 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(RE*) 216 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 236.3 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(48) 546.88 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\134\050RE\134\051) 216 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(48) 546.88 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\134n) 216 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 225.18 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(48) 546.88 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(RE\134{m,n\134}) 216 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(49) 546.88 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Expression Anchor) 198.2 389.33 T +(ing) 282.27 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 297.46 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(49) 546.88 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "vii" 7 +%%Page: "viii" 8 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(viii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "viii" 8 +%%Page: "ix" 9 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(ix) 550.78 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(List of Figures) 180 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(Figure 1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object model of the cdevCallback class) 234 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................................) 408.66 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 2.) 180 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object Model of the cdevCollection Class) 234 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(................................................) 417 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 3.) 180 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object Model of the cdevCollectionRequest Class) 234 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..................................) 455.92 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 4.) 180 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object model of the cdevData class) 234 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................................................) 391.98 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 5.) 180 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object model of the cdevDevice class) 234 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................................................) 403.1 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 546.88 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 6.) 180 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Return codes generated by the send method.) 234 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................................) 436.46 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(19) 546.88 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 7.) 180 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object model of the cdevError class) 234 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(......................................................) 394.76 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 546.88 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 8.) 180 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object model of the cdevGroup class) 234 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(....................................................) 400.32 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(23) 546.88 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 9.) 180 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object model of the cdevIOContext class) 234 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..............................................) 417 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(26) 546.88 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 10.) 180 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object model of the cdevRequestObject class) 234 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................................) 436.46 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(27) 546.88 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 11.) 180 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Return codes generated by the send method.) 234 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................................) 436.46 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(30) 546.88 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 12.) 180 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object model of the cdevSelector class) 234 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.................................................) 408.66 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(31) 546.88 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 13.) 180 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object model of the cdevService class) 234 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..................................................) 405.88 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 546.88 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 14.) 180 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object model of the cdevSync class) 234 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(......................................................) 394.76 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(36) 546.88 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 15.) 180 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object model of the cdevSystemBase class) 234 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..........................................) 428.12 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(37) 546.88 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 16.) 180 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object model of the cdevSystem class) 234 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..................................................) 405.88 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(38) 546.88 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 17.) 180 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Object model of the cdevTranObj class) 234 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.................................................) 408.66 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(42) 546.88 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 18.) 180 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Language specification for the cdev DDL file) 234 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.........................................) 430.9 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(44) 546.88 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "ix" 9 +%%Page: "x" 10 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(x) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "x" 10 +%%Page: "1" 11 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. The cde) 451.92 739 T +(vCallbac) 494.17 739 T +(k Class) 528.5 739 T +0 10 Q +(1) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(1.) 159.32 710.67 T +(The cde) 180 710.67 T +(vCallbac) 232.7 710.67 T +(k Class) 290 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w of the) 108.64 673.33 T +(cde) 72 661.33 T +(vCallbac) 89.08 661.33 T +(k) 130.01 661.33 T +(Class) 72 649.33 T +0 F +2.26 (The) 180 673.33 P +3 F +2.26 (cde) 202.27 673.33 P +2.26 (vCallbac) 218.09 673.33 P +2.26 (k) 256.23 673.33 P +0 F +2.26 (C++ class is used b) 266.26 673.33 P +2.26 (y the sendCallbac) 362.35 673.33 P +2.26 (k method to specify the) 446.14 673.33 P +1.24 (callbac) 180 661.33 P +1.24 (k function that should be e) 210.92 661.33 P +1.24 (x) 333.54 661.33 P +1.24 (ecuted when the message has been processed.) 338.24 661.33 P +1.8 (This class also allo) 180 649.33 P +1.8 (ws the caller to include a user speci\336ed argument that will be) 269.17 649.33 P +(pro) 180 637.33 T +(vided as a par) 194.3 637.33 T +(ameter in the callbac) 257.01 637.33 T +(k function when it is e) 349.07 637.33 T +(x) 444.37 637.33 T +(ecuted.) 449.07 637.33 T +3 9 Q +(Figure 1: Object model of the cde) 180 604 T +(vCallbac) 315.3 604 T +(k class) 349.62 604 T +2 10 Q +(Pub) 72 451.33 T +(lic Methods of) 90.79 451.33 T +(the cde) 72 439.33 T +(vCallbac) 106.86 439.33 T +(k) 147.79 439.33 T +(Class) 72 427.33 T +(cde) 180 451.33 T +(vCallbac) 197.08 451.33 T +(k) 238.01 451.33 T +3 F +(cde) 279.29 451.33 T +(vCallbac) 295.11 451.33 T +(k \050v) 333.25 451.33 T +(oid\051;) 349.11 451.33 T +(cde) 279.29 439.33 T +(vCallbac) 295.11 439.33 T +(k \050cde) 333.25 439.33 T +(vCallbac) 360.18 439.33 T +(kFunction func) 398.32 439.33 T +(, v) 463.2 439.33 T +(oid * user) 473.51 439.33 T +(arg\051;) 515.65 439.33 T +(cde) 279.29 427.33 T +(vCallbac) 295.11 427.33 T +(k \050cde) 333.25 427.33 T +(vCallbac) 360.18 427.33 T +(k & callbac) 398.32 427.33 T +(k\051;) 446.47 427.33 T +0 F +-0.27 (This is the constr) 279.29 410.33 P +-0.27 (uctor f) 354.21 410.33 P +-0.27 (or the callbac) 381.42 410.33 P +-0.27 (k object. It sets the inter) 440.15 410.33 P +-0.27 (nal) 544.66 410.33 P +2.27 (pointers to the user speci\336ed callbac) 279.43 398.33 P +2.27 (k function and user) 452.34 398.33 P +2.27 (arg) 543.55 398.33 P +(pointer) 279.43 386.33 T +(.) 309.5 386.33 T +2 F +(callbac) 180 362.33 T +(kFunction) 213.71 362.33 T +3 F +(cde) 279.29 362.33 T +(vCallbac) 295.11 362.33 T +(kFunction callbac) 333.25 362.33 T +(kFunction \050v) 410.3 362.33 T +(oid\051;) 464.51 362.33 T +0 F +0.99 (Obtains a pointer to the callbac) 279.29 345.33 P +0.99 (k function that is stored within) 421.88 345.33 P +(the cde) 279.43 333.33 T +(vCallbac) 311.93 333.33 T +(k object.) 350.07 333.33 T +2 F +(userar) 180 309.33 T +(g) 210.42 309.33 T +3 F +(v) 279.29 309.33 T +(oid * user) 284.04 309.33 T +(arg \050v) 326.18 309.33 T +(oid\051;) 351.49 309.33 T +0 F +0.22 (Obtains a pointer to the user argument that is stored within the) 279.29 292.33 P +(cde) 279.43 280.33 T +(vCallbac) 295.25 280.33 T +(k object.) 333.39 280.33 T +2 F +(operator ==) 180 256.33 T +3 F +(int oper) 279.29 256.33 T +(ator == \050const cde) 312.54 256.33 T +(vCallbac) 392.84 256.33 T +(k& callbac) 430.98 256.33 T +(k\051;) 476.35 256.33 T +0 F +1.68 (Used to compare tw) 279.29 239.33 P +1.68 (o cde) 373.15 239.33 P +1.68 (vCallbac) 398.99 239.33 P +1.68 (k objects) 437.13 239.33 P +1.68 (. T) 478.12 239.33 P +1.68 (w) 490.27 239.33 P +1.68 (o objects are) 497.39 239.33 P +-0.23 (considered equal if the) 279.43 227.33 P +-0.23 (y point to the same callbac) 379.15 227.33 P +-0.23 (k function and) 496.2 227.33 P +(user argument.) 279.43 215.33 T +2 F +(operator !=) 180 191.33 T +3 F +(int oper) 279.29 191.33 T +(ator != \050const cde) 312.54 191.33 T +(vCallbac) 389.78 191.33 T +(k& callbac) 427.92 191.33 T +(k\051;) 473.29 191.33 T +0 F +(Used to compare tw) 279.29 174.33 T +(o cde) 368.11 174.33 T +(vCallbac) 392.27 174.33 T +(k objects) 430.41 174.33 T +(. T) 469.72 174.33 T +(w) 480.19 174.33 T +(o objects are) 487.31 174.33 T +(considered equal if the) 279.43 162.33 T +(y point to the same callbac) 379.84 162.33 T +(k function and) 498.03 162.33 T +(user argument.) 279.43 150.33 T +180 477 558 680 C +180 477 558 601 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +177.29 477 560.71 601 R +7 X +0 0 0 1 0 0 0 K +V +187.38 484 559.05 593.5 R +0 X +V +0.5 H +2 Z +N +183.55 485.79 555.22 597.33 R +7 X +V +0 X +N +204.46 489.48 534.3 590.31 R +7 X +V +0 X +N +211.05 492.54 529.38 586.05 R +7 X +V +4 9 Q +0 X +(class cdevCallback) 321.61 580.05 T +(methods:) 211.05 569.05 T +(callbackFunction \050void\051 : cdevCallbackFunction) 224.38 558.05 T +(userarg \050void\051 : void *) 224.38 547.05 T +(operator == \050cdevCallback &\051 : int) 224.38 536.05 T +(operator != \050cdevCallback &\051 : int) 224.38 525.05 T +(fireCallback \050...\051 : void) 224.38 514.05 T +(isTransactionDone\050void\051 {static}: int) 224.38 503.05 T +203.97 576.61 533.12 576.61 2 L +N +180 477 558 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "1" 11 +%%Page: "2" 12 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. The cde) 54 739 T +(vCallbac) 96.25 739 T +(k Class) 130.58 739 T +0 10 Q +(2) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(\336reCallbac) 162 713.33 T +(k) 212.93 713.33 T +3 F +(v) 261.29 713.33 T +(oid \336reCallbac) 266.04 713.33 T +(k \050) 329.19 713.33 T +(int status) 351.91 713.33 T +(,) 391.78 713.33 T +(v) 351.91 701.33 T +(oid * user) 356.66 701.33 T +(arg,) 398.8 701.33 T +(cde) 351.91 689.33 T +(vRequestObject & req,) 367.73 689.33 T +(cde) 351.91 677.33 T +(vData & result,) 367.73 677.33 T +(int par) 351.91 665.33 T +(tialT) 380.1 665.33 T +(r) 397.79 665.33 T +(ansaction = 0\051;) 401.02 665.33 T +0 F +0.62 (This method allo) 261.29 648.33 P +0.62 (ws the caller to dispatch the callbac) 335.74 648.33 P +0.62 (k function) 496.58 648.33 P +2.99 (with the speci\336ed par) 261.43 636.33 P +2.99 (ameters) 364.23 636.33 P +2.99 (. If the callbac) 400.2 636.33 P +2.99 (k represents a) 470.66 636.33 P +4.58 (response that is one of man) 261.43 624.33 P +4.58 (y that will occur) 407.57 624.33 P +4.58 (, then the) 489.15 624.33 P +0.29 (par) 261.43 612.33 P +0.29 (tialT) 276.28 612.33 P +0.29 (r) 293.97 612.33 P +0.29 (ansaction \337ag should be set to non-z) 297.2 612.33 P +0.29 (ero) 461.67 612.33 P +0.29 (. The v) 475.72 612.33 P +0.29 (alue of) 509.69 612.33 P +10.37 (this \337ag can be retr) 261.43 600.33 P +10.37 (ie) 388.11 600.33 P +10.37 (v) 395.59 600.33 P +10.37 (ed b) 400.34 600.33 P +10.37 (y calling the static) 429.97 600.33 P +(cde) 261.43 588.33 T +(vCallbac) 277.25 588.33 T +(k::isT) 315.39 588.33 T +(r) 338.08 588.33 T +(ansactionDone method.) 341.31 588.33 T +2 F +(isT) 162 564.33 T +(ransactionDone) 175.65 564.33 T +3 F +(int isT) 261.29 564.33 T +(r) 286.76 564.33 T +(ansactionDone \050 v) 289.99 564.33 T +(oid \051;) 370.33 564.33 T +0 F +4.06 (This method retur) 261.29 547.33 P +4.06 (ns an integer indicating if this callbac) 348.01 547.33 P +4.06 (k) 535 547.33 P +0.7 (indicates the end of the tr) 261.43 535.33 P +0.7 (ansaction. In the e) 377.1 535.33 P +0.7 (v) 464.09 535.33 P +0.7 (ent of m) 468.84 535.33 P +0.7 (ulti-par) 506.26 535.33 P +0.7 (t) 537.22 535.33 P +2.5 (tr) 261.43 523.33 P +2.5 (ansactions such as \322monitorOn\323, this method will retur) 267.44 523.33 P +2.5 (n a) 523.6 523.33 P +0.06 (non-z) 261.43 511.33 P +0.06 (ero v) 286.29 511.33 P +0.06 (alue indicating that more callbac) 308.33 511.33 P +0.06 (ks can be e) 451.19 511.33 P +0.06 (xpected.) 502.2 511.33 P +0.73 (In the e) 261.43 499.33 P +0.73 (v) 295.94 499.33 P +0.73 (ent of monotonic oper) 300.69 499.33 P +0.73 (ations such as \322get\323 or \322set\323, or) 399.49 499.33 P +2.29 (when the last monitor callbac) 261.43 487.33 P +2.29 (k is receiv) 399.33 487.33 P +2.29 (ed, this method will) 448.1 487.33 P +(retur) 261.43 475.33 T +(n z) 282.24 475.33 T +(ero) 295.43 475.33 T +(.) 309.48 475.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "2" 12 +%%Page: "3" 13 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. The cde) 446.73 739 T +(vCollection Class) 488.99 739 T +0 10 Q +(3) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(2.) 159.32 710.67 T +(The cde) 180 710.67 T +(vCollection Class) 232.7 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w of the) 108.64 673.33 T +(cde) 72 661.33 T +(vCollection) 89.08 661.33 T +(Class) 72 649.33 T +0 F +-0.21 (The cde) 180 673.33 P +-0.21 (vCollection class pro) 215.62 673.33 P +-0.21 (vides a mechanism f) 306.74 673.33 P +-0.21 (or sending a message to a collection) 396.95 673.33 P +1.35 (of named de) 180 661.33 P +1.35 (vices) 237.98 661.33 P +1.35 (. The class maintains a list of CDEV de) 260.61 661.33 P +1.35 (vices that are associated) 443.91 661.33 P +1.92 (through an entr) 180 649.33 P +1.92 (y in the CDEV DDL \336le) 251.95 649.33 P +1.92 (. The de) 362.53 649.33 P +1.92 (v) 402.75 649.33 P +1.92 (eloper also dynamically create a) 407.5 649.33 P +(cde) 180 637.33 T +(vCollection de) 195.82 637.33 T +(vice) 258.32 637.33 T +(.) 275.95 637.33 T +3 9 Q +(Figure 2: Object Model of the cde) 180 621 T +(vCollection Class) 315.3 621 T +2 10 Q +(Pub) 72 237.9 T +(lic Methods of) 90.79 237.9 T +(the) 72 225.9 T +(cde) 72 213.9 T +(vCollection) 89.08 213.9 T +(Class) 72 201.9 T +(cde) 180 237.9 T +(vCollection) 197.08 237.9 T +3 F +(cde) 279.29 237.9 T +(vCollection \050char * name) 295.11 237.9 T +(, cde) 403.88 237.9 T +(vSystem & system\051;) 425.26 237.9 T +0 F +1.03 (This is the constr) 279.29 220.9 P +1.03 (uctor f) 358.11 220.9 P +1.03 (or the cde) 386.63 220.9 P +1.03 (vCollection class) 432.86 220.9 P +1.03 (. It has the) 508.21 220.9 P +(f) 279.43 208.9 T +(ollo) 281.91 208.9 T +(wing proper) 297.32 208.9 T +(ties) 349.96 208.9 T +(.) 365.37 208.9 T +(\245) 279.29 190.9 T +0.8 (This method is) 297.29 190.9 P +5 F +0.8 (pr) 367.48 190.9 P +0.8 (otected) 377.27 190.9 P +0 F +0.8 ( to pre) 412.83 190.9 P +0.8 (v) 442.48 190.9 P +0.8 (ent) 447.23 190.9 P +3 F +0.8 (cde) 464.7 190.9 P +0.8 (vCollections) 480.52 190.9 P +0 F +0.8 ( from) 534.42 190.9 P +2.2 (being instantiated directly) 297.29 178.9 P +2.2 (. Ne) 413.52 178.9 P +2.2 (w) 433.86 178.9 P +3 F +2.2 (cde) 446.06 178.9 P +2.2 (vCollection) 461.88 178.9 P +0 F +2.2 ( instances) 510.78 178.9 P +0.7 (are created b) 297.29 166.9 P +0.7 (y using the) 357.42 166.9 P +3 F +0.7 (attachPtr) 410.67 166.9 P +0 F +0.7 ( or) 450.69 166.9 P +3 F +0.7 (attachRef) 466.54 166.9 P +0 F +0.7 ( method of) 509.34 166.9 P +(the) 297.29 154.9 T +3 F +(cde) 313.97 154.9 T +(vCollection) 329.79 154.9 T +0 F +( class) 378.69 154.9 T +(.) 404.1 154.9 T +(\245) 279.29 136.91 T +2.59 (The name that is pro) 297.29 136.91 P +2.59 (vided to the) 399.19 136.91 P +3 F +2.59 (cde) 461.43 136.91 P +2.59 (vCollection) 477.25 136.91 P +0 F +2.59 ( is the) 526.15 136.91 P +1.37 (de) 297.29 124.91 P +1.37 (vice name that CDEV will use to ref) 308.11 124.91 P +1.37 (er to it. The name) 474.14 124.91 P +1.93 (m) 297.29 112.91 P +1.93 (ust be unique within the CDEV system of objects and) 305.52 112.91 P +-0.26 (cannot be the same as the name of an) 297.29 100.91 P +-0.26 (y regular) 465.75 100.91 P +3 F +-0.26 (cde) 506.92 100.91 P +-0.26 (vDe) 522.74 100.91 P +-0.26 (vice) 540.22 100.91 P +0 F +(that e) 297.29 88.91 T +(xists in the CDEV DDL \336le) 322.01 88.91 T +(.) 438 88.91 T +180 263.57 558 680 C +180 263.57 558 618 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +188.86 345.14 552.43 606.57 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +356.35 326.72 351.35 336.01 356.35 345.29 361.35 336.01 4 Y +N +377.57 307.86 509 322.14 R +7 X +V +0 X +N +2 10 Q +(c) 405.94 312.74 T +(lass cde) 411.3 312.74 T +(vSList) 450.62 312.74 T +356.35 326.71 356.35 314.57 377.78 314.57 3 L +N +399.35 288.72 394.35 298.01 399.35 307.29 404.35 298.01 4 Y +N +420.57 270.57 552 284.86 R +7 X +V +0 X +N +(c) 441.95 275.45 T +(har * de) 447.41 275.45 T +(viceName) 483.94 275.45 T +399.35 288.71 399.35 276.57 420.78 276.57 3 L +N +90 450 2.86 3.21 417.78 277.07 G +90 450 2.86 3.21 417.78 277.07 A +188.57 593.28 552.15 593.28 2 L +N +4 9 Q +(cdevCollection) 333.27 597.33 T +6 F +(methods) 192.14 586.33 T +4 F +(:) 229.94 586.33 T +(cdevCollection \050char *, cdevSystem &\051) 207 575.33 T +(~cdevCollection \050void\051 :{virtual}) 207 564.33 T +(getRequestObject \050char *, cdevRequestObject *&\051 :{virtual} int) 207 553.33 T +-0.11 (attachRef \050char *\051 :{static} cdevCollection &) 207 531.33 P +-0.11 (attachPtr \050char *\051 :{static} cdevCollection *) 207 520.33 P +-0.22 (attachRef \050char *, cdevSystem &\051 :{static} cdevCollection *) 207 509.33 P +-0.22 (attachPtr \050char *, cdevSystem &\051 :{static} cdevCollection &) 207 498.33 P +(detach \050cdevCollection &\051 :{static} void) 207 487.33 T +(detach \050cdevCollection *\051 :{static} void) 207 476.33 T +(className \050void\051 :{virtual} char *) 207 465.33 T +(add \050char *\051 : int) 207 454.33 T +(add \050int, char *, ...\051 : int) 207 443.33 T +(add \050int, char **\051 : int) 207 432.33 T +(add \050char **\051 : int) 207 421.33 T +(addRegexp \050char *\051 : int) 207 410.33 T +(remove \050char *\051 : int) 207 399.33 T +(remove \050int, char *, ...\051 : int) 207 388.33 T +(remove \050int, char **\051 : int) 207 377.33 T +(remove \050char **\051 : int) 207 366.33 T +(removeRegexp \050char *\051 : int) 207 355.33 T +180 263.57 558 618 R +1 H +0 Z +N +180 263.57 558 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "3" 13 +%%Page: "4" 14 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. The cde) 54 739 T +(vCollection Class) 96.25 739 T +0 10 Q +(4) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(\245) 261.29 713.33 T +6.39 (The) 279.29 713.33 P +3 F +6.39 (cde) 305.68 713.33 P +6.39 (vSystem) 321.5 713.33 P +0 F +6.39 ( ref) 359.84 713.33 P +6.39 (erence that is pro) 380.38 713.33 P +6.39 (vided is the) 476.65 713.33 P +3 F +1.7 (cde) 279.29 701.33 P +1.7 (vSystem) 295.11 701.33 P +0 F +1.7 ( instance that will be used to) 333.45 701.33 P +3 F +1.7 (poll) 473.77 701.33 P +0 F +1.7 (,) 489.33 701.33 P +3 F +1.7 (pend) 496.6 701.33 P +0 F +1.7 ( and) 518.84 701.33 P +3 F +(\337ush) 279.29 689.33 T +0 F +( the) 300.41 689.33 T +3 F +(cde) 319.87 689.33 T +(vCollection) 335.69 689.33 T +0 F +( object.) 384.59 689.33 T +(\245) 261.29 671.33 T +0.88 (If the name pro) 279.29 671.33 P +0.88 (vided is the name of a) 349.04 671.33 P +3 F +0.88 (cde) 454.94 671.33 P +0.88 (vCollection) 470.76 671.33 P +0 F +0.88 ( that) 519.66 671.33 P +1.23 (has been speci\336ed in the) 279.29 659.33 P +3 F +1.23 (CDEV DDL) 398.83 659.33 P +0 F +1.23 ( \336le) 450.62 659.33 P +1.23 (, then the list of) 467.26 659.33 P +5.11 (de) 279.29 647.33 P +5.11 (vices will be populated from the names that are) 290.11 647.33 P +-0.01 (speci\336ed. Otherwise) 279.29 635.33 P +-0.01 (, an empty) 369.16 635.33 P +3 F +-0.01 (cde) 418.61 635.33 P +-0.01 (vCollection) 434.43 635.33 P +0 F +-0.01 ( instance will) 483.33 635.33 P +(be created.) 279.29 623.33 T +2 F +(~cde) 162 599.33 T +(vCollection) 184.92 599.33 T +3 F +(vir) 261.29 599.33 T +(tual ~cde) 272.24 599.33 T +(vCollection \050v) 312.8 599.33 T +(oid\051;) 372.56 599.33 T +0 F +1.96 (This is the destr) 261.29 582.33 P +1.96 (uctor f) 337.9 582.33 P +1.96 (or a cde) 367.35 582.33 P +1.96 (vCollection object. It has the) 407.1 582.33 P +(f) 261.43 570.33 T +(ollo) 263.91 570.33 T +(wing proper) 279.32 570.33 T +(ties) 331.96 570.33 T +(.) 347.37 570.33 T +(\245) 261.29 546.33 T +2.91 (This method is protected to pre) 279.29 546.33 P +2.91 (v) 431.36 546.33 P +2.91 (ent the) 436.11 546.33 P +3 F +2.91 (cde) 475.28 546.33 P +2.91 (vCollection) 491.1 546.33 P +0 F +4.71 (object from being destro) 279.29 534.33 P +4.71 (y) 400.39 534.33 P +4.71 (ed b) 405.19 534.33 P +4.71 (y the application. This) 429.16 534.33 P +1.87 (method should only be called b) 279.29 522.33 P +1.87 (y the) 426.3 522.33 P +3 F +1.87 (cde) 454.51 522.33 P +1.87 (vSystem) 470.33 522.33 P +0 F +1.87 ( object) 508.67 522.33 P +(when the application is ter) 279.29 510.33 T +(minating.) 395.15 510.33 T +(\245) 261.29 486.33 T +-0.1 (Because the) 279.29 486.33 P +3 F +-0.1 (cde) 337.46 486.33 P +-0.1 (vCollection) 353.28 486.33 P +0 F +-0.1 ( object will nor) 402.18 486.33 P +-0.1 (mally be ref) 465.48 486.33 P +-0.1 (erred) 516.66 486.33 P +3.1 (to as a) 279.29 474.33 P +3 F +3.1 (cde) 321.39 474.33 P +3.1 (vDe) 337.2 474.33 P +3.1 (vice) 354.68 474.33 P +0 F +3.1 ( object, this destr) 372.46 474.33 P +3.1 (uctor is vir) 457.5 474.33 P +3.1 (tual to) 509.66 474.33 P +(ensure that the) 279.29 462.33 T +5 F +(\324most senior\325) 348.78 462.33 T +0 F +( destr) 411.02 462.33 T +(uctor is called \336rst.) 436.18 462.33 T +(\245) 261.29 438.33 T +2 (This method will delete all de) 279.29 438.33 P +2 (vice name str) 417.36 438.33 P +2 (ings that are) 480.97 438.33 P +(associated with the) 279.29 426.33 T +3 F +(cde) 367.11 426.33 T +(vCollection) 382.93 426.33 T +0 F +( object.) 431.83 426.33 T +2 F +(g) 162 402.33 T +(etRequestObject) 168.21 402.33 T +3 F +(vir) 261.29 402.33 T +(tual int getRequestObject \050) 272.24 402.33 T +(char *msg,) 390.63 402.33 T +(cde) 333.57 390.33 T +(vRequestObject* &req\051;) 349.39 390.33 T +0 F +0.06 (This method is called in order to obtain the cde) 261.29 373.33 P +0.06 (vRequestObject) 468.86 373.33 P +2.85 (associated with the speci\336ed de) 261.43 361.33 P +2.85 (vice/msg combination. This) 413.71 361.33 P +2.48 (method retur) 261.43 349.33 P +2.48 (ns CDEV_SUCCESS if the cde) 320.85 349.33 P +2.48 (vRequestObject) 468.86 349.33 P +3.67 (w) 261.43 337.33 P +3.67 (as successfully obtained. This method has the f) 268.5 337.33 P +3.67 (ollo) 504.03 337.33 P +3.67 (wing) 519.44 337.33 P +(proper) 261.43 325.33 T +(ties) 290.73 325.33 T +(.) 306.14 325.33 T +(\245) 261.29 301.33 T +0.57 (The) 279.29 301.33 P +3 F +0.57 (cde) 299.86 301.33 P +0.57 (vRequestObject) 315.68 301.33 P +0 F +0.57 ( pointer that is retur) 386.83 301.33 P +0.57 (ned is actually) 475.5 301.33 P +(a pointer to a) 279.29 289.33 T +3 F +(cde) 340.44 289.33 T +(vCollectionRequest) 356.26 289.33 T +0 F +( object.) 442.4 289.33 T +(\245) 261.29 265.33 T +0.77 (If a) 279.29 265.33 P +3 F +0.77 (cde) 297.51 265.33 P +0.77 (vCollectionRequest) 313.33 265.33 P +0 F +0.77 ( already e) 399.47 265.33 P +0.77 (xists f) 444.62 265.33 P +0.77 (or the speci\336ed) 470.65 265.33 P +0.35 (de) 279.29 253.33 P +0.35 (vice/msg combination, it will be retur) 290.11 253.33 P +0.35 (ned. Otherwise) 452.73 253.33 P +0.35 (, the) 520.18 253.33 P +9.93 (method will call the) 279.29 241.33 P +3 F +9.93 (attachPtr) 406.26 241.33 P +0 F +9.93 ( method of the) 446.28 241.33 P +3 F +2.22 (cde) 279.29 229.33 P +2.22 (vCollectionRequest) 295.11 229.33 P +0 F +2.22 ( in order to obtain a ne) 381.25 229.33 P +2.22 (w request) 494.43 229.33 P +(object.) 279.29 217.33 T +2 F +(attac) 162 193.33 T +(hRef/attac) 185.24 193.33 T +(hPtr) 233.48 193.33 T +3 F +(cde) 261.29 193.33 T +(vCollection & attachRef) 277.11 193.33 T +(\050char * name\051;) 381.04 193.33 T +(cde) 261.29 181.33 T +(vCollection & attachRef) 277.11 181.33 T +(\050char * name) 381.04 181.33 T +(, cde) 438.13 181.33 T +(vSystem & sys\051;) 459.51 181.33 T +(cde) 261.29 169.33 T +(vCollection * attachPtr) 277.11 169.33 T +(\050char * name\051;) 375.48 169.33 T +(cde) 261.29 157.33 T +(vCollection * attachPtr) 277.11 157.33 T +(\050char * name) 375.48 157.33 T +(, cde) 432.57 157.33 T +(vSystem &sys\051;) 453.95 157.33 T +0 F +0.86 (These methods are used to obtain a pointer or ref) 261.29 140.33 P +0.86 (erence to a) 488.26 140.33 P +-0.12 (cde) 261.43 128.33 P +-0.12 (vCollection object. The name v) 277.25 128.33 P +-0.12 (ar) 413.25 128.33 P +-0.12 (iab) 422.29 128.33 P +-0.12 (le speci\336es the name of) 435.43 128.33 P +0.29 (the collection to be attached. These method ha) 261.43 116.33 P +0.29 (v) 471.19 116.33 P +0.29 (e the f) 475.94 116.33 P +0.29 (ollo) 504.03 116.33 P +0.29 (wing) 519.44 116.33 P +(proper) 261.43 104.33 T +(ties) 290.73 104.33 T +(.) 306.14 104.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "4" 14 +%%Page: "5" 15 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. The cde) 446.73 739 T +(vCollection Class) 488.99 739 T +0 10 Q +(5) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 279.29 713.33 T +0.1 (All functionality f) 297.29 713.33 P +0.1 (or these methods is stored in the) 369.43 713.33 P +3 F +0.1 (attachPtr) 517.98 713.33 P +0.54 (\050char *, cde) 297.29 701.33 P +0.54 (vSystem &\051) 349.19 701.33 P +0 F +0.54 ( method. All other methods will call) 400.85 701.33 P +(this one) 297.29 689.33 T +(.) 332.16 689.33 T +(\245) 279.29 665.33 T +1.56 (The method will \336rst deter) 297.29 665.33 P +1.56 (mine if the de) 418.24 665.33 P +1.56 (vice has already) 482.64 665.33 P +2.1 (been created. If it has been created and its) 297.29 653.33 P +3 F +2.1 (className) 508.55 653.33 P +0 F +8.19 (method retur) 297.29 641.33 P +8.19 (ns \322) 362.42 641.33 P +3 F +8.19 (cde) 387.29 641.33 P +8.19 (vCollection) 403.11 641.33 P +0 F +8.19 (\323, then the e) 452.01 641.33 P +8.19 (xisting) 529.66 641.33 P +3 F +6.87 (cde) 297.29 629.33 P +6.87 (vCollection) 313.11 629.33 P +0 F +6.87 ( will be retur) 362.01 629.33 P +6.87 (ned. If a non-collection) 436.77 629.33 P +3 F +6.76 (cde) 297.29 617.33 P +6.76 (vDe) 313.11 617.33 P +6.76 (vice) 330.59 617.33 P +0 F +6.76 ( of the same name has already been) 348.37 617.33 P +(constr) 297.29 605.33 T +(ucted, then NULL will be retur) 324.67 605.33 T +(ned.) 456.64 605.33 T +(\245) 279.29 581.33 T +1.2 (If a de) 297.29 581.33 P +1.2 (vice with the speci\336ed name has not already been) 327.18 581.33 P +0.67 (created, then the method will search the) 297.29 569.33 P +3 F +0.67 (cde) 482.06 569.33 P +0.67 (vDirector) 497.88 569.33 P +0.67 (y) 538.18 569.33 P +0 F +0.67 ( f) 543.18 569.33 P +0.67 (or) 549.11 569.33 P +5.86 (the speci\336ed name) 297.29 557.33 P +5.86 (. If the de) 392.78 557.33 P +5.86 (vice name is in the) 451.76 557.33 P +3 F +2.95 (cde) 297.29 545.33 P +2.95 (vDirector) 313.11 545.33 P +2.95 (y) 353.41 545.33 P +0 F +2.95 ( AND is of class \322) 358.41 545.33 P +3 F +2.95 (collection) 449.85 545.33 P +0 F +2.95 (\323, then a ne) 491.53 545.33 P +2.95 (w) 550.78 545.33 P +3 F +1.19 (cde) 297.29 533.33 P +1.19 (vCollection) 313.11 533.33 P +0 F +1.19 ( will be instantiated and retur) 362.01 533.33 P +1.19 (ned. If a non-) 495.49 533.33 P +3.38 (collection) 297.29 521.33 P +3 F +3.38 (cde) 345.13 521.33 P +3.38 (vDe) 360.95 521.33 P +3.38 (vice) 378.43 521.33 P +0 F +3.38 ( of the same name e) 396.21 521.33 P +3.38 (xists in the) 503.99 521.33 P +3 F +(cde) 297.29 509.33 T +(vDirector) 313.11 509.33 T +(y) 353.41 509.33 T +0 F +(, then NULL will be retur) 357.41 509.33 T +(ned.) 464.92 509.33 T +(\245) 279.29 485.33 T +5.28 (If a de) 297.29 485.33 P +5.28 (vice with the speci\336ed name has not been) 335.36 485.33 P +0.27 (instantiated and does not e) 297.29 473.33 P +0.27 (xist in the) 418.15 473.33 P +3 F +0.27 (cde) 463.98 473.33 P +0.27 (vDirector) 479.8 473.33 P +0.27 (y) 520.1 473.33 P +0 F +0.27 (, then a) 524.1 473.33 P +5.57 (ne) 297.29 461.33 P +5.57 (w) 308.21 461.33 P +5.57 (, empty) 314.83 461.33 P +3 F +5.57 (cde) 361.53 461.33 P +5.57 (vCollection) 377.35 461.33 P +0 F +5.57 ( will be created with the) 426.25 461.33 P +(speci\336ed name) 297.29 449.33 T +(.) 364.39 449.33 T +(\245) 279.29 425.33 T +-0.16 (If NULL is retur) 297.29 425.33 P +-0.16 (ned to one of the) 364.3 425.33 P +3 F +-0.16 (attachRef) 441.34 425.33 P +0 F +-0.16 ( methods) 484.14 425.33 P +-0.16 (, then a) 524.96 425.33 P +-0.23 (ref) 297.29 413.33 P +-0.23 (erence to a) 308.66 413.33 P +3 F +-0.23 (cde) 360.79 413.33 P +-0.23 (vErrorCollection) 376.61 413.33 P +0 F +-0.23 ( object will be retur) 447.73 413.33 P +-0.23 (ned to) 530.43 413.33 P +(the caller) 297.29 401.33 T +(.) 337.36 401.33 T +(\245) 279.29 377.33 T +5.23 (The) 297.29 377.33 P +3 F +5.23 (refCount) 322.53 377.33 P +0 F +5.23 ( proper) 360.88 377.33 P +5.23 (ty of the) 398.19 377.33 P +3 F +5.23 (cde) 452.25 377.33 P +5.23 (vCollection) 468.07 377.33 P +0 F +5.23 ( will be) 516.97 377.33 P +0.36 (incremented each time a cop) 297.29 365.33 P +0.36 (y of the) 426.81 365.33 P +3 F +0.36 (cde) 463.46 365.33 P +0.36 (vCollection) 479.28 365.33 P +0 F +0.36 ( object) 528.18 365.33 P +(is obtained b) 297.29 353.33 T +(y the application.) 353.79 353.33 T +2 F +(detac) 180 329.33 T +(h) 206.02 329.33 T +3 F +(int detach \050cde) 279.29 329.33 T +(vCollection & col\051;) 344.58 329.33 T +(int detach \050cde) 279.29 317.33 T +(vCollection * col\051;) 344.58 317.33 T +0 F +2.12 (This method is called to detach a pointer or ref) 279.29 300.33 P +2.12 (erence to a) 503.73 300.33 P +(cde) 279.43 288.33 T +(vCollection object. It has the f) 295.25 288.33 T +(ollo) 425.57 288.33 T +(wing proper) 440.98 288.33 T +(ties) 493.62 288.33 T +(.) 509.03 288.33 T +(\245) 279.29 264.33 T +3.6 (This method decrements the) 297.29 264.33 P +3 F +3.6 (refCount) 441.19 264.33 P +0 F +3.6 ( proper) 479.54 264.33 P +3.6 (ty of the) 515.22 264.33 P +3 F +(cde) 297.29 252.33 T +(vCollection) 313.11 252.33 T +0 F +( object.) 362.01 252.33 T +(\245) 279.29 228.33 T +0.51 (When the) 297.29 228.33 P +3 F +0.51 (refCount) 343.89 228.33 P +0 F +0.51 ( proper) 382.24 228.33 P +0.51 (ty is decremented to 0, then the) 414.84 228.33 P +3 F +(cde) 297.29 216.33 T +(vCollection) 313.11 216.33 T +0 F +( object will be deleted.) 362.01 216.33 T +2 F +(c) 180 192.33 T +(lassName) 185.36 192.33 T +3 F +(char * className \050v) 279.29 192.33 T +(oid\051;) 368.5 192.33 T +0 F +0.41 (This method retur) 279.29 175.33 P +0.41 (ns the name of the class; \322) 358.71 175.33 P +3 F +0.41 (cde) 478.42 175.33 P +0.41 (vCollection) 494.24 175.33 P +0 F +0.41 (\323. If) 543.14 175.33 P +1.66 (the de) 279.43 163.33 P +1.66 (v) 308.6 163.33 P +1.66 (eloper inher) 313.35 163.33 P +1.66 (its a ser) 367.96 163.33 P +1.66 (vice speci\336c cde) 406.59 163.33 P +1.66 (vCollection, then) 482.42 163.33 P +(this method should not be altered or o) 279.43 151.33 T +(v) 447.15 151.33 T +(err) 451.9 151.33 T +(idden.) 464.27 151.33 T +2 F +(ad) 180 127.33 T +(d) 191.57 127.33 T +3 F +(int add \050char *name\051;) 279.29 127.33 T +0 F +1.21 (This method will add the individual name to the list of de) 279.29 110.33 P +1.21 (vice) 540.22 110.33 P +2.33 (names that are in the cde) 279.43 98.33 P +2.33 (vCollection. This method has the) 403.62 98.33 P +(f) 279.43 86.33 T +(ollo) 281.91 86.33 T +(wing proper) 297.32 86.33 T +(ties) 349.96 86.33 T +(.) 365.37 86.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "5" 15 +%%Page: "6" 16 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. The cde) 54 739 T +(vCollection Class) 96.25 739 T +0 10 Q +(6) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(\245) 261.29 713.33 T +0.09 (If a) 279.29 713.33 P +3 F +0.09 (cde) 296.14 713.33 P +0.09 (vCollectionRequest) 311.96 713.33 P +0 F +0.09 ( object has been instantiated f) 398.1 713.33 P +0.09 (or) 531.11 713.33 P +1.12 (this) 279.29 701.33 P +3 F +1.12 (cde) 298.75 701.33 P +1.12 (vCollection) 314.57 701.33 P +0 F +1.12 ( de) 363.47 701.33 P +1.12 (vice) 378.19 701.33 P +1.12 (, then the oper) 395.82 701.33 P +1.12 (ation will f) 463.58 701.33 P +1.12 (ail and) 509.42 701.33 P +2 F +(CDEV_INV) 279.29 689.33 T +(ALIDOP) 328.5 689.33 T +0 F +( will be retur) 366.28 689.33 T +(ned.) 420.43 689.33 T +(\245) 261.29 665.33 T +0.46 (If the name pro) 279.29 665.33 P +0.46 (vided is NULL or empty) 347.78 665.33 P +0.46 (, then the oper) 452.55 665.33 P +0.46 (ation) 518.32 665.33 P +(will f) 279.29 653.33 T +(ail and) 298.43 653.33 T +2 F +(CDEV_INV) 330.67 653.33 T +(ALIDOP) 379.88 653.33 T +0 F +( will be retur) 417.66 653.33 T +(ned.) 471.81 653.33 T +(\245) 261.29 629.33 T +2.45 (If the name speci\336ed already e) 279.29 629.33 P +2.45 (xists in the collection of) 427.4 629.33 P +1.29 (names) 279.29 617.33 P +1.29 (, then the oper) 309.15 617.33 P +1.29 (ation will f) 377.4 617.33 P +1.29 (ail and) 423.57 617.33 P +2 F +1.29 (CDEV_W) 458.38 617.33 P +1.29 (ARNING) 500.56 617.33 P +0 F +(will be retur) 279.29 605.33 T +(ned.) 330.66 605.33 T +(\245) 261.29 581.33 T +2.02 (If the name speci\336ed is not already in the list, then the) 279.29 581.33 P +0.79 (method will append the de) 279.29 569.33 P +0.79 (vice name to the end of the list) 398.86 569.33 P +(and retur) 279.29 557.33 T +(n) 319.56 557.33 T +2 F +(CDEV_SUCCESS) 327.9 557.33 T +0 F +(.) 409.38 557.33 T +2 F +(ad) 162 533.33 T +(d) 173.57 533.33 T +3 F +(int add \050int n) 261.29 533.33 T +(um, char *\336rstname) 316.22 533.33 T +(,...\051;) 402.76 533.33 T +0 F +1.93 (This method will attempt to add a list of n) 261.29 516.33 P +1.93 (um names to the) 459.73 516.33 P +(cde) 261.43 504.33 T +(vCollection. This method has the f) 277.25 504.33 T +(ollo) 427.57 504.33 T +(wing proper) 442.98 504.33 T +(ties) 495.62 504.33 T +(.) 511.03 504.33 T +(\245) 261.29 480.33 T +0.09 (If a) 279.29 480.33 P +3 F +0.09 (cde) 296.14 480.33 P +0.09 (vCollectionRequest) 311.96 480.33 P +0 F +0.09 ( object has been instantiated f) 398.1 480.33 P +0.09 (or) 531.11 480.33 P +1.12 (this) 279.29 468.33 P +3 F +1.12 (cde) 298.75 468.33 P +1.12 (vCollection) 314.57 468.33 P +0 F +1.12 ( de) 363.47 468.33 P +1.12 (vice) 378.19 468.33 P +1.12 (, then the oper) 395.82 468.33 P +1.12 (ation will f) 463.58 468.33 P +1.12 (ail and) 509.42 468.33 P +2 F +(CDEV_INV) 279.29 456.33 T +(ALIDOP) 328.5 456.33 T +0 F +( will be retur) 366.28 456.33 T +(ned.) 420.43 456.33 T +(\245) 261.29 432.33 T +-0.02 (This method will call the) 279.29 432.33 P +3 F +-0.02 (add \050char *name\051) 388.11 432.33 P +0 F +-0.02 (method f) 468.08 432.33 P +-0.02 (or each) 506.67 432.33 P +(name that is speci\336ed.) 279.29 420.33 T +(\245) 261.29 396.33 T +2.39 (If the add method f) 279.29 396.33 P +2.39 (ails to add an) 371.95 396.33 P +2.39 (y of the de) 438.46 396.33 P +2.39 (vice name) 492.04 396.33 P +-0.22 (str) 279.29 384.33 P +-0.22 (ings to the list, then the error code that w) 290.55 384.33 P +-0.22 (as gener) 469.04 384.33 P +-0.22 (ated b) 507.62 384.33 P +-0.22 (y) 535 384.33 P +(the call to) 279.29 372.33 T +3 F +(add \050char * name\051) 324.87 372.33 T +0 F +( will be retur) 404.9 372.33 T +(ned.) 459.05 372.33 T +(\245) 261.29 348.33 T +2.58 (If an error occurs while adding a name to the list, the) 279.29 348.33 P +-0.01 (method will contin) 279.29 336.33 P +-0.01 (ue with the ne) 358.63 336.33 P +-0.01 (xt name until the last name) 420.56 336.33 P +(is reached.) 279.29 324.33 T +(\245) 261.29 300.33 T +2.62 (If no errors occur while adding names to the list, then) 279.29 300.33 P +2 F +(CDEV_SUCCESS) 279.29 288.33 T +0 F +( will be retur) 360.97 288.33 T +(ned to the caller) 415.12 288.33 T +(.) 485.77 288.33 T +2 F +(ad) 162 264.33 T +(d) 173.57 264.33 T +3 F +(int add \050int n) 261.29 264.33 T +(um, char **names\051;) 316.22 264.33 T +0 F +1.46 (This method will attempt to add) 261.29 247.33 P +3 F +1.46 (n) 411.2 247.33 P +1.46 (um) 416.65 247.33 P +0 F +1.46 ( de) 430.55 247.33 P +1.46 (vice names from the) 445.6 247.33 P +3 F +0.9 (names) 261.43 235.33 P +0 F +0.9 ( arr) 291.44 235.33 P +0.9 (a) 307.25 235.33 P +0.9 (y to the list using the) 312.51 235.33 P +3 F +0.9 (add \050char *name\051) 411.88 235.33 P +0 F +0.9 ( method of) 490.94 235.33 P +1.6 (the) 261.43 223.33 P +3 F +1.6 (cde) 279.71 223.33 P +1.6 (vCollection) 295.53 223.33 P +0 F +1.6 (. This method has the same proper) 344.43 223.33 P +1.6 (ties as) 509.5 223.33 P +(the) 261.43 211.33 T +3 F +(add \050int n) 278.11 211.33 T +(um, char * \336rstname) 319.7 211.33 T +(,...\051) 409.02 211.33 T +0 F +( method.) 423.47 211.33 T +2 F +(ad) 162 187.33 T +(d) 173.57 187.33 T +3 F +(int add \050char **names\051;) 261.29 187.33 T +0 F +1.72 (This method will attempt to add each de) 261.29 170.33 P +1.72 (vice name from the) 449.8 170.33 P +1.36 (NULL ter) 261.43 158.33 P +1.36 (minated) 303.05 158.33 P +3 F +1.36 (names) 342.76 158.33 P +0 F +1.36 ( arr) 372.77 158.33 P +1.36 (a) 389.03 158.33 P +1.36 (y to the list using the) 394.29 158.33 P +3 F +1.36 (add \050char) 496.4 158.33 P +2.34 (*name\051) 261.43 146.33 P +0 F +2.34 ( method of the) 293.66 146.33 P +3 F +2.34 (cde) 369.75 146.33 P +2.34 (vCollection) 385.57 146.33 P +0 F +2.34 (. This method has the) 434.47 146.33 P +3.15 (same proper) 261.43 134.33 P +3.15 (ties as the) 321.11 134.33 P +3 F +3.15 (add \050int n) 378.91 134.33 P +3.15 (um, char * \336rstname) 426.79 134.33 P +3.15 (,...\051) 525.55 134.33 P +0 F +(method.) 261.43 122.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "6" 16 +%%Page: "7" 17 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. The cde) 446.73 739 T +(vCollection Class) 488.99 739 T +0 10 Q +(7) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(ad) 180 713.33 T +(dReg) 191.57 713.33 T +(e) 216.67 713.33 T +(xp) 222.08 713.33 T +3 F +(int addRege) 279.29 713.33 T +(xp \050char *rege) 332.91 713.33 T +(xp\051;) 395.41 713.33 T +0 F +-0.03 (This method will quer) 279.29 696.33 P +-0.03 (y the system name ser) 373.98 696.33 P +-0.03 (v) 474.76 696.33 P +-0.03 (er f) 479.51 696.33 P +-0.03 (or the list of all) 493.64 696.33 P +1.89 (names in the) 279.43 684.33 P +3 F +1.89 (cde) 345.14 684.33 P +1.89 (vDirector) 360.95 684.33 P +1.89 (y) 401.26 684.33 P +0 F +1.89 ( that match the speci\336ed regular) 406.26 684.33 P +1.03 (e) 279.43 672.33 P +1.03 (xpression. the arr) 284.69 672.33 P +1.03 (a) 363.91 672.33 P +1.03 (y of names will be added to the list using) 369.17 672.33 P +0.48 (the) 279.43 660.33 P +3 F +0.48 (add \050int n) 296.59 660.33 P +0.48 (um, char ** names\051) 339.14 660.33 P +0 F +0.48 (method and the result of this) 429.42 660.33 P +(oper) 279.43 648.33 T +(ation will be retur) 299.34 648.33 T +(ned.) 375.17 648.33 T +2 F +(remo) 180 624.33 T +(ve) 204.25 624.33 T +3 F +(int remo) 279.29 624.33 T +(v) 315.26 624.33 T +(e \050char *name\051;) 320.01 624.33 T +0 F +0.43 (This method will remo) 279.29 607.33 P +0.43 (v) 377.67 607.33 P +0.43 (e the speci\336ed de) 382.42 607.33 P +0.43 (vice name from list of) 461.8 607.33 P +0.94 (de) 279.43 595.33 P +0.94 (vice names that is stored in the) 290.25 595.33 P +3 F +0.94 (cde) 437.48 595.33 P +0.94 (vCollection) 453.3 595.33 P +0 F +0.94 ( object. This) 502.2 595.33 P +(method has the f) 279.43 583.33 T +(ollo) 353.62 583.33 T +(wing proper) 369.03 583.33 T +(ties) 421.67 583.33 T +(.) 437.08 583.33 T +(\245) 279.29 559.33 T +0.09 (If a) 297.29 559.33 P +3 F +0.09 (cde) 314.14 559.33 P +0.09 (vCollectionRequest) 329.96 559.33 P +0 F +0.09 ( object has been instantiated f) 416.1 559.33 P +0.09 (or) 549.11 559.33 P +1.12 (this) 297.29 547.33 P +3 F +1.12 (cde) 316.75 547.33 P +1.12 (vCollection) 332.57 547.33 P +0 F +1.12 ( de) 381.47 547.33 P +1.12 (vice) 396.19 547.33 P +1.12 (, then the oper) 413.82 547.33 P +1.12 (ation will f) 481.58 547.33 P +1.12 (ail and) 527.42 547.33 P +2 F +(CDEV_INV) 297.29 535.33 T +(ALIDOP) 346.5 535.33 T +0 F +( will be retur) 384.28 535.33 T +(ned.) 438.43 535.33 T +(\245) 279.29 511.33 T +0.46 (If the name pro) 297.29 511.33 P +0.46 (vided is NULL or empty) 365.78 511.33 P +0.46 (, then the oper) 470.55 511.33 P +0.46 (ation) 536.32 511.33 P +(will f) 297.29 499.33 T +(ail and) 316.43 499.33 T +2 F +(CDEV_W) 348.67 499.33 T +(ARNING) 390.85 499.33 T +0 F +( will be retur) 430.29 499.33 T +(ned.) 484.44 499.33 T +(\245) 279.29 475.33 T +2.14 (If the name speci\336ed does not e) 297.29 475.33 P +2.14 (xist in the collection of) 451.6 475.33 P +1.29 (names) 297.29 463.33 P +1.29 (, then the oper) 327.15 463.33 P +1.29 (ation will f) 395.4 463.33 P +1.29 (ail and) 441.57 463.33 P +2 F +1.29 (CDEV_W) 476.38 463.33 P +1.29 (ARNING) 518.56 463.33 P +0 F +(will be retur) 297.29 451.33 T +(ned.) 348.66 451.33 T +(\245) 279.29 427.33 T +3.16 (If the name speci\336ed e) 297.29 427.33 P +3.16 (xists in the list, then it will be) 410.25 427.33 P +(remo) 297.29 415.33 T +(v) 319.92 415.33 T +(ed and) 324.67 415.33 T +2 F +(CDEV_SUCCESS) 358.03 415.33 T +0 F +( will be retur) 439.71 415.33 T +(ned.) 493.86 415.33 T +2 F +(remo) 180 391.33 T +(ve) 204.25 391.33 T +3 F +(int remo) 279.29 391.33 T +(v) 315.26 391.33 T +(e \050int n) 320.01 391.33 T +(um, char *name) 350.48 391.33 T +(,...\051;) 420.91 391.33 T +0 F +1.08 (This method will attempt to remo) 279.29 374.33 P +1.08 (v) 429.04 374.33 P +1.08 (e a list of n) 433.79 374.33 P +1.08 (um names from) 486.38 374.33 P +(the) 279.43 362.33 T +3 F +(cde) 296.11 362.33 T +(vCollection) 311.93 362.33 T +0 F +(. This method has the f) 360.83 362.33 T +(ollo) 462.25 362.33 T +(wing proper) 477.66 362.33 T +(ties) 530.3 362.33 T +(.) 545.71 362.33 T +(\245) 279.29 338.33 T +0.09 (If a) 297.29 338.33 P +3 F +0.09 (cde) 314.14 338.33 P +0.09 (vCollectionRequest) 329.96 338.33 P +0 F +0.09 ( object has been instantiated f) 416.1 338.33 P +0.09 (or) 549.11 338.33 P +1.12 (this) 297.29 326.33 P +3 F +1.12 (cde) 316.75 326.33 P +1.12 (vCollection) 332.57 326.33 P +0 F +1.12 ( de) 381.47 326.33 P +1.12 (vice) 396.19 326.33 P +1.12 (, then the oper) 413.82 326.33 P +1.12 (ation will f) 481.58 326.33 P +1.12 (ail and) 527.42 326.33 P +2 F +(CDEV_INV) 297.29 314.33 T +(ALIDOP) 346.5 314.33 T +0 F +( will be retur) 384.28 314.33 T +(ned.) 438.43 314.33 T +(\245) 279.29 290.33 T +0.89 (This method will call the) 297.29 290.33 P +3 F +0.89 (remo) 410.65 290.33 P +0.89 (v) 433.28 290.33 P +0.89 (e \050char *name\051) 438.03 290.33 P +0 F +0.89 (method f) 509.61 290.33 P +0.89 (or) 549.11 290.33 P +(each name that is speci\336ed.) 297.29 278.33 T +(\245) 279.29 254.33 T +2.16 (If the remo) 297.29 254.33 P +2.16 (v) 349.26 254.33 P +2.16 (e method f) 354.01 254.33 P +2.16 (ails to remo) 405.27 254.33 P +2.16 (v) 461.12 254.33 P +2.16 (e an) 465.87 254.33 P +2.16 (y of the de) 487.34 254.33 P +2.16 (vice) 540.22 254.33 P +1.89 (name str) 297.29 242.33 P +1.89 (ings from the list, then the error code that w) 338.23 242.33 P +1.89 (as) 547.44 242.33 P +2.74 (gener) 297.29 230.33 P +2.74 (ated b) 322.76 230.33 P +2.74 (y the call to) 353.1 230.33 P +3 F +2.74 (remo) 417.43 230.33 P +2.74 (v) 440.06 230.33 P +2.74 (e \050char * name\051) 444.81 230.33 P +0 F +2.74 ( will be) 521.95 230.33 P +(retur) 297.29 218.33 T +(ned.) 318.1 218.33 T +(\245) 279.29 194.33 T +0.52 (If an error occurs while remo) 297.29 194.33 P +0.52 (ving a name from the list, the) 426.46 194.33 P +-0.01 (method will contin) 297.29 182.33 P +-0.01 (ue with the ne) 376.63 182.33 P +-0.01 (xt name until the last name) 438.56 182.33 P +(is reached.) 297.29 170.33 T +(\245) 279.29 146.33 T +0.35 (If no errors occur while remo) 297.29 146.33 P +0.35 (ving names from the list, then) 425.61 146.33 P +2 F +(CDEV_SUCCESS) 297.29 134.33 T +0 F +( will be retur) 378.97 134.33 T +(ned to the caller) 433.12 134.33 T +(.) 503.77 134.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "7" 17 +%%Page: "8" 18 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. The cde) 54 739 T +(vCollection Class) 96.25 739 T +0 10 Q +(8) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(remo) 162 713.33 T +(ve) 186.25 713.33 T +3 F +(int remo) 261.29 713.33 T +(v) 297.26 713.33 T +(e \050int n) 302.01 713.33 T +(um, char **names\051;) 332.48 713.33 T +0 F +2.71 (This method will attempt to remo) 261.29 696.33 P +2.71 (v) 419.2 696.33 P +2.71 (e) 423.95 696.33 P +3 F +2.71 (n) 435 696.33 P +2.71 (um) 440.46 696.33 P +0 F +2.71 ( de) 454.35 696.33 P +2.71 (vice names as) 470.66 696.33 P +2.04 (speci\336ed in the) 261.43 684.33 P +3 F +2.04 (names) 337.02 684.33 P +0 F +2.04 ( arr) 367.04 684.33 P +2.04 (a) 383.97 684.33 P +2.04 (y from the list using the) 389.23 684.33 P +3 F +2.04 (remo) 507.06 684.33 P +2.04 (v) 529.69 684.33 P +2.04 (e) 534.44 684.33 P +1.23 (\050char *name\051) 261.43 672.33 P +0 F +1.23 ( method of the) 320.45 672.33 P +3 F +1.23 (cde) 392.1 672.33 P +1.23 (vCollection) 407.92 672.33 P +0 F +1.23 (. This method has) 456.82 672.33 P +1.15 (the same proper) 261.43 660.33 P +1.15 (ties as the) 336.94 660.33 P +3 F +1.15 (remo) 388.75 660.33 P +1.15 (v) 411.38 660.33 P +1.15 (e \050int n) 416.13 660.33 P +1.15 (um, char * name) 448.89 660.33 P +1.15 (,...\051) 525.55 660.33 P +0 F +(method.) 261.43 648.33 T +2 F +(remo) 162 624.33 T +(ve) 186.25 624.33 T +3 F +(int remo) 261.29 624.33 T +(v) 297.26 624.33 T +(e \050char **names\051;) 302.01 624.33 T +0 F +3.01 (This method will attempt to remo) 261.29 607.33 P +3.01 (v) 420.68 607.33 P +3.01 (e each de) 425.43 607.33 P +3.01 (vice name as) 475.07 607.33 P +2.32 (speci\336ed in the NULL ter) 261.43 595.33 P +2.32 (minated) 380.44 595.33 P +3 F +2.32 (names) 421.1 595.33 P +0 F +2.32 ( arr) 451.11 595.33 P +2.32 (a) 468.33 595.33 P +2.32 (y from the list) 473.59 595.33 P +0.94 (using the) 261.43 583.33 P +3 F +0.94 (remo) 306.66 583.33 P +0.94 (v) 329.29 583.33 P +0.94 (e \050char *name\051) 334.04 583.33 P +0 F +0.94 ( method of the) 402.05 583.33 P +3 F +0.94 (cde) 472.5 583.33 P +0.94 (vCollection) 488.32 583.33 P +0 F +0.94 (.) 537.22 583.33 P +0.58 (This method has the same proper) 261.43 571.33 P +0.58 (ties as the) 414.23 571.33 P +3 F +0.58 (remo) 464.32 571.33 P +0.58 (v) 486.95 571.33 P +0.58 (e \050int n) 491.7 571.33 P +0.58 (um,) 523.33 571.33 P +(char * name) 261.43 559.33 T +(,...\051) 315.19 559.33 T +0 F +( method.) 329.64 559.33 T +2 F +(remo) 162 518.33 T +(veReg) 186.25 518.33 T +(e) 216.36 518.33 T +(xp) 221.77 518.33 T +3 F +(int remo) 261.29 518.33 T +(v) 297.26 518.33 T +(eRege) 302.01 518.33 T +(xp \050char *rege) 331.17 518.33 T +(xp\051;) 393.67 518.33 T +0 F +-0.03 (This method will quer) 261.29 501.33 P +-0.03 (y the system name ser) 355.98 501.33 P +-0.03 (v) 456.76 501.33 P +-0.03 (er f) 461.51 501.33 P +-0.03 (or the list of all) 475.64 501.33 P +1.89 (names in the) 261.43 489.33 P +3 F +1.89 (cde) 327.14 489.33 P +1.89 (vDirector) 342.95 489.33 P +1.89 (y) 383.26 489.33 P +0 F +1.89 ( that match the speci\336ed regular) 388.26 489.33 P +1.57 (e) 261.43 477.33 P +1.57 (xpression. the arr) 266.69 477.33 P +1.57 (a) 346.98 477.33 P +1.57 (y of names will be remo) 352.24 477.33 P +1.57 (v) 464.96 477.33 P +1.57 (ed from the list) 469.71 477.33 P +1.95 (using the) 261.43 465.33 P +3 F +1.95 (remo) 308.69 465.33 P +1.95 (v) 331.32 465.33 P +1.95 (e \050int n) 336.07 465.33 P +1.95 (um, char ** names\051) 370.45 465.33 P +0 F +1.95 (method and the) 466.61 465.33 P +(result of this oper) 261.43 453.33 T +(ation will be retur) 338.03 453.33 T +(ned.) 413.86 453.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "8" 18 +%%Page: "9" 19 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. The cde) 413.22 739 T +(vCollectionRequest Class) 455.47 739 T +0 10 Q +(9) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(3.) 159.32 710.67 T +(The cde) 180 710.67 T +(vCollectionRequest Class) 232.7 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w of the) 108.64 673.33 T +(cde) 72 661.33 T +(vCollection) 89.08 661.33 T +(Request Class) 72 649.33 T +0 F +4.16 (The cde) 180 673.33 P +4.16 (vCollectionRequest class is an abstr) 219.99 673.33 P +4.16 (act base class from which other) 397.14 673.33 P +1.41 (cde) 180 661.33 P +1.41 (vCollectionRequest objects are der) 195.82 661.33 P +1.41 (iv) 355.26 661.33 P +1.41 (ed. It pro) 362.23 661.33 P +1.41 (vides a protected constr) 404.36 661.33 P +1.41 (uctor and) 514.9 661.33 P +-0.16 (destr) 180 649.33 P +-0.16 (uctor that are used to initializ) 202.38 649.33 P +-0.16 (e its inter) 328.7 649.33 P +-0.16 (nals) 369.19 649.33 P +-0.16 (, ho) 387.38 649.33 P +-0.16 (w) 403.75 649.33 P +-0.16 (e) 410.87 649.33 P +-0.16 (v) 416.13 649.33 P +-0.16 (er) 420.88 649.33 P +-0.16 (, the pr) 429.27 649.33 P +-0.16 (imar) 460.23 649.33 P +-0.16 (y mechanism that) 479.96 649.33 P +(is used to obtain a cde) 180 637.33 T +(vCollectionRequest object is the) 279.76 637.33 T +3 F +(attachPtr) 424.82 637.33 T +0 F +( method.) 464.84 637.33 T +3 9 Q +(Figure 3: Object Model of the cde) 180 621 T +(vCollectionRequest Class) 315.3 621 T +2 10 Q +(Pub) 72 455.76 T +(lic Methods of) 90.79 455.76 T +(the) 72 443.76 T +(cde) 72 431.76 T +(vCollection) 89.08 431.76 T +(Request Class) 72 419.76 T +(constructor) 180 455.76 T +3 F +(cde) 279.29 455.76 T +(vCollectionRequest\050) 295.11 455.76 T +(char **de) 395.86 455.76 T +(vices) 436.69 455.76 T +(, int nDe) 459.32 455.76 T +(vices) 496.26 455.76 T +(,) 518.89 455.76 T +(char * msg, cde) 395.86 443.76 T +(vSystem & system\051;) 465.03 443.76 T +0 F +1.08 (This is the constr) 279.29 426.76 P +1.08 (uctor f) 358.26 426.76 P +1.08 (or the cde) 386.83 426.76 P +1.08 (vCollectionRequest class) 433.17 426.76 P +1.08 (. It) 545.8 426.76 P +(has the f) 279.43 414.76 T +(ollo) 317.49 414.76 T +(wing proper) 332.9 414.76 T +(ties) 385.54 414.76 T +(.) 400.95 414.76 T +(\245) 279.29 396.76 T +0.1 (This method is) 297.29 396.76 P +5 F +0.1 (pr) 365.39 396.76 P +0.1 (otected) 375.19 396.76 P +0 F +0.1 ( to pre) 410.75 396.76 P +0.1 (v) 439 396.76 P +0.1 (ent the direct instantiation) 443.75 396.76 P +3.95 (of ne) 297.29 384.76 P +3.95 (w) 323.27 384.76 P +3 F +3.95 (cde) 337.22 384.76 P +3.95 (vCollectionRequests) 353.04 384.76 P +0 F +3.95 (. Ne) 444.03 384.76 P +3.95 (w instances of the) 466.12 384.76 P +3 F +2.4 (cde) 297.29 372.76 P +2.4 (vCollectionRequest objects are) 313.11 372.76 P +0 F +2.4 (created b) 460.93 372.76 P +2.4 (y using the) 504.83 372.76 P +3 F +1.63 (attachPtr) 297.29 360.76 P +0 F +1.63 ( or) 337.31 360.76 P +3 F +1.63 (attachRef) 355.02 360.76 P +0 F +1.63 ( method of the) 397.82 360.76 P +3 F +1.63 (cde) 471.04 360.76 P +1.63 (vRequestObject) 486.86 360.76 P +0 F +0.62 (class which will call the local) 297.29 348.76 P +3 F +0.62 (attachPtr) 429.35 348.76 P +0 F +0.62 ( method to create a) 469.37 348.76 P +(ne) 297.29 336.76 T +(w object if necessar) 308.21 336.76 T +(y) 396.32 336.76 T +(.) 400.32 336.76 T +(\245) 279.29 318.76 T +0.74 (The constr) 297.29 318.76 P +0.74 (uctor is called b) 345.42 318.76 P +0.74 (y the cde) 416.92 318.76 P +0.74 (vCollection object and) 458.69 318.76 P +2.22 (is pro) 297.29 306.76 P +2.22 (vided with a list and count of de) 323.8 306.76 P +2.22 (vices that will be) 478.55 306.76 P +0.06 (included in the collection and the message that will be sent) 297.29 294.76 P +(to them.) 297.29 282.76 T +(\245) 279.29 264.76 T +6.39 (The) 297.29 264.76 P +3 F +6.39 (cde) 323.68 264.76 P +6.39 (vSystem) 339.5 264.76 P +0 F +6.39 ( ref) 377.84 264.76 P +6.39 (erence that is pro) 398.38 264.76 P +6.39 (vided is the) 494.65 264.76 P +3 F +1.7 (cde) 297.29 252.76 P +1.7 (vSystem) 313.11 252.76 P +0 F +1.7 ( instance that will be used to) 351.45 252.76 P +3 F +1.7 (poll) 491.77 252.76 P +0 F +1.7 (,) 507.33 252.76 P +3 F +1.7 (pend) 514.6 252.76 P +0 F +1.7 ( and) 536.84 252.76 P +3 F +(\337ush) 297.29 240.76 T +0 F +( the) 318.41 240.76 T +3 F +(cde) 337.87 240.76 T +(vCollectionRequest) 353.69 240.76 T +0 F +( object.) 439.83 240.76 T +2 F +(destructor) 180 216.76 T +3 F +(vir) 279.29 216.76 T +(tual ~cde) 290.24 216.76 T +(vCollectionRequest \050v) 330.8 216.76 T +(oid\051;) 427.8 216.76 T +0 F +-0.11 (This is the destr) 279.29 199.76 P +-0.11 (uctor f) 349.7 199.76 P +-0.11 (or a cde) 377.08 199.76 P +-0.11 (vCollectionRequest object. It has) 412.7 199.76 P +(the f) 279.43 187.76 T +(ollo) 298.59 187.76 T +(wing proper) 314 187.76 T +(ties) 366.64 187.76 T +(.) 382.05 187.76 T +(\245) 279.29 163.76 T +14.64 (This method is protected to pre) 297.29 163.76 P +14.64 (v) 508.03 163.76 P +14.64 (ent the) 512.78 163.76 P +3 F +0.54 (cde) 297.29 151.76 P +0.54 (vCollectionRequest) 313.11 151.76 P +0 F +0.54 ( object from being destro) 399.25 151.76 P +0.54 (y) 511.17 151.76 P +0.54 (ed b) 515.97 151.76 P +0.54 (y the) 535.78 151.76 P +3.29 (application. This method should only be called b) 297.29 139.76 P +3.29 (y the) 533.03 139.76 P +3 F +(cde) 297.29 127.76 T +(vSystem) 313.11 127.76 T +0 F +( object when the application is ter) 351.45 127.76 T +(minating.) 499.55 127.76 T +(\245) 279.29 103.76 T +-0.07 (Because the) 297.29 103.76 P +3 F +-0.07 (cde) 355.51 103.76 P +-0.07 (vCollectionRequest) 371.33 103.76 P +0 F +-0.07 ( object will nor) 457.47 103.76 P +-0.07 (mally be) 520.84 103.76 P +0.79 (ref) 297.29 91.76 P +0.79 (erred to as a) 308.66 91.76 P +3 F +0.79 (cde) 370.72 91.76 P +0.79 (vRequestObject) 386.54 91.76 P +0 F +0.79 ( object, this destr) 457.68 91.76 P +0.79 (uctor) 535.77 91.76 P +180 481.43 558 680 C +180 481.43 558 618 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +187.43 485.86 551 614.43 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +187.14 601.14 550.72 601.14 2 L +N +4 9 Q +(cdevCollectionRequest) 312.95 605.62 T +6 F +(attributes) 190.71 594.62 T +4 F +(:) 244.71 594.62 T +(RESULT_CODE_TAG: int) 207 583.62 T +6 F +(methods) 190.71 561.62 T +4 F +(:) 228.51 561.62 T +(cdevCollectionRequest \050char **, int, char *, cdevSystem &\051) 207 550.62 T +(~cdevCollectionRequest \050void\051 :{virtual}) 207 539.62 T +-0.71 (attachPtr \050...\051 :{static} cdevCollectionRequest *) 207 517.62 P +(className \050void\051 :{virtual} char *) 207 506.62 T +(resultCodeTag \050void\051 :{virtual} int) 207 495.62 T +180 481.43 558 618 R +1 H +0 Z +N +180 481.43 558 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "9" 19 +%%Page: "10" 20 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. The cde) 54 739 T +(vCollectionRequest Class) 96.25 739 T +0 10 Q +(10) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +2.29 (is vir) 279.29 713.33 P +2.29 (tual to ensure that the) 302.53 713.33 P +5 F +2.29 (\324most senior\325) 413.5 713.33 P +0 F +2.29 ( destr) 478.03 713.33 P +2.29 (uctor is) 505.48 713.33 P +(called \336rst.) 279.29 701.33 T +2 F +(attac) 162 677.33 T +(hPtr) 185.24 677.33 T +3 F +(cde) 261.29 677.33 T +(vCollectionRequest * attachPtr) 277.11 677.33 T +(\050) 281.29 665.33 T +(cde) 284.62 665.33 T +(vCollection &col, char *msg, cde) 300.44 665.33 T +(vSystem &sys\051;) 443.52 665.33 T +0 F +1.3 (This method is used b) 261.29 648.33 P +1.3 (y the cde) 364.1 648.33 P +1.3 (vCollection object to obtain a) 406.97 648.33 P +(ne) 261.43 636.33 T +(w cde) 272.35 636.33 T +(vCollectionRequest object.) 298.17 636.33 T +(\245) 261.29 612.33 T +1.23 (This method will obtain a cop) 279.29 612.33 P +1.23 (y of the de) 414.09 612.33 P +1.23 (vice names from) 464.18 612.33 P +2.12 (the cde) 279.29 600.33 P +2.12 (vCollection object and will poll the cde) 313.9 600.33 P +2.12 (vDirector) 494.7 600.33 P +2.12 (y) 535 600.33 P +5.22 (object to deter) 279.29 588.33 P +5.22 (mine which ser) 353.34 588.33 P +5.22 (vice each of them is) 430.76 588.33 P +(associated with.) 279.29 576.33 T +(\245) 261.29 552.33 T +0.32 (If the de) 279.29 552.33 P +0.32 (vices are all from a single ser) 315.77 552.33 P +0.32 (vice) 447.49 552.33 P +0.32 (, this method will) 465.12 552.33 P +(retur) 279.29 540.33 T +(n a ser) 300.1 540.33 T +(vice speci\336c collection request object.) 330.97 540.33 T +(\245) 261.29 516.33 T +-0.27 (If the de) 279.29 516.33 P +-0.27 (vices are from a v) 314.58 516.33 P +-0.27 (ar) 392.14 516.33 P +-0.27 (iety of ser) 401.18 516.33 P +-0.27 (vices) 444.28 516.33 P +-0.27 (, this method will) 466.91 516.33 P +5.63 (retur) 279.29 504.33 P +5.63 (n a cde) 300.1 504.33 P +5.63 (vGr) 343.85 504.33 P +5.63 (pCollectionRequest that contains the) 360.26 504.33 P +(ser) 279.29 492.33 T +(vice speci\336c collection request objects) 293.48 492.33 T +(.) 462.28 492.33 T +(\245) 261.29 468.33 T +0.15 (De) 279.29 468.33 P +0.15 (vice/message combinations that are not associated with) 291.77 468.33 P +(a ser) 279.29 456.33 T +(vice will be ignored.) 301.82 456.33 T +(\245) 261.29 432.33 T +4.73 (If none of the de) 279.29 432.33 P +4.73 (vice/message combinations can be) 370.19 432.33 P +1.41 (associated with a ser) 279.29 420.33 P +1.41 (vice) 377.19 420.33 P +1.41 (, then an error message will be) 394.82 420.33 P +(gener) 279.29 408.33 T +(ated and NULL will be retur) 304.76 408.33 T +(ned.) 426.17 408.33 T +2 F +(c) 162 384.33 T +(lassName) 167.36 384.33 T +3 F +(char * className \050v) 261.29 384.33 T +(oid\051;) 350.5 384.33 T +0 F +12.7 (This method retur) 261.29 367.33 P +12.7 (ns the name of the class;) 365.31 367.33 P +2.96 (\322) 261.43 355.33 P +3 F +2.96 (cde) 264.76 355.33 P +2.96 (vCollectionRequest) 280.58 355.33 P +0 F +2.96 (\323. If the de) 366.72 355.33 P +2.96 (v) 420.33 355.33 P +2.96 (eloper inher) 425.08 355.33 P +2.96 (its a ser) 480.99 355.33 P +2.96 (vice) 522.22 355.33 P +-0.26 (speci\336c cde) 261.43 343.33 P +-0.26 (vCollectionRequest, then this method should not be) 313.11 343.33 P +(altered or o) 261.43 331.33 T +(v) 311.86 331.33 T +(err) 316.61 331.33 T +(idden.) 328.98 331.33 T +2 F +(resultCodeT) 162 307.33 T +(a) 219.54 307.33 T +(g) 225 307.33 T +3 F +(int resultCodetag \050v) 261.29 307.33 T +(oid\051;) 347.74 307.33 T +0 F +2.16 (This method retur) 261.29 290.33 P +2.16 (ns the integer tag that should be used to) 344.23 290.33 P +0.3 (inser) 261.43 278.33 P +0.3 (t the result code that w) 283.5 278.33 P +0.3 (as geneter) 385.47 278.33 P +0.3 (ated when the message) 432.92 278.33 P +(w) 261.43 266.33 T +(as sent to the actual de) 268.5 266.33 T +(vice) 371.6 266.33 T +(.) 389.23 266.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "10" 20 +%%Page: "11" 21 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. The cde) 467.23 739 T +(vData Class) 509.49 739 T +0 10 Q +(11) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(4.) 159.32 710.67 T +(The cde) 180 710.67 T +(vData Class) 232.7 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w of the) 108.64 673.33 T +(cde) 72 661.33 T +(vData Class) 89.08 661.33 T +0 F +( The cde) 180 673.33 T +(vData C++ class is a self descr) 218.61 673.33 T +(ibing data object. This class is the pr) 356.03 673.33 T +(imar) 517.36 673.33 T +(y) 537.1 673.33 T +(mechanism f) 180 661.33 T +(or data interchange within the cde) 236.38 661.33 T +(v system. The cde) 386.16 661.33 T +(vData object is) 467 661.33 T +(capab) 180 649.33 T +(le of stor) 207.04 649.33 T +(ing and retr) 245.54 649.33 T +(ie) 296.27 649.33 T +(ving data items of all the pr) 303.75 649.33 T +(imitiv) 423.4 649.33 T +(e data types) 445.92 649.33 T +(, as w) 500.25 649.33 T +(ell as) 526.27 649.33 T +(char) 180 637.33 T +(acter str) 199.35 637.33 T +(ings and time stamps) 235.62 637.33 T +(. These data items ma) 329.95 637.33 T +(y be scalar or m) 428.58 637.33 T +(ulti-) 499.61 637.33 T +(dimensional arr) 180 625.33 T +(a) 248.25 625.33 T +(ys) 253.51 625.33 T +(.) 263.36 625.33 T +3 9 Q +(Figure 4: Object model of the cde) 180 609 T +(vData class) 315.3 609 T +2 10 Q +(Pub) 72 153.33 T +(lic Methods of) 90.79 153.33 T +(the cde) 72 141.33 T +(vData) 106.86 141.33 T +(Class) 72 129.33 T +(ta) 180 153.33 T +(gC2I) 188.79 153.33 T +3 F +(static int tagC2I \050char *ctag, int *tag\051;) 279.29 153.33 T +0 F +2.68 (Con) 279.29 136.33 P +2.68 (v) 297.43 136.33 P +2.68 (er) 302.18 136.33 P +2.68 (ts a char) 311.47 136.33 P +2.68 (acter str) 355.08 136.33 P +2.68 (ing tag name to its unique integer) 394.04 136.33 P +6.27 (identi\336er) 279.43 124.33 P +6.27 (. The function retur) 316.72 124.33 P +6.27 (ns CDEV_SUCCESS if the) 419.71 124.33 P +14.1 (con) 279.43 112.33 P +14.1 (v) 295.35 112.33 P +14.1 (ersion w) 300.1 112.33 P +14.1 (as successful, otherwise it retur) 351.29 112.33 P +14.1 (ns) 547.44 112.33 P +(CDEV_ERR) 279.43 100.33 T +(OR.) 333.68 100.33 T +180 179 558 680 C +180 179 558 606 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +179.21 179 558.79 606 R +7 X +0 0 0 1 0 0 0 K +V +185.45 181.83 557.12 598.5 R +0 X +V +0.5 H +2 Z +N +181.62 186.33 553.29 602.33 R +7 X +V +0 X +N +187.79 192 546.79 583.58 R +7 X +V +0 X +N +192.95 197.02 543.79 579.92 R +7 X +V +4 9 Q +0 X +(class cdevData) 330.57 573.92 T +6 F +(methods:) 192.95 562.92 T +4 F +(tagC2I \050char *, int *\051 :int) 207.12 551.92 T +(tagI2C \050int, char * &\051 :int) 207.12 540.92 T +(insertTag \050int, char *\051 :void) 207.12 529.92 T +(addTagCallback \050cdevTagTableCallback*\051 :void) 207.12 518.92 T +(delTagCallback \050cdevTagTableCallback*\051 :void) 207.12 507.92 T +(readTagTable \050int *&,char **&,int &\051 :int) 207.12 496.92 T +(operator == \050cdevData & data\051 :int) 207.12 485.92 T +(operator != \050cdevData & data\051 :int) 207.12 474.92 T +(operator = \050cdevData &\051 :cdevData &) 207.12 463.92 T +(operator char \050void\051 :char) 207.12 452.92 T +(operator short \050void\051 :short) 207.12 441.92 T +-0.39 (operator unsigned short \050void\051 :unsigned short) 207.12 430.92 P +(operator int \050void\051 :int) 207.12 419.92 T +(operator unsigned int \050void\051 :unsigned int) 207.12 408.92 T +(operator long \050void\051 :long) 207.12 397.92 T +-0.15 (operator unsigned long \050void\051 :unsigned long) 207.12 386.92 P +(operator float \050void\051 :float) 207.12 375.92 T +(operator double \050void\051 :double) 207.12 364.92 T +(asciiDump \050FILE *\051 :void) 207.12 353.92 T +(xdrSize \050size_t *, size_t *\051 :int) 207.12 342.92 T +(xdrExport \050char **, size_t *\051 :int) 207.12 331.92 T +(xdrExport \050char *, size_t, size_t\051:int) 207.12 320.92 T +(xdrImport \050char *, size_t\051 :int) 207.12 309.92 T +(remove \050...\051 :void) 207.12 298.92 T +(changeTag \050...\051 :int) 207.12 287.92 T +-0.1 (getType \050...\051 :cdevDataTypes) 207.12 276.92 P +(getDim \050...\051 :int) 207.12 265.92 T +(getElems \050...\051 :int) 207.12 254.92 T +(getBounds \050...\051 :int) 207.12 243.92 T +(setBounds \050...\051 :int) 207.12 232.92 T +(insert \050...\051 :int) 207.12 221.92 T +(get \050...\051 :int) 207.12 210.92 T +(find \050...\051 :int) 207.12 199.92 T +187.95 568.92 547.12 568.92 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +180 179 558 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "11" 21 +%%Page: "12" 22 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. The cde) 54 739 T +(vData Class) 96.25 739 T +0 10 Q +(12) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(ta) 162 713.33 T +(gI2C) 170.79 713.33 T +3 F +(static int tagI2C \050int tag, char * &ctag\051;) 261.29 713.33 T +0 F +1.04 (Con) 261.29 696.33 P +1.04 (v) 279.43 696.33 P +1.04 (er) 284.18 696.33 P +1.04 (ts a unique integer tag n) 293.47 696.33 P +1.04 (umber to its related char) 405.88 696.33 P +1.04 (acter) 517.77 696.33 P +4.8 (str) 261.43 684.33 P +4.8 (ing tag. The function retur) 272.69 684.33 P +4.8 (ns CDEV_SUCCESS if the) 406.11 684.33 P +14.1 (con) 261.43 672.33 P +14.1 (v) 277.35 672.33 P +14.1 (ersion w) 282.1 672.33 P +14.1 (as successful, otherwise it retur) 333.29 672.33 P +14.1 (ns) 529.44 672.33 P +(CDEV_ERR) 261.43 660.33 T +(OR.) 315.68 660.33 T +2 F +(inser) 162 636.33 T +(tT) 186.1 636.33 T +(a) 194.74 636.33 T +(g) 200.2 636.33 T +3 F +(static v) 261.29 636.33 T +(oid inser) 292.16 636.33 T +(tT) 330.35 636.33 T +(ag\050int tag, char *ctag\051;) 338.04 636.33 T +0 F +-0.21 (Adds a ne) 261.29 619.33 P +-0.21 (w) 305.7 619.33 P +-0.21 (, unique tag identi\336er to the static tab) 312.32 619.33 P +-0.21 (le of tags) 474.07 619.33 P +-0.21 (. Both) 514.08 619.33 P +3.67 (the tag integer and the char) 261.43 607.33 P +3.67 (acter str) 402.01 607.33 P +3.67 (ing m) 441.95 607.33 P +3.67 (ust be unique) 469.98 607.33 P +3.67 (.) 537.22 607.33 P +0.97 (Retur) 261.43 595.33 P +0.97 (ns CDEV_SUCCESS on success) 286.13 595.33 P +0.97 (, or CDEV_ERR) 436.71 595.33 P +0.97 (OR on) 510.13 595.33 P +(f) 261.43 583.33 T +(ailure) 263.91 583.33 T +(.) 288.21 583.33 T +2 F +(ad) 162 559.33 T +(dT) 173.57 559.33 T +(a) 184.99 559.33 T +(gCallbac) 190.45 559.33 T +(k) 231.93 559.33 T +3 F +(static v) 261.29 559.33 T +(oid addT) 292.16 559.33 T +(agCallbac) 329.87 559.33 T +(k\050cde) 374.13 559.33 T +(vT) 398.28 559.33 T +(agT) 408.19 559.33 T +(ab) 424.22 559.33 T +(leCallbac) 435.14 559.33 T +(k * cb\051;) 476.06 559.33 T +0 F +0 (This method is used to install a cde) 261.29 542.33 P +0 (vT) 417.19 542.33 P +0 (agT) 427.1 542.33 P +0 (ab) 443.13 542.33 P +0 (leCallbac) 454.05 542.33 P +0 (k object in) 494.97 542.33 P +1.02 (the global tag tab) 261.43 530.33 P +1.02 (le that will be called each time a ne) 341.02 530.33 P +1.02 (w tag is) 504.06 530.33 P +0.3 (inser) 261.43 518.33 P +0.3 (ted into the global tag tab) 283.5 518.33 P +0.3 (le) 397.11 518.33 P +0.3 (. This method ma) 404.74 518.33 P +0.3 (y be used b) 482.6 518.33 P +0.3 (y) 535 518.33 P +1.36 (ser) 261.43 506.33 P +1.36 (vice de) 275.62 506.33 P +1.36 (v) 308.36 506.33 P +1.36 (elopers to detect when ne) 313.11 506.33 P +1.36 (w tags are created and) 432.85 506.33 P +4.33 (update the corresponding tag mapping tab) 261.43 494.33 P +4.33 (les on remote) 470.76 494.33 P +(ser) 261.43 482.33 T +(v) 275.62 482.33 T +(ers) 280.37 482.33 T +(.) 294.11 482.33 T +4.73 (The) 261.29 465.33 P +3 F +4.73 (cde) 286.03 465.33 P +4.73 (vT) 301.85 465.33 P +4.73 (agT) 311.76 465.33 P +4.73 (ab) 327.79 465.33 P +4.73 (leCallbac) 338.71 465.33 P +4.73 (k) 379.63 465.33 P +0 F +4.73 ( class contains a user de\336ned) 384.63 465.33 P +3 F +2.24 (callbac) 261.43 453.33 P +2.24 (k) 292.35 453.33 P +0 F +2.24 ( method that tak) 297.35 453.33 P +2.24 (es as its par) 375.6 453.33 P +2.24 (ameters the ne) 436.14 453.33 P +2.24 (w tag\325) 507.13 453.33 P +2.24 (s) 535 453.33 P +(integer identi\336er and its str) 261.43 441.33 T +(ing equiv) 378.85 441.33 T +(alent.) 418.62 441.33 T +2 F +(delT) 162 417.33 T +(a) 181.76 417.33 T +(gCallbac) 187.22 417.33 T +(k) 228.7 417.33 T +3 F +(static v) 261.29 417.33 T +(oid delT) 292.16 417.33 T +(agCallbac) 326.53 417.33 T +(k\050cde) 370.79 417.33 T +(vT) 394.94 417.33 T +(agT) 404.85 417.33 T +(ab) 420.88 417.33 T +(leCallbac) 431.8 417.33 T +(k * cb\051;) 472.72 417.33 T +0 F +2.05 (This method remo) 261.29 400.33 P +2.05 (v) 345.83 400.33 P +2.05 (es the speci\336ed callbac) 350.58 400.33 P +2.05 (k object from the) 459.92 400.33 P +2.61 (global tag tab) 261.43 388.33 P +2.61 (le) 326.48 388.33 P +2.61 (. The callbac) 334.11 388.33 P +2.61 (k should ha) 395.82 388.33 P +2.61 (v) 451.97 388.33 P +2.61 (e been pre) 456.72 388.33 P +2.61 (viously) 509.44 388.33 P +(installed using the addT) 261.43 376.33 T +(agCallbac) 365.84 376.33 T +(k method.) 410.1 376.33 T +2 F +(readT) 162 352.33 T +(a) 188.43 352.33 T +(gT) 193.89 352.33 T +(ab) 205.31 352.33 T +(le) 216.88 352.33 T +3 F +(static int readT) 261.29 352.33 T +(agT) 325.67 352.33 T +(ab) 341.7 352.33 T +(le\050int *&tag, char **&ctag, int &ntag\051;) 352.62 352.33 T +0 F +0.97 (This method will read the complete contents of the global tag) 261.29 335.33 P +-0.19 (tab) 261.43 323.33 P +-0.19 (le and use the data to populate the caller pro) 275.13 323.33 P +-0.19 (vided v) 471.17 323.33 P +-0.19 (ar) 502.41 323.33 P +-0.19 (iab) 511.45 323.33 P +-0.19 (les) 524.59 323.33 P +-0.19 (.) 537.22 323.33 P +-0.15 (The) 261.43 311.33 P +3 F +-0.15 (ntags) 281.29 311.33 P +0 F +-0.15 ( par) 305.75 311.33 P +-0.15 (ameter will be set to the n) 322.73 311.33 P +-0.15 (umber of tags that w) 435.66 311.33 P +-0.15 (ere) 525.55 311.33 P +(f) 261.43 299.33 T +(ound in the global tag tab) 263.91 299.33 T +(le) 376.01 299.33 T +(.) 383.64 299.33 T +0.09 (The) 261.29 282.33 P +3 F +0.09 (tag) 281.39 282.33 P +0 F +0.09 ( arr) 295.29 282.33 P +0.09 (a) 310.28 282.33 P +0.09 (y and the) 315.54 282.33 P +3 F +0.09 (ctag) 359.74 282.33 P +0 F +0.09 ( arr) 378.64 282.33 P +0.09 (a) 393.63 282.33 P +0.09 (y will both be allocated to a siz) 398.89 282.33 P +0.09 (e) 534.44 282.33 P +2.43 (suf\336cient to hold the resultant data. The) 261.43 270.33 P +3 F +2.43 (tag) 456.33 270.33 P +0 F +2.43 ( par) 470.23 270.33 P +2.43 (ameter will) 489.79 270.33 P +-0.24 (contain the list of integer tags and the) 261.43 258.33 P +3 F +-0.24 (ctag) 428.53 258.33 P +0 F +-0.24 ( arr) 447.43 258.33 P +-0.24 (a) 462.09 258.33 P +-0.24 (y will contain the) 467.35 258.33 P +(list of corresponding char) 261.43 246.33 T +(acter str) 373.04 246.33 T +(ings) 409.31 246.33 T +(.) 427.5 246.33 T +1.51 (The caller will be responsib) 261.29 229.33 P +1.51 (le f) 387.7 229.33 P +1.51 (or deleting the arr) 402.25 229.33 P +1.51 (a) 485.04 229.33 P +1.51 (ys that are) 490.3 229.33 P +3.18 (retur) 261.43 217.33 P +3.18 (ned b) 282.24 217.33 P +3.18 (y this method. Because the) 310.24 217.33 P +3 F +3.18 (ctag) 449.55 217.33 P +0 F +3.18 ( arr) 468.45 217.33 P +3.18 (a) 486.54 217.33 P +3.18 (y contains) 491.8 217.33 P +-0.23 (pointers to the actual str) 261.43 205.33 P +-0.23 (ings from the global tag tab) 367.4 205.33 P +-0.23 (le) 486.69 205.33 P +-0.23 (, the caller) 494.32 205.33 P +(should delete the arr) 261.43 193.33 T +(a) 352.49 193.33 T +(y only \050not the individual elements\051.) 357.75 193.33 T +2 F +(Operator =) 162 169.33 T +3 F +(cde) 261.29 169.33 T +(vData & oper) 277.11 169.33 T +(ator = \050cde) 335.37 169.33 T +(vData & data\051;) 383.15 169.33 T +0 F +1.37 (This is the assignment oper) 261.29 152.33 P +1.37 (ator f) 388.92 152.33 P +1.37 (or the class) 412.77 152.33 P +1.37 (. It will cop) 466.48 152.33 P +1.37 (y the) 516.96 152.33 P +0.7 (e) 261.43 140.33 P +0.7 (xact contents of the cde) 266.69 140.33 P +0.7 (vData object speci\336ed b) 374.81 140.33 P +0.7 (y data to the) 482.86 140.33 P +(current cde) 261.43 128.33 T +(vData object.) 311.15 128.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "12" 22 +%%Page: "13" 23 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. The cde) 467.23 739 T +(vData Class) 509.49 739 T +0 10 Q +(13) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Cast operator) 180 713.33 T +(s) 244.86 713.33 T +3 F +(oper) 279.29 713.33 T +(ator char \050v) 299.2 713.33 T +(oid\051;) 349.52 713.33 T +(oper) 279.29 701.33 T +(ator shor) 299.2 701.33 T +(t \050v) 339.06 701.33 T +(oid\051;) 352.7 701.33 T +(oper) 279.29 689.33 T +(ator unsigned shor) 299.2 689.33 T +(t \050v) 382.42 689.33 T +(oid\051;) 396.06 689.33 T +(oper) 279.29 677.33 T +(ator int \050v) 299.2 677.33 T +(oid\051;) 340.63 677.33 T +(oper) 279.29 665.33 T +(ator unsigned int \050v) 299.2 665.33 T +(oid\051;) 383.99 665.33 T +(oper) 279.29 653.33 T +(ator long \050v) 299.2 653.33 T +(oid\051;) 348.97 653.33 T +(oper) 279.29 641.33 T +(ator unsigned long \050v) 299.2 641.33 T +(oid\051;) 392.33 641.33 T +(oper) 279.29 629.33 T +(ator \337oat \050v) 299.2 629.33 T +(oid\051;) 348.97 629.33 T +(oper) 279.29 617.33 T +(ator doub) 299.2 617.33 T +(le \050v) 341.25 617.33 T +(oid\051;) 359.89 617.33 T +(oper) 279.29 605.33 T +(ator char* \050v) 299.2 605.33 T +(oid\051;) 353.41 605.33 T +0 F +0.11 (Directly e) 279.29 588.33 P +0.11 (xtr) 320.76 588.33 P +0.11 (acts a scalar v) 331.77 588.33 P +0.11 (alue that is stored in the \322v) 395.75 588.33 P +0.11 (alue\323 data) 513.42 588.33 P +-0.2 (item, and retur) 279.43 576.33 P +-0.2 (ns it as the v) 343.76 576.33 P +-0.2 (alue of the current cde) 398.85 576.33 P +-0.2 (vData object.) 497.26 576.33 P +2 F +(Operator ==) 180 552.33 T +3 F +(int oper) 279.29 552.33 T +(ator == \050cde) 312.54 552.33 T +(vData & data\051;) 366.16 552.33 T +0 F +3.03 (This oper) 279.29 535.33 P +3.03 (ator will do a deep compar) 323.9 535.33 P +3.03 (ison of tw) 456.48 535.33 P +3.03 (o cde) 504.69 535.33 P +3.03 (vData) 531.88 535.33 P +1.54 (objects) 279.43 523.33 P +1.54 (, including a compar) 310.96 523.33 P +1.54 (ison of the individual elements of) 405.22 523.33 P +2.28 (arr) 279.43 511.33 P +2.28 (a) 291.55 511.33 P +2.28 (y data. The order in which the tagged data items w) 296.81 511.33 P +2.28 (ere) 543.55 511.33 P +(inser) 279.43 499.33 T +(ted into either object is unimpor) 301.5 499.33 T +(tant.) 440.85 499.33 T +2 F +(Operator !=) 180 475.33 T +3 F +(int oper) 279.29 475.33 T +(ator != \050cde) 312.54 475.33 T +(vData & data\051;) 363.1 475.33 T +0 F +3.03 (This oper) 279.29 458.33 P +3.03 (ator will do a deep compar) 323.9 458.33 P +3.03 (ison of tw) 456.48 458.33 P +3.03 (o cde) 504.69 458.33 P +3.03 (vData) 531.88 458.33 P +(objects) 279.43 446.33 T +(, including a compar) 310.96 446.33 T +(ison of the individual elements of) 400.59 446.33 T +2.28 (arr) 279.43 434.33 P +2.28 (a) 291.55 434.33 P +2.28 (y data. The order in which the tagged data items w) 296.81 434.33 P +2.28 (ere) 543.55 434.33 P +(inser) 279.43 422.33 T +(ted into either object is unimpor) 301.5 422.33 T +(tant.) 440.85 422.33 T +2 F +(asciiDump) 180 398.33 T +3 F +(v) 279.29 398.33 T +(oid asciiDump \050FILE * fp\051;) 284.04 398.33 T +0 F +0.34 (Outputs the complete contents of the cde) 279.29 381.33 P +0.34 (vData object to a \336le) 463.39 381.33 P +0.34 (.) 555.22 381.33 P +(If no \336le pointer is speci\336ed, then stdout will be used.) 279.43 369.33 T +2 F +(xdrSiz) 180 345.33 T +(e) 210.11 345.33 T +3 F +(int xdrSiz) 279.29 345.33 T +(e \050siz) 320.26 345.33 T +(e_t * b) 344 345.33 T +(ufLen, siz) 372.71 345.33 T +(e_t * elementCount\051;) 415.36 345.33 T +0 F +-0.1 (Calculates the siz) 279.29 328.33 P +-0.1 (e of the b) 357.29 328.33 P +-0.1 (uff) 398.48 328.33 P +-0.1 (er \050) 409.3 328.33 P +3 F +-0.1 (b) 424.2 328.33 P +-0.1 (ufLen) 429.56 328.33 P +0 F +-0.1 (\051 that will be required to) 454.58 328.33 P +1.43 (store this cde) 279.43 316.33 P +1.43 (vData object as represented b) 341.45 316.33 P +1.43 (y XDR. The total) 480.36 316.33 P +0.35 (n) 279.43 304.33 P +0.35 (umber of data items \050) 284.89 304.33 P +3 F +0.35 (elementCount) 380.79 304.33 P +0 F +0.35 (\051 that will be placed in the) 443.04 304.33 P +0.03 (b) 279.43 292.33 P +0.03 (uff) 284.79 292.33 P +0.03 (er is also calculated. The v) 295.61 292.33 P +0.03 (alues obtained from this function) 413.91 292.33 P +0.46 (ma) 279.43 280.33 P +0.46 (y be passed to the) 293.02 280.33 P +3 F +0.46 (xdrExpor) 379.84 280.33 P +0.46 (t) 420.25 280.33 P +0 F +0.46 ( method in order to use a pre-) 423.03 280.33 P +(allocated data b) 279.43 268.33 T +(uff) 349.83 268.33 T +(er) 360.65 268.33 T +(.) 369.04 268.33 T +2 F +(xdrExpor) 180 244.33 T +(t) 224.1 244.33 T +3 F +(int xdrExpor) 279.29 244.33 T +(t \050char ** b) 333.04 244.33 T +(uf) 380.08 244.33 T +(, siz) 388.12 244.33 T +(e_t * b) 405.75 244.33 T +(ufLen\051;) 434.46 244.33 T +0 F +3.17 (Allocates a b) 279.29 227.33 P +3.17 (uff) 342.67 227.33 P +3.17 (er \050) 353.49 227.33 P +3 F +3.17 (b) 371.66 227.33 P +3.17 (uf) 377.02 227.33 P +0 F +3.17 (\051 of suf\336cient siz) 385.36 227.33 P +3.17 (e to hold the XDR) 466.4 227.33 P +0.8 (representation of this cde) 279.43 215.33 P +0.8 (vData object. It will then tr) 393.8 215.33 P +0.8 (anslate all) 512.18 215.33 P +-0.23 (data items stored within the object to XDR and wr) 279.43 203.33 P +-0.23 (ite this data to) 496.45 203.33 P +1.18 (the b) 279.43 191.33 P +1.18 (uff) 302.65 191.33 P +1.18 (er) 313.48 191.33 P +1.18 (. The siz) 321.86 191.33 P +1.18 (e of the allocated b) 361.87 191.33 P +1.18 (uff) 450.9 191.33 P +1.18 (er will be pro) 461.72 191.33 P +1.18 (vided to) 521.8 191.33 P +(the caller in the) 279.43 179.33 T +3 F +(b) 350.02 179.33 T +(ufLen) 355.38 179.33 T +0 F +( v) 380.4 179.33 T +(ar) 387.93 179.33 T +(iab) 396.97 179.33 T +(le) 410.11 179.33 T +(.) 417.74 179.33 T +2 F +(xdrExpor) 180 155.33 T +(t) 224.1 155.33 T +3 F +(int xdrExpor) 279.29 155.33 T +(t \050char * b) 333.04 155.33 T +(uf) 376.19 155.33 T +(, siz) 384.23 155.33 T +(e_t b) 401.86 155.33 T +(ufLen, siz) 423.9 155.33 T +(e_t count\051;) 466.55 155.33 T +0 F +6.96 (P) 279.29 138.33 P +6.96 (opulates the preallocated b) 285.46 138.33 P +6.96 (uff) 426.2 138.33 P +6.96 (er \050) 437.02 138.33 P +3 F +6.96 (b) 458.97 138.33 P +6.96 (uf) 464.33 138.33 P +0 F +6.96 (\051 with the XDR) 472.67 138.33 P +2.48 (representation of the contents of this cde) 279.43 126.33 P +2.48 (vData object. The) 474.67 126.33 P +1.86 (b) 279.43 114.33 P +1.86 (uff) 284.79 114.33 P +1.86 (er length \050) 295.61 114.33 P +3 F +1.86 (b) 344.36 114.33 P +1.86 (ufLen) 349.72 114.33 P +0 F +1.86 (\051 and n) 374.74 114.33 P +1.86 (umber of elements \050) 409.49 114.33 P +3 F +1.86 (count) 504 114.33 P +0 F +1.86 (\051 m) 528.46 114.33 P +1.86 (ust) 544.66 114.33 P +(ha) 279.43 102.33 T +(v) 290.35 102.33 T +(e been calculated in adv) 295.1 102.33 T +(ance using the) 402.69 102.33 T +3 F +(xdrSiz) 470.51 102.33 T +(e) 498.14 102.33 T +0 F +( method.) 503.7 102.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "13" 23 +%%Page: "14" 24 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. The cde) 54 739 T +(vData Class) 96.25 739 T +0 10 Q +(14) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(xdrImpor) 162 713.33 T +(t) 205.54 713.33 T +3 F +(int xdrImpor) 261.29 713.33 T +(t \050char * b) 314.48 713.33 T +(uf) 357.63 713.33 T +(, siz) 365.67 713.33 T +(e_t b) 383.3 713.33 T +(ufLen\051;) 405.34 713.33 T +0 F +8.32 (Decodes the caller supplied b) 261.29 696.33 P +8.32 (uff) 425.53 696.33 P +8.32 (er \050) 436.35 696.33 P +3 F +8.32 (b) 459.67 696.33 P +8.32 (uf) 465.02 696.33 P +0 F +8.32 (\051 from XDR) 473.36 696.33 P +2.99 (representation and populates the cde) 261.43 684.33 P +2.99 (vData object with the) 438.2 684.33 P +1.51 (contents) 261.43 672.33 P +1.51 (. The caller m) 299.08 672.33 P +1.51 (ust specify the n) 364.08 672.33 P +1.51 (umber of b) 440.78 672.33 P +1.51 (ytes in the) 491.4 672.33 P +(XDR b) 261.43 660.33 T +(uff) 290.68 660.33 T +(er \050) 301.5 660.33 T +3 F +(b) 316.5 660.33 T +(ufLen) 321.86 660.33 T +0 F +(\051.) 346.88 660.33 T +2 F +(remo) 162 636.33 T +(ve) 186.25 636.33 T +3 F +(v) 261.29 636.33 T +(oid remo) 266.04 636.33 T +(v) 304.79 636.33 T +(e\050v) 309.54 636.33 T +(oid\051;) 323.18 636.33 T +(v) 261.29 624.33 T +(oid remo) 266.04 624.33 T +(v) 304.79 624.33 T +(e\050int tag\051;) 309.54 624.33 T +(v) 261.29 612.33 T +(oid remo) 266.04 612.33 T +(v) 304.79 612.33 T +(e\050char * ctag\051;) 309.54 612.33 T +0 F +1.53 (Remo) 261.29 595.33 P +1.53 (v) 287.81 595.33 P +1.53 (es the data item speci\336ed b) 292.56 595.33 P +1.53 (y the unique tag name or) 421.73 595.33 P +1.65 (integer from this cde) 261.43 583.33 P +1.65 (vData object. If the tag is not speci\336ed,) 356.68 583.33 P +(then all data items will be remo) 261.43 571.33 T +(v) 398.55 571.33 T +(ed from the object.) 403.3 571.33 T +2 F +(c) 162 547.33 T +(hang) 167.46 547.33 T +(eT) 191.45 547.33 T +(a) 202.32 547.33 T +(g) 207.78 547.33 T +3 F +(int changeT) 261.29 547.33 T +(ag\050int oldT) 312.34 547.33 T +(ag, int ne) 358.38 547.33 T +(wT) 399.32 547.33 T +(ag\051;) 411.45 547.33 T +(int changeT) 261.29 535.33 T +(ag\050int oldT) 312.34 535.33 T +(ag, char *c_ne) 358.38 535.33 T +(wT) 422.66 535.33 T +(ag\051;) 434.79 535.33 T +(int changeT) 261.29 523.33 T +(ag\050char *c_oldT) 312.34 523.33 T +(ag, int ne) 381.72 523.33 T +(wT) 422.66 523.33 T +(ag\051;) 434.79 523.33 T +(int changeT) 261.29 511.33 T +(ag\050char *c_oldT) 312.34 511.33 T +(ag, char *c_ne) 381.72 511.33 T +(wT) 446 511.33 T +(ag\051;) 458.13 511.33 T +2.17 (Retags) 261.29 494.33 P +0 F +2.17 ( a data item that is currently stored in the cde) 292.97 494.33 P +2.17 (vData) 513.88 494.33 P +-0.17 (object from \322oldT) 261.43 482.33 P +-0.17 (ag\323 to \322ne) 334.9 482.33 P +-0.17 (wT) 377.16 482.33 P +-0.17 (ag\323. By using this method the data) 389.29 482.33 P +0.49 (can be renamed inter) 261.43 470.33 P +0.49 (nally without ha) 357.63 470.33 P +0.49 (ving to perf) 427.32 470.33 P +0.49 (or) 477.46 470.33 P +0.49 (m a cop) 486.6 470.33 P +0.49 (y or) 522.84 470.33 P +7.54 (remo) 261.43 458.33 P +7.54 (v) 284.06 458.33 P +7.54 (al. This function is o) 288.81 458.33 P +7.54 (v) 407.18 458.33 P +7.54 (er) 411.93 458.33 P +7.54 (loaded to suppor) 420.97 458.33 P +7.54 (t an) 510.93 458.33 P +7.54 (y) 535 458.33 P +(per) 261.43 446.33 T +(m) 276.13 446.33 T +(utation of char) 284.36 446.33 T +(acter str) 347.63 446.33 T +(ing tag or integer tag identi\336er) 383.9 446.33 T +(.) 515.69 446.33 T +2 F +(g) 162 422.33 T +(etT) 168.21 422.33 T +(ype) 182.61 422.33 T +3 F +(cde) 261.29 422.33 T +(vDataT) 277.11 422.33 T +(ypes getT) 308.14 422.33 T +(ype\050int tag\051;) 350.85 422.33 T +(cde) 261.29 410.33 T +(vDataT) 277.11 410.33 T +(ypes getT) 308.14 410.33 T +(ype\050char *ctag\051;) 350.85 410.33 T +0 F +2.12 (Retr) 261.29 393.33 P +2.12 (ie) 280.33 393.33 P +2.12 (v) 287.81 393.33 P +2.12 (es the en) 292.56 393.33 P +2.12 (umer) 337.83 393.33 P +2.12 (ated data type of the speci\336ed tagged) 360.51 393.33 P +7.51 (data item within this cde) 261.43 381.33 P +7.51 (vData object. The f) 397.88 381.33 P +7.51 (ollo) 504.03 381.33 P +7.51 (wing) 519.44 381.33 P +(en) 261.43 369.33 T +(umer) 272.45 369.33 T +(ated types are de\336ned in the \336le) 295.13 369.33 T +3 F +(cde) 439.66 369.33 T +(vT) 455.48 369.33 T +(ypes) 465.39 369.33 T +(.h) 486.36 369.33 T +0 F +(.) 494.7 369.33 T +2 F +(CDEV_BYTE) 261.29 352.33 T +0 F +(8 bit unsigned char) 401.31 352.33 T +(acter) 485.7 352.33 T +2 F +(CDEV_INT16) 261.29 335.33 T +0 F +(16 bit signed integer) 401.31 335.33 T +2 F +(CDEV_UINT16) 261.29 318.33 T +0 F +(16 bit unsigned integer) 401.31 318.33 T +2 F +(CDEV_INT32) 261.29 301.33 T +0 F +(32 bit signed integer) 401.31 301.33 T +2 F +(CDEV_UINT32) 261.29 284.33 T +0 F +(32 bit unsigned integer) 401.31 284.33 T +2 F +(CDEV_FLO) 261.29 267.33 T +(A) 314.13 267.33 T +(T) 320.45 267.33 T +0 F +(single precision \337oating point) 401.31 267.33 T +2 F +(CDEV_DOUBLE) 261.29 250.33 T +0 F +(doub) 401.31 250.33 T +(le precision \337oating point.) 423.35 250.33 T +2 F +(CDEV_STRING) 261.29 233.33 T +0 F +(NULL ter) 401.31 233.33 T +(minated char) 441.57 233.33 T +(acter) 499.27 233.33 T +(str) 401.67 221.33 T +(ing) 412.93 221.33 T +2 F +(CDEV_TIMEST) 261.29 204.33 T +(AMP) 330.4 204.33 T +0 F +(cde) 401.31 204.33 T +(v time stamp) 417.13 204.33 T +2 F +(CDEV_INV) 261.29 187.33 T +(ALID) 310.5 187.33 T +0 F +(in) 401.31 187.33 T +(v) 408.89 187.33 T +(alid or unkno) 413.64 187.33 T +(wn data type) 470.74 187.33 T +2 F +(g) 162 163.33 T +(etDim) 168.21 163.33 T +3 F +(int getDim\050int tag, siz) 261.29 163.33 T +(e_t *dim\051;) 354.5 163.33 T +(int getDim\050char *ctag, siz) 261.29 151.33 T +(e_t *dim\051;) 372.28 151.33 T +0 F +1.18 (Retr) 261.29 134.33 P +1.18 (ie) 280.33 134.33 P +1.18 (v) 287.81 134.33 P +1.18 (es the n) 292.56 134.33 P +1.18 (umber of dimensions in a data item that is an) 330.4 134.33 P +1.38 (arr) 261.43 122.33 P +1.38 (a) 273.55 122.33 P +1.38 (y) 278.81 122.33 P +1.38 (. If dim is 0, then the data item is scalar) 282.81 122.33 P +1.38 (, otherwise) 469.57 122.33 P +1.38 (, the) 519.16 122.33 P +4.56 (data item is a \322dim\323 dimensional arr) 261.43 110.33 P +4.56 (a) 444.82 110.33 P +4.56 (y) 450.08 110.33 P +4.56 (. This function is) 454.08 110.33 P +0.42 (o) 261.43 98.33 P +0.42 (v) 266.84 98.33 P +0.42 (er) 271.59 98.33 P +0.42 (loaded to suppor) 280.63 98.33 P +0.42 (t either the integer tag or char) 356.36 98.33 P +0.42 (acter str) 489.97 98.33 P +0.42 (ing) 526.66 98.33 P +(tag.) 261.43 86.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "14" 24 +%%Page: "15" 25 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. The cde) 467.23 739 T +(vData Class) 509.49 739 T +0 10 Q +(15) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(g) 180 713.33 T +(etElems) 186.21 713.33 T +3 F +(int getElems\050int tag, siz) 279.29 713.33 T +(e_t *elems\051;) 382.51 713.33 T +(int getElems\050char *ctag, siz) 279.29 701.33 T +(e_t *elems\051;) 400.29 701.33 T +0 F +1.08 (Retr) 279.29 684.33 P +1.08 (ie) 298.33 684.33 P +1.08 (v) 305.81 684.33 P +1.08 (es the n) 310.56 684.33 P +1.08 (umber of data elements in all dimensions of a) 348.19 684.33 P +2.22 (m) 279.43 672.33 P +2.22 (ulti-dimensional arr) 287.66 672.33 P +2.22 (a) 374.24 672.33 P +2.22 (y) 379.5 672.33 P +2.22 (. If elems is 1, then the data item is) 383.5 672.33 P +-0.14 (scalar) 279.43 660.33 P +-0.14 (, otherwise) 305.6 660.33 P +-0.14 (, the data item is an arr) 353.66 660.33 P +-0.14 (a) 454.96 660.33 P +-0.14 (y of \322elems\323 elements) 460.22 660.33 P +-0.14 (.) 555.22 660.33 P +0.61 (This function is o) 279.43 648.33 P +0.61 (v) 356.13 648.33 P +0.61 (er) 360.88 648.33 P +0.61 (loaded to suppor) 369.92 648.33 P +0.61 (t either the integer tag or) 446.02 648.33 P +(char) 279.43 636.33 T +(acter str) 298.78 636.33 T +(ing tag.) 335.05 636.33 T +2 F +(g) 180 612.33 T +(etBounds) 186.21 612.33 T +3 F +(int getBounds\050) 279.29 612.33 T +(int tag,) 351.57 612.33 T +(cde) 351.57 600.33 T +(vBounds * bounds) 367.39 600.33 T +(,) 448.4 600.33 T +(siz) 351.57 588.33 T +(e_t n) 363.64 588.33 T +(umBounds\051;) 385.78 588.33 T +(int getBounds\050) 279.29 576.33 T +(char * ctag,) 351.57 576.33 T +(cde) 351.57 564.33 T +(vBounds * bounds) 367.39 564.33 T +(,) 448.4 564.33 T +(siz) 351.57 552.33 T +(e_t n) 363.64 552.33 T +(umBounds\051;) 385.78 552.33 T +0 F +0.59 (Obtains the bounding dimensions of the arr) 279.29 535.33 P +0.59 (a) 473.92 535.33 P +0.59 (y speci\336ed b) 479.18 535.33 P +0.59 (y the) 535.73 535.33 P +2.38 (caller pro) 279.43 523.33 P +2.38 (vided tag. The cde) 322.78 523.33 P +2.38 (vBounds str) 411.87 523.33 P +2.38 (ucture contains tw) 467.2 523.33 P +2.38 (o) 552.44 523.33 P +0.81 (integers: offset and length. The length v) 279.43 511.33 P +0.81 (ar) 459.71 511.33 P +0.81 (iab) 468.76 511.33 P +0.81 (le represents the) 481.89 511.33 P +1.49 (n) 279.43 499.33 P +1.49 (umber of data elements in that dimension of the arr) 284.89 499.33 P +1.49 (a) 524.46 499.33 P +1.49 (y) 529.72 499.33 P +1.49 (. The) 533.72 499.33 P +1.39 (offset integer is pro) 279.43 487.33 P +1.39 (vided f) 368.49 487.33 P +1.39 (or use in specifying the position of) 399.04 487.33 P +1.63 (arr) 279.43 475.33 P +1.63 (a) 291.55 475.33 P +1.63 (ys that are sub-sets of the actual data. A v) 296.81 475.33 P +1.63 (ersion of this) 498.04 475.33 P +0.9 (function is a) 279.43 463.33 P +0.9 (v) 334.4 463.33 P +0.9 (ailab) 339.15 463.33 P +0.9 (le that uses an arr) 360.07 463.33 P +0.9 (a) 443.62 463.33 P +0.9 (y of integers r) 448.88 463.33 P +0.9 (ather than) 512.07 463.33 P +4.3 (the cde) 279.43 451.33 P +4.3 (vBounds str) 316.23 451.33 P +4.3 (ucture) 373.48 451.33 P +4.3 (. This function is o) 401.12 451.33 P +4.3 (v) 498.77 451.33 P +4.3 (er) 503.52 451.33 P +4.3 (loaded to) 512.56 451.33 P +(suppor) 279.43 439.33 T +(t either the integer tag or char) 310.4 439.33 T +(acter str) 441.48 439.33 T +(ing tag.) 477.75 439.33 T +2 F +(setBounds) 180 415.33 T +3 F +(int setBounds\050) 279.29 415.33 T +(int tag,) 351.57 415.33 T +(cde) 351.57 403.33 T +(vBounds * bounds) 367.39 403.33 T +(,) 448.4 403.33 T +(siz) 351.57 391.33 T +(e_t n) 363.64 391.33 T +(umBounds\051;) 385.78 391.33 T +(int setBounds\050) 279.29 379.33 T +(char * ctag,) 351.57 379.33 T +(cde) 351.57 367.33 T +(vBounds * bounds) 367.39 367.33 T +(,) 448.4 367.33 T +(siz) 351.57 355.33 T +(e_t n) 363.64 355.33 T +(umBounds\051;) 385.78 355.33 T +0 F +-0.13 (Speci\336es the bounding dimensions of a m) 279.29 338.33 P +-0.13 (ulti-dimensional arr) 463.51 338.33 P +-0.13 (a) 547.74 338.33 P +-0.13 (y) 553 338.33 P +0.12 (of data. In order to use this function, the n) 279.43 326.33 P +0.12 (umber of dimensions) 464.95 326.33 P +2.1 (in the arr) 279.43 314.33 P +2.1 (a) 322.99 314.33 P +2.1 (y m) 328.25 314.33 P +2.1 (ust be speci\336ed as a par) 346.36 314.33 P +2.1 (ameter to the inser) 465.15 314.33 P +2.1 (t) 555.22 314.33 P +0.23 (command when placing the data into the cde) 279.43 302.33 P +0.23 (vData object. The) 479.17 302.33 P +0.44 (cde) 279.43 290.33 P +0.44 (vBounds str) 295.25 290.33 P +0.44 (ucture contains tw) 348.65 290.33 P +0.44 (o integers: offset and length.) 430.03 290.33 P +0.36 (The length v) 279.43 278.33 P +0.36 (ar) 334.94 278.33 P +0.36 (iab) 343.98 278.33 P +0.36 (le represents the n) 357.12 278.33 P +0.36 (umber of data elements in) 440.93 278.33 P +1.31 (that dimension of the arr) 279.43 266.33 P +1.31 (a) 392.39 266.33 P +1.31 (y) 397.65 266.33 P +1.31 (. The offset integer is pro) 401.65 266.33 P +1.31 (vided f) 518.64 266.33 P +1.31 (or) 549.11 266.33 P +0.4 (use in specifying the position of arr) 279.43 254.33 P +0.4 (a) 435.68 254.33 P +0.4 (ys that are sub-sets of the) 440.95 254.33 P +0.6 (actual data. A v) 279.43 242.33 P +0.6 (ersion of this function is a) 349.9 242.33 P +0.6 (v) 465.5 242.33 P +0.6 (ailab) 470.25 242.33 P +0.6 (le that uses an) 491.17 242.33 P +1.92 (arr) 279.43 230.33 P +1.92 (a) 291.55 230.33 P +1.92 (y of integers r) 296.81 230.33 P +1.92 (ather than the cde) 363.05 230.33 P +1.92 (vBounds str) 449.12 230.33 P +1.92 (ucture) 503.99 230.33 P +1.92 (. This) 531.63 230.33 P +3.08 (function is o) 279.43 218.33 P +3.08 (v) 338.8 218.33 P +3.08 (er) 343.55 218.33 P +3.08 (loaded to suppor) 352.59 218.33 P +3.08 (t either the integer tag or) 433.64 218.33 P +(char) 279.43 206.33 T +(acter str) 298.78 206.33 T +(ing tag.) 335.05 206.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "15" 25 +%%Page: "16" 26 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. The cde) 54 739 T +(vData Class) 96.25 739 T +0 10 Q +(16) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(inser) 162 713.33 T +(t \050) 186.1 713.33 T +5 F +(scalar) 195.54 713.33 T +2 F +(\051) 224.45 713.33 T +3 F +(int inser) 261.29 713.33 T +(t \050int tag, BYTE data\051;) 296.7 713.33 T +(int inser) 261.29 701.33 T +(t \050int tag, shor) 296.7 701.33 T +(t data\051;) 358.24 701.33 T +(int inser) 261.29 689.33 T +(t \050int tag, unsigned shor) 296.7 689.33 T +(t data\051;) 401.6 689.33 T +(int inser) 261.29 677.33 T +(t \050int tag, int data\051;) 296.7 677.33 T +(int inser) 261.29 665.33 T +(t \050int tag, unsigned int data\051;) 296.7 665.33 T +(int inser) 261.29 653.33 T +(t \050int tag, long data\051;) 296.7 653.33 T +(int inser) 261.29 641.33 T +(t \050int tag, unsigned long data\051;) 296.7 641.33 T +(int inser) 261.29 629.33 T +(t \050int tag, \337oat data\051;) 296.7 629.33 T +(int inser) 261.29 617.33 T +(t \050int tag, doub) 296.7 617.33 T +(le data\051;) 360.43 617.33 T +(int inser) 261.29 605.33 T +(t \050int tag, cde) 296.7 605.33 T +(v_TS_ST) 354.21 605.33 T +(AMP data\051;) 394.69 605.33 T +0 F +0.61 (These methods allo) 261.29 588.33 P +0.61 (w the user to inser) 349.61 588.33 P +0.61 (t a single data item into) 434.14 588.33 P +2.02 (the cde) 261.43 576.33 P +2.02 (vData object using the speci\336ed tag. If another data) 295.95 576.33 P +0.79 (item already occupies that tag within the cde) 261.43 564.33 P +0.79 (vData object, the) 463.39 564.33 P +2.63 (ne) 261.43 552.33 P +2.63 (w data item will o) 272.35 552.33 P +2.63 (v) 358.84 552.33 P +2.63 (err) 363.59 552.33 P +2.63 (ide the old one) 375.96 552.33 P +2.63 (. Although only the) 449.29 552.33 P +6.15 (integer tag prototypes are sho) 261.43 540.33 P +6.15 (wn, these functions are) 418.73 540.33 P +2.28 (o) 261.43 528.33 P +2.28 (v) 266.84 528.33 P +2.28 (er) 271.59 528.33 P +2.28 (loaded to suppor) 280.63 528.33 P +2.28 (t both the integer and char) 360.08 528.33 P +2.28 (acter str) 488.11 528.33 P +2.28 (ing) 526.66 528.33 P +(data tags) 261.43 516.33 T +(.) 302.42 516.33 T +2 F +(inser) 162 492.33 T +(t \050arra) 186.1 492.33 T +(y\051) 214.24 492.33 T +3 F +(int inser) 261.29 492.33 T +(t \050int tag, BYTE * data, siz) 296.7 492.33 T +(e_t len, siz) 411.05 492.33 T +(e_t ndim\051;) 458.7 492.33 T +(int inser) 261.29 480.33 T +(t \050int tag, shor) 296.7 480.33 T +(t * data, siz) 358.24 480.33 T +(e_t len, siz) 407.56 480.33 T +(e_t ndim\051;) 455.21 480.33 T +-0.28 (int inser) 261.29 468.33 P +-0.28 (t \050int tag, unsigned shor) 296.42 468.33 P +-0.28 (t * data, siz) 400.22 468.33 P +-0.28 (e_t len, siz) 448.72 468.33 P +-0.28 (e_t ndim\051;) 495.82 468.33 P +(int inser) 261.29 456.33 T +(t \050int tag, int * data, siz) 296.7 456.33 T +(e_t len, siz) 395.49 456.33 T +(e_t ndim\051;) 443.14 456.33 T +(int inser) 261.29 444.33 T +(t \050int tag, unsigned int * data, siz) 296.7 444.33 T +(e_t len, siz) 438.85 444.33 T +(e_t ndim\051;) 486.5 444.33 T +(int inser) 261.29 432.33 T +(t \050int tag, long * data, siz) 296.7 432.33 T +(e_t len, siz) 403.83 432.33 T +(e_t ndim\051;) 451.48 432.33 T +(int inser) 261.29 420.33 T +(t \050int tag, unsigned long * data, siz) 296.7 420.33 T +(e_t len, siz) 447.19 420.33 T +(e_t ndim\051;) 494.84 420.33 T +(int inser) 261.29 408.33 T +(t \050int tag, \337oat * data, siz) 296.7 408.33 T +(e_t len, siz) 403.83 408.33 T +(e_t ndim\051;) 451.48 408.33 T +(int inser) 261.29 396.33 T +(t \050int tag, doub) 296.7 396.33 T +(le * data, siz) 360.43 396.33 T +(e_t len, siz) 414.75 396.33 T +(e_t ndim\051;) 462.4 396.33 T +0 F +-0.27 (These methods allo) 261.29 379.33 P +-0.27 (w the user to inser) 347.87 379.33 P +-0.27 (t arr) 428.9 379.33 P +-0.27 (a) 446.31 379.33 P +-0.27 (y data items into the) 451.57 379.33 P +0.86 (cde) 261.43 367.33 P +0.86 (vData object using the speci\336ed tag. The len par) 277.25 367.33 P +0.86 (ameter is) 498.02 367.33 P +0.04 (used to specify the total n) 261.43 355.33 P +0.04 (umber of items in the arr) 374.94 355.33 P +0.04 (a) 483.42 355.33 P +0.04 (y) 488.68 355.33 P +0.04 (. The ndim) 492.68 355.33 P +0.87 (par) 261.43 343.33 P +0.87 (ameter is used to specify the n) 275.78 343.33 P +0.87 (umber of dimensions in the) 416.49 343.33 P +1.47 (arr) 261.43 331.33 P +1.47 (a) 273.55 331.33 P +1.47 (y \0501 b) 278.81 331.33 P +1.47 (y def) 306.56 331.33 P +1.47 (ault\051. Although only the integer tag prototypes) 329.41 331.33 P +0.44 (are sho) 261.43 319.33 P +0.44 (wn, these functions are o) 295.07 319.33 P +0.44 (v) 407.86 319.33 P +0.44 (er) 412.61 319.33 P +0.44 (loaded to suppor) 421.65 319.33 P +0.44 (t both the) 497.42 319.33 P +(integer and char) 261.43 307.33 T +(acter str) 333.59 307.33 T +(ing data tags) 369.86 307.33 T +(.) 426.97 307.33 T +2 F +(inser) 162 283.33 T +(t \050c) 186.1 283.33 T +(haracter string\051) 201 283.33 T +3 F +(int inser) 261.29 271.33 T +(t \050int tag, char * data\051;) 296.7 271.33 T +(int inser) 261.29 259.33 T +(t \050int tag, char ** data, siz) 296.7 259.33 T +(e_t len, siz) 408.27 259.33 T +(e_t ndim\051;) 455.92 259.33 T +0 F +1.82 (These methods are used to add NULL ter) 261.29 242.33 P +1.82 (minated char) 458.25 242.33 P +1.82 (acter) 517.77 242.33 P +0.93 (str) 261.43 230.33 P +0.93 (ings to the cde) 272.69 230.33 P +0.93 (vData object. These methods diff) 340.21 230.33 P +0.93 (er from the) 489.8 230.33 P +0.62 (others because a single char) 261.43 218.33 P +0.62 (acter str) 391.64 218.33 P +0.62 (ing is treated as a scalar) 428.53 218.33 P +3.34 (v) 261.43 206.33 P +3.34 (alue) 266.18 206.33 P +3.34 (. The len par) 284.93 206.33 P +3.34 (ameter \050where used\051 speci\336es the total) 351 206.33 P +0 (n) 261.43 194.33 P +0 (umber of char) 266.89 194.33 P +0 (acter str) 328.49 194.33 P +0 (ings in the arr) 364.76 194.33 P +0 (a) 425.24 194.33 P +0 (y) 430.5 194.33 P +0 (. The ndim par) 434.5 194.33 P +0 (ameter is) 498.88 194.33 P +1.54 (used to specify the n) 261.43 182.33 P +1.54 (umber of dimensions in the arr) 359.21 182.33 P +1.54 (a) 501.85 182.33 P +1.54 (y \0501 b) 507.11 182.33 P +1.54 (y) 535 182.33 P +1.46 (def) 261.43 170.33 P +1.46 (ault\051. Although only the integer tag prototypes are sho) 275.03 170.33 P +1.46 (wn,) 524.44 170.33 P +0.3 (these functions are o) 261.43 158.33 P +0.3 (v) 355.01 158.33 P +0.3 (er) 359.76 158.33 P +0.3 (loaded to suppor) 368.8 158.33 P +0.3 (t both the integer and) 444.29 158.33 P +(char) 261.43 146.33 T +(acter str) 280.78 146.33 T +(ing data tags) 317.05 146.33 T +(.) 374.16 146.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "16" 26 +%%Page: "17" 27 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. The cde) 467.23 739 T +(vData Class) 509.49 739 T +0 10 Q +(17) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(g) 180 713.33 T +(et) 186.21 713.33 T +3 F +(int get\050int tag, BYTE * data\051;) 279.29 713.33 T +(int get\050int tag, shor) 279.29 701.33 T +(t * data\051;) 362.51 701.33 T +(int get\050int tag, unsigned shor) 279.29 689.33 T +(t * data\051;) 405.87 689.33 T +(int get\050int tag, int * data\051;) 279.29 677.33 T +(int get\050int tag, unsigned int * data\051;) 279.29 665.33 T +(int get\050int tag, long * data\051;) 279.29 653.33 T +(int get\050int tag, unsigned long * data\051;) 279.29 641.33 T +(int get\050int tag, \337oat * data\051;) 279.29 629.33 T +(int get\050int tag, doub) 279.29 617.33 T +(le * data\051;) 364.7 617.33 T +(int get\050int tag, cde) 279.29 605.33 T +(v_TS_ST) 358.48 605.33 T +(AMP * data\051;) 398.96 605.33 T +0 F +1.2 (These methods are used to retr) 279.29 588.33 P +1.2 (ie) 424.93 588.33 P +1.2 (v) 432.41 588.33 P +1.2 (e scalar v) 437.16 588.33 P +1.2 (alues and arr) 482.09 588.33 P +1.2 (a) 542.74 588.33 P +1.2 (ys) 548 588.33 P +2.59 (that are stored in the cde) 279.43 576.33 P +2.59 (vData object. When retr) 402.72 576.33 P +2.59 (ie) 515.69 576.33 P +2.59 (ving an) 523.17 576.33 P +-0.02 (arr) 279.43 564.33 P +-0.02 (a) 291.55 564.33 P +-0.02 (y) 296.81 564.33 P +-0.02 (, it is the caller\325) 300.81 564.33 P +-0.02 (s responsibility to call the) 366.37 564.33 P +3 F +-0.02 (getElems) 480.21 564.33 P +0 F +-0.02 ( method) 521.89 564.33 P +2.12 (to obtain the n) 279.43 552.33 P +2.12 (umber of elements and then pre-allocate the) 349.07 552.33 P +1.19 (b) 279.43 540.33 P +1.19 (uff) 284.79 540.33 P +1.19 (er to receiv) 295.61 540.33 P +1.19 (e the data. If the receiving data type does not) 347.19 540.33 P +1.71 (match the data type stored in the cde) 279.43 528.33 P +1.71 (vData object, then the) 455.61 528.33 P +1.89 (data will be con) 279.43 516.33 P +1.89 (v) 353.81 516.33 P +1.89 (er) 358.56 516.33 P +1.89 (ted to the ne) 367.85 516.33 P +1.89 (w type when it is e) 428.91 516.33 P +1.89 (xtr) 519.75 516.33 P +1.89 (acted.) 530.76 516.33 P +2.88 (Although only the integer tag prototypes are sho) 279.43 504.33 P +2.88 (wn, these) 512.32 504.33 P +3.74 (functions are o) 279.43 492.33 P +3.74 (v) 352.36 492.33 P +3.74 (er) 357.11 492.33 P +3.74 (loaded to suppor) 366.15 492.33 P +3.74 (t both the integer and) 448.52 492.33 P +(char) 279.43 480.33 T +(acter str) 298.78 480.33 T +(ing data tags) 335.05 480.33 T +(.) 392.16 480.33 T +2 F +(g) 180 456.33 T +(et \050c) 186.21 456.33 T +(haracter string\051) 206.67 456.33 T +3 F +(int get\050int tag, char * data, siz) 279.29 444.33 T +(e_t len\051;) 408.65 444.33 T +(int get\050int tag, char ** data\051;) 279.29 432.33 T +0 F +3.13 (These methods are used to retr) 279.29 415.33 P +3.13 (ie) 434.61 415.33 P +3.13 (v) 442.09 415.33 P +3.13 (e char) 446.84 415.33 P +3.13 (acter str) 477.66 415.33 P +3.13 (ings and) 517.07 415.33 P +3.29 (arr) 279.43 403.33 P +3.29 (a) 291.55 403.33 P +3.29 (ys of char) 296.81 403.33 P +3.29 (acter str) 346.65 403.33 P +3.29 (ings from a cde) 386.21 403.33 P +3.29 (vData object. When) 464.15 403.33 P +0.99 (obtaining a single char) 279.43 391.33 P +0.99 (acter str) 382.36 391.33 P +0.99 (ing, the length of the allocated) 419.62 391.33 P +0.76 (b) 279.43 379.33 P +0.76 (uff) 284.79 379.33 P +0.76 (er m) 295.61 379.33 P +0.76 (ust be speci\336ed in the) 316.27 379.33 P +3 F +0.76 (len) 419.58 379.33 P +0 F +0.76 ( par) 432.92 379.33 P +0.76 (ameter) 450.82 379.33 P +0.76 (. When obtaining) 481.44 379.33 P +1.38 (an arr) 279.43 367.33 P +1.38 (a) 306.83 367.33 P +1.38 (y of char) 312.09 367.33 P +1.38 (acter str) 353.1 367.33 P +1.38 (ings) 390.74 367.33 P +1.38 (, the caller m) 408.93 367.33 P +1.38 (ust pre-allocate the) 470.2 367.33 P +0.23 (POINTERS f) 279.43 355.33 P +0.23 (or each element in the arr) 336.05 355.33 P +0.23 (a) 451.06 355.33 P +0.23 (y) 456.32 355.33 P +0.23 (. The cde) 460.32 355.33 P +0.23 (vData object) 502.18 355.33 P +1.15 (will allocate suf\336cient memor) 279.43 343.33 P +1.15 (y to each of the pointers to hold) 410.43 343.33 P +7.18 (the individual char) 279.43 331.33 P +7.18 (acter str) 374.27 331.33 P +7.18 (ings) 417.72 331.33 P +7.18 (. It then becomes the) 435.91 331.33 P +-0.19 (responsibility of the caller to free the memor) 279.43 319.33 P +-0.19 (y assigned to those) 472.39 319.33 P +1.86 (pointers) 279.43 307.33 P +1.86 (. If the receiving data type does not match the data) 314.85 307.33 P +3.32 (type stored in the cde) 279.43 295.33 P +3.32 (vData object, then the data will be) 388.01 295.33 P +1.02 (con) 279.43 283.33 P +1.02 (v) 295.35 283.33 P +1.02 (er) 300.1 283.33 P +1.02 (ted to the ne) 309.39 283.33 P +1.02 (w type when it is e) 367.85 283.33 P +1.02 (xtr) 454.34 283.33 P +1.02 (acted. Although only) 465.35 283.33 P +3.3 (the integer tag prototypes are sho) 279.43 271.33 P +3.3 (wn, these functions are) 445.29 271.33 P +2.28 (o) 279.43 259.33 P +2.28 (v) 284.84 259.33 P +2.28 (er) 289.59 259.33 P +2.28 (loaded to suppor) 298.63 259.33 P +2.28 (t both the integer and char) 378.08 259.33 P +2.28 (acter str) 506.11 259.33 P +2.28 (ing) 544.66 259.33 P +(data tags) 279.43 247.33 T +(.) 320.42 247.33 T +2 F +(\336nd) 180 223.33 T +3 F +(int \336nd\050int tag, v) 279.29 223.33 T +(oid* &data\051;) 349.63 223.33 T +(int \336nd\050char * ctag, v) 279.29 211.33 T +(oid* &data\051;) 370.19 211.33 T +0 F +0.32 (Retr) 279.29 194.33 P +0.32 (ie) 298.33 194.33 P +0.32 (v) 305.81 194.33 P +0.32 (es a pointer to the data within the cde) 310.56 194.33 P +0.32 (vData object. The) 479 194.33 P +0.21 (caller is responsib) 279.43 182.33 P +0.21 (le f) 359.68 182.33 P +0.21 (or ensur) 372.93 182.33 P +0.21 (ing that the receiving pointer is of) 409.98 182.33 P +-0.22 (the correct data type f) 279.43 170.33 P +-0.22 (or the data within the object. This function) 374.98 170.33 P +0.91 (is o) 279.43 158.33 P +0.91 (v) 295.76 158.33 P +0.91 (er) 300.51 158.33 P +0.91 (loaded to suppor) 309.55 158.33 P +0.91 (t both integer and char) 386.27 158.33 P +0.91 (acter str) 489.88 158.33 P +0.91 (ing tag) 527.07 158.33 P +(identi\336ers) 279.43 146.33 T +(.) 322.07 146.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "17" 27 +%%Page: "18" 28 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. The cde) 54 739 T +(vDe) 96.25 739 T +(vice Class) 111.99 739 T +0 10 Q +(18) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(5.) 141.32 710.67 T +(The cde) 162 710.67 T +(vDe) 214.7 710.67 T +(vice Class) 240.16 710.67 T +2 10 Q +(Over) 54 673.33 T +(vie) 76.89 673.33 T +(w of the) 90.64 673.33 T +(cde) 54 661.33 T +(vDe) 71.08 661.33 T +(vice Class) 89.27 661.33 T +0 F +(The) 162 673.33 T +3 F +(cde) 182.01 673.33 T +(vDe) 197.83 673.33 T +(vice) 215.31 673.33 T +0 F +( C++ class is the user\325) 233.09 673.33 T +(s pr) 330.96 673.33 T +(imar) 347.78 673.33 T +(y interf) 367.52 673.33 T +(ace to cde) 397.23 673.33 T +(v) 443.07 673.33 T +(. In f) 447.27 673.33 T +(act, it is possib) 466.43 673.33 T +(le) 531.81 673.33 T +(to de) 162 661.33 T +(v) 183.94 661.33 T +(elop complete cde) 188.69 661.33 T +(v applications using only) 269.54 661.33 T +3 F +(cde) 380.7 661.33 T +(vDe) 396.52 661.33 T +(vice) 414 661.33 T +0 F +( and) 431.78 661.33 T +3 F +(cde) 454.02 661.33 T +(vData) 469.84 661.33 T +0 F +( objects) 495.96 661.33 T +(.) 530.27 661.33 T +(The) 162 649.33 T +3 F +(cde) 182.01 649.33 T +(vDe) 197.83 649.33 T +(vice) 215.31 649.33 T +0 F +( class de\336nes the basic interf) 233.09 649.33 T +(ace that all applications m) 361.18 649.33 T +(ust use to) 476.13 649.33 T +(tr) 162 637.33 T +(ansmit messages to a cde) 168.01 637.33 T +(v ser) 283.87 637.33 T +(vice) 305.84 637.33 T +(.) 323.47 637.33 T +3 9 Q +(Figure 5: Object model of the cde) 162 604 T +(vDe) 297.3 604 T +(vice class) 313.03 604 T +2 10 Q +(Pub) 54 235 T +(lic Methods of) 72.79 235 T +(the cde) 54 223 T +(vDe) 88.86 223 T +(vice) 107.05 223 T +(Class) 54 211 T +(attac) 162 235 T +(hRef) 185.24 235 T +3 F +(static cde) 261.29 235 T +(vDe) 303.23 235 T +(vice& attachRef \050char *name\051;) 320.71 235 T +0 F +3.38 (Obtains a ref) 261.29 218 P +3.38 (erence to a cde) 324.99 218 P +3.38 (vDe) 403.76 218 P +3.38 (vice object b) 421.24 218 P +3.38 (y name) 483.37 218 P +3.38 (. By) 519.39 218 P +4.63 (def) 261.43 206 P +4.63 (ault, the ne) 275.03 206 P +4.63 (w object will be managed b) 333.57 206 P +4.63 (y the def) 476.56 206 P +4.63 (ault) 523.88 206 P +(cde) 261.43 194 T +(vSystem.) 277.25 194 T +2 F +(attac) 162 170 T +(hPtr) 185.24 170 T +3 F +(static cde) 261.29 170 T +(vDe) 303.23 170 T +(vice* attachPtr \050char *name\051;) 320.71 170 T +0 F +-0.05 (Obtains a pointer to a cde) 261.29 153 P +-0.05 (vDe) 375.26 153 P +-0.05 (vice object speci\336ed b) 392.74 153 P +-0.05 (y name) 490.22 153 P +-0.05 (. By) 522.82 153 P +4.63 (def) 261.43 141 P +4.63 (ault, the ne) 275.03 141 P +4.63 (w object will be managed b) 333.57 141 P +4.63 (y the def) 476.56 141 P +4.63 (ault) 523.88 141 P +(cde) 261.43 129 T +(vSystem.) 277.25 129 T +162 260.67 540 680 C +162 277.67 540 601 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +161.21 277.67 540.79 601 R +7 X +0 0 0 1 0 0 0 K +V +167.45 281.83 539.12 593.5 R +0 X +V +0.5 H +2 Z +N +163.62 286.5 535.29 597.33 R +7 X +V +0 X +N +169.79 310.25 528.79 538.58 R +7 X +V +0 X +N +174.95 315.18 525.79 535.56 R +7 X +V +4 9 Q +0 X +(class cdevDevice) 307.17 529.56 T +(methods:) 174.95 518.56 T +(attachRef \050char *\051 :cdevDevice&) 188.29 507.56 T +(attachPtr \050char *\051 :cdevDevice*) 188.29 496.56 T +(detach \050cdevDevice&\051 :void) 188.29 485.56 T +(detach \050cdevDevice*\051 :void) 188.29 474.56 T +(getRequestObject \050char *msg\051 :cdevRequestObject*) 188.29 463.56 T +(name \050void\051 :char *) 188.29 452.56 T +(system \050void\051 :cdevSystem&) 188.29 441.56 T +(setContext \050cdevData&\051 :int) 188.29 430.56 T +(send \050char*, cdevData&, cdevData&\051 :) 188.29 419.56 T +(int) 474.49 419.56 T +(send \050char*, cdevData*, cdevData&\051 :) 188.29 408.56 T +(int) 474.49 408.56 T +(send \050char*, cdevData&, cdevData*\051 :) 188.29 397.56 T +(int) 474.49 397.56 T +(send \050char*, cdevData*, cdevData*\051 :) 188.29 386.56 T +(int) 474.49 386.56 T +(sendNoBlock \050char*, cdevData&, cdevData&\051 :) 188.29 375.56 T +(int) 474.49 375.56 T +(sendNoBlock \050char*, cdevData*, cdevData&\051 :) 188.29 364.56 T +(int) 474.49 364.56 T +(sendNoBlock \050char*, cdevData&, cdevData*\051 :) 188.29 353.56 T +(int) 474.49 353.56 T +(sendNoBlock \050char*, cdevData*, cdevData*\051 :) 188.29 342.56 T +(int) 474.49 342.56 T +(sendCallback \050char*, cdevData&, cdevCallback&\051 :) 188.29 331.56 T +(int) 474.49 331.56 T +(sendCallback \050char*, cdevData*, cdevCallback&\051 :) 188.29 320.56 T +(int) 474.49 320.56 T +169.95 526.49 529.12 526.49 2 L +N +314.2 575.5 322.11 579.5 330.01 575.5 322.11 571.5 4 Y +7 X +V +0.1 H +0 X +N +330.5 575.5 339.65 575.5 2 L +N +90 450 1.98 2.25 338.23 575.25 G +90 450 1.98 2.25 338.23 575.25 A +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +182.62 568 313.29 583 R +7 X +V +0.5 H +0 X +N +187.12 571.5 308.43 579.83 R +7 X +V +0 X +(class cdevIOContext) 196.48 573.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +341.45 568 450.45 583 R +7 X +V +0 X +N +345.21 571.5 446.4 579.83 R +7 X +V +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +239.29 548.48 247.95 561.14 256.62 548.48 3 Y +V +0.1 H +0 X +N +247.95 561.14 247.95 568.14 2 L +N +247.95 538.86 247.95 548.14 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +162 260.67 540 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "18" 28 +%%Page: "19" 29 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. The cde) 459.01 739 T +(vDe) 501.26 739 T +(vice Class) 517 739 T +0 10 Q +(19) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(detac) 180 713.33 T +(h) 206.02 713.33 T +3 F +(static v) 279.29 713.33 T +(oid detach \050cde) 310.16 713.33 T +(vDe) 378.23 713.33 T +(vice& de) 395.71 713.33 T +(v\051;) 433.76 713.33 T +0 F +1.26 (Remo) 279.29 696.33 P +1.26 (v) 305.81 696.33 P +1.26 (es a ref) 310.56 696.33 P +1.26 (erenced cde) 346.12 696.33 P +1.26 (vDe) 402.11 696.33 P +1.26 (vice object from its associated) 419.59 696.33 P +-0.22 (cde) 279.43 684.33 P +-0.22 (vSystem object. Ordinar) 295.25 684.33 P +-0.22 (y applications should ne) 401.81 684.33 P +-0.22 (v) 507.56 684.33 P +-0.22 (er use this) 512.31 684.33 P +(command.) 279.43 672.33 T +2 F +(detac) 180 648.33 T +(h) 206.02 648.33 T +3 F +(static v) 279.29 648.33 T +(oid detach \050cde) 310.16 648.33 T +(vDe) 378.23 648.33 T +(vice* de) 395.71 648.33 T +(v\051;) 430.98 648.33 T +0 F +3.37 (Detaches the cde) 279.29 631.33 P +3.37 (vDe) 363.54 631.33 P +3.37 (vice object speci\336ed b) 381.02 631.33 P +3.37 (y de) 488.74 631.33 P +3.37 (v from its) 510.71 631.33 P +2.47 (associated cde) 279.43 619.33 P +2.47 (vSystem object. Ordinar) 348.3 619.33 P +2.47 (y applications should) 460.24 619.33 P +(ne) 279.43 607.33 T +(v) 290.25 607.33 T +(er use this command.) 295 607.33 T +2 F +(g) 180 583.33 T +(etRequestObject) 186.21 583.33 T +3 F +(cde) 279.29 583.33 T +(vRequestObject* getRequestObject \050char *msg\051;) 295.11 583.33 T +0 F +1.66 (Obtains a ser) 279.29 566.33 P +1.66 (vice speci\336c request object. This function uses) 342.38 566.33 P +0.48 (the name of the de) 279.43 554.33 P +0.48 (vice speci\336ed within the cde) 364.45 554.33 P +0.48 (vDe) 490.02 554.33 P +0.48 (vice object,) 507.5 554.33 P +1.94 (and the message pro) 279.43 542.33 P +1.94 (vided b) 379.04 542.33 P +1.94 (y the caller to deter) 413.01 542.33 P +1.94 (mine which) 506.05 542.33 P +0.01 (cde) 279.43 530.33 P +0.01 (v ser) 295.25 530.33 P +0.01 (vice will be used to ser) 317.23 530.33 P +0.01 (vice this request. The ser) 418.17 530.33 P +0.01 (vice is) 530.21 530.33 P +2.71 (then loaded \050if necessar) 279.43 518.33 P +2.71 (y\051, and is contacted to pro) 394.58 518.33 P +2.71 (vided a) 523.05 518.33 P +4.84 (request object f) 279.43 506.33 P +4.84 (or the de) 357.19 506.33 P +4.84 (vice/message combination. This) 406.04 506.33 P +0.48 (cde) 279.43 494.33 P +0.48 (vRequestObject will then be used to comm) 295.25 494.33 P +0.48 (unicate with the) 487.56 494.33 P +(ser) 279.43 482.33 T +(vice directly) 293.62 482.33 T +(.) 344.85 482.33 T +2 F +(name) 180 458.33 T +3 F +(const char *name \050v) 279.29 458.33 T +(oid\051 const;) 367.96 458.33 T +0 F +(Retur) 279.29 441.33 T +(ns the name of the de) 303.99 441.33 T +(vice) 400.42 441.33 T +(.) 418.05 441.33 T +2 F +(system) 180 417.33 T +3 F +(cde) 279.29 417.33 T +(vSystem& system \050v) 295.11 417.33 T +(oid\051 const;) 385.43 417.33 T +0 F +1.06 (Obtains a ref) 279.29 400.33 P +1.06 (erence to the under) 338.36 400.33 P +1.06 (lying cde) 428.4 400.33 P +1.06 (vSystem object that) 468.62 400.33 P +(manages this de) 279.43 388.33 T +(vice) 352.5 388.33 T +(.) 370.13 388.33 T +2 F +(setConte) 180 364.33 T +(xt) 222.63 364.33 T +3 F +(int setConte) 279.29 364.33 T +(xt \050cde) 332.35 364.33 T +(vData& cxt\051;) 362.06 364.33 T +0 F +0.17 (Used to inser) 279.29 347.33 P +0.17 (t a cde) 338.93 347.33 P +0.17 (vData object containing tagged v) 368.98 347.33 P +0.17 (alues that) 514.47 347.33 P +0.16 (control optional beha) 279.43 335.33 P +0.16 (vior of the under) 372.38 335.33 P +0.16 (lying de) 445.28 335.33 P +0.16 (vice) 479.6 335.33 P +0.16 (. The conte) 497.23 335.33 P +0.16 (xt) 550.22 335.33 P +4.55 (is often used to specify which proper) 279.43 323.33 P +4.55 (ties \050v) 468.86 323.33 P +4.55 (alue) 499.83 323.33 P +4.55 (, status) 518.58 323.33 P +4.55 (,) 555.22 323.33 P +0.52 (se) 279.43 311.33 P +0.52 (v) 289.69 311.33 P +0.52 (er) 294.44 311.33 P +0.52 (ity\051 a de) 303.48 311.33 P +0.52 (vice retur) 339.79 311.33 P +0.52 (ns in response to a \322get\323 message) 381.68 311.33 P +0.52 (. It is) 535.84 311.33 P +1.78 (impor) 279.43 299.33 P +1.78 (tant to note that an) 304.83 299.33 P +1.78 (y change made to the conte) 395.2 299.33 P +1.78 (xt of a) 527.2 299.33 P +3 F +9.76 (cde) 279.43 287.33 P +9.76 (vDe) 295.25 287.33 P +9.76 (vice) 312.73 287.33 P +0 F +9.76 ( will automatically be propagated to all) 330.51 287.33 P +3 F +1.17 (cde) 279.43 275.33 P +1.17 (vRequestObjects) 295.25 275.33 P +0 F +1.17 ( created from that de) 371.39 275.33 P +1.17 (vice) 468.04 275.33 P +1.17 (. Theref) 485.67 275.33 P +1.17 (ore) 521 275.33 P +1.17 (, an) 535.3 275.33 P +1.17 (y) 553 275.33 P +1.01 (message speci\336c conte) 279.43 263.33 P +1.01 (xt settings should be speci\336ed directly) 385.09 263.33 P +(to the cde) 279.43 251.33 T +(vRequestObject, r) 323.05 251.33 T +(ather than to the cde) 402.98 251.33 T +(vDe) 494.41 251.33 T +(vice) 511.89 251.33 T +(.) 529.52 251.33 T +2 F +(g) 180 227.33 T +(etConte) 186.21 227.33 T +(xt) 223.28 227.33 T +3 F +(cde) 279.29 227.33 T +(vData & getConte) 295.11 227.33 T +(xt \050v) 373.74 227.33 T +(oid\051;) 392.38 227.33 T +0 F +0.63 (Retr) 279.29 210.33 P +0.63 (ie) 298.33 210.33 P +0.63 (v) 305.81 210.33 P +0.63 (es a ref) 310.56 210.33 P +0.63 (erence to the cde) 344.87 210.33 P +0.63 (vData object that contains the) 423.73 210.33 P +(conte) 279.43 198.33 T +(xt f) 303.59 198.33 T +(or a speci\336c de) 316.63 198.33 T +(vice) 383.58 198.33 T +(.) 401.21 198.33 T +2 F +(setPriv) 180 174.33 T +(ate) 213.15 174.33 T +3 F +(v) 279.29 174.33 T +(oid setPr) 284.04 174.33 T +(iv) 323.65 174.33 T +(ate \050v) 330.62 174.33 T +(oid * data\051;) 355.38 174.33 T +0 F +1.64 (Associates a user speci\336ed data object with this cde) 279.29 157.33 P +1.64 (vDe) 522.74 157.33 P +1.64 (vice) 540.22 157.33 P +0.93 (object. The pointer can be retr) 279.43 145.33 P +0.93 (ie) 417.64 145.33 P +0.93 (v) 425.12 145.33 P +0.93 (ed later using the) 429.87 145.33 P +3 F +0.93 (getPr) 513.08 145.33 P +0.93 (iv) 537.13 145.33 P +0.93 (ate) 544.1 145.33 P +0 F +(method.) 279.43 133.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "19" 29 +%%Page: "20" 30 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. The cde) 54 739 T +(vDe) 96.25 739 T +(vice Class) 111.99 739 T +0 10 Q +(20) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(g) 162 713.33 T +(etPriv) 168.21 713.33 T +(ate) 195.8 713.33 T +3 F +(v) 261.29 713.33 T +(oid * getPr) 266.04 713.33 T +(iv) 312.88 713.33 T +(ate \050v) 319.85 713.33 T +(oid\051;) 344.61 713.33 T +0 F +2.09 (Retr) 261.29 696.33 P +2.09 (ie) 280.33 696.33 P +2.09 (v) 287.81 696.33 P +2.09 (es a pointer to a data object that w) 292.56 696.33 P +2.09 (as placed in this) 462.02 696.33 P +(cde) 261.43 684.33 T +(vDe) 277.25 684.33 T +(vice object using the setPr) 294.73 684.33 T +(iv) 411.6 684.33 T +(ate function.) 418.57 684.33 T +2 F +(send) 162 660.33 T +3 F +(int send \050char *msg, cde) 261.29 660.33 T +(vData &out, cde) 368.81 660.33 T +(vData& result\051;) 439.66 660.33 T +(int send \050char *msg, cde) 261.29 648.33 T +(vData *out, cde) 368.81 648.33 T +(vData& result\051;) 436.88 648.33 T +(int send \050char *msg, cde) 261.29 636.33 T +(vData &out, cde) 368.81 636.33 T +(vData* result\051;) 439.66 636.33 T +(int send \050char *msg, cde) 261.29 624.33 T +(vData *out, cde) 368.81 624.33 T +(vData* result\051;) 436.88 624.33 T +0 F +1.74 (The send function is the standard method f) 261.29 607.33 P +1.74 (or synchronously) 462.68 607.33 P +0.17 (comm) 261.43 595.33 P +0.17 (unicating with a de) 288.55 595.33 P +0.17 (vice) 371.59 595.33 P +0.17 (. The caller pro) 389.22 595.33 P +0.17 (vides the message) 456.28 595.33 P +0.71 (as a char) 261.43 583.33 P +0.71 (acter str) 303.88 583.33 P +0.71 (ing in the) 340.86 583.33 P +3 F +0.71 (msg) 386.34 583.33 P +0 F +0.71 (par) 408.72 583.33 P +0.71 (ameter) 423.07 583.33 P +0.71 (. The) 453.69 583.33 P +3 F +0.71 (out) 480.67 583.33 P +0 F +0.71 (cde) 498.06 583.33 P +0.71 (vData) 513.88 583.33 P +0.15 (object contains an) 261.43 571.33 P +0.15 (y proper) 342.18 571.33 P +0.15 (ty v) 379.41 571.33 P +0.15 (alues that the de) 394.88 571.33 P +0.15 (vice will need to) 468.97 571.33 P +1.53 (perf) 261.43 559.33 P +1.53 (or) 278.36 559.33 P +1.53 (m the task. The) 287.5 559.33 P +3 F +1.53 (result) 365.34 559.33 P +0 F +1.53 ( cde) 389.79 559.33 P +1.53 (vData object will contain the) 409.92 559.33 P +1.02 (output proper) 261.43 547.33 P +1.02 (ties that resulted from the call. This function will) 322.33 547.33 P +(retur) 261.43 535.33 T +(n one of the error code de\336ned in cde) 282.24 535.33 T +(vErrCode) 448.15 535.33 T +(.h.) 490.23 535.33 T +3 9 Q +(Figure 6: Retur) 162 502 T +(n codes gener) 224.75 502 T +(ated b) 281.69 502 T +(y the send method.) 306.53 502 T +2 10 Q +(sendNoBloc) 162 228.86 T +(k) 220.14 228.86 T +3 F +-0.01 (int sendNoBloc) 261.29 228.86 P +-0.01 (k\050char *msg, cde) 328.33 228.86 P +-0.01 (vData &out, cde) 403.04 228.86 P +-0.01 (vData &result\051;) 473.88 228.86 P +(int sendNoBloc) 261.29 216.86 T +(k\050char *msg, cde) 328.34 216.86 T +(vData *out, cde) 403.06 216.86 T +(vData &result\051;) 471.13 216.86 T +(int sendNoBloc) 261.29 204.86 T +(k\050char *msg, cde) 328.34 204.86 T +(vData &out, cde) 403.06 204.86 T +(vData *result\051;) 473.91 204.86 T +(int sendNoBloc) 261.29 192.86 T +(k\050char *msg, cde) 328.34 192.86 T +(vData *out, cde) 403.06 192.86 T +(vData *result\051;) 471.13 192.86 T +0 F +3.34 (The) 261.29 175.86 P +3 F +3.34 (sendNoBloc) 284.63 175.86 P +3.34 (k) 338.34 175.86 P +0 F +3.34 ( method uses the same par) 343.34 175.86 P +3.34 (ameters and) 481.08 175.86 P +1.51 (syntax as the) 261.43 163.86 P +3 F +1.51 (send) 327.67 163.86 P +0 F +1.51 ( method. Ho) 349.36 163.86 P +1.51 (w) 406.7 163.86 P +1.51 (e) 413.82 163.86 P +1.51 (v) 419.08 163.86 P +1.51 (er) 423.83 163.86 P +1.51 (, r) 432.22 163.86 P +1.51 (ather than w) 442.53 163.86 P +1.51 (aiting f) 500.43 163.86 P +1.51 (or) 531.11 163.86 P +0.89 (the under) 261.43 151.86 P +0.89 (lying ser) 304.72 151.86 P +0.89 (vice to respond to the request, this function) 343.14 151.86 P +2.34 (will retur) 261.43 139.86 P +2.34 (n immediately) 301.24 139.86 P +2.34 (. The caller m) 364.25 139.86 P +2.34 (ust utiliz) 431.73 139.86 P +2.34 (e a cde) 470.04 139.86 P +2.34 (vGroup) 507.21 139.86 P +(object to detect when this tr) 261.43 127.86 T +(ansaction has been completed.) 383.06 127.86 T +162 81 540 720 C +162 249.52 540 499 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.93 254.71 541.5 491.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +161.96 257 535.92 496.57 R +7 X +V +0 X +N +167.21 259.13 528.49 493.22 R +7 X +V +4 9 Q +0 X +(CDEV_WARNING:) 167.21 487.22 T +7 F +(Failure of the request in non-critical.) 280.61 487.22 T +4 F +(CDEV_SUCCESS:) 167.21 476.22 T +7 F +(The message was processed successfully.) 280.61 476.22 T +4 F +(CDEV_ERROR:) 167.21 465.22 T +7 F +( Failed to process message.) 275.21 465.22 T +4 F +(CDEV_INVALIDOBJ:) 167.21 454.22 T +7 F +( Invalid cdev request object used.) 269.81 454.22 T +4 F +(CDEV_INVALIDARG:) 167.21 443.22 T +7 F +(Invalid argument passed to cdev call) 280.61 443.22 T +8 F +(.) 475.01 443.22 T +4 F +(CDEV_INVALIDSVC:) 167.21 432.22 T +7 F +( Wrong service during dynamic loading.) 275.21 432.22 T +4 F +(CDEV_INVALIDOP:) 167.21 421.22 T +7 F +( Operation is not supported on device.) 275.21 421.22 T +4 F +(CDEV_NOTCONNECTED:) 167.21 410.22 T +7 F +( Not connected to low level network) 275.21 410.22 T +8 F +( service.) 167.21 399.22 T +4 F +(CDEV_IOFAILED:) 167.21 388.22 T +7 F +(Low level network service IO failed.) 280.61 388.22 T +4 F +(CDEV_CONFLICT:) 167.21 377.22 T +7 F +( Conflicts of data types or tags.) 275.21 377.22 T +4 F +(CDEV_NOTFOUND:) 167.21 366.22 T +7 F +(Cannot find specified data in cdevData.) 280.61 366.22 T +4 F +(CDEV_TIMEOUT:) 167.21 355.22 T +7 F +( Time out) 269.81 355.22 T +6 F +(.) 323.81 355.22 T +4 F +(CDEV_CONVERT:) 167.21 344.22 T +7 F +( cdevData conversion error.) 275.21 344.22 T +4 F +(CDEV_OUTOFRANGE:) 167.21 333.22 T +7 F +( Value out of range for device attribute.) 275.21 333.22 T +4 F +(CDEV_NOACCESS:) 167.21 322.22 T +7 F +( Insufficient access to perform request.) 275.21 322.22 T +4 F +(CDEV_ACCESSCHANGED:) 167.21 311.22 T +7 F +(Change in access permission of device.) 280.61 311.22 T +4 F +(CDEV_DISCONNECTED:) 167.21 300.22 T +7 F +( The service has lost contact with the) 275.21 300.22 T +8 F +( device.) 167.21 289.22 T +4 F +(CDEV_RECONNECTED:) 167.21 278.22 T +7 F +( The service has regained contact with) 275.21 278.22 T +( the device.) 167.21 267.22 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "20" 30 +%%Page: "21" 31 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. The cde) 459.01 739 T +(vDe) 501.26 739 T +(vice Class) 517 739 T +0 10 Q +(21) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(sendCallbac) 180 713.33 T +(k) 238.71 713.33 T +3 F +(int sendCallbac) 279.29 713.33 T +(k \050) 347.45 713.33 T +(char *msg,) 358.56 713.33 T +(cde) 411.91 713.33 T +(vData &out,) 427.73 713.33 T +(cde) 351.57 701.33 T +(vCallbac) 367.39 701.33 T +(k &callbac) 405.53 701.33 T +(k\051;) 450.9 701.33 T +(int sendCallbac) 279.29 689.33 T +(k \050) 347.45 689.33 T +(char *msg, cde) 358.56 689.33 T +(vData *out,) 424.95 689.33 T +(cde) 351.57 677.33 T +(vCallbac) 367.39 677.33 T +(k &callbac) 405.53 677.33 T +(k\051;) 450.9 677.33 T +0 F +6.06 (The sendCallbac) 279.29 660.33 P +6.06 (k function is the standard method f) 360.18 660.33 P +6.06 (or) 549.11 660.33 P +3.54 (asynchronously comm) 279.43 648.33 P +3.54 (unicating with a de) 382.34 648.33 P +3.54 (vice) 475.48 648.33 P +3.54 (. Rather than) 493.11 648.33 P +1.95 (pro) 279.43 636.33 P +1.95 (viding a result cde) 293.73 636.33 P +1.95 (vData object, this method requires the) 379.86 636.33 P +2.49 (user to pro) 279.43 624.33 P +2.49 (vide the address of a cde) 332.07 624.33 P +2.49 (vCallbac) 455.96 624.33 P +2.49 (k object. This) 494.1 624.33 P +1.4 (object contains a user supplied pointer and the address of a) 279.43 612.33 P +3.42 (function to call when the message has been successfully) 279.43 600.33 P +(processed.) 279.43 588.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "21" 31 +%%Page: "22" 32 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. The cde) 54 739 T +(vError Class) 96.25 739 T +0 10 Q +(22) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(6.) 141.32 710.67 T +(The cde) 162 710.67 T +(vErr) 214.7 710.67 T +(or Class) 242.43 710.67 T +2 10 Q +(Over) 54 673.33 T +(vie) 76.89 673.33 T +(w of the) 90.64 673.33 T +(cde) 54 661.33 T +(vErr) 71.08 661.33 T +(or Class) 90.89 661.33 T +0 F +2.6 (The) 162 673.33 P +3 F +2.6 (cde) 184.61 673.33 P +2.6 (vError) 200.43 673.33 P +0 F +2.6 (C++ class is an abstr) 233.03 673.33 P +2.6 (act base class that pro) 336.7 673.33 P +2.6 (vides error handling) 446.99 673.33 P +0.06 (ser) 162 661.33 P +0.06 (vices that are used b) 176.19 661.33 P +0.06 (y both the cde) 268.49 661.33 P +0.06 (vSer) 331.18 661.33 P +0.06 (vice object and the cde) 352.04 661.33 P +0.06 (vSystem object. It\325) 454.25 661.33 P +0.06 (s) 535 661.33 P +(constr) 162 649.33 T +(uctors are protected to pre) 189.38 649.33 T +(v) 306.36 649.33 T +(ent it from being instantiated directly) 311.11 649.33 T +(.) 470.18 649.33 T +3 9 Q +(Figure 7: Object model of the cde) 162 616 T +(vError class) 297.3 616 T +2 10 Q +(Pub) 54 410.33 T +(lic Methods of) 72.79 410.33 T +(the cde) 54 398.33 T +(vErr) 88.86 398.33 T +(or) 108.67 398.33 T +(Class) 54 386.33 T +(autoErr) 162 410.33 T +(orOn) 197.36 410.33 T +3 F +(int autoErrorOn \050v) 261.29 410.33 T +(oid\051;) 340.51 410.33 T +0 F +-0.21 (Inf) 261.29 393.33 P +-0.21 (or) 272.11 393.33 P +-0.21 (ms the cde) 281.25 393.33 P +-0.21 (vError class that it should use its inter) 329.43 393.33 P +-0.21 (nal def) 494.37 393.33 P +-0.21 (ault) 523.88 393.33 P +5.59 (error handler to process an) 261.43 381.33 P +5.59 (y error messages that are) 403.7 381.33 P +3.17 (gener) 261.43 369.33 P +3.17 (ated b) 286.9 369.33 P +3.17 (y objects within its control. This is the def) 317.67 369.33 P +3.17 (ault) 523.88 369.33 P +(oper) 261.43 357.33 T +(ating condition f) 281.34 357.33 T +(or the class) 351.08 357.33 T +(.) 402.06 357.33 T +2 F +(autoErr) 162 333.33 T +(orOff) 197.36 333.33 T +3 F +(int autoErrorOff \050v) 261.29 333.33 T +(oid\051;) 340.51 333.33 T +0 F +0 (Inf) 261.29 316.33 P +0 (or) 272.11 316.33 P +0 (ms the cde) 281.25 316.33 P +0 (vError class that it should use the user supplied) 329.87 316.33 P +0.28 (error handling function to process an) 261.43 304.33 P +0.28 (y error messages that are) 424.96 304.33 P +(gener) 261.43 292.33 T +(ated b) 286.9 292.33 T +(y objects within its control.) 314.5 292.33 T +2 F +(repor) 162 268.33 T +(tErr) 187.76 268.33 T +(or) 205.34 268.33 T +3 F +(int repor) 261.29 268.33 T +(tError \050) 298.37 268.33 T +(int se) 332.86 268.33 T +(v) 356.46 268.33 T +(er) 361.21 268.33 T +(ity) 370.25 268.33 T +(, char *name) 379.25 268.33 T +(,) 435.79 268.33 T +(cde) 332.86 256.33 T +(vRequestObject *obj,) 348.68 256.33 T +(char *f) 332.86 244.33 T +(or) 361.46 244.33 T +(matStr) 370.6 244.33 T +(ing,...\051;) 400.2 244.33 T +0 F +4.13 (Emits an error message) 261.29 227.33 P +4.13 (. The se) 379.68 227.33 P +4.13 (v) 423.77 227.33 P +4.13 (er) 428.52 227.33 P +4.13 (ity \336eld indicates the) 437.56 227.33 P +3 F +1.09 (se) 261.43 215.33 P +1.09 (v) 271.69 215.33 P +1.09 (er) 276.44 215.33 P +1.09 (ity) 285.48 215.33 P +0 F +1.09 ( of the error) 295.48 215.33 P +1.09 (, the) 349.93 215.33 P +3 F +1.09 (name) 374.34 215.33 P +0 F +1.09 ( str) 399.35 215.33 P +1.09 (ing identi\336es the object that) 414.48 215.33 P +11.86 (gener) 261.43 203.33 P +11.86 (ated the error) 286.9 203.33 P +11.86 (, the) 370.16 203.33 P +3 F +11.86 (obj) 416.13 203.33 P +0 F +11.86 (par) 444.12 203.33 P +11.86 (ameter is the) 458.47 203.33 P +1.32 (cde) 261.43 191.33 P +1.32 (vRequestObject that w) 277.25 191.33 P +1.32 (as in use when the error occurred,) 380.34 191.33 P +0.71 (and the) 261.43 179.33 P +3 F +0.71 (f) 298.99 179.33 P +0.71 (or) 301.47 179.33 P +0.71 (matStr) 310.61 179.33 P +0.71 (ing) 340.21 179.33 P +0 F +0.71 (and additional par) 357.03 179.33 P +0.71 (ameters \050...\051 should be) 437.84 179.33 P +2.71 (f) 261.43 167.33 P +2.71 (or) 263.91 167.33 P +2.71 (matted in the same manner as the par) 273.05 167.33 P +2.71 (ameters used b) 460.87 167.33 P +2.71 (y) 535 167.33 P +(pr) 261.43 155.33 T +(intf) 270.47 155.33 T +(.) 283.51 155.33 T +0.9 (The integer used b) 261.29 138.33 P +0.9 (y se) 347.16 138.33 P +0.9 (v) 366.09 138.33 P +0.9 (er) 370.84 138.33 P +0.9 (ity should ha) 379.88 138.33 P +0.9 (v) 437.61 138.33 P +0.9 (e one of the f) 442.36 138.33 P +0.9 (ollo) 504.03 138.33 P +0.9 (wing) 519.44 138.33 P +(v) 261.43 126.33 T +(alues indicating the se) 266.18 126.33 T +(v) 364.82 126.33 T +(er) 369.57 126.33 T +(ity of the error that has occurred.) 378.61 126.33 T +2 F +(CDEV_SEVERITY_INFO) 261.29 109.33 T +0 F +(No error) 401.31 109.33 T +(.) 437.48 109.33 T +162 436 540 680 C +162 453 540 613 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +161.21 453 540.79 613 R +7 X +0 0 0 1 0 0 0 K +V +167.45 458 539.12 605.5 R +0 X +V +0.5 H +2 Z +N +163.62 461.83 535.29 609.33 R +7 X +V +0 X +N +192.04 487.25 506.87 583.92 R +7 X +V +0 X +N +196.37 491.58 501.37 580.75 R +7 X +V +4 9 Q +0 X +(class cdevError) 308.37 574.75 T +(methods:) 196.37 563.75 T +(autoErrorOn \050 void \051 {virtual} : int) 214.7 552.75 T +(autoErrorOff \050 void \051 {virtual} : int) 214.7 541.75 T +(reportError \050 ... \051 {virtual} : int) 214.7 530.75 T +(setErrorHandler \050cdevErrorHandler \051 {virtual} : void) 214.7 519.75 T +(setThreshold \050 int \051 {virtual} : void) 214.7 508.75 T +-0.61 (className \050 void \051 {virtual} : char *) 214.7 497.75 P +192.2 571.25 506.7 571.25 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +162 436 540 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "22" 32 +%%Page: "23" 33 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. The cde) 466.24 739 T +(vError Class) 508.5 739 T +0 10 Q +(23) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_SEVERITY_W) 278.45 710.83 T +(ARN) 375.65 710.83 T +0 F +(An error occurred that should) 418.47 710.83 T +(not impact contin) 418.84 698.83 T +(ued) 494.33 698.83 T +(processing.) 418.84 686.83 T +2 F +(CDEV_SEVERITY_ERR) 278.45 669.83 T +(OR) 387.73 669.83 T +0 F +(An error occurred and should) 418.47 669.83 T +(be corrected bef) 418.84 657.83 T +(ore contin) 490.8 657.83 T +(uing.) 534.61 657.83 T +2 F +(CDEV_SEVERITY_SEVERE) 278.45 640.83 T +0 F +(A se) 418.47 640.83 T +(v) 438.18 640.83 T +(ere or f) 442.93 640.83 T +(atal error has) 474.31 640.83 T +(occurred and cde) 418.84 628.83 T +(v cannot) 495.8 628.83 T +(contin) 418.84 616.83 T +(ue nor) 445.42 616.83 T +(mal e) 474.02 616.83 T +(x) 498.17 616.83 T +(ecution.) 502.87 616.83 T +2 F +(setErr) 179.17 592.83 T +(orHandler) 207.87 592.83 T +3 F +(v) 278.45 592.83 T +(oid setErrorHandler \050cde) 283.2 592.83 T +(vErrorHandler handler\051;) 391.83 592.83 T +0 F +2.41 (Used to to install a user speci\336ed error handler) 278.45 575.83 P +2.41 (. This error) 504 575.83 P +0.68 (handler will be called when an error occurs if the) 278.6 563.83 P +3 F +0.68 (autoErrorOff) 502.15 563.83 P +0 F +0 (method has been used to disab) 278.6 551.83 P +0 (le the def) 417.91 551.83 P +0 (ault error handler) 458.75 551.83 P +0 (. The) 534.38 551.83 P +6.28 (user pro) 278.6 539.83 P +6.28 (vided error handler should ha) 321.41 539.83 P +6.28 (v) 476.39 539.83 P +6.28 (e the f) 481.14 539.83 P +6.28 (ollo) 521.2 539.83 P +6.28 (wing) 536.61 539.83 P +(prototype:) 278.6 527.83 T +3 F +(v) 278.45 510.83 T +(oid handler \050int se) 283.2 510.83 T +(v) 362.39 510.83 T +(er) 367.14 510.83 T +(ity) 376.17 510.83 T +(, char *te) 385.17 510.83 T +(xt, cde) 424.89 510.83 T +(vRequestObject *obj\051;) 454.05 510.83 T +0 F +4.89 (The) 278.45 493.83 P +3 F +4.89 (se) 303.35 493.83 P +4.89 (v) 313.61 493.83 P +4.89 (er) 318.36 493.83 P +4.89 (ity) 327.4 493.83 P +0 F +4.89 ( par) 337.4 493.83 P +4.89 (ameter will contain one of the integers) 359.42 493.83 P +0.81 (speci\336ed in the) 278.6 481.83 P +3 F +0.81 (repor) 350.51 481.83 P +0.81 (tError) 374.25 481.83 P +0 F +0.81 (documentation, the) 402.84 481.83 P +3 F +0.81 (te) 492.29 481.83 P +0.81 (xt) 500.33 481.83 P +0 F +0.81 ( par) 508.11 481.83 P +0.81 (ameter) 526.05 481.83 P +2.11 (will contain the te) 278.6 469.83 P +2.11 (xt of the error) 361.34 469.83 P +2.11 (, and the) 426.65 469.83 P +3 F +2.11 (obj) 474.69 469.83 P +0 F +2.11 ( par) 488.03 469.83 P +2.11 (ameter will) 507.27 469.83 P +0.37 (contain the cde) 278.6 457.83 P +0.37 (vRequestObject that w) 346.86 457.83 P +0.37 (as in use when the error) 448.05 457.83 P +(occurred.) 278.6 445.83 T +2 F +(setThreshold) 179.17 421.83 T +3 F +(v) 278.45 421.83 T +(oid setThreshold \050int errorThreshold\051;) 283.2 421.83 T +0 F +0.77 (Used to specify the le) 278.45 404.83 P +0.77 (v) 376.82 404.83 P +0.77 (el of se) 381.57 404.83 P +0.77 (v) 415.05 404.83 P +0.77 (er) 419.8 404.83 P +0.77 (ity at which errors should be) 428.84 404.83 P +2.4 (submitted to the error handler) 278.6 392.83 P +2.4 (. The v) 418.87 392.83 P +2.4 (alue of) 453.99 392.83 P +3 F +2.4 (errorThreshold) 491.6 392.83 P +0 F +0.23 (should be one of the se) 278.6 380.83 P +0.23 (v) 383.42 380.83 P +0.23 (er) 388.17 380.83 P +0.23 (ity le) 397.21 380.83 P +0.23 (v) 417.7 380.83 P +0.23 (els speci\336ed in the) 422.45 380.83 P +3 F +0.23 (repor) 508.43 380.83 P +0.23 (tError) 532.17 380.83 P +0 F +(method.) 278.6 368.83 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "23" 33 +%%Page: "24" 34 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. The cde) 54 739 T +(vGroup Class) 96.25 739 T +0 10 Q +(24) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(7.) 141.32 710.67 T +(The cde) 162 710.67 T +(vGr) 214.7 710.67 T +(oup Class) 238.54 710.67 T +2 10 Q +(Over) 54 673.33 T +(vie) 76.89 673.33 T +(w of the) 90.64 673.33 T +(cde) 54 661.33 T +(vGr) 71.08 661.33 T +(oup Class) 88.11 661.33 T +0 F +-0.21 (The) 162 673.33 P +3 F +-0.21 (cde) 181.8 673.33 P +-0.21 (vGroup) 197.62 673.33 P +0 F +-0.21 (C++ class pro) 232.98 673.33 P +-0.21 (vides the mechanisms that cde) 294.1 673.33 P +-0.21 (v uses to collect together) 430.23 673.33 P +0.44 (a list of oper) 162 661.33 P +0.44 (ations to be e) 217.69 661.33 P +0.44 (x) 278.75 661.33 P +0.44 (ecuted, perhaps repeatedly) 283.45 661.33 P +0.44 (, as a g) 404.51 661.33 P +0.44 (roup) 438.52 661.33 P +0.44 (, and to detect the) 458.18 661.33 P +(completion of m) 162 649.33 T +(ultiple requests that f) 232.48 649.33 T +(or) 324.45 649.33 T +(m a g) 333.59 649.33 T +(roup) 358.5 649.33 T +(.) 378.16 649.33 T +3 9 Q +(Figure 8: Object model of the cde) 162 616 T +(vGroup class) 297.3 616 T +2 10 Q +(Pub) 54 317.83 T +(lic Methods of) 72.79 317.83 T +(the cde) 54 305.83 T +(vGr) 88.86 305.83 T +(oup) 105.89 305.83 T +(Class) 54 293.83 T +(cde) 162 317.83 T +(vGr) 179.08 317.83 T +(oup) 196.11 317.83 T +3 F +(cde) 261.29 317.83 T +(vGroup \050unsigned b) 277.11 317.83 T +(loc) 364.73 317.83 T +(kSiz) 377.31 317.83 T +(e) 396.05 317.83 T +(, cde) 401.46 317.83 T +(vSystem& system\051;) 422.84 317.83 T +0 F +0.99 (This is the constr) 261.29 300.83 P +0.99 (uctor f) 339.97 300.83 P +0.99 (or the cde) 368.45 300.83 P +0.99 (vGroup object. It receiv) 414.59 300.83 P +0.99 (es a) 520.11 300.83 P +1.1 (b) 261.43 288.83 P +1.1 (loc) 266.79 288.83 P +1.1 (kSiz) 279.37 288.83 P +1.1 (e par) 298.11 288.83 P +1.1 (ameter which speci\336es the maxim) 321.9 288.83 P +1.1 (um n) 476.22 288.83 P +1.1 (umber of) 499.44 288.83 P +2.3 (cde) 261.43 276.83 P +2.3 (vT) 277.25 276.83 P +2.3 (r) 287.16 276.83 P +2.3 (anObj objects that ma) 290.39 276.83 P +2.3 (y be added and a cde) 394.27 276.83 P +2.3 (vSystem) 501.66 276.83 P +1.25 (par) 261.43 264.83 P +1.25 (ameter that the g) 275.78 264.83 P +1.25 (roup object will be associated with. If no) 355.04 264.83 P +9.4 (par) 261.43 252.83 P +9.4 (ameters are speci\336ed b) 275.78 252.83 P +9.4 (loc) 407.71 252.83 P +9.4 (kSiz) 420.3 252.83 P +9.4 (e will be set to) 439.04 252.83 P +5.68 (DEF) 261.43 240.83 P +5.68 (A) 280.63 240.83 P +5.68 (UL) 286.8 240.83 P +5.68 (T_BLOCK_SIZE and the system will be set to) 298.48 240.83 P +3.23 (cde) 261.43 228.83 P +3.23 (vSystem::def) 277.25 228.83 P +3.23 (aultSystem\050\051. The mode of the constr) 334.75 228.83 P +3.23 (ucted) 515.54 228.83 P +(g) 261.43 216.83 T +(roup will be CDEV_EXEC_IMMEDIA) 266.89 216.83 T +(TE.) 427.95 216.83 T +2 F +(star) 162 192.83 T +(t) 180.54 192.83 T +3 F +(int star) 261.29 192.83 T +(t \050v) 291.7 192.83 T +(oid\051;) 305.34 192.83 T +0 F +1.69 (Star) 261.29 175.83 P +1.69 (ts a g) 280.03 175.83 P +1.69 (roup of tr) 307.76 175.83 P +1.69 (ansactions) 351.06 175.83 P +1.69 (. This means that each time a) 398.71 175.83 P +1.67 (message is sent) 261.43 163.83 P +3 F +1.67 (asynchronously) 341.46 163.83 P +0 F +1.67 ( to a de) 410.93 163.83 P +1.67 (vice) 448.99 163.83 P +1.67 (, the associated) 466.62 163.83 P +3 F +0 (cde) 261.43 151.83 P +0 (vT) 277.25 151.83 P +0 (r) 287.16 151.83 P +0 (anObj) 290.39 151.83 P +0 F +0 (will be included in this g) 319.85 151.83 P +0 (roup) 424.77 151.83 P +0 (. The system will stop) 444.43 151.83 P +2.25 (adding tr) 261.43 139.83 P +2.25 (ansactions to this g) 302.5 139.83 P +2.25 (roup after the) 394.76 139.83 P +3 F +2.25 (end) 463.78 139.83 P +0 F +2.25 ( method has) 480.46 139.83 P +(been e) 261.43 127.83 T +(x) 291.71 127.83 T +(ecuted.) 296.41 127.83 T +2.49 (If the mode of the g) 261.29 110.83 P +2.49 (roup is CDEV_EXEC_IMMEDIA) 359.8 110.83 P +2.49 (TE, the) 505.27 110.83 P +0.22 (oper) 261.43 98.83 P +0.22 (ations are immediately f) 281.34 98.83 P +0.22 (orw) 387.31 98.83 P +0.22 (arded to the ser) 403.27 98.83 P +0.22 (vice and to the) 474.28 98.83 P +8.15 (appropr) 261.43 86.83 P +8.15 (iate ser) 296.04 86.83 P +8.15 (v) 337.28 86.83 P +8.15 (er) 342.03 86.83 P +8.15 (. If the mode of the g) 350.42 86.83 P +8.15 (roup is) 501.84 86.83 P +162 343.5 540 680 C +162 360.5 540 613 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +161.21 360.5 540.79 613 R +7 X +0 0 0 1 0 0 0 K +V +167.45 363.83 539.12 605.5 R +0 X +V +0.5 H +2 Z +N +163.62 366.83 535.29 609.33 R +7 X +V +0 X +N +286.62 577.58 412.29 592.58 R +7 X +V +0 X +N +290.95 581.08 407.62 589.42 R +7 X +V +4 9 Q +0 X +(class cdevSync) 311.49 583.42 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +340.79 557.92 349.45 570.58 358.12 557.92 3 Y +7 X +V +0.1 H +0 X +N +349.45 570.58 349.45 577.58 2 L +N +349.45 548.3 349.45 557.58 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +224.12 372.25 474.79 548.08 R +7 X +V +0.5 H +0 X +N +229.87 378.15 469.87 543.77 R +7 X +V +0 X +(class cdevGroup) 309.37 537.77 T +(methods:) 229.87 526.77 T +(start \050void\051 : int) 243.2 515.77 T +(end \050void\051 : int) 243.2 504.77 T +(flush \050void\051 : int) 243.2 493.77 T +(poll \050void\051 : int) 243.2 482.77 T +(pend \050int\051 : int) 243.2 471.77 T +(pend \050double, int\051 : int) 243.2 460.77 T +(allFinished \050void\051 : int) 243.2 449.77 T +(status \050int *, int &\051 : int) 243.2 438.77 T +-0.01 (className \050void\051 : char *) 243.2 427.77 P +(execDeferred \050void\051 : int) 243.2 416.77 T +(execImmediate \050void\051 : int) 243.2 405.77 T +(executionMode \050void\051 : int) 243.2 394.77 T +(readyToExec \050void\051 : int) 243.2 383.77 T +224.37 534.17 474.53 534.17 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +162 343.5 540 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "24" 34 +%%Page: "25" 35 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. The cde) 461.23 739 T +(vGroup Class) 503.49 739 T +0 10 Q +(25) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.07 (CDEV_EXEC_DEFERRED) 279.43 713.33 P +0.07 (, the oper) 399.86 713.33 P +0.07 (ation is k) 442.16 713.33 P +0.07 (ept in a list within) 481.57 713.33 P +-0.09 (the g) 279.43 701.33 P +-0.09 (roup) 301.48 701.33 P +-0.09 (, and sent to the ser) 321.14 701.33 P +-0.09 (vice/ser) 409.38 701.33 P +-0.09 (v) 444.13 701.33 P +-0.09 (er when \337ush\050\051 or pend\050\051) 448.88 701.33 P +(is called.) 279.43 689.33 T +2 F +(end) 180 665.33 T +3 F +(int end \050v) 279.29 665.33 T +(oid\051;) 320.17 665.33 T +0 F +1.3 (Inf) 279.29 648.33 P +1.3 (or) 290.11 648.33 P +1.3 (ms the system that no more ne) 299.25 648.33 P +1.3 (w tr) 444.14 648.33 P +1.3 (ansactions should be) 461.45 648.33 P +(included in this g) 279.43 636.33 T +(roup object.) 353.81 636.33 T +2 F +(\337ush) 180 612.33 T +3 F +(int \337ush \050v) 279.29 612.33 T +(oid\051;) 324.61 612.33 T +0 F +2.79 (Flushes an) 279.29 595.33 P +2.79 (y pending outbound requests to their respectiv) 330.84 595.33 P +2.79 (e) 552.44 595.33 P +(ser) 279.43 583.33 T +(vices) 293.62 583.33 T +(.) 316.25 583.33 T +1.7 (If the g) 279.29 566.33 P +1.7 (roup is in def) 313.17 566.33 P +1.7 (erred e) 375.23 566.33 P +1.7 (x) 408.32 566.33 P +1.7 (ecution mode) 413.02 566.33 P +1.7 (, and the g) 474.6 566.33 P +1.7 (rouped) 526.87 566.33 P +-0.08 (commands ha) 279.43 554.33 P +-0.08 (v) 341.95 554.33 P +-0.08 (e either not y) 346.7 554.33 P +-0.08 (et been \337ushed, or ha) 404.07 554.33 P +-0.08 (v) 500.28 554.33 P +-0.08 (e pre) 505.03 554.33 P +-0.08 (viously) 527.44 554.33 P +0.94 (been \337ushed and ha) 279.43 542.33 P +0.94 (v) 372.68 542.33 P +0.94 (e all completed, then \337ush will send the) 377.43 542.33 P +0.74 (commands to the under) 279.43 530.33 P +0.74 (lying ser) 386.86 530.33 P +0.74 (vices) 425.13 530.33 P +0.74 (. After completion, \337ush) 447.76 530.33 P +(ma) 279.43 518.33 T +(y be called again to re-e) 293.02 518.33 T +(x) 399.44 518.33 T +(ecute the g) 404.14 518.33 T +(rouped commands) 453.52 518.33 T +(.) 536.18 518.33 T +2 F +(poll) 180 494.33 T +3 F +(int poll \050v) 279.29 494.33 T +(oid\051;) 319.05 494.33 T +0 F +1.09 (Directly polls each of the cde) 279.29 477.33 P +1.09 (vGroup\325) 412.26 477.33 P +1.09 (s under) 446.77 477.33 P +1.09 (lying ser) 481.36 477.33 P +1.09 (vices f) 519.98 477.33 P +1.09 (or) 549.11 477.33 P +3.66 (activity) 279.43 465.33 P +3.66 (, and deliv) 308.99 465.33 P +3.66 (ers an) 361.64 465.33 P +3.66 (y asynchronous callbac) 392.94 465.33 P +3.66 (ks that are) 503.99 465.33 P +(ready) 279.43 453.33 T +(.) 303.44 453.33 T +2 F +(pend) 180 429.33 T +3 F +(int pend \050int fd\051;) 279.29 429.33 T +0 F +0.89 (A) 279.29 412.33 P +0.89 (utomatically end and \337ush the g) 285.66 412.33 P +0.89 (roup if it is star) 430.66 412.33 P +0.89 (ted, and w) 499.66 412.33 P +0.89 (ait) 547.44 412.33 P +1.75 (until all oper) 279.43 400.33 P +1.75 (ations within the g) 336.75 400.33 P +1.75 (roup are completed or until a) 421.95 400.33 P +(timeout occurs) 279.43 388.33 T +(.) 344.3 388.33 T +0.55 (In par) 279.29 371.33 P +0.55 (ticular) 305.8 371.33 P +0.55 (: w) 332.77 371.33 P +0.55 (aits f) 345.95 371.33 P +0.55 (or a def) 367.32 371.33 P +0.55 (ault per) 402.02 371.33 P +0.55 (iod of time f) 436.07 371.33 P +0.55 (or the speci\336ed) 489.1 371.33 P +1.11 (\336le descr) 279.43 359.33 P +1.11 (iptor to ha) 320.7 359.33 P +1.11 (v) 367.18 359.33 P +1.11 (e an I/O e) 371.93 359.33 P +1.11 (v) 418.87 359.33 P +1.11 (ent. If the fd par) 423.62 359.33 P +1.11 (ameter is not) 497.99 359.33 P +-0.05 (pro) 279.43 347.33 P +-0.05 (vided, the cde) 293.73 347.33 P +-0.05 (vGroup object will w) 355.6 347.33 P +-0.05 (ait f) 444.21 347.33 P +-0.05 (or an I/O e) 459.99 347.33 P +-0.05 (v) 506.8 347.33 P +-0.05 (ent on an) 511.55 347.33 P +-0.05 (y) 553 347.33 P +0.62 (of its contained \336le descr) 279.43 335.33 P +0.62 (iptors) 392.11 335.33 P +0.62 (. When an e) 416.42 335.33 P +0.62 (v) 471.9 335.33 P +0.62 (ent occurs on one) 476.65 335.33 P +3.88 (of the \336le descr) 279.43 323.33 P +3.88 (iptors) 359.02 323.33 P +3.88 (, the cde) 383.32 323.33 P +3.88 (vGroup object will call the) 429.13 323.33 P +0.69 (respectiv) 279.43 311.33 P +0.69 (e cde) 319.19 311.33 P +0.69 (vSer) 344.04 311.33 P +0.69 (vice to process the e) 364.9 311.33 P +0.69 (v) 459.06 311.33 P +0.69 (ent and dispatch an) 463.81 311.33 P +0.69 (y) 553 311.33 P +(asynchronous callbac) 279.43 299.33 T +(ks that are ready) 375.38 299.33 T +(.) 448.86 299.33 T +2 F +(pend) 180 275.33 T +3 F +(int pend \050doub) 279.29 275.33 T +(le seconds) 343.02 275.33 T +(, int fd\051;) 390.67 275.33 T +0 F +0.89 (A) 279.29 258.33 P +0.89 (utomatically end and \337ush the g) 285.66 258.33 P +0.89 (roup if it is star) 430.66 258.33 P +0.89 (ted, and w) 499.66 258.33 P +0.89 (ait) 547.44 258.33 P +1.75 (until all oper) 279.43 246.33 P +1.75 (ations within the g) 336.75 246.33 P +1.75 (roup are completed or until a) 421.95 246.33 P +(timeout occurs) 279.43 234.33 T +(.) 344.3 234.33 T +2.2 (In par) 279.29 217.33 P +2.2 (ticular) 307.46 217.33 P +2.2 (, processes all I/O e) 333.63 217.33 P +2.2 (v) 430.51 217.33 P +2.2 (ents that occur on the \336le) 435.26 217.33 P +4.73 (descr) 279.43 205.33 P +4.73 (iptor dur) 304.03 205.33 P +4.73 (ing the speci\336ed per) 345.6 205.33 P +4.73 (iod of time) 449.43 205.33 P +4.73 (. If the fd) 504.88 205.33 P +-0.22 (par) 279.43 193.33 P +-0.22 (ameter is not pro) 293.78 193.33 P +-0.22 (vided, the cde) 368 193.33 P +-0.22 (vGroup object will w) 429.52 193.33 P +-0.22 (ait f) 517.61 193.33 P +-0.22 (or I/O) 533.21 193.33 P +1.34 (e) 279.43 181.33 P +1.34 (v) 284.69 181.33 P +1.34 (ents on all of its contained \336le descr) 289.44 181.33 P +1.34 (iptors) 457.4 181.33 P +1.34 (. When an e) 481.7 181.33 P +1.34 (v) 539.35 181.33 P +1.34 (ent) 544.1 181.33 P +0.38 (occurs on one of the \336le descr) 279.43 169.33 P +0.38 (iptors) 415.23 169.33 P +0.38 (, the cde) 439.53 169.33 P +0.38 (vGroup object will) 478.34 169.33 P +3.73 (call the respectiv) 279.43 157.33 P +3.73 (e cde) 361.1 157.33 P +3.73 (vSer) 388.99 157.33 P +3.73 (vice to process the e) 409.85 157.33 P +3.73 (v) 516.16 157.33 P +3.73 (ent and) 520.91 157.33 P +(dispatch an) 279.43 145.33 T +(y asynchronous callbac) 330.42 145.33 T +(ks that are ready) 434.15 145.33 T +(.) 507.63 145.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "25" 35 +%%Page: "26" 36 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. The cde) 54 739 T +(vGroup Class) 96.25 739 T +0 10 Q +(26) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(allFinished) 162 713.33 T +3 F +(int allFinished \050v) 261.29 713.33 T +(oid\051;) 333.28 713.33 T +0 F +1.16 (Chec) 261.29 696.33 P +1.16 (ks the status of the cde) 284.43 696.33 P +1.16 (vGroup object to deter) 392.77 696.33 P +1.16 (mine if all) 495.45 696.33 P +0.06 (tr) 261.43 684.33 P +0.06 (ansactions ha) 267.44 684.33 P +0.06 (v) 329.01 684.33 P +0.06 (e been completed. Retur) 333.76 684.33 P +0.06 (ns 1 if all tr) 443.7 684.33 P +0.06 (ansactions) 492.2 684.33 P +(are complete or 0 if the) 261.43 672.33 T +(y are not.) 363.5 672.33 T +2 F +(status) 162 648.33 T +3 F +(int status \050int status[], int &n) 261.29 648.33 T +(umT) 384.03 648.33 T +(r) 402.83 648.33 T +(ansactions\051;) 406.06 648.33 T +0 F +1.62 (Retr) 261.29 631.33 P +1.62 (ie) 280.33 631.33 P +1.62 (v) 287.81 631.33 P +1.62 (es the status of the individual tr) 292.56 631.33 P +1.62 (ansaction objects that) 440.04 631.33 P +0.99 (are stored within the) 261.43 619.33 P +3 F +0.99 (cde) 358.22 619.33 P +0.99 (vGroup) 374.04 619.33 P +0 F +0.99 ( object. The cde) 406.83 619.33 P +0.99 (vGroup class) 480.66 619.33 P +0.66 (will populate the) 261.43 607.33 P +3 F +0.66 (status) 337.9 607.33 P +0 F +0.66 ( arr) 364.58 607.33 P +0.66 (a) 380.14 607.33 P +0.66 (y with up to) 385.4 607.33 P +3 F +0.66 (n) 441.41 607.33 P +0.66 (umT) 446.87 607.33 P +0.66 (r) 465.67 607.33 P +0.66 (ansactions) 468.9 607.33 P +0 F +0.66 (. The) 516.55 607.33 P +3 F +1.18 (n) 261.43 595.33 P +1.18 (umT) 266.89 595.33 P +1.18 (r) 285.69 595.33 P +1.18 (ansactions) 288.92 595.33 P +0 F +1.18 ( par) 336.72 595.33 P +1.18 (ameter will then be set to the n) 355.03 595.33 P +1.18 (umber of) 499.36 595.33 P +1.61 (tr) 261.43 583.33 P +1.61 (ansactions that w) 267.44 583.33 P +1.61 (ere actually loaded. If a) 347.83 583.33 P +3 F +1.61 (status) 462.05 583.33 P +0 F +1.61 ( entr) 488.73 583.33 P +1.61 (y is 0,) 510.66 583.33 P +0.94 (then the associated tr) 261.43 571.33 P +0.94 (ansaction has been completed. Retur) 359.77 571.33 P +0.94 (ns) 529.44 571.33 P +16.99 (CDEV_SUCCESS on successful completion, or) 261.43 559.33 P +(CDEV_INV) 261.43 547.33 T +(ALID) 310.64 547.33 T +(ARG if the) 332.47 547.33 T +3 F +(status) 381.38 547.33 T +0 F +( arr) 408.06 547.33 T +(a) 422.96 547.33 T +(y is too small.) 428.22 547.33 T +2 F +(e) 162 523.33 T +(x) 167.41 523.33 T +(ecDef) 172.87 523.33 T +(erred) 200 523.33 T +3 F +(int e) 261.29 523.33 T +(x) 279.89 523.33 T +(ecDef) 284.59 523.33 T +(erred \050v) 310.41 523.33 T +(oid\051;) 344.61 523.33 T +2 F +(e) 162 499.33 T +(x) 167.41 499.33 T +(ecImmediate) 172.87 499.33 T +3 F +(int e) 261.29 499.33 T +(x) 279.89 499.33 T +(ecImmediate \050v) 284.59 499.33 T +(oid\051;) 352.69 499.33 T +0 F +0.92 (Changes the beha) 261.29 482.33 P +0.92 (viour of e) 348.34 482.33 P +0.92 (x) 391.01 482.33 P +0.92 (ecution of commands inside the) 395.71 482.33 P +0.41 (g) 261.43 470.33 P +0.41 (roup) 266.89 470.33 P +0.41 (. e) 286.55 470.33 P +0.41 (x) 297.78 470.33 P +0.41 (ecDef) 302.48 470.33 P +0.41 (erred will b) 328.3 470.33 P +0.41 (uff) 377.25 470.33 P +0.41 (er all commands until pend or poll) 388.07 470.33 P +6.06 (\337ush is called; e) 261.43 458.33 P +6.06 (x) 350.45 458.33 P +6.06 (ecImmediate will \337ush commands to) 355.15 458.33 P +(under) 261.43 446.33 T +(lying ser) 287.15 446.33 T +(vices immediately) 324.68 446.33 T +(.) 402.58 446.33 T +2 F +(e) 162 422.33 T +(x) 167.41 422.33 T +(ecutionMode) 172.87 422.33 T +3 F +(int e) 261.29 422.33 T +(x) 279.89 422.33 T +(ecutionMode \050v) 284.59 422.33 T +(oid\051 const;) 352.7 422.33 T +0 F +9.33 (Retur) 261.29 405.33 P +9.33 (n e) 285.99 405.33 P +9.33 (x) 308.92 405.33 P +9.33 (ecution mode: CDEV_EXEC_DEFERRED or) 313.62 405.33 P +(CDEV_EXEC_IMMEDIA) 261.43 393.33 T +(TE.) 369.14 393.33 T +2 F +(read) 162 369.33 T +(yT) 182.97 369.33 T +(oEx) 193.84 369.33 T +(ec) 212.08 369.33 T +3 F +(int readyT) 261.29 369.33 T +(oEx) 304.55 369.33 T +(ec \050v) 321.48 369.33 T +(oid\051 const;) 342.9 369.33 T +0 F +(F) 261.29 352.33 T +(or def) 267.1 352.33 T +(erred mode g) 292.37 352.33 T +(roup only) 351.74 352.33 T +(. Retur) 391.87 352.33 T +(n e) 424.91 352.33 T +(x) 438.51 352.33 T +(ecution stage:) 443.21 352.33 T +(0 = still in the b) 261.29 335.33 T +(uff) 328.07 335.33 T +(ered stage) 338.89 335.33 T +(.) 385.99 335.33 T +(1 = ready to \337ush all b) 261.29 318.33 T +(uff) 359.2 318.33 T +(ered commands) 370.02 318.33 T +(.) 441.56 318.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "26" 36 +%%Page: "27" 37 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. The cde) 445.99 739 T +(vIOConte) 488.25 739 T +(xt Class) 526 739 T +0 10 Q +(27) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(8.) 159.32 710.67 T +(The cde) 180 710.67 T +(vIOConte) 232.7 710.67 T +(xt Class) 294.72 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w of the) 108.64 673.33 T +(cde) 72 661.33 T +(vIOConte) 89.08 661.33 T +(xt) 133.38 661.33 T +(Class) 72 649.33 T +0 F +0.73 (The) 180 673.33 P +3 F +0.73 (cde) 200.74 673.33 P +0.73 (vIOConte) 216.56 673.33 P +0.73 (xt) 258.5 673.33 P +0 F +0.73 (C++ class is an abstr) 269.79 673.33 P +0.73 (act base class that is inher) 365.99 673.33 P +0.73 (ited b) 487.63 673.33 P +0.73 (y both the) 512.62 673.33 P +3 F +5.37 (cde) 180 661.33 P +5.37 (vRequestObject) 195.82 661.33 P +0 F +5.37 ( class and the) 266.96 661.33 P +3 F +5.37 (cde) 352.93 661.33 P +5.37 (vDe) 368.75 661.33 P +5.37 (vice) 386.23 661.33 P +0 F +5.37 ( class) 404.01 661.33 P +5.37 (. This class de\336nes the) 434.8 661.33 P +(mechanisms that are used to store and retr) 180 649.33 T +(ie) 370.79 649.33 T +(v) 378.27 649.33 T +(e conte) 383.02 649.33 T +(xt inf) 415.52 649.33 T +(or) 436.34 649.33 T +(mation.) 445.48 649.33 T +3 9 Q +(Figure 9: Object model of the cde) 180 616 T +(vIOConte) 315.3 616 T +(xt class) 353.04 616 T +2 10 Q +(Pub) 72 387 T +(lic Methods of) 90.79 387 T +(the) 72 375 T +(cde) 72 363 T +(vIOConte) 89.08 363 T +(xt) 133.38 363 T +(Class) 72 351 T +(g) 180 387 T +(etConte) 186.21 387 T +(xt) 223.28 387 T +3 F +(cde) 279.29 387 T +(vData & getConte) 295.11 387 T +(xt \050v) 373.74 387 T +(oid\051;) 392.38 387 T +0 F +1.45 (Obtains a ref) 279.29 370 P +1.45 (erence to the cde) 339.14 370 P +1.45 (vData object that contains the) 420.46 370 P +(conte) 279.43 358 T +(xt f) 303.59 358 T +(or a speci\336c de) 316.63 358 T +(vice) 383.58 358 T +(.) 401.21 358 T +2 F +(setConte) 180 334 T +(xt) 222.63 334 T +3 F +(int setConte) 279.29 334 T +(xt \050cde) 332.35 334 T +(vData& cxt\051;) 362.06 334 T +0 F +0.17 (Used to inser) 279.29 317 P +0.17 (t a cde) 338.93 317 P +0.17 (vData object containing tagged v) 368.98 317 P +0.17 (alues that) 514.47 317 P +0.16 (control optional beha) 279.43 305 P +0.16 (vior of the under) 372.38 305 P +0.16 (lying de) 445.28 305 P +0.16 (vice) 479.6 305 P +0.16 (. The conte) 497.23 305 P +0.16 (xt) 550.22 305 P +4.55 (is often used to specify which proper) 279.43 293 P +4.55 (ties \050v) 468.86 293 P +4.55 (alue) 499.83 293 P +4.55 (, status) 518.58 293 P +4.55 (,) 555.22 293 P +(se) 279.43 281 T +(v) 289.69 281 T +(er) 294.44 281 T +(ity\051 a de) 303.48 281 T +(vice retur) 338.75 281 T +(ns in response to a \322get\323 message) 380.12 281 T +(. .) 531.15 281 T +2 F +(g) 180 257 T +(etPriv) 186.21 257 T +(ate) 213.8 257 T +3 F +(v) 279.29 257 T +(oid * getPr) 284.04 257 T +(iv) 330.88 257 T +(ate \050v) 337.85 257 T +(oid\051;) 362.61 257 T +0 F +2.09 (Retr) 279.29 240 P +2.09 (ie) 298.33 240 P +2.09 (v) 305.81 240 P +2.09 (es a pointer to a data object that w) 310.56 240 P +2.09 (as placed in this) 480.02 240 P +(object using the setPr) 279.43 228 T +(iv) 375.74 228 T +(ate function.) 382.71 228 T +2 F +(setPriv) 180 204 T +(ate) 213.15 204 T +3 F +(v) 279.29 204 T +(oid setPr) 284.04 204 T +(iv) 323.65 204 T +(ate \050v) 330.62 204 T +(oid * data\051;) 355.38 204 T +0 F +1.63 (Associates a user speci\336ed data object with this object. The) 279.29 187 P +(pointer can be retr) 279.43 175 T +(ie) 360.73 175 T +(v) 368.21 175 T +(ed later using the) 372.96 175 T +3 F +(getPr) 452.45 175 T +(iv) 476.5 175 T +(ate) 483.47 175 T +0 F +( method.) 497.37 175 T +180 412.67 558 680 C +180 429.67 558 613 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +179.21 429.67 558.79 613 R +7 X +0 0 0 1 0 0 0 K +V +185.45 434.67 557.12 605.5 R +0 X +V +0.5 H +2 Z +N +181.62 439.33 553.29 609.33 R +7 X +V +0 X +N +210.04 498.08 524.87 583.92 R +7 X +V +0 X +N +214.37 502.41 519.37 580.75 R +7 X +V +4 9 Q +0 X +(class cdevIOContext) 315.57 574.75 T +(methods:) 214.37 563.75 T +(getContext \050 void \051 {virtual} : cdevData &) 227.7 552.75 T +(setContext \050 cdevData &cxt \051) 227.7 541.75 T +({virtual} : int) 378.9 541.75 T +(getPrivate \050 void \051 : void *) 227.7 530.75 T +(setPrivate \050 void * data \051 : void) 227.7 519.75 T +(className \050 void \051 {virtual} : char *) 227.7 508.75 T +210.2 571.25 524.7 571.25 2 L +N +312.37 456.08 421.37 471.08 R +7 X +V +0 X +N +316.13 459.58 417.32 467.92 R +7 X +V +0 X +(class cdevData) 328.93 461.92 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +366.87 498 370.87 490.1 366.87 482.2 362.87 490.1 4 Y +7 X +V +0.1 H +0 X +N +366.87 481.7 366.87 472.55 2 L +N +90 450 1.98 2.25 270 366.62 473.98 GG +90 450 1.98 2.25 270 366.62 473.98 AA +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +180 412.67 558 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "27" 37 +%%Page: "28" 38 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. The cde) 54 739 T +(vRequestObject Class) 96.25 739 T +0 10 Q +(28) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(9.) 141.32 710.67 T +(The cde) 162 710.67 T +(vRequestObject Class) 214.7 710.67 T +2 10 Q +(Over) 54 673.33 T +(vie) 76.89 673.33 T +(w of the) 90.64 673.33 T +2 9 Q +(cde) 54 661.33 T +(vRequestObject) 69.37 661.33 T +2 10 Q +(Class) 54 649.33 T +0 F +2.61 (The) 162 673.33 P +3 F +2.61 (cde) 184.62 673.33 P +2.61 (vRequestObject) 200.44 673.33 P +0 F +2.61 ( C++ class pro) 271.58 673.33 P +2.61 (vides the user with a higher perf) 343.74 673.33 P +2.61 (or) 500.85 673.33 P +2.61 (mance) 509.99 673.33 P +2.16 (interf) 162 661.33 P +2.16 (ace to de) 183.93 661.33 P +2.16 (vices in cde) 229.1 661.33 P +2.16 (v) 285.36 661.33 P +2.16 (. Each time a) 289.56 661.33 P +3 F +2.16 (cde) 359.36 661.33 P +2.16 (vDe) 375.18 661.33 P +2.16 (vice) 392.66 661.33 P +0 F +2.16 ( object receiv) 410.44 661.33 P +2.16 (es a message) 473.42 661.33 P +0.96 (str) 162 649.33 P +0.96 (ing, it m) 173.26 649.33 P +0.96 (ust parse the message and then connect to the appropr) 210.09 649.33 P +0.96 (iate ser) 464.57 649.33 P +0.96 (vice) 498.62 649.33 P +0.96 (. The) 516.25 649.33 P +3 F +1.3 (cde) 162 637.33 P +1.3 (vRequestObject) 177.82 637.33 P +0 F +1.3 ( allo) 248.96 637.33 P +1.3 (ws the user to bind a) 268.45 637.33 P +3 F +1.3 (de) 371.3 637.33 P +1.3 (vice) 382.12 637.33 P +0 F +1.3 ( name to a) 399.9 637.33 P +3 F +1.3 (message) 455.13 637.33 P +0 F +1.3 (and then) 499.78 637.33 P +0.72 (connect to the under) 162 625.33 P +0.72 (lying ser) 255.49 625.33 P +0.72 (vice only) 293.74 625.33 P +5 F +0.72 (once) 336.87 625.33 P +0 F +0.72 (. Thereafter) 360.06 625.33 P +0.72 (, the) 411.97 625.33 P +3 F +0.72 (cde) 435.66 625.33 P +0.72 (vRequestObject) 451.48 625.33 P +0 F +0.72 ( will) 522.62 625.33 P +0.45 (remain connected to the ser) 162 613.33 P +0.45 (vice and can process its associated message with m) 288.06 613.33 P +0.45 (uch) 523.88 613.33 P +(higher ef\336ciency) 162 601.33 T +(.) 233.25 601.33 T +3 9 Q +(Figure 10: Object model of the cde) 162 568 T +(vRequestObject class) 302.3 568 T +2 10 Q +(Pub) 54 151.83 T +(lic Methods of) 72.79 151.83 T +(the) 54 139.83 T +2 9 Q +(cde) 54 127.83 T +(vRequestObject) 69.37 127.83 T +2 10 Q +(Class) 54 115.83 T +(attac) 162 151.83 T +(hRef) 185.24 151.83 T +3 F +-0.3 (static cde) 261.29 151.83 S +-0.3 (vRequestObject& attachRef \050char *de) 300.23 151.83 S +-0.3 (vice) 456.17 151.83 S +-0.3 (, char * msg\051;) 472.6 151.83 S +0 F +5.63 (Obtains a ref) 261.29 134.83 P +5.63 (erence to a) 329.49 134.83 P +3 F +5.63 (cde) 399.18 134.83 P +5.63 (vRequestObject) 415.01 134.83 P +0 F +5.63 ( object b) 486.14 134.83 P +5.63 (y) 535 134.83 P +0.64 (specifying the name of the de) 261.43 122.83 P +0.64 (vice and the message str) 394.94 122.83 P +0.64 (ing. By) 508.79 122.83 P +4.63 (def) 261.43 110.83 P +4.63 (ault, the ne) 275.03 110.83 P +4.63 (w object will be managed b) 333.57 110.83 P +4.63 (y the def) 476.56 110.83 P +4.63 (ault) 523.88 110.83 P +3 F +(cde) 261.43 98.83 T +(vSystem) 277.25 98.83 T +0 F +(.) 315.59 98.83 T +162 177.5 540 680 C +162 177.5 540 565 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +161.21 177.5 540.79 565 R +7 X +0 0 0 1 0 0 0 K +V +167.45 180.83 539.12 557.5 R +0 X +V +0.5 H +2 Z +N +163.62 185.5 535.29 561.33 R +7 X +V +0 X +N +169.79 209.25 528.79 502.58 R +7 X +V +0 X +N +174.95 213.58 525.79 499.42 R +7 X +V +4 9 Q +0 X +(class cdevRequestObject) 288.27 493.42 T +(methods:) 174.95 482.42 T +(attachRef \050char *, char *\051 : cdevRequestObject&) 188.29 471.42 T +(attachRef \050cdevDevice &, char *\051 : cdevRequestObject&) 188.29 460.42 T +(attachPtr \050char *, char *\051 : cdevRequestObject*) 188.29 449.42 T +(attachPtr \050cdevDevice &, char *\051 : cdevRequestObject*) 188.29 438.42 T +(detach \050cdevRequestObject&\051 : void) 188.29 427.42 T +(detach \050cdevRequestObject*\051 : void) 188.29 416.42 T +(message \050void\051 : char *) 188.29 405.42 T +(device \050void\051 : cdevDevice&) 188.29 394.42 T +(system \050void\051 : cdevSystem&) 188.29 383.42 T +(service \050void\051 : cdevService&) 188.29 372.42 T +(setContext \050cdevData &\051 : int) 188.29 361.42 T +(getState \050void\051 : int) 188.29 350.42 T +(getAccess \050void\051 : int) 188.29 339.42 T +(send \050cdevData&, cdevData&\051 : int) 188.29 328.42 T +(send \050cdevData*, cdevData&\051 : int) 188.29 317.42 T +(send \050cdevData&, cdevData*\051 : int) 188.29 306.42 T +(send \050cdevData*, cdevData*\051 : int) 188.29 295.42 T +(sendNoBlock \050cdevData&, cdevData&\051 : int) 188.29 284.42 T +(sendNoBlock \050cdevData*, cdevData&\051 : int) 188.29 273.42 T +(sendNoBlock \050cdevData&, cdevData*\051 : int) 188.29 262.42 T +(sendNoBlock \050cdevData*, cdevData*\051 : int) 188.29 251.42 T +(sendCallback \050cdevData&, cdevCallback&\051 : int) 188.29 240.42 T +(sendCallback \050cdevData*, cdevCallback&\051 : int) 188.29 229.42 T +(className \050void\051 : char *) 188.29 218.42 T +169.95 489.92 529.12 489.92 2 L +N +314.2 539.5 322.11 543.5 330.01 539.5 322.11 535.5 4 Y +7 X +V +0.1 H +0 X +N +330.5 539.5 339.65 539.5 2 L +N +90 450 1.98 2.25 338.23 539.25 G +90 450 1.98 2.25 338.23 539.25 A +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +182.62 532 313.29 547 R +7 X +V +0.5 H +0 X +N +187.12 535.5 308.43 543.83 R +7 X +V +0 X +(class cdevIOContext) 196.48 537.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +341.45 532 450.45 547 R +7 X +V +0 X +N +345.21 535.5 446.4 543.83 R +7 X +V +0 X +(class cdevData) 358.01 537.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +239.29 512.48 247.95 525.14 256.62 512.48 3 Y +7 X +V +0.1 H +0 X +N +247.95 525.14 247.95 532.14 2 L +N +247.95 502.86 247.95 512.14 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +162 177.5 540 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "28" 38 +%%Page: "29" 39 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. The cde) 426.72 739 T +(vRequestObject Class) 468.97 739 T +0 10 Q +(29) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(attac) 180 713.33 T +(hRef) 203.24 713.33 T +3 F +-0.5 (static cde) 279.29 713.33 S +-0.5 (vRequestObject& attachRef \050cde) 316.23 713.33 S +-0.5 (vDe) 446.55 713.33 S +-0.5 (vice &de) 462.53 713.33 S +-0.5 (v) 496.58 713.33 S +-0.5 (, char * msg\051;) 500.28 713.33 S +0 F +5.63 (Obtains a ref) 279.29 696.33 P +5.63 (erence to a) 347.49 696.33 P +3 F +5.63 (cde) 417.18 696.33 P +5.63 (vRequestObject) 433.01 696.33 P +0 F +5.63 ( object b) 504.14 696.33 P +5.63 (y) 553 696.33 P +0.49 (pro) 279.43 684.33 P +0.49 (viding a ref) 293.73 684.33 P +0.49 (erence to the associated) 343.32 684.33 P +3 F +0.49 (cde) 457.02 684.33 P +0.49 (vDe) 472.84 684.33 P +0.49 (vice) 490.32 684.33 P +0 F +0.49 ( object and) 508.1 684.33 P +-0.07 (the message str) 279.43 672.33 P +-0.07 (ing. By def) 350.59 672.33 P +-0.07 (ault, the ne) 397.41 672.33 P +-0.07 (w object will be managed) 446.55 672.33 P +(b) 279.43 660.33 T +(y the def) 284.79 660.33 T +(ault) 322.85 660.33 T +3 F +(cde) 341.75 660.33 T +(vSystem) 357.57 660.33 T +0 F +(.) 395.91 660.33 T +2 F +(attac) 180 636.33 T +(hPtr) 203.24 636.33 T +3 F +-0.5 (static cde) 279.29 636.33 S +-0.5 (vRequestObject* attachPtr \050char *de) 316.23 636.33 S +-0.5 (vice) 459.61 636.33 S +-0.5 (, char * msg\051;) 475.24 636.33 S +0 F +2.04 (Obtains a pointer to a) 279.29 619.33 P +3 F +2.04 (cde) 387.87 619.33 P +2.04 (vRequestObject) 403.69 619.33 P +0 F +2.04 ( b) 474.83 619.33 P +2.04 (y specifying the) 485 619.33 P +-0.24 (name of the de) 279.43 607.33 P +-0.24 (vice and the message str) 345.13 607.33 P +-0.24 (ing. By def) 455.5 607.33 P +-0.24 (ault, the ne) 501.97 607.33 P +-0.24 (w) 550.78 607.33 P +(object will be managed b) 279.43 595.33 T +(y the def) 389.28 595.33 T +(ault) 427.34 595.33 T +3 F +(cde) 446.24 595.33 T +(vSystem) 462.06 595.33 T +0 F +(.) 500.4 595.33 T +2 F +(attac) 180 571.33 T +(hPtr) 203.24 571.33 T +3 F +-0.5 (static cde) 279.29 571.33 S +-0.5 (vRequestObject* attachPtr \050cde) 316.23 571.33 S +-0.5 (vDe) 440.99 571.33 S +-0.5 (vice &de) 456.97 571.33 S +-0.5 (v) 491.02 571.33 S +-0.5 (, char * msg\051;) 494.72 571.33 S +0 F +3.59 (Obtains a pointer to a) 279.29 554.33 P +3 F +3.59 (cde) 395.6 554.33 P +3.59 (vRequestObject) 411.42 554.33 P +0 F +3.59 ( b) 482.56 554.33 P +3.59 (y pro) 494.29 554.33 P +3.59 (viding a) 519.96 554.33 P +5.54 (ref) 279.43 542.33 P +5.54 (erence to the associated) 290.8 542.33 P +3 F +5.54 (cde) 424.7 542.33 P +5.54 (vDe) 440.52 542.33 P +5.54 (vice) 458 542.33 P +0 F +5.54 ( object and the) 475.78 542.33 P +0.29 (message str) 279.43 530.33 P +0.29 (ing. By def) 334.33 530.33 P +0.29 (ault, the ne) 381.86 530.33 P +0.29 (w object will be managed b) 431.71 530.33 P +0.29 (y) 553 530.33 P +(the def) 279.43 518.33 T +(ault) 309.71 518.33 T +3 F +(cde) 328.61 518.33 T +(vSystem) 344.43 518.33 T +0 F +(.) 382.77 518.33 T +2 F +(detac) 180 494.33 T +(h) 206.02 494.33 T +3 F +(static v) 279.29 494.33 T +(oid detach \050cde) 310.16 494.33 T +(vRequestObject& de) 378.23 494.33 T +(v\051;) 469.64 494.33 T +0 F +3.92 (Remo) 279.29 477.33 P +3.92 (v) 305.81 477.33 P +3.92 (es a ref) 310.56 477.33 P +3.92 (erenced cde) 351.44 477.33 P +3.92 (vRequestObject object from its) 410.09 477.33 P +2.47 (associated cde) 279.43 465.33 P +2.47 (vSystem object. Ordinar) 348.3 465.33 P +2.47 (y applications should) 460.24 465.33 P +(ne) 279.43 453.33 T +(v) 290.25 453.33 T +(er use this command.) 295 453.33 T +2 F +(detac) 180 429.33 T +(h) 206.02 429.33 T +3 F +(static v) 279.29 429.33 T +(oid detach \050cde) 310.16 429.33 T +(vRequestObject* de) 378.23 429.33 T +(v\051;) 466.86 429.33 T +0 F +0.55 (Detaches the cde) 279.29 412.33 P +0.55 (vRequestObject object speci\336ed b) 357.9 412.33 P +0.55 (y de) 510.52 412.33 P +0.55 (v from) 529.67 412.33 P +-0.07 (its associated cde) 279.43 400.33 P +-0.07 (vSystem object. Ordinar) 358.47 400.33 P +-0.07 (y applications should) 465.32 400.33 P +(ne) 279.43 388.33 T +(v) 290.25 388.33 T +(er use this command.) 295 388.33 T +2 F +(messa) 180 364.33 T +(g) 211.03 364.33 T +(e) 217.24 364.33 T +3 F +(char *message \050v) 279.29 364.33 T +(oid\051 const;) 356.84 364.33 T +0 F +3.82 (Retr) 279.29 347.33 P +3.82 (ie) 298.33 347.33 P +3.82 (v) 305.81 347.33 P +3.82 (es the message str) 310.56 347.33 P +3.82 (ing that is associated with this) 406.64 347.33 P +(cde) 279.43 335.33 T +(vRequestObject.) 295.25 335.33 T +2 F +(de) 180 311.33 T +(vice) 191.52 311.33 T +3 F +(cde) 279.29 311.33 T +(vDe) 295.11 311.33 T +(vice &de) 312.59 311.33 T +(vice \050v) 350.64 311.33 T +(oid\051 const;) 379.28 311.33 T +0 F +5.41 (Retr) 279.29 294.33 P +5.41 (ie) 298.33 294.33 P +5.41 (v) 305.81 294.33 P +5.41 (es a ref) 310.56 294.33 P +5.41 (erence to the cde) 354.42 294.33 P +5.41 (vDe) 447.6 294.33 P +5.41 (vice object that is) 465.08 294.33 P +(associated with this cde) 279.43 282.33 T +(vRequestObject.) 384.73 282.33 T +2 F +(system) 180 258.33 T +3 F +(cde) 279.29 258.33 T +(vSystem& system \050v) 295.11 258.33 T +(oid\051 const;) 385.43 258.33 T +0 F +0.14 (Retr) 279.29 241.33 P +0.14 (ie) 298.33 241.33 P +0.14 (v) 305.81 241.33 P +0.14 (es a ref) 310.56 241.33 P +0.14 (erence to the under) 343.88 241.33 P +0.14 (lying cde) 431.17 241.33 P +0.14 (vSystem object that) 470.46 241.33 P +(manages this cde) 279.43 229.33 T +(vRequestObject.) 357.5 229.33 T +2 F +(ser) 180 205.33 T +(vice) 195.11 205.33 T +3 F +(cde) 279.29 205.33 T +(vSer) 295.11 205.33 T +(vice& ser) 315.97 205.33 T +(vice \050v) 357.39 205.33 T +(oid\051 const;) 386.03 205.33 T +0 F +0.1 (Retr) 279.29 188.33 P +0.1 (ie) 298.33 188.33 P +0.1 (v) 305.81 188.33 P +0.1 (es a ref) 310.56 188.33 P +0.1 (erence to the under) 343.81 188.33 P +0.1 (lying cde) 430.98 188.33 P +0.1 (vSer) 470.24 188.33 P +0.1 (vice object that) 491.1 188.33 P +(this cde) 279.43 176.33 T +(vRequestObject is attached to) 313.59 176.33 T +(.) 446.59 176.33 T +2 F +(g) 180 152.33 T +(etState) 186.21 152.33 T +3 F +(int getState \050v) 279.29 152.33 T +(oid\051;) 340.74 152.33 T +0 F +-0.15 (Obtains the state of the under) 279.29 135.33 P +-0.15 (lying de) 410.42 135.33 P +-0.15 (vice) 444.43 135.33 P +-0.15 (. This function retur) 462.06 135.33 P +-0.15 (ns) 547.44 135.33 P +(one of the f) 279.43 123.33 T +(ollo) 329.17 123.33 T +(wing v) 344.58 123.33 T +(alues as de\336ned in) 372.67 123.33 T +3 F +(cde) 458.83 123.33 T +(vErrCode) 474.65 123.33 T +(.h) 516.73 123.33 T +0 F +(.) 525.07 123.33 T +2 F +(CDEV_ST) 279.29 106.33 T +(A) 324.51 106.33 T +(TE_CONNECTED:) 330.83 106.33 T +0 F +(Object is connected.) 441.81 106.33 T +2 F +(CDEV_ST) 279.29 89.33 T +(A) 324.51 89.33 T +(TE_NO) 330.83 89.33 T +(TCONNECTED:) 363.77 89.33 T +0 F +(Object is not connected.) 441.81 89.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "29" 39 +%%Page: "30" 40 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. The cde) 54 739 T +(vRequestObject Class) 96.25 739 T +0 10 Q +(30) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(CDEV_ST) 261.29 696.33 T +(A) 306.51 696.33 T +(TE_INV) 312.83 696.33 T +(ALID:) 347.04 696.33 T +0 F +(Object is in) 423.81 696.33 T +(v) 473.07 696.33 T +(alid.) 477.82 696.33 T +3.16 (The ser) 261.29 662.33 P +3.16 (vice de) 298.65 662.33 P +3.16 (v) 333.2 662.33 P +3.16 (eloper is responsib) 337.95 662.33 P +3.16 (le f) 428 662.33 P +3.16 (or implementing this) 444.2 662.33 P +(function correctly in the ser) 261.43 650.33 T +(vice related cde) 381.22 650.33 T +(vRequestObject.) 450.95 650.33 T +2 F +(g) 162 626.33 T +(etAccess) 168.21 626.33 T +3 F +(int getAccess \050v) 261.29 626.33 T +(oid\051;) 331.62 626.33 T +0 F +5.3 (Obtains access control inf) 261.29 609.33 P +5.3 (or) 391.39 609.33 P +5.3 (mation about the under) 400.53 609.33 P +5.3 (lying) 519.44 609.33 P +2.27 (de) 261.43 597.33 P +2.27 (vice) 272.25 597.33 P +2.27 (. This function retur) 289.88 597.33 P +2.27 (ns one of the f) 382.54 597.33 P +2.27 (ollo) 454.71 597.33 P +2.27 (wing v) 470.12 597.33 P +2.27 (alues as) 500.49 597.33 P +(de\336ned in cde) 261.43 585.33 T +(vErrCode) 323.39 585.33 T +(.h.) 365.47 585.33 T +2 F +(CDEV_A) 261.29 568.33 T +(CCESS_NONE:) 301.45 568.33 T +0 F +(No access to attr) 423.81 568.33 T +(ib) 498.99 568.33 T +(ute) 506.57 568.33 T +(.) 520.32 568.33 T +2 F +(CDEV_A) 261.29 551.33 T +(CCESS_READONL) 301.45 551.33 T +(Y) 389.7 551.33 T +(:) 395.87 551.33 T +0 F +(Read-only access) 423.81 551.33 T +(.) 503.13 551.33 T +2 F +(CDEV_A) 261.29 534.33 T +(CCESS_WRITE:) 301.45 534.33 T +0 F +(Read-wr) 423.81 534.33 T +(ite access) 461.74 534.33 T +(.) 506.05 534.33 T +3.16 (The ser) 261.29 500.33 P +3.16 (vice de) 298.65 500.33 P +3.16 (v) 333.2 500.33 P +3.16 (eloper is responsib) 337.95 500.33 P +3.16 (le f) 428 500.33 P +3.16 (or implementing this) 444.2 500.33 P +(function correctly in the ser) 261.43 488.33 T +(vice related cde) 381.22 488.33 T +(vRequestObject.) 450.95 488.33 T +2 F +(setConte) 162 464.33 T +(xt) 204.63 464.33 T +3 F +(int setConte) 261.29 464.33 T +(xt \050cde) 314.35 464.33 T +(vData& cxt\051;) 344.06 464.33 T +0 F +0.17 (Used to inser) 261.29 447.33 P +0.17 (t a cde) 320.93 447.33 P +0.17 (vData object containing tagged v) 350.98 447.33 P +0.17 (alues that) 496.47 447.33 P +0.16 (control optional beha) 261.43 435.33 P +0.16 (vior of the under) 354.38 435.33 P +0.16 (lying de) 427.28 435.33 P +0.16 (vice) 461.6 435.33 P +0.16 (. The conte) 479.23 435.33 P +0.16 (xt) 532.22 435.33 P +4.55 (is often used to specify which proper) 261.43 423.33 P +4.55 (ties \050v) 450.86 423.33 P +4.55 (alue) 481.83 423.33 P +4.55 (, status) 500.58 423.33 P +4.55 (,) 537.22 423.33 P +0.41 (se) 261.43 411.33 P +0.41 (v) 271.69 411.33 P +0.41 (er) 276.44 411.33 P +0.41 (ity\051 a de) 285.48 411.33 P +0.41 (vice retur) 321.56 411.33 P +0.41 (ns in response to a \322get\323 message) 363.34 411.33 P +0.41 (. The) 516.8 411.33 P +2.61 (ser) 261.43 399.33 P +2.61 (vice de) 275.62 399.33 P +2.61 (v) 309.61 399.33 P +2.61 (eloper ma) 314.36 399.33 P +2.61 (y o) 361.13 399.33 P +2.61 (v) 376.93 399.33 P +2.61 (err) 381.68 399.33 P +2.61 (ide the def) 394.05 399.33 P +2.61 (ault beha) 445.66 399.33 P +2.61 (vior of this) 489.21 399.33 P +(method to better accomodate the requirements of the ser) 261.43 387.33 T +(vice) 514.08 387.33 T +(.) 531.71 387.33 T +2 F +(g) 162 363.33 T +(etConte) 168.21 363.33 T +(xt) 205.28 363.33 T +3 F +(cde) 261.29 363.33 T +(vData & getConte) 277.11 363.33 T +(xt \050v) 355.74 363.33 T +(oid\051;) 374.38 363.33 T +0 F +0.63 (Retr) 261.29 346.33 P +0.63 (ie) 280.33 346.33 P +0.63 (v) 287.81 346.33 P +0.63 (es a ref) 292.56 346.33 P +0.63 (erence to the cde) 326.87 346.33 P +0.63 (vData object that contains the) 405.73 346.33 P +6.79 (conte) 261.43 334.33 P +6.79 (xt f) 285.59 334.33 P +6.79 (or a speci\336c cde) 305.42 334.33 P +6.79 (vRequestObject. The ser) 397.74 334.33 P +6.79 (vice) 522.22 334.33 P +0.93 (de) 261.43 322.33 P +0.93 (v) 272.25 322.33 P +0.93 (eloper ma) 277 322.33 P +0.93 (y o) 322.09 322.33 P +0.93 (v) 336.21 322.33 P +0.93 (err) 340.96 322.33 P +0.93 (ide the def) 353.33 322.33 P +0.93 (ault beha) 401.59 322.33 P +0.93 (vior of this method to) 443.46 322.33 P +(better accomodate the requirements of the ser) 261.43 310.33 T +(vice) 466.83 310.33 T +(.) 484.46 310.33 T +2 F +(g) 162 286.33 T +(etPriv) 168.21 286.33 T +(ate) 195.8 286.33 T +3 F +(v) 261.29 286.33 T +(oid * getPr) 266.04 286.33 T +(iv) 312.88 286.33 T +(ate \050v) 319.85 286.33 T +(oid\051;) 344.61 286.33 T +0 F +2.09 (Retr) 261.29 269.33 P +2.09 (ie) 280.33 269.33 P +2.09 (v) 287.81 269.33 P +2.09 (es a pointer to a data object that w) 292.56 269.33 P +2.09 (as placed in this) 462.02 269.33 P +(object using the setPr) 261.43 257.33 T +(iv) 357.74 257.33 T +(ate function.) 364.71 257.33 T +2 F +(setPriv) 162 233.33 T +(ate) 195.15 233.33 T +3 F +(v) 261.29 233.33 T +(oid setPr) 266.04 233.33 T +(iv) 305.65 233.33 T +(ate \050v) 312.62 233.33 T +(oid * data\051;) 337.38 233.33 T +0 F +9.56 (Associates a user speci\336ed data object with this) 261.29 216.33 P +3 F +1.78 (cde) 261.43 204.33 P +1.78 (vRequestObject) 277.25 204.33 P +0 F +1.78 (. The pointer can be retr) 348.39 204.33 P +1.78 (ie) 464.17 204.33 P +1.78 (v) 471.65 204.33 P +1.78 (ed later using) 476.4 204.33 P +(the) 261.43 192.33 T +3 F +(getPr) 278.11 192.33 T +(iv) 302.16 192.33 T +(ate) 309.13 192.33 T +0 F +( method.) 323.03 192.33 T +2 F +(send) 162 168.33 T +3 F +(int send \050cde) 261.29 168.33 T +(vData &out, cde) 318.24 168.33 T +(vData& result\051;) 389.09 168.33 T +(int send \050cde) 261.29 156.33 T +(vData *out, cde) 318.24 156.33 T +(vData& result\051;) 386.31 156.33 T +(int send \050cde) 261.29 144.33 T +(vData &out, cde) 318.24 144.33 T +(vData* result\051;) 389.09 144.33 T +(int send \050cde) 261.29 132.33 T +(vData *out, cde) 318.24 132.33 T +(vData* result\051;) 386.31 132.33 T +0 F +1.74 (The send function is the standard method f) 261.29 115.33 P +1.74 (or synchronously) 462.68 115.33 P +5.38 (comm) 261.43 103.33 P +5.38 (unicating with a de) 288.55 103.33 P +5.38 (vice) 387.21 103.33 P +5.38 (. The) 404.84 103.33 P +3 F +5.38 (out) 441.16 103.33 P +0 F +5.38 (cde) 463.22 103.33 P +5.38 (vData object) 479.04 103.33 P +3.44 (contains an) 261.43 91.33 P +3.44 (y proper) 315.86 91.33 P +3.44 (ty v) 356.38 91.33 P +3.44 (alues that the de) 375.14 91.33 P +3.44 (vice will need to) 459.1 91.33 P +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "30" 40 +%%Page: "31" 41 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. The cde) 426.72 739 T +(vRequestObject Class) 468.97 739 T +0 10 Q +(31) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.53 (perf) 279.43 713.33 P +1.53 (or) 296.36 713.33 P +1.53 (m the task. The) 305.5 713.33 P +3 F +1.53 (result) 383.34 713.33 P +0 F +1.53 ( cde) 407.79 713.33 P +1.53 (vData object will contain the) 427.92 713.33 P +3.82 (output proper) 279.43 701.33 P +3.82 (ties that resulted from the call. The ser) 343.13 701.33 P +3.82 (vice) 540.22 701.33 P +1.67 (de) 279.43 689.33 P +1.67 (v) 290.25 689.33 P +1.67 (eloper is responsib) 295 689.33 P +1.67 (le f) 382.07 689.33 P +1.67 (or implementing this method in the) 396.79 689.33 P +1.09 (ser) 279.43 677.33 P +1.09 (vice speci\336ed cde) 293.62 677.33 P +1.09 (vRequestObject. This function will retur) 374.43 677.33 P +1.09 (n) 552.44 677.33 P +(one of the error code de\336ned in cde) 279.43 665.33 T +(vErrCode) 437 665.33 T +(.h.) 479.08 665.33 T +3 9 Q +(Figure 11: Retur) 180 632 T +(n codes gener) 247.75 632 T +(ated b) 304.7 632 T +(y the send method.) 329.54 632 T +2 10 Q +(sendNoBloc) 180 372.19 T +(k) 238.14 372.19 T +3 F +(int sendNoBloc) 279.29 372.19 T +(k \050cde) 346.34 372.19 T +(vData &out, cde) 373.27 372.19 T +(vData &result\051;) 444.12 372.19 T +(int sendNoBloc) 279.29 360.19 T +(k \050cde) 346.34 360.19 T +(vData *out, cde) 373.27 360.19 T +(vData &result\051;) 441.34 360.19 T +(int sendNoBloc) 279.29 348.19 T +(k \050cde) 346.34 348.19 T +(vData &out, cde) 373.27 348.19 T +(vData *result\051;) 444.12 348.19 T +(int sendNoBloc) 279.29 336.19 T +(k \050cde) 346.34 336.19 T +(vData *out, cde) 373.27 336.19 T +(vData *result\051;) 441.34 336.19 T +0 F +3.34 (The) 279.29 319.19 P +3 F +3.34 (sendNoBloc) 302.63 319.19 P +3.34 (k) 356.34 319.19 P +0 F +3.34 ( method uses the same par) 361.34 319.19 P +3.34 (ameters and) 499.08 319.19 P +1.51 (syntax as the) 279.43 307.19 P +3 F +1.51 (send) 345.67 307.19 P +0 F +1.51 ( method. Ho) 367.36 307.19 P +1.51 (w) 424.7 307.19 P +1.51 (e) 431.82 307.19 P +1.51 (v) 437.08 307.19 P +1.51 (er) 441.83 307.19 P +1.51 (, r) 450.22 307.19 P +1.51 (ather than w) 460.53 307.19 P +1.51 (aiting f) 518.43 307.19 P +1.51 (or) 549.11 307.19 P +0.89 (the under) 279.43 295.19 P +0.89 (lying ser) 322.72 295.19 P +0.89 (vice to respond to the request, this function) 361.14 295.19 P +0.16 (will retur) 279.43 283.19 P +0.16 (n immediately) 317.06 283.19 P +0.16 (.The caller m) 377.91 283.19 P +0.16 (ust use a cde) 435.92 283.19 P +0.16 (vGroup object) 495.59 283.19 P +1.44 (in order to detect when the tr) 279.43 271.19 P +1.44 (ansaction has been completed.) 415.27 271.19 P +3.14 (The ser) 279.43 259.19 P +3.14 (vice de) 316.78 259.19 P +3.14 (v) 351.3 259.19 P +3.14 (eloper is responsib) 356.05 259.19 P +3.14 (le f) 446.06 259.19 P +3.14 (or implementing this) 462.24 259.19 P +(method in the ser) 279.43 247.19 T +(vice speci\336ed cde) 356.99 247.19 T +(vRequestObject.) 435.61 247.19 T +2 F +(sendCallbac) 180 223.19 T +(k) 238.71 223.19 T +3 F +(int sendCallbac) 279.29 223.19 T +(k \050cde) 347.45 223.19 T +(vData &out, cde) 374.38 223.19 T +(vCallbac) 445.23 223.19 T +(k &callbac) 483.37 223.19 T +(k\051;) 528.74 223.19 T +(int sendCallbac) 279.29 211.19 T +(k \050cde) 347.45 211.19 T +(vData *out, cde) 374.38 211.19 T +(vCallbac) 442.45 211.19 T +(k &callbac) 480.59 211.19 T +(k\051;) 525.96 211.19 T +0 F +6.06 (The) 279.29 194.19 P +3 F +6.06 (sendCallbac) 305.36 194.19 P +6.06 (k) 360.18 194.19 P +0 F +6.06 (function is the standard method f) 374.02 194.19 P +6.06 (or) 549.11 194.19 P +3.54 (asynchronously comm) 279.43 182.19 P +3.54 (unicating with a de) 382.34 182.19 P +3.54 (vice) 475.48 182.19 P +3.54 (. Rather than) 493.11 182.19 P +1.95 (pro) 279.43 170.19 P +1.95 (viding a) 293.73 170.19 P +3 F +1.95 (result) 334.86 170.19 P +0 F +1.95 ( cde) 359.31 170.19 P +1.95 (vData object, this method requires the) 379.86 170.19 P +2.49 (user to pro) 279.43 158.19 P +2.49 (vide the address of a cde) 332.07 158.19 P +2.49 (vCallbac) 455.96 158.19 P +2.49 (k object. This) 494.1 158.19 P +1.4 (object contains a user supplied pointer and the address of a) 279.43 146.19 P +3.42 (function to call when the message has been successfully) 279.43 134.19 P +8.48 (processed. The ser) 279.43 122.19 P +8.48 (vice de) 382.29 122.19 P +8.48 (v) 422.15 122.19 P +8.48 (eloper is responsib) 426.9 122.19 P +8.48 (le f) 527.59 122.19 P +8.48 (or) 549.11 122.19 P +10.07 (implementing this method in the ser) 279.43 110.19 P +10.07 (vice speci\336ed) 487.91 110.19 P +(cde) 279.43 98.19 T +(vRequestObject.) 295.25 98.19 T +180 81 558 720 C +180 392.86 558 629 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.29 397.21 559.86 621.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +180.32 400.33 554.27 626.57 R +7 X +V +0 X +N +183.9 404.44 551.85 622.71 R +7 X +V +4 9 Q +0 X +(CDEV_WARNING) 183.9 616.71 T +8 F +(: Failure of the function is non-consequential.) 248.71 616.71 T +4 F +(CDEV_SUCCESS: The message was processed successfully.) 183.9 605.71 T +(CDEV_ERROR: Failed to process message.) 183.9 594.71 T +(CDEV_INVALIDOBJ: Invalid cdev request object used.) 183.9 583.71 T +(CDEV_INVALIDARG: Invalid argument passed to cdev call.) 183.9 572.71 T +(CDEV_INVALIDSVC: Wrong service during dynamic loading.) 183.9 561.71 T +(CDEV_NOTCONNECTED: Not connected to low level network service.) 183.9 550.71 T +(CDEV_INVALIDOP:) 183.9 539.71 T +8 F +(The operation is not supported by the device.) 302.7 539.71 T +4 F +(CDEV_IOFAILED: Low level network service IO failed.) 183.9 528.71 T +(CDEV_CONFLICT: Conflicts of data types or tags.) 183.9 517.71 T +(CDEV_NOTFOUND: Cannot find specified data in cdevData.) 183.9 506.71 T +(CDEV_TIMEOUT: Time out.) 183.9 495.71 T +(CDEV_CONVERT: cdevData conversion error.) 183.9 484.71 T +(CDEV_OUTOFRANGE: Value out of range for device attribute.) 183.9 473.71 T +(CDEV_NOACCESS: Insufficient access to perform request.) 183.9 462.71 T +(CDEV_ACCESSCHANGED: Change in access permission of device.) 183.9 451.71 T +(CDEV_DISCONNECTED: Service has lost contact with the device.) 183.9 440.71 T +(CDEV_RECONNECTED: Service has regained contact with the device.) 183.9 429.71 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "31" 41 +%%Page: "32" 42 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(10. The cde) 54 739 T +(vSelector Class) 101.26 739 T +0 10 Q +(32) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(10.) 133.54 710.67 T +(The cde) 162 710.67 T +(vSelector Class) 214.7 710.67 T +2 10 Q +(Over) 54 673.33 T +(vie) 76.89 673.33 T +(w of the) 90.64 673.33 T +(cde) 54 661.33 T +(vSelector) 71.08 661.33 T +(Class) 54 649.33 T +0 F +0.21 (The) 162 673.33 P +3 F +0.21 (cde) 182.22 673.33 P +0.21 (vSelector) 198.04 673.33 P +0 F +0.21 (C++ class is a utility class that ma) 242.71 673.33 P +0.21 (y be used b) 393.93 673.33 P +0.21 (y ser) 446.06 673.33 P +0.21 (vice de) 468.24 673.33 P +0.21 (v) 499.83 673.33 P +0.21 (elopers) 504.58 673.33 P +0.21 (.) 537.22 673.33 P +1.33 (It allo) 162 661.33 P +1.33 (ws a ser) 187.08 661.33 P +1.33 (vice that does not use netw) 227.28 661.33 P +1.33 (or) 355.03 661.33 P +1.33 (k I/O to pro) 364.07 661.33 P +1.33 (vide a locally managed \336le) 417.39 661.33 P +2.73 (descr) 162 649.33 P +2.73 (iptor to the) 186.6 649.33 P +3 F +2.73 (cde) 244.83 649.33 P +2.73 (vSystem) 260.65 649.33 P +0 F +2.73 ( object. The ser) 298.99 649.33 P +2.73 (vice ma) 376.41 649.33 P +2.73 (y then use the) 413.3 649.33 P +3 F +2.73 (inser) 489.83 649.33 P +2.73 (tEv) 511.9 649.33 P +2.73 (ent) 526.1 649.33 P +0 F +(method to signal the) 162 637.33 T +3 F +(cde) 254.83 637.33 T +(vSystem) 270.65 637.33 T +0 F +( object that the ser) 308.99 637.33 T +(vices needs attention.) 391.56 637.33 T +3 9 Q +(Figure 12: Object model of the cde) 162 604 T +(vSelector class) 302.3 604 T +2 10 Q +(Pub) 54 420.83 T +(lic Methods of) 72.79 420.83 T +(the cde) 54 408.83 T +(vSelector) 88.86 408.83 T +(Class) 54 396.83 T +(inser) 162 420.83 T +(tEvent) 186.1 420.83 T +3 F +(int inser) 261.29 420.83 T +(tEv) 296.7 420.83 T +(ent \050 int n) 310.9 420.83 T +(umEv) 352.49 420.83 T +(ents \051;) 377.8 420.83 T +0 F +4.44 (Inser) 261.29 403.83 P +4.44 (ts the n) 283.92 403.83 P +4.44 (umber of b) 325.5 403.83 P +4.44 (ytes speci\336ed in the n) 381.97 403.83 P +4.44 (umEv) 495.79 403.83 P +4.44 (ents) 521.1 403.83 P +0.04 (par) 261.43 391.83 P +0.04 (ameter into the \336le descr) 275.78 391.83 P +0.04 (iptor) 385.58 391.83 P +0.04 (. If n) 404.53 391.83 P +0.04 (umEv) 423.97 391.83 P +0.04 (ents is not speci\336ed,) 449.28 391.83 P +(then one b) 261.43 379.83 T +(yte will be wr) 308.49 379.83 T +(itten.) 365.87 379.83 T +2 F +(remo) 162 355.83 T +(veEvent) 186.25 355.83 T +3 F +(int remo) 261.29 355.83 T +(v) 297.26 355.83 T +(eEv) 302.01 355.83 T +(ent \050 int n) 318.99 355.83 T +(umEv) 360.58 355.83 T +(ents \051;) 385.89 355.83 T +0 F +3.01 (Remo) 261.29 338.83 P +3.01 (v) 287.81 338.83 P +3.01 (es the n) 292.56 338.83 P +3.01 (umber of b) 334.06 338.83 P +3.01 (ytes speci\336ed in the) 387.68 338.83 P +3 F +3.01 (n) 490.33 338.83 P +3.01 (umEv) 495.79 338.83 P +3.01 (ents) 521.1 338.83 P +0 F +5.19 (par) 261.43 326.83 P +5.19 (ameter from the \336le descr) 275.78 326.83 P +5.19 (iptor) 410.05 326.83 P +5.19 (. If) 429 326.83 P +3 F +5.19 (n) 453.27 326.83 P +5.19 (umEv) 458.73 326.83 P +5.19 (ents) 484.05 326.83 P +0 F +5.19 ( is not) 502.95 326.83 P +1.7 (speci\336ed, then one b) 261.43 314.83 P +1.7 (yte will be read. This function uses the) 358.6 314.83 P +0.06 (ioctl function to ensure that the) 261.43 302.83 P +3 F +0.06 (n) 400.76 302.83 P +0.06 (umEv) 406.22 302.83 P +0.06 (ents) 431.53 302.83 P +0 F +0.06 ( par) 450.43 302.83 P +0.06 (ameter does not) 467.62 302.83 P +3.3 (e) 261.43 290.83 P +3.3 (xceed the actual n) 266.69 290.83 P +3.3 (umber of b) 357.65 290.83 P +3.3 (ytes a) 411.85 290.83 P +3.3 (v) 441.63 290.83 P +3.3 (ailab) 446.38 290.83 P +3.3 (le from the \336le) 467.3 290.83 P +(descr) 261.43 278.83 T +(iptor) 286.03 278.83 T +(.) 304.98 278.83 T +2 F +(pur) 162 254.83 T +(g) 177.96 254.83 T +(e) 184.17 254.83 T +3 F +(v) 261.29 254.83 T +(oid purge \050 v) 266.04 254.83 T +(oid \051;) 321.37 254.83 T +0 F +(Remo) 261.29 237.83 T +(v) 287.81 237.83 T +(es all b) 292.56 237.83 T +(ytes from the \336le descr) 324.04 237.83 T +(iptor) 424.78 237.83 T +(.) 443.73 237.83 T +2 F +(writefd) 162 213.83 T +3 F +(int wr) 261.29 213.83 T +(itefd \050 v) 285.33 213.83 T +(oid \051;) 317.87 213.83 T +0 F +3.92 (Retur) 261.29 196.83 P +3.92 (ns the wr) 285.99 196.83 P +3.92 (ite \336le descr) 334.55 196.83 P +3.92 (iptor that is stored within the) 395.89 196.83 P +3 F +(cde) 261.43 184.83 T +(vSelector) 277.25 184.83 T +0 F +( object.) 318.93 184.83 T +2 F +(readfd) 162 160.83 T +3 F +(int readfd \050 v) 261.29 160.83 T +(oid \051;) 316.62 160.83 T +0 F +4.06 (Retur) 261.29 143.83 P +4.06 (ns the read \336le descr) 285.99 143.83 P +4.06 (iptor that is stored within the) 395.2 143.83 P +3 F +(cde) 261.43 131.83 T +(vSelector) 277.25 131.83 T +0 F +( object.) 318.93 131.83 T +162 446.5 540 680 C +162 463.5 540 601 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +161.93 463.5 540.07 601 R +7 X +0 0 0 1 0 0 0 K +V +166.74 469.33 538.41 593.5 R +0 X +V +0.5 H +2 Z +N +162.9 474 534.57 597.33 R +7 X +V +0 X +N +183.82 486.5 513.66 584.83 R +7 X +V +0 X +N +190.4 490 508.74 581.67 R +7 X +V +4 9 Q +0 X +(class cdevSelector) 300.97 575.67 T +(methods:) 190.4 564.67 T +(insertEvent \050int\051 : int) 203.74 553.67 T +(removeEvent \050int\051 : int) 203.74 542.67 T +(purge \050void\051 : void) 203.74 531.67 T +(writefd \050void\051 : int) 203.74 520.67 T +(readfd \050void\051 : int) 203.74 509.67 T +184.16 572.17 513.31 572.17 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +162 446.5 540 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "32" 42 +%%Page: "33" 43 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(11. The cde) 450.96 739 T +(vSer) 498.22 739 T +(vice Class) 517 739 T +0 10 Q +(33) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(11.) 151.54 710.67 T +(The cde) 180 710.67 T +(vSer) 232.7 710.67 T +(vice Class) 263.19 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w of the) 108.64 673.33 T +(cde) 72 661.33 T +(vSer) 89.08 661.33 T +(vice Class) 110.86 661.33 T +0 F +0.28 (The cde) 180 673.33 P +0.28 (vSer) 216.11 673.33 P +0.28 (vice C++ class is an abstr) 236.97 673.33 P +0.28 (act base class f) 352.23 673.33 P +0.28 (or all cde) 421.7 673.33 P +0.28 (v ser) 462.54 673.33 P +0.28 (vices) 484.79 673.33 P +0.28 (. This class) 507.42 673.33 P +2.07 (de\336nes the mechanisms that cde) 180 661.33 P +2.07 (v will utiliz) 334.14 661.33 P +2.07 (e to comm) 382.56 661.33 P +2.07 (unicate with the under) 433.27 661.33 P +2.07 (lying) 537.44 661.33 P +0.27 (control system. It is the responsibility of the ser) 180 649.33 P +0.27 (vice de) 389.78 649.33 P +0.27 (v) 421.43 649.33 P +0.27 (eloper to \324) 426.18 649.33 P +3 F +0.27 (\337esh out) 470.63 649.33 P +0 F +0.27 (\325 the vir) 508.71 649.33 P +0.27 (tual) 541.88 649.33 P +1.9 (functions that are de\336ned within this class and to de) 180 637.33 P +1.9 (v) 425.83 637.33 P +1.9 (elop the code necessar) 430.58 637.33 P +1.9 (y to) 539.98 637.33 P +(comm) 180 625.33 T +(unicate with the under) 207.12 625.33 T +(lying control system.) 305.1 625.33 T +3 9 Q +(Figure 13: Object model of the cde) 180 592 T +(vSer) 320.3 592 T +(vice class) 339.08 592 T +2 10 Q +(Pub) 72 328.83 T +(lic Methods of) 90.79 328.83 T +(the cde) 72 316.83 T +(vSer) 106.86 316.83 T +(vice) 128.64 316.83 T +(Class) 72 304.83 T +(\337ush) 180 328.83 T +3 F +(int \337ush \050v) 279.29 328.83 T +(oid\051;) 324.61 328.83 T +0 F +2.79 (Flushes an) 279.29 311.83 P +2.79 (y pending outbound requests to their respectiv) 330.84 311.83 P +2.79 (e) 552.44 311.83 P +0 (de) 279.43 299.83 P +0 (vices) 290.25 299.83 P +0 (. This is a pure vir) 312.88 299.83 P +0 (tual function that m) 392.22 299.83 P +0 (ust be pro) 476.62 299.83 P +0 (vided b) 520.95 299.83 P +0 (y) 553 299.83 P +(the ser) 279.43 287.83 T +(vice de) 310.3 287.83 T +(v) 341.68 287.83 T +(eloper) 346.43 287.83 T +(.) 373.72 287.83 T +2 F +(poll) 180 263.83 T +3 F +(int poll \050v) 279.29 263.83 T +(oid\051;) 319.05 263.83 T +0 F +5.89 (Directly polls each of the cde) 279.29 246.83 P +5.89 (vSer) 436.25 246.83 P +5.89 (vice\325) 457.11 246.83 P +5.89 (s under) 476.61 246.83 P +5.89 (lying \336le) 515.99 246.83 P +6.67 (descr) 279.43 234.83 P +6.67 (iptors f) 304.03 234.83 P +6.67 (or activity) 340.41 234.83 P +6.67 (, and deliv) 388.32 234.83 P +6.67 (ers an) 446.99 234.83 P +6.67 (y asynchronous) 481.3 234.83 P +-0.26 (callbac) 279.43 222.83 P +-0.26 (ks that are ready) 310.35 222.83 P +-0.26 (. This is a pure vir) 383.05 222.83 P +-0.26 (tual function that m) 461.05 222.83 P +-0.26 (ust) 544.66 222.83 P +(be pro) 279.43 210.83 T +(vided b) 307.63 210.83 T +(y the ser) 339.67 210.83 T +(vice de) 378.32 210.83 T +(v) 409.7 210.83 T +(eloper) 414.45 210.83 T +(.) 441.74 210.83 T +2 F +(pend) 180 186.83 T +3 F +(int pend \050int fd\051;) 279.29 186.83 T +0 F +0.01 (W) 279.29 169.83 P +0.01 (aits f) 288.33 169.83 P +0.01 (or a def) 309.16 169.83 P +0.01 (ault per) 342.8 169.83 P +0.01 (iod of time f) 376.31 169.83 P +0.01 (or the speci\336ed \336le descr) 427.74 169.83 P +0.01 (iptor) 538.55 169.83 P +1.27 (to ha) 279.43 157.83 P +1.27 (v) 302.74 157.83 P +1.27 (e an I/O e) 307.49 157.83 P +1.27 (v) 354.92 157.83 P +1.27 (ent. If the fd par) 359.67 157.83 P +1.27 (ameter is not pro) 434.69 157.83 P +1.27 (vided, the) 513.37 157.83 P +2.74 (cde) 279.43 145.83 P +2.74 (vSer) 295.25 145.83 P +2.74 (vice object will w) 316.11 145.83 P +2.74 (ait f) 398.09 145.83 P +2.74 (or an I/O e) 416.65 145.83 P +2.74 (v) 471.83 145.83 P +2.74 (ent on an) 476.58 145.83 P +2.74 (y of its) 523.61 145.83 P +0.23 (contained \336le descr) 279.43 133.83 P +0.23 (iptors) 366.19 133.83 P +0.23 (. When an e) 390.49 133.83 P +0.23 (v) 444.81 133.83 P +0.23 (ent occurs on one of the) 449.56 133.83 P +0.41 (\336le descr) 279.43 121.83 P +0.41 (iptors) 320.01 121.83 P +0.41 (, the cde) 344.31 121.83 P +0.41 (vSer) 383.2 121.83 P +0.41 (vice object will call the appropr) 404.06 121.83 P +0.41 (iate) 541.88 121.83 P +1 (function to process the e) 279.43 109.83 P +1 (v) 392.09 109.83 P +1 (ent and dispatch an) 396.84 109.83 P +1 (y asynchronous) 486.97 109.83 P +-0.26 (callbac) 279.43 97.83 P +-0.26 (ks that are ready) 310.35 97.83 P +-0.26 (. This is a pure vir) 383.05 97.83 P +-0.26 (tual function that m) 461.05 97.83 P +-0.26 (ust) 544.66 97.83 P +(be pro) 279.43 85.83 T +(vided b) 307.63 85.83 T +(y the ser) 339.67 85.83 T +(vice de) 378.32 85.83 T +(v) 409.7 85.83 T +(eloper) 414.45 85.83 T +(.) 441.74 85.83 T +180 354.5 558 680 C +180 371.5 558 589 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +179.21 371.5 558.79 589 R +7 X +0 0 0 1 0 0 0 K +V +185.45 374.83 557.12 581.5 R +0 X +V +0.5 H +2 Z +N +181.62 377.83 553.29 585.33 R +7 X +V +0 X +N +222.12 508.75 512.79 524.58 R +7 X +V +0 X +N +226.45 512.25 508.12 521.42 R +7 X +V +4 9 Q +0 X +(class cdevSystemBase) 313.29 515.42 T +222.12 553.58 347.79 568.58 R +7 X +V +0 X +N +226.45 557.08 343.12 565.42 R +7 X +V +0 X +(class cdevError) 244.29 559.42 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +387.12 553.58 512.79 568.58 R +7 X +V +0 X +N +391.45 557.08 508.12 565.42 R +7 X +V +0 X +(class cdevSync) 411.99 559.42 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +271.29 534.42 279.95 547.08 288.62 534.42 3 Y +7 X +V +0.1 H +0 X +N +279.95 547.08 279.95 554.08 2 L +N +279.95 524.8 279.95 534.08 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +441.29 533.92 449.95 546.58 458.62 533.92 3 Y +7 X +V +0 X +N +449.95 546.58 449.95 553.58 2 L +N +449.95 524.3 449.95 533.58 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +197.12 382.42 537.79 479.08 R +7 X +V +0.5 H +0 X +N +202.04 386.75 533.7 475.92 R +7 X +V +0 X +(class cdevService) 321.97 469.92 T +(methods:) 202.04 458.92 T +(getFd \050int* &, int &\051 {pure virtual} :int) 215.37 447.92 T +(getNameServer \050cdevDevice* &\051 {pure virtual} :int) 215.37 436.92 T +(registerFd \050int, int\051 {virtual} :int) 215.37 425.92 T +-0.31 (name \050void\051 {virtual} :char *) 215.37 414.92 P +(getCollectionRequest \050...\051 {virtual} :int) 215.37 403.92 T +-0.36 (className \050void\051 {virtual} :char *) 215.37 392.92 P +197.12 466.42 537.95 466.42 2 L +N +358.79 489.25 367.45 501.92 376.12 489.25 3 Y +7 X +V +0.1 H +0 X +N +367.45 501.92 367.45 508.92 2 L +N +367.45 479.63 367.45 488.92 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +180 354.5 558 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "33" 43 +%%Page: "34" 44 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(11. The cde) 54 739 T +(vSer) 101.26 739 T +(vice Class) 120.03 739 T +0 10 Q +(34) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(pend) 162 713.33 T +3 F +(int pend \050doub) 261.29 713.33 T +(le seconds) 325.02 713.33 T +(, int fd\051;) 372.67 713.33 T +0 F +0.11 (Processes all I/O e) 261.29 696.33 P +0.11 (v) 345.23 696.33 P +0.11 (ents that occur on the \336le descr) 349.98 696.33 P +0.11 (iptor dur) 489.72 696.33 P +0.11 (ing) 526.66 696.33 P +0.13 (the speci\336ed per) 261.43 684.33 P +0.13 (iod of time) 335.22 684.33 P +0.13 (. If the fd par) 381.46 684.33 P +0.13 (ameter is not pro) 438.04 684.33 P +0.13 (vided,) 513.32 684.33 P +2.58 (the cde) 261.43 672.33 P +2.58 (vSer) 296.51 672.33 P +2.58 (vice object will w) 317.37 672.33 P +2.58 (ait f) 398.85 672.33 P +2.58 (or I/O e) 417.25 672.33 P +2.58 (v) 455.46 672.33 P +2.58 (ents on all of its) 460.21 672.33 P +0.23 (contained \336le descr) 261.43 660.33 P +0.23 (iptors) 348.19 660.33 P +0.23 (. When an e) 372.49 660.33 P +0.23 (v) 426.81 660.33 P +0.23 (ent occurs on one of the) 431.56 660.33 P +0.41 (\336le descr) 261.43 648.33 P +0.41 (iptors) 302.01 648.33 P +0.41 (, the cde) 326.31 648.33 P +0.41 (vSer) 365.2 648.33 P +0.41 (vice object will call the appropr) 386.06 648.33 P +0.41 (iate) 523.88 648.33 P +0.38 (functions to process the e) 261.43 636.33 P +0.38 (v) 376.59 636.33 P +0.38 (ent and dispatch an) 381.34 636.33 P +0.38 (y asynchronous) 469.59 636.33 P +-0.26 (callbac) 261.43 624.33 P +-0.26 (ks that are ready) 292.35 624.33 P +-0.26 (. This is a pure vir) 365.05 624.33 P +-0.26 (tual function that m) 443.05 624.33 P +-0.26 (ust) 526.66 624.33 P +(be pro) 261.43 612.33 T +(vided b) 289.63 612.33 T +(y the ser) 321.67 612.33 T +(vice de) 360.32 612.33 T +(v) 391.7 612.33 T +(eloper) 396.45 612.33 T +(.) 423.74 612.33 T +2 F +(g) 162 588.33 T +(etRequestObject) 168.21 588.33 T +3 F +(int getRequestObject \050) 261.29 588.33 T +(char *de) 368.57 588.33 T +(v) 405.51 588.33 T +(, char *msg,) 409.71 588.33 T +(cde) 368.57 576.33 T +(vRequestObject* &req\051;) 384.39 576.33 T +0 F +-0.17 (Obtains a pointer to a) 261.29 559.33 P +3 F +-0.17 (cde) 358.84 559.33 P +-0.17 (vRequestObject) 374.66 559.33 P +0 F +-0.17 ( that is speci\336c to this) 445.8 559.33 P +2.06 (ser) 261.43 547.33 P +2.06 (vice and the speci\336ed de) 275.62 547.33 P +2.06 (vice/message combination. This) 393.61 547.33 P +-0.16 (method should only be called b) 261.43 535.33 P +-0.16 (y the) 398.28 535.33 P +3 F +-0.16 (cde) 422.41 535.33 P +-0.16 (vSystem) 438.23 535.33 P +0 F +-0.16 ( object. This is) 476.57 535.33 P +1.93 (a pure vir) 261.43 523.33 P +1.93 (tual function that m) 307.37 523.33 P +1.93 (ust be pro) 397.56 523.33 P +1.93 (vided b) 445.74 523.33 P +1.93 (y the ser) 479.71 523.33 P +1.93 (vice) 522.22 523.33 P +(de) 261.43 511.33 T +(v) 272.25 511.33 T +(eloper) 277 511.33 T +(.) 304.29 511.33 T +2 F +(g) 162 487.33 T +(etNameSer) 168.21 487.33 T +(ver) 220.55 487.33 T +3 F +(int getNameSer) 261.29 487.33 T +(v) 331.06 487.33 T +(er \050cde) 335.81 487.33 T +(vDe) 366.63 487.33 T +(vice* &ser) 384.11 487.33 T +(v) 429.42 487.33 T +(er\051;) 434.17 487.33 T +0 F +1.95 (Obtains a cde) 261.29 470.33 P +1.95 (vDe) 326.58 470.33 P +1.95 (vice object identifying the name ser) 344.06 470.33 P +1.95 (v) 510.27 470.33 P +1.95 (er f) 515.02 470.33 P +1.95 (or) 531.11 470.33 P +0.65 (this ser) 261.43 458.33 P +0.65 (vice) 294.62 458.33 P +0.65 (. A ser) 312.25 458.33 P +0.65 (vice is not required to pro) 342.76 458.33 P +0.65 (vide its o) 458.15 458.33 P +0.65 (wn name) 498.77 458.33 P +0.32 (ser) 261.43 446.33 P +0.32 (v) 275.62 446.33 P +0.32 (er and ma) 280.37 446.33 P +0.32 (y simply set the) 325.74 446.33 P +3 F +0.32 (ser) 398.72 446.33 P +0.32 (v) 412.91 446.33 P +0.32 (er) 417.66 446.33 P +0 F +0.32 ( par) 426.55 446.33 P +0.32 (ameter to) 444 446.33 P +3 F +0.32 (NULL) 489.67 446.33 P +0 F +0.32 (. This) 515.23 446.33 P +1.35 (is a pure vir) 261.43 434.33 P +1.35 (tual function an m) 317.57 434.33 P +1.35 (ust be pro) 400.45 434.33 P +1.35 (vided b) 447.48 434.33 P +1.35 (y the ser) 480.87 434.33 P +1.35 (vice) 522.22 434.33 P +(de) 261.43 422.33 T +(v) 272.25 422.33 T +(eloper) 277 422.33 T +(.) 304.29 422.33 T +2 F +(g) 162 398.33 T +(etCollectionRequest) 168.21 398.33 T +3 F +(int getCollectionRequest \050) 267.67 398.33 T +(char ** de) 396.07 398.33 T +(vices) 439.68 398.33 T +(,) 462.31 398.33 T +(int nDe) 396.07 386.33 T +(vices) 427.45 386.33 T +(, char * msg,) 450.08 386.33 T +(cde) 396.07 374.33 T +(vCollectionRequest * &req\051;) 411.89 374.33 T +0 F +14.35 (This method allo) 261.29 357.33 P +14.35 (ws the caller to obtain a) 363.2 357.33 P +-0.14 (cde) 261.43 345.33 P +-0.14 (vCollectionRequest object that will contain only de) 277.25 345.33 P +-0.14 (vices that) 497.9 345.33 P +4.13 (are associated with the ser) 261.43 333.33 P +4.13 (vice) 397.21 333.33 P +4.13 (. A def) 414.84 333.33 P +4.13 (ault mechanism is) 451.71 333.33 P +1.74 (pro) 261.43 321.33 P +1.74 (vided to suppor) 275.73 321.33 P +1.74 (t this functionality) 347.97 321.33 P +1.74 (, ho) 427.14 321.33 P +1.74 (w) 445.41 321.33 P +1.74 (e) 452.53 321.33 P +1.74 (v) 457.79 321.33 P +1.74 (er) 462.54 321.33 P +1.74 (, the de) 470.93 321.33 P +1.74 (v) 507.46 321.33 P +1.74 (eloper) 512.21 321.33 P +5.42 (ma) 261.43 309.33 P +5.42 (y create a special request object to optimiz) 275.02 309.33 P +5.42 (e these) 501.78 309.33 P +(oper) 261.43 297.33 T +(ations) 281.34 297.33 T +(.) 307.87 297.33 T +2 F +(g) 162 273.33 T +(etFd) 168.21 273.33 T +3 F +(int getFd \050int* &fd, int &n) 261.29 273.33 T +(umFd\051;) 369.58 273.33 T +0 F +0.72 (Retr) 261.29 256.33 P +0.72 (ie) 280.33 256.33 P +0.72 (v) 287.81 256.33 P +0.72 (es a list of \336le descr) 292.56 256.33 P +0.72 (iptors that are contained within the) 384.11 256.33 P +0.93 (cde) 261.43 244.33 P +0.93 (vSer) 277.25 244.33 P +0.93 (vice object. The) 298.11 244.33 P +3 F +0.93 (fd) 373.7 244.33 P +0 F +0.93 ( pointer will be giv) 382.04 244.33 P +0.93 (en the pointer to) 464.95 244.33 P +0.3 (the inter) 261.43 232.33 P +0.3 (nal arr) 298.11 232.33 P +0.3 (a) 326.65 232.33 P +0.3 (y of \336le descr) 331.91 232.33 P +0.3 (iptors) 391.87 232.33 P +0.3 (, and the) 416.17 232.33 P +3 F +0.3 (n) 458.77 232.33 P +0.3 (umFD) 464.23 232.33 P +0 F +0.3 ( par) 491.45 232.33 P +0.3 (ameter) 508.88 232.33 P +0.2 (will be set to the n) 261.43 220.33 P +0.2 (umber of \336le descr) 342.36 220.33 P +0.2 (iptors in the list. A ser) 425.35 220.33 P +0.2 (vice) 522.22 220.33 P +0.31 (that does not use \336le descr) 261.43 208.33 P +0.31 (iptors should set the) 382.63 208.33 P +3 F +0.31 (fd) 476.12 208.33 P +0 F +0.31 ( and) 484.46 208.33 P +3 F +0.31 (n) 507.32 208.33 P +0.31 (umFD) 512.78 208.33 P +0 F +0.83 (par) 261.43 196.33 P +0.83 (ameters to) 275.78 196.33 P +3 F +0.83 (NULL) 327.46 196.33 P +0 F +0.83 ( and) 353.02 196.33 P +3 F +0.83 (0) 376.92 196.33 P +0 F +0.83 (, respectiv) 382.48 196.33 P +0.83 (ely) 428.64 196.33 P +0.83 (. This is a pure vir) 440.42 196.33 P +0.83 (tual) 523.88 196.33 P +(function that m) 261.43 184.33 T +(ust be pro) 326.92 184.33 T +(vided b) 371.24 184.33 T +(y the ser) 403.28 184.33 T +(vice de) 441.93 184.33 T +(v) 473.31 184.33 T +(eloper) 478.06 184.33 T +(.) 505.35 184.33 T +2 F +(registerFd) 162 160.33 T +3 F +(int registerFd \050int fd, int opened\051;) 261.29 160.33 T +0 F +2.41 (The ser) 261.29 143.33 P +2.41 (vice de) 297.9 143.33 P +2.41 (v) 331.7 143.33 P +2.41 (eloper ma) 336.45 143.33 P +2.41 (y implement this method to allo) 383.02 143.33 P +2.41 (w) 532.78 143.33 P +-0.11 (e) 261.43 131.33 P +-0.11 (xter) 266.69 131.33 P +-0.11 (nal \336le descr) 283.61 131.33 P +-0.11 (iptors to be added to the list of \336le descr) 339.66 131.33 P +-0.11 (iptors) 515.55 131.33 P +4.2 (in the ser) 261.43 119.33 P +4.2 (vice) 311.27 119.33 P +4.2 (. The) 328.9 119.33 P +3 F +4.2 (fd) 362.88 119.33 P +0 F +4.2 ( par) 371.22 119.33 P +4.2 (ameter should contain the \336le) 392.56 119.33 P +-0.22 (descr) 261.43 107.33 P +-0.22 (iptor) 286.03 107.33 P +-0.22 (, and the) 304.98 107.33 P +3 F +-0.22 (opened) 346.01 107.33 P +0 F +-0.22 ( par) 379.37 107.33 P +-0.22 (ameter should contain 1 to add it) 396.27 107.33 P +(to the list or 0 to remo) 261.43 95.33 T +(v) 357.99 95.33 T +(e it from the list.) 362.74 95.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "34" 44 +%%Page: "35" 45 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(11. The cde) 450.96 739 T +(vSer) 498.22 739 T +(vice Class) 517 739 T +0 10 Q +(35) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(autoErr) 180 713.33 T +(orOn) 215.36 713.33 T +3 F +(int autoErrorOn \050v) 279.29 713.33 T +(oid\051;) 358.51 713.33 T +0 F +1.67 (Inf) 279.29 696.33 P +1.67 (or) 290.11 696.33 P +1.67 (ms the cde) 299.25 696.33 P +1.67 (vSer) 351.2 696.33 P +1.67 (vice object that it should use its inter) 372.07 696.33 P +1.67 (nal) 544.66 696.33 P +1.36 (def) 279.43 684.33 P +1.36 (ault error handler to process an) 293.03 684.33 P +1.36 (y error messages that are) 438.63 684.33 P +3.17 (gener) 279.43 672.33 P +3.17 (ated b) 304.9 672.33 P +3.17 (y objects within its control. This is the def) 335.67 672.33 P +3.17 (ault) 541.88 672.33 P +(oper) 279.43 660.33 T +(ating condition f) 299.34 660.33 T +(or the cde) 369.08 660.33 T +(vSer) 413.25 660.33 T +(vice object.) 434.11 660.33 T +2 F +(autoErr) 180 636.33 T +(orOff) 215.36 636.33 T +3 F +(int autoErrorOff \050v) 279.29 636.33 T +(oid\051;) 358.51 636.33 T +0 F +1.67 (Inf) 279.29 619.33 P +1.67 (or) 290.11 619.33 P +1.67 (ms the cde) 299.25 619.33 P +1.67 (vSer) 351.2 619.33 P +1.67 (vice object that it should use its inter) 372.07 619.33 P +1.67 (nal) 544.66 619.33 P +1.36 (def) 279.43 607.33 P +1.36 (ault error handler to process an) 293.03 607.33 P +1.36 (y error messages that are) 438.63 607.33 P +3.17 (gener) 279.43 595.33 P +3.17 (ated b) 304.9 595.33 P +3.17 (y objects within its control. This is the def) 335.67 595.33 P +3.17 (ault) 541.88 595.33 P +(oper) 279.43 583.33 T +(ating condition f) 299.34 583.33 T +(or the cde) 369.08 583.33 T +(vSer) 413.25 583.33 T +(vice object.) 434.11 583.33 T +2 F +(repor) 180 559.33 T +(tErr) 205.76 559.33 T +(or) 223.34 559.33 T +3 F +(int repor) 279.29 559.33 T +(tError \050) 316.37 559.33 T +(int se) 351.57 559.33 T +(v) 375.17 559.33 T +(er) 379.92 559.33 T +(ity) 388.96 559.33 T +(, char *name) 397.96 559.33 T +(,) 454.5 559.33 T +(cde) 351.57 547.33 T +(vRequestObject *obj,) 367.39 547.33 T +(char *f) 351.57 535.33 T +(or) 380.17 535.33 T +(matStr) 389.31 535.33 T +(ing,...\051;) 418.91 535.33 T +0 F +4.13 (Emits an error message) 279.29 518.33 P +4.13 (. The se) 397.68 518.33 P +4.13 (v) 441.77 518.33 P +4.13 (er) 446.52 518.33 P +4.13 (ity \336eld indicates the) 455.56 518.33 P +1.09 (se) 279.43 506.33 P +1.09 (v) 289.69 506.33 P +1.09 (er) 294.44 506.33 P +1.09 (ity of the error) 303.48 506.33 P +1.09 (, the name str) 367.93 506.33 P +1.09 (ing identi\336es the object that) 432.48 506.33 P +11.86 (gener) 279.43 494.33 P +11.86 (ated the error) 304.9 494.33 P +11.86 (, the obj par) 388.16 494.33 P +11.86 (ameter is the) 476.47 494.33 P +1.32 (cde) 279.43 482.33 P +1.32 (vRequestObject that w) 295.25 482.33 P +1.32 (as in use when the error occurred,) 398.34 482.33 P +0.71 (and the f) 279.43 470.33 P +0.71 (or) 319.47 470.33 P +0.71 (matStr) 328.61 470.33 P +0.71 (ing and additional par) 358.21 470.33 P +0.71 (ameters \050...\051 should be) 455.84 470.33 P +2.71 (f) 279.43 458.33 P +2.71 (or) 281.91 458.33 P +2.71 (matted in the same manner as the par) 291.05 458.33 P +2.71 (ameters used b) 478.87 458.33 P +2.71 (y) 553 458.33 P +(pr) 279.43 446.33 T +(intf) 288.47 446.33 T +(.) 301.51 446.33 T +0.9 (The integer used b) 279.29 429.33 P +0.9 (y se) 365.16 429.33 P +0.9 (v) 384.09 429.33 P +0.9 (er) 388.84 429.33 P +0.9 (ity should ha) 397.88 429.33 P +0.9 (v) 455.61 429.33 P +0.9 (e one of the f) 460.36 429.33 P +0.9 (ollo) 522.03 429.33 P +0.9 (wing) 537.44 429.33 P +(v) 279.43 417.33 T +(alues indicating the se) 284.18 417.33 T +(v) 382.82 417.33 T +(er) 387.57 417.33 T +(ity of the error that has occurred.) 396.61 417.33 T +2 F +(CDEV_SEVERITY_INFO:) 279.29 400.33 T +0 F +(No error) 419.31 400.33 T +(.) 455.48 400.33 T +2 F +(CDEV_SEVERITY_W) 279.29 383.33 T +(ARN:) 376.49 383.33 T +0 F +(An error occurred that should) 419.31 383.33 T +(not impact contin) 419.67 371.33 T +(ued) 495.16 371.33 T +(processing.) 419.67 359.33 T +2 F +(CDEV_SEVERITY_ERR) 279.29 342.33 T +(OR:) 388.56 342.33 T +0 F +(An error occurred and should) 419.31 342.33 T +(be corrected bef) 419.67 330.33 T +(ore contin) 491.63 330.33 T +(uing.) 535.44 330.33 T +2 F +(CDEV_SEVERITY_SEVERE:) 279.29 313.33 T +0 F +(A se) 419.31 313.33 T +(v) 439.02 313.33 T +(ere or f) 443.77 313.33 T +(atal error has) 475.15 313.33 T +(occurred and cde) 419.67 301.33 T +(v cannot) 496.63 301.33 T +(contin) 419.67 289.33 T +(ue nor) 446.25 289.33 T +(mal e) 474.85 289.33 T +(x) 499 289.33 T +(ecution.) 503.7 289.33 T +2 F +(setErr) 180 248.33 T +(orHandler) 208.7 248.33 T +3 F +(v) 279.29 248.33 T +(oid setErrorHandler \050cde) 284.04 248.33 T +(vErrorHandler handler\051;) 392.66 248.33 T +0 F +2.41 (Used to to install a user speci\336ed error handler) 279.29 231.33 P +2.41 (. This error) 504.84 231.33 P +0.68 (handler will be called when an error occurs if the) 279.43 219.33 P +3 F +0.68 (autoErrorOff) 502.98 219.33 P +0 F +0 (method has been used to disab) 279.43 207.33 P +0 (le the def) 418.75 207.33 P +0 (ault error handler) 459.58 207.33 P +0 (. The) 535.21 207.33 P +6.28 (user pro) 279.43 195.33 P +6.28 (vided error handler should ha) 322.24 195.33 P +6.28 (v) 477.22 195.33 P +6.28 (e the f) 481.97 195.33 P +6.28 (ollo) 522.03 195.33 P +6.28 (wing) 537.44 195.33 P +(prototype:) 279.43 183.33 T +3 F +(v) 279.29 166.33 T +(oid handler \050int se) 284.04 166.33 T +(v) 363.22 166.33 T +(er) 367.97 166.33 T +(ity) 377.01 166.33 T +(, char *te) 386.01 166.33 T +(xt, cde) 425.73 166.33 T +(vRequestObject *obj\051;) 454.89 166.33 T +0 F +4.89 (The) 279.29 149.33 P +3 F +4.89 (se) 304.19 149.33 P +4.89 (v) 314.45 149.33 P +4.89 (er) 319.2 149.33 P +4.89 (ity) 328.24 149.33 P +0 F +4.89 ( par) 338.24 149.33 P +4.89 (ameter will contain one of the integers) 360.26 149.33 P +0.81 (speci\336ed in the) 279.43 137.33 P +3 F +0.81 (repor) 351.34 137.33 P +0.81 (tError) 375.08 137.33 P +0 F +0.81 (documentation, the) 403.67 137.33 P +3 F +0.81 (te) 493.12 137.33 P +0.81 (xt) 501.16 137.33 P +0 F +0.81 ( par) 508.94 137.33 P +0.81 (ameter) 526.88 137.33 P +2.11 (will contain the te) 279.43 125.33 P +2.11 (xt of the error) 362.17 125.33 P +2.11 (, and the) 427.48 125.33 P +3 F +2.11 (obj) 475.52 125.33 P +0 F +2.11 ( par) 488.86 125.33 P +2.11 (ameter will) 508.11 125.33 P +0.37 (contain the cde) 279.43 113.33 P +0.37 (vRequestObject that w) 347.69 113.33 P +0.37 (as in use when the error) 448.88 113.33 P +(occurred.) 279.43 101.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "35" 45 +%%Page: "36" 46 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(11. The cde) 54 739 T +(vSer) 101.26 739 T +(vice Class) 120.03 739 T +0 10 Q +(36) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(setThreshold) 162 713.33 T +3 F +(v) 261.29 713.33 T +(oid setThreshold \050int errorThreshold\051;) 266.04 713.33 T +0 F +0.77 (Used to specify the le) 261.29 696.33 P +0.77 (v) 359.66 696.33 P +0.77 (el of se) 364.41 696.33 P +0.77 (v) 397.88 696.33 P +0.77 (er) 402.63 696.33 P +0.77 (ity at which errors should be) 411.67 696.33 P +2.4 (submitted to the error handler) 261.43 684.33 P +2.4 (. The v) 401.71 684.33 P +2.4 (alue of) 436.83 684.33 P +3 F +2.4 (errorThreshold) 474.43 684.33 P +0 F +0.23 (should be one of the se) 261.43 672.33 P +0.23 (v) 366.26 672.33 P +0.23 (er) 371.01 672.33 P +0.23 (ity le) 380.05 672.33 P +0.23 (v) 400.54 672.33 P +0.23 (els speci\336ed in the) 405.29 672.33 P +3 F +0.23 (repor) 491.26 672.33 P +0.23 (tError) 515 672.33 P +0 F +(method.) 261.43 660.33 T +2 F +(name) 162 636.33 T +3 F +(char *name \050v) 261.29 636.33 T +(oid\051 const;) 323.28 636.33 T +0 F +3.89 (Retr) 261.29 619.33 P +3.89 (ie) 280.33 619.33 P +3.89 (v) 287.81 619.33 P +3.89 (es the name of the ser) 292.56 619.33 P +3.89 (vice) 411.79 619.33 P +3.89 (. This method is used) 429.42 619.33 P +1.52 (e) 261.43 607.33 P +1.52 (xtensiv) 266.69 607.33 P +1.52 (ely to deter) 297.56 607.33 P +1.52 (mine the ser) 350.33 607.33 P +1.52 (vice that under) 408.7 607.33 P +1.52 (lies a speci\336c) 477.49 607.33 P +3 F +2.38 (cde) 261.43 595.33 P +2.38 (vRequestObject) 277.25 595.33 P +0 F +2.38 ( object. If not o) 348.39 595.33 P +2.38 (v) 423.37 595.33 P +2.38 (er-r) 428.12 595.33 P +2.38 (idden b) 443.82 595.33 P +2.38 (y the ser) 478.8 595.33 P +2.38 (vice) 522.22 595.33 P +(de) 261.43 583.33 T +(v) 272.25 583.33 T +(eloper) 277 583.33 T +(, this method will retur) 304.29 583.33 T +(n the str) 401.79 583.33 T +(ing \322cde) 438.07 583.33 T +(vSer) 473.34 583.33 T +(vice\323.) 494.2 583.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "36" 46 +%%Page: "37" 47 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(12. The cde) 461.23 739 T +(vSync Class) 508.49 739 T +0 10 Q +(37) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(12.) 151.54 710.67 T +(The cde) 180 710.67 T +(vSync Class) 232.7 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w of the) 108.64 673.33 T +(cde) 72 661.33 T +(vSync Class) 89.08 661.33 T +0 F +0.32 (The) 180 673.33 P +3 F +0.32 (cde) 200.33 673.33 P +0.32 (vSync) 216.15 673.33 P +0 F +0.32 (C++ class is a pure vir) 246.48 673.33 P +0.32 (tual base class that declares the I/O oper) 347.41 673.33 P +0.32 (ations) 531.32 673.33 P +3.05 (that m) 180 661.33 P +3.05 (ust be suppor) 210.74 661.33 P +3.05 (ted b) 277.84 661.33 P +3.05 (y the cde) 302.93 661.33 P +3.05 (vSer) 349.32 661.33 P +3.05 (vice object and the cde) 370.18 661.33 P +3.05 (vSystem object.) 484.37 661.33 P +(Because se) 180 649.33 T +(v) 231.95 649.33 T +(er) 236.7 649.33 T +(al of its functions are pure vir) 245.49 649.33 T +(tual, it cannot be instantiated directly) 373.72 649.33 T +(.) 534.47 649.33 T +3 9 Q +(Figure 14: Object model of the cde) 180 616 T +(vSync class) 320.3 616 T +2 10 Q +(Pub) 72 463.67 T +(lic Methods of) 90.79 463.67 T +(the cde) 72 451.67 T +(vSync) 106.86 451.67 T +(Class) 72 439.67 T +(\337ush) 180 463.67 T +3 F +(int \337ush \050v) 279.29 463.67 T +(oid\051;) 324.61 463.67 T +0 F +2.79 (Flushes an) 279.29 446.67 P +2.79 (y pending outbound requests to their respectiv) 330.84 446.67 P +2.79 (e) 552.44 446.67 P +1.01 (ser) 279.43 434.67 P +1.01 (vices) 293.62 434.67 P +1.01 (. This is a pure vir) 316.25 434.67 P +1.01 (tual method that is implemented in) 400.64 434.67 P +(der) 279.43 422.67 T +(iv) 294.03 422.67 T +(ed classes) 301 422.67 T +(.) 348.09 422.67 T +2 F +(poll) 180 398.67 T +3 F +(int poll \050v) 279.29 398.67 T +(oid\051;) 319.05 398.67 T +0 F +1.36 (Directly polls each of the under) 279.29 381.67 P +1.36 (lying ser) 423.52 381.67 P +1.36 (vices f) 462.41 381.67 P +1.36 (or activity) 491.81 381.67 P +1.36 (, and) 534.4 381.67 P +1.18 (deliv) 279.43 369.67 P +1.18 (ers an) 299.74 369.67 P +1.18 (y asynchronous callbac) 328.56 369.67 P +1.18 (ks that are ready) 434.65 369.67 P +1.18 (. This is a) 511.67 369.67 P +0 (pure vir) 279.43 357.67 P +0 (tual function that is implemented in the der) 313.17 357.67 P +0 (iv) 501.16 357.67 P +0 (ed classes) 508.13 357.67 P +0 (.) 555.22 357.67 P +2 F +(pend) 180 333.67 T +3 F +(int pend \050int fd\051;) 279.29 333.67 T +0 F +0.01 (W) 279.29 316.67 P +0.01 (aits f) 288.33 316.67 P +0.01 (or a def) 309.16 316.67 P +0.01 (ault per) 342.8 316.67 P +0.01 (iod of time f) 376.31 316.67 P +0.01 (or the speci\336ed \336le descr) 427.74 316.67 P +0.01 (iptor) 538.55 316.67 P +1.27 (to ha) 279.43 304.67 P +1.27 (v) 302.74 304.67 P +1.27 (e an I/O e) 307.49 304.67 P +1.27 (v) 354.92 304.67 P +1.27 (ent. If the fd par) 359.67 304.67 P +1.27 (ameter is not pro) 434.69 304.67 P +1.27 (vided, the) 513.37 304.67 P +3.78 (cde) 279.43 292.67 P +3.78 (vSync object will w) 295.25 292.67 P +3.78 (ait f) 389.79 292.67 P +3.78 (or an I/O e) 409.39 292.67 P +3.78 (v) 467.68 292.67 P +3.78 (ent on an) 472.43 292.67 P +3.78 (y of its) 521.54 292.67 P +0.23 (contained \336le descr) 279.43 280.67 P +0.23 (iptors) 366.19 280.67 P +0.23 (. When an e) 390.49 280.67 P +0.23 (v) 444.81 280.67 P +0.23 (ent occurs on one of the) 449.56 280.67 P +1.84 (\336le descr) 279.43 268.67 P +1.84 (iptors) 321.43 268.67 P +1.84 (, the cde) 345.73 268.67 P +1.84 (vSync object will call the appropr) 387.48 268.67 P +1.84 (iate) 541.88 268.67 P +0.38 (functions to process the e) 279.43 256.67 P +0.38 (v) 394.59 256.67 P +0.38 (ent and dispatch an) 399.34 256.67 P +0.38 (y asynchronous) 487.59 256.67 P +1.04 (callbac) 279.43 244.67 P +1.04 (ks that are ready) 310.35 244.67 P +1.04 (. This is a pure vir) 386.96 244.67 P +1.04 (tual function that is) 471.49 244.67 P +(implemented in the der) 279.43 232.67 T +(iv) 381.29 232.67 T +(ed classes) 388.26 232.67 T +(.) 435.35 232.67 T +2 F +(pend) 180 208.67 T +3 F +(int pend \050doub) 279.29 208.67 T +(le seconds) 343.02 208.67 T +(, int fd\051;) 390.67 208.67 T +0 F +0.11 (Processes all I/O e) 279.29 191.67 P +0.11 (v) 363.23 191.67 P +0.11 (ents that occur on the \336le descr) 367.98 191.67 P +0.11 (iptor dur) 507.72 191.67 P +0.11 (ing) 544.66 191.67 P +0.13 (the speci\336ed per) 279.43 179.67 P +0.13 (iod of time) 353.22 179.67 P +0.13 (. If the fd par) 399.46 179.67 P +0.13 (ameter is not pro) 456.04 179.67 P +0.13 (vided,) 531.32 179.67 P +3.62 (the cde) 279.43 167.67 P +3.62 (vSync object will w) 315.55 167.67 P +3.62 (ait f) 409.59 167.67 P +3.62 (or I/O e) 429.03 167.67 P +3.62 (v) 469.31 167.67 P +3.62 (ents on all of its) 474.06 167.67 P +0.23 (contained \336le descr) 279.43 155.67 P +0.23 (iptors) 366.19 155.67 P +0.23 (. When an e) 390.49 155.67 P +0.23 (v) 444.81 155.67 P +0.23 (ent occurs on one of the) 449.56 155.67 P +1.84 (\336le descr) 279.43 143.67 P +1.84 (iptors) 321.43 143.67 P +1.84 (, the cde) 345.73 143.67 P +1.84 (vSync object will call the appropr) 387.48 143.67 P +1.84 (iate) 541.88 143.67 P +0.38 (functions to process the e) 279.43 131.67 P +0.38 (v) 394.59 131.67 P +0.38 (ent and dispatch an) 399.34 131.67 P +0.38 (y asynchronous) 487.59 131.67 P +1.04 (callbac) 279.43 119.67 P +1.04 (ks that are ready) 310.35 119.67 P +1.04 (. This is a pure vir) 386.96 119.67 P +1.04 (tual function that is) 471.49 119.67 P +(implemented in the der) 279.43 107.67 T +(iv) 381.29 107.67 T +(ed classes) 388.26 107.67 T +(.) 435.35 107.67 T +180 489.33 558 680 C +180 506.33 558 613 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +179.21 506.33 558.79 613 R +7 X +0 0 0 1 0 0 0 K +V +185.45 509.67 557.12 605.5 R +0 X +V +0.5 H +2 Z +N +181.62 513.5 553.29 609.33 R +7 X +V +0 X +N +222.12 519.33 512.79 603.5 R +7 X +V +0 X +N +226.45 523.67 508.12 600.33 R +7 X +V +4 9 Q +0 X +(class cdevSync) 329.49 594.33 T +(methods:) 226.45 583.33 T +(flush \050 void \051 {pure virtual} :int) 239.79 572.33 T +(poll \050 void \051 {pure virtual} :int) 239.79 561.33 T +(pend \050 int \051 {pure virtual} :int) 239.79 550.33 T +(pend \050 double, int \051 {pure virtual} :int) 239.79 539.33 T +-0.57 (className \050 void \051 {virtual} :char *) 239.79 528.33 P +222.29 590.83 512.45 590.83 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +180 489.33 558 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "37" 47 +%%Page: "38" 48 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(13. The cde) 54 739 T +(vSystemBase Class) 101.26 739 T +0 10 Q +(38) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(13.) 133.54 710.67 T +(The cde) 162 710.67 T +(vSystemBase Class) 214.7 710.67 T +2 10 Q +(Over) 54 673.33 T +(vie) 76.89 673.33 T +(w of the) 90.64 673.33 T +(cde) 54 661.33 T +(vSystemBase) 71.08 661.33 T +(Class) 54 649.33 T +0 F +3.46 (The) 162 673.33 P +3 F +3.46 (cde) 185.47 673.33 P +3.46 (vSystemBase) 201.29 673.33 P +0 F +3.46 (C++ class is a pure vir) 268.66 673.33 P +3.46 (tual base class that inher) 385.27 673.33 P +3.46 (its the) 509.86 673.33 P +0.7 (capabilities of both the cde) 162 661.33 P +0.7 (vError class and the cde) 282.91 661.33 P +0.7 (vSync class) 393.24 661.33 P +0.7 (. It then declares the) 446.58 661.33 P +0.96 (functions necessar) 162 649.33 P +0.96 (y to obtain a request object. Because se) 246.63 649.33 P +0.96 (v) 430.92 649.33 P +0.96 (er) 435.67 649.33 P +0.96 (al of its functions are) 444.46 649.33 P +(pure vir) 162 637.33 T +(tual, it cannot be instantiated directly) 195.74 637.33 T +(.) 356.49 637.33 T +3 9 Q +(Figure 15: Object model of the cde) 162 604 T +(vSystemBase class) 302.3 604 T +2 10 Q +(Pub) 54 416.67 T +(lic Methods of) 72.79 416.67 T +(the) 54 404.67 T +(cde) 54 392.67 T +(vSystemBase) 71.08 392.67 T +(Class) 54 380.67 T +(g) 162 416.67 T +(etRequestObject) 168.21 416.67 T +3 F +(int getRequestObject \050) 261.29 416.67 T +(char *de) 369.29 416.67 T +(vice) 406.23 416.67 T +(, char *msg,) 423.86 416.67 T +(cde) 369.29 404.67 T +(vRequestObject &req\051;) 385.11 404.67 T +0 F +1.08 (Obtains a ref) 261.29 387.67 P +1.08 (erence to a cde) 320.4 387.67 P +1.08 (vRequestObject from a speci\336ed) 392.26 387.67 P +0.62 (de) 261.43 375.67 P +0.62 (vice name and message name) 272.25 375.67 P +0.62 (. The object that is produced) 410.74 375.67 P +6 (b) 261.43 363.67 P +6 (y this function will be o) 266.79 363.67 P +6 (wned and controlled b) 396.69 363.67 P +6 (y the) 512.32 363.67 P +1.1 (cde) 261.43 351.67 P +1.1 (vSystem object that created it. This means that) 277.25 351.67 P +3 F +1.1 (\337ush, poll) 496.67 351.67 P +0 F +3.52 (and) 261.43 339.67 P +3 F +3.52 ( pend) 278.11 339.67 P +0 F +3.52 ( commands m) 306.65 339.67 P +3.52 (ust be routed through the o) 376.37 339.67 P +3.52 (wning) 513.88 339.67 P +1.34 (cde) 261.43 327.67 P +1.34 (vSystem object in order to eff) 277.25 327.67 P +1.34 (ect this cde) 413.13 327.67 P +1.34 (vRequetsObject.) 466.08 327.67 P +(Retur) 261.43 315.67 T +(ns) 286.13 315.67 T +3 F +(CDEV_SUCCESS) 299.47 315.67 T +0 F +( or an en) 381.15 315.67 T +(umer) 420.52 315.67 T +(ated error code) 443.2 315.67 T +(.) 510.86 315.67 T +162 442.33 540 680 C +162 459.33 540 601 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +161.21 459.33 540.79 601 R +7 X +0 0 0 1 0 0 0 K +V +167.45 463.5 539.12 593.5 R +0 X +V +0.5 H +2 Z +N +163.62 468.17 535.29 597.33 R +7 X +V +0 X +N +204.12 484.92 494.79 536.58 R +7 X +V +0 X +N +208.45 488.42 490.12 533.42 R +7 X +V +4 9 Q +0 X +(class cdevSystemBase) 295.29 527.42 T +(methods:) 208.45 516.42 T +(getRequestObject \050 ... \051 {pure virtual} : int) 221.79 505.42 T +-0.34 (className \050 void \051 {virtual} : char *) 221.79 494.42 P +204.29 523.92 494.45 523.92 2 L +N +204.12 565.58 329.79 580.58 R +7 X +V +0 X +N +208.45 569.08 325.12 577.42 R +7 X +V +0 X +(class cdevError) 226.29 571.42 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +369.12 565.58 494.79 580.58 R +7 X +V +0 X +N +373.45 569.08 490.12 577.42 R +7 X +V +0 X +(class cdevSync) 393.99 571.42 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +258.29 545.58 266.95 558.25 275.62 545.58 3 Y +7 X +V +0.1 H +0 X +N +266.95 558.25 266.95 565.25 2 L +N +266.95 535.96 266.95 545.25 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +423.29 545.92 431.95 558.58 440.62 545.92 3 Y +7 X +V +0 X +N +431.95 558.58 431.95 565.58 2 L +N +431.95 536.3 431.95 545.58 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +162 442.33 540 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "38" 48 +%%Page: "39" 49 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(14. The cde) 451.23 739 T +(vSystem Class) 498.49 739 T +0 10 Q +(39) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(14.) 151.54 710.67 T +(The cde) 180 710.67 T +(vSystem Class) 232.7 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w of the) 108.64 673.33 T +(cde) 72 661.33 T +(vSystem Class) 89.08 661.33 T +0 F +0.34 (The) 180 673.33 P +3 F +0.34 (cde) 200.35 673.33 P +0.34 (vSystem) 216.18 673.33 P +0 F +0.34 (C++ class pro) 257.64 673.33 P +0.34 (vides the mechanisms that cde) 319.87 673.33 P +0.34 (v uses to manage and) 458.23 673.33 P +0.44 (comm) 180 661.33 P +0.44 (unicate with m) 207.12 661.33 P +0.44 (ultiple ser) 271.82 661.33 P +0.44 (vices) 315.35 661.33 P +0.44 (. This class also pro) 337.98 661.33 P +0.44 (vides the caller with the tools) 427.96 661.33 P +(necessar) 180 649.33 T +(y to instantiate) 220.87 649.33 T +3 F +(cde) 288.13 649.33 T +(vDe) 303.95 649.33 T +(vice) 321.43 649.33 T +0 F +( objects and) 339.21 649.33 T +3 F +(cde) 395.91 649.33 T +(vRequestObject) 411.73 649.33 T +0 F +( objects) 482.87 649.33 T +(.) 517.18 649.33 T +3 9 Q +(Figure 16: Object model of the cde) 180 616 T +(vSystem class) 320.3 616 T +2 10 Q +(Pub) 72 186.17 T +(lic Methods of) 90.79 186.17 T +(the cde) 72 174.17 T +(vSystem) 106.86 174.17 T +(Class) 72 162.17 T +(attac) 180 186.17 T +(hRef) 203.24 186.17 T +3 F +(static cde) 279.29 186.17 T +(vSystem& attachRef\050char *name) 321.23 186.17 T +(, char *pre\336x\051;) 466.13 186.17 T +0 F +1.82 (Obtains a ref) 279.29 169.17 P +1.82 (erence to a ne) 339.87 169.17 P +1.82 (w or e) 409.06 169.17 P +1.82 (xisting cde) 439.62 169.17 P +1.82 (vSystem object) 488.38 169.17 P +0.84 (that has the speci\336ed name) 279.43 157.17 P +0.84 (. The) 404.94 157.17 P +3 F +0.84 (pre\336x) 432.19 157.17 P +0 F +0.84 ( par) 456.64 157.17 P +0.84 (ameter is optional,) 474.62 157.17 P +0.88 (b) 279.43 145.17 P +0.88 (ut, if pro) 284.79 145.17 P +0.88 (vided will be prepended to the name of each) 322.52 145.17 P +3 F +0.88 (de) 529.4 145.17 P +0.88 (vice) 540.22 145.17 P +0 F +0.09 (that is requested through the named cde) 279.43 133.17 P +0.09 (vSystem object bef) 459.2 133.17 P +0.09 (ore) 543.55 133.17 P +(it is f) 279.43 121.17 T +(ound in the de) 299.69 121.17 T +(vice de\336nition \336le) 362.77 121.17 T +(.) 438.76 121.17 T +180 211.83 558 680 C +180 228.83 558 613 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +179.21 228.83 558.79 613 R +7 X +0 0 0 1 0 0 0 K +V +185.45 231.33 557.12 605.5 R +0 X +V +0.5 H +2 Z +N +181.62 234.33 553.29 609.33 R +7 X +V +0 X +N +222.12 532.75 512.79 548.58 R +7 X +V +0 X +N +226.45 536.25 508.12 545.42 R +7 X +V +4 9 Q +0 X +(class cdevSystemBase) 313.29 539.42 T +222.12 577.58 347.79 592.58 R +7 X +V +0 X +N +226.45 581.08 343.12 589.42 R +7 X +V +0 X +(class cdevError) 244.29 583.42 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +387.12 577.58 512.79 592.58 R +7 X +V +0 X +N +391.45 581.08 508.12 589.42 R +7 X +V +0 X +(class cdevSync) 411.99 583.42 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +271.29 558.42 279.95 571.08 288.62 558.42 3 Y +7 X +V +0.1 H +0 X +N +279.95 571.08 279.95 578.08 2 L +N +279.95 548.8 279.95 558.08 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +441.29 557.92 449.95 570.58 458.62 557.92 3 Y +7 X +V +0 X +N +449.95 570.58 449.95 577.58 2 L +N +449.95 548.3 449.95 557.58 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.45 307.25 550.29 503.08 R +7 X +V +0.5 H +0 X +N +188.49 311.48 547.42 498.77 R +7 X +V +0 X +(class cdevSystem) 324.76 492.77 T +(methods:) 188.49 481.77 T +-0.26 (attachRef \050char *name, char *prefix\051 :cdevSystem&) 201.83 470.77 P +-0.26 (attachPtr \050char *name, char *prefix\051 :cdevSystem*) 201.83 459.77 P +-0.17 (getDevice \050char *device\051 :cdevDevice*) 201.83 448.77 P +(getRequestObject \050 ... \051 :int) 201.83 437.77 T +(name \050void\051 :char *) 201.83 426.77 T +(prefix \050void\051 :char *) 201.83 415.77 T +(prefix \050char *prefix\051 :void) 201.83 404.77 T +(flush \050void\051 :int) 201.83 393.77 T +(poll \050void\051 :int) 201.83 382.77 T +(pend \050int fd \051 :int) 201.83 371.77 T +(pend \050double seconds, int fd\051 :int) 201.83 360.77 T +-0.16 (defaultSystem \050void\051 :cdevSystem&) 201.83 349.77 P +(getFd \050int fd[], int &numFD\051 :int) 201.83 338.77 T +(addFdChangedCallback \050cdevFdChangedCallback,void*\051 :int) 201.83 327.77 T +(className \050void\051 :char *) 201.83 316.77 T +185.82 489.18 549.91 489.18 2 L +N +358.79 513.25 367.45 525.92 376.12 513.25 3 Y +7 X +V +0.1 H +0 X +N +367.45 525.92 367.45 532.92 2 L +N +367.45 503.63 367.45 512.92 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +202.95 265.42 311.95 280.42 R +7 X +V +0.5 H +0 X +N +206.71 268.92 307.9 277.25 R +7 X +V +0 X +(class cdevService) 206.71 271.25 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +257.45 307.33 261.45 299.43 257.45 291.53 253.45 299.43 4 Y +7 X +V +0.1 H +0 X +N +257.45 291.04 257.45 281.89 2 L +N +90 450 1.98 2.25 270 257.2 283.31 GG +90 450 1.98 2.25 270 257.2 283.31 AA +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +298.37 242.41 436.54 257.41 R +7 X +V +0.5 H +0 X +N +303.14 245.92 431.41 254.25 R +7 X +V +0 X +(class cdevRequestObject) 303.14 248.25 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +371.29 306.83 375.29 298.93 371.29 291.03 367.29 298.93 4 Y +7 X +V +0.1 H +0 X +N +371.29 290.54 371.29 259.5 2 L +N +90 450 1.98 2.25 270 371.29 260.31 GG +90 450 1.98 2.25 270 371.29 260.31 AA +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +422.62 264.92 531.62 279.92 R +7 X +V +0.5 H +0 X +N +426.38 268.42 527.57 276.75 R +7 X +V +0 X +(class cdevDevice) 426.38 270.75 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +477.12 306.83 481.12 298.93 477.12 291.03 473.12 298.93 4 Y +7 X +V +0.1 H +0 X +N +477.12 290.54 477.12 281.39 2 L +N +90 450 1.98 2.25 270 476.87 282.81 GG +90 450 1.98 2.25 270 476.87 282.81 AA +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +180 211.83 558 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "39" 49 +%%Page: "40" 50 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(14. The cde) 54 739 T +(vSystem Class) 101.26 739 T +0 10 Q +(40) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(attac) 162 713.33 T +(hPtr) 185.24 713.33 T +3 F +(static cde) 261.29 713.33 T +(vSystem* attachPtr\050char *name) 303.23 713.33 T +(, char *pre\336x\051;) 442.57 713.33 T +0 F +0.83 (Obtains a pointer to a ne) 261.29 696.33 P +0.83 (w or e) 374.73 696.33 P +0.83 (xisting cde) 403.32 696.33 P +0.83 (vSystem object that) 451.08 696.33 P +(has the speci\336ed name) 261.43 684.33 T +(. The) 364.11 684.33 T +3 F +(pre\336x) 389.68 684.33 T +0 F +( par) 414.13 684.33 T +(ameter is optional, b) 431.26 684.33 T +(ut, if) 521.1 684.33 T +0.65 (pro) 261.43 672.33 P +0.65 (vided will be prepended to the name of each) 275.73 672.33 P +3 F +0.65 (de) 480.63 672.33 P +0.65 (vice) 491.45 672.33 P +0 F +0.65 ( that is) 509.23 672.33 P +1.55 (requested through the named cde) 261.43 660.33 P +1.55 (vSystem object bef) 417.41 660.33 P +1.55 (ore it is) 504.68 660.33 P +(f) 261.43 648.33 T +(ound in the de) 263.91 648.33 T +(vice de\336nition \336le) 326.99 648.33 T +(.) 402.98 648.33 T +2 F +(defaultSystem) 162 624.33 T +3 F +(static cde) 261.29 624.33 T +(vSystem &def) 303.23 624.33 T +(aultSystem \050v) 364.62 624.33 T +(oid\051;) 424.94 624.33 T +0 F +0.68 (Obtains a ref) 261.29 607.33 P +0.68 (erence to the def) 319.6 607.33 P +0.68 (ault cde) 396.4 607.33 P +0.68 (vSystem object. In most) 431.8 607.33 P +0.05 (applications this mechanism is used to access the cde) 261.43 595.33 P +0.05 (vSystem) 501.66 595.33 P +(object.) 261.43 583.33 T +2 F +(g) 162 559.33 T +(etDe) 168.21 559.33 T +(vice) 189.73 559.33 T +3 F +(cde) 261.29 559.33 T +(vDe) 277.11 559.33 T +(vice* getDe) 294.59 559.33 T +(vice \050char *de) 345.42 559.33 T +(vice\051;) 406.25 559.33 T +0 F +-0.06 (Retr) 261.29 542.33 P +-0.06 (ie) 280.33 542.33 P +-0.06 (v) 287.81 542.33 P +-0.06 (es a pointer to a cde) 292.56 542.33 P +-0.06 (vDe) 382.56 542.33 P +-0.06 (vice object b) 400.04 542.33 P +-0.06 (y name) 455.3 542.33 P +-0.06 (. The object) 487.87 542.33 P +0.09 (that is retur) 261.43 530.33 P +0.09 (ned b) 311.88 530.33 P +0.09 (y this function will be o) 336.78 530.33 P +0.09 (wned and controlled b) 437.11 530.33 P +0.09 (y) 535 530.33 P +1.28 (the cde) 261.43 518.33 P +1.28 (vSystem object that created it. This means that) 295.21 518.33 P +3 F +1.28 (\337ush,) 516.1 518.33 P +1.09 (poll) 261.43 506.33 P +0 F +1.09 (and) 280.86 506.33 P +3 F +1.09 ( pend) 297.54 506.33 P +0 F +1.09 ( commands m) 323.65 506.33 P +1.09 (ust be routed through the o) 388.51 506.33 P +1.09 (wning) 513.88 506.33 P +(cde) 261.43 494.33 T +(vSystem object in order to eff) 277.25 494.33 T +(ect this cde) 406.45 494.33 T +(vDe) 456.73 494.33 T +(vice object.) 474.21 494.33 T +2 F +(g) 162 470.33 T +(etRequestObject) 168.21 470.33 T +3 F +(int getRequestObject \050) 261.29 470.33 T +(char *de) 367.86 470.33 T +(vice) 404.8 470.33 T +(, char *msg,) 422.43 470.33 T +(cde) 367.86 458.33 T +(vRequestObject &req\051;) 383.68 458.33 T +0 F +0.16 (Retr) 261.29 441.33 P +0.16 (ie) 280.33 441.33 P +0.16 (v) 287.81 441.33 P +0.16 (es a ref) 292.56 441.33 P +0.16 (erence to a cde) 325.92 441.33 P +0.16 (vRequestObject from a speci\336ed) 395.03 441.33 P +0.62 (de) 261.43 429.33 P +0.62 (vice name and message name) 272.25 429.33 P +0.62 (. The object that is produced) 410.74 429.33 P +6 (b) 261.43 417.33 P +6 (y this function will be o) 266.79 417.33 P +6 (wned and controlled b) 396.69 417.33 P +6 (y the) 512.32 417.33 P +1.1 (cde) 261.43 405.33 P +1.1 (vSystem object that created it. This means that) 277.25 405.33 P +3 F +1.1 (\337ush, poll) 496.67 405.33 P +0 F +3.52 (and) 261.43 393.33 P +3 F +3.52 ( pend) 278.11 393.33 P +0 F +3.52 ( commands m) 306.65 393.33 P +3.52 (ust be routed through the o) 376.37 393.33 P +3.52 (wning) 513.88 393.33 P +1.34 (cde) 261.43 381.33 P +1.34 (vSystem object in order to eff) 277.25 381.33 P +1.34 (ect this cde) 413.13 381.33 P +1.34 (vRequestObject.) 466.08 381.33 P +(Retur) 261.43 369.33 T +(ns) 286.13 369.33 T +3 F +(CDEV_SUCCESS) 299.47 369.33 T +0 F +( or an en) 381.15 369.33 T +(umer) 420.52 369.33 T +(ated error code) 443.2 369.33 T +(.) 510.86 369.33 T +2 F +(name) 162 345.33 T +3 F +(char *name \050v) 261.29 345.33 T +(oid\051;) 323.28 345.33 T +0 F +(Retur) 261.29 328.33 T +(ns the name of this cde) 285.99 328.33 T +(vSystem object.) 389.08 328.33 T +2 F +(pre\336x) 162 304.33 T +3 F +(char *pre\336x \050v) 261.29 304.33 T +(oid\051;) 322.72 304.33 T +0 F +1.5 (Retr) 261.29 287.33 P +1.5 (ie) 280.33 287.33 P +1.5 (v) 287.81 287.33 P +1.5 (es a pointer to the pre\336x str) 292.56 287.33 P +1.5 (ing that is currently being) 422.86 287.33 P +1 (used b) 261.43 275.33 P +1 (y the cde) 292.26 275.33 P +1 (vSystem object. See the) 334.54 275.33 P +3 F +1 (attachPtr) 449.17 275.33 P +0 F +1 ( entr) 489.19 275.33 P +1 (y f) 510.5 275.33 P +1 (or a) 521.77 275.33 P +(descr) 261.43 263.33 T +(iption of the pre\336x str) 286.03 263.33 T +(ing.) 379 263.33 T +2 F +(pre\336x) 162 239.33 T +3 F +(v) 261.29 239.33 T +(oid pre\336x \050char *pre\051;) 266.04 239.33 T +0 F +-0.05 (Changes the pre\336x str) 261.29 222.33 P +-0.05 (ing that is being used b) 359.1 222.33 P +-0.05 (y the cde) 461.48 222.33 P +-0.05 (vSystem) 501.66 222.33 P +1.5 (object. See the) 261.43 210.33 P +3 F +1.5 (attachPtr) 335.41 210.33 P +0 F +1.5 ( entr) 375.43 210.33 P +1.5 (y f) 397.23 210.33 P +1.5 (or a descr) 408.99 210.33 P +1.5 (iption of the pre\336x) 456.59 210.33 P +(str) 261.43 198.33 T +(ing.) 272.69 198.33 T +2 F +(\337ush) 162 174.33 T +3 F +(int \337ush \050v) 261.29 174.33 T +(oid\051;) 306.61 174.33 T +0 F +2.79 (Flushes an) 261.29 157.33 P +2.79 (y pending outbound requests to their respectiv) 312.84 157.33 P +2.79 (e) 534.44 157.33 P +(ser) 261.43 145.33 T +(vices) 275.62 145.33 T +(.) 298.25 145.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "40" 50 +%%Page: "41" 51 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(14. The cde) 451.23 739 T +(vSystem Class) 498.49 739 T +0 10 Q +(41) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(poll) 180 713.33 T +3 F +(int poll \050v) 279.29 713.33 T +(oid\051;) 319.05 713.33 T +0 F +0.4 (Directly polls each of the cde) 279.29 696.33 P +0.4 (vSystem\325) 408.79 696.33 P +0.4 (s under) 448.85 696.33 P +0.4 (lying ser) 482.75 696.33 P +0.4 (vices f) 520.67 696.33 P +0.4 (or) 549.11 696.33 P +3.66 (activity) 279.43 684.33 P +3.66 (, and deliv) 308.99 684.33 P +3.66 (ers an) 361.64 684.33 P +3.66 (y asynchronous callbac) 392.94 684.33 P +3.66 (ks that are) 503.99 684.33 P +(ready) 279.43 672.33 T +(.) 303.44 672.33 T +2 F +(pend) 180 648.33 T +3 F +(int pend \050int fd\051;) 279.29 648.33 T +0 F +0.01 (W) 279.29 631.33 P +0.01 (aits f) 288.33 631.33 P +0.01 (or a def) 309.16 631.33 P +0.01 (ault per) 342.8 631.33 P +0.01 (iod of time f) 376.31 631.33 P +0.01 (or the speci\336ed \336le descr) 427.74 631.33 P +0.01 (iptor) 538.55 631.33 P +1.27 (to ha) 279.43 619.33 P +1.27 (v) 302.74 619.33 P +1.27 (e an I/O e) 307.49 619.33 P +1.27 (v) 354.92 619.33 P +1.27 (ent. If the fd par) 359.67 619.33 P +1.27 (ameter is not pro) 434.69 619.33 P +1.27 (vided, the) 513.37 619.33 P +2.77 (cde) 279.43 607.33 P +2.77 (vSystem object will w) 295.25 607.33 P +2.77 (ait f) 397.87 607.33 P +2.77 (or an I/O e) 416.46 607.33 P +2.77 (v) 471.72 607.33 P +2.77 (ent on an) 476.47 607.33 P +2.77 (y of its) 523.56 607.33 P +0.23 (contained \336le descr) 279.43 595.33 P +0.23 (iptors) 366.19 595.33 P +0.23 (. When an e) 390.49 595.33 P +0.23 (v) 444.81 595.33 P +0.23 (ent occurs on one of the) 449.56 595.33 P +1.13 (\336le descr) 279.43 583.33 P +1.13 (iptors) 320.72 583.33 P +1.13 (, the cde) 345.02 583.33 P +1.13 (vSystem object will call the respectiv) 385.34 583.33 P +1.13 (e) 552.44 583.33 P +7.66 (cde) 279.43 571.33 P +7.66 (vSer) 295.25 571.33 P +7.66 (vice to process the e) 316.11 571.33 P +7.66 (v) 438.15 571.33 P +7.66 (ent and dispatch an) 442.9 571.33 P +7.66 (y) 553 571.33 P +(asynchronous callbac) 279.43 559.33 T +(ks that are ready) 375.38 559.33 T +(.) 448.86 559.33 T +2 F +(pend) 180 535.33 T +3 F +(int pend \050doub) 279.29 535.33 T +(le seconds) 343.02 535.33 T +(, int fd\051;) 390.67 535.33 T +0 F +0.11 (Processes all I/O e) 279.29 518.33 P +0.11 (v) 363.23 518.33 P +0.11 (ents that occur on the \336le descr) 367.98 518.33 P +0.11 (iptor dur) 507.72 518.33 P +0.11 (ing) 544.66 518.33 P +0.13 (the speci\336ed per) 279.43 506.33 P +0.13 (iod of time) 353.22 506.33 P +0.13 (. If the fd par) 399.46 506.33 P +0.13 (ameter is not pro) 456.04 506.33 P +0.13 (vided,) 531.32 506.33 P +2.61 (the cde) 279.43 494.33 P +2.61 (vSystem object will w) 314.54 494.33 P +2.61 (ait f) 416.66 494.33 P +2.61 (or I/O e) 435.09 494.33 P +2.61 (v) 473.35 494.33 P +2.61 (ents on all of its) 478.1 494.33 P +0.23 (contained \336le descr) 279.43 482.33 P +0.23 (iptors) 366.19 482.33 P +0.23 (. When an e) 390.49 482.33 P +0.23 (v) 444.81 482.33 P +0.23 (ent occurs on one of the) 449.56 482.33 P +1.13 (\336le descr) 279.43 470.33 P +1.13 (iptors) 320.72 470.33 P +1.13 (, the cde) 345.02 470.33 P +1.13 (vSystem object will call the respectiv) 385.34 470.33 P +1.13 (e) 552.44 470.33 P +7.66 (cde) 279.43 458.33 P +7.66 (vSer) 295.25 458.33 P +7.66 (vice to process the e) 316.11 458.33 P +7.66 (v) 438.15 458.33 P +7.66 (ent and dispatch an) 442.9 458.33 P +7.66 (y) 553 458.33 P +(asynchronous callbac) 279.43 446.33 T +(ks that are ready) 375.38 446.33 T +(.) 448.86 446.33 T +2 F +(g) 180 422.33 T +(etFd) 186.21 422.33 T +3 F +(int getFd \050int fd[], int &n) 279.29 422.33 T +(umFD\051;) 382.58 422.33 T +0 F +0.72 (Retr) 279.29 405.33 P +0.72 (ie) 298.33 405.33 P +0.72 (v) 305.81 405.33 P +0.72 (es a list of \336le descr) 310.56 405.33 P +0.72 (iptors that are contained within the) 402.11 405.33 P +0.16 (cde) 279.43 393.33 P +0.16 (vSystem object. The fd arr) 295.25 393.33 P +0.16 (a) 412.51 393.33 P +0.16 (y m) 417.77 393.33 P +0.16 (ust be preallocated, and the) 433.94 393.33 P +3.58 (maxim) 279.43 381.33 P +3.58 (um n) 308.77 381.33 P +3.58 (umber of elements should be speci\336ed in the) 334.48 381.33 P +3.91 (n) 279.43 369.33 P +3.91 (umFD par) 284.89 369.33 P +3.91 (ameter) 333.15 369.33 P +3.91 (. Upon completion, the fd arr) 363.77 369.33 P +3.91 (a) 509.37 369.33 P +3.91 (y will be) 514.63 369.33 P +3.3 (populated with the list of \336le descr) 279.43 357.33 P +3.3 (iptors) 449.43 357.33 P +3.3 (, and the n) 473.73 357.33 P +3.3 (umFD) 530.78 357.33 P +(par) 279.43 345.33 T +(ameter will contain the actual count.) 293.78 345.33 T +2 F +(ad) 180 321.33 T +(dFdChang) 191.57 321.33 T +(edCallbac) 241.11 321.33 T +(k) 288.15 321.33 T +3 F +(int addFdChangedCallbac) 279.29 309.33 T +(k \050cde) 394.7 309.33 T +(vFdChangedCallbac) 421.63 309.33 T +(k cbk,) 512.02 309.33 T +( v) 279.29 297.33 T +(oid*user) 411.92 297.33 T +(arg\051) 448.5 297.33 T +0 F +4.57 (Adds a ne) 279.29 280.33 P +4.57 (w function to be called each time a ser) 333.26 280.33 P +4.57 (vice) 540.22 280.33 P +1.62 (announces to the system that it has opened or closed a \336le) 279.43 268.33 P +(descr) 279.43 256.33 T +(iptor) 304.03 256.33 T +(. The function will be called with 3 arguments:) 322.98 256.33 T +3 F +( v) 279.29 239.33 T +(oid \050*cde) 286.82 239.33 T +(vFdChangedCallbac) 325.98 239.33 T +(k\051 \050int fd, int opened,) 416.37 239.33 T +( v) 279.29 227.33 T +(oid *user) 445.28 227.33 T +(arg\051) 484.64 227.33 T +0 F +0.45 (The \336rst argument speci\336es the \336le descr) 279.29 210.33 P +0.45 (iptor) 464.43 210.33 P +0.45 (, the second is 1) 483.38 210.33 P +2.08 (f) 279.43 198.33 P +2.08 (or opened, 0 f) 281.91 198.33 P +2.08 (or closed, and the last argument is the user) 349.57 198.33 P +(speci\336ed argument.) 279.43 186.33 T +2 F +(autoErr) 180 162.33 T +(orOn) 215.36 162.33 T +3 F +(int autoErrorOn \050v) 279.29 162.33 T +(oid\051;) 358.51 162.33 T +0 F +1.71 (Inf) 279.29 145.33 P +1.71 (or) 290.11 145.33 P +1.71 (ms the cde) 299.25 145.33 P +1.71 (vSystem object that it should use its inter) 351.27 145.33 P +1.71 (nal) 544.66 145.33 P +1.36 (def) 279.43 133.33 P +1.36 (ault error handler to process an) 293.03 133.33 P +1.36 (y error messages that are) 438.63 133.33 P +3.17 (gener) 279.43 121.33 P +3.17 (ated b) 304.9 121.33 P +3.17 (y objects within its control. This is the def) 335.67 121.33 P +3.17 (ault) 541.88 121.33 P +(oper) 279.43 109.33 T +(ating condition f) 299.34 109.33 T +(or the cde) 369.08 109.33 T +(vSystem object.) 413.25 109.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "41" 51 +%%Page: "42" 52 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(14. The cde) 54 739 T +(vSystem Class) 101.26 739 T +0 10 Q +(42) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(autoErr) 162 713.33 T +(orOff) 197.36 713.33 T +3 F +(int autoErrorOff \050v) 261.29 713.33 T +(oid\051;) 340.51 713.33 T +0 F +2.78 (Inf) 261.29 696.33 P +2.78 (or) 272.11 696.33 P +2.78 (ms the cde) 281.25 696.33 P +2.78 (vSystem object that it should use the user) 335.42 696.33 P +-0.1 (supplied error handling function to process an) 261.43 684.33 P +-0.1 (y error messages) 462.97 684.33 P +(that are gener) 261.43 672.33 T +(ated b) 323.59 672.33 T +(y objects within its control.) 351.19 672.33 T +2 F +(repor) 162 648.33 T +(tErr) 187.76 648.33 T +(or) 205.34 648.33 T +3 F +(int repor) 261.29 648.33 T +(tError \050) 298.37 648.33 T +(int se) 333.57 648.33 T +(v) 357.17 648.33 T +(er) 361.92 648.33 T +(ity) 370.96 648.33 T +(, char *name) 379.96 648.33 T +(,) 436.5 648.33 T +(cde) 333.57 636.33 T +(vRequestObject *obj,) 349.39 636.33 T +(char *f) 333.57 624.33 T +(or) 362.17 624.33 T +(matStr) 371.31 624.33 T +(ing,...\051;) 400.91 624.33 T +0 F +4.13 (Emits an error message) 261.29 607.33 P +4.13 (. The se) 379.68 607.33 P +4.13 (v) 423.77 607.33 P +4.13 (er) 428.52 607.33 P +4.13 (ity \336eld indicates the) 437.56 607.33 P +3 F +1.09 (se) 261.43 595.33 P +1.09 (v) 271.69 595.33 P +1.09 (er) 276.44 595.33 P +1.09 (ity) 285.48 595.33 P +0 F +1.09 ( of the error) 295.48 595.33 P +1.09 (, the) 349.93 595.33 P +3 F +1.09 (name) 374.34 595.33 P +0 F +1.09 ( str) 399.35 595.33 P +1.09 (ing identi\336es the object that) 414.48 595.33 P +11.86 (gener) 261.43 583.33 P +11.86 (ated the error) 286.9 583.33 P +11.86 (, the) 370.16 583.33 P +3 F +11.86 (obj) 416.13 583.33 P +0 F +11.86 (par) 444.12 583.33 P +11.86 (ameter is the) 458.47 583.33 P +1.32 (cde) 261.43 571.33 P +1.32 (vRequestObject that w) 277.25 571.33 P +1.32 (as in use when the error occurred,) 380.34 571.33 P +0.71 (and the) 261.43 559.33 P +3 F +0.71 (f) 298.99 559.33 P +0.71 (or) 301.47 559.33 P +0.71 (matStr) 310.61 559.33 P +0.71 (ing) 340.21 559.33 P +0 F +0.71 (and additional par) 357.03 559.33 P +0.71 (ameters \050...\051 should be) 437.84 559.33 P +2.71 (f) 261.43 547.33 P +2.71 (or) 263.91 547.33 P +2.71 (matted in the same manner as the par) 273.05 547.33 P +2.71 (ameters used b) 460.87 547.33 P +2.71 (y) 535 547.33 P +(pr) 261.43 535.33 T +(intf) 270.47 535.33 T +(.) 283.51 535.33 T +0.9 (The integer used b) 261.29 518.33 P +0.9 (y se) 347.16 518.33 P +0.9 (v) 366.09 518.33 P +0.9 (er) 370.84 518.33 P +0.9 (ity should ha) 379.88 518.33 P +0.9 (v) 437.61 518.33 P +0.9 (e one of the f) 442.36 518.33 P +0.9 (ollo) 504.03 518.33 P +0.9 (wing) 519.44 518.33 P +(v) 261.43 506.33 T +(alues indicating the se) 266.18 506.33 T +(v) 364.82 506.33 T +(er) 369.57 506.33 T +(ity of the error that has occurred.) 378.61 506.33 T +2 F +(CDEV_SEVERITY_INFO:) 261.29 489.33 T +0 F +(No error) 401.31 489.33 T +(.) 437.48 489.33 T +2 F +(CDEV_SEVERITY_W) 261.29 472.33 T +(ARN:) 358.49 472.33 T +0 F +(An error occurred that should) 401.31 472.33 T +(not impact contin) 401.67 460.33 T +(ued) 477.16 460.33 T +(processing.) 401.67 448.33 T +2 F +(CDEV_SEVERITY_ERR) 261.29 431.33 T +(OR:) 370.56 431.33 T +0 F +(An error occurred and should) 401.31 431.33 T +(be corrected bef) 401.67 419.33 T +(ore contin) 473.63 419.33 T +(uing.) 517.44 419.33 T +2 F +(CDEV_SEVERITY_SEVERE:) 261.29 402.33 T +0 F +(A se) 401.31 402.33 T +(v) 421.02 402.33 T +(ere or f) 425.77 402.33 T +(atal error has) 457.15 402.33 T +(occurred and cde) 401.67 390.33 T +(v cannot) 478.63 390.33 T +(contin) 401.67 378.33 T +(ue nor) 428.25 378.33 T +(mal e) 456.85 378.33 T +(x) 481 378.33 T +(ecution.) 485.7 378.33 T +2 F +(setErr) 162 354.33 T +(orHandler) 190.7 354.33 T +3 F +(v) 261.29 354.33 T +(oid setErrorHandler \050cde) 266.04 354.33 T +(vErrorHandler handler\051;) 374.66 354.33 T +0 F +2.41 (Used to to install a user speci\336ed error handler) 261.29 337.33 P +2.41 (. This error) 486.84 337.33 P +0.68 (handler will be called when an error occurs if the) 261.43 325.33 P +3 F +0.68 (autoErrorOff) 484.98 325.33 P +0 F +0 (method has been used to disab) 261.43 313.33 P +0 (le the def) 400.75 313.33 P +0 (ault error handler) 441.58 313.33 P +0 (. The) 517.21 313.33 P +6.28 (user pro) 261.43 301.33 P +6.28 (vided error handler should ha) 304.24 301.33 P +6.28 (v) 459.22 301.33 P +6.28 (e the f) 463.97 301.33 P +6.28 (ollo) 504.03 301.33 P +6.28 (wing) 519.44 301.33 P +(prototype:) 261.43 289.33 T +3 F +(v) 261.29 272.33 T +(oid handler \050int se) 266.04 272.33 T +(v) 345.22 272.33 T +(er) 349.97 272.33 T +(ity) 359.01 272.33 T +(, char *te) 368.01 272.33 T +(xt, cde) 407.73 272.33 T +(vRequestObject *obj\051;) 436.89 272.33 T +0 F +4.89 (The) 261.29 255.33 P +3 F +4.89 (se) 286.19 255.33 P +4.89 (v) 296.45 255.33 P +4.89 (er) 301.2 255.33 P +4.89 (ity) 310.24 255.33 P +0 F +4.89 ( par) 320.24 255.33 P +4.89 (ameter will contain one of the integers) 342.26 255.33 P +0.81 (speci\336ed in the) 261.43 243.33 P +3 F +0.81 (repor) 333.34 243.33 P +0.81 (tError) 357.08 243.33 P +0 F +0.81 (documentation, the) 385.67 243.33 P +3 F +0.81 (te) 475.12 243.33 P +0.81 (xt) 483.16 243.33 P +0 F +0.81 ( par) 490.94 243.33 P +0.81 (ameter) 508.88 243.33 P +2.11 (will contain the te) 261.43 231.33 P +2.11 (xt of the error) 344.17 231.33 P +2.11 (, and the) 409.48 231.33 P +3 F +2.11 (obj) 457.52 231.33 P +0 F +2.11 ( par) 470.86 231.33 P +2.11 (ameter will) 490.11 231.33 P +0.37 (contain the cde) 261.43 219.33 P +0.37 (vRequestObject that w) 329.69 219.33 P +0.37 (as in use when the error) 430.88 219.33 P +(occurred.) 261.43 207.33 T +2 F +(setThreshold) 162 183.33 T +3 F +(v) 261.29 183.33 T +(oid setThreshold \050int errorThreshold\051;) 266.04 183.33 T +0 F +0.77 (Used to specify the le) 261.29 166.33 P +0.77 (v) 359.66 166.33 P +0.77 (el of se) 364.41 166.33 P +0.77 (v) 397.88 166.33 P +0.77 (er) 402.63 166.33 P +0.77 (ity at which errors should be) 411.67 166.33 P +2.4 (submitted to the error handler) 261.43 154.33 P +2.4 (. The v) 401.71 154.33 P +2.4 (alue of) 436.83 154.33 P +3 F +2.4 (errorThreshold) 474.43 154.33 P +0 F +0.23 (should be one of the se) 261.43 142.33 P +0.23 (v) 366.26 142.33 P +0.23 (er) 371.01 142.33 P +0.23 (ity le) 380.05 142.33 P +0.23 (v) 400.54 142.33 P +0.23 (els speci\336ed in the) 405.29 142.33 P +3 F +0.23 (repor) 491.26 142.33 P +0.23 (tError) 515 142.33 P +0 F +(method.) 261.43 130.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "42" 52 +%%Page: "43" 53 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(15. The cde) 449.9 739 T +(vT) 497.16 739 T +(r) 506.08 739 T +(anObj Class) 508.99 739 T +0 10 Q +(43) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(15.) 151.54 710.67 T +(The cde) 180 710.67 T +(vT) 232.7 710.67 T +(ranObj Class) 247.91 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w of the) 108.64 673.33 T +(cde) 72 661.33 T +(vT) 89.08 661.33 T +(ranObj Class) 99.95 661.33 T +0 F +(The cde) 180 673.33 T +(vT) 215.83 673.33 T +(r) 225.74 673.33 T +(anObj \050cde) 228.97 673.33 T +(v tr) 277.58 673.33 T +(ansaction object\051 C++ class is a container class that is used) 291.37 673.33 T +(to maintain inf) 180 661.33 T +(or) 241.95 661.33 T +(mation that is required f) 251.09 661.33 T +(or individual oper) 355.28 661.33 T +(ations within a ser) 431.32 661.33 T +(vice) 511.65 661.33 T +(. This) 529.28 661.33 T +(class stores a cop) 180 649.33 T +(y of the cde) 259.73 649.33 T +(vRequestObject that w) 311.13 649.33 T +(as used to submit a request, the) 411.58 649.33 T +(cde) 180 637.33 T +(vSystem object in which the request object w) 195.82 637.33 T +(as created, the cde) 394.64 637.33 T +(vCallbac) 479.39 637.33 T +(k object) 517.53 637.33 T +(pro) 180 625.33 T +(vided b) 194.3 625.33 T +(y the user) 226.34 625.33 T +(, and the cde) 269.75 625.33 T +(vData object that the retur) 327.27 625.33 T +(ned data should be placed) 442.58 625.33 T +(in. Because this object is intended f) 180 613.33 T +(or usage only b) 336.45 613.33 T +(y cde) 404.62 613.33 T +(v inter) 428.22 613.33 T +(nals) 455.7 613.33 T +(, all of its data) 473.89 613.33 T +(elements are pub) 180 601.33 T +(lic.) 257.06 601.33 T +(The cde) 180 584.33 T +(vT) 215.83 584.33 T +(r) 225.74 584.33 T +(anObj is used to submit a request from the cde) 228.97 584.33 T +(vRequestObject to the) 435.99 584.33 T +-0.03 (cde) 180 572.33 P +-0.03 (vSer) 195.82 572.33 P +-0.03 (vice) 216.68 572.33 P +-0.03 (. It ma) 234.31 572.33 P +-0.03 (y also be used to place a tr) 261.74 572.33 P +-0.03 (ansaction into a g) 380.95 572.33 P +-0.03 (roup of requests using) 459.15 572.33 P +(a cde) 180 560.33 T +(vGroup object. The ser) 204.16 560.33 T +(vice noti\336es the cde) 306.17 560.33 T +(vSystem object and the cde) 393.69 560.33 T +(vGroup) 516.23 560.33 T +(objects that this tr) 180 548.33 T +(ansaction has been processed b) 258.27 548.33 T +(y calling its remo) 402.04 548.33 T +(v) 476.35 548.33 T +(eF) 481.1 548.33 T +(romGr) 492.32 548.33 T +(ps) 520.95 548.33 T +(method. This will eff) 180 536.33 T +(ectiv) 268.06 536.33 T +(ely remo) 288.37 536.33 T +(v) 326.56 536.33 T +(e the cde) 331.31 536.33 T +(vT) 372.15 536.33 T +(r) 382.06 536.33 T +(anObj from all g) 385.29 536.33 T +(roups that it is) 455.77 536.33 T +(associated with.) 180 524.33 T +3 9 Q +(Figure 17: Object model of the cde) 180 491 T +(vT) 320.3 491 T +(r) 329.22 491 T +(anObj class) 332.13 491 T +2 10 Q +(Pub) 72 272.62 T +(lic Data) 90.79 272.62 T +(Pr) 72 260.62 T +(oper) 82.36 260.62 T +(ties of the) 104.23 260.62 T +(cde) 72 248.62 T +(vT) 89.08 248.62 T +(ranObj Class) 99.95 248.62 T +(system_) 180 272.62 T +3 F +(cde) 279.29 272.62 T +(vSystem *system_;) 295.11 272.62 T +0 F +5.06 (This is a pointer to the cde) 279.29 255.62 P +5.06 (vSystem that contains this) 426.65 255.62 P +0.12 (tr) 279.43 243.62 P +0.12 (ansaction object. The tr) 285.44 243.62 P +0.12 (ansaction will be processed whene) 389.65 243.62 P +0.12 (v) 544.36 243.62 P +0.12 (er) 549.11 243.62 P +3.93 (the) 279.43 231.62 P +3 F +3.93 (poll) 300.05 231.62 P +0 F +3.93 (or) 322.32 231.62 P +3 F +3.93 (pend) 337.93 231.62 P +0 F +3.93 ( methods of this) 360.17 231.62 P +3 F +3.93 (cde) 449.28 231.62 P +3.93 (vSystem) 465.1 231.62 P +0 F +3.93 ( object are) 503.44 231.62 P +(e) 279.43 219.62 T +(x) 284.69 219.62 T +(ecuted.) 289.39 219.62 T +2 F +(reqObj_) 180 195.62 T +3 F +(cde) 279.29 195.62 T +(vRequestObject *reqObj_;) 295.11 195.62 T +0 F +1.07 (This is a pointer to the cde) 279.29 178.62 P +1.07 (vRequestObject that w) 402.69 178.62 P +1.07 (as called to) 505.28 178.62 P +5.74 (submit this tr) 279.43 166.62 P +5.74 (ansaction. This) 347.49 166.62 P +3 F +5.74 (cde) 429 166.62 P +5.74 (vRequestObject) 444.82 166.62 P +0 F +5.74 ( will be) 515.96 166.62 P +2.89 (submitted to the user speci\336ed callbac) 279.43 154.62 P +2.89 (k function when the) 463.18 154.62 P +(tr) 279.43 142.62 T +(ansaction has been completed.) 285.44 142.62 T +180 298.29 558 680 C +180 298.29 558 488 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +179.93 298.29 558.07 488 R +7 X +0 0 0 1 0 0 0 K +V +184.74 301 556.41 480.5 R +0 X +V +0.5 H +2 Z +N +180.9 305.88 552.57 484.33 R +7 X +V +0 X +N +250.68 324.87 483.02 465.58 R +7 X +V +0 X +N +255.85 330.75 475.85 462.42 R +7 X +V +4 9 Q +0 X +(class cdevTranObj) 319.95 456.42 T +(properties:) 255.85 445.42 T +(system_ : cdevSystem *) 269.18 434.42 T +(reqObj_ : cdevRequestObject *) 269.18 423.42 T +(resultData_ : cdevData *) 269.18 412.42 T +(userCallback_ : cdevCallback *) 269.18 401.42 T +(methods:) 255.85 379.42 T +(status \050void\051 : int) 269.18 368.42 T +(removeFromGrps \050void\051 : int) 269.18 357.42 T +(enableDeleteCbk \050void\051 : void) 269.18 346.42 T +(disableDeleteCbk \050void\051 : void) 269.18 335.42 T +250.79 452.92 482.91 452.92 2 L +N +250.46 392.42 482.57 392.42 2 L +N +180 298.29 558 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "43" 53 +%%Page: "44" 54 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(15. The cde) 54 739 T +(vT) 101.26 739 T +(r) 110.18 739 T +(anObj Class) 113.08 739 T +0 10 Q +(44) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(resultData_) 162 713.33 T +3 F +(cde) 261.29 713.33 T +(vData *resultData_;) 277.11 713.33 T +0 F +2.5 (This is the cde) 261.29 696.33 P +2.5 (vData object that will be populated with the) 332.96 696.33 P +0.69 (results of the tr) 261.43 684.33 P +0.69 (ansaction. This object will also be submitted to) 329.54 684.33 P +1.23 (the user speci\336ed callbac) 261.43 672.33 P +1.23 (k function when the tr) 377.2 672.33 P +1.23 (ansaction has) 477.07 672.33 P +(been completed.) 261.43 660.33 T +2 F +(userCallbac) 162 636.33 T +(k_) 218.49 636.33 T +3 F +(cde) 261.29 636.33 T +(vCallbac) 277.11 636.33 T +(k *userCallbac) 315.25 636.33 T +(k_;) 379.51 636.33 T +0 F +1.9 (This class contains a pointer to the caller speci\336ed callbac) 261.29 619.33 P +1.9 (k) 535 619.33 P +1.3 (function as w) 261.43 607.33 P +1.3 (ell as an) 322.29 607.33 P +1.3 (y user argument. The callbac) 361.97 607.33 P +1.3 (k function) 495.9 607.33 P +2.18 (will be e) 261.43 595.33 P +2.18 (x) 301.62 595.33 P +2.18 (ecuted when the tr) 306.32 595.33 P +2.18 (ansaction has been completed.) 395.04 595.33 P +1.25 (Note that it is the responsibility of the ser) 261.43 583.33 P +1.25 (vice to e) 451.81 583.33 P +1.25 (x) 491.25 583.33 P +1.25 (ecute this) 495.95 583.33 P +6.63 (callbac) 261.43 571.33 P +6.63 (k function when it has \336nished processing the) 292.35 571.33 P +(tr) 261.43 559.33 T +(ansaction.) 267.44 559.33 T +2 F +(Pub) 54 530.33 T +(lic Member) 72.79 530.33 T +(Functions of the) 54 518.33 T +(cde) 54 506.33 T +(vT) 71.08 506.33 T +(ranObj Class) 81.95 506.33 T +(status) 162 530.33 T +3 F +(int status \050v) 261.29 530.33 T +(oid\051;) 312.17 530.33 T +0 F +4.05 (Retur) 261.29 513.33 P +4.05 (ns the status of the) 285.99 513.33 P +3 F +4.05 (cde) 393.52 513.33 P +4.05 (vT) 409.35 513.33 P +4.05 (r) 419.26 513.33 P +4.05 (anObj) 422.48 513.33 P +0 F +4.05 ( object. The v) 449.17 513.33 P +4.05 (alue) 521.1 513.33 P +0.63 (retur) 261.43 501.33 P +0.63 (ned will be) 282.24 501.33 P +2 F +0.63 (1) 334.15 501.33 P +0 F +0.63 ( if this object is a member of an) 339.71 501.33 P +0.63 (y) 482.98 501.33 P +3 F +0.63 (cde) 491.39 501.33 P +0.63 (vGroup) 507.21 501.33 P +0 F +1.21 (object, or) 261.43 489.33 P +2 F +1.21 (-1) 307.75 489.33 P +0 F +1.21 ( if this object is not a member of an) 316.64 489.33 P +1.21 (y) 482.4 489.33 P +3 F +1.21 (cde) 491.39 489.33 P +1.21 (vGroup) 507.21 489.33 P +0 F +(object.) 261.43 477.33 T +2 F +(remo) 162 453.33 T +(veFr) 186.25 453.33 T +(omGrps) 207.17 453.33 T +3 F +(int remo) 261.29 453.33 T +(v) 297.26 453.33 T +(eF) 302.01 453.33 T +(romGr) 313.23 453.33 T +(ps \050v) 341.86 453.33 T +(oid\051;) 363.28 453.33 T +0 F +2.16 (Remo) 261.29 436.33 P +2.16 (v) 287.81 436.33 P +2.16 (es this tr) 292.56 436.33 P +2.16 (ansaction object from an) 334.57 436.33 P +2.16 (y) 449.83 436.33 P +3 F +2.16 (cde) 459.77 436.33 P +2.16 (vGroup) 475.59 436.33 P +0 F +2.16 ( object) 508.38 436.33 P +(that it ma) 261.43 424.33 T +(y be in.) 302.26 424.33 T +2 F +(enab) 162 400.33 T +(leDeleteCbk) 185.24 400.33 T +3 F +(v) 261.29 400.33 T +(oid enab) 266.04 400.33 T +(leDeleteCbk \050v) 304.2 400.33 T +(oid\051;) 369.52 400.33 T +0 F +0.68 (Sets the inter) 261.29 383.33 P +0.68 (nal \337ag telling the tr) 321.81 383.33 P +0.68 (ansaction object to delete its) 411.12 383.33 P +1.1 (inter) 261.43 371.33 P +1.1 (nal callbac) 281.13 371.33 P +1.1 (k object while e) 329.27 371.33 P +1.1 (x) 400.64 371.33 P +1.1 (ecuting its destr) 405.34 371.33 P +1.1 (uctor) 477.73 371.33 P +1.1 (. This is) 499.46 371.33 P +(the def) 261.43 359.33 T +(ault beha) 291.71 359.33 T +(vior f) 332.65 359.33 T +(or the cde) 354.02 359.33 T +(vT) 398.19 359.33 T +(r) 408.1 359.33 T +(anObj.) 411.33 359.33 T +2 F +(disab) 162 335.33 T +(leDeleteCbk) 188.02 335.33 T +3 F +(v) 261.29 335.33 T +(oid disab) 266.04 335.33 T +(leDeleteCbk \050v) 305.86 335.33 T +(oid\051;) 371.18 335.33 T +0 F +0.28 (Sets the inter) 261.29 318.33 P +0.28 (nal \337ag telling the tr) 321.03 318.33 P +0.28 (ansaction object not to delete) 408.78 318.33 P +0.79 (its inter) 261.43 306.33 P +0.79 (nal callbac) 294.71 306.33 P +0.79 (k object while e) 342.54 306.33 P +0.79 (x) 412.98 306.33 P +0.79 (ecuting its destr) 417.68 306.33 P +0.79 (uctor) 489.45 306.33 P +0.79 (. This) 511.18 306.33 P +0.77 (mode should be used when the user speci\336ed callbac) 261.43 294.33 P +0.77 (k object) 504.77 294.33 P +(is shared b) 261.43 282.33 T +(y n) 310.14 282.33 T +(umerous tr) 323.38 282.33 T +(ansaction objects) 371.07 282.33 T +(.) 448.18 282.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "44" 54 +%%Page: "45" 55 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(16. Language Speci\336cation f) 365.94 739 T +(or the cde) 479.24 739 T +(v DDL \336le) 518.99 739 T +0 10 Q +(45) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(16.) 151.54 710.67 T +(Langua) 180 710.67 T +(g) 229.64 710.67 T +(e Speci\336cation f) 238.34 710.67 T +(or the cde) 345.42 710.67 T +(v DDL \336le) 412.12 710.67 T +2 10 Q +(Langua) 72 673.33 T +(g) 107.46 673.33 T +(e) 113.67 673.33 T +(Speci\336cation) 72 661.33 T +0 F +0.48 (In the f) 180 673.33 P +0.48 (ollo) 211.24 673.33 P +0.48 (wing, required language elements are in doub) 226.65 673.33 P +0.48 (le quotes) 432.2 673.33 P +0.48 (, optional elements) 473.11 673.33 P +1.2 (are in square br) 180 661.33 P +1.2 (ac) 253.54 661.33 P +1.2 (k) 263.9 661.33 P +1.2 (ets) 268.7 661.33 P +1.2 (. Names are arbitr) 281.89 661.33 P +1.2 (ar) 365.41 661.33 P +1.2 (y char) 374.6 661.33 P +1.2 (acter str) 402.94 661.33 P +1.2 (ings) 440.41 661.33 P +1.2 (. v) 458.6 661.33 P +1.2 (alue is of an) 470.11 661.33 P +1.2 (y type) 527.49 661.33 P +1.2 (.) 555.22 661.33 P +(Plus sign indicates concatenation, v) 180 649.33 T +(er) 338.16 649.33 T +(tical bar alter) 347.45 649.33 T +(nate choices) 404.94 649.33 T +(.) 460.93 649.33 T +3 9 Q +(Figure 18: Language speci\336cation f) 180 616 T +(or the cde) 322.31 616 T +(v DDL \336le) 362.06 616 T +180 81 558 680 C +180 246.69 558 613 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +178.64 246.69 559.36 613 R +7 X +0 0 0 1 0 0 0 K +V +180.1 251.09 555.81 605.86 R +0 X +V +0.5 H +2 Z +N +180 254.52 551.79 608.57 R +7 X +V +0 X +N +182.71 258.24 548.07 605.14 R +7 X +V +4 9 Q +0 X +(specification = serviceSpecs + classSpecs + instances + aliases +) 182.71 599.14 T +(collections) 182.71 588.14 T +(serviceSpecs = serviceSpec + [serviceSpecs]) 182.71 566.14 T +-0.12 (serviceSpec = \322service\323 + name + \322{\322 + \322tags\323 + \322{\322 + tagList + \322}\323) 182.71 555.14 P +(+ \322}\323) 182.71 544.14 T +(tagList = tag + [\322,\323 + tagList]) 182.71 533.14 T +(classSpecs = classSpec + [classSpecs]) 182.71 511.14 T +(classSpec = \322class\323 + name + [\322 : \323 + parentList] + \322{\322 +) 182.71 500.14 T +( verbs + attributes + messages) 200.71 489.14 T +(parentList = name + [\322,\323 + parentList]) 182.71 478.14 T +(verbs = \322verbs\323 + \322{\322 + verbList + \322}\323) 182.71 467.14 T +(verbList = name + [\322,\323 + verbList]) 182.71 456.14 T +(attributes = \322attributes\323 + \322{\322 + attrList + \322}\323) 182.71 445.14 T +(attrList = name + serviceName + [\322{\322 + serviceData + \322}\323] + [\322;\323 +) 182.71 434.14 T +(attrList]) 182.71 423.14 T +(serviceData = name + \322=\323 + value) 182.71 412.14 T +(messages = \322messages\323 + \322{\322 + msgList + \322}\323) 182.71 401.14 T +(msgList = msg + serviceName + [\322{\322 + serviceData + \322}\323] + [\322;\323 +) 182.71 390.14 T +(msgList]) 182.71 379.14 T +(msg = name | \322\322\322string\323\323\323) 182.71 368.14 T +(instances = className + \322:\323 instanceList + \322;\323) 182.71 346.14 T +(instanceList = instance + [\322 \322 + instanceList]) 182.71 335.14 T +(aliases = alias + [\322 \322 + aliases]) 182.71 313.14 T +(alias = \322alias \323 + aliasname + \322 \322 + actualname) 182.71 302.14 T +(collections = collection + \322 \322 + name + \322 : \322 instanceList + \322;\323) 182.71 280.14 T +(instanceList = instance + [\322 \322 + instanceList]) 182.71 269.14 T +180 81 558 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "45" 55 +%%Page: "46" 56 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(17. Regular Expressions) 54 739 T +0 10 Q +(46) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(17.) 133.54 710.67 T +(Regular Expressions) 162 710.67 T +2 10 Q +(Over) 54 673.33 T +(vie) 76.89 673.33 T +(w of) 90.64 673.33 T +(Regular) 54 661.33 T +(Expressions) 54 649.33 T +0 F +1.86 (A regular e) 162 673.33 P +1.86 (xpression is a mechanism suppor) 214.33 673.33 P +1.86 (ted b) 370.54 673.33 P +1.86 (y man) 394.44 673.33 P +1.86 (y utilities f) 423.38 673.33 P +1.86 (or locating and) 470.69 673.33 P +0.03 (manipulating patter) 162 661.33 P +0.03 (ns in te) 247.32 661.33 P +0.03 (xt. Basic regular e) 279.31 661.33 P +0.03 (xpression \050RE\051 notation and constr) 359.12 661.33 P +0.03 (uction) 513.32 661.33 P +1.53 (r) 162 649.33 P +1.53 (ules apply to utilities de\336ned as using basic REs) 165.48 649.33 P +1.53 (. An) 390.42 649.33 P +1.53 (y e) 409.58 649.33 P +1.53 (xceptions to the f) 424.15 649.33 P +1.53 (ollo) 504.03 649.33 P +1.53 (wing) 519.44 649.33 P +(r) 162 637.33 T +(ules are noted in the descr) 165.48 637.33 T +(iptions of the speci\336c utilities that use REs) 283.47 637.33 T +(.) 469.51 637.33 T +2 F +(Or) 54 608.33 T +(dinar) 65.47 608.33 T +(y) 90.02 608.33 T +(Character) 54 596.33 T +(s) 100.53 596.33 T +0 F +2.19 (An ordinar) 162 608.33 P +2.19 (y char) 210.62 608.33 P +2.19 (acter is an RE that matches itself) 239.94 608.33 P +2.19 (. An ordinar) 398.95 608.33 P +2.19 (y char) 455.32 608.33 P +2.19 (acter is an) 484.64 608.33 P +2.19 (y) 535 608.33 P +0.01 (char) 162 596.33 P +0.01 (acter in the suppor) 181.35 596.33 P +0.01 (ted char) 264.59 596.33 P +0.01 (acter set e) 300.63 596.33 P +0.01 (xcept and the regular e) 390.48 596.33 P +0.01 (xpression) 497.21 596.33 P +-0.03 (special char) 162 584.33 P +-0.03 (acters listed in Special Char) 215.22 584.33 P +-0.03 (acters belo) 338.94 584.33 P +-0.03 (w) 387.67 584.33 P +-0.03 (. An ordinar) 394.29 584.33 P +-0.03 (y char) 446.23 584.33 P +-0.03 (acter preceded) 473.33 584.33 P +-0.21 (b) 162 572.33 P +-0.21 (y a bac) 167.36 572.33 P +-0.21 (kslash \050\134\051 is treated as the ordinar) 198.98 572.33 P +-0.21 (y char) 346.42 572.33 P +-0.21 (acter itself) 373.34 572.33 P +-0.21 (, e) 418.4 572.33 P +-0.21 (xcept when the char) 429.01 572.33 P +-0.21 (acter) 517.77 572.33 P +2.1 (is \050, \051, {, or }, or the digits 1 through 9 \050see REs Matching Multiple Char) 162 560.33 P +2.1 (acters\051.) 506.66 560.33 P +1.86 (Matching is based on the bit patter) 162 548.33 P +1.86 (n used f) 326.24 548.33 P +1.86 (or encoding the char) 365.24 548.33 P +1.86 (acter) 461.86 548.33 P +1.86 (; not on the) 484.39 548.33 P +(g) 162 536.33 T +(r) 167.46 536.33 T +(aphic representation of the char) 170.69 536.33 T +(acter) 311.22 536.33 T +(.) 332.95 536.33 T +2 F +(Special Character) 54 507.33 T +(s) 138.33 507.33 T +0 F +3.92 (A regular e) 162 507.33 P +3.92 (xpression special char) 218.45 507.33 P +3.92 (acter preceded b) 325.11 507.33 P +3.92 (y a bac) 407.78 507.33 P +3.92 (kslash is a regular) 447.66 507.33 P +3.42 (e) 162 495.33 P +3.42 (xpression that matches the special char) 167.26 495.33 P +3.42 (acter itself) 359.89 495.33 P +3.42 (. When not preceded b) 408.58 495.33 P +3.42 (y a) 523.24 495.33 P +0.04 (bac) 162 483.33 P +0.04 (kslash, such char) 177.92 483.33 P +0.04 (acters ha) 255.15 483.33 P +0.04 (v) 296.11 483.33 P +0.04 (e special meaning in the speci\336cation of REs) 300.86 483.33 P +0.04 (. Regular) 499.39 483.33 P +1.04 (e) 162 471.33 P +1.04 (xpression special char) 167.26 471.33 P +1.04 (acters and the conte) 268.15 471.33 P +1.04 (xts in which the) 361.58 471.33 P +1.04 (y ha) 432.85 471.33 P +1.04 (v) 452.58 471.33 P +1.04 (e special meaning) 457.33 471.33 P +(are:) 162 459.33 T +2 F +(. [ \134) 162 435.33 T +0 F +2.88 (The per) 261.29 435.33 P +2.88 (iod, left square br) 298.78 435.33 P +2.88 (ac) 384.57 435.33 P +2.88 (k) 394.93 435.33 P +2.88 (et, and bac) 399.73 435.33 P +2.88 (kslash are special) 454.77 435.33 P +2.04 (e) 261.43 423.33 P +2.04 (xcept when used in a br) 266.69 423.33 P +2.04 (ac) 382.42 423.33 P +2.04 (k) 392.78 423.33 P +2.04 (et e) 397.58 423.33 P +2.04 (xpression \050see RE Br) 416 423.33 P +2.04 (ac) 516.5 423.33 P +2.04 (k) 526.86 423.33 P +2.04 (et) 531.66 423.33 P +(Expression\051.) 261.43 411.33 T +2 F +(*) 162 387.33 T +0 F +4.8 (The aster) 261.29 387.33 P +4.8 (isk is special e) 308.47 387.33 P +4.8 (xcept when used in a br) 387.02 387.33 P +4.8 (ac) 516.5 387.33 P +4.8 (k) 526.86 387.33 P +4.8 (et) 531.66 387.33 P +0.25 (e) 261.43 375.33 P +0.25 (xpression, as the \336rst char) 266.69 375.33 P +0.25 (acter of a regular e) 384.3 375.33 P +0.25 (xpression, or as) 468.92 375.33 P +2.99 (the \336rst char) 261.43 363.33 P +2.99 (acter f) 322.33 363.33 P +2.99 (ollo) 352.81 363.33 P +2.99 (wing the char) 368.22 363.33 P +2.99 (acter pair \134\050 \050see REs) 433.57 363.33 P +(Matching Multiple Char) 261.43 351.33 T +(acters\051.) 363.58 351.33 T +2 F +(^) 162 327.33 T +0 F +0.06 (The circum\337e) 261.29 327.33 P +0.06 (x is special when used as the \336rst char) 321.06 327.33 P +0.06 (acter of an) 492.63 327.33 P +0.69 (entire RE \050see Expression Anchor) 261.43 315.33 P +0.69 (ing\051 or as the \336rst char) 414.95 315.33 P +0.69 (acter) 517.77 315.33 P +(of a br) 261.43 303.33 T +(ac) 289.68 303.33 T +(k) 300.04 303.33 T +(et e) 304.84 303.33 T +(xpression.) 321.22 303.33 T +2 F +($) 162 279.33 T +0 F +0.03 (The dollar sign is special when used as the last char) 261.29 279.33 P +0.03 (acter of an) 492.69 279.33 P +(entire RE \050see Expression Anchor) 261.43 267.33 T +(ing\051.) 412.19 267.33 T +2 F +(delimiter) 162 243.33 T +0 F +2.57 (An) 261.29 243.33 P +2.57 (y char) 273.37 243.33 P +2.57 (acter used to bound \050i.e) 303.07 243.33 P +2.57 (., delimit\051 an entire RE is) 418.24 243.33 P +(special f) 261.43 231.33 T +(or that RE.) 297.81 231.33 T +2 F +(period) 162 207.33 T +0 F +0.74 (A per) 261.29 207.33 P +0.74 (iod \050.\051, when used outside of a br) 286.08 207.33 P +0.74 (ac) 436.77 207.33 P +0.74 (k) 447.14 207.33 P +0.74 (et e) 451.93 207.33 P +0.74 (xpression, is an) 469.05 207.33 P +-0.11 (RE that matches an) 261.43 195.33 P +-0.11 (y pr) 348.76 195.33 P +-0.11 (intab) 365.47 195.33 P +-0.11 (le or nonpr) 386.95 195.33 P +-0.11 (intab) 434.67 195.33 P +-0.11 (le char) 456.15 195.33 P +-0.11 (acter e) 485.94 195.33 P +-0.11 (xcept) 516.1 195.33 P +(.) 278.19 183.33 T +2 F +(Brac) 54 154.33 T +(ket) 76.03 154.33 T +(Expression) 54 142.33 T +0 F +0.2 (A br) 162 154.33 P +0.2 (ac) 180.44 154.33 P +0.2 (k) 190.8 154.33 P +0.2 (et e) 195.6 154.33 P +0.2 (xpression enclosed in square br) 212.18 154.33 P +0.2 (ac) 354.06 154.33 P +0.2 (k) 364.42 154.33 P +0.2 (ets \050[ ]\051 is an RE that matches a single) 369.22 154.33 P +0.32 (collating element contained in the nonempty set of collating elements represented b) 162 142.33 P +0.32 (y) 535 142.33 P +(the br) 162 130.33 T +(ac) 187.47 130.33 T +(k) 197.83 130.33 T +(et e) 202.63 130.33 T +(xpression. The f) 219.01 130.33 T +(ollo) 289.85 130.33 T +(wing r) 305.26 130.33 T +(ules apply to br) 332.08 130.33 T +(ac) 399.79 130.33 T +(k) 410.15 130.33 T +(et e) 414.95 130.33 T +(xpressions:) 431.33 130.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "46" 56 +%%Page: "47" 57 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(17. Regular Expressions) 459.96 739 T +0 10 Q +(47) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(brac) 180 713.33 T +(ket e) 200.92 713.33 T +(xpression) 223.56 713.33 T +0 F +1.08 (A br) 279.29 713.33 P +1.08 (ac) 298.61 713.33 P +1.08 (k) 308.97 713.33 P +1.08 (et e) 313.77 713.33 P +1.08 (xpression is either a matching list e) 331.23 713.33 P +1.08 (xpression or a) 493.04 713.33 P +2.9 (non-matching list e) 279.43 701.33 P +2.9 (xpression, and consists of one or more) 368.85 701.33 P +5.07 (e) 279.43 689.33 P +5.07 (xpressions in an) 284.69 689.33 P +5.07 (y order) 366.94 689.33 P +5.07 (. Expressions can be: collating) 402.64 689.33 P +11.43 (elements) 279.43 677.33 P +11.43 (, collating symbols) 319.85 677.33 P +11.43 (, noncollating char) 424.24 677.33 P +11.43 (acters) 528.14 677.33 P +11.43 (,) 555.22 677.33 P +0.87 (equiv) 279.43 665.33 P +0.87 (alence classes) 303.08 665.33 P +0.87 (, r) 369.38 665.33 P +0.87 (ange e) 379.04 665.33 P +0.87 (xpressions) 410.19 665.33 P +0.87 (, or char) 457.83 665.33 P +0.87 (acter classes) 496.15 665.33 P +0.87 (.) 555.22 665.33 P +0.92 (The r) 279.43 653.33 P +0.92 (ight br) 303.84 653.33 P +0.92 (ac) 332.45 653.33 P +0.92 (k) 342.81 653.33 P +0.92 (et \050]\051 loses its special meaning and represents) 347.61 653.33 P +0.33 (itself in a br) 279.43 641.33 P +0.33 (ac) 331.45 641.33 P +0.33 (k) 341.81 641.33 P +0.33 (et e) 346.61 641.33 P +0.33 (xpression if it occurs \336rst in the list \050after an) 363.32 641.33 P +0.27 (initial ^, if an) 279.43 629.33 P +0.27 (y\051. Otherwise) 334.8 629.33 P +0.27 (, it ter) 393.81 629.33 P +0.27 (minates the br) 419.61 629.33 P +0.27 (ac) 483.4 629.33 P +0.27 (k) 493.76 629.33 P +0.27 (et e) 498.56 629.33 P +0.27 (xpression) 515.21 629.33 P +-0.06 (\050unless it is the ending r) 279.43 617.33 P +-0.06 (ight br) 384.89 617.33 P +-0.06 (ac) 412.52 617.33 P +-0.06 (k) 422.88 617.33 P +-0.06 (et f) 427.68 617.33 P +-0.06 (or a v) 441.22 617.33 P +-0.06 (alid collating symbol,) 465.87 617.33 P +3.05 (equiv) 279.43 605.33 P +3.05 (alence class) 303.08 605.33 P +3.05 (, or char) 361 605.33 P +3.05 (acter class) 403.68 605.33 P +3.05 (, or it is the collating) 454.38 605.33 P +5.61 (element within a collating symbol or equiv) 279.43 593.33 P +5.61 (alence class) 497.37 593.33 P +(e) 279.43 581.33 T +(xpression\051. The special char) 284.69 581.33 T +(acters) 409.63 581.33 T +2 F +(. * [ \134) 180 557.33 T +0 F +0.43 (\050per) 279.29 557.33 P +0.43 (iod, aster) 297.22 557.33 P +0.43 (isk, left br) 338.93 557.33 P +0.43 (ac) 382.48 557.33 P +0.43 (k) 392.84 557.33 P +0.43 (et, and bac) 397.64 557.33 P +0.43 (kslash\051 lose their special) 447.79 557.33 P +(meaning within a br) 279.43 545.33 T +(ac) 366.03 545.33 T +(k) 376.39 545.33 T +(et e) 381.19 545.33 T +(xpression.) 397.57 545.33 T +2 F +(matc) 180 521.33 T +(hing list) 203.24 521.33 T +0 F +-0.04 (A matching list e) 279.29 521.33 P +-0.04 (xpression speci\336es a list that matches an) 352.23 521.33 P +-0.04 (y one) 533.58 521.33 P +0.92 (of the char) 279.43 509.33 P +0.92 (acters represented in the list. The \336rst char) 328.42 509.33 P +0.92 (acter in) 524.29 509.33 P +0.96 (the list cannot be the circum\337e) 279.43 497.33 P +0.96 (x. F) 419.02 497.33 P +0.96 (or e) 436.35 497.33 P +0.96 (xample) 454.25 497.33 P +0.96 (, [abc] is an RE) 486.33 497.33 P +(that matches an) 279.43 485.33 T +(y of a, b) 350.43 485.33 T +(, or c.) 385.61 485.33 T +2 F +(non-matc) 180 461.33 T +(hing list) 224.9 461.33 T +0 F +-0.24 (A non-matching list e) 279.29 461.33 P +-0.24 (xpression begins with a circum\337e) 371.64 461.33 P +-0.24 (x \050^\051, and) 517.1 461.33 P +1.64 (speci\336es a list that matches an) 279.43 449.33 P +1.64 (y char) 423.63 449.33 P +1.64 (acter e) 452.4 449.33 P +1.64 (xcept ) 529.38 449.33 P +0.57 (and the char) 279.43 437.33 P +0.57 (acters represented in the list. F) 336.07 437.33 P +0.57 (or e) 475.91 437.33 P +0.57 (xample) 493.42 437.33 P +0.57 (, [^abc]) 525.5 437.33 P +0.37 (is an RE that matches an) 279.43 425.33 P +0.37 (y char) 392.83 425.33 P +0.37 (acter e) 420.33 425.33 P +0.37 (xcept or a, b) 494.77 425.33 P +0.37 (,) 555.22 425.33 P +2.38 (or c. The circum\337e) 279.43 413.33 P +2.38 (x has this special meaning only when it) 368.51 413.33 P +2.41 (occurs \336rst in the list, immediately f) 279.43 401.33 P +2.41 (ollo) 448.64 401.33 P +2.41 (wing the left square) 464.05 401.33 P +(br) 279.43 389.33 T +(ac) 288.22 389.33 T +(k) 298.58 389.33 T +(et.) 303.38 389.33 T +2 F +(collating element) 180 365.33 T +0 F +1.26 (A collating element is a sequence of one or more char) 279.29 365.33 P +1.26 (acters) 530.77 365.33 P +1.12 (that represents a single element in the collating sequence as) 279.43 353.33 P +1.95 (identi\336ed via the most current setting of the locale categor) 279.43 341.33 P +1.95 (y) 553 341.33 P +(LC_COLLA) 279.43 329.33 T +(TE \050see setlocale\0503C\051\051.) 329.36 329.33 T +2 F +(collating symbol) 180 305.33 T +0 F +3.86 (A collating symbol is a collating element enclosed within) 279.29 305.33 P +7.41 (br) 279.43 293.33 P +7.41 (ac) 288.22 293.33 P +7.41 (k) 298.58 293.33 P +7.41 (et-per) 303.38 293.33 P +7.41 (iod \050[.....]\051 delimiters) 329.65 293.33 P +7.41 (. Multi-char) 432.13 293.33 P +7.41 (acter collating) 488.89 293.33 P +5.75 (elements m) 279.43 281.33 P +5.75 (ust be represented as collating symbols to) 336.76 281.33 P +1.13 (distinguish them from single-char) 279.43 269.33 P +1.13 (acter collating elements) 429.45 269.33 P +1.13 (. F) 536.6 269.33 P +1.13 (or) 549.11 269.33 P +0.41 (e) 279.43 257.33 P +0.41 (xample) 284.69 257.33 P +0.41 (, if the str) 316.77 257.33 P +0.41 (ing ch is a v) 359.29 257.33 P +0.41 (alid collating element, then [.ch.]) 413.5 257.33 P +5.12 (is treated as an element matching the same str) 279.43 245.33 P +5.12 (ing of) 528.42 245.33 P +0.09 (char) 279.43 233.33 P +0.09 (acters) 298.78 233.33 P +0.09 (, while ch is treated as a simple list of the char) 325.86 233.33 P +0.09 (acters) 530.77 233.33 P +-0.11 (c and h. If the str) 279.43 221.33 P +-0.11 (ing within the br) 353.51 221.33 P +-0.11 (ac) 423.1 221.33 P +-0.11 (k) 433.46 221.33 P +-0.11 (et-per) 438.26 221.33 P +-0.11 (iod delimiters is not a) 464.53 221.33 P +4.82 (v) 279.43 209.33 P +4.82 (alid collating element in the current collating sequence) 284.18 209.33 P +(de\336nition, the symbol is treated as an in) 279.43 197.33 T +(v) 454.87 197.33 T +(alid e) 459.62 197.33 T +(xpression.) 483.22 197.33 T +2 F +(noncollating c) 180 173.33 T +(har) 247.69 173.33 T +0 F +3.23 (A noncollating char) 279.29 173.33 P +3.23 (acter is a char) 370.7 173.33 P +3.23 (acter that is ignored f) 443.1 173.33 P +3.23 (or) 549.11 173.33 P +4.83 (collating pur) 279.43 161.33 P +4.83 (poses) 338.47 161.33 P +4.83 (. By de\336nition, such char) 365 161.33 P +4.83 (acters cannot) 493.14 161.33 P +(par) 279.43 149.33 T +(ticipate in equiv) 294.28 149.33 T +(alence classes or r) 362.95 149.33 T +(ange e) 446.21 149.33 T +(xpressions) 476.49 149.33 T +(.) 524.13 149.33 T +2 F +(equiv) 180 125.33 T +(alence c) 205.92 125.33 T +(lass) 245.19 125.33 T +0 F +0.1 (An equiv) 279.29 125.33 P +0.1 (alence class e) 318.05 125.33 P +0.1 (xpression represents the set of collating) 381.31 125.33 P +0.3 (elements belonging to an equiv) 279.43 113.33 P +0.3 (alence class) 418.78 113.33 P +0.3 (. It is e) 473.94 113.33 P +0.3 (xpressed b) 503.99 113.33 P +0.3 (y) 553 113.33 P +0.49 (enclosing an) 279.43 101.33 P +0.49 (y one of the collating elements in the equiv) 335.91 101.33 P +0.49 (alence) 528.54 101.33 P +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "47" 57 +%%Page: "48" 58 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(17. Regular Expressions) 54 739 T +0 10 Q +(48) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +1.89 (class within br) 261.43 713.33 P +1.89 (ac) 327.9 713.33 P +1.89 (k) 338.26 713.33 P +1.89 (et-equal \050[=...=]\051 delimiters) 343.06 713.33 P +1.89 (. F) 463.39 713.33 P +1.89 (or e) 476.65 713.33 P +1.89 (xample) 495.47 713.33 P +1.89 (, if) 527.55 713.33 P +1.47 (,,and A belong to the same equiv) 261.43 701.33 P +1.47 (alence class) 416.21 701.33 P +1.47 (, then [[=a=]b],) 472.56 701.33 P +(=]b], and [[=A=]b] are each equiv) 261.43 689.33 T +(alent toAb].) 406.56 689.33 T +2 F +(rang) 162 665.33 T +(e e) 183.77 665.33 T +(xpression) 197.52 665.33 T +0 F +2.03 (A r) 261.29 665.33 P +2.03 (ange e) 275.99 665.33 P +2.03 (xpression represents the set of collating elements) 308.3 665.33 P +-0.24 (that f) 261.43 653.33 P +-0.24 (all betw) 283.13 653.33 P +-0.24 (een tw) 316.69 653.33 P +-0.24 (o elements in the current collation sequence) 345.8 653.33 P +1.15 (as de\336ned via the most current setting of the locale categor) 261.43 641.33 P +1.15 (y) 535 641.33 P +4.12 (LC_COLLA) 261.43 629.33 P +4.12 (TE \050see setlocale\0503C\051\051. It is e) 311.36 629.33 P +4.12 (xpressed as the) 461.16 629.33 P +(star) 261.43 617.33 T +(ting point and the ending point separ) 278.5 617.33 T +(ated b) 440.17 617.33 T +(y a h) 467.77 617.33 T +(yphen \050-\051.) 489.15 617.33 T +0.41 (The star) 261.29 600.33 P +0.41 (ting r) 298.78 600.33 P +0.41 (ange point and the ending r) 321.33 600.33 P +0.41 (ange point m) 445.05 600.33 P +0.41 (ust be a) 503.59 600.33 P +5.16 (collating element, collating symbol, or equiv) 261.43 588.33 P +5.16 (alence class) 479.82 588.33 P +1.16 (e) 261.43 576.33 P +1.16 (xpression. An equiv) 266.69 576.33 P +1.16 (alence class e) 356.02 576.33 P +1.16 (xpression used as an end) 421.41 576.33 P +0.19 (point of a r) 261.43 564.33 P +0.19 (ange e) 309.14 564.33 P +0.19 (xpression is inter) 339.61 564.33 P +0.19 (preted such that all collating) 415.3 564.33 P +3.38 (elements within the equiv) 261.43 552.33 P +3.38 (alence class are included in the) 383.59 552.33 P +0.35 (r) 261.43 540.33 P +0.35 (ange) 264.66 540.33 P +0.35 (. F) 286.75 540.33 P +0.35 (or e) 298.48 540.33 P +0.35 (xample) 315.76 540.33 P +0.35 (, if the collating order is A, a, B) 347.84 540.33 P +0.35 (, b) 486.08 540.33 P +0.35 (, C) 497.15 540.33 P +0.35 (, c) 509.98 540.33 P +0.35 (, ch,) 520.75 540.33 P +1.72 (D) 261.43 528.33 P +1.72 (, d; and A and a constitute an equiv) 267.95 528.33 P +1.72 (alence class) 438.26 528.33 P +1.72 (, then the) 494.85 528.33 P +(e) 261.43 516.33 T +(xpression [[=a=]-D] is treated as [AaBbCc[.ch.]D].) 266.69 516.33 T +1.27 (Both star) 261.29 499.33 P +1.27 (ting and ending r) 302.98 499.33 P +1.27 (ange points m) 381.17 499.33 P +1.27 (ust be v) 446.41 499.33 P +1.27 (alid collating) 483.71 499.33 P +0.38 (elements) 261.43 487.33 P +0.38 (, collating symbols) 301.85 487.33 P +0.38 (, or equiv) 384.14 487.33 P +0.38 (alence class e) 425.77 487.33 P +0.38 (xpressions) 489.58 487.33 P +0.38 (,) 537.22 487.33 P +0.08 (and the ending r) 261.43 475.33 P +0.08 (ange point m) 333.83 475.33 P +0.08 (ust collate equal to or higher than) 391.69 475.33 P +-0.09 (the star) 261.43 463.33 P +-0.09 (ting r) 295.09 463.33 P +-0.09 (ange point; otherwise the e) 317.13 463.33 P +-0.09 (xpression is in) 436.55 463.33 P +-0.09 (v) 499.52 463.33 P +-0.09 (alid. F) 504.27 463.33 P +-0.09 (or) 531.11 463.33 P +0.21 (e) 261.43 451.33 P +0.21 (xample) 266.69 451.33 P +0.21 (, with the abo) 298.77 451.33 P +0.21 (v) 358.72 451.33 P +0.21 (e collating order and assuming that E is) 363.47 451.33 P +1.57 (a noncollating char) 261.43 439.33 P +1.57 (acter) 348.4 439.33 P +1.57 (, then both the e) 370.13 439.33 P +1.57 (xpressions [[=A=]-E]) 448.39 439.33 P +(and [d-a] are in) 261.43 427.33 T +(v) 328.49 427.33 T +(alid.) 333.24 427.33 T +0.23 (An ending r) 261.29 410.33 P +0.23 (ange point can also be the star) 312.79 410.33 P +0.23 (ting r) 451.34 410.33 P +0.23 (ange point in a) 473.7 410.33 P +0.92 (subsequent r) 261.43 398.33 P +0.92 (ange e) 320.07 398.33 P +0.92 (xpression. Each such r) 351.27 398.33 P +0.92 (ange e) 455.08 398.33 P +0.92 (xpression is) 486.29 398.33 P +1.11 (e) 261.43 386.33 P +1.11 (v) 266.69 386.33 P +1.11 (aluated separ) 271.44 386.33 P +1.11 (ately) 333.04 386.33 P +1.11 (. F) 353.16 386.33 P +1.11 (or e) 365.64 386.33 P +1.11 (xample) 383.68 386.33 P +1.11 (, the br) 415.76 386.33 P +1.11 (ac) 449 386.33 P +1.11 (k) 459.36 386.33 P +1.11 (et e) 464.16 386.33 P +1.11 (xpression [a-) 481.65 386.33 P +(m-o] is treated as [a-mm-o].) 261.43 374.33 T +0.77 (The h) 261.29 357.33 P +0.77 (yphen char) 287.33 357.33 P +0.77 (acter is treated as itself if it occurs \336rst \050after) 337.46 357.33 P +-0.27 (an initial ^, if an) 261.43 345.33 P +-0.27 (y\051 or last in the list, or as the r) 328.83 345.33 P +-0.27 (ightmost symbol in) 457.73 345.33 P +1.83 (a r) 261.43 333.33 P +1.83 (ange e) 274.83 333.33 P +1.83 (xpression. As e) 306.93 333.33 P +1.83 (xamples) 378.64 333.33 P +1.83 (, the e) 415.72 333.33 P +1.83 (xpressions [-ac] and) 446.87 333.33 P +0.53 ([ac-] are equiv) 261.43 321.33 P +0.53 (alent and match an) 325.59 321.33 P +0.53 (y of the char) 412.07 321.33 P +0.53 (acters a, c) 468.58 321.33 P +0.53 (, or -;) 515.61 321.33 P +0.22 (the e) 261.43 309.33 P +0.22 (xpressions [^-ac] and [^ac-] are equiv) 283.59 309.33 P +0.22 (alent and match an) 449.44 309.33 P +0.22 (y) 535 309.33 P +1.74 (char) 261.43 297.33 P +1.74 (acters e) 280.78 297.33 P +1.74 (xcept , a, c) 362.96 297.33 P +1.74 (, or -; the e) 416.58 297.33 P +1.74 (xpression [%--]) 471.58 297.33 P +5.32 (matches an) 261.43 285.33 P +5.32 (y of the char) 318.3 285.33 P +5.32 (acters in the de\336ned collating) 389.2 285.33 P +2.65 (sequence betw) 261.43 273.33 P +2.65 (een % and - inclusiv) 331.24 273.33 P +2.65 (e; the e) 431.06 273.33 P +2.65 (xpression [--@]) 469.41 273.33 P +5.32 (matches an) 261.43 261.33 P +5.32 (y of the char) 318.3 261.33 P +5.32 (acters in the de\336ned collating) 389.2 261.33 P +0.87 (sequence betw) 261.43 249.33 P +0.87 (een - and @ inclusiv) 329.46 249.33 P +0.87 (e; and the e) 423.43 249.33 P +0.87 (xpression [a--) 478.56 249.33 P +(@] is in) 261.43 237.33 T +(v) 294.72 237.33 T +(alid, assuming - precedes a in the collating sequence) 299.47 237.33 T +(.) 534.43 237.33 T +2 F +(c) 162 213.33 T +(haracter c) 167.46 213.33 T +(lass) 215.06 213.33 T +0 F +1 (A char) 261.29 213.33 P +1 (acter class e) 291.09 213.33 P +1 (xpression represents the set of char) 348.92 213.33 P +1 (acters) 512.77 213.33 P +0.37 (belonging to a char) 261.43 201.33 P +0.37 (acter class) 347.49 201.33 P +0.37 (, as de\336ned via the most current) 395.5 201.33 P +0.51 (setting of the locale categor) 261.43 189.33 P +0.51 (y LC_CTYPE. It is e) 386.07 189.33 P +0.51 (xpressed as a) 476.73 189.33 P +3.84 (char) 261.43 177.33 P +3.84 (acter class name enclosed within br) 280.78 177.33 P +3.84 (ac) 458.26 177.33 P +3.84 (k) 468.62 177.33 P +3.84 (et-colon \050[: :]\051) 473.42 177.33 P +(delimiters) 261.43 165.33 T +(.) 304.06 165.33 T +0.4 (V) 261.29 148.33 P +0.4 (alid char) 267.26 148.33 P +0.4 (acter class e) 305.35 148.33 P +0.4 (xpressions and the class the) 361.99 148.33 P +0.4 (y represent) 489.58 148.33 P +(are:) 261.43 136.33 T +([:alpha:] letters) 261.29 119.33 T +([:upper) 261.29 102.33 T +(:] upper-case letters) 292.72 102.33 T +([:lo) 261.29 85.33 T +(w) 274.48 85.33 T +(er) 281.6 85.33 T +(:] lo) 290.79 85.33 T +(w) 306.76 85.33 T +(er-case letters) 313.88 85.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "48" 58 +%%Page: "49" 59 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(17. Regular Expressions) 459.96 739 T +0 10 Q +(49) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +([:digit:] decimal digits) 279.29 713.33 T +([:xdigit:] he) 279.29 696.33 T +(xadecimal digits) 327.35 696.33 T +([:aln) 279.29 679.33 T +(um:] letters or decimal digits) 298.09 679.33 T +([:space:] char) 279.29 662.33 T +(acters producing white- space in displa) 339.22 662.33 T +(y) 511.21 662.33 T +(ed te) 516.01 662.33 T +(xt) 537.95 662.33 T +([:pr) 279.29 645.33 T +(int:] pr) 293.89 645.33 T +(inting char) 321.83 645.33 T +(acters) 367.86 645.33 T +([:punct:] punctuation char) 279.29 628.33 T +(acters) 391.48 628.33 T +([:g) 279.29 611.33 T +(r) 290.31 611.33 T +(aph:] char) 293.54 611.33 T +(acters with a visib) 337.91 611.33 T +(le representation) 416.62 611.33 T +([:cntr) 279.29 594.33 T +(l:] control char) 301.67 594.33 T +(acters) 364.37 594.33 T +2 F +(Matc) 72 565.33 T +(hing Multiple) 94.68 565.33 T +(Character) 72 553.33 T +(s) 118.53 553.33 T +0 F +0.52 (The f) 180 565.33 P +0.52 (ollo) 203.01 565.33 P +0.52 (wing r) 218.43 565.33 P +0.52 (ules ma) 245.77 565.33 P +0.52 (y be used to constr) 281.01 565.33 P +0.52 (uct REs matching m) 367.74 565.33 P +0.52 (ultiple char) 458.69 565.33 P +0.52 (acters from) 507.46 565.33 P +(REs matching a single char) 180 553.33 T +(acter) 301.61 553.33 T +(:) 324.14 553.33 T +2 F +(RERE) 180 529.33 T +0 F +2.75 (The concatenation of REs is an RE that matches the \336rst) 279.29 529.33 P +2.72 (encountered concatenation of the str) 279.43 517.33 P +2.72 (ings matched b) 452.77 517.33 P +2.72 (y each) 525.82 517.33 P +1.75 (component of the RE. F) 279.43 505.33 P +1.75 (or e) 391.75 505.33 P +1.75 (xample) 410.44 505.33 P +1.75 (, the RE bc matches the) 442.52 505.33 P +(second and third char) 279.43 493.33 T +(acters of the str) 375.49 493.33 T +(ing abcdef) 444.56 493.33 T +(abcdef) 490.4 493.33 T +(.) 520.12 493.33 T +2 F +(RE*) 180 469.33 T +0 F +-0.16 (An RE matching a single char) 279.29 469.33 P +-0.16 (acter f) 410.09 469.33 P +-0.16 (ollo) 437.42 469.33 P +-0.16 (w) 452.83 469.33 P +-0.16 (ed b) 459.95 469.33 P +-0.16 (y an aster) 479.04 469.33 P +-0.16 (isk \050*\051 is) 522.78 469.33 P +2.97 (an RE that matches z) 279.43 457.33 P +2.97 (ero or more occurrences of the RE) 386.77 457.33 P +-0.26 (preceding the aster) 279.43 445.33 P +-0.26 (isk. The \336rst encountered str) 364.66 445.33 P +-0.26 (ing that per) 489.92 445.33 P +-0.26 (mits) 539.67 445.33 P +0.33 (a match is chosen, and the matched str) 279.43 433.33 P +0.33 (ing will encompass the) 456.42 433.33 P +3.35 (maxim) 279.43 421.33 P +3.35 (um n) 308.77 421.33 P +3.35 (umber of char) 334.25 421.33 P +3.35 (acters per) 402.55 421.33 P +3.35 (mitted b) 450.61 421.33 P +3.35 (y the RE. F) 489.33 421.33 P +3.35 (or) 549.11 421.33 P +1.61 (e) 279.43 409.33 P +1.61 (xample) 284.69 409.33 P +1.61 (, in the str) 316.77 409.33 P +1.61 (ing ab) 365.67 409.33 P +1.61 (b) 394.42 409.33 P +1.61 (bcdeab) 399.88 409.33 P +1.61 (b) 432.58 409.33 P +1.61 (b) 438.04 409.33 P +1.61 (b) 443.5 409.33 P +1.61 (b) 448.96 409.33 P +1.61 (bcde) 454.42 409.33 P +1.61 (, both the RE b*c) 475.95 409.33 P +(and the RE b) 279.43 397.33 T +(b) 337.7 397.33 T +(b*c are matched b) 343.16 397.33 T +(y the) 424.11 397.33 T +-0.15 (substr) 279.29 380.33 P +-0.15 (ing b) 306.67 380.33 P +-0.15 (b) 328.1 380.33 P +-0.15 (bc in the second through \336fth positions) 333.55 380.33 P +-0.15 (. An aster) 503.14 380.33 P +-0.15 (isk) 545.78 380.33 P +-0.21 (as the \336rst char) 279.43 368.33 P +-0.21 (acter of an RE loses this special meaning and is) 347.05 368.33 P +(treated as itself) 279.43 356.33 T +(.) 346.94 356.33 T +2 F +(\134\050RE\134\051) 180 332.33 T +0 F +1.19 (A sube) 279.29 332.33 P +1.19 (xpression can be de\336ned within an RE b) 311.3 332.33 P +1.19 (y enclosing it) 497.83 332.33 P +1.61 (betw) 279.43 320.33 P +1.61 (een the char) 300.45 320.33 P +1.61 (acter pairs \134\050 and \134\051. Such a sube) 359.16 320.33 P +1.61 (xpression) 515.21 320.33 P +0.51 (matches whate) 279.43 308.33 P +0.51 (v) 346.89 308.33 P +0.51 (er it w) 351.64 308.33 P +0.51 (ould ha) 379.23 308.33 P +0.51 (v) 412.34 308.33 P +0.51 (e matched without the \134\050 and \134\051.) 417.09 308.33 P +7.17 (Sube) 279.43 296.33 P +7.17 (xpressions can be arbitr) 302.48 296.33 P +7.17 (ar) 430.04 296.33 P +7.17 (ily nested. An aster) 439.08 296.33 P +7.17 (isk) 545.78 296.33 P +1.67 (immediately f) 279.43 284.33 P +1.67 (ollo) 339.7 284.33 P +1.67 (wing the \134\050 loses its special meaning and is) 355.11 284.33 P +2.55 (treated as itself) 279.43 272.33 P +2.55 (. An aster) 352.05 272.33 P +2.55 (isk immediately f) 400.1 272.33 P +2.55 (ollo) 478.8 272.33 P +2.55 (wing the \134\051 is) 494.21 272.33 P +(treated as an in) 279.43 260.33 T +(v) 348.16 260.33 T +(alid char) 352.91 260.33 T +(acter) 390.6 260.33 T +(.) 412.33 260.33 T +2 F +(\134n) 180 236.33 T +0 F +1.54 (The e) 279.29 236.33 P +1.54 (xpression \134n matches the same str) 306.1 236.33 P +1.54 (ing of char) 466.22 236.33 P +1.54 (acters as) 515.89 236.33 P +1.21 (w) 279.43 224.33 P +1.21 (as matched b) 286.5 224.33 P +1.21 (y a sube) 348.74 224.33 P +1.21 (xpression enclosed betw) 388.66 224.33 P +1.21 (een \134\050 and \134\051) 500.46 224.33 P +2.96 (preceding the \134n. The char) 279.43 212.33 P +2.96 (acter n m) 407.89 212.33 P +2.96 (ust be a digit from 1) 455.39 212.33 P +2.97 (through 9, specifying the n-th sube) 279.43 200.33 P +2.97 (xpression \050the one that) 447.38 200.33 P +0.51 (begins with the n-th \134\050 and ends with the corresponding paired) 279.43 188.33 P +4.28 (\134\051. F) 279.43 176.33 P +4.28 (or e) 301.2 176.33 P +4.28 (xample) 322.41 176.33 P +4.28 (, the e) 354.49 176.33 P +4.28 (xpression ^\134\050.*\134\051\1341$ matches a line) 390.56 176.33 P +(consisting of tw) 279.43 164.33 T +(o adjacent appear) 347.69 164.33 T +(ances of the same str) 427.64 164.33 T +(ing.) 523.39 164.33 T +1.8 (If the \134n is f) 279.29 147.33 P +1.8 (ollo) 335.1 147.33 P +1.8 (w) 350.51 147.33 P +1.8 (ed b) 357.63 147.33 P +1.8 (y an aster) 378.69 147.33 P +1.8 (isk, it matches z) 426.35 147.33 P +1.8 (ero or more) 502.72 147.33 P +0.16 (occurrences of the sube) 279.43 135.33 P +0.16 (xpression ref) 386.34 135.33 P +0.16 (erred to) 443.45 135.33 P +0.16 (. F) 477.67 135.33 P +0.16 (or e) 489.2 135.33 P +0.16 (xample) 506.3 135.33 P +0.16 (, the) 538.38 135.33 P +13.97 (e) 279.43 123.33 P +13.97 (xpression \134\050ab\134\050cd\134\051ef\134\051Z\1342*Z\1341 matches the str) 284.69 123.33 P +13.97 (ing) 544.66 123.33 P +(abcdefZcdcdZabcdef) 279.43 111.33 T +(.) 372.51 111.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "49" 59 +%%Page: "50" 60 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(17. Regular Expressions) 54 739 T +0 10 Q +(50) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(RE\134{m,n\134}) 162 713.33 T +0 F +0.61 (An RE matching a single char) 261.29 713.33 P +0.61 (acter f) 395.96 713.33 P +0.61 (ollo) 424.06 713.33 P +0.61 (w) 439.47 713.33 P +0.61 (ed b) 446.59 713.33 P +0.61 (y \134{m\134}, \134{m,\134}, or) 466.46 713.33 P +0.23 (\134{m,n\134} is an RE that matches repeated occurrences of the RE.) 261.43 701.33 P +0.17 (The v) 261.43 689.33 P +0.17 (alues of m and n m) 286.36 689.33 P +0.17 (ust be decimal integers in the r) 372.16 689.33 P +0.17 (ange 0) 509.25 689.33 P +-0.22 (through 255, with m specifying the e) 261.43 677.33 P +-0.22 (xact or minim) 419.92 677.33 P +-0.22 (um n) 478.84 677.33 P +-0.22 (umber of) 500.76 677.33 P +5.53 (occurrences and n specifying the maxim) 261.43 665.33 P +5.53 (um n) 467.36 665.33 P +5.53 (umber of) 495.01 665.33 P +3.97 (occurrences) 261.43 653.33 P +3.97 (. \134{m\134} matches e) 315.74 653.33 P +3.97 (xactly m occurrences of the) 402.4 653.33 P +2.88 (preceding RE, \134{m,\134} matches at least m occurrences) 261.43 641.33 P +2.88 (, and) 514.88 641.33 P +0.36 (\134{m,n\134} matches an) 261.43 629.33 P +0.36 (y n) 345.38 629.33 P +0.36 (umber of occurrences betw) 358.98 629.33 P +0.36 (een m and n,) 480.55 629.33 P +(inclusiv) 261.43 617.33 T +(e) 293.96 617.33 T +(.) 299.37 617.33 T +2.41 (The \336rst encountered str) 261.29 600.33 P +2.41 (ing that matches the e) 377.06 600.33 P +2.41 (xpression is) 484.8 600.33 P +2.86 (chosen; it will contain as man) 261.43 588.33 P +2.86 (y occurrences of the RE as) 405.64 588.33 P +0.33 (possib) 261.43 576.33 P +0.33 (le) 290.13 576.33 P +0.33 (. F) 297.76 576.33 P +0.33 (or e) 309.46 576.33 P +0.33 (xample) 326.72 576.33 P +0.33 (, in the str) 358.8 576.33 P +0.33 (ing ab) 403.86 576.33 P +0.33 (b) 431.33 576.33 P +0.33 (b) 436.79 576.33 P +0.33 (b) 442.25 576.33 P +0.33 (b) 447.71 576.33 P +0.33 (b) 453.17 576.33 P +0.33 (bc the RE b\134{3\134} is) 458.63 576.33 P +3.17 (matched b) 261.43 564.33 P +3.17 (y char) 311.09 564.33 P +3.17 (acters tw) 341.39 564.33 P +3.17 (o through f) 384.47 564.33 P +3.17 (our) 438.32 564.33 P +3.17 (, the RE b\134{3,\134} is) 452.27 564.33 P +0.36 (matched b) 261.43 552.33 P +0.36 (y char) 308.28 552.33 P +0.36 (acters tw) 335.78 552.33 P +0.36 (o through eight, and the RE b\134{3,5\134}c) 376.05 552.33 P +(is matched b) 261.43 540.33 T +(y char) 317.92 540.33 T +(acters f) 345.05 540.33 T +(our through nine) 377.54 540.33 T +(.) 450.21 540.33 T +2 F +(Expression) 54 511.33 T +(Anc) 54 499.33 T +(horing) 72.79 499.33 T +0 F +1.56 (An RE can be limited to matching str) 162 511.33 P +1.56 (ings that begin or end a line \050i.e) 334.8 511.33 P +1.56 (., anchored\051) 485.08 511.33 P +(according to the f) 162 499.33 T +(ollo) 238.41 499.33 T +(wing r) 253.82 499.33 T +(ules:) 280.64 499.33 T +(\245) 162 475.33 T +(A circum\337e) 180 475.33 T +(x \050^\051as the \336rst RE anchors the e) 229.15 475.33 T +(xpression to the beginning of a line;) 374.15 475.33 T +(only str) 180 463.33 T +(ings star) 212.38 463.33 T +(ting at the \336rst char) 250.57 463.33 T +(acter of a line are matched b) 335.51 463.33 T +(y the RE. F) 462.04 463.33 T +(or) 511.76 463.33 T +(e) 180 451.33 T +(xample) 185.26 451.33 T +(, the RE ^ab matches the str) 217.34 451.33 T +(ing ab in the line abcdef) 343.35 451.33 T +(, b) 448.67 451.33 T +(ut not the same) 459.59 451.33 T +(str) 180 439.33 T +(ing in the line cdef) 191.26 439.33 T +(ab) 271.56 439.33 T +(.) 282.28 439.33 T +(\245) 162 415.33 T +-0.02 (A dollar sign \050$\051 as the last char) 180 415.33 P +-0.02 (acter of an RE anchors the e) 320.37 415.33 P +-0.02 (xpression to the end) 447.25 415.33 P +-0.16 (of a line; only str) 180 403.33 P +-0.16 (ings ending at the last char) 252.34 403.33 P +-0.16 (acter of a line are matched b) 370.96 403.33 P +-0.16 (y the RE.) 496.56 403.33 P +(F) 180 391.33 T +(or e) 185.81 391.33 T +(xample) 202.74 391.33 T +(, the RE ab$ matches the str) 234.82 391.33 T +(ing ab in the line cdef) 361.7 391.33 T +(ab) 455.9 391.33 T +(, b) 466.62 391.33 T +(ut not the) 477.54 391.33 T +(same str) 180 379.33 T +(ing in the line abcdef) 218.49 379.33 T +(.) 309.91 379.33 T +(\245) 162 355.33 T +-0.24 (An RE anchored b) 180 355.33 P +-0.24 (y both ^ and $ matches only str) 260.78 355.33 P +-0.24 (ings that are lines) 397.31 355.33 P +-0.24 (. F) 474.79 355.33 P +-0.24 (or e) 485.92 355.33 P +-0.24 (xample) 502.6 355.33 P +-0.24 (,) 534.68 355.33 P +(the RE ^abcdef$ matches only lines consisting of the str) 180 343.33 T +(ing abcdef) 427.73 343.33 T +(.) 473.57 343.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "50" 60 +%%Trailer +%%BoundingBox: 0 0 612 792 +%%PageOrder: Ascend +%%Pages: 60 +%%DocumentFonts: Helvetica +%%+ Times-BoldItalic +%%+ Helvetica-Bold +%%+ Helvetica-Oblique +%%+ Courier-Bold +%%+ Helvetica-BoldOblique +%%+ Courier-BoldOblique +%%+ Courier-Oblique +%%+ Courier +%%EOF diff --git a/doc/ps/cdevScriptService.ps b/doc/ps/cdevScriptService.ps new file mode 100755 index 0000000..ef99962 --- /dev/null +++ b/doc/ps/cdevScriptService.ps @@ -0,0 +1,4822 @@ +%!PS-Adobe-3.0 +%%BoundingBox: (atend) +%%Pages: (atend) +%%PageOrder: (atend) +%%DocumentFonts: (atend) +%%Creator: Frame 5.0 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +% +% Frame ps_prolog 5.0, for use with Frame 5.0 products +% This ps_prolog file is Copyright (c) 1986-1995 Frame Technology +% Corporation. All rights reserved. This ps_prolog file may be +% freely copied and distributed in conjunction with documents created +% using FrameMaker, FrameMaker/SGML and FrameViewer as long as this +% copyright notice is preserved. +% +% FrameMaker users specify the proper paper size for each print job in the +% "Print" dialog's "Printer Paper Size" "Width" and "Height~ fields. If the +% printer that the PS file is sent to does not support the requested paper +% size, or if there is no paper tray of the proper size currently installed, +% then the job will not be printed. The following flag, if set to true, will +% cause the job to print on the default paper in such cases. +/FMAllowPaperSizeMismatch false def +% +% Frame products normally print colors as their true color on a color printer +% or as shades of gray, based on luminance, on a black-and white printer. The +% following flag, if set to true, forces all non-white colors to print as pure +% black. This has no effect on bitmap images. +/FMPrintAllColorsAsBlack false def +% +% Frame products can either set their own line screens or use a printer's +% default settings. Three flags below control this separately for no +% separations, spot separations and process separations. If a flag +% is true, then the default printer settings will not be changed. If it is +% false, Frame products will use their own settings from a table based on +% the printer's resolution. +/FMUseDefaultNoSeparationScreen true def +/FMUseDefaultSpotSeparationScreen true def +/FMUseDefaultProcessSeparationScreen false def +% +% For any given PostScript printer resolution, Frame products have two sets of +% screen angles and frequencies for printing process separations, which are +% recomended by Adobe. The following variable chooses the higher frequencies +% when set to true or the lower frequencies when set to false. This is only +% effective if the appropriate FMUseDefault...SeparationScreen flag is false. +/FMUseHighFrequencyScreens true def +% +% The following is a set of predefined optimal frequencies and angles for various +% common dpi settings. This is taken from "Advances in Color Separation Using +% PostScript Software Technology," from Adobe Systems (3/13/89 P.N. LPS 0043) +% and corrolated with information which is in various PPD (4.0) files. +% +% The "dpiranges" figure is the minimum dots per inch device resolution which +% can support this setting. The "low" and "high" values are controlled by the +% setting of the FMUseHighFrequencyScreens flag above. The "TDot" flags control +% the use of the "Yellow Triple Dot" feature whereby the frequency id divided by +% three, but the dot function is "trippled" giving a block of 3x3 dots per cell. +% +% PatFreq is a compromise pattern frequency for ps Level 2 printers which is close +% to the ideal WYSIWYG pattern frequency of 9 repetitions/inch but does not beat +% (too badly) against the screen frequencies of any separations for that DPI. +/dpiranges [ 2540 2400 1693 1270 1200 635 600 0 ] def +/CMLowFreqs [ 100.402 94.8683 89.2289 100.402 94.8683 66.9349 63.2456 47.4342 ] def +/YLowFreqs [ 95.25 90.0 84.65 95.25 90.0 70.5556 66.6667 50.0 ] def +/KLowFreqs [ 89.8026 84.8528 79.8088 89.8026 84.8528 74.8355 70.7107 53.033 ] def +/CLowAngles [ 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 ] def +/MLowAngles [ 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 ] def +/YLowTDot [ true true false true true false false false ] def +/CMHighFreqs [ 133.87 126.491 133.843 108.503 102.523 100.402 94.8683 63.2456 ] def +/YHighFreqs [ 127.0 120.0 126.975 115.455 109.091 95.25 90.0 60.0 ] def +/KHighFreqs [ 119.737 113.137 119.713 128.289 121.218 89.8026 84.8528 63.6395 ] def +/CHighAngles [ 71.5651 71.5651 71.5651 70.0169 70.0169 71.5651 71.5651 71.5651 ] def +/MHighAngles [ 18.4349 18.4349 18.4349 19.9831 19.9831 18.4349 18.4349 18.4349 ] def +/YHighTDot [ false false true false false true true false ] def +/PatFreq [ 10.5833 10.0 9.4055 10.5833 10.0 10.5833 10.0 9.375 ] def +% +% PostScript Level 2 printers contain an "Accurate Screens" feature which can +% improve process separation rendering at the expense of compute time. This +% flag is ignored by PostScript Level 1 printers. +/FMUseAcccurateScreens true def +% +% The following PostScript procedure defines the spot function that Frame +% products will use for process separations. You may un-comment-out one of +% the alternative functions below, or use your own. +% +% Dot function +/FMSpotFunction {abs exch abs 2 copy add 1 gt + {1 sub dup mul exch 1 sub dup mul add 1 sub } + {dup mul exch dup mul add 1 exch sub }ifelse } def +% +% Line function +% /FMSpotFunction { pop } def +% +% Elipse function +% /FMSpotFunction { dup 5 mul 8 div mul exch dup mul exch add +% sqrt 1 exch sub } def +% +% +/FMversion (5.0) def +/fMLevel1 /languagelevel where {pop languagelevel} {1} ifelse 2 lt def +/FMPColor + fMLevel1 { + false + /colorimage where {pop pop true} if + } { + true + } ifelse +def +/FrameDict 400 dict def +systemdict /errordict known not {/errordict 10 dict def + errordict /rangecheck {stop} put} if +% The readline in PS 23.0 doesn't recognize cr's as nl's on AppleTalk +FrameDict /tmprangecheck errordict /rangecheck get put +errordict /rangecheck {FrameDict /bug true put} put +FrameDict /bug false put +mark +% Some PS machines read past the CR, so keep the following 3 lines together! +currentfile 5 string readline +00 +0000000000 +cleartomark +errordict /rangecheck FrameDict /tmprangecheck get put +FrameDict /bug get { + /readline { + /gstring exch def + /gfile exch def + /gindex 0 def + { + gfile read pop + dup 10 eq {exit} if + dup 13 eq {exit} if + gstring exch gindex exch put + /gindex gindex 1 add def + } loop + pop + gstring 0 gindex getinterval true + } bind def + } if +/FMshowpage /showpage load def +/FMquit /quit load def +/FMFAILURE { + dup = flush + FMshowpage + /Helvetica findfont 12 scalefont setfont + 72 200 moveto show + 72 220 moveto show + FMshowpage + FMquit + } def +/FMVERSION { + FMversion ne { + (Frame product version does not match ps_prolog! Check installation;) + (also check ~/fminit and ./fminit for old versions) FMFAILURE + } if + } def +/FMBADEPSF { + (Adobe's PostScript Language Reference Manual, 2nd Edition, section H.2.4) + (says your EPS file is not valid, as it calls X ) + dup dup (X) search pop exch pop exch pop length + 5 -1 roll + putinterval + FMFAILURE + } def +/fmConcatProcs + { + /proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def + newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx +}def +FrameDict begin [ + /ALDsave + /FMdicttop + /FMoptop + /FMpointsize + /FMsaveobject + /b + /bitmapsave + /blut + /bpside + /bs + /bstring + /bwidth + /c + /cf + /cs + /cynu + /depth + /edown + /fh + /fillvals + /fw + /fx + /fy + /g + /gfile + /gindex + /grnt + /gryt + /gstring + /height + /hh + /i + /im + /indx + /is + /k + /kk + /landscape + /lb + /len + /llx + /lly + /m + /magu + /manualfeed + /n + /offbits + /onbits + /organgle + /orgbangle + /orgbfreq + /orgbproc + /orgbxfer + /orgfreq + /orggangle + /orggfreq + /orggproc + /orggxfer + /orgmatrix + /orgproc + /orgrangle + /orgrfreq + /orgrproc + /orgrxfer + /orgxfer + /pagesave + /paperheight + /papersizedict + /paperwidth + /pos + /pwid + /r + /rad + /redt + /sl + /str + /tran + /u + /urx + /ury + /val + /width + /width + /ws + /ww + /x + /x1 + /x2 + /xindex + /xpoint + /xscale + /xx + /y + /y1 + /y2 + /yelu + /yindex + /ypoint + /yscale + /yy +] { 0 def } forall +/FmBD {bind def} bind def +systemdict /pdfmark known { + /fMAcrobat true def + + /FmPD /pdfmark load def + + + /FmPT /show load def + + + currentdistillerparams /CoreDistVersion get 2000 ge { + + + /FmPD2 /pdfmark load def + + + + + + /FmPA { mark exch /Dest exch 5 3 roll + /View [ /XYZ null 6 -2 roll FmDC exch pop null] /DEST FmPD + }FmBD + } { + + /FmPD2 /cleartomark load def + /FmPA {pop pop pop}FmBD + } ifelse +} { + + /fMAcrobat false def + /FmPD /cleartomark load def + /FmPD2 /cleartomark load def + /FmPT /pop load def + /FmPA {pop pop pop}FmBD +} ifelse +/FmDC { + transform fMDefaultMatrix itransform cvi exch cvi exch +}FmBD +/FmBx { + dup 3 index lt {3 1 roll exch} if + 1 index 4 index lt {4 -1 roll 3 1 roll exch 4 1 roll} if +}FmBD +/FMnone 0 def +/FMcyan 1 def +/FMmagenta 2 def +/FMyellow 3 def +/FMblack 4 def +/FMcustom 5 def +/fMNegative false def +/FrameSepIs FMnone def +/FrameSepBlack 0 def +/FrameSepYellow 0 def +/FrameSepMagenta 0 def +/FrameSepCyan 0 def +/FrameSepRed 1 def +/FrameSepGreen 1 def +/FrameSepBlue 1 def +/FrameCurGray 1 def +/FrameCurPat null def +/FrameCurColors [ 0 0 0 1 0 0 0 ] def +/FrameColorEpsilon .001 def +/eqepsilon { + sub dup 0 lt {neg} if + FrameColorEpsilon le +} bind def +/FrameCmpColorsCMYK { + 2 copy 0 get exch 0 get eqepsilon { + 2 copy 1 get exch 1 get eqepsilon { + 2 copy 2 get exch 2 get eqepsilon { + 3 get exch 3 get eqepsilon + } {pop pop false} ifelse + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/FrameCmpColorsRGB { + 2 copy 4 get exch 0 get eqepsilon { + 2 copy 5 get exch 1 get eqepsilon { + 6 get exch 2 get eqepsilon + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/RGBtoCMYK { + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 3 copy + 2 copy + le { pop } { exch pop } ifelse + 2 copy + le { pop } { exch pop } ifelse + dup dup dup + 6 1 roll + 4 1 roll + 7 1 roll + sub + 6 1 roll + sub + 5 1 roll + sub + 4 1 roll +} bind def +/CMYKtoRGB { + dup dup 4 -1 roll add + 5 1 roll 3 -1 roll add + 4 1 roll add + 1 exch sub dup 0 lt {pop 0} if 3 1 roll + 1 exch sub dup 0 lt {pop 0} if exch + 1 exch sub dup 0 lt {pop 0} if exch +} bind def +/FrameSepInit { + 1.0 RealSetgray +} bind def +/FrameSetSepColor { + /FrameSepBlue exch def + /FrameSepGreen exch def + /FrameSepRed exch def + /FrameSepBlack exch def + /FrameSepYellow exch def + /FrameSepMagenta exch def + /FrameSepCyan exch def + /FrameSepIs FMcustom def + setCurrentScreen +} bind def +/FrameSetCyan { + /FrameSepBlue 1.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 1.0 def + /FrameSepIs FMcyan def + setCurrentScreen +} bind def + +/FrameSetMagenta { + /FrameSepBlue 1.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 1.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMmagenta def + setCurrentScreen +} bind def + +/FrameSetYellow { + /FrameSepBlue 0.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 1.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMyellow def + setCurrentScreen +} bind def + +/FrameSetBlack { + /FrameSepBlue 0.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 1.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMblack def + setCurrentScreen +} bind def + +/FrameNoSep { + /FrameSepIs FMnone def + setCurrentScreen +} bind def +/FrameSetSepColors { + FrameDict begin + [ exch 1 add 1 roll ] + /FrameSepColors + exch def end + } bind def +/FrameColorInSepListCMYK { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsCMYK + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/FrameColorInSepListRGB { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsRGB + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/RealSetgray /setgray load def +/RealSetrgbcolor /setrgbcolor load def +/RealSethsbcolor /sethsbcolor load def +end +/setgray { + FrameDict begin + FrameSepIs FMnone eq + { RealSetgray } + { + FrameSepIs FMblack eq + { RealSetgray } + { FrameSepIs FMcustom eq + FrameSepRed 0 eq and + FrameSepGreen 0 eq and + FrameSepBlue 0 eq and { + RealSetgray + } { + 1 RealSetgray pop + } ifelse + } ifelse + } ifelse + end +} bind def +/setrgbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetrgbcolor } + { + 3 copy [ 4 1 roll ] + FrameColorInSepListRGB + { + FrameSepBlue eq exch + FrameSepGreen eq and exch + FrameSepRed eq and + { 0 } { 1 } ifelse + } + { + FMPColor { + RealSetrgbcolor + currentcmykcolor + } { + RGBtoCMYK + } ifelse + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end +} bind def +/sethsbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSethsbcolor } + { + RealSethsbcolor + currentrgbcolor + setrgbcolor + } + ifelse + end +} bind def +FrameDict begin +/setcmykcolor where { + pop /RealSetcmykcolor /setcmykcolor load def +} { + /RealSetcmykcolor { + 4 1 roll + 3 { 3 index add 0 max 1 min 1 exch sub 3 1 roll} repeat + RealSetrgbcolor pop + } bind def +} ifelse +userdict /setcmykcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetcmykcolor } + { + 4 copy [ 5 1 roll ] + FrameColorInSepListCMYK + { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + { 0 } { 1 } ifelse + } + { + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end + } bind put +fMLevel1 { + + + + /patScreenDict 7 dict dup begin + <0f1e3c78f0e1c387> [ 45 { pop } {exch pop} .5 2 sqrt] FmBD + <0f87c3e1f0783c1e> [ 135 { pop } {exch pop} .5 2 sqrt] FmBD + [ 0 { pop } dup .5 2 ] FmBD + [ 90 { pop } dup .5 2 ] FmBD + <8142241818244281> [ 45 { 2 copy lt {exch} if pop} dup .75 2 sqrt] FmBD + <03060c183060c081> [ 45 { pop } {exch pop} .875 2 sqrt] FmBD + <8040201008040201> [ 135 { pop } {exch pop} .875 2 sqrt] FmBD + end def +} { + + /patProcDict 5 dict dup begin + <0f1e3c78f0e1c387> { 3 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <0f87c3e1f0783c1e> { 3 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + <8142241818244281> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -1 -1 moveto 9 9 lineto stroke } bind def + <03060c183060c081> { 1 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <8040201008040201> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + end def + /patDict 15 dict dup begin + /PatternType 1 def + /PaintType 2 def + /TilingType 3 def + /BBox [ 0 0 8 8 ] def + /XStep 8 def + /YStep 8 def + /PaintProc { + begin + patProcDict bstring known { + patProcDict bstring get exec + } { + 8 8 true [1 0 0 -1 0 8] bstring imagemask + } ifelse + end + } bind def + end def +} ifelse +/combineColor { + FrameSepIs FMnone eq + { + graymode fMLevel1 or not { + + [/Pattern [/DeviceCMYK]] setcolorspace + FrameCurColors 0 4 getinterval aload pop FrameCurPat setcolor + } { + FrameCurColors 3 get 1.0 ge { + FrameCurGray RealSetgray + } { + fMAcrobat not FMPColor graymode and and { + 0 1 3 { + FrameCurColors exch get + 1 FrameCurGray sub mul + } for + RealSetcmykcolor + } { + 4 1 6 { + FrameCurColors exch get + graymode { + 1 exch sub 1 FrameCurGray sub mul 1 exch sub + } { + 1.0 lt {FrameCurGray} {1} ifelse + } ifelse + } for + RealSetrgbcolor + } ifelse + } ifelse + } ifelse + } { + FrameCurColors 0 4 getinterval aload + FrameColorInSepListCMYK { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + FrameSepIs FMcustom eq and + { FrameCurGray } { 1 } ifelse + } { + FrameSepIs FMblack eq + {FrameCurGray 1.0 exch sub mul 1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop FrameCurGray 1.0 exch sub mul 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + graymode fMLevel1 or not { + + [/Pattern [/DeviceGray]] setcolorspace + FrameCurPat setcolor + } { + graymode not fMLevel1 and { + + dup 1 lt {pop FrameCurGray} if + } if + RealSetgray + } ifelse + } ifelse +} bind def +/savematrix { + orgmatrix currentmatrix pop + } bind def +/restorematrix { + orgmatrix setmatrix + } bind def +/fMDefaultMatrix matrix defaultmatrix def +/fMatrix2 matrix def +/dpi 72 0 fMDefaultMatrix dtransform + dup mul exch dup mul add sqrt def + +/freq dpi dup 72 div round dup 0 eq {pop 1} if 8 mul div def +/sangle 1 0 fMDefaultMatrix dtransform exch atan def + sangle fMatrix2 rotate + fMDefaultMatrix fMatrix2 concatmatrix + dup 0 get /sflipx exch def + 3 get /sflipy exch def +/screenIndex { + 0 1 dpiranges length 1 sub { dup dpiranges exch get 1 sub dpi le {exit} {pop} ifelse } for +} bind def +/getCyanScreen { + FMUseHighFrequencyScreens { CHighAngles CMHighFreqs} {CLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getMagentaScreen { + FMUseHighFrequencyScreens { MHighAngles CMHighFreqs } {MLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getYellowScreen { + FMUseHighFrequencyScreens { YHighTDot YHighFreqs} { YLowTDot YLowFreqs } ifelse + screenIndex dup 3 1 roll get 3 1 roll get { 3 div + {2 { 1 add 2 div 3 mul dup floor sub 2 mul 1 sub exch} repeat + FMSpotFunction } } {/FMSpotFunction load } ifelse + 0.0 exch +} bind def +/getBlackScreen { + FMUseHighFrequencyScreens { KHighFreqs } { KLowFreqs } ifelse + screenIndex get 45.0 /FMSpotFunction load +} bind def +/getSpotScreen { + getBlackScreen +} bind def +/getCompositeScreen { + getBlackScreen +} bind def +/FMSetScreen + fMLevel1 { /setscreen load + }{ { + 8 dict begin + /HalftoneType 1 def + /SpotFunction exch def + /Angle exch def + /Frequency exch def + /AccurateScreens FMUseAcccurateScreens def + currentdict end sethalftone + } bind } ifelse +def +/setDefaultScreen { + FMPColor { + orgrxfer cvx orggxfer cvx orgbxfer cvx orgxfer cvx setcolortransfer + } + { + orgxfer cvx settransfer + } ifelse + orgfreq organgle orgproc cvx setscreen +} bind def +/setCurrentScreen { + FrameSepIs FMnone eq { + FMUseDefaultNoSeparationScreen { + setDefaultScreen + } { + getCompositeScreen FMSetScreen + } ifelse + } { + FrameSepIs FMcustom eq { + FMUseDefaultSpotSeparationScreen { + setDefaultScreen + } { + getSpotScreen FMSetScreen + } ifelse + } { + FMUseDefaultProcessSeparationScreen { + setDefaultScreen + } { + FrameSepIs FMcyan eq { + getCyanScreen FMSetScreen + } { + FrameSepIs FMmagenta eq { + getMagentaScreen FMSetScreen + } { + FrameSepIs FMyellow eq { + getYellowScreen FMSetScreen + } { + getBlackScreen FMSetScreen + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse +} bind def +end + +/FMDOCUMENT { + array /FMfonts exch def + /#copies exch def + FrameDict begin + 0 ne /manualfeed exch def + /paperheight exch def + /paperwidth exch def + 0 ne /fMNegative exch def + 0 ne /edown exch def + /yscale exch def + /xscale exch def + fMLevel1 { + manualfeed {setmanualfeed} if + /FMdicttop countdictstack 1 add def + /FMoptop count def + setpapername + manualfeed {true} {papersize} ifelse + {manualpapersize} {false} ifelse + {desperatepapersize} {false} ifelse + {papersizefailure} if + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + } + {2 dict + dup /PageSize [paperwidth paperheight] put + manualfeed {dup /ManualFeed manualfeed put} if + {setpagedevice} stopped {papersizefailure} if + } + ifelse + + FMPColor { + currentcolorscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + cvlit /orgbproc exch def + /orgbangle exch def + /orgbfreq exch def + cvlit /orggproc exch def + /orggangle exch def + /orggfreq exch def + cvlit /orgrproc exch def + /orgrangle exch def + /orgrfreq exch def + currentcolortransfer + fMNegative { + 1 1 4 { + pop { 1 exch sub } fmConcatProcs 4 1 roll + } for + 4 copy + setcolortransfer + } if + cvlit /orgxfer exch def + cvlit /orgbxfer exch def + cvlit /orggxfer exch def + cvlit /orgrxfer exch def + } { + currentscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + + currenttransfer + fMNegative { + { 1 exch sub } fmConcatProcs + dup settransfer + } if + cvlit /orgxfer exch def + } ifelse + end +} def +/FMBEGINPAGE { + FrameDict begin + /pagesave save def + 3.86 setmiterlimit + /landscape exch 0 ne def + landscape { + 90 rotate 0 exch dup /pwid exch def neg translate pop + }{ + pop /pwid exch def + } ifelse + edown { [-1 0 0 1 pwid 0] concat } if + 0 0 moveto paperwidth 0 lineto paperwidth paperheight lineto + 0 paperheight lineto 0 0 lineto 1 setgray fill + xscale yscale scale + /orgmatrix matrix def + gsave +} def +/FMENDPAGE { + grestore + pagesave restore + end + showpage + } def +/FMFONTDEFINE { + FrameDict begin + findfont + ReEncode + 1 index exch + definefont + FMfonts 3 1 roll + put + end + } def +/FMFILLS { + FrameDict begin dup + array /fillvals exch def + dict /patCache exch def + end + } def +/FMFILL { + FrameDict begin + fillvals 3 1 roll put + end + } def +/FMNORMALIZEGRAPHICS { + newpath + 1 setlinewidth + 0 setlinecap + 0 0 0 sethsbcolor + 0 setgray + } bind def +/FMBEGINEPSF { + end + /FMEPSF save def + /showpage {} def +% See Adobe's "PostScript Language Reference Manual, 2nd Edition", page 714. +% "...the following operators MUST NOT be used in an EPS file:" (emphasis ours) + /banddevice {(banddevice) FMBADEPSF} def + /clear {(clear) FMBADEPSF} def + /cleardictstack {(cleardictstack) FMBADEPSF} def + /copypage {(copypage) FMBADEPSF} def + /erasepage {(erasepage) FMBADEPSF} def + /exitserver {(exitserver) FMBADEPSF} def + /framedevice {(framedevice) FMBADEPSF} def + /grestoreall {(grestoreall) FMBADEPSF} def + /initclip {(initclip) FMBADEPSF} def + /initgraphics {(initgraphics) FMBADEPSF} def + /quit {(quit) FMBADEPSF} def + /renderbands {(renderbands) FMBADEPSF} def + /setglobal {(setglobal) FMBADEPSF} def + /setpagedevice {(setpagedevice) FMBADEPSF} def + /setshared {(setshared) FMBADEPSF} def + /startjob {(startjob) FMBADEPSF} def + /lettertray {(lettertray) FMBADEPSF} def + /letter {(letter) FMBADEPSF} def + /lettersmall {(lettersmall) FMBADEPSF} def + /11x17tray {(11x17tray) FMBADEPSF} def + /11x17 {(11x17) FMBADEPSF} def + /ledgertray {(ledgertray) FMBADEPSF} def + /ledger {(ledger) FMBADEPSF} def + /legaltray {(legaltray) FMBADEPSF} def + /legal {(legal) FMBADEPSF} def + /statementtray {(statementtray) FMBADEPSF} def + /statement {(statement) FMBADEPSF} def + /executivetray {(executivetray) FMBADEPSF} def + /executive {(executive) FMBADEPSF} def + /a3tray {(a3tray) FMBADEPSF} def + /a3 {(a3) FMBADEPSF} def + /a4tray {(a4tray) FMBADEPSF} def + /a4 {(a4) FMBADEPSF} def + /a4small {(a4small) FMBADEPSF} def + /b4tray {(b4tray) FMBADEPSF} def + /b4 {(b4) FMBADEPSF} def + /b5tray {(b5tray) FMBADEPSF} def + /b5 {(b5) FMBADEPSF} def + FMNORMALIZEGRAPHICS + [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall + fx fw 2 div add fy fh 2 div add translate + rotate + fw 2 div neg fh 2 div neg translate + fw urx llx sub div fh ury lly sub div scale + llx neg lly neg translate + /FMdicttop countdictstack 1 add def + /FMoptop count def + } bind def +/FMENDEPSF { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMEPSF restore + FrameDict begin + } bind def +FrameDict begin +/setmanualfeed { +%%BeginFeature *ManualFeed True + statusdict /manualfeed true put +%%EndFeature + } bind def +/max {2 copy lt {exch} if pop} bind def +/min {2 copy gt {exch} if pop} bind def +/inch {72 mul} def +/pagedimen { + paperheight sub abs 16 lt exch + paperwidth sub abs 16 lt and + {/papername exch def} {pop} ifelse + } bind def +/setpapername { + /papersizedict 14 dict def + papersizedict begin + /papername /unknown def + /Letter 8.5 inch 11.0 inch pagedimen + /LetterSmall 7.68 inch 10.16 inch pagedimen + /Tabloid 11.0 inch 17.0 inch pagedimen + /Ledger 17.0 inch 11.0 inch pagedimen + /Legal 8.5 inch 14.0 inch pagedimen + /Statement 5.5 inch 8.5 inch pagedimen + /Executive 7.5 inch 10.0 inch pagedimen + /A3 11.69 inch 16.5 inch pagedimen + /A4 8.26 inch 11.69 inch pagedimen + /A4Small 7.47 inch 10.85 inch pagedimen + /B4 10.125 inch 14.33 inch pagedimen + /B5 7.16 inch 10.125 inch pagedimen + end + } bind def +/papersize { + papersizedict begin + /Letter {lettertray letter} def + /LetterSmall {lettertray lettersmall} def + /Tabloid {11x17tray 11x17} def + /Ledger {ledgertray ledger} def + /Legal {legaltray legal} def + /Statement {statementtray statement} def + /Executive {executivetray executive} def + /A3 {a3tray a3} def + /A4 {a4tray a4} def + /A4Small {a4tray a4small} def + /B4 {b4tray b4} def + /B5 {b5tray b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + statusdict begin stopped end + } bind def +/manualpapersize { + papersizedict begin + /Letter {letter} def + /LetterSmall {lettersmall} def + /Tabloid {11x17} def + /Ledger {ledger} def + /Legal {legal} def + /Statement {statement} def + /Executive {executive} def + /A3 {a3} def + /A4 {a4} def + /A4Small {a4small} def + /B4 {b4} def + /B5 {b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + stopped + } bind def +/desperatepapersize { + statusdict /setpageparams known + { + paperwidth paperheight 0 1 + statusdict begin + {setpageparams} stopped + end + } {true} ifelse + } bind def +/papersizefailure { + FMAllowPaperSizeMismatch not + { +(The requested paper size is not available in any currently-installed tray) +(Edit the PS file to "FMAllowPaperSizeMismatch true" to use default tray) + FMFAILURE } if + } def +/DiacriticEncoding [ +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl +/numbersign /dollar /percent /ampersand /quotesingle /parenleft +/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K +/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash +/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h +/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar +/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute +/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis +/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis +/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve +/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex +/udieresis /dagger /.notdef /cent /sterling /section /bullet +/paragraph /germandbls /registered /copyright /trademark /acute +/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef +/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown +/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef +/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde +/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright +/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis +/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl +/periodcentered /quotesinglbase /quotedblbase /perthousand +/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute +/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve +/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron +/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +] def +/ReEncode { + dup + length + dict begin + { + 1 index /FID ne + {def} + {pop pop} ifelse + } forall + 0 eq {/Encoding DiacriticEncoding def} if + currentdict + end + } bind def +FMPColor + + { + /BEGINBITMAPCOLOR { + BITMAPCOLOR} def + /BEGINBITMAPCOLORc { + BITMAPCOLORc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUECOLOR } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUECOLORc } def + /BEGINBITMAPCMYK { + BITMAPCMYK } def + /BEGINBITMAPCMYKc { + BITMAPCMYKc } def + } + + { + /BEGINBITMAPCOLOR { + BITMAPGRAY} def + /BEGINBITMAPCOLORc { + BITMAPGRAYc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUEGRAY } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUEGRAYc } def + /BEGINBITMAPCMYK { + BITMAPCMYKGRAY } def + /BEGINBITMAPCMYKc { + BITMAPCMYKGRAYc } def + } +ifelse +/K { + FMPrintAllColorsAsBlack { + dup 1 eq 2 index 1 eq and 3 index 1 eq and not + {7 {pop} repeat 0 0 0 1 0 0 0} if + } if + FrameCurColors astore + pop combineColor +} bind def +/graymode true def +fMLevel1 { + /fmGetFlip { + fMatrix2 exch get mul 0 lt { -1 } { 1 } ifelse + } FmBD +} if +/setPatternMode { + fMLevel1 { + 2 index patScreenDict exch known { + pop pop + patScreenDict exch get aload pop + freq + mul + 5 2 roll + fMatrix2 currentmatrix 1 get 0 ne { + 3 -1 roll 90 add 3 1 roll + sflipx 1 fmGetFlip sflipy 2 fmGetFlip neg mul + } { + sflipx 0 fmGetFlip sflipy 3 fmGetFlip mul + } ifelse + 0 lt {exch pop} {pop} ifelse + fMNegative { + {neg} fmConcatProcs + } if + bind + + + + systemdict /setscreen get exec + /FrameCurGray exch def + } { + /bwidth exch def + /bpside exch def + /bstring exch def + /onbits 0 def /offbits 0 def + freq sangle landscape {90 add} if + {/ypoint exch def + /xpoint exch def + /xindex xpoint 1 add 2 div bpside mul cvi def + /yindex ypoint 1 add 2 div bpside mul cvi def + bstring yindex bwidth mul xindex 8 idiv add get + 1 7 xindex 8 mod sub bitshift and 0 ne fMNegative {not} if + {/onbits onbits 1 add def 1} + {/offbits offbits 1 add def 0} + ifelse + } + setscreen + offbits offbits onbits add div fMNegative {1.0 exch sub} if + /FrameCurGray exch def + } ifelse + } { + pop pop + dup patCache exch known { + patCache exch get + } { + dup + patDict /bstring 3 -1 roll put + patDict + 9 PatFreq screenIndex get div dup matrix scale + makepattern + dup + patCache 4 -1 roll 3 -1 roll put + } ifelse + /FrameCurGray 0 def + /FrameCurPat exch def + } ifelse + /graymode false def + combineColor +} bind def +/setGrayScaleMode { + graymode not { + /graymode true def + fMLevel1 { + setCurrentScreen + } if + } if + /FrameCurGray exch def + combineColor +} bind def +/normalize { + transform round exch round exch itransform + } bind def +/dnormalize { + dtransform round exch round exch idtransform + } bind def +/lnormalize { + 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop + } bind def +/H { + lnormalize setlinewidth + } bind def +/Z { + setlinecap + } bind def + +/PFill { + graymode fMLevel1 or not { + gsave 1 setgray eofill grestore + } if +} bind def +/PStroke { + graymode fMLevel1 or not { + gsave 1 setgray stroke grestore + } if + stroke +} bind def +/X { + fillvals exch get + dup type /stringtype eq + {8 1 setPatternMode} + {setGrayScaleMode} + ifelse + } bind def +/V { + PFill gsave eofill grestore + } bind def +/Vclip { + clip + } bind def +/Vstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/N { + PStroke + } bind def +/Nclip { + strokepath clip newpath + } bind def +/Nstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/M {newpath moveto} bind def +/E {lineto} bind def +/D {curveto} bind def +/O {closepath} bind def +/L { + /n exch def + newpath + normalize + moveto + 2 1 n {pop normalize lineto} for + } bind def +/Y { + L + closepath + } bind def +/R { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + x1 y1 + x2 y1 + x2 y2 + x1 y2 + 4 Y + } bind def +/rarc + {rad + arcto + } bind def +/RR { + /rad exch def + normalize + /y2 exch def + /x2 exch def + normalize + /y1 exch def + /x1 exch def + mark + newpath + { + x1 y1 rad add moveto + x1 y2 x2 y2 rarc + x2 y2 x2 y1 rarc + x2 y1 x1 y1 rarc + x1 y1 x1 y2 rarc + closepath + } stopped {x1 y1 x2 y2 R} if + cleartomark + } bind def +/RRR { + /rad exch def + normalize /y4 exch def /x4 exch def + normalize /y3 exch def /x3 exch def + normalize /y2 exch def /x2 exch def + normalize /y1 exch def /x1 exch def + newpath + normalize moveto + mark + { + x2 y2 x3 y3 rarc + x3 y3 x4 y4 rarc + x4 y4 x1 y1 rarc + x1 y1 x2 y2 rarc + closepath + } stopped + {x1 y1 x2 y2 x3 y3 x4 y4 newpath moveto lineto lineto lineto closepath} if + cleartomark + } bind def +/C { + grestore + gsave + R + clip + setCurrentScreen +} bind def +/CP { + grestore + gsave + Y + clip + setCurrentScreen +} bind def +/F { + FMfonts exch get + FMpointsize scalefont + setfont + } bind def +/Q { + /FMpointsize exch def + F + } bind def +/T { + moveto show + } bind def +/RF { + rotate + 0 ne {-1 1 scale} if + } bind def +/TF { + gsave + moveto + RF + show + grestore + } bind def +/P { + moveto + 0 32 3 2 roll widthshow + } bind def +/PF { + gsave + moveto + RF + 0 32 3 2 roll widthshow + grestore + } bind def +/S { + moveto + 0 exch ashow + } bind def +/SF { + gsave + moveto + RF + 0 exch ashow + grestore + } bind def +/B { + moveto + 0 32 4 2 roll 0 exch awidthshow + } bind def +/BF { + gsave + moveto + RF + 0 32 4 2 roll 0 exch awidthshow + grestore + } bind def +/G { + gsave + newpath + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill fill + grestore + } bind def +/Gstrk { + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/Gclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GG { + gsave + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill + fill + grestore + } bind def +/GGclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GGstrk { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/A { + gsave + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/Aclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/Astrk { + Gstrk +} bind def +/AA { + gsave + savematrix + newpath + + 3 index 2 div add exch 4 index 2 div sub exch + + normalize 3 index 2 div sub exch 4 index 2 div add exch + translate + rotate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/AAclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/AAstrk { + GGstrk +} bind def +/BEGINPRINTCODE { + /FMdicttop countdictstack 1 add def + /FMoptop count 7 sub def + /FMsaveobject save def + userdict begin + /showpage {} def + FMNORMALIZEGRAPHICS + 3 index neg 3 index neg translate + } bind def +/ENDPRINTCODE { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMsaveobject restore + } bind def +/gn { + 0 + { 46 mul + cf read pop + 32 sub + dup 46 lt {exit} if + 46 sub add + } loop + add + } bind def +/cfs { + /str sl string def + 0 1 sl 1 sub {str exch val put} for + str def + } bind def +/ic [ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 + {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx} + {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx} + {19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} + {13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh} + {4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh} + {13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl} + {7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl} + {0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl} + {10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl} + ] def +/ms { + /sl exch def + /val 255 def + /ws cfs + /im cfs + /val 0 def + /bs cfs + /cs cfs + } bind def +400 ms +/ip { + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip { + + + bis ris copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + ris gis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + gis bis copy pop + dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip4 { + + + kis cis copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + cis mis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + mis yis copy pop + dup dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + yis kis copy pop + 3 mul is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/wh { + /len exch def + /pos exch def + ws 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/bl { + /len exch def + /pos exch def + bs 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/s1 1 string def +/fl { + /len exch def + /pos exch def + /val cf s1 readhexstring pop 0 get def + pos 1 pos len add 1 sub {im exch val put} for + pos len + } bind def +/hx { + 3 copy getinterval + cf exch readhexstring pop pop + } bind def +/wbytes { + dup dup + 8 gt { pop 8 idiv mul } + { 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse } ifelse + } bind def +/BEGINBITMAPBWc { + 1 {} COMMONBITMAPc + } bind def +/BEGINBITMAPGRAYc { + 8 {} COMMONBITMAPc + } bind def +/BEGINBITMAP2BITc { + 2 {} COMMONBITMAPc + } bind def +/COMMONBITMAPc { + + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + cvtProc + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} image + bitmapsave restore + grestore + } bind def +/BEGINBITMAPBW { + 1 {} COMMONBITMAP + } bind def +/BEGINBITMAPGRAY { + 8 {} COMMONBITMAP + } bind def +/BEGINBITMAP2BIT { + 2 {} COMMONBITMAP + } bind def +/COMMONBITMAP { + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + cvtProc + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} image + bitmapsave restore + grestore + } bind def +/ngrayt 256 array def +/nredt 256 array def +/nbluet 256 array def +/ngreent 256 array def +fMLevel1 { +/colorsetup { + currentcolortransfer + /gryt exch def + /blut exch def + /grnt exch def + /redt exch def + 0 1 255 { + /indx exch def + /cynu 1 red indx get 255 div sub def + /magu 1 green indx get 255 div sub def + /yelu 1 blue indx get 255 div sub def + /kk cynu magu min yelu min def + /u kk currentundercolorremoval exec def +% /u 0 def + nredt indx 1 0 cynu u sub max sub redt exec put + ngreent indx 1 0 magu u sub max sub grnt exec put + nbluet indx 1 0 yelu u sub max sub blut exec put + ngrayt indx 1 kk currentblackgeneration exec sub gryt exec put + } for + {255 mul cvi nredt exch get} + {255 mul cvi ngreent exch get} + {255 mul cvi nbluet exch get} + {255 mul cvi ngrayt exch get} + setcolortransfer + {pop 0} setundercolorremoval + {} setblackgeneration + } bind def +} +{ +/colorSetup2 { + [ /Indexed /DeviceRGB 255 + {dup red exch get 255 div + exch dup green exch get 255 div + exch blue exch get 255 div} + ] setcolorspace +} bind def +} ifelse +/fakecolorsetup { + /tran 256 string def + 0 1 255 {/indx exch def + tran indx + red indx get 77 mul + green indx get 151 mul + blue indx get 28 mul + add add 256 idiv put} for + currenttransfer + {255 mul cvi tran exch get 255.0 div} + exch fmConcatProcs settransfer +} bind def +/BITMAPCOLOR { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + fMLevel1 { + colorsetup + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} {is} {is} true 3 colorimage + } { + colorSetup2 + /is width depth wbytes string def + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {cf is readhexstring pop} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPCOLORc { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + fMLevel1 { + colorsetup + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} {is} {is} true 3 colorimage + } { + colorSetup2 + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {ip} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLORc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris} {gis} {bis} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYKc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip4 pop cis} {mis} {yis} {kis} true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLOR { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf gis readhexstring pop } + { cf bis readhexstring pop } + true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYK { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /mis width string def + /yis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf mis readhexstring pop } + { cf yis readhexstring pop } + { cf kis readhexstring pop } + true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUEGRAYc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris gis bis width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAYc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop cis mis yis kis width cgray} image + bitmapsave restore + grestore + } bind def +/cgray { + /ww exch def + /k exch def + /y exch def + /m exch def + /c exch def + 0 1 ww 1 sub { /i exch def c i get m i get y i get k i get CMYKtoRGB + .144 mul 3 1 roll .587 mul 3 1 roll .299 mul add add + c i 3 -1 roll floor cvi put } for + c + } bind def +/gray { + /ww exch def + /b exch def + /g exch def + /r exch def + 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul + b i get .114 mul add add r i 3 -1 roll floor cvi put } for + r + } bind def +/BITMAPTRUEGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf gis readhexstring pop + cf bis readhexstring pop width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /yis width string def + /mis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf mis readhexstring pop + cf yis readhexstring pop + cf kis readhexstring pop width cgray} image + bitmapsave restore + grestore + } bind def +/BITMAPGRAY { + 8 {fakecolorsetup} COMMONBITMAP + } bind def +/BITMAPGRAYc { + 8 {fakecolorsetup} COMMONBITMAPc + } bind def +/ENDBITMAP { + } bind def +end + /ALDmatrix matrix def ALDmatrix currentmatrix pop +/StartALD { + /ALDsave save def + savematrix + ALDmatrix setmatrix + } bind def +/InALD { + restorematrix + } bind def +/DoneALD { + ALDsave restore + } bind def +/I { setdash } bind def +/J { [] 0 setdash } bind def +%%EndProlog +%%BeginSetup +(5.0) FMVERSION +1 1 0 0 612 792 0 1 9 FMDOCUMENT +0 0 /Helvetica FMFONTDEFINE +1 0 /Times-BoldItalic FMFONTDEFINE +2 0 /Helvetica-Bold FMFONTDEFINE +3 0 /Helvetica-Oblique FMFONTDEFINE +4 0 /Helvetica-BoldOblique FMFONTDEFINE +5 0 /Courier-BoldOblique FMFONTDEFINE +32 FMFILLS +0 0 FMFILL +1 0.1 FMFILL +2 0.3 FMFILL +3 0.5 FMFILL +4 0.7 FMFILL +5 0.9 FMFILL +6 0.97 FMFILL +7 1 FMFILL +8 <0f1e3c78f0e1c387> FMFILL +9 <0f87c3e1f0783c1e> FMFILL +10 FMFILL +11 FMFILL +12 <8142241818244281> FMFILL +13 <03060c183060c081> FMFILL +14 <8040201008040201> FMFILL +16 1 FMFILL +17 0.9 FMFILL +18 0.7 FMFILL +19 0.5 FMFILL +20 0.3 FMFILL +21 0.1 FMFILL +22 0.03 FMFILL +23 0 FMFILL +24 FMFILL +25 FMFILL +26 <3333333333333333> FMFILL +27 <0000ffff0000ffff> FMFILL +28 <7ebddbe7e7dbbd7e> FMFILL +29 FMFILL +30 <7fbfdfeff7fbfdfe> FMFILL +%%EndSetup +%%Page: "i" 1 +%%BeginPaperSize: Letter +%%EndPaperSize +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(i) 555.78 57 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 720 558 720 2 L +0.5 H +2 Z +N +72 72 558 72 2 L +N +72 504 558 504 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 32 Q +(CDEV Script Service) 198 662.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(A T) 198 627.33 T +(ool f) 212.36 627.33 T +(or Using Inter) 230.96 627.33 T +(activ) 290.88 627.33 T +(e Scr) 311.19 627.33 T +(ipts from CDEV) 334.68 627.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(W) 198 603.33 T +(alt Ak) 207.04 603.33 T +(ers) 231.85 603.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 198 579.33 T +(ersion 1.0 - F) 203.87 579.33 T +(ebr) 262.48 579.33 T +(uar) 277.08 579.33 T +(y 11, 1997) 291.83 579.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(TJNAF - Thomas Jeff) 198 555.33 T +(erson National Acceler) 292.72 555.33 T +(ator F) 393.21 555.33 T +(acility) 418.83 555.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "i" 1 +%%Page: "ii" 2 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(ii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(TRADEMARKS:) 54 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(UNIX is a registered tr) 180 569.33 T +(ademar) 278.26 569.33 T +(k of A) 312.31 569.33 T +(T&T in the USA and other countr) 336.68 569.33 T +(ies) 481.9 569.33 T +(.) 494.53 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(VxW) 180 545.33 T +(or) 200.81 545.33 T +(ks is a register tr) 209.85 545.33 T +(ademar) 283.1 545.33 T +(k of Wind Riv) 317.15 545.33 T +(er Systems) 375.8 545.33 T +(.) 425.66 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The X Windo) 180 521.33 T +(w System is a tr) 237.65 521.33 T +(ademar) 308.12 521.33 T +(k of Massachusetts Institute of T) 342.17 521.33 T +(echnology) 484.37 521.33 T +(.) 528.95 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(OSF/Motif and Motif are tr) 180 497.33 T +(ademar) 294.94 497.33 T +(ks of Open Softw) 328.99 497.33 T +(are F) 404.99 497.33 T +(oundation, Inc.) 428.03 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ultr) 180 473.33 T +(ix and DEC are registered tr) 195.7 473.33 T +(ademar) 319.53 473.33 T +(ks of Digital Equipment Cor) 353.58 473.33 T +(por) 475.03 473.33 T +(ation.) 489.38 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(HPUX is a registered tr) 180 449.33 T +(ademar) 282.15 449.33 T +(k of He) 316.2 449.33 T +(wlett P) 347.68 449.33 T +(ac) 377.29 449.33 T +(kard.) 387.65 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(SURA/CEB) 54 344.33 T +(AF:) 105.92 344.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.44 (The Southeaster) 180 344.33 P +4.44 (n Univ) 258.62 344.33 P +4.44 (ersities Research Association \050SURA\051 oper) 291.15 344.33 P +4.44 (ates the) 499.98 344.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.01 (Contin) 180 332.33 P +2.01 (uous Electron Beam Acceler) 208.8 332.33 P +2.01 (ator F) 340.89 332.33 P +2.01 (acility \050CEBAF\051 f) 368.52 332.33 P +2.01 (or the United States) 445.59 332.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Depar) 180 320.33 T +(tment of Energy under contr) 207.63 320.33 T +(act DE-A) 331.48 320.33 T +(C05-84ER40150.) 371.19 320.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DISCLAIMER:) 54 218.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.49 (This repor) 180 218.33 P +0.49 (t w) 225.9 218.33 P +0.49 (as prepared as an account of w) 239.02 218.33 P +0.49 (or) 381.4 218.33 P +0.49 (k sponsored b) 390.44 218.33 P +0.49 (y the United States) 454.03 218.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.18 (go) 180 206.33 P +2.18 (v) 190.97 206.33 P +2.18 (er) 195.72 206.33 P +2.18 (nment. Neither the United States nor the United States Depar) 204.86 206.33 P +2.18 (tment of) 501.68 206.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.04 (Energy) 180 194.33 P +1.04 (, nor an) 210.68 194.33 P +1.04 (y of their emplo) 246.52 194.33 P +1.04 (y) 317.69 194.33 P +1.04 (ees) 322.49 194.33 P +1.04 (, mak) 338.46 194.33 P +1.04 (es an) 363.75 194.33 P +1.04 (y w) 389.1 194.33 P +1.04 (arr) 404.99 194.33 P +1.04 (anty) 417.11 194.33 P +1.04 (, e) 435.01 194.33 P +1.04 (xpress or implied, or) 446.86 194.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.83 (assumes an) 180 182.33 P +1.83 (y legal liability or responsibility f) 235.59 182.33 P +1.83 (or the accur) 383.89 182.33 P +1.83 (acy) 440.24 182.33 P +1.83 (, completeness) 454.8 182.33 P +1.83 (, or) 523.72 182.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.68 (usefulness of an) 180 170.33 P +3.68 (y inf) 260.02 170.33 P +3.68 (or) 281.74 170.33 P +3.68 (mation, appar) 290.88 170.33 P +3.68 (atus) 355.59 170.33 P +3.68 (, product or process disclosed, or) 374.34 170.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.46 (represents that its use w) 180 158.33 P +2.46 (ould not infr) 298.11 158.33 P +2.46 (inge pr) 355.42 158.33 P +2.46 (iv) 388.59 158.33 P +2.46 (ately o) 395.56 158.33 P +2.46 (wned r) 427.33 158.33 P +2.46 (ights) 459.95 158.33 P +2.46 (. Ref) 480.92 158.33 P +2.46 (erence) 509.43 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.6 (herein to an) 180 146.33 P +1.6 (y speci\336c commercial product, process) 235.85 146.33 P +1.6 (, or ser) 413.79 146.33 P +1.6 (vice b) 448.4 146.33 P +1.6 (y tr) 475.92 146.33 P +1.6 (ade name) 491.3 146.33 P +1.6 (,) 537.22 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (mar) 180 134.33 P +2.12 (k, man) 197.37 134.33 P +2.12 (uf) 229.4 134.33 P +2.12 (acturer) 237.44 134.33 P +2.12 (, or otherwise) 268.06 134.33 P +2.12 (, does not necessar) 332.17 134.33 P +2.12 (ily constitute or imply its) 425.94 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (endorsement, recommendation, or f) 180 122.33 P +1.08 (a) 341.33 122.33 P +1.08 (v) 346.69 122.33 P +1.08 (or) 351.44 122.33 P +1.08 (ing b) 360.48 122.33 P +1.08 (y the United States go) 383.03 122.33 P +1.08 (v) 485.57 122.33 P +1.08 (er) 490.32 122.33 P +1.08 (nment or) 499.46 122.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (an) 180 110.33 P +0.83 (y agency thereof) 190.97 110.33 P +0.83 (. The vie) 266.26 110.33 P +0.83 (w and opinions of the authors e) 309.67 110.33 P +0.83 (xpressed herein do) 453.3 110.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.94 (not necessar) 180 98.33 P +1.94 (ily state or re\337ect those of the United States go) 239.34 98.33 P +1.94 (v) 464.01 98.33 P +1.94 (er) 468.76 98.33 P +1.94 (nment or an) 477.9 98.33 P +1.94 (y) 535 98.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(agency thereof) 180 86.33 T +(.) 245.85 86.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DOCUMENT D) 54 668.33 T +(A) 121.37 668.33 T +(TE:) 127.69 668.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(T) 180 668.33 T +(ab) 184.91 668.33 T +(le of contents gener) 195.83 668.33 T +(ated: F) 283.56 668.33 T +(ebr) 314.39 668.33 T +(uar) 328.99 668.33 T +(y 13, 1997 2:57 pm) 343.74 668.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "ii" 2 +%%Page: "iii" 3 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iii) 551.34 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(T) 180 710.67 T +(ab) 187.43 710.67 T +(le of Contents) 203.63 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Scr) 198 684.33 T +(ipt Ser) 213.15 684.33 T +(vice Fundamentals) 242.35 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 328.04 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 672.33 T +(er) 210.73 672.33 T +(vie) 219.92 672.33 T +(w of the Scr) 232.5 672.33 T +(ipt Ser) 285.45 672.33 T +(vice) 314.65 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 333.6 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(F) 198.2 660.33 T +(eatures of the Scr) 204.01 660.33 T +(ipt Ser) 283.09 660.33 T +(vice) 312.29 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 330.82 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 180 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Building the Scr) 198 648.33 T +(ipt Ser) 268.18 648.33 T +(vice) 297.38 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 316.92 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Location of Files) 198.2 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Steps to Building Ser) 198.2 624.33 T +(vice) 291.88 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 311.36 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 180 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Str) 198 612.33 T +(ucture of Data Pro) 210.93 612.33 T +(vided to the Scr) 291.93 612.33 T +(ipt) 361.56 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 372.52 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Gener) 198.2 600.33 T +(al F) 225.89 600.33 T +(or) 242.26 600.33 T +(m of Data Str) 251.4 600.33 T +(ing) 310.46 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 325.26 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Representation of Scalar Data) 198.2 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 333.6 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Representation of Arr) 198.2 576.33 T +(a) 293.14 576.33 T +(y Data) 298.4 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 328.04 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 180 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Str) 198 564.33 T +(ucture of Data Retur) 210.93 564.33 T +(ned from the Scr) 301.22 564.33 T +(ipt) 375.29 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 386.42 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Retur) 198.2 552.33 T +(ning Data to the Calling CDEV Application) 222.9 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . .) 411.44 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Gener) 198.2 540.33 T +(al F) 225.89 540.33 T +(or) 242.26 540.33 T +(m of Str) 251.4 540.33 T +(ing Data) 286.56 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 325.26 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Retur) 198.2 528.33 T +(ning a Single Result P) 222.9 528.33 T +(ac) 320.88 528.33 T +(k) 331.24 528.33 T +(et) 336.04 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 344.72 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Retur) 198.2 516.33 T +(ning Multiple Result P) 222.9 516.33 T +(ac) 319.2 516.33 T +(k) 329.56 516.33 T +(ets) 334.36 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 350.28 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Special Consider) 198.2 504.33 T +(ations) 273.68 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 303.02 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 180 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(DDL Entr) 198 492.33 T +(ies f) 239.27 492.33 T +(or the Scr) 257.31 492.33 T +(ipt Ser) 300.81 492.33 T +(vice) 330.01 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 350.28 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Setting Up the DDL) 198.2 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 286.34 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iii" 3 +%%Page: "iv" 4 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iv) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iv" 4 +%%Page: "v" 5 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(v) 553 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(List of Figures) 180 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(Figure 1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(General form of string representation of cdevData) 234 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..................................) 455.92 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 2.) 180 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(String representation of scalar data in a cdevData object) 234 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................) 483.72 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 3.) 180 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(String representation of array data) 234 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........................................................) 386.42 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 4.) 180 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Returning a single result packet to the CDEV application) 234 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................) 483.72 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 5.) 180 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Returning a multiple result packets to the CDEV application) 234 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................) 497.62 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 6.) 180 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Simple DDL file for the Script Service) 234 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(......................................................) 400.32 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "v" 5 +%%Page: "vi" 6 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(vi) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "vi" 6 +%%Page: "1" 7 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. Scr) 432.55 739 T +(ipt Ser) 456.19 739 T +(vice Fundamentals) 482.47 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1) 552.44 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(1.) 159.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Script Ser) 180 710.67 T +(vice Fundamentals) 246.28 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w of the) 108.64 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Script Ser) 72 661.33 T +(vice) 119.34 661.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.1 (The CDEV Scr) 180 673.33 P +1.1 (ipt Ser) 247.92 673.33 P +1.1 (vice is designed to allo) 278.21 673.33 P +1.1 (w a a CDEV application to e) 383.05 673.33 P +1.1 (x) 513.84 673.33 P +1.1 (ecute an) 518.54 673.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.6 (e) 180 661.33 P +0.6 (xter) 185.26 661.33 P +0.6 (nal scr) 202.18 661.33 P +0.6 (ipt to process a message) 232.38 661.33 P +0.6 (. The output that is produced b) 345.77 661.33 P +0.6 (y the e) 484.79 661.33 P +0.6 (x) 515.7 661.33 P +0.6 (ecutab) 520.4 661.33 P +0.6 (le) 550.22 661.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.54 (will be retur) 180 649.33 P +1.54 (ned to the caller in the f) 234.45 649.33 P +1.54 (or) 347.32 649.33 P +1.54 (m of a cde) 356.46 649.33 P +1.54 (vData. The CDEV Scr) 407.47 649.33 P +1.54 (ipt Ser) 509.48 649.33 P +1.54 (vice) 540.22 649.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(meets the f) 180 637.33 T +(ollo) 229.17 637.33 T +(wing requirements) 244.58 637.33 T +(.) 326.12 637.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Features of the) 72 608.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Script Ser) 72 596.33 T +(vice) 119.34 596.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(\245) 180 608.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +5.28 (The \336lename of the scr) 198 608.33 P +5.28 (ipt is associated with a CDEV de) 320.98 608.33 P +5.28 (vice/message) 496.87 608.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.17 (combination b) 198 596.33 P +-0.17 (y using the \322\336lename\323 \336eld of the ser) 259.88 596.33 P +-0.17 (vice data in the CDEV DDL \336le) 420.2 596.33 P +-0.17 (.) 555.22 596.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Syntax is descr) 198 584.33 T +(ibed later in this document.) 265.95 584.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 560.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.22 (A ne) 198 560.33 P +-0.22 (w process will be spa) 218.15 560.33 P +-0.22 (wned f) 311.56 560.33 P +-0.22 (or the scr) 340.51 560.33 P +-0.22 (ipt each time it is e) 381.9 560.33 P +-0.22 (x) 463.34 560.33 P +-0.22 (ecuted. Its standard) 468.04 560.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.77 (output \050stdout\051 \336le descr) 198 548.33 P +0.77 (iptor will be redirected to retur) 307.73 548.33 P +0.77 (n data to the main CDEV) 443.54 548.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(application, allo) 198 536.33 T +(wing the scr) 266.77 536.33 T +(ipt to retur) 320.27 536.33 T +(n results to the parent process) 365.54 536.33 T +(.) 499.9 536.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 512.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.43 (The e) 198 512.33 P +1.43 (xter) 224.7 512.33 P +1.43 (nal e) 241.62 512.33 P +1.43 (x) 264.43 512.33 P +1.43 (ecutab) 269.13 512.33 P +1.43 (le \336le can be an) 298.95 512.33 P +1.43 (y f) 374.57 512.33 P +1.43 (or) 386.26 512.33 P +1.43 (m of user shell, batch \336le or binar) 395.4 512.33 P +1.43 (y) 553 512.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(application that is suppor) 198 500.33 T +(ted on the host platf) 309.01 500.33 T +(or) 396.55 500.33 T +(m.) 405.69 500.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 476.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +6.12 (The Scr) 198 476.33 P +6.12 (ipt Ser) 239.28 476.33 P +6.12 (vice suppor) 274.61 476.33 P +6.12 (ts all of CDEV\325) 332.26 476.33 P +6.12 (s send mechanisms; \322send\323,) 414.59 476.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.28 (\322sendNoBloc) 198 464.33 P +0.28 (k\323 and \322sendCallbac) 255.04 464.33 P +0.28 (k\323. Because of limits imposed on the n) 344.33 464.33 P +0.28 (umber of) 518.25 464.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.14 (activ) 198 452.33 P +2.14 (e processes) 218.31 452.33 P +2.14 (, the user is advised to use the synchronous \322send\323 method) 274.21 452.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(whene) 198 440.33 T +(v) 227.16 440.33 T +(er pr) 231.91 440.33 T +(actical.) 252.37 440.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 416.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.09 (When called b) 198 416.33 P +1.09 (y CDEV) 263.34 416.33 P +1.09 (, the scr) 298.74 416.33 P +1.09 (ipt will receiv) 336.65 416.33 P +1.09 (e three arguments; the name of the) 395.25 416.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.06 (CDEV de) 198 404.33 P +0.06 (vice associated with the request, the message str) 239.44 404.33 P +0.06 (ing that w) 458.47 404.33 P +0.06 (as submitted) 501.25 404.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.49 (to the de) 198 392.33 P +0.49 (vice) 237.6 392.33 P +0.49 (, and a str) 255.23 392.33 P +0.49 (ing that descr) 301.31 392.33 P +0.49 (ibes the contents of the outbound cde) 362.47 392.33 P +0.49 (vData) 531.88 392.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(object.) 198 380.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 356.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.46 (The reply that is wr) 198 356.33 P +0.46 (itten to the standard output b) 284.47 356.33 P +0.46 (y the scr) 413.9 356.33 P +0.46 (ipt m) 452.77 356.33 P +0.46 (ust ha) 474.8 356.33 P +0.46 (v) 502.3 356.33 P +0.46 (e a speci\336c) 507.05 356.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.05 (f) 198 344.33 P +1.05 (or) 200.48 344.33 P +1.05 (mat as descr) 209.62 344.33 P +1.05 (ibed later in this document. A scr) 269.1 344.33 P +1.05 (ipt ma) 424.42 344.33 P +1.05 (y retur) 452.4 344.33 P +1.05 (n more than one) 482.04 344.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(reply pac) 198 332.33 T +(k) 238.37 332.33 T +(et to the caller) 243.17 332.33 T +(.) 305.48 332.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 308.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.6 (The scr) 198 308.33 P +0.6 (ipt noti\336es CDEV that it has wr) 232.09 308.33 P +0.6 (itten its last reply pac) 370.87 308.33 P +0.6 (k) 466.43 308.33 P +0.6 (et b) 471.23 308.33 P +0.6 (y wr) 488.3 308.33 P +0.6 (iting \322done\323) 507.38 308.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(alone on a line to the standard output.) 198 296.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 272.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.17 (If the scr) 198 272.33 P +0.17 (ipt is to retur) 236.84 272.33 P +0.17 (n m) 292.62 272.33 P +0.17 (ultiple results) 309.36 272.33 P +0.17 (, it should wr) 367.73 272.33 P +0.17 (ite \322end\323 alone on a line to the) 424.51 272.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.56 (standard output betw) 198 260.33 P +0.56 (een each pac) 292.41 260.33 P +0.56 (k) 353.37 260.33 P +0.56 (et, and wr) 358.17 260.33 P +0.56 (ite \322done\323 alone on a line f) 403.35 260.33 P +0.56 (ollo) 522.03 260.33 P +0.56 (wing) 537.44 260.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the last pac) 198 248.33 T +(k) 248.94 248.33 T +(et.) 253.74 248.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 224.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.88 (If the scr) 198 224.33 P +1.88 (ipt retur) 240.26 224.33 P +1.88 (ns a v) 276.3 224.33 P +1.88 (alue in the \322status\323 tag of its reply pac) 306.49 224.33 P +1.88 (k) 487.53 224.33 P +1.88 (et, this will be) 492.33 224.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.02 (pro) 198 212.33 P +2.02 (vided to the caller as the completion code of the message) 212.3 212.33 P +2.02 (. T) 487.46 212.33 P +2.02 (r) 499.95 212.33 P +2.02 (aditionally a) 503.18 212.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(status of 0 indicates success) 198 200.33 T +(, and all other v) 325.13 200.33 T +(alues indicated an error occurred.) 393.25 200.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 176.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.02 (Because the callbac) 198 176.33 P +0.02 (k mechanism of the Scr) 287.33 176.33 P +0.02 (ipt Ser) 392.02 176.33 P +0.02 (vice is tr) 421.24 176.33 P +0.02 (iggered b) 458.1 176.33 P +0.02 (y output from) 499.61 176.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.29 (the scr) 198 164.33 P +0.29 (ipt, the scr) 228.45 164.33 P +0.29 (ipt de) 275.32 164.33 P +0.29 (v) 299.77 164.33 P +0.29 (eloper should at least wr) 304.52 164.33 P +0.29 (ite \322done\323 to the standard output) 414.22 164.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(e) 198 152.33 T +(v) 203.26 152.33 T +(en if the application retur) 208.01 152.33 T +(ns no output.) 317.76 152.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "1" 7 +%%Page: "2" 8 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. Building the Scr) 54 739 T +(ipt Ser) 127.17 739 T +(vice) 153.45 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(2) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(2.) 141.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Building the Script Ser) 162 710.67 T +(vice) 313.06 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Location of Files) 54 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.15 (The source code f) 162 673.33 P +0.15 (or the Scr) 242.19 673.33 P +0.15 (ipt Ser) 285.99 673.33 P +0.15 (vice is pro) 315.34 673.33 P +0.15 (vided with the CDEV distr) 360.5 673.33 P +0.15 (ib) 474.62 673.33 P +0.15 (ution star) 482.2 673.33 P +0.15 (ting) 523.88 673.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.92 (with v) 162 661.33 P +1.92 (ersion 1.5. The source code is located in the director) 189.24 661.33 P +1.92 (y $CDEV/e) 443.89 661.33 P +1.92 (xtensions/) 494.98 661.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Scr) 162 649.33 T +(iptSer) 177.15 649.33 T +(vice) 203.57 649.33 T +(. The f) 221.2 649.33 T +(ollo) 252.03 649.33 T +(wing steps should be tak) 267.44 649.33 T +(en to b) 376.74 649.33 T +(uild the Scr) 407.12 649.33 T +(iptSer) 457.29 649.33 T +(vice) 483.71 649.33 T +(.) 501.34 649.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Steps to Building) 54 620.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ser) 54 608.33 T +(vice) 70.22 608.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(1.) 162 620.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Obtain and install the CDEV distr) 180 620.33 T +(ib) 326.32 620.33 T +(ution - V) 333.9 620.33 T +(ersion 1.5 or higher) 370.34 620.33 T +(.) 455.99 620.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 162 596.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(F) 180 596.33 T +(ollo) 185.81 596.33 T +(w the installation steps to b) 201.22 596.33 T +(uild CDEV on y) 321.08 596.33 T +(our system. This includes setting) 388.68 596.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(all of the en) 180 584.33 T +(vironment v) 231.5 584.33 T +(ar) 282.93 584.33 T +(iab) 291.97 584.33 T +(les required b) 305.11 584.33 T +(y CDEV) 365.49 584.33 T +(.) 399.8 584.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 162 560.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Change director) 180 560.33 T +(ies to) 251.29 560.33 T +3 F +($CDEV/e) 277.97 560.33 T +(xtensions/Scr) 319.35 560.33 T +(iptSer) 379.52 560.33 T +(vice/src) 405.94 560.33 T +0 F +(.) 439.83 560.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 162 536.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(There is a collection of platf) 180 536.33 T +(or) 301.42 536.33 T +(m speci\336c mak) 310.56 536.33 T +(e\336les in the director) 376.48 536.33 T +(y) 463.48 536.33 T +3 F +($CDEV/) 471.26 536.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(e) 180 524.33 T +(xtensions/cde) 185.26 524.33 T +(vGener) 246.1 524.33 T +(icSer) 279.04 524.33 T +(v) 302.12 524.33 T +(er/include/mak) 306.87 524.33 T +(einclude) 371.69 524.33 T +0 F +(. Link the mak) 408.78 524.33 T +(e\336le that is) 473.61 524.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(appropr) 180 512.33 T +(iate to y) 214.61 512.33 T +(our architecture to the \336le Mak) 249.43 512.33 T +(e\336le) 383.73 512.33 T +(.OS) 401.92 512.33 T +(.) 418.95 512.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(F) 180 488.33 T +(or e) 185.81 488.33 T +(xample) 202.74 488.33 T +(, to link to the mak) 234.82 488.33 T +(e\336le f) 315.77 488.33 T +(or HP-UX, y) 339.37 488.33 T +(ou w) 392.51 488.33 T +(ould type the f) 413.53 488.33 T +(ollo) 476.05 488.33 T +(wing) 491.46 488.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(command.) 180.12 476.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(ln -s Make\336le) 180 452.33 T +(.hpux Make\336le) 243 452.33 T +(.OS) 312.11 452.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(5.) 162 428.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(T) 180 428.33 T +(ype mak) 184.91 428.33 T +(e to compile and link the Scr) 222.5 428.33 T +(ipt Ser) 348.26 428.33 T +(vice shared object. Note that y) 377.46 428.33 T +(ou) 514.55 428.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(m) 180 416.33 T +(ust be using GNU mak) 188.23 416.33 T +(e in order to b) 288.62 416.33 T +(uild this distr) 350.12 416.33 T +(ib) 405.84 416.33 T +(ution.) 413.42 416.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.04 (Upon completion the Mak) 162 392.33 P +1.04 (e\336le will gener) 278.29 392.33 P +1.04 (ate the shared object f) 343.61 392.33 P +1.04 (or the Scr) 446.41 392.33 P +1.04 (ipt Ser) 491.98 392.33 P +1.04 (vice) 522.22 392.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.56 (and will install it into y) 162 380.33 P +0.56 (our CDEVSHOBJ director) 260.74 380.33 P +0.56 (y) 376.63 380.33 P +0.56 (. At this point y) 380.63 380.33 P +0.56 (ou are ready to use) 451.6 380.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the Scr) 162 368.33 T +(ipt Ser) 193.83 368.33 T +(vice) 223.03 368.33 T +(.) 240.66 368.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "2" 8 +%%Page: "3" 9 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Str) 391.28 739 T +(ucture of Data Pro) 412.93 739 T +(vided to the Scr) 485.83 739 T +(ipt) 548.5 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(3) 552.44 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(3.) 159.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Structure of Data Pr) 180 710.67 T +(o) 311.96 710.67 T +(vided to the Script) 320.24 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(General Form of) 72 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data String) 72 661.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.2 (When a de) 180 673.33 P +1.2 (v) 230.46 673.33 P +1.2 (eloper mak) 235.21 673.33 P +1.2 (es a CDEV send call, he ma) 285.67 673.33 P +1.2 (y pro) 417.62 673.33 P +1.2 (vide outbound data in the) 440.9 673.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.03 (f) 180 661.33 P +0.03 (or) 182.48 661.33 P +0.03 (m of a cde) 191.62 661.33 P +0.03 (vData object. Bef) 238.1 661.33 P +0.03 (ore calling the scr) 314.01 661.33 P +0.03 (ipt, this data is con) 392.61 661.33 P +0.03 (v) 475.35 661.33 P +0.03 (er) 480.1 661.33 P +0.03 (ted into a str) 489.39 661.33 P +0.03 (ing) 544.66 661.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.19 (and pro) 180 649.33 P +0.19 (vided as the third argument to the application \050the \336rst argument is the de) 213.95 649.33 P +0.19 (vice) 540.22 649.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.05 (name and the second is the message\051. The str) 180 637.33 P +0.05 (ucture of the outbound data str) 386.8 637.33 P +0.05 (ing is of) 523.43 637.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the f) 180 625.33 T +(ollo) 199.16 625.33 T +(wing f) 214.57 625.33 T +(or) 240.39 625.33 T +(m.) 249.53 625.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 1: Gener) 180 592 T +(al f) 245.44 592 T +(or) 257.17 592 T +(m of str) 265.4 592 T +(ing representation of cde) 295.54 592 T +(vData) 394.33 592 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Representation of) 72 507.14 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Scalar Data) 72 495.14 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +2.02 (The abo) 180 507.14 P +2.02 (v) 218.56 507.14 P +2.02 (e e) 223.31 507.14 P +2.02 (xample sho) 238.93 507.14 P +2.02 (ws tw) 291.93 507.14 P +2.02 (o data entr) 318.86 507.14 P +2.02 (ies of the f) 370.86 507.14 P +2.02 (or) 422.76 507.14 P +2.02 (m) 431.9 507.14 P +3 F +2.02 (tag=v) 445.04 507.14 P +2.02 (alue) 469.52 507.14 P +0 F +2.02 (. Each entr) 488.27 507.14 P +2.02 (y is) 540.98 507.14 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.12 (separ) 180 495.14 P +0.12 (ated b) 204.91 495.14 P +0.12 (y a carr) 232.63 495.14 P +0.12 (iage retur) 266.37 495.14 P +0.12 (n. The \336rst entr) 308.98 495.14 P +0.12 (y has a tag name of) 376.9 495.14 P +3 F +0.12 (\324tag1\325) 468.26 495.14 P +0 F +0.12 ( and a v) 492.15 495.14 P +0.12 (alue of) 527.86 495.14 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +2 (\324str) 180 483.14 P +2 (ing v) 193.48 483.14 P +2 (alue\325) 216.35 483.14 P +0 F +2 (. Y) 237.47 483.14 P +2 (ou will note that) 250.3 483.14 P +3 F +2 (\324str) 330.55 483.14 P +2 (ing v) 344.03 483.14 P +2 (alue\325) 366.89 483.14 P +0 F +2 ( is enclosed in doub) 388.02 483.14 P +2 (le quotes in the) 484.19 483.14 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.2 (e) 180 471.14 P +1.2 (xample) 185.26 471.14 P +1.2 (. This is used to notify the scr) 217.34 471.14 P +1.2 (ipt that the v) 355.38 471.14 P +1.2 (alue is a non-n) 413.2 471.14 P +1.2 (umer) 482.29 471.14 P +1.2 (ic char) 505.22 471.14 P +1.2 (acter) 535.77 471.14 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.26 (str) 180 459.14 P +-0.26 (ing. In the second data entr) 191.26 459.14 P +-0.26 (y the v) 311.44 459.14 P +-0.26 (alue) 340.13 459.14 P +3 F +-0.26 (\3251.0\325) 361.54 459.14 P +0 F +-0.26 (is not enclosed in quotes) 382.4 459.14 P +-0.26 (, indicating that) 491.26 459.14 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the v) 180 447.14 T +(alue is a n) 201.43 447.14 T +(umber) 246.91 447.14 T +(.) 274.75 447.14 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 (The f) 180 430.14 P +0 (ollo) 202.49 430.14 P +0 (wing e) 217.9 430.14 P +0 (xample illustr) 246.51 430.14 P +0 (ates ho) 304.76 430.14 P +0 (w scalar v) 337.41 430.14 P +0 (alues stored in a cde) 381.62 430.14 P +0 (vData object w) 473.61 430.14 P +0 (ould) 539.1 430.14 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(look when the) 180 418.14 T +(y are passed to the scr) 241.5 418.14 T +(ipt.) 342.81 418.14 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 2: Str) 180 384.81 T +(ing representation of scalar data in a cde) 232.15 384.81 T +(vData object) 394.47 384.81 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Representation of) 72 132.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Arra) 72 120.1 T +(y Data) 92.36 120.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.61 (If arr) 180 132.1 P +0.61 (a) 201.07 132.1 P +0.61 (y data is stored in the outbound cde) 206.33 132.1 P +0.61 (vData object, it too can be pro) 368.73 132.1 P +0.61 (vided to the) 505.08 132.1 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.52 (scr) 180 120.1 P +1.52 (ipt. The data is str) 193.48 120.1 P +1.52 (uctured in the standard C f) 279.2 120.1 P +1.52 (or) 404.36 120.1 P +1.52 (mat where opening and closing) 413.5 120.1 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.32 (br) 180 108.1 P +0.32 (aces mar) 188.79 108.1 P +0.32 (k the beginning and end \050respectiv) 230.38 108.1 P +0.32 (ely\051 of each arr) 384.61 108.1 P +0.32 (a) 452.17 108.1 P +0.32 (y bound. The f) 457.43 108.1 P +0.32 (ollo) 522.03 108.1 P +0.32 (wing) 537.44 108.1 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(e) 180 96.1 T +(xample illustr) 185.26 96.1 T +(ates ho) 243.5 96.1 T +(w v) 276.15 96.1 T +(ar) 290.9 96.1 T +(ious arr) 299.94 96.1 T +(a) 333.18 96.1 T +(ys w) 338.44 96.1 T +(ould be represented as str) 358.34 96.1 T +(ings) 474.66 96.1 T +(.) 492.85 96.1 T +0 0 0 1 0 0 0 K +180 532.81 558 680 C +0 0 0 1 0 0 0 K +180 549.81 558 589 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +187.43 553.41 551 585.43 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +5 9 Q +(tag1=\323string value\323) 196.43 576.14 T +(tag2=1.00) 196.43 565.14 T +180 532.81 558 680 C +0 0 612 792 C +180 157.76 558 513.81 C +180 174.76 558 381.81 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +187.43 179.79 551 378.24 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +5 9 Q +(Data stored in cdevData object:) 196.43 368.95 T +(Tag:) 226 357.95 T +(value) 247.6 357.95 T +(Data Type:) 226 346.95 T +(character string) 280 346.95 T +(Value:) 226 335.95 T +(Test) 258.4 335.95 T +(Tag:) 226 313.95 T +(status) 247.6 313.95 T +(Data Type:) 226 302.95 T +(integer) 280 302.95 T +(Value:) 226 291.95 T +(0) 258.4 291.95 T +(Tag:) 226 269.95 T +(controlHigh) 247.6 269.95 T +(Data Type:) 226 258.95 T +(double) 280 258.95 T +(Value:) 226 247.95 T +(1.001) 258.4 247.95 T +(String representation provided to script:) 196.43 225.95 T +(value=\323Test\323\134n) 226 214.95 T +(status=0\134n) 226 203.95 T +(controlHigh=1.001\134n) 226 192.95 T +180 157.76 558 513.81 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "3" 9 +%%Page: "4" 10 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Str) 54 739 T +(ucture of Data Pro) 75.64 739 T +(vided to the Scr) 148.54 739 T +(ipt) 211.21 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(4) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Figure 3: Str) 162 714 T +(ing representation of arr) 214.15 714 T +(a) 309.61 714 T +(y data) 314.34 714 T +0 0 0 1 0 0 0 K +162 81 540 720 C +0 0 0 1 0 0 0 K +162 393.95 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +169.43 397.55 533 707.43 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +5 9 Q +(Data stored in cdevData object:) 178.43 698.14 T +(Tag:) 208 687.14 T +(value) 229.6 687.14 T +(Data Type:) 208 676.14 T +(character string [3]) 262 676.14 T +(Value:) 208 665.14 T +(\322value1\323 \322value2\323 \322value3\323) 240.4 665.14 T +(String representation provided to script:) 178.43 643.14 T +(value={\323value1\323,\322value2\323,\323value3\323}\134n) 208 632.14 T +(Data stored in cdevData object:) 178.43 587.14 T +(Tag:) 208 576.14 T +(value) 229.6 576.14 T +(Data Type:) 208 565.14 T +(double [3]) 262 565.14 T +(Value:) 208 554.14 T +(1.0, 2.0, 3.01) 240.4 554.14 T +(String representation provided to script:) 178.43 532.14 T +(value={1,2,3.01}\134n) 208 521.14 T +(Data stored in cdevData object:) 178.43 476.14 T +(Tag:) 208 465.14 T +(value) 229.6 465.14 T +(Data Type:) 208 454.14 T +(double [3][2]) 262 454.14 T +(Value:) 208 443.14 T +(1.0, 2.0, 3.0, 4.0, 5.0, 6.0) 240.4 443.14 T +(String representation provided to script:) 178.43 421.14 T +(value={{1,2},{3,4},{5,6}}\134n) 208 410.14 T +172 401.14 528.43 704.14 C +172 606.14 528.43 618.14 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.43 612.14 532 612.14 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +172 401.14 528.43 704.14 C +162 393.95 540 711 C +172 401.14 528.43 704.14 C +172 495.14 528.43 507.14 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.43 501.14 532 501.14 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +172 401.14 528.43 704.14 C +162 393.95 540 711 C +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "4" 10 +%%Page: "5" 11 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. Str) 378.93 739 T +(ucture of Data Retur) 400.57 739 T +(ned from the Scr) 481.83 739 T +(ipt) 548.5 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(5) 552.44 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(4.) 159.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Structure of Data Returned fr) 180 710.67 T +(om the Script) 372.63 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Returning Data to) 72 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the Calling CDEV) 72 661.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Application) 72 649.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.17 (Bef) 180 673.33 P +0.17 (ore CDEV star) 194.71 673.33 P +0.17 (ts the scr) 259.9 673.33 P +0.17 (ipt, it creates a pipe that is used to pass data betw) 300.95 673.33 P +0.17 (een the) 524.47 673.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.03 (scr) 180 661.33 P +-0.03 (ipt and the CDEV application. One end of this pipe is maintained b) 193.48 661.33 P +-0.03 (y the application) 485.81 661.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.36 (and the other end of the pipe is pro) 180 649.33 P +1.36 (vided to the scr) 345.8 649.33 P +1.36 (ipt as its standard output. This) 417.82 649.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.16 (means that an) 180 637.33 P +0.16 (ytime the scr) 243.54 637.33 P +0.16 (ipt uses the \322echo\323 command or the \322pr) 300.7 637.33 P +0.16 (intf) 474.27 637.33 P +0.16 (\323 command, the) 488.21 637.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(data that it output\325) 180 625.33 T +(s will be tr) 259 625.33 T +(ansmitted through the pipe to the parent application.) 303.35 625.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.8 (The scr) 180 608.33 P +0.8 (ipt is responsib) 214.29 608.33 P +0.8 (le f) 282.39 608.33 P +0.8 (or f) 296.23 608.33 P +0.8 (or) 311.18 608.33 P +0.8 (matting the data into a collection of char) 320.32 608.33 P +0.8 (acter str) 502.59 608.33 P +0.8 (ings) 539.66 608.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(that can be recogniz) 180 596.33 T +(ed b) 269.9 596.33 T +(y the CDEV application.) 289.16 596.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(General Form of) 72 567.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(String Data) 72 555.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.37 (In gener) 180 567.33 P +0.37 (al, the data that is retur) 216.96 567.33 P +0.37 (ned from a scr) 321.35 567.33 P +0.37 (ipt is of the same f) 386.53 567.33 P +0.37 (or) 469.23 567.33 P +0.37 (m as descr) 478.37 567.33 P +0.37 (ibed in) 528.17 567.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.17 (the preceding section, \322) 180 555.33 P +3 F +1.17 (Str) 287.44 555.33 P +1.17 (ucture of Data Pro) 300.37 555.33 P +1.17 (vided to the Scr) 384.86 555.33 P +1.17 (ipt) 457.99 555.33 P +0 F +1.17 (\323. The most notab) 468.55 555.33 P +1.17 (le) 550.22 555.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.34 (diff) 180 543.33 P +0.34 (erence is that the scr) 193.04 543.33 P +0.34 (ipt m) 287.38 543.33 P +0.34 (ust ter) 309.3 543.33 P +0.34 (minate the list b) 337.68 543.33 P +0.34 (y pro) 408.54 543.33 P +0.34 (viding a char) 430.96 543.33 P +0.34 (acter str) 488.24 543.33 P +0.34 (ing that) 524.86 543.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.22 (indicates that the g) 180 531.33 P +0.22 (roup of data items is complete; the str) 264.5 531.33 P +0.22 (ing \322) 432.94 531.33 P +3 F +0.22 (end) 452.61 531.33 P +0 F +0.22 (\323 or \322) 469.3 531.33 P +3 F +0.22 (done) 490.85 531.33 P +0 F +0.22 (\323 alone on) 513.09 531.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(a line) 180 519.33 T +(.) 203.75 519.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Returning a) 72 490.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Single Result) 72 478.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(P) 72 466.33 T +(ac) 78.37 466.33 T +(ket) 89.29 466.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +-0.22 (If the scr) 180 490.33 P +-0.22 (ipt is going to retur) 218.06 490.33 P +-0.22 (n e) 299.68 490.33 P +-0.22 (xactly one result pac) 313.06 490.33 P +-0.22 (k) 403.34 490.33 P +-0.22 (et \050) 408.14 490.33 P +3 F +-0.22 (a g) 422.37 490.33 P +-0.22 (roup of tags and v) 435.95 490.33 P +-0.22 (alues that) 514.86 490.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.19 (will be used to populate the result cde) 180 478.33 P +0.19 (vData) 348.33 478.33 P +0 F +0.19 (\051, then it should wr) 374.45 478.33 P +0.19 (ite the str) 457.05 478.33 P +0.19 (ing \322) 498.7 478.33 P +3 F +0.19 (done) 518.34 478.33 P +0 F +0.19 (\323 on) 540.58 478.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.1 (a line b) 180 466.33 P +0.1 (y itself immediately f) 212.24 466.33 P +0.1 (ollo) 302.26 466.33 P +0.1 (wing the output data. This will notify the Scr) 317.67 466.33 P +0.1 (ipt Ser) 510.92 466.33 P +0.1 (vice) 540.22 466.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(that no more data will be retur) 180 454.33 T +(ned from the scr) 312.53 454.33 T +(ipt.) 384.93 454.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.53 (The f) 180 437.33 P +0.53 (ollo) 203.02 437.33 P +0.53 (wing e) 218.43 437.33 P +0.53 (xample sho) 247.56 437.33 P +0.53 (ws ho) 299.07 437.33 P +0.53 (w a single result will be retur) 325.57 437.33 P +0.53 (ned from a scr) 454.58 437.33 P +0.53 (ipt. Note) 520.23 437.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.78 (that the \322status\323 tag contains the completion code that will be retur) 180 425.33 P +0.78 (ned to the CDEV) 480.62 425.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(application.) 180 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 4: Retur) 180 397 T +(ning a single result pac) 242.75 397 T +(k) 334.61 397 T +(et to the CDEV application) 338.93 397 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Returning) 72 273.43 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Multiple Result) 72 261.43 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(P) 72 249.43 T +(ac) 78.37 249.43 T +(kets) 89.29 249.43 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +2.12 (Retur) 180 273.43 P +2.12 (ning m) 204.7 273.43 P +2.12 (ultiple results from a single scr) 236.73 273.43 P +2.12 (ipt e) 381.93 273.43 P +2.12 (x) 402.65 273.43 P +2.12 (ecution is not gener) 407.35 273.43 P +2.12 (ally advised.) 500.86 273.43 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.07 (Ho) 180 261.43 P +-0.07 (w) 192.63 261.43 P +-0.07 (e) 199.75 261.43 P +-0.07 (v) 205.01 261.43 P +-0.07 (er) 209.76 261.43 P +-0.07 (, If the scr) 218.15 261.43 P +-0.07 (ipt is going to retur) 262.01 261.43 P +-0.07 (n more than one result pac) 344.24 261.43 P +-0.07 (k) 462.65 261.43 P +-0.07 (et, then each inter) 467.45 261.43 P +-0.07 (im) 547.45 261.43 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.85 (pac) 180 249.43 P +1.85 (k) 195.92 249.43 P +1.85 (et should be ter) 200.72 249.43 P +1.85 (minated b) 275.44 249.43 P +1.85 (y the \322) 321 249.43 P +3 F +1.85 (end) 352.48 249.43 P +0 F +1.85 (\323 k) 369.16 249.43 P +1.85 (e) 381.92 249.43 P +1.85 (yw) 387.27 249.43 P +1.85 (ord on a line b) 399.39 249.43 P +1.85 (y itself) 469.95 249.43 P +1.85 (. The \322) 499.84 249.43 P +3 F +1.85 (done) 532.43 249.43 P +0 F +1.85 (\323) 554.67 249.43 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(k) 180 237.43 T +(e) 184.8 237.43 T +(yw) 190.16 237.43 T +(ord should f) 202.28 237.43 T +(ollo) 254.23 237.43 T +(w the last entr) 269.64 237.43 T +(y) 332.19 237.43 T +(.) 336.19 237.43 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The f) 180 220.43 T +(ollo) 202.49 220.43 T +(wing e) 217.9 220.43 T +(xample sho) 246.5 220.43 T +(ws ho) 297.48 220.43 T +(w tw) 323.45 220.43 T +(o results will be retur) 343.35 220.43 T +(ned from a scr) 435.29 220.43 T +(ipt.) 499.35 220.43 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 5: Retur) 180 204.1 T +(ning a m) 242.75 204.1 T +(ultiple result pac) 277.17 204.1 T +(k) 342.02 204.1 T +(ets to the CDEV application) 346.34 204.1 T +0 0 0 1 0 0 0 K +180 299.1 558 497 C +0 0 0 1 0 0 0 K +180 299.1 558 394 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +187.43 302.69 551 390.43 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +5 9 Q +(#\134! /bin/csh -f) 196.43 381.14 T +(echo value=\134\323Test\134\323) 196.43 359.14 T +(echo status=0) 196.43 348.14 T +(echo controlLow=1.5) 196.43 337.14 T +(echo controlHigh=25.1) 196.43 326.14 T +(echo done) 196.43 315.14 T +180 299.1 558 497 C +0 0 612 792 C +180 81 558 280.1 C +180 84.76 558 201.1 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +187.43 89.07 551 197.53 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +5 9 Q +(#\134! /bin/csh -f) 196.43 188.24 T +(echo value=\134\323Start Result 1\134\323) 196.43 166.24 T +(echo status=0) 196.43 155.24 T +(echo end) 196.43 144.24 T +(echo value=\134\323Start Result 2\134\323) 196.43 133.24 T +(echo status=-1) 196.43 122.24 T +(echo done) 196.43 111.24 T +180 81 558 280.1 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "5" 11 +%%Page: "6" 12 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. Str) 54 739 T +(ucture of Data Retur) 75.64 739 T +(ned from the Scr) 156.91 739 T +(ipt) 223.57 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(6) 54 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 41.83 T +(vision: 1) 506.99 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Special) 54 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Considerations) 54 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.76 (If the scr) 162 713.33 P +0.76 (ipt that is being e) 202.01 713.33 P +0.76 (x) 280.34 713.33 P +0.76 (ecuted will not retur) 285.04 713.33 P +0.76 (n a result, then the de) 374.25 713.33 P +0.76 (v) 474.46 713.33 P +0.76 (eloper should) 479.21 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.55 (still wr) 162 701.33 P +0.55 (ite \322) 190.47 701.33 P +3 F +0.55 (done\323) 207.69 701.33 P +0 F +0.55 ( to the standard output in order to notify the CDEV application that it) 233.26 701.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.41 (should no longer w) 162 689.33 P +0.41 (ait f) 247 689.33 P +0.41 (or output. If the scr) 263.23 689.33 P +0.41 (ipt is not retur) 348.39 689.33 P +0.41 (ning a result, it ma) 410.44 689.33 P +0.41 (y wr) 493.46 689.33 P +0.41 (ite the) 512.35 689.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.4 (ter) 162 677.33 P +0.4 (minating) 173.92 677.33 P +3 F +0.4 (\322done\323) 214.89 677.33 P +0 F +0.4 ( at the beginning of the scr) 243.79 677.33 P +0.4 (ipt or at the end. Because synchronous) 364.18 677.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.4 (calls will b) 162 665.33 P +1.4 (loc) 209.6 665.33 P +1.4 (k until a reply is receiv) 222.18 665.33 P +1.4 (ed, the de) 327.3 665.33 P +1.4 (v) 374.29 665.33 P +1.4 (eloper should retur) 379.04 665.33 P +1.4 (n a result to the) 465.46 665.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV application as quic) 162 653.33 T +(kly as possib) 274.62 653.33 T +(le) 331.66 653.33 T +(.) 339.29 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.51 (If the de) 162 636.33 P +0.51 (v) 198.87 636.33 P +0.51 (eloper ne) 203.62 636.33 P +0.51 (v) 245.52 636.33 P +0.51 (er wr) 250.27 636.33 P +0.51 (ites an) 273.15 636.33 P +0.51 (ything to the standard output, then the user speci\336ed) 302.98 636.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.76 (CDEV callbac) 162 624.33 P +1.76 (k will ne) 225.24 624.33 P +1.76 (v) 264.01 624.33 P +1.76 (er be e) 268.76 624.33 P +1.76 (x) 303.11 624.33 P +1.76 (ecuted... theref) 307.81 624.33 P +1.76 (ore) 375.98 624.33 P +1.76 (, it is cr) 390.28 624.33 P +1.76 (ucial to notify the CDEV) 427.37 624.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(application when the scr) 162 612.33 T +(ipt has completed.) 269.42 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "6" 12 +%%Page: "7" 13 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. DDL Entr) 413.18 739 T +(ies f) 460.33 739 T +(or the Scr) 476.57 739 T +(ipt Ser) 515.72 739 T +(vice) 542 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(7) 552.44 41.83 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(5.) 159.32 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(DDL Entries f) 180 710.67 T +(or the Script Ser) 268.4 710.67 T +(vice) 377.46 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Setting Up the) 72 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(DDL) 72 661.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +1.82 (The f) 180 673.33 P +1.82 (ollo) 204.31 673.33 P +1.82 (wing e) 219.72 673.33 P +1.82 (xample illustr) 250.14 673.33 P +1.82 (ates ho) 310.2 673.33 P +1.82 (w to add a ser) 344.67 673.33 P +1.82 (vice entr) 415.06 673.33 P +1.82 (y to identify the Scr) 454.97 673.33 P +1.82 (ipt) 547.44 673.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.2 (Ser) 180 661.33 P +-0.2 (vice and ho) 195.86 661.33 P +-0.2 (w to use the ser) 246.44 661.33 P +-0.2 (vice data to specify the \336lename that the Scr) 316.51 661.33 P +-0.2 (ipt Ser) 511.23 661.33 P +-0.2 (vice) 540.22 661.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(will e) 180 649.33 T +(x) 201.92 649.33 T +(ecute to ser) 206.62 649.33 T +(vice a message) 259.17 649.33 T +(.) 328.49 649.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 6: Simple DDL \336le f) 180 633 T +(or the Scr) 287.26 633 T +(ipt Ser) 326.41 633 T +(vice) 352.69 633 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +180 81 558 680 C +0 0 0 1 0 0 0 K +180 232.95 558 630 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +187.43 237.97 551 626.43 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +5 9 Q +(/*) 196.43 617.14 T +( * This is the service definition, it tells CDEV that there is) 196.43 606.14 T +( * a service named Script and that it will use the cdevData) 196.43 595.14 T +( * tag \324filename\325 to read configuration information from the) 196.43 584.14 T +( * DDL file entries.) 196.43 573.14 T +( */) 196.43 562.14 T +(service Script) 196.43 551.14 T +({) 208 540.14 T +(tags {filename}) 208 529.14 T +(}) 208 518.14 T +(/*) 196.43 496.14 T +( * This class definition identifies the class scriptClass which) 196.43 485.14 T +( * supports the \322get and \322set\323 commands on attributes \322attrib0\323) 196.43 474.14 T +( * and \322attrib1\323. Note that attrib0 will call script /bin/ouch) 196.43 463.14 T +( * and attrib1 will call script /bin/wammo.) 196.43 452.14 T +( */) 196.43 441.14 T +(class scriptClass) 196.43 430.14 T +({) 208 419.14 T +(verbs {get, set}) 218.03 408.14 T +(attributes) 208 397.14 T +({) 226 386.14 T +(attrib0 Script {filename = /bin/ouch};) 226 375.14 T +(attrib1 Script {filename = /bin/wammo};) 228.83 364.14 T +(}) 226 353.14 T +(}) 196.43 342.14 T +(/*) 196.43 320.14 T +( * Finally, the CDEV DDL identifies two devices that are of type) 196.43 309.14 T +-0.08 ( * scriptClass. Any time one of the supported messages is passed) 196.43 298.14 P +( * to one of these devices it will activate the corresponding) 196.43 287.14 T +( * script.) 196.43 276.14 T +( */) 196.43 265.14 T +(scriptClass : device0, device1;) 196.43 254.14 T +180 81 558 680 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "7" 13 +%%Trailer +%%BoundingBox: 0 0 612 792 +%%PageOrder: Ascend +%%Pages: 13 +%%DocumentFonts: Helvetica +%%+ Times-BoldItalic +%%+ Helvetica-Bold +%%+ Helvetica-Oblique +%%+ Helvetica-BoldOblique +%%+ Courier-BoldOblique +%%EOF diff --git a/doc/ps/cdevServiceGuide.ps b/doc/ps/cdevServiceGuide.ps new file mode 100755 index 0000000..62e7004 --- /dev/null +++ b/doc/ps/cdevServiceGuide.ps @@ -0,0 +1,14152 @@ +%!PS-Adobe-3.0 +%%BoundingBox: (atend) +%%Pages: (atend) +%%PageOrder: (atend) +%%DocumentFonts: (atend) +%%Creator: Frame 5.0 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +% +% Frame ps_prolog 5.0, for use with Frame 5.0 products +% This ps_prolog file is Copyright (c) 1986-1995 Frame Technology +% Corporation. All rights reserved. This ps_prolog file may be +% freely copied and distributed in conjunction with documents created +% using FrameMaker, FrameMaker/SGML and FrameViewer as long as this +% copyright notice is preserved. +% +% FrameMaker users specify the proper paper size for each print job in the +% "Print" dialog's "Printer Paper Size" "Width" and "Height~ fields. If the +% printer that the PS file is sent to does not support the requested paper +% size, or if there is no paper tray of the proper size currently installed, +% then the job will not be printed. The following flag, if set to true, will +% cause the job to print on the default paper in such cases. +/FMAllowPaperSizeMismatch false def +% +% Frame products normally print colors as their true color on a color printer +% or as shades of gray, based on luminance, on a black-and white printer. The +% following flag, if set to true, forces all non-white colors to print as pure +% black. This has no effect on bitmap images. +/FMPrintAllColorsAsBlack false def +% +% Frame products can either set their own line screens or use a printer's +% default settings. Three flags below control this separately for no +% separations, spot separations and process separations. If a flag +% is true, then the default printer settings will not be changed. If it is +% false, Frame products will use their own settings from a table based on +% the printer's resolution. +/FMUseDefaultNoSeparationScreen true def +/FMUseDefaultSpotSeparationScreen true def +/FMUseDefaultProcessSeparationScreen false def +% +% For any given PostScript printer resolution, Frame products have two sets of +% screen angles and frequencies for printing process separations, which are +% recomended by Adobe. The following variable chooses the higher frequencies +% when set to true or the lower frequencies when set to false. This is only +% effective if the appropriate FMUseDefault...SeparationScreen flag is false. +/FMUseHighFrequencyScreens true def +% +% The following is a set of predefined optimal frequencies and angles for various +% common dpi settings. This is taken from "Advances in Color Separation Using +% PostScript Software Technology," from Adobe Systems (3/13/89 P.N. LPS 0043) +% and corrolated with information which is in various PPD (4.0) files. +% +% The "dpiranges" figure is the minimum dots per inch device resolution which +% can support this setting. The "low" and "high" values are controlled by the +% setting of the FMUseHighFrequencyScreens flag above. The "TDot" flags control +% the use of the "Yellow Triple Dot" feature whereby the frequency id divided by +% three, but the dot function is "trippled" giving a block of 3x3 dots per cell. +% +% PatFreq is a compromise pattern frequency for ps Level 2 printers which is close +% to the ideal WYSIWYG pattern frequency of 9 repetitions/inch but does not beat +% (too badly) against the screen frequencies of any separations for that DPI. +/dpiranges [ 2540 2400 1693 1270 1200 635 600 0 ] def +/CMLowFreqs [ 100.402 94.8683 89.2289 100.402 94.8683 66.9349 63.2456 47.4342 ] def +/YLowFreqs [ 95.25 90.0 84.65 95.25 90.0 70.5556 66.6667 50.0 ] def +/KLowFreqs [ 89.8026 84.8528 79.8088 89.8026 84.8528 74.8355 70.7107 53.033 ] def +/CLowAngles [ 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 ] def +/MLowAngles [ 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 ] def +/YLowTDot [ true true false true true false false false ] def +/CMHighFreqs [ 133.87 126.491 133.843 108.503 102.523 100.402 94.8683 63.2456 ] def +/YHighFreqs [ 127.0 120.0 126.975 115.455 109.091 95.25 90.0 60.0 ] def +/KHighFreqs [ 119.737 113.137 119.713 128.289 121.218 89.8026 84.8528 63.6395 ] def +/CHighAngles [ 71.5651 71.5651 71.5651 70.0169 70.0169 71.5651 71.5651 71.5651 ] def +/MHighAngles [ 18.4349 18.4349 18.4349 19.9831 19.9831 18.4349 18.4349 18.4349 ] def +/YHighTDot [ false false true false false true true false ] def +/PatFreq [ 10.5833 10.0 9.4055 10.5833 10.0 10.5833 10.0 9.375 ] def +% +% PostScript Level 2 printers contain an "Accurate Screens" feature which can +% improve process separation rendering at the expense of compute time. This +% flag is ignored by PostScript Level 1 printers. +/FMUseAcccurateScreens true def +% +% The following PostScript procedure defines the spot function that Frame +% products will use for process separations. You may un-comment-out one of +% the alternative functions below, or use your own. +% +% Dot function +/FMSpotFunction {abs exch abs 2 copy add 1 gt + {1 sub dup mul exch 1 sub dup mul add 1 sub } + {dup mul exch dup mul add 1 exch sub }ifelse } def +% +% Line function +% /FMSpotFunction { pop } def +% +% Elipse function +% /FMSpotFunction { dup 5 mul 8 div mul exch dup mul exch add +% sqrt 1 exch sub } def +% +% +/FMversion (5.0) def +/fMLevel1 /languagelevel where {pop languagelevel} {1} ifelse 2 lt def +/FMPColor + fMLevel1 { + false + /colorimage where {pop pop true} if + } { + true + } ifelse +def +/FrameDict 400 dict def +systemdict /errordict known not {/errordict 10 dict def + errordict /rangecheck {stop} put} if +% The readline in PS 23.0 doesn't recognize cr's as nl's on AppleTalk +FrameDict /tmprangecheck errordict /rangecheck get put +errordict /rangecheck {FrameDict /bug true put} put +FrameDict /bug false put +mark +% Some PS machines read past the CR, so keep the following 3 lines together! +currentfile 5 string readline +00 +0000000000 +cleartomark +errordict /rangecheck FrameDict /tmprangecheck get put +FrameDict /bug get { + /readline { + /gstring exch def + /gfile exch def + /gindex 0 def + { + gfile read pop + dup 10 eq {exit} if + dup 13 eq {exit} if + gstring exch gindex exch put + /gindex gindex 1 add def + } loop + pop + gstring 0 gindex getinterval true + } bind def + } if +/FMshowpage /showpage load def +/FMquit /quit load def +/FMFAILURE { + dup = flush + FMshowpage + /Helvetica findfont 12 scalefont setfont + 72 200 moveto show + 72 220 moveto show + FMshowpage + FMquit + } def +/FMVERSION { + FMversion ne { + (Frame product version does not match ps_prolog! Check installation;) + (also check ~/fminit and ./fminit for old versions) FMFAILURE + } if + } def +/FMBADEPSF { + (Adobe's PostScript Language Reference Manual, 2nd Edition, section H.2.4) + (says your EPS file is not valid, as it calls X ) + dup dup (X) search pop exch pop exch pop length + 5 -1 roll + putinterval + FMFAILURE + } def +/fmConcatProcs + { + /proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def + newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx +}def +FrameDict begin [ + /ALDsave + /FMdicttop + /FMoptop + /FMpointsize + /FMsaveobject + /b + /bitmapsave + /blut + /bpside + /bs + /bstring + /bwidth + /c + /cf + /cs + /cynu + /depth + /edown + /fh + /fillvals + /fw + /fx + /fy + /g + /gfile + /gindex + /grnt + /gryt + /gstring + /height + /hh + /i + /im + /indx + /is + /k + /kk + /landscape + /lb + /len + /llx + /lly + /m + /magu + /manualfeed + /n + /offbits + /onbits + /organgle + /orgbangle + /orgbfreq + /orgbproc + /orgbxfer + /orgfreq + /orggangle + /orggfreq + /orggproc + /orggxfer + /orgmatrix + /orgproc + /orgrangle + /orgrfreq + /orgrproc + /orgrxfer + /orgxfer + /pagesave + /paperheight + /papersizedict + /paperwidth + /pos + /pwid + /r + /rad + /redt + /sl + /str + /tran + /u + /urx + /ury + /val + /width + /width + /ws + /ww + /x + /x1 + /x2 + /xindex + /xpoint + /xscale + /xx + /y + /y1 + /y2 + /yelu + /yindex + /ypoint + /yscale + /yy +] { 0 def } forall +/FmBD {bind def} bind def +systemdict /pdfmark known { + /fMAcrobat true def + + /FmPD /pdfmark load def + + + /FmPT /show load def + + + currentdistillerparams /CoreDistVersion get 2000 ge { + + + /FmPD2 /pdfmark load def + + + + + + /FmPA { mark exch /Dest exch 5 3 roll + /View [ /XYZ null 6 -2 roll FmDC exch pop null] /DEST FmPD + }FmBD + } { + + /FmPD2 /cleartomark load def + /FmPA {pop pop pop}FmBD + } ifelse +} { + + /fMAcrobat false def + /FmPD /cleartomark load def + /FmPD2 /cleartomark load def + /FmPT /pop load def + /FmPA {pop pop pop}FmBD +} ifelse +/FmDC { + transform fMDefaultMatrix itransform cvi exch cvi exch +}FmBD +/FmBx { + dup 3 index lt {3 1 roll exch} if + 1 index 4 index lt {4 -1 roll 3 1 roll exch 4 1 roll} if +}FmBD +/FMnone 0 def +/FMcyan 1 def +/FMmagenta 2 def +/FMyellow 3 def +/FMblack 4 def +/FMcustom 5 def +/fMNegative false def +/FrameSepIs FMnone def +/FrameSepBlack 0 def +/FrameSepYellow 0 def +/FrameSepMagenta 0 def +/FrameSepCyan 0 def +/FrameSepRed 1 def +/FrameSepGreen 1 def +/FrameSepBlue 1 def +/FrameCurGray 1 def +/FrameCurPat null def +/FrameCurColors [ 0 0 0 1 0 0 0 ] def +/FrameColorEpsilon .001 def +/eqepsilon { + sub dup 0 lt {neg} if + FrameColorEpsilon le +} bind def +/FrameCmpColorsCMYK { + 2 copy 0 get exch 0 get eqepsilon { + 2 copy 1 get exch 1 get eqepsilon { + 2 copy 2 get exch 2 get eqepsilon { + 3 get exch 3 get eqepsilon + } {pop pop false} ifelse + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/FrameCmpColorsRGB { + 2 copy 4 get exch 0 get eqepsilon { + 2 copy 5 get exch 1 get eqepsilon { + 6 get exch 2 get eqepsilon + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/RGBtoCMYK { + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 3 copy + 2 copy + le { pop } { exch pop } ifelse + 2 copy + le { pop } { exch pop } ifelse + dup dup dup + 6 1 roll + 4 1 roll + 7 1 roll + sub + 6 1 roll + sub + 5 1 roll + sub + 4 1 roll +} bind def +/CMYKtoRGB { + dup dup 4 -1 roll add + 5 1 roll 3 -1 roll add + 4 1 roll add + 1 exch sub dup 0 lt {pop 0} if 3 1 roll + 1 exch sub dup 0 lt {pop 0} if exch + 1 exch sub dup 0 lt {pop 0} if exch +} bind def +/FrameSepInit { + 1.0 RealSetgray +} bind def +/FrameSetSepColor { + /FrameSepBlue exch def + /FrameSepGreen exch def + /FrameSepRed exch def + /FrameSepBlack exch def + /FrameSepYellow exch def + /FrameSepMagenta exch def + /FrameSepCyan exch def + /FrameSepIs FMcustom def + setCurrentScreen +} bind def +/FrameSetCyan { + /FrameSepBlue 1.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 1.0 def + /FrameSepIs FMcyan def + setCurrentScreen +} bind def + +/FrameSetMagenta { + /FrameSepBlue 1.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 1.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMmagenta def + setCurrentScreen +} bind def + +/FrameSetYellow { + /FrameSepBlue 0.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 1.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMyellow def + setCurrentScreen +} bind def + +/FrameSetBlack { + /FrameSepBlue 0.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 1.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMblack def + setCurrentScreen +} bind def + +/FrameNoSep { + /FrameSepIs FMnone def + setCurrentScreen +} bind def +/FrameSetSepColors { + FrameDict begin + [ exch 1 add 1 roll ] + /FrameSepColors + exch def end + } bind def +/FrameColorInSepListCMYK { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsCMYK + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/FrameColorInSepListRGB { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsRGB + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/RealSetgray /setgray load def +/RealSetrgbcolor /setrgbcolor load def +/RealSethsbcolor /sethsbcolor load def +end +/setgray { + FrameDict begin + FrameSepIs FMnone eq + { RealSetgray } + { + FrameSepIs FMblack eq + { RealSetgray } + { FrameSepIs FMcustom eq + FrameSepRed 0 eq and + FrameSepGreen 0 eq and + FrameSepBlue 0 eq and { + RealSetgray + } { + 1 RealSetgray pop + } ifelse + } ifelse + } ifelse + end +} bind def +/setrgbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetrgbcolor } + { + 3 copy [ 4 1 roll ] + FrameColorInSepListRGB + { + FrameSepBlue eq exch + FrameSepGreen eq and exch + FrameSepRed eq and + { 0 } { 1 } ifelse + } + { + FMPColor { + RealSetrgbcolor + currentcmykcolor + } { + RGBtoCMYK + } ifelse + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end +} bind def +/sethsbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSethsbcolor } + { + RealSethsbcolor + currentrgbcolor + setrgbcolor + } + ifelse + end +} bind def +FrameDict begin +/setcmykcolor where { + pop /RealSetcmykcolor /setcmykcolor load def +} { + /RealSetcmykcolor { + 4 1 roll + 3 { 3 index add 0 max 1 min 1 exch sub 3 1 roll} repeat + RealSetrgbcolor pop + } bind def +} ifelse +userdict /setcmykcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetcmykcolor } + { + 4 copy [ 5 1 roll ] + FrameColorInSepListCMYK + { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + { 0 } { 1 } ifelse + } + { + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end + } bind put +fMLevel1 { + + + + /patScreenDict 7 dict dup begin + <0f1e3c78f0e1c387> [ 45 { pop } {exch pop} .5 2 sqrt] FmBD + <0f87c3e1f0783c1e> [ 135 { pop } {exch pop} .5 2 sqrt] FmBD + [ 0 { pop } dup .5 2 ] FmBD + [ 90 { pop } dup .5 2 ] FmBD + <8142241818244281> [ 45 { 2 copy lt {exch} if pop} dup .75 2 sqrt] FmBD + <03060c183060c081> [ 45 { pop } {exch pop} .875 2 sqrt] FmBD + <8040201008040201> [ 135 { pop } {exch pop} .875 2 sqrt] FmBD + end def +} { + + /patProcDict 5 dict dup begin + <0f1e3c78f0e1c387> { 3 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <0f87c3e1f0783c1e> { 3 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + <8142241818244281> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -1 -1 moveto 9 9 lineto stroke } bind def + <03060c183060c081> { 1 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <8040201008040201> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + end def + /patDict 15 dict dup begin + /PatternType 1 def + /PaintType 2 def + /TilingType 3 def + /BBox [ 0 0 8 8 ] def + /XStep 8 def + /YStep 8 def + /PaintProc { + begin + patProcDict bstring known { + patProcDict bstring get exec + } { + 8 8 true [1 0 0 -1 0 8] bstring imagemask + } ifelse + end + } bind def + end def +} ifelse +/combineColor { + FrameSepIs FMnone eq + { + graymode fMLevel1 or not { + + [/Pattern [/DeviceCMYK]] setcolorspace + FrameCurColors 0 4 getinterval aload pop FrameCurPat setcolor + } { + FrameCurColors 3 get 1.0 ge { + FrameCurGray RealSetgray + } { + fMAcrobat not FMPColor graymode and and { + 0 1 3 { + FrameCurColors exch get + 1 FrameCurGray sub mul + } for + RealSetcmykcolor + } { + 4 1 6 { + FrameCurColors exch get + graymode { + 1 exch sub 1 FrameCurGray sub mul 1 exch sub + } { + 1.0 lt {FrameCurGray} {1} ifelse + } ifelse + } for + RealSetrgbcolor + } ifelse + } ifelse + } ifelse + } { + FrameCurColors 0 4 getinterval aload + FrameColorInSepListCMYK { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + FrameSepIs FMcustom eq and + { FrameCurGray } { 1 } ifelse + } { + FrameSepIs FMblack eq + {FrameCurGray 1.0 exch sub mul 1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop FrameCurGray 1.0 exch sub mul 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + graymode fMLevel1 or not { + + [/Pattern [/DeviceGray]] setcolorspace + FrameCurPat setcolor + } { + graymode not fMLevel1 and { + + dup 1 lt {pop FrameCurGray} if + } if + RealSetgray + } ifelse + } ifelse +} bind def +/savematrix { + orgmatrix currentmatrix pop + } bind def +/restorematrix { + orgmatrix setmatrix + } bind def +/fMDefaultMatrix matrix defaultmatrix def +/fMatrix2 matrix def +/dpi 72 0 fMDefaultMatrix dtransform + dup mul exch dup mul add sqrt def + +/freq dpi dup 72 div round dup 0 eq {pop 1} if 8 mul div def +/sangle 1 0 fMDefaultMatrix dtransform exch atan def + sangle fMatrix2 rotate + fMDefaultMatrix fMatrix2 concatmatrix + dup 0 get /sflipx exch def + 3 get /sflipy exch def +/screenIndex { + 0 1 dpiranges length 1 sub { dup dpiranges exch get 1 sub dpi le {exit} {pop} ifelse } for +} bind def +/getCyanScreen { + FMUseHighFrequencyScreens { CHighAngles CMHighFreqs} {CLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getMagentaScreen { + FMUseHighFrequencyScreens { MHighAngles CMHighFreqs } {MLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getYellowScreen { + FMUseHighFrequencyScreens { YHighTDot YHighFreqs} { YLowTDot YLowFreqs } ifelse + screenIndex dup 3 1 roll get 3 1 roll get { 3 div + {2 { 1 add 2 div 3 mul dup floor sub 2 mul 1 sub exch} repeat + FMSpotFunction } } {/FMSpotFunction load } ifelse + 0.0 exch +} bind def +/getBlackScreen { + FMUseHighFrequencyScreens { KHighFreqs } { KLowFreqs } ifelse + screenIndex get 45.0 /FMSpotFunction load +} bind def +/getSpotScreen { + getBlackScreen +} bind def +/getCompositeScreen { + getBlackScreen +} bind def +/FMSetScreen + fMLevel1 { /setscreen load + }{ { + 8 dict begin + /HalftoneType 1 def + /SpotFunction exch def + /Angle exch def + /Frequency exch def + /AccurateScreens FMUseAcccurateScreens def + currentdict end sethalftone + } bind } ifelse +def +/setDefaultScreen { + FMPColor { + orgrxfer cvx orggxfer cvx orgbxfer cvx orgxfer cvx setcolortransfer + } + { + orgxfer cvx settransfer + } ifelse + orgfreq organgle orgproc cvx setscreen +} bind def +/setCurrentScreen { + FrameSepIs FMnone eq { + FMUseDefaultNoSeparationScreen { + setDefaultScreen + } { + getCompositeScreen FMSetScreen + } ifelse + } { + FrameSepIs FMcustom eq { + FMUseDefaultSpotSeparationScreen { + setDefaultScreen + } { + getSpotScreen FMSetScreen + } ifelse + } { + FMUseDefaultProcessSeparationScreen { + setDefaultScreen + } { + FrameSepIs FMcyan eq { + getCyanScreen FMSetScreen + } { + FrameSepIs FMmagenta eq { + getMagentaScreen FMSetScreen + } { + FrameSepIs FMyellow eq { + getYellowScreen FMSetScreen + } { + getBlackScreen FMSetScreen + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse +} bind def +end + +/FMDOCUMENT { + array /FMfonts exch def + /#copies exch def + FrameDict begin + 0 ne /manualfeed exch def + /paperheight exch def + /paperwidth exch def + 0 ne /fMNegative exch def + 0 ne /edown exch def + /yscale exch def + /xscale exch def + fMLevel1 { + manualfeed {setmanualfeed} if + /FMdicttop countdictstack 1 add def + /FMoptop count def + setpapername + manualfeed {true} {papersize} ifelse + {manualpapersize} {false} ifelse + {desperatepapersize} {false} ifelse + {papersizefailure} if + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + } + {2 dict + dup /PageSize [paperwidth paperheight] put + manualfeed {dup /ManualFeed manualfeed put} if + {setpagedevice} stopped {papersizefailure} if + } + ifelse + + FMPColor { + currentcolorscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + cvlit /orgbproc exch def + /orgbangle exch def + /orgbfreq exch def + cvlit /orggproc exch def + /orggangle exch def + /orggfreq exch def + cvlit /orgrproc exch def + /orgrangle exch def + /orgrfreq exch def + currentcolortransfer + fMNegative { + 1 1 4 { + pop { 1 exch sub } fmConcatProcs 4 1 roll + } for + 4 copy + setcolortransfer + } if + cvlit /orgxfer exch def + cvlit /orgbxfer exch def + cvlit /orggxfer exch def + cvlit /orgrxfer exch def + } { + currentscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + + currenttransfer + fMNegative { + { 1 exch sub } fmConcatProcs + dup settransfer + } if + cvlit /orgxfer exch def + } ifelse + end +} def +/FMBEGINPAGE { + FrameDict begin + /pagesave save def + 3.86 setmiterlimit + /landscape exch 0 ne def + landscape { + 90 rotate 0 exch dup /pwid exch def neg translate pop + }{ + pop /pwid exch def + } ifelse + edown { [-1 0 0 1 pwid 0] concat } if + 0 0 moveto paperwidth 0 lineto paperwidth paperheight lineto + 0 paperheight lineto 0 0 lineto 1 setgray fill + xscale yscale scale + /orgmatrix matrix def + gsave +} def +/FMENDPAGE { + grestore + pagesave restore + end + showpage + } def +/FMFONTDEFINE { + FrameDict begin + findfont + ReEncode + 1 index exch + definefont + FMfonts 3 1 roll + put + end + } def +/FMFILLS { + FrameDict begin dup + array /fillvals exch def + dict /patCache exch def + end + } def +/FMFILL { + FrameDict begin + fillvals 3 1 roll put + end + } def +/FMNORMALIZEGRAPHICS { + newpath + 1 setlinewidth + 0 setlinecap + 0 0 0 sethsbcolor + 0 setgray + } bind def +/FMBEGINEPSF { + end + /FMEPSF save def + /showpage {} def +% See Adobe's "PostScript Language Reference Manual, 2nd Edition", page 714. +% "...the following operators MUST NOT be used in an EPS file:" (emphasis ours) + /banddevice {(banddevice) FMBADEPSF} def + /clear {(clear) FMBADEPSF} def + /cleardictstack {(cleardictstack) FMBADEPSF} def + /copypage {(copypage) FMBADEPSF} def + /erasepage {(erasepage) FMBADEPSF} def + /exitserver {(exitserver) FMBADEPSF} def + /framedevice {(framedevice) FMBADEPSF} def + /grestoreall {(grestoreall) FMBADEPSF} def + /initclip {(initclip) FMBADEPSF} def + /initgraphics {(initgraphics) FMBADEPSF} def + /quit {(quit) FMBADEPSF} def + /renderbands {(renderbands) FMBADEPSF} def + /setglobal {(setglobal) FMBADEPSF} def + /setpagedevice {(setpagedevice) FMBADEPSF} def + /setshared {(setshared) FMBADEPSF} def + /startjob {(startjob) FMBADEPSF} def + /lettertray {(lettertray) FMBADEPSF} def + /letter {(letter) FMBADEPSF} def + /lettersmall {(lettersmall) FMBADEPSF} def + /11x17tray {(11x17tray) FMBADEPSF} def + /11x17 {(11x17) FMBADEPSF} def + /ledgertray {(ledgertray) FMBADEPSF} def + /ledger {(ledger) FMBADEPSF} def + /legaltray {(legaltray) FMBADEPSF} def + /legal {(legal) FMBADEPSF} def + /statementtray {(statementtray) FMBADEPSF} def + /statement {(statement) FMBADEPSF} def + /executivetray {(executivetray) FMBADEPSF} def + /executive {(executive) FMBADEPSF} def + /a3tray {(a3tray) FMBADEPSF} def + /a3 {(a3) FMBADEPSF} def + /a4tray {(a4tray) FMBADEPSF} def + /a4 {(a4) FMBADEPSF} def + /a4small {(a4small) FMBADEPSF} def + /b4tray {(b4tray) FMBADEPSF} def + /b4 {(b4) FMBADEPSF} def + /b5tray {(b5tray) FMBADEPSF} def + /b5 {(b5) FMBADEPSF} def + FMNORMALIZEGRAPHICS + [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall + fx fw 2 div add fy fh 2 div add translate + rotate + fw 2 div neg fh 2 div neg translate + fw urx llx sub div fh ury lly sub div scale + llx neg lly neg translate + /FMdicttop countdictstack 1 add def + /FMoptop count def + } bind def +/FMENDEPSF { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMEPSF restore + FrameDict begin + } bind def +FrameDict begin +/setmanualfeed { +%%BeginFeature *ManualFeed True + statusdict /manualfeed true put +%%EndFeature + } bind def +/max {2 copy lt {exch} if pop} bind def +/min {2 copy gt {exch} if pop} bind def +/inch {72 mul} def +/pagedimen { + paperheight sub abs 16 lt exch + paperwidth sub abs 16 lt and + {/papername exch def} {pop} ifelse + } bind def +/setpapername { + /papersizedict 14 dict def + papersizedict begin + /papername /unknown def + /Letter 8.5 inch 11.0 inch pagedimen + /LetterSmall 7.68 inch 10.16 inch pagedimen + /Tabloid 11.0 inch 17.0 inch pagedimen + /Ledger 17.0 inch 11.0 inch pagedimen + /Legal 8.5 inch 14.0 inch pagedimen + /Statement 5.5 inch 8.5 inch pagedimen + /Executive 7.5 inch 10.0 inch pagedimen + /A3 11.69 inch 16.5 inch pagedimen + /A4 8.26 inch 11.69 inch pagedimen + /A4Small 7.47 inch 10.85 inch pagedimen + /B4 10.125 inch 14.33 inch pagedimen + /B5 7.16 inch 10.125 inch pagedimen + end + } bind def +/papersize { + papersizedict begin + /Letter {lettertray letter} def + /LetterSmall {lettertray lettersmall} def + /Tabloid {11x17tray 11x17} def + /Ledger {ledgertray ledger} def + /Legal {legaltray legal} def + /Statement {statementtray statement} def + /Executive {executivetray executive} def + /A3 {a3tray a3} def + /A4 {a4tray a4} def + /A4Small {a4tray a4small} def + /B4 {b4tray b4} def + /B5 {b5tray b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + statusdict begin stopped end + } bind def +/manualpapersize { + papersizedict begin + /Letter {letter} def + /LetterSmall {lettersmall} def + /Tabloid {11x17} def + /Ledger {ledger} def + /Legal {legal} def + /Statement {statement} def + /Executive {executive} def + /A3 {a3} def + /A4 {a4} def + /A4Small {a4small} def + /B4 {b4} def + /B5 {b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + stopped + } bind def +/desperatepapersize { + statusdict /setpageparams known + { + paperwidth paperheight 0 1 + statusdict begin + {setpageparams} stopped + end + } {true} ifelse + } bind def +/papersizefailure { + FMAllowPaperSizeMismatch not + { +(The requested paper size is not available in any currently-installed tray) +(Edit the PS file to "FMAllowPaperSizeMismatch true" to use default tray) + FMFAILURE } if + } def +/DiacriticEncoding [ +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl +/numbersign /dollar /percent /ampersand /quotesingle /parenleft +/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K +/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash +/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h +/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar +/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute +/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis +/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis +/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve +/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex +/udieresis /dagger /.notdef /cent /sterling /section /bullet +/paragraph /germandbls /registered /copyright /trademark /acute +/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef +/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown +/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef +/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde +/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright +/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis +/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl +/periodcentered /quotesinglbase /quotedblbase /perthousand +/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute +/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve +/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron +/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +] def +/ReEncode { + dup + length + dict begin + { + 1 index /FID ne + {def} + {pop pop} ifelse + } forall + 0 eq {/Encoding DiacriticEncoding def} if + currentdict + end + } bind def +FMPColor + + { + /BEGINBITMAPCOLOR { + BITMAPCOLOR} def + /BEGINBITMAPCOLORc { + BITMAPCOLORc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUECOLOR } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUECOLORc } def + /BEGINBITMAPCMYK { + BITMAPCMYK } def + /BEGINBITMAPCMYKc { + BITMAPCMYKc } def + } + + { + /BEGINBITMAPCOLOR { + BITMAPGRAY} def + /BEGINBITMAPCOLORc { + BITMAPGRAYc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUEGRAY } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUEGRAYc } def + /BEGINBITMAPCMYK { + BITMAPCMYKGRAY } def + /BEGINBITMAPCMYKc { + BITMAPCMYKGRAYc } def + } +ifelse +/K { + FMPrintAllColorsAsBlack { + dup 1 eq 2 index 1 eq and 3 index 1 eq and not + {7 {pop} repeat 0 0 0 1 0 0 0} if + } if + FrameCurColors astore + pop combineColor +} bind def +/graymode true def +fMLevel1 { + /fmGetFlip { + fMatrix2 exch get mul 0 lt { -1 } { 1 } ifelse + } FmBD +} if +/setPatternMode { + fMLevel1 { + 2 index patScreenDict exch known { + pop pop + patScreenDict exch get aload pop + freq + mul + 5 2 roll + fMatrix2 currentmatrix 1 get 0 ne { + 3 -1 roll 90 add 3 1 roll + sflipx 1 fmGetFlip sflipy 2 fmGetFlip neg mul + } { + sflipx 0 fmGetFlip sflipy 3 fmGetFlip mul + } ifelse + 0 lt {exch pop} {pop} ifelse + fMNegative { + {neg} fmConcatProcs + } if + bind + + + + systemdict /setscreen get exec + /FrameCurGray exch def + } { + /bwidth exch def + /bpside exch def + /bstring exch def + /onbits 0 def /offbits 0 def + freq sangle landscape {90 add} if + {/ypoint exch def + /xpoint exch def + /xindex xpoint 1 add 2 div bpside mul cvi def + /yindex ypoint 1 add 2 div bpside mul cvi def + bstring yindex bwidth mul xindex 8 idiv add get + 1 7 xindex 8 mod sub bitshift and 0 ne fMNegative {not} if + {/onbits onbits 1 add def 1} + {/offbits offbits 1 add def 0} + ifelse + } + setscreen + offbits offbits onbits add div fMNegative {1.0 exch sub} if + /FrameCurGray exch def + } ifelse + } { + pop pop + dup patCache exch known { + patCache exch get + } { + dup + patDict /bstring 3 -1 roll put + patDict + 9 PatFreq screenIndex get div dup matrix scale + makepattern + dup + patCache 4 -1 roll 3 -1 roll put + } ifelse + /FrameCurGray 0 def + /FrameCurPat exch def + } ifelse + /graymode false def + combineColor +} bind def +/setGrayScaleMode { + graymode not { + /graymode true def + fMLevel1 { + setCurrentScreen + } if + } if + /FrameCurGray exch def + combineColor +} bind def +/normalize { + transform round exch round exch itransform + } bind def +/dnormalize { + dtransform round exch round exch idtransform + } bind def +/lnormalize { + 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop + } bind def +/H { + lnormalize setlinewidth + } bind def +/Z { + setlinecap + } bind def + +/PFill { + graymode fMLevel1 or not { + gsave 1 setgray eofill grestore + } if +} bind def +/PStroke { + graymode fMLevel1 or not { + gsave 1 setgray stroke grestore + } if + stroke +} bind def +/X { + fillvals exch get + dup type /stringtype eq + {8 1 setPatternMode} + {setGrayScaleMode} + ifelse + } bind def +/V { + PFill gsave eofill grestore + } bind def +/Vclip { + clip + } bind def +/Vstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/N { + PStroke + } bind def +/Nclip { + strokepath clip newpath + } bind def +/Nstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/M {newpath moveto} bind def +/E {lineto} bind def +/D {curveto} bind def +/O {closepath} bind def +/L { + /n exch def + newpath + normalize + moveto + 2 1 n {pop normalize lineto} for + } bind def +/Y { + L + closepath + } bind def +/R { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + x1 y1 + x2 y1 + x2 y2 + x1 y2 + 4 Y + } bind def +/rarc + {rad + arcto + } bind def +/RR { + /rad exch def + normalize + /y2 exch def + /x2 exch def + normalize + /y1 exch def + /x1 exch def + mark + newpath + { + x1 y1 rad add moveto + x1 y2 x2 y2 rarc + x2 y2 x2 y1 rarc + x2 y1 x1 y1 rarc + x1 y1 x1 y2 rarc + closepath + } stopped {x1 y1 x2 y2 R} if + cleartomark + } bind def +/RRR { + /rad exch def + normalize /y4 exch def /x4 exch def + normalize /y3 exch def /x3 exch def + normalize /y2 exch def /x2 exch def + normalize /y1 exch def /x1 exch def + newpath + normalize moveto + mark + { + x2 y2 x3 y3 rarc + x3 y3 x4 y4 rarc + x4 y4 x1 y1 rarc + x1 y1 x2 y2 rarc + closepath + } stopped + {x1 y1 x2 y2 x3 y3 x4 y4 newpath moveto lineto lineto lineto closepath} if + cleartomark + } bind def +/C { + grestore + gsave + R + clip + setCurrentScreen +} bind def +/CP { + grestore + gsave + Y + clip + setCurrentScreen +} bind def +/F { + FMfonts exch get + FMpointsize scalefont + setfont + } bind def +/Q { + /FMpointsize exch def + F + } bind def +/T { + moveto show + } bind def +/RF { + rotate + 0 ne {-1 1 scale} if + } bind def +/TF { + gsave + moveto + RF + show + grestore + } bind def +/P { + moveto + 0 32 3 2 roll widthshow + } bind def +/PF { + gsave + moveto + RF + 0 32 3 2 roll widthshow + grestore + } bind def +/S { + moveto + 0 exch ashow + } bind def +/SF { + gsave + moveto + RF + 0 exch ashow + grestore + } bind def +/B { + moveto + 0 32 4 2 roll 0 exch awidthshow + } bind def +/BF { + gsave + moveto + RF + 0 32 4 2 roll 0 exch awidthshow + grestore + } bind def +/G { + gsave + newpath + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill fill + grestore + } bind def +/Gstrk { + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/Gclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GG { + gsave + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill + fill + grestore + } bind def +/GGclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GGstrk { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/A { + gsave + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/Aclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/Astrk { + Gstrk +} bind def +/AA { + gsave + savematrix + newpath + + 3 index 2 div add exch 4 index 2 div sub exch + + normalize 3 index 2 div sub exch 4 index 2 div add exch + translate + rotate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/AAclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/AAstrk { + GGstrk +} bind def +/BEGINPRINTCODE { + /FMdicttop countdictstack 1 add def + /FMoptop count 7 sub def + /FMsaveobject save def + userdict begin + /showpage {} def + FMNORMALIZEGRAPHICS + 3 index neg 3 index neg translate + } bind def +/ENDPRINTCODE { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMsaveobject restore + } bind def +/gn { + 0 + { 46 mul + cf read pop + 32 sub + dup 46 lt {exit} if + 46 sub add + } loop + add + } bind def +/cfs { + /str sl string def + 0 1 sl 1 sub {str exch val put} for + str def + } bind def +/ic [ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 + {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx} + {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx} + {19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} + {13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh} + {4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh} + {13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl} + {7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl} + {0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl} + {10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl} + ] def +/ms { + /sl exch def + /val 255 def + /ws cfs + /im cfs + /val 0 def + /bs cfs + /cs cfs + } bind def +400 ms +/ip { + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip { + + + bis ris copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + ris gis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + gis bis copy pop + dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip4 { + + + kis cis copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + cis mis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + mis yis copy pop + dup dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + yis kis copy pop + 3 mul is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/wh { + /len exch def + /pos exch def + ws 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/bl { + /len exch def + /pos exch def + bs 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/s1 1 string def +/fl { + /len exch def + /pos exch def + /val cf s1 readhexstring pop 0 get def + pos 1 pos len add 1 sub {im exch val put} for + pos len + } bind def +/hx { + 3 copy getinterval + cf exch readhexstring pop pop + } bind def +/wbytes { + dup dup + 8 gt { pop 8 idiv mul } + { 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse } ifelse + } bind def +/BEGINBITMAPBWc { + 1 {} COMMONBITMAPc + } bind def +/BEGINBITMAPGRAYc { + 8 {} COMMONBITMAPc + } bind def +/BEGINBITMAP2BITc { + 2 {} COMMONBITMAPc + } bind def +/COMMONBITMAPc { + + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + cvtProc + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} image + bitmapsave restore + grestore + } bind def +/BEGINBITMAPBW { + 1 {} COMMONBITMAP + } bind def +/BEGINBITMAPGRAY { + 8 {} COMMONBITMAP + } bind def +/BEGINBITMAP2BIT { + 2 {} COMMONBITMAP + } bind def +/COMMONBITMAP { + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + cvtProc + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} image + bitmapsave restore + grestore + } bind def +/ngrayt 256 array def +/nredt 256 array def +/nbluet 256 array def +/ngreent 256 array def +fMLevel1 { +/colorsetup { + currentcolortransfer + /gryt exch def + /blut exch def + /grnt exch def + /redt exch def + 0 1 255 { + /indx exch def + /cynu 1 red indx get 255 div sub def + /magu 1 green indx get 255 div sub def + /yelu 1 blue indx get 255 div sub def + /kk cynu magu min yelu min def + /u kk currentundercolorremoval exec def +% /u 0 def + nredt indx 1 0 cynu u sub max sub redt exec put + ngreent indx 1 0 magu u sub max sub grnt exec put + nbluet indx 1 0 yelu u sub max sub blut exec put + ngrayt indx 1 kk currentblackgeneration exec sub gryt exec put + } for + {255 mul cvi nredt exch get} + {255 mul cvi ngreent exch get} + {255 mul cvi nbluet exch get} + {255 mul cvi ngrayt exch get} + setcolortransfer + {pop 0} setundercolorremoval + {} setblackgeneration + } bind def +} +{ +/colorSetup2 { + [ /Indexed /DeviceRGB 255 + {dup red exch get 255 div + exch dup green exch get 255 div + exch blue exch get 255 div} + ] setcolorspace +} bind def +} ifelse +/fakecolorsetup { + /tran 256 string def + 0 1 255 {/indx exch def + tran indx + red indx get 77 mul + green indx get 151 mul + blue indx get 28 mul + add add 256 idiv put} for + currenttransfer + {255 mul cvi tran exch get 255.0 div} + exch fmConcatProcs settransfer +} bind def +/BITMAPCOLOR { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + fMLevel1 { + colorsetup + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} {is} {is} true 3 colorimage + } { + colorSetup2 + /is width depth wbytes string def + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {cf is readhexstring pop} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPCOLORc { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + fMLevel1 { + colorsetup + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} {is} {is} true 3 colorimage + } { + colorSetup2 + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {ip} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLORc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris} {gis} {bis} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYKc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip4 pop cis} {mis} {yis} {kis} true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLOR { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf gis readhexstring pop } + { cf bis readhexstring pop } + true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYK { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /mis width string def + /yis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf mis readhexstring pop } + { cf yis readhexstring pop } + { cf kis readhexstring pop } + true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUEGRAYc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris gis bis width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAYc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop cis mis yis kis width cgray} image + bitmapsave restore + grestore + } bind def +/cgray { + /ww exch def + /k exch def + /y exch def + /m exch def + /c exch def + 0 1 ww 1 sub { /i exch def c i get m i get y i get k i get CMYKtoRGB + .144 mul 3 1 roll .587 mul 3 1 roll .299 mul add add + c i 3 -1 roll floor cvi put } for + c + } bind def +/gray { + /ww exch def + /b exch def + /g exch def + /r exch def + 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul + b i get .114 mul add add r i 3 -1 roll floor cvi put } for + r + } bind def +/BITMAPTRUEGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf gis readhexstring pop + cf bis readhexstring pop width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /yis width string def + /mis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf mis readhexstring pop + cf yis readhexstring pop + cf kis readhexstring pop width cgray} image + bitmapsave restore + grestore + } bind def +/BITMAPGRAY { + 8 {fakecolorsetup} COMMONBITMAP + } bind def +/BITMAPGRAYc { + 8 {fakecolorsetup} COMMONBITMAPc + } bind def +/ENDBITMAP { + } bind def +end + /ALDmatrix matrix def ALDmatrix currentmatrix pop +/StartALD { + /ALDsave save def + savematrix + ALDmatrix setmatrix + } bind def +/InALD { + restorematrix + } bind def +/DoneALD { + ALDsave restore + } bind def +/I { setdash } bind def +/J { [] 0 setdash } bind def +%%EndProlog +%%BeginSetup +(5.0) FMVERSION +1 1 0 0 612 792 0 1 16 FMDOCUMENT +0 0 /Helvetica FMFONTDEFINE +1 0 /Times-BoldItalic FMFONTDEFINE +2 0 /Helvetica-Bold FMFONTDEFINE +3 0 /Helvetica-Oblique FMFONTDEFINE +4 0 /Helvetica-BoldOblique FMFONTDEFINE +5 0 /Courier-Bold FMFONTDEFINE +6 0 /Courier-BoldOblique FMFONTDEFINE +32 FMFILLS +0 0 FMFILL +1 0.1 FMFILL +2 0.3 FMFILL +3 0.5 FMFILL +4 0.7 FMFILL +5 0.9 FMFILL +6 0.97 FMFILL +7 1 FMFILL +8 <0f1e3c78f0e1c387> FMFILL +9 <0f87c3e1f0783c1e> FMFILL +10 FMFILL +11 FMFILL +12 <8142241818244281> FMFILL +13 <03060c183060c081> FMFILL +14 <8040201008040201> FMFILL +16 1 FMFILL +17 0.9 FMFILL +18 0.7 FMFILL +19 0.5 FMFILL +20 0.3 FMFILL +21 0.1 FMFILL +22 0.03 FMFILL +23 0 FMFILL +24 FMFILL +25 FMFILL +26 <3333333333333333> FMFILL +27 <0000ffff0000ffff> FMFILL +28 <7ebddbe7e7dbbd7e> FMFILL +29 FMFILL +30 <7fbfdfeff7fbfdfe> FMFILL +%%EndSetup +%%Page: "i" 1 +%%BeginPaperSize: Letter +%%EndPaperSize +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(i) 555.78 57 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 720 558 720 2 L +0.5 H +2 Z +N +72 72 558 72 2 L +N +72 504 558 504 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 32 Q +(Service Dev) 198 662.67 T +(eloper\325) 353.01 662.67 T +(s Guide) 443.06 662.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 12 Q +(T) 198 638 T +(ec) 204.61 638 T +(hniques f) 217.84 638 T +(or De) 270.94 638 T +(veloping Ser) 301.43 638 T +(vices using the) 373.57 638 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Contr) 198 624 T +(ol De) 229.75 624 T +(vice Interface) 258.91 624 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(Chip W) 198 596 T +(atson, Jie Chen, Danjin W) 236.86 596 T +(u, W) 375.22 596 T +(alt Ak) 399.41 596 T +(ers) 429.18 596 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 198 568 T +(ersion 1.5 - December 9, 1996) 205.04 568 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(TJNAF - Thomas Jeff) 198 540 T +(erson National Acceler) 311.66 540 T +(ator F) 432.25 540 T +(acility) 463 540 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "i" 1 +%%Page: "ii" 2 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(ii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(TRADEMARKS:) 54 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(UNIX is a registered tr) 180 569.33 T +(ademar) 278.26 569.33 T +(k of A) 312.31 569.33 T +(T&T in the USA and other countr) 336.68 569.33 T +(ies) 481.9 569.33 T +(.) 494.53 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(VxW) 180 545.33 T +(or) 200.81 545.33 T +(ks is a register tr) 209.85 545.33 T +(ademar) 283.1 545.33 T +(k of Wind Riv) 317.15 545.33 T +(er Systems) 375.8 545.33 T +(.) 425.66 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The X Windo) 180 521.33 T +(w System is a tr) 237.65 521.33 T +(ademar) 308.12 521.33 T +(k of Massachusetts Institute of T) 342.17 521.33 T +(echnology) 484.37 521.33 T +(.) 528.95 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(OSF/Motif and Motif are tr) 180 497.33 T +(ademar) 294.94 497.33 T +(ks of Open Softw) 328.99 497.33 T +(are F) 404.99 497.33 T +(oundation, Inc.) 428.03 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ultr) 180 473.33 T +(ix and DEC are registered tr) 195.7 473.33 T +(ademar) 319.53 473.33 T +(ks of Digital Equipment Cor) 353.58 473.33 T +(por) 475.03 473.33 T +(ation.) 489.38 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(HPUX is a registered tr) 180 449.33 T +(ademar) 282.15 449.33 T +(k of He) 316.2 449.33 T +(wlett P) 347.68 449.33 T +(ac) 377.29 449.33 T +(kard.) 387.65 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(SURA/CEB) 54 344.33 T +(AF:) 105.92 344.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.44 (The Southeaster) 180 344.33 P +4.44 (n Univ) 258.62 344.33 P +4.44 (ersities Research Association \050SURA\051 oper) 291.15 344.33 P +4.44 (ates the) 499.98 344.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.01 (Contin) 180 332.33 P +2.01 (uous Electron Beam Acceler) 208.8 332.33 P +2.01 (ator F) 340.89 332.33 P +2.01 (acility \050CEBAF\051 f) 368.52 332.33 P +2.01 (or the United States) 445.59 332.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Depar) 180 320.33 T +(tment of Energy under contr) 207.63 320.33 T +(act DE-A) 331.48 320.33 T +(C05-84ER40150.) 371.19 320.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DISCLAIMER:) 54 218.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.49 (This repor) 180 218.33 P +0.49 (t w) 225.9 218.33 P +0.49 (as prepared as an account of w) 239.02 218.33 P +0.49 (or) 381.4 218.33 P +0.49 (k sponsored b) 390.44 218.33 P +0.49 (y the United States) 454.03 218.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.18 (go) 180 206.33 P +2.18 (v) 190.97 206.33 P +2.18 (er) 195.72 206.33 P +2.18 (nment. Neither the United States nor the United States Depar) 204.86 206.33 P +2.18 (tment of) 501.68 206.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.04 (Energy) 180 194.33 P +1.04 (, nor an) 210.68 194.33 P +1.04 (y of their emplo) 246.52 194.33 P +1.04 (y) 317.69 194.33 P +1.04 (ees) 322.49 194.33 P +1.04 (, mak) 338.46 194.33 P +1.04 (es an) 363.75 194.33 P +1.04 (y w) 389.1 194.33 P +1.04 (arr) 404.99 194.33 P +1.04 (anty) 417.11 194.33 P +1.04 (, e) 435.01 194.33 P +1.04 (xpress or implied, or) 446.86 194.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.83 (assumes an) 180 182.33 P +1.83 (y legal liability or responsibility f) 235.59 182.33 P +1.83 (or the accur) 383.89 182.33 P +1.83 (acy) 440.24 182.33 P +1.83 (, completeness) 454.8 182.33 P +1.83 (, or) 523.72 182.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.68 (usefulness of an) 180 170.33 P +3.68 (y inf) 260.02 170.33 P +3.68 (or) 281.74 170.33 P +3.68 (mation, appar) 290.88 170.33 P +3.68 (atus) 355.59 170.33 P +3.68 (, product or process disclosed, or) 374.34 170.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.46 (represents that its use w) 180 158.33 P +2.46 (ould not infr) 298.11 158.33 P +2.46 (inge pr) 355.42 158.33 P +2.46 (iv) 388.59 158.33 P +2.46 (ately o) 395.56 158.33 P +2.46 (wned r) 427.33 158.33 P +2.46 (ights) 459.95 158.33 P +2.46 (. Ref) 480.92 158.33 P +2.46 (erence) 509.43 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.6 (herein to an) 180 146.33 P +1.6 (y speci\336c commercial product, process) 235.85 146.33 P +1.6 (, or ser) 413.79 146.33 P +1.6 (vice b) 448.4 146.33 P +1.6 (y tr) 475.92 146.33 P +1.6 (ade name) 491.3 146.33 P +1.6 (,) 537.22 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (mar) 180 134.33 P +2.12 (k, man) 197.37 134.33 P +2.12 (uf) 229.4 134.33 P +2.12 (acturer) 237.44 134.33 P +2.12 (, or otherwise) 268.06 134.33 P +2.12 (, does not necessar) 332.17 134.33 P +2.12 (ily constitute or imply its) 425.94 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (endorsement, recommendation, or f) 180 122.33 P +1.08 (a) 341.33 122.33 P +1.08 (v) 346.69 122.33 P +1.08 (or) 351.44 122.33 P +1.08 (ing b) 360.48 122.33 P +1.08 (y the United States go) 383.03 122.33 P +1.08 (v) 485.57 122.33 P +1.08 (er) 490.32 122.33 P +1.08 (nment or) 499.46 122.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (an) 180 110.33 P +0.83 (y agency thereof) 190.97 110.33 P +0.83 (. The vie) 266.26 110.33 P +0.83 (w and opinions of the authors e) 309.67 110.33 P +0.83 (xpressed herein do) 453.3 110.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.94 (not necessar) 180 98.33 P +1.94 (ily state or re\337ect those of the United States go) 239.34 98.33 P +1.94 (v) 464.01 98.33 P +1.94 (er) 468.76 98.33 P +1.94 (nment or an) 477.9 98.33 P +1.94 (y) 535 98.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(agency thereof) 180 86.33 T +(.) 245.85 86.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DOCUMENT D) 54 668.33 T +(A) 121.37 668.33 T +(TE:) 127.69 668.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(T) 180 668.33 T +(ab) 184.91 668.33 T +(le of ontents gener) 195.83 668.33 T +(ated: December 9, 1996 11:46 am) 278.56 668.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "ii" 2 +%%Page: "iii" 3 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iii) 551.34 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(T) 180 710.67 T +(ab) 187.43 710.67 T +(le of Contents) 203.63 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198 684.33 T +(er) 210.53 684.33 T +(vie) 219.72 684.33 T +(w of cde) 232.3 684.33 T +(v Ser) 269.24 684.33 T +(vices) 292.88 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 316.92 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(What is a cde) 198.2 672.33 T +(v Ser) 258.48 672.33 T +(vice) 282.12 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 300.24 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ser) 198.2 660.33 T +(vice Classes) 214.06 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Request Object Classes) 198.2 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 305.8 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Loader Functions) 198.2 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(What the De) 198.2 624.33 T +(v) 253.48 624.33 T +(eloper Must Understand) 258.23 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 366.96 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 180 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198 612.33 T +(v) 210.48 612.33 T +(eloping cde) 215.23 612.33 T +(v Ser) 266.07 612.33 T +(vices) 289.71 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 314.14 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Steps in De) 198.2 600.33 T +(v) 249.59 600.33 T +(eloping a cde) 254.34 600.33 T +(v Ser) 313.52 600.33 T +(vice) 337.16 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 355.84 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 180 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 198 588.33 T +(vSer) 233.83 588.33 T +(vice Class) 254.69 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 303.02 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 576.33 T +(er) 210.73 576.33 T +(vie) 219.92 576.33 T +(w of the cde) 232.5 576.33 T +(vSer) 286.12 576.33 T +(vice Class) 306.98 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 353.06 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The \337ush Method) 198.2 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The poll Method) 198.2 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The pend Method) 198.2 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The getRequestObject Method) 198.2 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 336.38 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 198.2 516.33 T +(lic Member Functions of the cde) 215.79 516.33 T +(vSer) 357.21 516.33 T +(vice Class) 378.07 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . .) 425.34 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 198.2 504.33 T +(lic Functions of the cde) 215.79 504.33 T +(vSer) 317.76 504.33 T +(vice Class) 338.62 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 386.42 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\337ush) 216 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(poll) 216 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 233.52 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pend) 216 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pend) 216 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getRequestObject) 216 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 297.46 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getNameSer) 216 432.33 T +(v) 272.43 432.33 T +(er) 277.18 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 286.34 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getCollectionRequest) 216 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 311.36 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getFd) 216 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(registerFd) 216 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(autoErrorOn) 216 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(autoErrorOff) 216 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(repor) 216 360.33 T +(tError) 239.74 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 266.88 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setErrorHandler) 216 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 289.12 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setThreshold) 216 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(name) 216 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 180 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 198 312.33 T +(vRequestObject Class) 233.83 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 333.6 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 300.33 T +(er) 210.73 300.33 T +(vie) 219.92 300.33 T +(w of the cde) 232.5 300.33 T +(vRequest Object Class) 286.12 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 389.2 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 198.2 288.33 T +(lic Member Functions of the cde) 215.79 288.33 T +(vRequest Object Class) 357.21 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . .) 461.48 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachRef) 216 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachRef) 216 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachPtr) 216 252.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 252.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 252.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachPtr) 216 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(detach) 216 228.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 228.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 228.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(detach) 216 216.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 216.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 216.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(message) 216 204.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 204.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 204.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(de) 216 192.33 T +(vice) 226.82 192.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 192.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 192.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(system) 216 180.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 180.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 180.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ser) 216 168.33 T +(vice) 230.19 168.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 168.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 168.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getState) 216 156.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 255.76 156.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 156.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getAccess) 216 144.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 144.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 144.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setConte) 216 132.33 T +(xt) 255.72 132.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 132.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 132.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getConte) 216 120.33 T +(xt) 256.28 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getPr) 216 108.33 T +(iv) 240.05 108.33 T +(ate) 247.02 108.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 108.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 108.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setPr) 216 96.33 T +(iv) 239.49 96.33 T +(ate) 246.46 96.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 96.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 96.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(send) 216 84.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 84.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 84.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iii" 3 +%%Page: "iv" 4 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iv) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(sendNoBloc) 198 713.33 T +(k) 251.71 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 528.88 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendCallbac) 198 701.33 T +(k) 252.82 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 528.88 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 162 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 180 689.33 T +(vCollectionRequest Class) 215.83 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 330.82 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 528.88 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180.2 677.33 T +(er) 192.73 677.33 T +(vie) 201.92 677.33 T +(w of the cde) 214.5 677.33 T +(vCollection Request Class) 268.12 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . .) 386.42 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 528.88 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 180.2 665.33 T +(lic Member Functions of the cde) 197.79 665.33 T +(vCollection Request Class) 339.21 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . .) 455.92 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 528.88 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(constr) 198 653.33 T +(uctor) 225.38 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 528.88 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(destr) 198 641.33 T +(uctor) 220.38 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 528.88 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachPtr) 198 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 528.88 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(className) 198 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 528.88 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(resultCodeT) 198 605.33 T +(ag) 251.26 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 528.88 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 162 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The Ser) 180 593.33 T +(vice Loader Function) 215.87 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 311.36 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 528.88 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180.2 581.33 T +(er) 192.73 581.33 T +(vie) 201.92 581.33 T +(w) 214.5 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 222.4 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 528.88 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Naming Con) 180.2 569.33 T +(v) 235.57 569.33 T +(ention) 240.32 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 528.88 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 162 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 180 557.33 T +(vT) 215.83 557.33 T +(r) 225.74 557.33 T +(anObj Class) 228.97 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 528.88 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180.2 545.33 T +(er) 192.73 545.33 T +(vie) 201.92 545.33 T +(w of the cde) 214.5 545.33 T +(vT) 268.12 545.33 T +(r) 278.03 545.33 T +(anObj Class) 281.26 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 336.38 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 528.88 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 180.2 533.33 T +(lic Data Proper) 197.79 533.33 T +(ties of the cde) 264.32 533.33 T +(vT) 326.28 533.33 T +(r) 336.19 533.33 T +(anObj Class) 339.42 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . .) 394.76 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 528.88 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(system_) 198 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 236.3 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 528.88 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(reqObj_) 198 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 236.3 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 528.88 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(resultData_) 198 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 528.88 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(userCallbac) 198 485.33 T +(k_) 250.59 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 528.88 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 180.2 473.33 T +(lic Member Functions of the cde) 197.79 473.33 T +(vT) 339.21 473.33 T +(r) 349.12 473.33 T +(anObj Class) 352.35 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . .) 408.66 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 528.88 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(status) 198 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 225.18 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 528.88 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(remo) 198 449.33 T +(v) 220.63 449.33 T +(eF) 225.38 449.33 T +(romGr) 236.6 449.33 T +(ps) 265.23 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15) 528.88 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(enab) 198 437.33 T +(leDeleteCbk) 220.04 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15) 528.88 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(disab) 198 425.33 T +(leDeleteCbk) 221.7 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15) 528.88 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8.) 162 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Def) 180 413.33 T +(ault Ser) 195.26 413.33 T +(vice Beha) 230.02 413.33 T +(vior f) 273.73 413.33 T +(or Standard Messages) 295.1 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . .) 397.54 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 528.88 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180.2 401.33 T +(er) 192.73 401.33 T +(vie) 201.92 401.33 T +(w) 214.5 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 222.4 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 528.88 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322get\323 Message) 180.2 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 528.88 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322set\323 Message) 180.2 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 528.88 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322monitorOn\323 Message) 180.2 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(19) 528.88 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_SUCCESS) 198 353.33 T +0 F +(:) 279.68 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(20) 528.88 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_DISCONNECTED) 198 341.33 T +0 F +(:) 311.34 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 314.14 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(20) 528.88 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_RECONNECTED) 198 329.33 T +0 F +(:) 308.56 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 311.36 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(20) 528.88 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_ERR) 198 317.33 T +(OR) 252.25 317.33 T +0 F +(:) 267.25 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(20) 528.88 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_INV) 198 305.33 T +(ALIDOBJ) 247.21 305.33 T +0 F +(:) 291.1 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 294.68 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(20) 528.88 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_INV) 198 293.33 T +(ALID) 247.21 293.33 T +(ARG) 270.14 293.33 T +0 F +(:) 292.36 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 297.46 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(20) 528.88 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_INV) 198 281.33 T +(ALIDSVC) 247.21 281.33 T +0 F +(:) 291.1 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 294.68 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(20) 528.88 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_NO) 198 269.33 T +(TCONNECTED) 245.94 269.33 T +0 F +(:) 315.38 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 319.7 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(20) 528.88 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_IOF) 198 257.33 T +(AILED) 247.21 257.33 T +0 F +(:) 277.21 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(20) 528.88 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_CONFLICT) 198 245.33 T +0 F +(:) 281.69 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 286.34 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_NO) 198 233.33 T +(TFOUND) 245.94 233.33 T +0 F +(:) 287.6 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_TIMEOUT) 198 221.33 T +0 F +(:) 276.14 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_CONVER) 198 209.33 T +(T) 273.92 209.33 T +0 F +(:) 279.83 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_OUT) 198 197.33 T +(OFRANGE) 252.05 197.33 T +0 F +(:) 302.05 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 305.8 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_NO) 198 185.33 T +(A) 245.84 185.33 T +(CCESS) 252.66 185.33 T +0 F +(:) 287.11 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_A) 198 173.33 T +(CCESSCHANGED) 238.16 173.33 T +0 F +(:) 323.16 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 328.04 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322monitorOff) 180.2 161.33 T +(\323 Message) 230.81 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(de) 198 149.33 T +(vice) 208.82 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 227.96 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attr) 198 137.33 T +(ib) 212.6 137.33 T +(ute) 220.18 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 236.3 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(function) 198 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 233.52 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(user) 198 113.33 T +(arg) 217.35 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 233.52 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9.) 162 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(demoSer) 180 101.33 T +(vice: A Sample cde) 220.87 101.33 T +(v Ser) 306.16 101.33 T +(vice) 329.8 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 350.28 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(25) 528.88 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180.2 89.33 T +(er) 192.73 89.33 T +(vie) 201.92 89.33 T +(w of the demoSer) 214.5 89.33 T +(vice) 293.17 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 311.36 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(25) 528.88 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iv" 4 +%%Page: "v" 5 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(v) 553 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The demoDe) 198.2 713.33 T +(vice Object) 255.7 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 305.8 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(25) 546.88 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The demoSer) 198.2 701.33 T +(vice Object) 259.08 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(31) 546.88 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The enqueueT) 198.2 689.33 T +(r) 262.04 689.33 T +(ansaction Method) 265.27 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 344.72 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 546.88 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The processT) 198.2 677.33 T +(r) 258.13 677.33 T +(ansaction Method) 261.36 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 341.94 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 546.88 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The ne) 198.2 665.33 T +(wDemoSer) 229.13 665.33 T +(vice Function) 278.88 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 339.16 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 546.88 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 198.2 653.33 T +(vSelector Object) 234.03 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 546.88 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The VERB En) 198.2 641.33 T +(umer) 260.35 641.33 T +(ation) 283.03 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 305.8 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 546.88 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The A) 198.2 629.33 T +(TTR En) 223.68 629.33 T +(umer) 258.03 629.33 T +(ation) 280.71 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 303.02 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 546.88 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The demoRequestObject Object) 198.2 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 341.94 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Mak) 198.2 605.33 T +(e\336le f) 216.89 605.33 T +(or the demoSer) 240.49 605.33 T +(vice) 309.71 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 328.04 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(52) 546.88 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198.2 593.33 T +(vice De\336nition File f) 210.68 593.33 T +(or the demoSer) 297.07 593.33 T +(vice) 366.29 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 386.42 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(53) 546.88 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "v" 5 +%%Page: "vi" 6 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(vi) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "vi" 6 +%%Page: "vii" 7 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(vii) 548.56 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(List of Figures) 180 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(Figure 1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Return codes generated by the send method.) 234 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.........................................) 436.46 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 2.) 180 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Naming convention and syntax for the cdevService loader function) 234 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(......) 528.2 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 3.) 180 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Example cdevService loader function) 234 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(....................................................) 400.32 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 4.) 180 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Default behavior of the \322get\323 and \322set\323 messages) 234 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..................................) 450.36 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 546.88 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 5.) 180 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Default behavior of the \322monitorOn\323 and \322monitorOff\323 messages) 234 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..........) 517.08 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(22) 546.88 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 6.) 180 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(demoDevice.h: Header file for devices used by the demoService) 234 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.........) 519.86 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(26) 546.88 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 7.) 180 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(demoDevice.cc: C++ source for the demoDevice class) 234 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.........................) 475.38 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(27) 546.88 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 8.) 180 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(demoService.h: Header file for the demoService class) 234 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..........................) 472.6 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 546.88 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 9.) 180 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(demoService.cc: Source code for the demoService class) 234 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.....................) 486.5 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(38) 546.88 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 10.) 180 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(demoRequestObject.h: Header file for the demoRequestObject class) 234 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..) 539.32 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 11.) 180 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(demoRequestObject.cc: Source for the demoRequestObject class) 234 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(......) 528.2 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(47) 546.88 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 12.) 180 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Makefile for the demoService) 234 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.................................................................) 364.18 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(52) 546.88 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 13.) 180 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Device Definition Language file for the demoService) 234 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.............................) 464.26 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(53) 546.88 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "vii" 7 +%%Page: "viii" 8 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(viii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "viii" 8 +%%Page: "1" 9 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. Ov) 442.1 739 T +(er) 463.38 739 T +(vie) 471.65 739 T +(w of cde) 482.98 739 T +(v Ser) 516.22 739 T +(vices) 537.5 739 T +0 10 Q +(1) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(1.) 159.32 710.67 T +(Over) 180 710.67 T +(vie) 212.05 710.67 T +(w of cde) 231.3 710.67 T +(v Ser) 287.1 710.67 T +(vices) 321.48 710.67 T +2 10 Q +(What is a cde) 72 673.33 T +(v) 135.76 673.33 T +(Ser) 72 661.33 T +(vice) 88.22 661.33 T +0 F +0.62 (The cde) 180 673.33 P +0.62 (v libr) 216.45 673.33 P +0.62 (ar) 238.07 673.33 P +0.62 (y de\336nes a command set that can be used to pro) 247.26 673.33 P +0.62 (vide a homogenous) 469.5 673.33 P +0.25 (interf) 180 661.33 P +0.25 (ace to diff) 201.93 661.33 P +0.25 (er) 245.49 661.33 P +0.25 (ing control systems) 254.53 661.33 P +0.25 (. In order to incor) 340.46 661.33 P +0.25 (por) 417.34 661.33 P +0.25 (ate a control system into the) 431.69 661.33 P +-0.09 (cde) 180 649.33 P +-0.09 (v en) 195.82 649.33 P +-0.09 (vironment, the de) 214.43 649.33 P +-0.09 (v) 291.2 649.33 P +-0.09 (eloper m) 295.95 649.33 P +-0.09 (ust create) 334.66 649.33 P +3 F +-0.09 (linking code) 381.16 649.33 P +0 F +-0.09 ( that allo) 433.87 649.33 P +-0.09 (ws the cde) 471.33 649.33 P +-0.09 (v system) 518.64 649.33 P +1.93 (to comm) 180 637.33 P +1.93 (unicate with the system. This) 220.17 637.33 P +3 F +1.93 (linking code) 360.98 637.33 P +0 F +1.93 ( is called a) 415.7 637.33 P +3 F +1.93 (cde) 473.44 637.33 P +1.93 (v ser) 489.26 637.33 P +1.93 (vice) 513.16 637.33 P +1.93 (.) 530.79 637.33 P +0 F +1.93 ( At a) 533.57 637.33 P +-0.22 (minim) 180 625.33 P +-0.22 (um, the cde) 206.56 625.33 P +-0.22 (v ser) 258.07 625.33 P +-0.22 (vice de) 279.82 625.33 P +-0.22 (v) 310.97 625.33 P +-0.22 (eloper m) 315.72 625.33 P +-0.22 (ust de) 354.3 625.33 P +-0.22 (v) 381.02 625.33 P +-0.22 (elop tw) 385.77 625.33 P +-0.22 (o interf) 417.13 625.33 P +-0.22 (ace classes and a simple) 447.18 625.33 P +0 (constr) 180 613.33 P +0 (uctor function in order to create a ne) 207.38 613.33 P +0 (w ser) 367.8 613.33 P +0 (vice) 391.99 613.33 P +0 (. These classes and functions will) 409.62 613.33 P +(be descr) 180 601.33 T +(ibed at length in the sections that f) 218.5 601.33 T +(ollo) 369.96 601.33 T +(w) 385.37 601.33 T +(.) 391.99 601.33 T +2 F +(Ser) 72 572.33 T +(vice Classes) 88.22 572.33 T +0 F +4.35 (Each ser) 180 572.33 P +4.35 (vice m) 224.11 572.33 P +4.35 (ust de\336ne a ser) 257.25 572.33 P +4.35 (vice class that pro) 338.96 572.33 P +4.35 (vides the mechanisms f) 431.89 572.33 P +4.35 (or) 549.11 572.33 P +1.51 (comm) 180 560.33 P +1.51 (unicating with the under) 207.12 560.33 P +1.51 (lying control system. This class is inher) 317.4 560.33 P +1.51 (ited from the) 499.41 560.33 P +3 F +0.22 (cde) 180 548.33 P +0.22 (vSer) 195.82 548.33 P +0.22 (vice) 216.68 548.33 P +0 F +0.22 ( class) 234.46 548.33 P +0.22 (, from which it gains most of its functionality) 260.09 548.33 P +0.22 (. The main eff) 453.15 548.33 P +0.22 (or) 514.66 548.33 P +0.22 (t f) 523.95 548.33 P +0.22 (or the) 532.21 548.33 P +-0.03 (de) 180 536.33 P +-0.03 (v) 190.82 536.33 P +-0.03 (eloper in creating this class is in the) 195.57 536.33 P +3 F +-0.03 (\337ush, poll and pend) 355.98 536.33 P +0 F +-0.03 ( methods) 442.62 536.33 P +-0.03 (. These methods) 483.57 536.33 P +2.02 (are functionally identical to those de\336ned in the) 180 524.33 P +3 F +2.02 (cde) 406.82 524.33 P +2.02 (vSystem) 422.64 524.33 P +0 F +2.02 ( object, ho) 460.98 524.33 P +2.02 (w) 511 524.33 P +2.02 (e) 518.12 524.33 P +2.02 (v) 523.38 524.33 P +2.02 (er) 528.13 524.33 P +2.02 (, the) 536.52 524.33 P +1.38 (de) 180 512.33 P +1.38 (v) 190.82 512.33 P +1.38 (eloper m) 195.57 512.33 P +1.38 (ust pro) 235.75 512.33 P +1.38 (vide concrete mechanisms f) 267.54 512.33 P +1.38 (or comm) 395.3 512.33 P +1.38 (unicating with the intended) 435.47 512.33 P +1.82 (control system, as w) 180 500.33 P +1.82 (ell as managing and repor) 275.95 500.33 P +1.82 (ting errors that might occur dur) 399.24 500.33 P +1.82 (ing) 544.66 500.33 P +(nor) 180 488.33 T +(mal oper) 194.7 488.33 T +(ation.) 233.5 488.33 T +2 F +(Request Object) 72 459.33 T +(Classes) 72 447.33 T +0 F +2.32 (The ser) 180 459.33 P +2.32 (vice de) 216.52 459.33 P +2.32 (v) 250.21 459.33 P +2.32 (eloper m) 254.96 459.33 P +2.32 (ust also create a request object class that pro) 296.08 459.33 P +2.32 (vides the) 515.66 459.33 P +1.8 (mechanisms f) 180 447.33 P +1.8 (or a) 243.18 447.33 P +3 F +1.8 (cde) 266.78 447.33 P +1.8 (vDe) 282.6 447.33 P +1.8 (vice) 300.08 447.33 P +0 F +1.8 ( object to comm) 317.86 447.33 P +1.8 (unicate with the de) 393.73 447.33 P +1.8 (v) 482.19 447.33 P +1.8 (eloper\325) 486.94 447.33 P +1.8 (s ser) 516.45 447.33 P +1.8 (vice) 540.22 447.33 P +0.93 (class) 180 435.33 P +0.93 (. This class is inher) 202.63 435.33 P +0.93 (ited from the) 291.5 435.33 P +3 F +0.93 (cde) 352.64 435.33 P +0.93 (vRequestObject) 368.46 435.33 P +0 F +0.93 ( class) 439.6 435.33 P +0.93 (, from which it gains) 465.94 435.33 P +0.17 (most of its functionality) 180 423.33 P +0.17 (. The pr) 280.65 423.33 P +0.17 (imar) 315.59 423.33 P +0.17 (y eff) 335.33 423.33 P +0.17 (or) 354.1 423.33 P +0.17 (t f) 363.39 423.33 P +0.17 (or the de) 371.59 423.33 P +0.17 (v) 411.09 423.33 P +0.17 (eloper in creating this class is in) 415.84 423.33 P +1.38 (the) 180 411.33 P +3 F +1.38 (send, sendNoBloc) 198.05 411.33 P +1.38 (k) 280.38 411.33 P +0 F +1.38 (and) 289.54 411.33 P +3 F +1.38 (sendCallbac) 310.37 411.33 P +1.38 (k) 365.19 411.33 P +0 F +1.38 ( functions) 370.19 411.33 P +1.38 (. The ser) 414.21 411.33 P +1.38 (vice creator m) 456.73 411.33 P +1.38 (ust also) 522.16 411.33 P +1.76 (de) 180 399.33 P +1.76 (v) 190.82 399.33 P +1.76 (elop his str) 195.57 399.33 P +1.76 (ategy f) 247.35 399.33 P +1.76 (or ef\336ciently comm) 278.83 399.33 P +1.76 (unicating with the under) 365.61 399.33 P +1.76 (lying system. The) 476.67 399.33 P +-0.07 (source code in the f) 180 387.33 P +-0.07 (ollo) 266.69 387.33 P +-0.07 (wing chapters will illustr) 282.1 387.33 P +-0.07 (ate a queueing scheme that pro) 386.25 387.33 P +-0.07 (vides a) 526.39 387.33 P +1.65 (v) 180 375.33 P +1.65 (er) 184.75 375.33 P +1.65 (y simple and ef\336cient linkage betw) 193.94 375.33 P +1.65 (een the ser) 353.82 375.33 P +1.65 (vice and the request object. The) 407.45 375.33 P +0.57 (request object is also responsib) 180 363.33 P +0.57 (le f) 322.14 363.33 P +0.57 (or detecting and repor) 335.75 363.33 P +0.57 (ting errors that occur within) 435.68 363.33 P +(its domain.) 180 351.33 T +2 F +(Loader Functions) 72 322.33 T +0 F +-0.14 (The loader function is an e) 180 322.33 P +-0.14 (xter) 296.81 322.33 P +-0.14 (n \322C\323 function that is called b) 313.73 322.33 P +-0.14 (y the cde) 439.38 322.33 P +-0.14 (vSystem object to) 479.37 322.33 P +(dynamically constr) 180 310.33 T +(uct a cop) 262.39 310.33 T +(y of the ser) 302.67 310.33 T +(vice class) 352.44 310.33 T +(.) 395.63 310.33 T +2 F +(What the) 72 281.33 T +(De) 72 269.33 T +(veloper Must) 84.63 269.33 T +(Under) 72 257.33 T +(stand) 100.74 257.33 T +0 F +0.01 (In order to create cde) 180 281.33 P +0.01 (v ser) 274.81 281.33 P +0.01 (vices) 296.79 281.33 P +0.01 (, the de) 319.42 281.33 P +0.01 (v) 352.51 281.33 P +0.01 (eloper m) 357.26 281.33 P +0.01 (ust ha) 396.07 281.33 P +0.01 (v) 423.13 281.33 P +0.01 (e an e) 427.88 281.33 P +0.01 (xtensiv) 455.41 281.33 P +0.01 (e understanding) 486.28 281.33 P +2.68 (of the complete cde) 180 269.33 P +2.68 (v system. A potential ser) 275.02 269.33 P +2.68 (vice de) 394.97 269.33 P +2.68 (v) 429.04 269.33 P +2.68 (eloper should \336rst de) 433.79 269.33 P +2.68 (v) 534.35 269.33 P +2.68 (elop) 539.1 269.33 P +-0.23 (applications using e) 180 257.33 P +-0.23 (xisting cde) 267.07 257.33 P +-0.23 (v ser) 313.78 257.33 P +-0.23 (vices in order to understand the e) 335.52 257.33 P +-0.23 (xpected beha) 482.28 257.33 P +-0.23 (vior) 541.89 257.33 P +0.74 (of a ser) 180 245.33 P +0.74 (vice) 215.14 245.33 P +0.74 (. The de) 232.77 245.33 P +0.74 (v) 270.64 245.33 P +0.74 (eloper should then f) 275.39 245.33 P +0.74 (amiliar) 365.16 245.33 P +0.74 (iz) 394.75 245.33 P +0.74 (e himself completely with all of the) 401.82 245.33 P +0.58 (classes within the cde) 180 233.33 P +0.58 (v libr) 278.71 233.33 P +0.58 (ar) 300.31 233.33 P +0.58 (y) 309.5 233.33 P +0.58 (, pa) 313.5 233.33 P +0.58 (ying special attention to the) 330.46 233.33 P +3 F +0.58 (cde) 457.35 233.33 P +0.58 (vSer) 473.17 233.33 P +0.58 (vice) 494.03 233.33 P +0 F +0.58 ( class and) 511.81 233.33 P +(the) 180 221.33 T +3 F +(cde) 196.68 221.33 T +(vRequestObject) 212.5 221.33 T +0 F +( class) 283.64 221.33 T +(.) 309.05 221.33 T +1.65 (The f) 180 204.33 P +1.65 (ollo) 204.14 204.33 P +1.65 (wing chapters descr) 219.55 204.33 P +1.65 (ibe the str) 311.92 204.33 P +1.65 (ucture and syntax of the most impor) 359.28 204.33 P +1.65 (tant of) 528.55 204.33 P +-0.18 (these classes and an o) 180 192.33 P +-0.18 (v) 281.41 192.33 P +-0.18 (er) 286.16 192.33 P +-0.18 (vie) 295.35 192.33 P +-0.18 (w of ho) 307.93 192.33 P +-0.18 (w cer) 339.66 192.33 P +-0.18 (tain messages are e) 363.77 192.33 P +-0.18 (xpected to beha) 452.97 192.33 P +-0.18 (v) 523.57 192.33 P +-0.18 (e) 528.32 192.33 P +-0.18 (. This) 533.73 192.33 P +0.02 (man) 180 180.33 P +0.02 (ual \336nishes with the complete annotated source code f) 199.35 180.33 P +0.02 (or a demonstr) 439.91 180.33 P +0.02 (ation ser) 501.55 180.33 P +0.02 (vice) 540.22 180.33 P +(that oper) 180 168.33 T +(ates on a vir) 219.37 168.33 T +(tual control system.) 274.24 168.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "1" 9 +%%Page: "2" 10 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. De) 54 739 T +(v) 75.24 739 T +(eloping cde) 79.51 739 T +(v Ser) 125.27 739 T +(vices) 146.55 739 T +0 10 Q +(2) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(2.) 141.32 710.67 T +(De) 162 710.67 T +(veloping cde) 179.68 710.67 T +(v Ser) 265.05 710.67 T +(vices) 299.44 710.67 T +2 10 Q +(Steps in) 54 673.33 T +-0.1 (De) 54 661.33 P +-0.1 (veloping a cde) 66.63 661.33 P +-0.1 (v) 135.76 661.33 P +(Ser) 54 649.33 T +(vice) 70.22 649.33 T +0 F +(1.) 162 673.33 T +2 F +(Install and b) 180 673.33 T +(uild the cde) 238.15 673.33 T +(v distrib) 293.57 673.33 T +(ution.) 332.27 673.33 T +0 F +( Obtain a cop) 359.49 673.33 T +(y of the most recent cde) 418.67 673.33 T +(v) 525.09 673.33 T +(distr) 180 661.33 T +(ib) 199.04 661.33 T +(ution and install it on y) 206.62 661.33 T +(our system.) 305.36 661.33 T +(2.) 162 637.33 T +2 F +(De\336ne the de) 180 637.33 T +(vices in y) 242.64 637.33 T +(our contr) 287.42 637.33 T +(ol system.) 331.11 637.33 T +0 F +( De\336ne the names) 380.02 637.33 T +(, attr) 461.02 637.33 T +(ib) 481.18 637.33 T +(utes and) 488.76 637.33 T +(messages associated with each de) 180 625.33 T +(vice in y) 334.77 625.33 T +(our control system. This inf) 370.69 625.33 T +(or) 489.87 625.33 T +(mation) 499.01 625.33 T +(will be cr) 180 613.33 T +(itical in the constr) 219.04 613.33 T +(uction of the) 296.44 613.33 T +3 F +( De) 350.92 613.33 T +(vice De\336nition Language) 366.18 613.33 T +0 F +(\336le that cde) 478.46 613.33 T +(v) 529.3 613.33 T +(will use to deter) 180 601.33 T +(mine which ser) 249.72 601.33 T +(vice will process messages f) 316.7 601.33 T +(or a de) 442.54 601.33 T +(vice) 473.37 601.33 T +(.) 491 601.33 T +(3.) 162 577.33 T +2 F +(Design and document speci\336c de) 180 577.33 T +(vice/messa) 338.78 577.33 T +(g) 392.05 577.33 T +(e beha) 398.26 577.33 T +(vior) 429.79 577.33 T +(.) 447.53 577.33 T +0 F +(Deter) 453.09 577.33 T +(mine the) 477.79 577.33 T +(speci\336c inputs and outputs required f) 180 565.33 T +(or each de) 342.56 565.33 T +(vice to process a message) 389.51 565.33 T +(.) 507.74 565.33 T +(Design and document ho) 180 553.33 T +(w the ser) 291.02 553.33 T +(vice will route messages to the under) 331.89 553.33 T +(lying) 496.55 553.33 T +(control system. Ensure that the disposition of standard messages within y) 180 541.33 T +(our) 504.94 541.33 T +(ser) 180 529.33 T +(vice is consistent with the beha) 194.19 529.33 T +(vior of standard cde) 331.83 529.33 T +(v ser) 419.35 529.33 T +(vices) 441.32 529.33 T +(.) 463.95 529.33 T +(4.) 162 505.33 T +2 F +-0.11 (De) 180 505.33 P +-0.11 (velop y) 192.63 505.33 P +-0.11 (our cde) 226.73 505.33 P +-0.11 (vSer) 262.58 505.33 P +-0.11 (vice object.) 284.36 505.33 P +0 F +-0.11 ( This object is a sub-class of the) 338.72 505.33 P +3 F +-0.11 (cde) 482.87 505.33 P +-0.11 (vSer) 498.69 505.33 P +-0.11 (vice) 519.55 505.33 P +0 F +-0.21 (class and will be responsib) 180 493.33 P +-0.21 (le f) 297.87 493.33 P +-0.21 (or responding to) 310.7 493.33 P +3 F +-0.21 (\337ush, poll,) 385.1 493.33 P +0 F +-0.21 ( and) 429.9 493.33 P +3 F +-0.21 ( pend) 449.15 493.33 P +0 F +-0.21 (requests from) 476.52 493.33 P +(the cde) 180 481.33 T +(vSystem object. The ser) 212.5 481.33 T +(vice object should be ab) 320.06 481.33 T +(le to perf) 427.14 481.33 T +(or) 465.75 481.33 T +(m all interf) 474.89 481.33 T +(ace) 520.71 481.33 T +-0.26 (tasks necessar) 180 469.33 P +-0.26 (y to link the ser) 246.73 469.33 P +-0.26 (vice speci\336c) 313.26 469.33 P +3 F +-0.26 (cde) 369.42 469.33 P +-0.26 (vRequestObjects) 385.24 469.33 P +0 F +-0.26 ( to the under) 461.39 469.33 P +-0.26 (lying) 516.92 469.33 P +(control system.) 180 457.33 T +(5.) 162 433.33 T +2 F +(De) 180 433.33 T +(velop y) 192.63 433.33 T +(our cde) 226.84 433.33 T +(vRequestObject object.) 262.81 433.33 T +0 F +( This object is a sub-class of the) 373.95 433.33 T +3 F +(cde) 180 421.33 T +(vRequestObject) 195.82 421.33 T +0 F +( class and will be responsib) 266.96 421.33 T +(le f) 388.47 421.33 T +(or responding to) 401.51 421.33 T +3 F +(send,) 476.55 421.33 T +(sendNoBloc) 180 409.33 T +(k) 233.71 409.33 T +0 F +(and) 241.49 409.33 T +3 F +(sendCallbac) 260.95 409.33 T +(k) 315.77 409.33 T +0 F +( requests from the cde) 320.77 409.33 T +(v application.) 419.96 409.33 T +(6.) 162 385.33 T +2 F +(De) 180 385.33 T +(velop y) 192.63 385.33 T +(our cde) 226.84 385.33 T +(vCollectionRequest object \050optional\051.) 262.81 385.33 T +0 F +(If y) 445.06 385.33 T +(our ser) 458.2 385.33 T +(vice will) 489.62 385.33 T +(pro) 180 373.33 T +(vide specializ) 194.3 373.33 T +(ed suppor) 253.61 373.33 T +(t f) 298.48 373.33 T +(or collections of de) 306.52 373.33 T +(vices) 389.59 373.33 T +(, it wil be necessar) 412.22 373.33 T +(y to) 494.77 373.33 T +(de) 180 361.33 T +(v) 190.82 361.33 T +(elop a cde) 195.57 361.33 T +(vCollectionRequest object that processes these requests) 241.41 361.33 T +(.) 493.04 361.33 T +(7.) 162 337.33 T +2 F +(Create a ser) 180 337.33 T +(vice loader function.) 237.35 337.33 T +0 F +( This function is descr) 334.6 337.33 T +(ibed ear) 431.45 337.33 T +(lier in this) 467.73 337.33 T +(document and is used b) 180 325.33 T +(y the cde) 285.97 325.33 T +(vSystem object to an instantiate a ne) 326.25 325.33 T +(w ser) 489.47 325.33 T +(vice) 513.66 325.33 T +(object f) 180 313.33 T +(or this ser) 211.94 313.33 T +(vice) 256.14 313.33 T +(.) 273.77 313.33 T +(8.) 162 289.33 T +2 F +(Compile and link the shared object.) 180 289.33 T +0 F +( Compile a position-independent shared) 348.38 289.33 T +(object \336le that cde) 180 277.33 T +(v can load on request. The ser) 260.3 277.33 T +(vice\325) 395.67 277.33 T +(s shared object \336le should) 415.17 277.33 T +(contain all of the object code necessar) 180 265.33 T +(y to directly load and utiliz) 350.39 265.33 T +(e the ser) 464.73 265.33 T +(vice) 503.94 265.33 T +(.) 521.57 265.33 T +(This \336le should be copied to the director) 180 253.33 T +(y where the other cde) 357.05 253.33 T +(v ser) 452.91 253.33 T +(vices are) 474.88 253.33 T +(stored.) 180 241.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "2" 10 +%%Page: "3" 11 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. The cde) 455.97 739 T +(vSer) 498.22 739 T +(vice Class) 517 739 T +0 10 Q +(3) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(3.) 159.32 710.67 T +(The cde) 180 710.67 T +(vSer) 232.7 710.67 T +(vice Class) 263.19 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w of the) 108.64 673.33 T +(cde) 72 661.33 T +(vSer) 89.08 661.33 T +(vice Class) 110.86 661.33 T +0 F +0.28 (The cde) 180 673.33 P +0.28 (vSer) 216.11 673.33 P +0.28 (vice C++ class is an abstr) 236.97 673.33 P +0.28 (act base class f) 352.23 673.33 P +0.28 (or all cde) 421.7 673.33 P +0.28 (v ser) 462.54 673.33 P +0.28 (vices) 484.79 673.33 P +0.28 (. This class) 507.42 673.33 P +1.58 (de\336nes the mechanisms that cde) 180 661.33 P +1.58 (v will utiliz) 332.19 661.33 P +1.58 (e to comm) 379.64 661.33 P +1.58 (unicate with y) 429.38 661.33 P +1.58 (our under) 492.91 661.33 P +1.58 (lying) 537.44 661.33 P +0.27 (control system. It is the responsibility of the ser) 180 649.33 P +0.27 (vice de) 389.78 649.33 P +0.27 (v) 421.43 649.33 P +0.27 (eloper to \324) 426.18 649.33 P +3 F +0.27 (\337esh out) 470.63 649.33 P +0 F +0.27 (\325 the vir) 508.71 649.33 P +0.27 (tual) 541.88 649.33 P +1.9 (functions that are de\336ned within this class and to de) 180 637.33 P +1.9 (v) 425.83 637.33 P +1.9 (elop the code necessar) 430.58 637.33 P +1.9 (y to) 539.98 637.33 P +(comm) 180 625.33 T +(unicate with the under) 207.12 625.33 T +(lying control system.) 305.1 625.33 T +1.24 (The pr) 180 608.33 P +1.24 (imar) 210.29 608.33 P +1.24 (y methods that de) 230.03 608.33 P +1.24 (v) 312.93 608.33 P +1.24 (elopers m) 317.68 608.33 P +1.24 (ust concer) 362.72 608.33 P +1.24 (n themselv) 410.34 608.33 P +1.24 (es with are) 459.68 608.33 P +3 F +1.24 (\337ush, poll) 514.52 608.33 P +0.49 (pend,) 180 596.33 P +0 F +0.49 (and) 208.29 596.33 P +3 F +0.49 (getRequestObject.) 228.24 596.33 P +0 F +0.49 (These methods represent the major) 314.33 596.33 P +0.49 (ity of the w) 474.84 596.33 P +0.49 (or) 524.01 596.33 P +0.49 (k that) 533.05 596.33 P +(m) 180 584.33 T +(ust be perf) 188.23 584.33 T +(or) 235.18 584.33 T +(med in de) 244.32 584.33 T +(v) 287.93 584.33 T +(eloping a cde) 292.68 584.33 T +(v ser) 351.86 584.33 T +(vice) 373.83 584.33 T +(.) 391.46 584.33 T +2 F +(The) 72 555.33 T +4 F +(\337ush) 92.56 555.33 T +2 F +( Method) 116.45 555.33 T +0 F +1.07 (The) 180 555.33 P +3 F +1.07 (\337ush) 201.08 555.33 P +0 F +1.07 ( method is responsib) 222.2 555.33 P +1.07 (le f) 317.46 555.33 P +1.07 (or submitting an) 331.57 555.33 P +1.07 (y unsent messages to the de) 404.7 555.33 P +1.07 (vice) 537.59 555.33 P +1.07 (.) 555.22 555.33 P +0.14 (This ma) 180 543.33 P +0.14 (y entail submission of a message using a netw) 215.4 543.33 P +0.14 (or) 422.65 543.33 P +0.14 (k protocol or simply calling a) 431.69 543.33 P +0.5 (statically link) 180 531.33 P +0.5 (ed C function. The) 236.42 531.33 P +3 F +0.5 (cde) 322.93 531.33 P +0.5 (vSystem) 338.75 531.33 P +0 F +0.5 ( object will call this method pr) 377.09 531.33 P +0.5 (ior to each) 510.3 531.33 P +3 F +1 (pend) 180 519.33 P +0 F +1 ( or) 202.24 519.33 P +3 F +1 (poll) 218.69 519.33 P +0 F +1 ( oper) 234.25 519.33 P +1 (ation, or whene) 257.95 519.33 P +1 (v) 328.02 519.33 P +1 (er the) 332.77 519.33 P +3 F +1 (\337ush) 363.12 519.33 P +0 F +1 ( method of the system object is called) 384.24 519.33 P +(directly b) 180 507.33 T +(y the user) 219.81 507.33 T +(.) 263.22 507.33 T +2 F +(The) 72 478.33 T +4 F +(poll) 92.56 478.33 T +2 F +( Method) 110.34 478.33 T +0 F +-0.12 (The) 180 478.33 P +3 F +-0.12 (poll) 199.89 478.33 P +0 F +-0.12 (method is responsib) 218.12 478.33 P +-0.12 (le f) 307.17 478.33 P +-0.12 (or directly polling each of the ph) 320.09 478.33 P +-0.12 (ysical de) 460.28 478.33 P +-0.12 (vices that are) 498.76 478.33 P +1.62 (managed b) 180 466.33 P +1.62 (y the ser) 231.45 466.33 P +1.62 (vice to detect if the) 273.35 466.33 P +1.62 (y require attention \050typically b) 363.03 466.33 P +1.62 (y chec) 499.37 466.33 P +1.62 (king a) 529.7 466.33 P +3.13 (single soc) 180 454.33 P +3.13 (k) 227.39 454.33 P +3.13 (et\051. This method is typically utiliz) 232.19 454.33 P +3.13 (ed to allo) 391.04 454.33 P +3.13 (w the ph) 437.72 454.33 P +3.13 (ysical de) 481.47 454.33 P +3.13 (vice an) 523.19 454.33 P +2.19 (oppor) 180 442.33 P +2.19 (tunity to retur) 205.97 442.33 P +2.19 (n a response to a pre) 268.95 442.33 P +2.19 (viously sent message) 374.08 442.33 P +2.19 (. The) 473.9 442.33 P +3 F +2.19 (cde) 503.84 442.33 P +2.19 (vSystem) 519.66 442.33 P +0 F +2.14 (object will call this method whene) 180 430.33 P +2.14 (v) 338.24 430.33 P +2.14 (er the application calls the) 342.99 430.33 P +3 F +2.14 (poll) 472.08 430.33 P +0 F +2.14 ( method of the) 487.64 430.33 P +2.16 (system object. Most ser) 180 418.33 P +2.16 (vices can route this call directly to their associated) 291.8 418.33 P +3 F +2.16 (pend) 535.76 418.33 P +0 F +(method.) 180 406.33 T +2 F +(The) 72 377.33 T +4 F +(pend) 92.56 377.33 T +2 F +( Method) 116.45 377.33 T +0 F +2.67 (The) 180 377.33 P +3 F +2.67 (pend) 202.68 377.33 P +0 F +2.67 (method allo) 230.37 377.33 P +2.67 (ws the ser) 284.58 377.33 P +2.67 (vice to w) 335.8 377.33 P +2.67 (ait f) 379.89 377.33 P +2.67 (or a per) 398.38 377.33 P +2.67 (iod of time f) 438.33 377.33 P +2.67 (or one of its) 497.74 377.33 P +-0.04 (under) 180 365.33 P +-0.04 (lying de) 205.72 365.33 P +-0.04 (vices to require attention. After w) 239.85 365.33 P +-0.04 (aiting f) 385.14 365.33 P +-0.04 (or a speci\336ed per) 414.26 365.33 P +-0.04 (iod of time) 491.01 365.33 P +-0.04 (, this) 536.91 365.33 P +0.92 (method will retur) 180 353.33 P +0.92 (n) 255.44 353.33 P +3 F +0.92 (CDEV_SUCCESS) 264.7 353.33 P +0 F +0.92 ( if it successfully ser) 346.38 353.33 P +0.92 (viced an) 439.27 353.33 P +0.92 (y of its under) 477.28 353.33 P +0.92 (lying) 537.44 353.33 P +2.14 (de) 180 341.33 P +2.14 (vices) 190.82 341.33 P +2.14 (, or) 213.45 341.33 P +3 F +2.14 (CDEV_TIMEOUT) 234.96 341.33 P +0 F +2.14 ( if no de) 313.3 341.33 P +2.14 (vice became activ) 355.01 341.33 P +2.14 (e dur) 438.52 341.33 P +2.14 (ing that per) 463.6 341.33 P +2.14 (iod. This) 518.07 341.33 P +0.48 (method is typically called b) 180 329.33 P +0.48 (y the) 300.63 329.33 P +3 F +0.48 (cde) 326.04 329.33 P +0.48 (vSystem) 341.86 329.33 P +0 F +0.48 ( object in response to a change in state) 380.2 329.33 P +(of one or more of the ser) 180 317.33 T +(vice\325) 289.8 317.33 T +(s \336le descr) 309.3 317.33 T +(iptors) 357.24 317.33 T +(.) 381.54 317.33 T +2 F +(The) 72 288.33 T +4 F +(g) 72 276.33 T +(etRequestObject) 78.21 276.33 T +2 F +(Method) 72 264.33 T +0 F +1.73 (The) 180 288.33 P +3 F +1.73 (getRequestObject) 201.74 288.33 P +0 F +1.73 ( method is used b) 281.78 288.33 P +1.73 (y the cde) 367.42 288.33 P +1.73 (vSystem object to obtain a ne) 411.16 288.33 P +1.73 (w) 550.78 288.33 P +0.18 (instance of one of the ser) 180 276.33 P +0.18 (vice\325) 293.47 276.33 P +0.18 (s request objects in response to a request made b) 312.97 276.33 P +0.18 (y the) 536.14 276.33 P +1.06 (application. The ser) 180 264.33 P +1.06 (vice ma) 269.67 264.33 P +1.06 (y inter) 304.88 264.33 P +1.06 (nally de\336ne man) 333.42 264.33 P +1.06 (y request object types f) 408.2 264.33 P +1.06 (or use b) 514.96 264.33 P +1.06 (y) 553 264.33 P +2.07 (applications) 180 252.33 P +2.07 (, theref) 232.65 252.33 P +2.07 (ore) 265.55 252.33 P +2.07 (, it is the responsibility of this function to retur) 279.85 252.33 P +2.07 (n the correct) 498.28 252.33 P +0.18 (request object f) 180 240.33 P +0.18 (or the speci\336ed) 248.43 240.33 P +3 F +0.18 (de) 319.55 240.33 P +0.18 (vice) 330.37 240.33 P +0 F +0.18 ( /) 348.15 240.33 P +3 F +0.18 (message) 356.85 240.33 P +0 F +0.18 ( combination. T) 397.42 240.33 P +0.18 (ypically a ser) 464.93 240.33 P +0.18 (vice will) 523.38 240.33 P +(only de\336ne one type of request object and will use it f) 180 228.33 T +(or all requests) 414.27 228.33 T +(.) 476.92 228.33 T +2 F +(Pub) 72 199.33 T +(lic Member) 90.79 199.33 T +(Functions of the) 72 187.33 T +(cde) 72 175.33 T +(vSer) 89.08 175.33 T +(vice Class) 110.86 175.33 T +(Pub) 72 146.33 T +(lic Functions) 90.79 146.33 T +(of the) 72 134.33 T +(cde) 72 122.33 T +(vSer) 89.08 122.33 T +(vice Class) 110.86 122.33 T +(\337ush) 180 146.33 T +3 F +(int \337ush \050v) 279.29 146.33 T +(oid\051;) 324.61 146.33 T +0 F +2.81 (Flushes an) 279.29 129.33 P +2.81 (y pending outbound requests to the appropr) 330.86 129.33 P +2.81 (iate) 541.88 129.33 P +0.08 (ser) 279.43 117.33 P +0.08 (v) 293.62 117.33 P +0.08 (ers) 298.37 117.33 P +0.08 (. This is a pure vir) 312.11 117.33 P +0.08 (tual function that m) 391.8 117.33 P +0.08 (ust be pro) 476.41 117.33 P +0.08 (vided b) 520.89 117.33 P +0.08 (y) 553 117.33 P +(the ser) 279.43 105.33 T +(vice de) 310.3 105.33 T +(v) 341.68 105.33 T +(eloper) 346.43 105.33 T +(.) 373.72 105.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "3" 11 +%%Page: "4" 12 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. The cde) 54 739 T +(vSer) 96.25 739 T +(vice Class) 115.03 739 T +0 10 Q +(4) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(poll) 162 713.33 T +3 F +(int poll \050v) 261.29 713.33 T +(oid\051;) 301.05 713.33 T +0 F +5.89 (Directly polls each of the cde) 261.29 696.33 P +5.89 (vSer) 418.25 696.33 P +5.89 (vice\325) 439.11 696.33 P +5.89 (s under) 458.61 696.33 P +5.89 (lying \336le) 497.99 696.33 P +6.67 (descr) 261.43 684.33 P +6.67 (iptors f) 286.03 684.33 P +6.67 (or activity) 322.41 684.33 P +6.67 (, and deliv) 370.32 684.33 P +6.67 (ers an) 428.99 684.33 P +6.67 (y asynchronous) 463.3 684.33 P +-0.26 (callbac) 261.43 672.33 P +-0.26 (ks that are ready) 292.35 672.33 P +-0.26 (. This is a pure vir) 365.05 672.33 P +-0.26 (tual function that m) 443.05 672.33 P +-0.26 (ust) 526.66 672.33 P +(be pro) 261.43 660.33 T +(vided b) 289.63 660.33 T +(y the ser) 321.67 660.33 T +(vice de) 360.32 660.33 T +(v) 391.7 660.33 T +(eloper) 396.45 660.33 T +(.) 423.74 660.33 T +2 F +(pend) 162 636.33 T +3 F +(int pend \050int fd\051;) 261.29 636.33 T +0 F +0.01 (W) 261.29 619.33 P +0.01 (aits f) 270.33 619.33 P +0.01 (or a def) 291.16 619.33 P +0.01 (ault per) 324.8 619.33 P +0.01 (iod of time f) 358.31 619.33 P +0.01 (or the speci\336ed \336le descr) 409.74 619.33 P +0.01 (iptor) 520.55 619.33 P +1.27 (to ha) 261.43 607.33 P +1.27 (v) 284.74 607.33 P +1.27 (e an I/O e) 289.49 607.33 P +1.27 (v) 336.92 607.33 P +1.27 (ent. If the fd par) 341.67 607.33 P +1.27 (ameter is not pro) 416.69 607.33 P +1.27 (vided, the) 495.37 607.33 P +2.74 (cde) 261.43 595.33 P +2.74 (vSer) 277.25 595.33 P +2.74 (vice object will w) 298.11 595.33 P +2.74 (ait f) 380.09 595.33 P +2.74 (or an I/O e) 398.65 595.33 P +2.74 (v) 453.83 595.33 P +2.74 (ent on an) 458.58 595.33 P +2.74 (y of its) 505.61 595.33 P +0.23 (contained \336le descr) 261.43 583.33 P +0.23 (iptors) 348.19 583.33 P +0.23 (. When an e) 372.49 583.33 P +0.23 (v) 426.81 583.33 P +0.23 (ent occurs on one of the) 431.56 583.33 P +0.41 (\336le descr) 261.43 571.33 P +0.41 (iptors) 302.01 571.33 P +0.41 (, the cde) 326.31 571.33 P +0.41 (vSer) 365.2 571.33 P +0.41 (vice object will call the appropr) 386.06 571.33 P +0.41 (iate) 523.88 571.33 P +1 (function to process the e) 261.43 559.33 P +1 (v) 374.09 559.33 P +1 (ent and dispatch an) 378.84 559.33 P +1 (y asynchronous) 468.97 559.33 P +-0.26 (callbac) 261.43 547.33 P +-0.26 (ks that are ready) 292.35 547.33 P +-0.26 (. This is a pure vir) 365.05 547.33 P +-0.26 (tual function that m) 443.05 547.33 P +-0.26 (ust) 526.66 547.33 P +(be pro) 261.43 535.33 T +(vided b) 289.63 535.33 T +(y the ser) 321.67 535.33 T +(vice de) 360.32 535.33 T +(v) 391.7 535.33 T +(eloper) 396.45 535.33 T +(.) 423.74 535.33 T +2 F +(pend) 162 511.33 T +3 F +(int pend \050doub) 261.29 511.33 T +(le seconds) 325.02 511.33 T +(, int fd\051;) 372.67 511.33 T +0 F +0.11 (Processes all I/O e) 261.29 494.33 P +0.11 (v) 345.23 494.33 P +0.11 (ents that occur on the \336le descr) 349.98 494.33 P +0.11 (iptor dur) 489.72 494.33 P +0.11 (ing) 526.66 494.33 P +0.13 (the speci\336ed per) 261.43 482.33 P +0.13 (iod of time) 335.22 482.33 P +0.13 (. If the fd par) 381.46 482.33 P +0.13 (ameter is not pro) 438.04 482.33 P +0.13 (vided,) 513.32 482.33 P +2.58 (the cde) 261.43 470.33 P +2.58 (vSer) 296.51 470.33 P +2.58 (vice object will w) 317.37 470.33 P +2.58 (ait f) 398.85 470.33 P +2.58 (or I/O e) 417.25 470.33 P +2.58 (v) 455.46 470.33 P +2.58 (ents on all of its) 460.21 470.33 P +0.23 (contained \336le descr) 261.43 458.33 P +0.23 (iptors) 348.19 458.33 P +0.23 (. When an e) 372.49 458.33 P +0.23 (v) 426.81 458.33 P +0.23 (ent occurs on one of the) 431.56 458.33 P +0.41 (\336le descr) 261.43 446.33 P +0.41 (iptors) 302.01 446.33 P +0.41 (, the cde) 326.31 446.33 P +0.41 (vSer) 365.2 446.33 P +0.41 (vice object will call the appropr) 386.06 446.33 P +0.41 (iate) 523.88 446.33 P +0.38 (functions to process the e) 261.43 434.33 P +0.38 (v) 376.59 434.33 P +0.38 (ent and dispatch an) 381.34 434.33 P +0.38 (y asynchronous) 469.59 434.33 P +-0.26 (callbac) 261.43 422.33 P +-0.26 (ks that are ready) 292.35 422.33 P +-0.26 (. This is a pure vir) 365.05 422.33 P +-0.26 (tual function that m) 443.05 422.33 P +-0.26 (ust) 526.66 422.33 P +(be pro) 261.43 410.33 T +(vided b) 289.63 410.33 T +(y the ser) 321.67 410.33 T +(vice de) 360.32 410.33 T +(v) 391.7 410.33 T +(eloper) 396.45 410.33 T +(.) 423.74 410.33 T +2 F +(g) 162 386.33 T +(etRequestObject) 168.21 386.33 T +3 F +(int getRequestObject \050) 261.29 386.33 T +(char *de) 382.57 386.33 T +(v) 419.51 386.33 T +(, char *msg,) 423.71 386.33 T +(cde) 382.57 374.33 T +(vRequestObject* &req\051;) 398.39 374.33 T +0 F +-0.17 (Obtains a pointer to a) 261.29 357.33 P +3 F +-0.17 (cde) 358.84 357.33 P +-0.17 (vRequestObject) 374.66 357.33 P +0 F +-0.17 ( that is speci\336c to this) 445.8 357.33 P +2.06 (ser) 261.43 345.33 P +2.06 (vice and the speci\336ed de) 275.62 345.33 P +2.06 (vice/message combination. This) 393.61 345.33 P +-0.16 (method should only be called b) 261.43 333.33 P +-0.16 (y the) 398.28 333.33 P +3 F +-0.16 (cde) 422.41 333.33 P +-0.16 (vSystem) 438.23 333.33 P +0 F +-0.16 ( object. This is) 476.57 333.33 P +1.93 (a pure vir) 261.43 321.33 P +1.93 (tual function that m) 307.37 321.33 P +1.93 (ust be pro) 397.56 321.33 P +1.93 (vided b) 445.74 321.33 P +1.93 (y the ser) 479.71 321.33 P +1.93 (vice) 522.22 321.33 P +(de) 261.43 309.33 T +(v) 272.25 309.33 T +(eloper) 277 309.33 T +(.) 304.29 309.33 T +2 F +(g) 162 285.33 T +(etNameSer) 168.21 285.33 T +(ver) 220.55 285.33 T +3 F +(int getNameSer) 261.29 285.33 T +(v) 331.06 285.33 T +(er \050cde) 335.81 285.33 T +(vDe) 366.63 285.33 T +(vice* &ser) 384.11 285.33 T +(v) 429.42 285.33 T +(er\051;) 434.17 285.33 T +0 F +1.95 (Obtains a cde) 261.29 268.33 P +1.95 (vDe) 326.58 268.33 P +1.95 (vice object identifying the name ser) 344.06 268.33 P +1.95 (v) 510.27 268.33 P +1.95 (er f) 515.02 268.33 P +1.95 (or) 531.11 268.33 P +0.65 (this ser) 261.43 256.33 P +0.65 (vice) 294.62 256.33 P +0.65 (. A ser) 312.25 256.33 P +0.65 (vice is not required to pro) 342.76 256.33 P +0.65 (vide its o) 458.15 256.33 P +0.65 (wn name) 498.77 256.33 P +0.32 (ser) 261.43 244.33 P +0.32 (v) 275.62 244.33 P +0.32 (er and ma) 280.37 244.33 P +0.32 (y simply set the) 325.74 244.33 P +3 F +0.32 (ser) 398.72 244.33 P +0.32 (v) 412.91 244.33 P +0.32 (er) 417.66 244.33 P +0 F +0.32 ( par) 426.55 244.33 P +0.32 (ameter to) 444 244.33 P +3 F +0.32 (NULL) 489.67 244.33 P +0 F +0.32 (. This) 515.23 244.33 P +1.35 (is a pure vir) 261.43 232.33 P +1.35 (tual function an m) 317.57 232.33 P +1.35 (ust be pro) 400.45 232.33 P +1.35 (vided b) 447.48 232.33 P +1.35 (y the ser) 480.87 232.33 P +1.35 (vice) 522.22 232.33 P +(de) 261.43 220.33 T +(v) 272.25 220.33 T +(eloper) 277 220.33 T +(.) 304.29 220.33 T +2 F +(g) 162 196.33 T +(etCollectionRequest) 168.21 196.33 T +3 F +(int getCollectionRequest \050) 267.67 196.33 T +(char ** de) 396.07 196.33 T +(vices) 439.68 196.33 T +(,) 462.31 196.33 T +(int nDe) 396.07 184.33 T +(vices) 427.45 184.33 T +(, char * msg,) 450.08 184.33 T +(cde) 396.07 172.33 T +(vCollectionRequest * &req\051;) 411.89 172.33 T +0 F +14.35 (This method allo) 261.29 155.33 P +14.35 (ws the caller to obtain a) 363.2 155.33 P +-0.14 (cde) 261.43 143.33 P +-0.14 (vCollectionRequest object that will contain only de) 277.25 143.33 P +-0.14 (vices that) 497.9 143.33 P +4.13 (are associated with the ser) 261.43 131.33 P +4.13 (vice) 397.21 131.33 P +4.13 (. A def) 414.84 131.33 P +4.13 (ault mechanism is) 451.71 131.33 P +1.74 (pro) 261.43 119.33 P +1.74 (vided to suppor) 275.73 119.33 P +1.74 (t this functionality) 347.97 119.33 P +1.74 (, ho) 427.14 119.33 P +1.74 (w) 445.41 119.33 P +1.74 (e) 452.53 119.33 P +1.74 (v) 457.79 119.33 P +1.74 (er) 462.54 119.33 P +1.74 (, the de) 470.93 119.33 P +1.74 (v) 507.46 119.33 P +1.74 (eloper) 512.21 119.33 P +5.42 (ma) 261.43 107.33 P +5.42 (y create a special request object to optimiz) 275.02 107.33 P +5.42 (e these) 501.78 107.33 P +(oper) 261.43 95.33 T +(ations) 281.34 95.33 T +(.) 307.87 95.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "4" 12 +%%Page: "5" 13 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. The cde) 455.97 739 T +(vSer) 498.22 739 T +(vice Class) 517 739 T +0 10 Q +(5) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(g) 180.5 712.83 T +(etFd) 186.71 712.83 T +3 F +(int getFd \050int* &fd, int &n) 279.79 712.83 T +(umFd\051;) 388.08 712.83 T +0 F +0.72 (Retr) 279.79 695.83 P +0.72 (ie) 298.83 695.83 P +0.72 (v) 306.31 695.83 P +0.72 (es a list of \336le descr) 311.06 695.83 P +0.72 (iptors that are contained within the) 402.61 695.83 P +0.93 (cde) 279.93 683.83 P +0.93 (vSer) 295.75 683.83 P +0.93 (vice object. The) 316.61 683.83 P +3 F +0.93 (fd) 392.2 683.83 P +0 F +0.93 ( pointer will be giv) 400.54 683.83 P +0.93 (en the pointer to) 483.45 683.83 P +0.3 (the inter) 279.93 671.83 P +0.3 (nal arr) 316.61 671.83 P +0.3 (a) 345.15 671.83 P +0.3 (y of \336le descr) 350.41 671.83 P +0.3 (iptors) 410.37 671.83 P +0.3 (, and the) 434.67 671.83 P +3 F +0.3 (n) 477.27 671.83 P +0.3 (umFD) 482.73 671.83 P +0 F +0.3 ( par) 509.95 671.83 P +0.3 (ameter) 527.38 671.83 P +0.2 (will be set to the n) 279.93 659.83 P +0.2 (umber of \336le descr) 360.86 659.83 P +0.2 (iptors in the list. A ser) 443.85 659.83 P +0.2 (vice) 540.72 659.83 P +0.31 (that does not use \336le descr) 279.93 647.83 P +0.31 (iptors should set the) 401.13 647.83 P +3 F +0.31 (fd) 494.62 647.83 P +0 F +0.31 ( and) 502.96 647.83 P +3 F +0.31 (n) 525.82 647.83 P +0.31 (umFD) 531.28 647.83 P +0 F +0.83 (par) 279.93 635.83 P +0.83 (ameters to) 294.28 635.83 P +3 F +0.83 (NULL) 345.96 635.83 P +0 F +0.83 ( and) 371.52 635.83 P +3 F +0.83 (0) 395.42 635.83 P +0 F +0.83 (, respectiv) 400.98 635.83 P +0.83 (ely) 447.14 635.83 P +0.83 (. This is a pure vir) 458.92 635.83 P +0.83 (tual) 542.38 635.83 P +(function that m) 279.93 623.83 T +(ust be pro) 345.42 623.83 T +(vided b) 389.74 623.83 T +(y the ser) 421.78 623.83 T +(vice de) 460.43 623.83 T +(v) 491.81 623.83 T +(eloper) 496.56 623.83 T +(.) 523.85 623.83 T +2 F +(registerFd) 180.5 599.83 T +3 F +(int registerFd \050int fd, int opened\051;) 279.79 599.83 T +0 F +2.41 (The ser) 279.79 582.83 P +2.41 (vice de) 316.4 582.83 P +2.41 (v) 350.2 582.83 P +2.41 (eloper ma) 354.95 582.83 P +2.41 (y implement this method to allo) 401.52 582.83 P +2.41 (w) 551.28 582.83 P +-0.11 (e) 279.93 570.83 P +-0.11 (xter) 285.19 570.83 P +-0.11 (nal \336le descr) 302.11 570.83 P +-0.11 (iptors to be added to the list of \336le descr) 358.16 570.83 P +-0.11 (iptors) 534.05 570.83 P +4.2 (in the ser) 279.93 558.83 P +4.2 (vice) 329.77 558.83 P +4.2 (. The) 347.4 558.83 P +3 F +4.2 (fd) 381.38 558.83 P +0 F +4.2 ( par) 389.72 558.83 P +4.2 (ameter should contain the \336le) 411.06 558.83 P +-0.22 (descr) 279.93 546.83 P +-0.22 (iptor) 304.53 546.83 P +-0.22 (, and the) 323.48 546.83 P +3 F +-0.22 (opened) 364.51 546.83 P +0 F +-0.22 ( par) 397.87 546.83 P +-0.22 (ameter should contain 1 to add it) 414.77 546.83 P +(to the list or 0 to remo) 279.93 534.83 T +(v) 376.49 534.83 T +(e it from the list.) 381.24 534.83 T +2 F +(autoErr) 180.5 510.83 T +(orOn) 215.86 510.83 T +3 F +(int autoErrorOn \050v) 279.79 510.83 T +(oid\051;) 359.01 510.83 T +0 F +1.67 (Inf) 279.79 493.83 P +1.67 (or) 290.61 493.83 P +1.67 (ms the cde) 299.75 493.83 P +1.67 (vSer) 351.7 493.83 P +1.67 (vice object that it should use its inter) 372.57 493.83 P +1.67 (nal) 545.16 493.83 P +1.36 (def) 279.93 481.83 P +1.36 (ault error handler to process an) 293.53 481.83 P +1.36 (y error messages that are) 439.13 481.83 P +3.17 (gener) 279.93 469.83 P +3.17 (ated b) 305.4 469.83 P +3.17 (y objects within its control. This is the def) 336.17 469.83 P +3.17 (ault) 542.38 469.83 P +(oper) 279.93 457.83 T +(ating condition f) 299.84 457.83 T +(or the cde) 369.58 457.83 T +(vSer) 413.75 457.83 T +(vice object.) 434.61 457.83 T +2 F +(autoErr) 180.5 433.83 T +(orOff) 215.86 433.83 T +3 F +(int autoErrorOff \050v) 279.79 433.83 T +(oid\051;) 359.01 433.83 T +0 F +1.67 (Inf) 279.79 416.83 P +1.67 (or) 290.61 416.83 P +1.67 (ms the cde) 299.75 416.83 P +1.67 (vSer) 351.7 416.83 P +1.67 (vice object that it should use its inter) 372.57 416.83 P +1.67 (nal) 545.16 416.83 P +1.36 (def) 279.93 404.83 P +1.36 (ault error handler to process an) 293.53 404.83 P +1.36 (y error messages that are) 439.13 404.83 P +3.17 (gener) 279.93 392.83 P +3.17 (ated b) 305.4 392.83 P +3.17 (y objects within its control. This is the def) 336.17 392.83 P +3.17 (ault) 542.38 392.83 P +(oper) 279.93 380.83 T +(ating condition f) 299.84 380.83 T +(or the cde) 369.58 380.83 T +(vSer) 413.75 380.83 T +(vice object.) 434.61 380.83 T +2 F +(repor) 180.5 356.83 T +(tErr) 206.26 356.83 T +(or) 223.84 356.83 T +3 F +(int repor) 279.79 356.83 T +(tError \050) 316.87 356.83 T +(int se) 352.07 356.83 T +(v) 375.67 356.83 T +(er) 380.42 356.83 T +(ity) 389.46 356.83 T +(, char *name) 398.46 356.83 T +(,) 455 356.83 T +(cde) 352.07 344.83 T +(vRequestObject *obj,) 367.89 344.83 T +(char *f) 352.07 332.83 T +(or) 380.67 332.83 T +(matStr) 389.81 332.83 T +(ing,...\051;) 419.41 332.83 T +0 F +4.13 (Emits an error message) 279.79 315.83 P +4.13 (. The se) 398.18 315.83 P +4.13 (v) 442.27 315.83 P +4.13 (er) 447.02 315.83 P +4.13 (ity \336eld indicates the) 456.06 315.83 P +1.09 (se) 279.93 303.83 P +1.09 (v) 290.19 303.83 P +1.09 (er) 294.94 303.83 P +1.09 (ity of the error) 303.98 303.83 P +1.09 (, the name str) 368.43 303.83 P +1.09 (ing identi\336es the object that) 432.98 303.83 P +11.86 (gener) 279.93 291.83 P +11.86 (ated the error) 305.4 291.83 P +11.86 (, the obj par) 388.66 291.83 P +11.86 (ameter is the) 476.97 291.83 P +1.32 (cde) 279.93 279.83 P +1.32 (vRequestObject that w) 295.75 279.83 P +1.32 (as in use when the error occurred,) 398.84 279.83 P +0.71 (and the f) 279.93 267.83 P +0.71 (or) 319.97 267.83 P +0.71 (matStr) 329.11 267.83 P +0.71 (ing and additional par) 358.71 267.83 P +0.71 (ameters \050...\051 should be) 456.34 267.83 P +2.71 (f) 279.93 255.83 P +2.71 (or) 282.41 255.83 P +2.71 (matted in the same manner as the par) 291.55 255.83 P +2.71 (ameters used b) 479.37 255.83 P +2.71 (y) 553.5 255.83 P +(pr) 279.93 243.83 T +(intf) 288.97 243.83 T +(.) 302.01 243.83 T +0.9 (The integer used b) 279.79 226.83 P +0.9 (y se) 365.66 226.83 P +0.9 (v) 384.59 226.83 P +0.9 (er) 389.34 226.83 P +0.9 (ity should ha) 398.38 226.83 P +0.9 (v) 456.11 226.83 P +0.9 (e one of the f) 460.86 226.83 P +0.9 (ollo) 522.53 226.83 P +0.9 (wing) 537.94 226.83 P +(v) 279.93 214.83 T +(alues indicating the se) 284.68 214.83 T +(v) 383.32 214.83 T +(er) 388.07 214.83 T +(ity of the error that has occurred.) 397.11 214.83 T +2 F +(CDEV_SEVERITY_INFO:) 279.79 197.83 T +0 F +(No error) 424.33 197.83 T +(.) 460.5 197.83 T +2 F +(CDEV_SEVERITY_W) 279.79 180.83 T +(ARN:) 376.99 180.83 T +0 F +(An error occurred that should) 423.5 180.83 T +(not impact contin) 423.5 168.83 T +(ued) 498.99 168.83 T +(processing.) 423.5 156.83 T +2 F +(CDEV_SEVERITY_ERR) 279.79 139.83 T +(OR:) 389.06 139.83 T +0 F +(An error occurred and should) 423.5 139.83 T +(be corrected bef) 423.5 127.83 T +(ore) 495.46 127.83 T +(contin) 423.5 115.83 T +(uing.) 450.08 115.83 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "5" 13 +%%Page: "6" 14 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. The cde) 54 739 T +(vSer) 96.25 739 T +(vice Class) 115.03 739 T +0 10 Q +(6) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(CDEV_SEVERITY_SEVERE:) 261.29 713.33 T +0 F +(A se) 405 713.33 T +(v) 424.71 713.33 T +(ere or f) 429.46 713.33 T +(atal error has) 460.84 713.33 T +(occurred and cde) 405 701.33 T +(v cannot) 481.96 701.33 T +(contin) 405 689.33 T +(ue nor) 431.58 689.33 T +(mal e) 460.18 689.33 T +(x) 484.33 689.33 T +(ecution.) 489.03 689.33 T +2 F +(setErr) 162 665.33 T +(orHandler) 190.7 665.33 T +3 F +(v) 261.29 665.33 T +(oid setErrorHandler \050cde) 266.04 665.33 T +(vErrorHandler handler\051;) 374.66 665.33 T +0 F +-0.09 (Used to install a user speci\336ed error handler) 261.29 648.33 P +-0.09 (. This error handler) 455.8 648.33 P +0.68 (will be called when an error occurs if the) 261.43 636.33 P +3 F +0.68 (autoErrorOff) 448.17 636.33 P +0 F +0.68 ( method) 503.19 636.33 P +1.39 (has been used to disab) 261.43 624.33 P +1.39 (le the def) 370.18 624.33 P +1.39 (ault error handler) 413.79 624.33 P +1.39 (. The user) 492.21 624.33 P +(pro) 261.43 612.33 T +(vided error handler should ha) 275.73 612.33 T +(v) 405.59 612.33 T +(e the f) 410.34 612.33 T +(ollo) 437.84 612.33 T +(wing prototype:) 453.25 612.33 T +(v) 261.29 595.33 T +(oid handler \050int se) 266.04 595.33 T +(v) 345.22 595.33 T +(er) 349.97 595.33 T +(ity) 359.01 595.33 T +(, char *te) 368.01 595.33 T +(xt, cde) 407.73 595.33 T +(vRequestObject *obj\051;) 436.89 595.33 T +4.89 (The) 261.29 578.33 P +3 F +4.89 (se) 286.19 578.33 P +4.89 (v) 296.45 578.33 P +4.89 (er) 301.2 578.33 P +4.89 (ity) 310.24 578.33 P +0 F +4.89 ( par) 320.24 578.33 P +4.89 (ameter will contain one of the integers) 342.26 578.33 P +0.81 (speci\336ed in the) 261.43 566.33 P +3 F +0.81 (repor) 333.34 566.33 P +0.81 (tError) 357.08 566.33 P +0 F +0.81 (documentation, the) 385.67 566.33 P +3 F +0.81 (te) 475.12 566.33 P +0.81 (xt) 483.16 566.33 P +0 F +0.81 ( par) 490.94 566.33 P +0.81 (ameter) 508.88 566.33 P +2.11 (will contain the te) 261.43 554.33 P +2.11 (xt of the error) 344.17 554.33 P +2.11 (, and the) 409.48 554.33 P +3 F +2.11 (obj) 457.52 554.33 P +0 F +2.11 ( par) 470.86 554.33 P +2.11 (ameter will) 490.11 554.33 P +0.37 (contain the cde) 261.43 542.33 P +0.37 (vRequestObject that w) 329.69 542.33 P +0.37 (as in use when the error) 430.88 542.33 P +(occurred.) 261.43 530.33 T +2 F +(setThreshold) 162 506.33 T +3 F +(v) 261.29 506.33 T +(oid setThreshold \050int errorThreshold\051;) 266.04 506.33 T +0 F +0.77 (Used to specify the le) 261.29 489.33 P +0.77 (v) 359.66 489.33 P +0.77 (el of se) 364.41 489.33 P +0.77 (v) 397.88 489.33 P +0.77 (er) 402.63 489.33 P +0.77 (ity at which errors should be) 411.67 489.33 P +2.4 (submitted to the error handler) 261.43 477.33 P +2.4 (. The v) 401.71 477.33 P +2.4 (alue of) 436.83 477.33 P +3 F +2.4 (errorThreshold) 474.43 477.33 P +0 F +0.23 (should be one of the se) 261.43 465.33 P +0.23 (v) 366.26 465.33 P +0.23 (er) 371.01 465.33 P +0.23 (ity le) 380.05 465.33 P +0.23 (v) 400.54 465.33 P +0.23 (els speci\336ed in the) 405.29 465.33 P +3 F +0.23 (repor) 491.26 465.33 P +0.23 (tError) 515 465.33 P +0 F +(method.) 261.43 453.33 T +2 F +(name) 162 429.33 T +3 F +(char *name \050v) 261.29 429.33 T +(oid\051 const;) 323.28 429.33 T +0 F +3.89 (Retr) 261.29 412.33 P +3.89 (ie) 280.33 412.33 P +3.89 (v) 287.81 412.33 P +3.89 (es the name of the ser) 292.56 412.33 P +3.89 (vice) 411.79 412.33 P +3.89 (. This method is used) 429.42 412.33 P +1.52 (e) 261.43 400.33 P +1.52 (xtensiv) 266.69 400.33 P +1.52 (ely to deter) 297.56 400.33 P +1.52 (mine the ser) 350.33 400.33 P +1.52 (vice that under) 408.7 400.33 P +1.52 (lies a speci\336c) 477.49 400.33 P +3 F +2.38 (cde) 261.43 388.33 P +2.38 (vRequestObject) 277.25 388.33 P +0 F +2.38 ( object. If not o) 348.39 388.33 P +2.38 (v) 423.37 388.33 P +2.38 (er-r) 428.12 388.33 P +2.38 (idden b) 443.82 388.33 P +2.38 (y the ser) 478.8 388.33 P +2.38 (vice) 522.22 388.33 P +(de) 261.43 376.33 T +(v) 272.25 376.33 T +(eloper) 277 376.33 T +(, this method will retur) 304.29 376.33 T +(n the str) 401.79 376.33 T +(ing \322cde) 438.07 376.33 T +(vSer) 473.34 376.33 T +(vice\323.) 494.2 376.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "6" 14 +%%Page: "7" 15 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. The cde) 426.72 739 T +(vRequestObject Class) 468.97 739 T +0 10 Q +(7) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(4.) 159.32 710.67 T +(The) 180 710.67 T +4 F +(cde) 208.78 710.67 T +(vRequestObject) 232.7 710.67 T +2 F +(Class) 343.17 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w of the) 108.64 673.33 T +(cde) 72 661.33 T +(vRequest) 89.08 661.33 T +(Object Class) 72 649.33 T +0 F +2.21 (The) 180 673.33 P +3 F +2.21 (cde) 202.22 673.33 P +2.21 (vRequestObject) 218.04 673.33 P +0 F +2.21 ( C++ class is the application\325) 289.18 673.33 P +2.21 (s interf) 426.46 673.33 P +2.21 (ace to the under) 458.38 673.33 P +2.21 (lying) 537.44 673.33 P +0.31 (ser) 180 661.33 P +0.31 (vice) 194.19 661.33 P +0.31 (. Each ser) 211.82 661.33 P +0.31 (vice m) 257.77 661.33 P +0.31 (ust pro) 286.88 661.33 P +0.31 (vide a ser) 317.61 661.33 P +0.31 (vice speci\336c request object that applications) 361.89 661.33 P +(ma) 180 649.33 T +(y use to send messages to the ser) 193.59 649.33 T +(vice) 346.19 649.33 T +(.) 363.82 649.33 T +1.14 (The message associated with a) 180 632.33 P +3 F +1.14 (cde) 328.56 632.33 P +1.14 (vRequestObject) 344.38 632.33 P +0 F +1.14 ( ma) 415.52 632.33 P +1.14 (y be sent to a de) 433.04 632.33 P +1.14 (vice using) 512.4 632.33 P +3.07 (one of the three send member functions) 180 620.33 P +3.07 (, these are:) 375.01 620.33 P +4 F +3.07 (send, sendNoBloc) 437.02 620.33 P +3.07 (k) 527.13 620.33 P +3 F +3.07 (, and) 532.69 620.33 P +4 F +1.93 (sendCallbac) 180 608.33 P +1.93 (k) 238.71 608.33 P +0 F +1.93 (. The syntax and functionality of these methods is descr) 244.27 608.33 P +1.93 (ibed in the) 508 608.33 P +0.71 (section belo) 180 596.33 P +0.71 (w) 233.92 596.33 P +0.71 (. The major) 240.54 596.33 P +0.71 (ity of w) 292.67 596.33 P +0.71 (or) 325.11 596.33 P +0.71 (k in the de) 334.15 596.33 P +0.71 (v) 382.12 596.33 P +0.71 (elopment of a ser) 386.87 596.33 P +0.71 (vice speci\336c request) 466.55 596.33 P +(object is in the de) 180 584.33 T +(v) 257.52 584.33 T +(elopment of these three methods) 262.27 584.33 T +(.) 408.31 584.33 T +2 F +(Pub) 72 555.33 T +(lic Member) 90.79 555.33 T +(Functions of the) 72 543.33 T +(cde) 72 531.33 T +(vRequest) 89.08 531.33 T +(Object Class) 72 519.33 T +(attac) 180 555.33 T +(hRef) 203.24 555.33 T +3 F +3.5 (static cde) 279.29 555.33 P +3.5 (vRequestObject& attachRef \050char *de) 324.73 555.33 P +3.5 (vice) 501.68 555.33 P +3.5 (, char *) 519.31 555.33 P +(msg\051;) 279.43 543.33 T +0 F +5.63 (Obtains a ref) 279.29 526.33 P +5.63 (erence to a) 347.49 526.33 P +3 F +5.63 (cde) 417.18 526.33 P +5.63 (vRequestObject) 433.01 526.33 P +0 F +5.63 ( object b) 504.14 526.33 P +5.63 (y) 553 526.33 P +0.64 (specifying the name of the de) 279.43 514.33 P +0.64 (vice and the message str) 412.94 514.33 P +0.64 (ing. By) 526.79 514.33 P +4.63 (def) 279.43 502.33 P +4.63 (ault, the ne) 293.03 502.33 P +4.63 (w object will be managed b) 351.57 502.33 P +4.63 (y the def) 494.56 502.33 P +4.63 (ault) 541.88 502.33 P +3 F +(cde) 279.43 490.33 T +(vSystem) 295.25 490.33 T +0 F +(.) 333.59 490.33 T +2 F +(attac) 180 466.33 T +(hRef) 203.24 466.33 T +3 F +0.01 (static cde) 279.29 466.33 P +0.01 (vRequestObject& attachRef \050cde) 321.23 466.33 P +0.01 (vDe) 466.57 466.33 P +0.01 (vice &de) 484.05 466.33 P +0.01 (v) 522.11 466.33 P +0.01 (, char *) 526.31 466.33 P +(msg\051;) 279.43 454.33 T +0 F +5.63 (Obtains a ref) 279.29 437.33 P +5.63 (erence to a) 347.49 437.33 P +3 F +5.63 (cde) 417.18 437.33 P +5.63 (vRequestObject) 433.01 437.33 P +0 F +5.63 ( object b) 504.14 437.33 P +5.63 (y) 553 437.33 P +0.49 (pro) 279.43 425.33 P +0.49 (viding a ref) 293.73 425.33 P +0.49 (erence to the associated) 343.32 425.33 P +3 F +0.49 (cde) 457.02 425.33 P +0.49 (vDe) 472.84 425.33 P +0.49 (vice) 490.32 425.33 P +0 F +0.49 ( object and) 508.1 425.33 P +-0.07 (the message str) 279.43 413.33 P +-0.07 (ing. By def) 350.59 413.33 P +-0.07 (ault, the ne) 397.41 413.33 P +-0.07 (w object will be managed) 446.55 413.33 P +(b) 279.43 401.33 T +(y the def) 284.79 401.33 T +(ault) 322.85 401.33 T +3 F +(cde) 341.75 401.33 T +(vSystem) 357.57 401.33 T +0 F +(.) 395.91 401.33 T +2 F +(attac) 180 377.33 T +(hPtr) 203.24 377.33 T +3 F +-0.17 (static cde) 279.29 377.33 P +-0.17 (vRequestObject* attachPtr \050char *de) 321.06 377.33 P +-0.17 (vice) 481.42 377.33 P +-0.17 (, char * msg\051;) 499.05 377.33 P +0 F +2.04 (Obtains a pointer to a) 279.29 360.33 P +3 F +2.04 (cde) 387.87 360.33 P +2.04 (vRequestObject) 403.69 360.33 P +0 F +2.04 ( b) 474.83 360.33 P +2.04 (y specifying the) 485 360.33 P +-0.24 (name of the de) 279.43 348.33 P +-0.24 (vice and the message str) 345.13 348.33 P +-0.24 (ing. By def) 455.5 348.33 P +-0.24 (ault, the ne) 501.97 348.33 P +-0.24 (w) 550.78 348.33 P +(object will be managed b) 279.43 336.33 T +(y the def) 389.28 336.33 T +(ault) 427.34 336.33 T +3 F +(cde) 446.24 336.33 T +(vSystem) 462.06 336.33 T +0 F +(.) 500.4 336.33 T +2 F +(attac) 180 312.33 T +(hPtr) 203.24 312.33 T +3 F +0.93 (static cde) 279.29 312.33 P +0.93 (vRequestObject* attachPtr \050cde) 322.16 312.33 P +0.93 (vDe) 463.79 312.33 P +0.93 (vice &de) 481.27 312.33 P +0.93 (v) 520.25 312.33 P +0.93 (, char *) 524.45 312.33 P +(msg\051;) 279.43 300.33 T +0 F +3.59 (Obtains a pointer to a) 279.29 283.33 P +3 F +3.59 (cde) 395.6 283.33 P +3.59 (vRequestObject) 411.42 283.33 P +0 F +3.59 ( b) 482.56 283.33 P +3.59 (y pro) 494.29 283.33 P +3.59 (viding a) 519.96 283.33 P +5.54 (ref) 279.43 271.33 P +5.54 (erence to the associated) 290.8 271.33 P +3 F +5.54 (cde) 424.7 271.33 P +5.54 (vDe) 440.52 271.33 P +5.54 (vice) 458 271.33 P +0 F +5.54 ( object and the) 475.78 271.33 P +0.29 (message str) 279.43 259.33 P +0.29 (ing. By def) 334.33 259.33 P +0.29 (ault, the ne) 381.86 259.33 P +0.29 (w object will be managed b) 431.71 259.33 P +0.29 (y) 553 259.33 P +(the def) 279.43 247.33 T +(ault) 309.71 247.33 T +3 F +(cde) 328.61 247.33 T +(vSystem) 344.43 247.33 T +0 F +(.) 382.77 247.33 T +2 F +(detac) 180 223.33 T +(h) 206.02 223.33 T +3 F +(static v) 279.29 223.33 T +(oid detach \050cde) 310.16 223.33 T +(vRequestObject& de) 378.23 223.33 T +(v\051;) 469.64 223.33 T +0 F +3.92 (Remo) 279.29 206.33 P +3.92 (v) 305.81 206.33 P +3.92 (es a ref) 310.56 206.33 P +3.92 (erenced cde) 351.44 206.33 P +3.92 (vRequestObject object from its) 410.09 206.33 P +2.47 (associated cde) 279.43 194.33 P +2.47 (vSystem object. Ordinar) 348.3 194.33 P +2.47 (y applications should) 460.24 194.33 P +(ne) 279.43 182.33 T +(v) 290.25 182.33 T +(er use this command.) 295 182.33 T +2 F +(detac) 180 158.33 T +(h) 206.02 158.33 T +3 F +(static v) 279.29 158.33 T +(oid detach \050cde) 310.16 158.33 T +(vRequestObject* de) 378.23 158.33 T +(v\051;) 466.86 158.33 T +0 F +0.55 (Detaches the cde) 279.29 141.33 P +0.55 (vRequestObject object speci\336ed b) 357.9 141.33 P +0.55 (y de) 510.52 141.33 P +0.55 (v from) 529.67 141.33 P +-0.07 (its associated cde) 279.43 129.33 P +-0.07 (vSystem object. Ordinar) 358.47 129.33 P +-0.07 (y applications should) 465.32 129.33 P +(ne) 279.43 117.33 T +(v) 290.25 117.33 T +(er use this command.) 295 117.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "7" 15 +%%Page: "8" 16 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. The cde) 54 739 T +(vRequestObject Class) 96.25 739 T +0 10 Q +(8) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(messa) 162 713.33 T +(g) 193.03 713.33 T +(e) 199.24 713.33 T +3 F +(char *message \050v) 261.29 713.33 T +(oid\051 const;) 338.84 713.33 T +0 F +3.82 (Retr) 261.29 696.33 P +3.82 (ie) 280.33 696.33 P +3.82 (v) 287.81 696.33 P +3.82 (es the message str) 292.56 696.33 P +3.82 (ing that is associated with this) 388.64 696.33 P +(cde) 261.43 684.33 T +(vRequestObject.) 277.25 684.33 T +2 F +(de) 162 660.33 T +(vice) 173.52 660.33 T +3 F +(cde) 261.29 660.33 T +(vDe) 277.11 660.33 T +(vice &de) 294.59 660.33 T +(vice \050v) 332.64 660.33 T +(oid\051 const;) 361.28 660.33 T +0 F +5.41 (Retr) 261.29 643.33 P +5.41 (ie) 280.33 643.33 P +5.41 (v) 287.81 643.33 P +5.41 (es a ref) 292.56 643.33 P +5.41 (erence to the cde) 336.42 643.33 P +5.41 (vDe) 429.6 643.33 P +5.41 (vice object that is) 447.08 643.33 P +(associated with this cde) 261.43 631.33 T +(vRequestObject.) 366.73 631.33 T +2 F +(system) 162 607.33 T +3 F +(cde) 261.29 607.33 T +(vSystem& system \050v) 277.11 607.33 T +(oid\051 const;) 367.43 607.33 T +0 F +0.14 (Retr) 261.29 590.33 P +0.14 (ie) 280.33 590.33 P +0.14 (v) 287.81 590.33 P +0.14 (es a ref) 292.56 590.33 P +0.14 (erence to the under) 325.88 590.33 P +0.14 (lying cde) 413.17 590.33 P +0.14 (vSystem object that) 452.46 590.33 P +(manages this cde) 261.43 578.33 T +(vRequestObject.) 339.5 578.33 T +2 F +(ser) 162 554.33 T +(vice) 177.11 554.33 T +3 F +(cde) 261.29 554.33 T +(vSer) 277.11 554.33 T +(vice& ser) 297.97 554.33 T +(vice \050v) 339.39 554.33 T +(oid\051 const;) 368.03 554.33 T +0 F +0.1 (Retr) 261.29 537.33 P +0.1 (ie) 280.33 537.33 P +0.1 (v) 287.81 537.33 P +0.1 (es a ref) 292.56 537.33 P +0.1 (erence to the under) 325.81 537.33 P +0.1 (lying cde) 412.98 537.33 P +0.1 (vSer) 452.24 537.33 P +0.1 (vice object that) 473.1 537.33 P +(this cde) 261.43 525.33 T +(vRequestObject is attached to) 295.59 525.33 T +(.) 428.59 525.33 T +2 F +(g) 162 501.33 T +(etState) 168.21 501.33 T +3 F +(int getState \050v) 261.29 501.33 T +(oid\051;) 322.74 501.33 T +0 F +-0.15 (Obtains the state of the under) 261.29 484.33 P +-0.15 (lying de) 392.42 484.33 P +-0.15 (vice) 426.43 484.33 P +-0.15 (. This function retur) 444.06 484.33 P +-0.15 (ns) 529.44 484.33 P +(one of the f) 261.43 472.33 T +(ollo) 311.17 472.33 T +(wing v) 326.58 472.33 T +(alues as de\336ned in) 354.67 472.33 T +3 F +(cde) 440.83 472.33 T +(vErrCode) 456.65 472.33 T +(.h) 498.73 472.33 T +0 F +(.) 507.07 472.33 T +2 F +(CDEV_ST) 261.29 455.33 T +(A) 306.51 455.33 T +(TE_CONNECTED:) 312.83 455.33 T +0 F +(Object is connected.) 426 455.33 T +2 F +(CDEV_ST) 261.29 438.33 T +(A) 306.51 438.33 T +(TE_NO) 312.83 438.33 T +(TCONNECTED:) 345.77 438.33 T +0 F +(Object is not connected.) 426 438.33 T +2 F +(CDEV_ST) 261.29 421.33 T +(A) 306.51 421.33 T +(TE_INV) 312.83 421.33 T +(ALID:) 347.04 421.33 T +0 F +(Object is in) 426 421.33 T +(v) 475.26 421.33 T +(alid.) 480.01 421.33 T +3.16 (The ser) 261.29 404.33 P +3.16 (vice de) 298.65 404.33 P +3.16 (v) 333.2 404.33 P +3.16 (eloper is responsib) 337.95 404.33 P +3.16 (le f) 428 404.33 P +3.16 (or implementing this) 444.2 404.33 P +(function correctly in the ser) 261.43 392.33 T +(vice related cde) 381.22 392.33 T +(vRequestObject.) 450.95 392.33 T +2 F +(g) 162 368.33 T +(etAccess) 168.21 368.33 T +3 F +(int getAccess \050v) 261.29 368.33 T +(oid\051;) 331.62 368.33 T +0 F +5.3 (Obtains access control inf) 261.29 351.33 P +5.3 (or) 391.39 351.33 P +5.3 (mation about the under) 400.53 351.33 P +5.3 (lying) 519.44 351.33 P +2.27 (de) 261.43 339.33 P +2.27 (vice) 272.25 339.33 P +2.27 (. This function retur) 289.88 339.33 P +2.27 (ns one of the f) 382.54 339.33 P +2.27 (ollo) 454.71 339.33 P +2.27 (wing v) 470.12 339.33 P +2.27 (alues as) 500.49 339.33 P +(de\336ned in cde) 261.43 327.33 T +(vErrCode) 323.39 327.33 T +(.h.) 365.47 327.33 T +2 F +(CDEV_A) 261.29 310.33 T +(CCESS_NONE:) 301.45 310.33 T +0 F +(No access to attr) 405.83 310.33 T +(ib) 481.01 310.33 T +(ute) 488.59 310.33 T +(.) 502.34 310.33 T +2 F +(CDEV_A) 261.29 293.33 T +(CCESS_READONL) 301.45 293.33 T +(Y) 389.7 293.33 T +(:) 395.87 293.33 T +0 F +(Read-only access) 405.83 293.33 T +(.) 485.15 293.33 T +2 F +(CDEV_A) 261.29 276.33 T +(CCESS_WRITE:) 301.45 276.33 T +0 F +(Read-wr) 405.83 276.33 T +(ite access) 443.76 276.33 T +(.) 488.07 276.33 T +3.16 (The ser) 261.29 259.33 P +3.16 (vice de) 298.65 259.33 P +3.16 (v) 333.2 259.33 P +3.16 (eloper is responsib) 337.95 259.33 P +3.16 (le f) 428 259.33 P +3.16 (or implementing this) 444.2 259.33 P +(function correctly in the ser) 261.43 247.33 T +(vice related cde) 381.22 247.33 T +(vRequestObject.) 450.95 247.33 T +2 F +(setConte) 162 223.33 T +(xt) 204.63 223.33 T +3 F +(int setConte) 261.29 223.33 T +(xt \050cde) 314.35 223.33 T +(vData& cxt\051;) 344.06 223.33 T +0 F +0.17 (Used to inser) 261.29 206.33 P +0.17 (t a cde) 320.93 206.33 P +0.17 (vData object containing tagged v) 350.98 206.33 P +0.17 (alues that) 496.47 206.33 P +0.53 (control optional beha) 261.43 194.33 P +0.53 (vior of the under) 355.12 194.33 P +0.53 (lying de) 429.11 194.33 P +0.53 (vice) 463.8 194.33 P +0.53 (. The conte) 481.43 194.33 P +0.53 (xt) 532.22 194.33 P +4.55 (is often used to specify which proper) 261.43 182.33 P +4.55 (ties \050v) 450.86 182.33 P +4.55 (alue) 481.83 182.33 P +4.55 (, status) 500.58 182.33 P +4.55 (,) 537.22 182.33 P +0.41 (se) 261.43 170.33 P +0.41 (v) 271.69 170.33 P +0.41 (er) 276.44 170.33 P +0.41 (ity\051 a de) 285.48 170.33 P +0.41 (vice retur) 321.56 170.33 P +0.41 (ns in response to a \322get\323 message) 363.34 170.33 P +0.41 (. The) 516.8 170.33 P +2.61 (ser) 261.43 158.33 P +2.61 (vice de) 275.62 158.33 P +2.61 (v) 309.61 158.33 P +2.61 (eloper ma) 314.36 158.33 P +2.61 (y o) 361.13 158.33 P +2.61 (v) 376.93 158.33 P +2.61 (err) 381.68 158.33 P +2.61 (ide the def) 394.05 158.33 P +2.61 (ault beha) 445.66 158.33 P +2.61 (vior of this) 489.21 158.33 P +4.94 (method to better accommodate the requirements of the) 261.43 146.33 P +(ser) 261.43 134.33 T +(vice) 275.62 134.33 T +(.) 293.25 134.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "8" 16 +%%Page: "9" 17 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. The cde) 426.72 739 T +(vRequestObject Class) 468.97 739 T +0 10 Q +(9) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(g) 180 713.33 T +(etConte) 186.21 713.33 T +(xt) 223.28 713.33 T +3 F +(cde) 279.29 713.33 T +(vData & getConte) 295.11 713.33 T +(xt \050v) 373.74 713.33 T +(oid\051;) 392.38 713.33 T +0 F +0.63 (Retr) 279.29 696.33 P +0.63 (ie) 298.33 696.33 P +0.63 (v) 305.81 696.33 P +0.63 (es a ref) 310.56 696.33 P +0.63 (erence to the cde) 344.87 696.33 P +0.63 (vData object that contains the) 423.73 696.33 P +6.79 (conte) 279.43 684.33 P +6.79 (xt f) 303.59 684.33 P +6.79 (or a speci\336c cde) 323.42 684.33 P +6.79 (vRequestObject. The ser) 415.74 684.33 P +6.79 (vice) 540.22 684.33 P +0.93 (de) 279.43 672.33 P +0.93 (v) 290.25 672.33 P +0.93 (eloper ma) 295 672.33 P +0.93 (y o) 340.09 672.33 P +0.93 (v) 354.21 672.33 P +0.93 (err) 358.96 672.33 P +0.93 (ide the def) 371.33 672.33 P +0.93 (ault beha) 419.59 672.33 P +0.93 (vior of this method to) 461.46 672.33 P +(better accommodate the requirements of the ser) 279.43 660.33 T +(vice) 493.16 660.33 T +(.) 510.79 660.33 T +2 F +(g) 180 636.33 T +(etPriv) 186.21 636.33 T +(ate) 213.8 636.33 T +3 F +(v) 279.29 636.33 T +(oid * getPr) 284.04 636.33 T +(iv) 330.88 636.33 T +(ate \050v) 337.85 636.33 T +(oid\051;) 362.61 636.33 T +0 F +2.09 (Retr) 279.29 619.33 P +2.09 (ie) 298.33 619.33 P +2.09 (v) 305.81 619.33 P +2.09 (es a pointer to a data object that w) 310.56 619.33 P +2.09 (as placed in this) 480.02 619.33 P +(object using the setPr) 279.43 607.33 T +(iv) 375.74 607.33 T +(ate function.) 382.71 607.33 T +2 F +(setPriv) 180 583.33 T +(ate) 213.15 583.33 T +3 F +(v) 279.29 583.33 T +(oid setPr) 284.04 583.33 T +(iv) 323.65 583.33 T +(ate \050v) 330.62 583.33 T +(oid * data\051;) 355.38 583.33 T +0 F +9.56 (Associates a user speci\336ed data object with this) 279.29 566.33 P +3 F +1.78 (cde) 279.43 554.33 P +1.78 (vRequestObject) 295.25 554.33 P +0 F +1.78 (. The pointer can be retr) 366.39 554.33 P +1.78 (ie) 482.17 554.33 P +1.78 (v) 489.65 554.33 P +1.78 (ed later using) 494.4 554.33 P +(the) 279.43 542.33 T +3 F +(getPr) 296.11 542.33 T +(iv) 320.16 542.33 T +(ate) 327.13 542.33 T +0 F +( method.) 341.03 542.33 T +2 F +(send) 180 518.33 T +3 F +(int send \050cde) 279.29 518.33 T +(vData &out, cde) 336.24 518.33 T +(vData& result\051;) 407.09 518.33 T +(int send \050cde) 279.29 506.33 T +(vData *out, cde) 336.24 506.33 T +(vData& result\051;) 404.31 506.33 T +(int send \050cde) 279.29 494.33 T +(vData &out, cde) 336.24 494.33 T +(vData* result\051;) 407.09 494.33 T +(int send \050cde) 279.29 482.33 T +(vData *out, cde) 336.24 482.33 T +(vData* result\051;) 404.31 482.33 T +0 F +1.74 (The send function is the standard method f) 279.29 465.33 P +1.74 (or synchronously) 480.68 465.33 P +5.38 (comm) 279.43 453.33 P +5.38 (unicating with a de) 306.55 453.33 P +5.38 (vice) 405.21 453.33 P +5.38 (. The) 422.84 453.33 P +3 F +5.38 (out) 459.16 453.33 P +0 F +5.38 (cde) 481.22 453.33 P +5.38 (vData object) 497.04 453.33 P +3.44 (contains an) 279.43 441.33 P +3.44 (y proper) 333.86 441.33 P +3.44 (ty v) 374.38 441.33 P +3.44 (alues that the de) 393.14 441.33 P +3.44 (vice will need to) 477.1 441.33 P +1.53 (perf) 279.43 429.33 P +1.53 (or) 296.36 429.33 P +1.53 (m the task. The) 305.5 429.33 P +3 F +1.53 (result) 383.34 429.33 P +0 F +1.53 ( cde) 407.79 429.33 P +1.53 (vData object will contain the) 427.92 429.33 P +3.82 (output proper) 279.43 417.33 P +3.82 (ties that resulted from the call. The ser) 343.13 417.33 P +3.82 (vice) 540.22 417.33 P +1.67 (de) 279.43 405.33 P +1.67 (v) 290.25 405.33 P +1.67 (eloper is responsib) 295 405.33 P +1.67 (le f) 382.07 405.33 P +1.67 (or implementing this method in the) 396.79 405.33 P +1.09 (ser) 279.43 393.33 P +1.09 (vice speci\336ed cde) 293.62 393.33 P +1.09 (vRequestObject. This function will retur) 374.43 393.33 P +1.09 (n) 552.44 393.33 P +(one of the error code de\336ned in cde) 279.43 381.33 T +(vErrCode) 437 381.33 T +(.h.) 479.08 381.33 T +3 9 Q +(Figure 1: Retur) 180 365 T +(n codes gener) 242.75 365 T +(ated b) 299.69 365 T +(y the send method.) 324.53 365 T +180 81 558 720 C +180 93.02 558 362 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.28 96.88 559.85 354.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +180.31 100.67 554.27 359.57 R +7 X +V +0 X +N +185.56 102.98 546.84 355.95 R +7 X +V +5 10 Q +0 X +(CDEV_WARNING:) 185.56 349.29 T +6 F +( The failure was non-critical.) 293.56 349.29 T +5 F +(CDEV_SUCCESS:) 185.56 337.29 T +6 F +( The message was processed successfully.) 293.56 337.29 T +5 F +(CDEV_ERROR:) 185.56 325.29 T +6 F +( Failed to process message.) 293.56 325.29 T +5 F +(CDEV_INVALIDOBJ:) 185.56 313.29 T +6 F +( Invalid cdev request object used.) 293.56 313.29 T +5 F +(CDEV_INVALIDARG:) 185.56 301.29 T +6 F +( Invalid argument passed to cdev call.) 299.56 301.29 T +5 F +(CDEV_INVALIDSVC:) 185.56 289.29 T +6 F +( Wrong service during dynamic loading.) 293.56 289.29 T +5 F +(CDEV_INVALIDOP:) 185.56 277.29 T +6 F +(The operation is not supported.) 305.56 277.29 T +5 F +(CDEV_NOTCONNECTED:) 185.56 265.29 T +6 F +(Not connected to low level network) 305.56 265.29 T +( service.) 185.56 253.29 T +5 F +(CDEV_IOFAILED:) 185.56 241.29 T +6 F +( Low level network service IO failed.) 299.56 241.29 T +5 F +(CDEV_CONFLICT:) 185.56 229.29 T +6 F +( Conflicts of data types or tags.) 299.56 229.29 T +5 F +(CDEV_NOTFOUND:) 185.56 217.29 T +6 F +( Cannot find specified data in cdevData.) 299.56 217.29 T +5 F +(CDEV_TIMEOUT:) 185.56 205.29 T +6 F +( Time out.) 299.56 205.29 T +5 F +(CDEV_CONVERT:) 185.56 193.29 T +6 F +( cdevData conversion error.) 299.56 193.29 T +5 F +(CDEV_OUTOFRANGE:) 185.56 181.29 T +6 F +(Value out of range for device attribute.) 305.56 181.29 T +5 F +(CDEV_NOACCESS:) 185.56 169.29 T +6 F +(Insufficient access to perform request.) 305.56 169.29 T +5 F +(CDEV_ACCESSCHANGED:) 185.56 157.29 T +6 F +(Change in access permission of device.) 305.56 157.29 T +5 F +(CDEV_DISCONNECTED:) 185.56 145.29 T +6 F +(The service has lost contact with the) 305.56 145.29 T +( device.) 185.56 133.29 T +5 F +(CDEV_RECONNECTED:) 185.56 121.29 T +6 F +( The service has regained contact with) 299.56 121.29 T +( the device.) 185.56 109.29 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "9" 17 +%%Page: "10" 18 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. The cde) 54 739 T +(vRequestObject Class) 96.25 739 T +0 10 Q +(10) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(sendNoBloc) 162 717.33 T +(k) 220.14 717.33 T +3 F +(int sendNoBloc) 261.29 717.33 T +(k \050cde) 328.34 717.33 T +(vData &out, cde) 355.27 717.33 T +(vData &result\051;) 426.12 717.33 T +(int sendNoBloc) 261.29 705.33 T +(k \050cde) 328.34 705.33 T +(vData *out, cde) 355.27 705.33 T +(vData &result\051;) 423.34 705.33 T +(int sendNoBloc) 261.29 693.33 T +(k \050cde) 328.34 693.33 T +(vData &out, cde) 355.27 693.33 T +(vData *result\051;) 426.12 693.33 T +(int sendNoBloc) 261.29 681.33 T +(k \050cde) 328.34 681.33 T +(vData *out, cde) 355.27 681.33 T +(vData *result\051;) 423.34 681.33 T +0 F +3.34 (The) 261.29 664.33 P +3 F +3.34 (sendNoBloc) 284.63 664.33 P +3.34 (k) 338.34 664.33 P +0 F +3.34 ( method uses the same par) 343.34 664.33 P +3.34 (ameters and) 481.08 664.33 P +1.51 (syntax as the) 261.43 652.33 P +3 F +1.51 (send) 327.67 652.33 P +0 F +1.51 ( method. Ho) 349.36 652.33 P +1.51 (w) 406.7 652.33 P +1.51 (e) 413.82 652.33 P +1.51 (v) 419.08 652.33 P +1.51 (er) 423.83 652.33 P +1.51 (, r) 432.22 652.33 P +1.51 (ather than w) 442.53 652.33 P +1.51 (aiting f) 500.43 652.33 P +1.51 (or) 531.11 652.33 P +0.89 (the under) 261.43 640.33 P +0.89 (lying ser) 304.72 640.33 P +0.89 (vice to respond to the request, this function) 343.14 640.33 P +0.16 (will retur) 261.43 628.33 P +0.16 (n immediately) 299.06 628.33 P +0.16 (.The caller m) 359.91 628.33 P +0.16 (ust use a cde) 417.92 628.33 P +0.16 (vGroup object) 477.59 628.33 P +1.44 (in order to detect when the tr) 261.43 616.33 P +1.44 (ansaction has been completed.) 397.27 616.33 P +3.14 (The ser) 261.43 604.33 P +3.14 (vice de) 298.78 604.33 P +3.14 (v) 333.3 604.33 P +3.14 (eloper is responsib) 338.05 604.33 P +3.14 (le f) 428.06 604.33 P +3.14 (or implementing this) 444.24 604.33 P +(method in the ser) 261.43 592.33 T +(vice speci\336ed cde) 338.99 592.33 T +(vRequestObject.) 417.61 592.33 T +2 F +(sendCallbac) 162 568.33 T +(k) 220.71 568.33 T +3 F +(int sendCallbac) 261.29 568.33 T +(k \050cde) 329.45 568.33 T +(vData &out, cde) 356.38 568.33 T +(vCallbac) 427.23 568.33 T +(k &callbac) 465.37 568.33 T +(k\051;) 510.74 568.33 T +(int sendCallbac) 261.29 556.33 T +(k \050cde) 329.45 556.33 T +(vData *out, cde) 356.38 556.33 T +(vCallbac) 424.45 556.33 T +(k &callbac) 462.59 556.33 T +(k\051;) 507.96 556.33 T +0 F +6.06 (The) 261.29 539.33 P +3 F +6.06 (sendCallbac) 287.36 539.33 P +6.06 (k) 342.18 539.33 P +0 F +6.06 (function is the standard method f) 356.02 539.33 P +6.06 (or) 531.11 539.33 P +3.54 (asynchronously comm) 261.43 527.33 P +3.54 (unicating with a de) 364.34 527.33 P +3.54 (vice) 457.48 527.33 P +3.54 (. Rather than) 475.11 527.33 P +1.95 (pro) 261.43 515.33 P +1.95 (viding a) 275.73 515.33 P +3 F +1.95 (result) 316.86 515.33 P +0 F +1.95 ( cde) 341.31 515.33 P +1.95 (vData object, this method requires the) 361.86 515.33 P +2.49 (user to pro) 261.43 503.33 P +2.49 (vide the address of a cde) 314.07 503.33 P +2.49 (vCallbac) 437.96 503.33 P +2.49 (k object. This) 476.1 503.33 P +1.4 (object contains a user supplied pointer and the address of a) 261.43 491.33 P +3.42 (function to call when the message has been successfully) 261.43 479.33 P +8.48 (processed. The ser) 261.43 467.33 P +8.48 (vice de) 364.29 467.33 P +8.48 (v) 404.15 467.33 P +8.48 (eloper is responsib) 408.9 467.33 P +8.48 (le f) 509.59 467.33 P +8.48 (or) 531.11 467.33 P +10.07 (implementing this method in the ser) 261.43 455.33 P +10.07 (vice speci\336ed) 469.91 455.33 P +(cde) 261.43 443.33 T +(vRequestObject.) 277.25 443.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "10" 18 +%%Page: "11" 19 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. The cde) 413.22 739 T +(vCollectionRequest Class) 455.47 739 T +0 10 Q +(11) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(5.) 159.32 710.67 T +(The cde) 180 710.67 T +(vCollectionRequest Class) 232.7 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w of the) 108.64 673.33 T +(cde) 72 661.33 T +(vCollection) 89.08 661.33 T +(Request Class) 72 649.33 T +0 F +4.16 (The cde) 180 673.33 P +4.16 (vCollectionRequest class is an abstr) 219.99 673.33 P +4.16 (act base class from which other) 397.14 673.33 P +1.41 (cde) 180 661.33 P +1.41 (vCollectionRequest objects are der) 195.82 661.33 P +1.41 (iv) 355.26 661.33 P +1.41 (ed. It pro) 362.23 661.33 P +1.41 (vides a protected constr) 404.36 661.33 P +1.41 (uctor and) 514.9 661.33 P +-0.16 (destr) 180 649.33 P +-0.16 (uctor that are used to initializ) 202.38 649.33 P +-0.16 (e its inter) 328.7 649.33 P +-0.16 (nals) 369.19 649.33 P +-0.16 (, ho) 387.38 649.33 P +-0.16 (w) 403.75 649.33 P +-0.16 (e) 410.87 649.33 P +-0.16 (v) 416.13 649.33 P +-0.16 (er) 420.88 649.33 P +-0.16 (, the pr) 429.27 649.33 P +-0.16 (imar) 460.23 649.33 P +-0.16 (y mechanism that) 479.96 649.33 P +(is used to obtain a cde) 180 637.33 T +(vCollectionRequest object is the) 279.76 637.33 T +3 F +(attachPtr) 424.82 637.33 T +0 F +( method.) 464.84 637.33 T +1.17 (Because the cde) 180 620.33 P +1.17 (vCollectionRequest is inher) 256.53 620.33 P +1.17 (ited from the cde) 380.16 620.33 P +1.17 (vRequestObject, all of) 457.84 620.33 P +3.15 (the methods of that class m) 180 608.33 P +3.15 (ust be ful\336lled in addition to those speci\336c to the) 317.91 608.33 P +(cde) 180 596.33 T +(vCollectionRequest class) 195.82 596.33 T +(.) 307.37 596.33 T +2 F +(Pub) 72 567.33 T +(lic Member) 90.79 567.33 T +(Functions of the) 72 555.33 T +(cde) 72 543.33 T +(vCollection) 89.08 543.33 T +(Request Class) 72 531.33 T +(constructor) 180 567.33 T +3 F +(cde) 279.29 567.33 T +(vCollectionRequest\050) 295.11 567.33 T +(char **de) 395.86 567.33 T +(vices) 436.69 567.33 T +(, int nDe) 459.32 567.33 T +(vices) 496.26 567.33 T +(,) 518.89 567.33 T +(char * msg, cde) 395.86 555.33 T +(vSystem & system\051;) 465.03 555.33 T +0 F +1.08 (This is the constr) 279.29 538.33 P +1.08 (uctor f) 358.26 538.33 P +1.08 (or the cde) 386.83 538.33 P +1.08 (vCollectionRequest class) 433.17 538.33 P +1.08 (. It) 545.8 538.33 P +(has the f) 279.43 526.33 T +(ollo) 317.49 526.33 T +(wing proper) 332.9 526.33 T +(ties) 385.54 526.33 T +(.) 400.95 526.33 T +(\245) 279.29 502.33 T +0.1 (This method is) 297.29 502.33 P +4 F +0.1 (pr) 365.39 502.33 P +0.1 (otected) 375.19 502.33 P +0 F +0.1 ( to pre) 410.75 502.33 P +0.1 (v) 439 502.33 P +0.1 (ent the direct instantiation) 443.75 502.33 P +3.95 (of ne) 297.29 490.33 P +3.95 (w) 323.27 490.33 P +3 F +3.95 (cde) 337.22 490.33 P +3.95 (vCollectionRequests) 353.04 490.33 P +0 F +3.95 (. Ne) 444.03 490.33 P +3.95 (w instances of the) 466.12 490.33 P +3 F +2.4 (cde) 297.29 478.33 P +2.4 (vCollectionRequest objects are) 313.11 478.33 P +0 F +2.4 (created b) 460.93 478.33 P +2.4 (y using the) 504.83 478.33 P +3 F +1.63 (attachPtr) 297.29 466.33 P +0 F +1.63 ( or) 337.31 466.33 P +3 F +1.63 (attachRef) 355.02 466.33 P +0 F +1.63 ( method of the) 397.82 466.33 P +3 F +1.63 (cde) 471.04 466.33 P +1.63 (vRequestObject) 486.86 466.33 P +0 F +0.62 (class which will call the local) 297.29 454.33 P +3 F +0.62 (attachPtr) 429.35 454.33 P +0 F +0.62 ( method to create a) 469.37 454.33 P +(ne) 297.29 442.33 T +(w object if necessar) 308.21 442.33 T +(y) 396.32 442.33 T +(.) 400.32 442.33 T +(\245) 279.29 418.33 T +0.74 (The constr) 297.29 418.33 P +0.74 (uctor is called b) 345.42 418.33 P +0.74 (y the cde) 416.92 418.33 P +0.74 (vCollection object and) 458.69 418.33 P +2.22 (is pro) 297.29 406.33 P +2.22 (vided with a list and count of de) 323.8 406.33 P +2.22 (vices that will be) 478.55 406.33 P +0.06 (included in the collection and the message that will be sent) 297.29 394.33 P +(to them.) 297.29 382.33 T +(\245) 279.29 358.33 T +6.39 (The) 297.29 358.33 P +3 F +6.39 (cde) 323.68 358.33 P +6.39 (vSystem) 339.5 358.33 P +0 F +6.39 ( ref) 377.84 358.33 P +6.39 (erence that is pro) 398.38 358.33 P +6.39 (vided is the) 494.65 358.33 P +3 F +1.7 (cde) 297.29 346.33 P +1.7 (vSystem) 313.11 346.33 P +0 F +1.7 ( instance that will be used to) 351.45 346.33 P +3 F +1.7 (poll) 491.77 346.33 P +0 F +1.7 (,) 507.33 346.33 P +3 F +1.7 (pend) 514.6 346.33 P +0 F +1.7 ( and) 536.84 346.33 P +3 F +(\337ush) 297.29 334.33 T +0 F +( the) 318.41 334.33 T +3 F +(cde) 337.87 334.33 T +(vCollectionRequest) 353.69 334.33 T +0 F +( object.) 439.83 334.33 T +2 F +(destructor) 180 310.33 T +3 F +(vir) 279.29 310.33 T +(tual ~cde) 290.24 310.33 T +(vCollectionRequest \050v) 330.8 310.33 T +(oid\051;) 427.8 310.33 T +0 F +-0.11 (This is the destr) 279.29 293.33 P +-0.11 (uctor f) 349.7 293.33 P +-0.11 (or a cde) 377.08 293.33 P +-0.11 (vCollectionRequest object. It has) 412.7 293.33 P +(the f) 279.43 281.33 T +(ollo) 298.59 281.33 T +(wing proper) 314 281.33 T +(ties) 366.64 281.33 T +(.) 382.05 281.33 T +(\245) 279.29 257.33 T +14.64 (This method is protected to pre) 297.29 257.33 P +14.64 (v) 508.03 257.33 P +14.64 (ent the) 512.78 257.33 P +3 F +0.54 (cde) 297.29 245.33 P +0.54 (vCollectionRequest) 313.11 245.33 P +0 F +0.54 ( object from being destro) 399.25 245.33 P +0.54 (y) 511.17 245.33 P +0.54 (ed b) 515.97 245.33 P +0.54 (y the) 535.78 245.33 P +3.29 (application. This method should only be called b) 297.29 233.33 P +3.29 (y the) 533.03 233.33 P +3 F +(cde) 297.29 221.33 T +(vSystem) 313.11 221.33 T +0 F +( object when the application is ter) 351.45 221.33 T +(minating.) 499.55 221.33 T +(\245) 279.29 197.33 T +-0.07 (Because the) 297.29 197.33 P +3 F +-0.07 (cde) 355.51 197.33 P +-0.07 (vCollectionRequest) 371.33 197.33 P +0 F +-0.07 ( object will nor) 457.47 197.33 P +-0.07 (mally be) 520.84 197.33 P +0.79 (ref) 297.29 185.33 P +0.79 (erred to as a) 308.66 185.33 P +3 F +0.79 (cde) 370.72 185.33 P +0.79 (vRequestObject) 386.54 185.33 P +0 F +0.79 ( object, this destr) 457.68 185.33 P +0.79 (uctor) 535.77 185.33 P +2.29 (is vir) 297.29 173.33 P +2.29 (tual to ensure that the) 320.53 173.33 P +4 F +2.29 (\324most senior\325) 431.5 173.33 P +0 F +2.29 ( destr) 496.03 173.33 P +2.29 (uctor is) 523.48 173.33 P +(called \336rst.) 297.29 161.33 T +2 F +(attac) 180 137.33 T +(hPtr) 203.24 137.33 T +3 F +(cde) 279.29 137.33 T +(vCollectionRequest * attachPtr) 295.11 137.33 T +(\050) 299.29 125.33 T +(cde) 302.62 125.33 T +(vCollection &col, char *msg, cde) 318.44 125.33 T +(vSystem &sys\051;) 461.52 125.33 T +0 F +1.3 (This method is used b) 279.29 108.33 P +1.3 (y the cde) 382.1 108.33 P +1.3 (vCollection object to obtain a) 424.97 108.33 P +(ne) 279.43 96.33 T +(w cde) 290.35 96.33 T +(vCollectionRequest object.) 316.17 96.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "11" 19 +%%Page: "12" 20 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. The cde) 54 739 T +(vCollectionRequest Class) 96.25 739 T +0 10 Q +(12) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(\245) 261.29 713.33 T +1.23 (This method will obtain a cop) 279.29 713.33 P +1.23 (y of the de) 414.09 713.33 P +1.23 (vice names from) 464.18 713.33 P +2.12 (the cde) 279.29 701.33 P +2.12 (vCollection object and will poll the cde) 313.9 701.33 P +2.12 (vDirector) 494.7 701.33 P +2.12 (y) 535 701.33 P +5.22 (object to deter) 279.29 689.33 P +5.22 (mine which ser) 353.34 689.33 P +5.22 (vice each of them is) 430.76 689.33 P +(associated with.) 279.29 677.33 T +(\245) 261.29 653.33 T +0.32 (If the de) 279.29 653.33 P +0.32 (vices are all from a single ser) 315.77 653.33 P +0.32 (vice) 447.49 653.33 P +0.32 (, this method will) 465.12 653.33 P +(retur) 279.29 641.33 T +(n a ser) 300.1 641.33 T +(vice speci\336c collection request object.) 330.97 641.33 T +(\245) 261.29 617.33 T +-0.27 (If the de) 279.29 617.33 P +-0.27 (vices are from a v) 314.58 617.33 P +-0.27 (ar) 392.14 617.33 P +-0.27 (iety of ser) 401.18 617.33 P +-0.27 (vices) 444.28 617.33 P +-0.27 (, this method will) 466.91 617.33 P +5.63 (retur) 279.29 605.33 P +5.63 (n a cde) 300.1 605.33 P +5.63 (vGr) 343.85 605.33 P +5.63 (pCollectionRequest that contains the) 360.26 605.33 P +(ser) 279.29 593.33 T +(vice speci\336c collection request objects) 293.48 593.33 T +(.) 462.28 593.33 T +(\245) 261.29 569.33 T +0.15 (De) 279.29 569.33 P +0.15 (vice/message combinations that are not associated with) 291.77 569.33 P +(a ser) 279.29 557.33 T +(vice will be ignored.) 301.82 557.33 T +(\245) 261.29 533.33 T +4.73 (If none of the de) 279.29 533.33 P +4.73 (vice/message combinations can be) 370.19 533.33 P +1.41 (associated with a ser) 279.29 521.33 P +1.41 (vice) 377.19 521.33 P +1.41 (, then an error message will be) 394.82 521.33 P +(gener) 279.29 509.33 T +(ated and NULL will be retur) 304.76 509.33 T +(ned.) 426.17 509.33 T +2 F +(c) 162 485.33 T +(lassName) 167.36 485.33 T +3 F +(char * className \050v) 261.29 485.33 T +(oid\051;) 350.5 485.33 T +0 F +12.7 (This method retur) 261.29 468.33 P +12.7 (ns the name of the class;) 365.31 468.33 P +2.96 (\322) 261.43 456.33 P +3 F +2.96 (cde) 264.76 456.33 P +2.96 (vCollectionRequest) 280.58 456.33 P +0 F +2.96 (\323. If the de) 366.72 456.33 P +2.96 (v) 420.33 456.33 P +2.96 (eloper inher) 425.08 456.33 P +2.96 (its a ser) 480.99 456.33 P +2.96 (vice) 522.22 456.33 P +-0.26 (speci\336c cde) 261.43 444.33 P +-0.26 (vCollectionRequest, then this method should not be) 313.11 444.33 P +(altered or o) 261.43 432.33 T +(v) 311.86 432.33 T +(err) 316.61 432.33 T +(idden.) 328.98 432.33 T +2 F +(resultCodeT) 162 408.33 T +(a) 219.54 408.33 T +(g) 225 408.33 T +3 F +(int resultCodetag \050v) 261.29 408.33 T +(oid\051;) 347.74 408.33 T +0 F +2.16 (This method retur) 261.29 391.33 P +2.16 (ns the integer tag that should be used to) 344.23 391.33 P +0.3 (inser) 261.43 379.33 P +0.3 (t the result code that w) 283.5 379.33 P +0.3 (as geneter) 385.47 379.33 P +0.3 (ated when the message) 432.92 379.33 P +(w) 261.43 367.33 T +(as sent to the actual de) 268.5 367.33 T +(vice) 371.6 367.33 T +(.) 389.23 367.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "12" 20 +%%Page: "13" 21 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. The Ser) 432.17 739 T +(vice Loader Function) 474.46 739 T +0 10 Q +(13) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(6.) 159.32 710.67 T +(The Ser) 180 710.67 T +(vice Loader Function) 231.49 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w) 108.64 673.33 T +0 F +(The ser) 180 673.33 T +(vice loader function is used to create an initial instance of the ser) 214.2 673.33 T +(vice after the) 500.75 673.33 T +(its associated shared object \336le has been dynamically loaded.) 180 661.33 T +2 F +(Naming) 72 632.33 T +(Con) 72 620.33 T +(vention) 91.04 620.33 T +0 F +(The naming con) 180 632.33 T +(v) 251.5 632.33 T +(ention f) 256.25 632.33 T +(or this class is v) 288.75 632.33 T +(er) 359.07 632.33 T +(y speci\336c. The f) 368.26 632.33 T +(ollo) 437.43 632.33 T +(wing syntax is required:) 452.84 632.33 T +3 9 Q +(Figure 2: Naming con) 180 599 T +(v) 268.35 599 T +(ention and syntax f) 272.63 599 T +(or the cde) 347.9 599 T +(vSer) 387.66 599 T +(vice loader function) 406.43 599 T +0 10 Q +0.28 (In the function name abo) 180 529.5 P +0.28 (v) 291.04 529.5 P +0.28 (e the) 295.79 529.5 P +3 F +0.28 (Xxxxx) 321.37 529.5 P +0 F +0.28 ( should be replaced b) 348.04 529.5 P +0.28 (y the name of the ser) 444.58 529.5 P +0.28 (vice) 540.22 529.5 P +2.55 (with the \336rst char) 180 517.5 P +2.55 (acter capitaliz) 263.12 517.5 P +2.55 (ed. A ser) 326.65 517.5 P +2.55 (vice named) 372.07 517.5 P +3 F +2.55 (demo) 431.08 517.5 P +0 F +2.55 ( w) 456.09 517.5 P +2.55 (ould ha) 468.54 517.5 P +2.55 (v) 503.68 517.5 P +2.55 (e a loader) 508.43 517.5 P +0.92 (function named) 180 505.5 P +3 F +0.92 (ne) 252.99 505.5 P +0.92 (wDemoSer) 263.91 505.5 P +0.92 (vice) 313.66 505.5 P +0.92 (.) 331.29 505.5 P +0 F +0.92 (The loader function is only required to allocate a) 337.77 505.5 P +1.46 (ne) 180 493.5 P +1.46 (w ser) 190.92 493.5 P +1.46 (vice class f) 216.57 493.5 P +1.46 (or the ser) 268.1 493.5 P +1.46 (vice and retur) 313.56 493.5 P +1.46 (n a pointer to it. The f) 377.32 493.5 P +1.46 (ollo) 480.3 493.5 P +1.46 (wing e) 495.71 493.5 P +1.46 (xample) 525.77 493.5 P +(illustr) 180 481.5 T +(ates ho) 203.23 481.5 T +(w the loader function f) 235.88 481.5 T +(or the demo ser) 333.41 481.5 T +(vice w) 403.74 481.5 T +(ould be wr) 431.42 481.5 T +(itten.) 477.7 481.5 T +3 9 Q +(Figure 3: Example cde) 180 448.17 T +(vSer) 272.27 448.17 T +(vice loader function) 291.04 448.17 T +180 81 558 639 C +180 560.17 558 596 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.71 565.84 559.29 584.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +179.75 570.79 553.7 590 R +7 X +V +0 X +N +185 575.51 547.11 585.33 R +7 X +V +5 9 Q +0 X +(cdevService *new) 185 579.33 T +6 F +(Xxxxx) 271.4 579.33 T +5 F +(Service \050char * name, cdevSystem * system\051;) 298.4 579.33 T +180 81 558 639 C +0 0 612 792 C +180 81 558 639 C +180 264.34 558 445.17 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.21 268.34 559.79 433.74 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +180.25 273.29 554.2 439.17 R +7 X +V +0 X +N +185.5 278.84 547.61 434.5 R +7 X +V +5 9 Q +0 X +(#include ) 185.5 428.5 T +(// ****************************************************************) 185.5 406.5 T +(// * Include file with definition of the service class) 185.5 395.5 T +(// ****************************************************************) 185.5 384.5 T +(#include \322demoService.h\323) 185.5 373.5 T +(// ****************************************************************) 185.5 351.5 T +(// * Loader function for the demoService class) 185.5 340.5 T +(// ****************************************************************) 185.5 329.5 T +(cdevService *newDemoService \050char * name, cdevSystem * system\051) 185.5 318.5 T +({) 203.5 307.5 T +(return new demoService\050name, *system\051;) 203.5 296.5 T +(}) 203.5 285.5 T +180 81 558 639 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "13" 21 +%%Page: "14" 22 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. The cde) 54 739 T +(vT) 96.25 739 T +(r) 105.17 739 T +(anObj Class) 108.08 739 T +0 10 Q +(14) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(7.) 141.32 710.67 T +(The cde) 162 710.67 T +(vT) 214.7 710.67 T +(ranObj Class) 229.91 710.67 T +2 10 Q +(Over) 54 673.33 T +(vie) 76.89 673.33 T +(w of the) 90.64 673.33 T +(cde) 54 661.33 T +(vT) 71.08 661.33 T +(ranObj Class) 81.95 661.33 T +0 F +0.16 (The cde) 162 673.33 P +0.16 (vT) 197.99 673.33 P +0.16 (r) 207.9 673.33 P +0.16 (anObj \050) 211.13 673.33 P +3 F +0.16 (cde) 244.08 673.33 P +0.16 (v tr) 259.9 673.33 P +0.16 (ansaction object) 273.85 673.33 P +0 F +0.16 (\051 C++ class is a container class that is used) 346.27 673.33 P +0.36 (to maintain inf) 162 661.33 P +0.36 (or) 224.66 661.33 P +0.36 (mation that is required f) 233.8 661.33 P +0.36 (or individual oper) 339.42 661.33 P +0.36 (ations within a ser) 416.17 661.33 P +0.36 (vice) 497.56 661.33 P +0.36 (. This) 515.19 661.33 P +0.29 (class stores a cop) 162 649.33 P +0.29 (y of the) 242.61 649.33 P +3 F +0.29 (cde) 279.08 649.33 P +0.29 (vRequestObject) 294.89 649.33 P +0 F +0.29 ( that w) 366.04 649.33 P +0.29 (as used to submit a request, the) 395.93 649.33 P +3 F +0.55 (cde) 162 637.33 P +0.55 (vSystem) 177.82 637.33 P +0 F +0.55 (object in which the request object w) 219.49 637.33 P +0.55 (as created, the) 380.46 637.33 P +3 F +0.55 (cde) 451.03 637.33 P +0.55 (vCallbac) 466.85 637.33 P +0.55 (k) 504.99 637.33 P +0 F +0.55 ( object) 509.99 637.33 P +-0.13 (pro) 162 625.33 P +-0.13 (vided b) 176.3 625.33 P +-0.13 (y the user) 208.21 625.33 P +-0.13 (, and the) 251.35 625.33 P +3 F +-0.13 (cde) 292.64 625.33 P +-0.13 (vData) 308.46 625.33 P +0 F +-0.13 ( object that the retur) 334.58 625.33 P +-0.13 (ned data should be placed) 423.24 625.33 P +1.49 (in. Because this object is intended f) 162 613.33 P +1.49 (or usage only b) 327.41 613.33 P +1.49 (y cde) 400.07 613.33 P +1.49 (v inter) 425.16 613.33 P +1.49 (nals) 454.13 613.33 P +1.49 (, all of its data) 472.32 613.33 P +(elements are) 162 601.33 T +3 F +(pub) 222.58 601.33 T +(lic) 239.06 601.33 T +0 F +(.) 248.5 601.33 T +1.92 (The) 162 584.33 P +3 F +1.92 (cde) 183.93 584.33 P +1.92 (vT) 199.75 584.33 P +1.92 (r) 209.66 584.33 P +1.92 (anObj) 212.89 584.33 P +0 F +1.92 (is used to submit a request from the cde) 244.27 584.33 P +1.92 (vRequestObject to the) 437.21 584.33 P +0.54 (cde) 162 572.33 P +0.54 (vSer) 177.82 572.33 P +0.54 (vice) 198.68 572.33 P +0.54 (. It is also used to place a tr) 216.31 572.33 P +0.54 (ansaction into a g) 342.29 572.33 P +0.54 (roup of requests using the) 422.2 572.33 P +3 F +1.73 (cde) 162 560.33 P +1.73 (vGroup) 177.82 560.33 P +0 F +1.73 ( object. The ser) 210.61 560.33 P +1.73 (vice noti\336es the) 285.03 560.33 P +3 F +1.73 (cde) 361.92 560.33 P +1.73 (vSystem) 377.74 560.33 P +0 F +1.73 ( object and the) 416.08 560.33 P +3 F +1.73 (cde) 491.39 560.33 P +1.73 (vGroup) 507.21 560.33 P +0 F +2.65 (objects that this tr) 162 548.33 P +2.65 (ansaction has been processed b) 248.22 548.33 P +2.65 (y calling its) 402.58 548.33 P +3 F +2.65 (remo) 462.21 548.33 P +2.65 (v) 484.84 548.33 P +2.65 (eF) 489.59 548.33 P +2.65 (romGr) 500.81 548.33 P +2.65 (ps) 529.44 548.33 P +0 F +3.33 (method. This will eff) 162 536.33 P +3.33 (ectiv) 260.05 536.33 P +3.33 (ely remo) 280.36 536.33 P +3.33 (v) 321.89 536.33 P +3.33 (e the) 326.64 536.33 P +3 F +3.33 (cde) 358.32 536.33 P +3.33 (vT) 374.14 536.33 P +3.33 (r) 384.05 536.33 P +3.33 (anObj) 387.28 536.33 P +0 F +3.33 ( from all g) 413.96 536.33 P +3.33 (roups that it is) 467.76 536.33 P +(associated with.) 162 524.33 T +2 F +(Pub) 54 495.33 T +(lic Data) 72.79 495.33 T +(Pr) 54 483.33 T +(oper) 64.36 483.33 T +(ties of the) 86.23 483.33 T +(cde) 54 471.33 T +(vT) 71.08 471.33 T +(ranObj Class) 81.95 471.33 T +(system_) 162 495.33 T +3 F +(cde) 261.29 495.33 T +(vSystem *system_;) 277.11 495.33 T +0 F +5.06 (This is a pointer to the cde) 261.29 478.33 P +5.06 (vSystem that contains this) 408.65 478.33 P +0.12 (tr) 261.43 466.33 P +0.12 (ansaction object. The tr) 267.44 466.33 P +0.12 (ansaction will be processed whene) 371.65 466.33 P +0.12 (v) 526.36 466.33 P +0.12 (er) 531.11 466.33 P +3.93 (the) 261.43 454.33 P +3 F +3.93 (poll) 282.05 454.33 P +0 F +3.93 (or) 304.32 454.33 P +3 F +3.93 (pend) 319.93 454.33 P +0 F +3.93 ( methods of this) 342.17 454.33 P +3 F +3.93 (cde) 431.28 454.33 P +3.93 (vSystem) 447.1 454.33 P +0 F +3.93 ( object are) 485.44 454.33 P +(e) 261.43 442.33 T +(x) 266.69 442.33 T +(ecuted.) 271.39 442.33 T +2 F +(reqObj_) 162 418.33 T +3 F +(cde) 261.29 418.33 T +(vRequestObject *reqObj_;) 277.11 418.33 T +0 F +1.07 (This is a pointer to the cde) 261.29 401.33 P +1.07 (vRequestObject that w) 384.69 401.33 P +1.07 (as called to) 487.28 401.33 P +5.74 (submit this tr) 261.43 389.33 P +5.74 (ansaction. This) 329.49 389.33 P +3 F +5.74 (cde) 411 389.33 P +5.74 (vRequestObject) 426.82 389.33 P +0 F +5.74 ( will be) 497.96 389.33 P +2.89 (submitted to the user speci\336ed callbac) 261.43 377.33 P +2.89 (k function when the) 445.18 377.33 P +(tr) 261.43 365.33 T +(ansaction has been completed.) 267.44 365.33 T +2 F +(resultData_) 162 341.33 T +3 F +(cde) 261.29 341.33 T +(vData *resultData_;) 277.11 341.33 T +0 F +2.5 (This is the cde) 261.29 324.33 P +2.5 (vData object that will be populated with the) 332.96 324.33 P +0.69 (results of the tr) 261.43 312.33 P +0.69 (ansaction. This object will also be submitted to) 329.54 312.33 P +1.23 (the user speci\336ed callbac) 261.43 300.33 P +1.23 (k function when the tr) 377.2 300.33 P +1.23 (ansaction has) 477.07 300.33 P +(been completed.) 261.43 288.33 T +2 F +(userCallbac) 162 264.33 T +(k_) 218.49 264.33 T +3 F +(cde) 261.29 264.33 T +(vCallbac) 277.11 264.33 T +(k *userCallbac) 315.25 264.33 T +(k_;) 379.51 264.33 T +0 F +1.9 (This class contains a pointer to the caller speci\336ed callbac) 261.29 247.33 P +1.9 (k) 535 247.33 P +1.3 (function as w) 261.43 235.33 P +1.3 (ell as an) 322.29 235.33 P +1.3 (y user argument. The callbac) 361.97 235.33 P +1.3 (k function) 495.9 235.33 P +2.18 (will be e) 261.43 223.33 P +2.18 (x) 301.62 223.33 P +2.18 (ecuted when the tr) 306.32 223.33 P +2.18 (ansaction has been completed.) 395.04 223.33 P +1.25 (Note that it is the responsibility of the ser) 261.43 211.33 P +1.25 (vice to e) 451.81 211.33 P +1.25 (x) 491.25 211.33 P +1.25 (ecute this) 495.95 211.33 P +6.63 (callbac) 261.43 199.33 P +6.63 (k function when it has \336nished processing the) 292.35 199.33 P +(tr) 261.43 187.33 T +(ansaction.) 267.44 187.33 T +2 F +(Pub) 54 158.33 T +(lic Member) 72.79 158.33 T +(Functions of the) 54 146.33 T +(cde) 54 134.33 T +(vT) 71.08 134.33 T +(ranObj Class) 81.95 134.33 T +(status) 162 158.33 T +3 F +(int status \050v) 261.29 158.33 T +(oid\051;) 312.17 158.33 T +0 F +4.05 (Retur) 261.29 141.33 P +4.05 (ns the status of the) 285.99 141.33 P +3 F +4.05 (cde) 393.52 141.33 P +4.05 (vT) 409.35 141.33 P +4.05 (r) 419.26 141.33 P +4.05 (anObj) 422.48 141.33 P +0 F +4.05 ( object. The v) 449.17 141.33 P +4.05 (alue) 521.1 141.33 P +0.63 (retur) 261.43 129.33 P +0.63 (ned will be) 282.24 129.33 P +2 F +0.63 (1) 334.15 129.33 P +0 F +0.63 ( if this object is a member of an) 339.71 129.33 P +0.63 (y) 482.98 129.33 P +3 F +0.63 (cde) 491.39 129.33 P +0.63 (vGroup) 507.21 129.33 P +0 F +1.21 (object, or) 261.43 117.33 P +2 F +1.21 (-1) 307.75 117.33 P +0 F +1.21 ( if this object is not a member of an) 316.64 117.33 P +1.21 (y) 482.4 117.33 P +3 F +1.21 (cde) 491.39 117.33 P +1.21 (vGroup) 507.21 117.33 P +0 F +(object.) 261.43 105.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "14" 22 +%%Page: "15" 23 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. The cde) 454.9 739 T +(vT) 497.16 739 T +(r) 506.08 739 T +(anObj Class) 508.99 739 T +0 10 Q +(15) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(remo) 180 713.33 T +(veFr) 204.25 713.33 T +(omGrps) 225.17 713.33 T +3 F +(int remo) 279.29 713.33 T +(v) 315.26 713.33 T +(eF) 320.01 713.33 T +(romGr) 331.23 713.33 T +(ps \050v) 359.86 713.33 T +(oid\051;) 381.28 713.33 T +0 F +2.16 (Remo) 279.29 696.33 P +2.16 (v) 305.81 696.33 P +2.16 (es this tr) 310.56 696.33 P +2.16 (ansaction object from an) 352.57 696.33 P +2.16 (y) 467.83 696.33 P +3 F +2.16 (cde) 477.77 696.33 P +2.16 (vGroup) 493.59 696.33 P +0 F +2.16 ( object) 526.38 696.33 P +(that it ma) 279.43 684.33 T +(y be in.) 320.26 684.33 T +2 F +(enab) 180 660.33 T +(leDeleteCbk) 203.24 660.33 T +3 F +(v) 279.29 660.33 T +(oid enab) 284.04 660.33 T +(leDeleteCbk \050v) 322.2 660.33 T +(oid\051;) 387.52 660.33 T +0 F +0.68 (Sets the inter) 279.29 643.33 P +0.68 (nal \337ag telling the tr) 339.81 643.33 P +0.68 (ansaction object to delete its) 429.12 643.33 P +1.59 (inter) 279.43 631.33 P +1.59 (nal callbac) 299.13 631.33 P +1.59 (k object while e) 347.76 631.33 P +1.59 (x) 420.59 631.33 P +1.59 (ecuting its destr) 425.29 631.33 P +1.59 (uctor) 498.64 631.33 P +1.59 (. This is) 520.37 631.33 P +(the def) 279.43 619.33 T +(ault beha) 309.71 619.33 T +(vior f) 350.65 619.33 T +(or the cde) 372.02 619.33 T +(vT) 416.19 619.33 T +(r) 426.1 619.33 T +(anObj.) 429.33 619.33 T +2 F +(disab) 180 595.33 T +(leDeleteCbk) 206.02 595.33 T +3 F +(v) 279.29 595.33 T +(oid disab) 284.04 595.33 T +(leDeleteCbk \050v) 323.86 595.33 T +(oid\051;) 389.18 595.33 T +0 F +0.28 (Sets the inter) 279.29 578.33 P +0.28 (nal \337ag telling the tr) 339.03 578.33 P +0.28 (ansaction object not to delete) 426.78 578.33 P +1.24 (its inter) 279.43 566.33 P +1.24 (nal callbac) 313.15 566.33 P +1.24 (k object while e) 361.43 566.33 P +1.24 (x) 433.22 566.33 P +1.24 (ecuting its destr) 437.92 566.33 P +1.24 (uctor) 510.58 566.33 P +1.24 (. This) 532.31 566.33 P +0.77 (mode should be used when the user speci\336ed callbac) 279.43 554.33 P +0.77 (k object) 522.77 554.33 P +(is shared b) 279.43 542.33 T +(y n) 328.14 542.33 T +(umerous tr) 341.38 542.33 T +(ansaction objects) 389.07 542.33 T +(.) 466.18 542.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "15" 23 +%%Page: "16" 24 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 54 739 T +(ault Ser) 77.74 739 T +(vice Beha) 109.03 739 T +(vior f) 148.37 739 T +(or Standard Messages) 167.6 739 T +0 10 Q +(16) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(8.) 141.32 710.67 T +(Default Ser) 162 710.67 T +(vice Beha) 236.05 710.67 T +(vior f) 301.2 710.67 T +(or Standar) 335.15 710.67 T +(d Messa) 404.89 710.67 T +(g) 459.99 710.67 T +(es) 468.68 710.67 T +2 10 Q +(Over) 54 673.33 T +(vie) 76.89 673.33 T +(w) 90.64 673.33 T +0 F +2.46 (The cde) 162 673.33 P +2.46 (v libr) 200.29 673.33 P +2.46 (ar) 223.76 673.33 P +2.46 (y is designed to pro) 232.95 673.33 P +2.46 (vide a standard calling interf) 329.36 673.33 P +2.46 (ace to dissimilar) 463.4 673.33 P +0.89 (de) 162 661.33 P +0.89 (vices within a control system. This interf) 172.82 661.33 P +0.89 (ace is accommodated through the use of) 354.02 661.33 P +0.02 (the cde) 162 649.33 P +0.02 (vDe) 194.52 649.33 P +0.02 (vice methods) 212 649.33 P +4 F +0.02 (send, sendNoBloc) 273.73 649.33 P +0.02 (k) 360.79 649.33 P +0 F +0.02 ( and) 366.35 649.33 P +4 F +0.02 (sendCallbac) 388.62 649.33 P +0.02 (k) 447.33 649.33 P +3 F +0.02 (.) 452.89 649.33 P +0 F +0.02 ( Ho) 455.67 649.33 P +0.02 (w) 471.1 649.33 P +0.02 (e) 478.22 649.33 P +0.02 (v) 483.48 649.33 P +0.02 (er) 488.23 649.33 P +0.02 (, because) 496.62 649.33 P +0.79 (each ser) 162 637.33 P +0.79 (vice can de\336ne the names and beha) 201.44 637.33 P +0.79 (viors of the messages that it suppor) 366.61 637.33 P +0.79 (ts) 529.59 637.33 P +0.79 (,) 537.22 637.33 P +(the user m) 162 625.33 T +(ust be increasingly a) 209.14 625.33 T +(w) 300.09 625.33 T +(are of which ser) 307.16 625.33 T +(vice ma) 378.04 625.33 T +(y process its messages) 412.19 625.33 T +(.) 515.96 625.33 T +0 (In order to reduce the required kno) 162 608.33 P +0 (wledge of the user) 315.81 608.33 P +0 (, and to impro) 397.01 608.33 P +0 (v) 457.99 608.33 P +0 (e the consistency) 462.74 608.33 P +-0.2 (of all ser) 162 596.33 P +-0.2 (vices) 199.7 596.33 P +-0.2 (, all cde) 222.32 596.33 P +-0.2 (v ser) 256.09 596.33 P +-0.2 (vices should pro) 277.86 596.33 P +-0.2 (vide w) 349.57 596.33 P +-0.2 (ell-de\336ned suppor) 377.61 596.33 P +-0.2 (t f) 457.29 596.33 P +-0.2 (or a minim) 465.13 596.33 P +-0.2 (um list) 511.31 596.33 P +(of) 162 584.33 T +3 F +(v) 173.12 584.33 T +(erbs) 177.87 584.33 T +0 F +(.) 197.17 584.33 T +0.15 (The f) 162 567.33 P +0.15 (ollo) 184.64 567.33 P +0.15 (wing v) 200.05 567.33 P +0.15 (erbs should be implemented to pro) 228.29 567.33 P +0.15 (vide a standard beha) 382.86 567.33 P +0.15 (vior in all cde) 476.5 567.33 P +0.15 (v) 535 567.33 P +(ser) 162 555.33 T +(vices:) 176.19 555.33 T +4 F +(g) 204.53 555.33 T +(et, set, monitorOn,) 210.74 555.33 T +0 F +( and) 299.09 555.33 T +4 F +(monitorOff) 321.33 555.33 T +(.) 372.89 555.33 T +2 F +(\322g) 54 526.33 T +(et\323 Messa) 65.21 526.33 T +(g) 112.35 526.33 T +(e) 118.56 526.33 T +0 F +0.79 (The) 162 526.33 P +3 F +0.79 (\322get\323) 182.8 526.33 P +0 F +0.79 ( v) 203.36 526.33 P +0.79 (erb can be joined with an) 211.68 526.33 P +0.79 (y) 326.66 526.33 P +3 F +0.79 (attr) 335.23 526.33 P +0.79 (ib) 349.83 526.33 P +0.79 (ute) 357.42 526.33 P +0 F +0.79 ( of a de) 371.32 526.33 P +0.79 (vice to f) 406.75 526.33 P +0.79 (or) 442.49 526.33 P +0.79 (m a \322get\323 message) 451.63 526.33 P +0.79 (.) 537.22 526.33 P +1.89 (This message is then sent to the de) 162 514.33 P +1.89 (vice in order to obtain the v) 332.8 514.33 P +1.89 (alue of speci\336ed) 463.96 514.33 P +3 F +0.19 (proper) 162 502.33 P +0.19 (ties) 191.3 502.33 P +0 F +0.19 (of the) 209.83 502.33 P +3 F +0.19 (attr) 238.02 502.33 P +0.19 (ib) 252.62 502.33 P +0.19 (ute) 260.2 502.33 P +0.19 (.) 273.95 502.33 P +0 F +0.19 (The f) 279.7 502.33 P +0.19 (ollo) 302.38 502.33 P +0.19 (wing steps should be e) 317.79 502.33 P +0.19 (x) 419.98 502.33 P +0.19 (ecuted in order to utiliz) 424.68 502.33 P +0.19 (e a) 525.91 502.33 P +3 F +(\322get\323) 162 490.33 T +0 F +( message) 182.56 490.33 T +(.) 225.76 490.33 T +(1.) 162 473.33 T +(Obtain a pointer to the) 180 473.33 T +3 F +(cde) 281.73 473.33 T +(vDe) 297.55 473.33 T +(vice) 315.03 473.33 T +0 F +( object f) 332.81 473.33 T +(or the de) 367.53 473.33 T +(vice that y) 406.7 473.33 T +(ou wish to address) 451.52 473.33 T +(.) 534.74 473.33 T +(2.) 162 449.33 T +(Create a message str) 180 449.33 T +(ing b) 275.74 449.33 T +(y concatenating the) 297.22 449.33 T +3 F +(attr) 386.72 449.33 T +(ib) 401.32 449.33 T +(ute) 408.9 449.33 T +0 F +(that y) 425.58 449.33 T +(ou wish to address) 449.84 449.33 T +(to the) 180 437.33 T +3 F +(\322get\323) 207.8 437.33 T +0 F +( v) 228.36 437.33 T +(erb) 235.89 437.33 T +(. F) 249.94 437.33 T +(or instance) 261.31 437.33 T +(, to get the) 310.07 437.33 T +3 F +(V) 360.11 437.33 T +(AL) 365.98 437.33 T +0 F +( attr) 378.21 437.33 T +(ib) 395.59 437.33 T +(ute of a de) 403.17 437.33 T +(vice) 450.13 437.33 T +(, the message) 467.76 437.33 T +(str) 180 425.33 T +(ings should be:) 191.26 425.33 T +4 F +(\322g) 261.3 425.33 T +(et V) 272.51 425.33 T +(AL) 290.05 425.33 T +(\323) 301.98 425.33 T +0 F +(.) 306.98 425.33 T +(3.) 162 401.33 T +(Optionally) 180 401.33 T +(, use the cde) 223.46 401.33 T +(vDe) 280.42 401.33 T +(vice object created in step 1 and the message str) 297.9 401.33 T +(ing) 515.38 401.33 T +(created in step 2 to obtain a pointer to a) 180 389.33 T +3 F +(cde) 359 389.33 T +(vRequestObject) 374.82 389.33 T +0 F +(object.) 448.74 389.33 T +(4.) 162 365.33 T +(Set the) 180 365.33 T +3 F +(conte) 214.47 365.33 T +(xt) 238.63 365.33 T +0 F +( of the) 246.41 365.33 T +3 F +(cde) 276.99 365.33 T +(vDe) 292.81 365.33 T +(vice) 310.29 365.33 T +0 F +( or) 328.07 365.33 T +3 F +(cde) 342.52 365.33 T +(vRequestObject) 358.34 365.33 T +0 F +( to indicate which) 429.48 365.33 T +(proper) 180 353.33 T +(ties y) 209.3 353.33 T +(ou wish to obtain. A non-z) 232.44 353.33 T +(ero v) 347.35 353.33 T +(alue in an) 369.33 353.33 T +(y proper) 412.54 353.33 T +(ty indicates that its) 449.62 353.33 T +(v) 180 341.33 T +(alue should be retur) 184.75 341.33 T +(ned. If no conte) 273.38 341.33 T +(xt has been speci\336ed, the ser) 342.02 341.33 T +(vice should) 472.39 341.33 T +(retur) 180 329.33 T +(n the) 200.81 329.33 T +3 F +(v) 225.83 329.33 T +(alue) 230.58 329.33 T +0 F +( proper) 249.48 329.33 T +(ty b) 281.56 329.33 T +(y def) 297.48 329.33 T +(ault. A complete descr) 318.86 329.33 T +(iption of the conte) 417.94 329.33 T +(xt data) 496.58 329.33 T +(object is pro) 180 317.33 T +(vided in the cde) 233.76 317.33 T +(vDe) 303.5 317.33 T +(vice documentation.) 320.98 317.33 T +(5.) 162 293.33 T +-0.08 (Use the) 180 293.33 P +4 F +-0.08 (send, sendNoBloc) 217.09 293.33 P +-0.08 (k,) 304.05 293.33 P +0 F +-0.08 (or) 315.09 293.33 P +4 F +-0.08 (sendCallbac) 326.68 293.33 P +-0.08 (k) 385.39 293.33 P +0 F +-0.08 ( message to submit the message) 390.95 293.33 P +(to the de) 180 281.33 T +(vice) 218.62 281.33 T +(.) 236.25 281.33 T +(6.) 162 257.33 T +(Ev) 180 257.33 T +(aluate the retur) 191.42 257.33 T +(n v) 258.93 257.33 T +(alue from the) 272.02 257.33 T +4 F +(send) 333.16 257.33 T +0 F +(command to deter) 359.28 257.33 T +(mine if the oper) 440.12 257.33 T +(ation) 508.94 257.33 T +(completed successful. An) 180 245.33 T +(y v) 293.23 245.33 T +(alue other than) 305.76 245.33 T +4 F +(CDEV_SUCCESS) 375.25 245.33 T +0 F +(indicates that an) 459.71 245.33 T +(error occurred in handling the message) 180 233.33 T +(.) 353.81 233.33 T +(7.) 162 209.33 T +(If the call w) 180 209.33 T +(as completed successfully) 229.87 209.33 T +(, e) 345.02 209.33 T +(xtr) 355.84 209.33 T +(act the desired proper) 366.85 209.33 T +(ties from the) 464.52 209.33 T +(resultant cde) 180 197.33 T +(vData object.) 236.95 197.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "16" 24 +%%Page: "17" 25 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 353.86 739 T +(ault Ser) 377.6 739 T +(vice Beha) 408.89 739 T +(vior f) 448.23 739 T +(or Standard Messages) 467.46 739 T +0 10 Q +(17) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(\322set\323 Messa) 72 717.33 T +(g) 129.7 717.33 T +(e) 135.91 717.33 T +0 F +0.86 (The) 180 717.33 P +3 F +0.86 (\322set\323) 200.87 717.33 P +0 F +0.86 ( v) 220.87 717.33 P +0.86 (erb can be joined with an) 229.26 717.33 P +0.86 (y) 344.59 717.33 P +3 F +0.86 (attr) 353.23 717.33 P +0.86 (ib) 367.83 717.33 P +0.86 (ute) 375.42 717.33 P +0 F +0.86 ( of a de) 389.32 717.33 P +0.86 (vice to f) 424.96 717.33 P +0.86 (or) 460.84 717.33 P +0.86 (m a \322set\323 message) 469.98 717.33 P +0.86 (.) 555.22 717.33 P +1.75 (This message is then sent to the de) 180 705.33 P +1.75 (vice in order to set the v) 349.8 705.33 P +1.75 (alue) 466.2 705.33 P +3 F +1.75 (proper) 489.62 705.33 P +1.75 (ty) 518.92 705.33 P +0 F +1.75 (of the) 531.23 705.33 P +3 F +(attr) 180 693.33 T +(ib) 194.6 693.33 T +(ute) 202.18 693.33 T +(.) 215.93 693.33 T +0 F +(The f) 221.49 693.33 T +(ollo) 243.98 693.33 T +(wing steps should be e) 259.39 693.33 T +(x) 360.81 693.33 T +(ecuted in order to utiliz) 365.51 693.33 T +(e a) 465.96 693.33 T +3 F +(\322set\323) 482.64 693.33 T +0 F +( message) 502.64 693.33 T +(.) 545.84 693.33 T +(1.) 180 676.33 T +(Obtain a pointer to the) 198 676.33 T +3 F +(cde) 299.73 676.33 T +(vDe) 315.55 676.33 T +(vice) 333.03 676.33 T +0 F +( object f) 350.81 676.33 T +(or the de) 385.53 676.33 T +(vice that y) 424.7 676.33 T +(ou wish to address) 469.52 676.33 T +(.) 552.74 676.33 T +(2.) 180 652.33 T +(Create a message str) 198 652.33 T +(ing b) 293.74 652.33 T +(y concatenating the) 315.22 652.33 T +3 F +(attr) 404.72 652.33 T +(ib) 419.32 652.33 T +(ute) 426.9 652.33 T +0 F +(that y) 443.58 652.33 T +(ou wish to address) 467.84 652.33 T +(to the) 198 640.33 T +3 F +(\322set\323) 225.8 640.33 T +0 F +( v) 245.8 640.33 T +(erb) 253.33 640.33 T +(. F) 267.38 640.33 T +(or instance) 278.75 640.33 T +(, to set the) 327.51 640.33 T +3 F +(bdl) 376.99 640.33 T +0 F +( attr) 390.33 640.33 T +(ib) 407.71 640.33 T +(ute of a de) 415.29 640.33 T +(vice) 462.25 640.33 T +(, the message) 479.88 640.33 T +(str) 198 628.33 T +(ing should be:) 209.26 628.33 T +4 F +(\322set bdl\323) 274.3 628.33 T +0 F +(.) 316.53 628.33 T +(3.) 180 604.33 T +(Optionally) 198 604.33 T +(, use the cde) 241.46 604.33 T +(vDe) 298.42 604.33 T +(vice object created in step 1 and the message str) 315.9 604.33 T +(ing) 533.38 604.33 T +(created in step 2 to obtain a pointer to a) 198 592.33 T +3 F +(cde) 377 592.33 T +(vRequestObject) 392.82 592.33 T +0 F +(object.) 466.74 592.33 T +(4.) 180 568.33 T +(Set the) 198 568.33 T +3 F +(v) 232.47 568.33 T +(alue) 237.22 568.33 T +0 F +( proper) 256.12 568.33 T +(ty of the outbound cde) 288.2 568.33 T +(vData object to the ne) 386.86 568.33 T +(w v) 483.94 568.33 T +(alue) 498.69 568.33 T +(.) 517.44 568.33 T +(5.) 180 544.33 T +-0.08 (Use the) 198 544.33 P +4 F +-0.08 (send, sendNoBloc) 235.09 544.33 P +-0.08 (k,) 322.05 544.33 P +0 F +-0.08 (or) 333.09 544.33 P +4 F +-0.08 (sendCallbac) 344.68 544.33 P +-0.08 (k) 403.39 544.33 P +0 F +-0.08 ( message to submit the message) 408.95 544.33 P +(to the de) 198 532.33 T +(vice) 236.62 532.33 T +(.) 254.25 532.33 T +(6.) 180 508.33 T +(Ev) 198 508.33 T +(aluate the retur) 209.42 508.33 T +(n v) 276.93 508.33 T +(alue from the speci\336c) 290.02 508.33 T +4 F +(send) 387.28 508.33 T +0 F +(command to deter) 413.4 508.33 T +(mine if the) 494.24 508.33 T +(message w) 198 496.33 T +(as tr) 248.42 496.33 T +(ansmitted successful. An) 267.77 496.33 T +(y v) 378.22 496.33 T +(alue other than) 390.75 496.33 T +4 F +(CDEV_SUCCESS) 460.24 496.33 T +0 F +(indicates that the message w) 198 484.33 T +(as not tr) 326.8 484.33 T +(ansmitted successfully) 362.83 484.33 T +(.) 461.86 484.33 T +1.92 (In the f) 180 460.33 P +1.92 (ollo) 214.13 460.33 P +1.92 (wing e) 229.54 460.33 P +1.92 (xample) 260.06 460.33 P +1.92 (, the) 292.14 460.33 P +3 F +1.92 (\322get\323) 318.23 460.33 P +0 F +1.92 ( message will be used to obtain the proper) 338.79 460.33 P +1.92 (ties) 542.44 460.33 P +3 F +3.16 (v) 180 448.33 P +3.16 (alue) 184.75 448.33 P +3.16 (, status and se) 203.5 448.33 P +3.16 (v) 277.71 448.33 P +3.16 (er) 282.46 448.33 P +3.16 (ity) 291.5 448.33 P +0 F +3.16 (from the) 307.44 448.33 P +3 F +3.16 (bdl) 353.21 448.33 P +0 F +3.16 ( attr) 366.55 448.33 P +3.16 (ib) 387.09 448.33 P +3.16 (ute of de) 394.67 448.33 P +3.16 (vice) 439.6 448.33 P +3 F +3.16 (MQB1S01) 463.32 448.33 P +0 F +3.16 (, the) 509.45 448.33 P +3 F +3.16 (\322set\323) 538 448.33 P +0 F +1.15 (message will then be used to cop) 180 436.33 P +1.15 (y the) 334.43 436.33 P +3 F +1.15 (v) 361.18 436.33 P +1.15 (alue) 365.93 436.33 P +0 F +1.15 ( proper) 384.83 436.33 P +1.15 (ty to the) 418.06 436.33 P +3 F +1.15 (bdl) 459.86 436.33 P +0 F +1.15 (attr) 477.13 436.33 P +1.15 (ib) 491.73 436.33 P +1.15 (ute of de) 499.31 436.33 P +1.15 (vice) 540.22 436.33 P +3 F +(MQB1S02) 180 424.33 T +0 F +(.) 226.13 424.33 T +3 9 Q +(Figure 4: Def) 180 391 T +(ault beha) 234.25 391 T +(vior of the \322get\323 and \322set\323 messages) 271.1 391 T +180 81 558 724 C +180 86.62 558 388 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.71 88.23 559.29 376.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +179.75 91.48 553.7 385.57 R +7 X +V +0 X +N +185 95.84 547.11 381.9 R +7 X +V +5 9 Q +0 X +(#include ) 185 375.9 T +(#include ) 185 364.9 T +(#include ) 185 353.9 T +(#include ) 185 342.9 T +(// ****************************************************************) 185 320.9 T +(// * The printError function will be used to output any error that) 185 309.9 T +(// * that occurs during the processing of the \322get\323 or \322set\323) 185 298.9 T +(// * messages.) 185 287.9 T +(// ****************************************************************) 185 276.9 T +(int printError \050int errCode\051) 185 265.9 T +({) 203 254.9 T +(switch\050errCode\051) 203 243.9 T +({) 221 232.9 T +(// ******* Unknown device or device/message mismatch ******) 221 221.9 T +(case CDEV_INVALIDOBJ:) 221 210.9 T +(printf\050\322Unknown device or device/message mismatch\134n\323\051;) 239 199.9 T +(break;) 239 188.9 T +(// * Communications error between application and service *) 221 166.9 T +(case CDEV_NOTCONNECTED:) 221 155.9 T +(case CDEV_IOFAILED:) 221 144.9 T +(case CDEV_TIMEOUT:) 221 133.9 T +(printf\050\322Communications error while sending\134n\323\051;) 239 122.9 T +(break;) 239 111.9 T +180 81 558 724 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "17" 25 +%%Page: "18" 26 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 54 739 T +(ault Ser) 77.74 739 T +(vice Beha) 109.03 739 T +(vior f) 148.37 739 T +(or Standard Messages) 167.6 739 T +0 10 Q +(18) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Figure 4: Def) 162 714 T +(ault beha) 216.25 714 T +(vior of the \322get\323 and \322set\323 messages \050contin) 253.1 714 T +(ued\051) 424.58 714 T +162 81 540 720 C +162 82.21 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.71 84.33 541.29 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +161.75 89.12 535.7 705 R +7 X +V +0 X +N +167 92.17 529.11 701.33 R +7 X +V +5 9 Q +0 X +(// ******* No data or bad data passed with message ********) 203 695.33 T +(case CDEV_INVALIDARG:) 203 684.33 T +(case CDEV_OUTOFRANGE:) 203 673.33 T +(case CDEV_NOTFOUND:) 203 662.33 T +(case CDEV_CONVERT:) 203 651.33 T +(printf\050\322Bad or missing value passed in message\134n\323\051;) 221 640.33 T +(break;) 221 629.33 T +(// ******************** Generic Error *********************) 203 607.33 T +(case CDEV_ERROR:) 203 596.33 T +(case default:) 203 585.33 T +(printf\050\322Unable to send message\134n\323\051;) 221 574.33 T +(break;) 221 563.33 T +(}) 203 552.33 T +(}) 185 541.33 T +(void main\050\051) 167 519.33 T +({) 185 508.33 T +(cdevRequestObject * req1, *req2;) 185 497.33 T +(cdevData ctx;) 185 486.33 T +(cdevData output, input;) 185 475.33 T +(double val;) 185 464.33 T +(int errorCode = CDEV_SUCCESS;) 185 453.33 T +(// ***********************************************************) 185 431.33 T +(// * Obtain a pointer to the cdevRequestObject for the) 185 420.33 T +(// * \322get bdl\323 message on device \322MQB1S01\323.) 185 409.33 T +(// ***********************************************************) 185 398.33 T +(req1 = cdevRequestObject::attachPtr\050\322MQB1S01\323, \322get bdl\323\051;) 185 387.33 T +(// ***********************************************************) 185 365.33 T +(// * Place a non-zero value in the properties value, status,) 185 354.33 T +(// * severity.) 185 343.33 T +(// ***********************************************************) 185 332.33 T +(ctx.set\050\322value\323, 1\051;) 185 321.33 T +(ctx.set\050\322status\323, 1\051;) 185 310.33 T +(ctx.set\050\322severity\323, 1\051;) 185 299.33 T +(// ***********************************************************) 185 277.33 T +(// * Set the context of the cdevRequestObject.) 185 266.33 T +(// ***********************************************************) 185 255.33 T +(req1->setContext\050ctx\051;) 185 244.33 T +(// ***********************************************************) 185 222.33 T +(// * Submit the message to the device and test the return) 185 211.33 T +(// * value to ensure that the message was processed correctly) 185 200.33 T +(// ***********************************************************) 185 189.33 T +(if\050\050errorCode=req1->send\050NULL, &output\051\051==CDEV_SUCCESS\051) 185 178.33 T +({) 203 167.33 T +(// ********************************************************) 203 156.33 T +(// * Message was transmitted and processed successfuly.) 203 145.33 T +(// ********************************************************) 203 134.33 T +(char stat[50], sev[255];) 203 123.33 T +(output.get\050\322value\323, &val\051;) 203 112.33 T +(output.get\050\322status\323, stat, 50\051;) 203 101.33 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "18" 26 +%%Page: "19" 27 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 353.86 739 T +(ault Ser) 377.6 739 T +(vice Beha) 408.89 739 T +(vior f) 448.23 739 T +(or Standard Messages) 467.46 739 T +0 10 Q +(19) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 4: Def) 180 714 T +(ault beha) 234.25 714 T +(vior of the \322get\323 and \322set\323 messages) 271.1 714 T +2 10 Q +(\322monitorOn\323) 72 320.98 T +(Messa) 72 308.98 T +(g) 102.47 308.98 T +(e) 108.68 308.98 T +0 F +3.52 (The) 180 320.98 P +3 F +3.52 (\322monitorOn\323) 203.52 320.98 P +0 F +3.52 ( v) 256.86 320.98 P +3.52 (erb can be joined with an) 267.91 320.98 P +3.52 (y) 396.51 320.98 P +3 F +3.52 (attr) 407.8 320.98 P +3.52 (ib) 422.4 320.98 P +3.52 (ute) 429.98 320.98 P +0 F +3.52 ( of a de) 443.88 320.98 P +3.52 (vice to f) 487.48 320.98 P +3.52 (or) 528.67 320.98 P +3.52 (m a) 537.82 320.98 P +-0.02 (\322) 180 308.98 P +3 F +-0.02 (monitorOn) 183.33 308.98 P +0 F +-0.02 (\323 message) 230.01 308.98 P +-0.02 (. This message is tells the cde) 276.52 308.98 P +-0.02 (vDe) 410.02 308.98 P +-0.02 (vice that each time one of the) 427.5 308.98 P +0.61 (monitored) 180 296.98 P +3 F +0.61 (proper) 227.85 296.98 P +0.61 (ties) 257.15 296.98 P +0 F +0.61 ( changes) 272.71 296.98 P +0.61 (, it should call the user speci\336ed callbac) 313.74 296.98 P +0.61 (k function with) 493.42 296.98 P +6.26 (the updated v) 180 284.98 P +6.26 (alue) 252.87 284.98 P +6.26 (. This message should alw) 271.62 284.98 P +6.26 (a) 414.32 284.98 P +6.26 (ys be submitted using the) 419.58 284.98 P +2 F +1.13 (sendCallbac) 180 272.98 P +1.13 (k) 238.71 272.98 P +0 F +1.13 (method of the cde) 248.18 272.98 P +1.13 (vDe) 331.32 272.98 P +1.13 (vice or cde) 348.8 272.98 P +1.13 (vRequestObject in order to pro) 399.12 272.98 P +1.13 (vide) 539.66 272.98 P +(the address of the callbac) 180 260.98 T +(k function.) 293.75 260.98 T +(The f) 180 243.98 T +(ollo) 202.49 243.98 T +(wing steps should be e) 217.9 243.98 T +(x) 319.32 243.98 T +(ecuted in order to submit a) 324.02 243.98 T +3 F +(\322monitorOn\323) 445.19 243.98 T +0 F +( message) 498.53 243.98 T +(.) 541.73 243.98 T +(1.) 180 226.98 T +(Obtain a pointer to the) 198 226.98 T +3 F +(cde) 299.73 226.98 T +(vDe) 315.55 226.98 T +(vice) 333.03 226.98 T +0 F +( object f) 350.81 226.98 T +(or the de) 385.53 226.98 T +(vice that y) 424.7 226.98 T +(ou wish to address) 469.52 226.98 T +(.) 552.74 226.98 T +(2.) 180 202.98 T +(Create a message str) 198 202.98 T +(ing b) 293.74 202.98 T +(y concatenating the) 315.22 202.98 T +3 F +(attr) 404.72 202.98 T +(ib) 419.32 202.98 T +(ute) 426.9 202.98 T +0 F +(that y) 443.58 202.98 T +(ou wish to address) 467.84 202.98 T +-0.38 (to the) 198 190.98 P +3 F +-0.38 (\322monitorOn\323) 225.04 190.98 P +0 F +-0.38 ( v) 278.38 190.98 P +-0.38 (erb) 285.53 190.98 P +-0.38 (. F) 299.58 190.98 P +-0.38 (or instance) 310.57 190.98 P +-0.38 (, to monitor a proper) 358.95 190.98 P +-0.38 (ty of the) 447.86 190.98 P +3 F +-0.38 (bdl) 485.08 190.98 P +0 F +-0.38 ( attr) 498.42 190.98 P +-0.38 (ib) 515.42 190.98 P +-0.38 (ute of a) 523 190.98 P +(de) 198 178.98 T +(vice) 208.82 178.98 T +(, the message str) 226.45 178.98 T +(ing should be:) 303.3 178.98 T +4 F +(\322monitorOn bdl\323) 368.34 178.98 T +0 F +(.) 447.23 178.98 T +(3.) 180 154.98 T +(Optionally) 198 154.98 T +(, use the cde) 241.46 154.98 T +(vDe) 298.42 154.98 T +(vice object created in step 1 and the message str) 315.9 154.98 T +(ing) 533.38 154.98 T +(created in step 2 to obtain a pointer to a) 198 142.98 T +3 F +(cde) 377 142.98 T +(vRequestObject) 392.82 142.98 T +0 F +(object.) 466.74 142.98 T +(4.) 180 118.98 T +-0.41 (Set the) 198 118.98 P +3 F +-0.41 (conte) 231.65 118.98 P +-0.41 (xt) 255.81 118.98 P +0 F +-0.41 (of the cde) 265.95 118.98 P +-0.41 (vDe) 308.75 118.98 P +-0.41 (vice or cde) 326.23 118.98 P +-0.41 (vRequestObject to indicate the) 373.46 118.98 P +3 F +-0.41 (proper) 510.77 118.98 P +-0.41 (ties) 540.07 118.98 P +0 F +(that y) 198 106.98 T +(ou wish to monitor) 222.26 106.98 T +(, and the) 302.9 106.98 T +3 F +(proper) 344.6 106.98 T +(ties) 373.9 106.98 T +0 F +( y) 389.46 106.98 T +(ou wish to receiv) 397.04 106.98 T +(e when a change) 471.26 106.98 T +(occurs) 198 94.98 T +(. The conte) 227.3 94.98 T +(xt used b) 277.03 94.98 T +(y the \322) 317.41 94.98 T +3 F +(monitorOn) 345.2 94.98 T +0 F +(\323 message diff) 391.88 94.98 T +(ers from that of the) 454.38 94.98 T +180 346.64 558 720 C +180 346.64 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.21 349.93 559.79 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +180.25 353.17 554.2 705 R +7 X +V +0 X +N +185.5 358.6 547.61 701.33 R +7 X +V +5 9 Q +0 X +(output.get\050\322severity\323, sev, 50\051;) 221.5 695.33 T +(printf\050\322Val:%f, status:%s, severity:%s\323, val, stat, sev\051;) 221.5 684.33 T +(}) 221.5 673.33 T +(else printError\050errorCode\051;) 203.5 662.33 T +(// ***********************************************************) 203.5 640.33 T +(// * Obtain a pointer to the cdevRequestObject for the) 203.5 629.33 T +(// * \322set bdl\323 message on device \322MQB1S02\323.) 203.5 618.33 T +(// ***********************************************************) 203.5 607.33 T +(req2 = cdevRequestObject::attachPtr\050\322MQB1S02\323, \322set bdl\323\051;) 203.5 596.33 T +(// ***********************************************************) 203.5 574.33 T +(// * Insert the new value into the input cdevData object.) 203.5 563.33 T +(// ***********************************************************) 203.5 552.33 T +(input.insert\050\322value\323, value\051;) 203.5 541.33 T +(// ***********************************************************) 203.5 519.33 T +(// * Submit the message) 203.5 508.33 T +6 F +(\322set bdl\323) 333.1 508.33 T +5 F +(to the device and test) 387.1 508.33 T +(// * the return value to ensure that the message was) 203.5 497.33 T +(// * processed successfully. Note that, by default, the set) 203.5 486.33 T +(// * message does not generate any output.) 203.5 475.33 T +(// ***********************************************************) 203.5 464.33 T +(if\050\050errorCode==req2->send\050&input, NULL\051\051==CDEV_SUCCESS\051) 203.5 453.33 T +({) 221.5 442.33 T +(// ********************************************************) 221.5 431.33 T +(// * Message was transmitted and processed successfuly.) 221.5 420.33 T +(// ********************************************************) 221.5 409.33 T +(printf\050\322Message was transmitted successfully\134n\323\051;) 221.5 398.33 T +(}) 221.5 387.33 T +(else printError\050errorCode\051;) 203.5 376.33 T +(}) 203.5 365.33 T +180 346.64 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "19" 27 +%%Page: "20" 28 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 54 739 T +(ault Ser) 77.74 739 T +(vice Beha) 109.03 739 T +(vior f) 148.37 739 T +(or Standard Messages) 167.6 739 T +0 10 Q +(20) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 10 Q +(\322get\323) 180 713.33 T +0 F +( message in that diff) 200.56 713.33 T +(erent non-z) 289.75 713.33 T +(ero v) 340.18 713.33 T +(alues ha) 362.16 713.33 T +(v) 399.76 713.33 T +(e special meanings) 404.51 713.33 T +(. The) 489.95 713.33 T +(f) 180 701.33 T +(ollo) 182.48 701.33 T +(wing is a list of integer v) 197.89 701.33 T +(alues that should be suppor) 303.79 701.33 T +(ted b) 427.04 701.33 T +(y the conte) 449.08 701.33 T +(xt of a) 497.7 701.33 T +(\322) 180 689.33 T +3 F +(monitorOn) 183.33 689.33 T +0 F +(\323 message) 230.01 689.33 T +(.) 276.54 689.33 T +2 F +(0) 180 665.33 T +0 F +(The v) 314.62 665.33 T +(alue of this proper) 339.38 665.33 T +(ty should ne) 419.82 665.33 T +(v) 473.44 665.33 T +(er be) 478.19 665.33 T +(retur) 315.12 653.33 T +(ned.) 335.93 653.33 T +2 F +(1) 180 629.33 T +0 F +(This proper) 314.62 629.33 T +(ty should not be monitored, b) 365.59 629.33 T +(ut it) 494.35 629.33 T +(should be retur) 315.12 617.33 T +(ned as conte) 382.07 617.33 T +(xt when a monitored) 439.03 617.33 T +(v) 315.12 605.33 T +(alue changes; e) 319.87 605.33 T +(.g. a time stamp) 390.32 605.33 T +(.) 461.11 605.33 T +2 F +(2) 180 581.33 T +0 F +(Monitor this proper) 314.62 581.33 T +(ty and call the callbac) 398.38 581.33 T +(k function) 493.78 581.33 T +-0.41 (when it changes) 315.12 569.33 P +-0.41 (, ho) 386.4 569.33 P +-0.41 (w) 402.52 569.33 P +-0.41 (e) 409.64 569.33 P +-0.41 (v) 414.9 569.33 P +-0.41 (er) 419.65 569.33 P +-0.41 (, retur) 428.04 569.33 P +-0.41 (n only this proper) 453.99 569.33 P +-0.41 (ty) 529.85 569.33 P +(in the resultant cde) 315.12 557.33 T +(vData object.) 399.31 557.33 T +2 F +(3) 180 533.33 T +0 F +(Monitor this proper) 314.62 533.33 T +(ty and call the) 398.38 533.33 T +( callbac) 460.08 533.33 T +(k function) 493.78 533.33 T +(when it changes and include the v) 315.12 521.33 T +(alue of all) 465.51 521.33 T +(proper) 315.12 509.33 T +(ties whose conte) 344.42 509.33 T +(xt is 1 in the resultant) 418.6 509.33 T +(cde) 315.12 497.33 T +(vData object.) 330.94 497.33 T +(5.) 162 473.33 T +(Create a) 180 473.33 T +3 F +(cde) 221.13 473.33 T +(vCallbac) 236.95 473.33 T +(k) 275.09 473.33 T +0 F +( object that contains the address of the cde) 280.09 473.33 T +(vCallbac) 470.46 473.33 T +(k) 508.6 473.33 T +(function and a v) 180 461.33 T +(oid pointer to an) 250.35 461.33 T +(y user argument that should be pro) 321.91 461.33 T +(vided to the) 476.84 461.33 T +(callbac) 180 449.33 T +(k function.) 210.92 449.33 T +(6.) 162 425.33 T +(Use the) 180 425.33 T +4 F +(sendCallbac) 217.24 425.33 T +(k) 275.95 425.33 T +0 F +( message to submit the message to the de) 281.51 425.33 T +(vice) 469.64 425.33 T +(.) 487.27 425.33 T +(7.) 162 401.33 T +-0.15 (Ev) 180 401.33 P +-0.15 (aluate the retur) 191.42 401.33 P +-0.15 (n v) 258.64 401.33 P +-0.15 (alue from the speci\336c) 271.58 401.33 P +4 F +-0.15 (sendCallbac) 368.25 401.33 P +-0.15 (k) 426.96 401.33 P +0 F +-0.15 (command to deter) 435.15 401.33 P +-0.15 (mine) 515.7 401.33 P +(if the message w) 180 389.33 T +(as tr) 254.88 389.33 T +(ansmitted successful. An) 274.23 389.33 T +(y v) 384.68 389.33 T +(alue other than) 397.21 389.33 T +4 F +(CDEV_SUCCESS) 180 377.33 T +0 F +(indicates that the message w) 264.46 377.33 T +(as not tr) 393.26 377.33 T +(ansmitted successfully) 429.29 377.33 T +(.) 528.32 377.33 T +(8.) 162 353.33 T +(Monitor the status retur) 180 353.33 T +(ned to the) 283.07 353.33 T +3 F +(cde) 330.33 353.33 T +(vCallbac) 346.15 353.33 T +(kFunction) 384.29 353.33 T +0 F +(to deter) 430.42 353.33 T +(mine if the) 464.58 353.33 T +(callbac) 180 341.33 T +(k is oper) 210.92 341.33 T +(ating correctly) 248.61 341.33 T +(. An) 309.85 341.33 T +(y of the f) 327.49 341.33 T +(ollo) 365.55 341.33 T +(wing v) 380.96 341.33 T +(alues ma) 409.05 341.33 T +(y be retur) 449.32 341.33 T +(ned in the) 491.81 341.33 T +3 F +(status) 180 329.33 T +0 F +( par) 206.68 329.33 T +(ameter) 223.81 329.33 T +(.) 254.43 329.33 T +2 F +(CDEV_SUCCESS:) 180 305.33 T +0 F +2.07 (The v) 326.29 305.33 P +2.07 (alue has changed and the ne) 353.11 305.33 P +2.07 (w v) 492.22 305.33 P +2.07 (alue is) 509.04 305.33 P +0.31 (stored in the cde) 326.43 293.33 P +0.31 (vData par) 400.99 293.33 P +0.31 (ameter) 444.55 293.33 P +0.31 (. This status is) 475.17 293.33 P +1.6 (also gener) 326.43 281.33 P +1.6 (ated when the monitorOn command) 374.63 281.33 P +(is initially issued.) 326.43 269.33 T +2 F +(CDEV_DISCONNECTED:) 180 252.33 T +0 F +4.32 (The connection has been lost betw) 326.29 252.33 P +4.32 (een the) 502.32 252.33 P +(application and the ser) 326.43 240.33 T +(v) 427.34 240.33 T +(er) 432.09 240.33 T +(.) 440.48 240.33 T +2 F +(CDEV_RECONNECTED:) 180 223.33 T +0 F +0.24 (The connection betw) 326.29 223.33 P +0.24 (een the application and the) 418.95 223.33 P +0.23 (ser) 326.43 211.33 P +0.23 (v) 340.62 211.33 P +0.23 (er has been re-estab) 345.37 211.33 P +0.23 (lished and the updated) 438.13 211.33 P +(v) 326.43 199.33 T +(alue is a) 331.18 199.33 T +(v) 368.22 199.33 T +(ailab) 372.97 199.33 T +(le in the cde) 393.89 199.33 T +(vData par) 447.51 199.33 T +(ameter) 490.76 199.33 T +(.) 521.38 199.33 T +2 F +(CDEV_ERR) 180 182.33 T +(OR:) 234.25 182.33 T +0 F +(The message w) 326.29 182.33 T +(as not processed successfully) 396.72 182.33 T +(.) 528.55 182.33 T +2 F +(CDEV_INV) 180 165.33 T +(ALIDOBJ:) 229.21 165.33 T +0 F +(In) 326.29 165.33 T +(v) 334.43 165.33 T +(alid cde) 339.18 165.33 T +(v request object used.) 373.34 165.33 T +2 F +(CDEV_INV) 180 148.33 T +(ALID) 229.21 148.33 T +(ARG:) 252.14 148.33 T +0 F +(In) 326.29 148.33 T +(v) 334.43 148.33 T +(alid argument passed to cde) 339.18 148.33 T +(v call.) 464.5 148.33 T +2 F +(CDEV_INV) 180 131.33 T +(ALIDSVC:) 229.21 131.33 T +0 F +(Wrong ser) 326.29 131.33 T +(vice dur) 372.71 131.33 T +(ing dynamic loading.) 407.87 131.33 T +2 F +(CDEV_NO) 180 114.33 T +(TCONNECTED:) 227.94 114.33 T +0 F +(Not connected to lo) 326.29 114.33 T +(w le) 412.3 114.33 T +(v) 429.78 114.33 T +(el netw) 434.53 114.33 T +(or) 466.11 114.33 T +(k ser) 475.15 114.33 T +(vice) 497.12 114.33 T +(.) 514.75 114.33 T +2 F +(CDEV_IOF) 180 97.33 T +(AILED:) 229.21 97.33 T +0 F +(Lo) 326.29 97.33 T +(w le) 337.26 97.33 T +(v) 354.74 97.33 T +(el netw) 359.49 97.33 T +(or) 391.07 97.33 T +(k ser) 400.11 97.33 T +(vice IO f) 422.08 97.33 T +(ailed.) 458.46 97.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "20" 28 +%%Page: "21" 29 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 353.86 739 T +(ault Ser) 377.6 739 T +(vice Beha) 408.89 739 T +(vior f) 448.23 739 T +(or Standard Messages) 467.46 739 T +0 10 Q +(21) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_CONFLICT) 198 713.33 T +(:) 281.49 713.33 T +0 F +(Con\337icts of data types or tags) 344.29 713.33 T +(.) 475.87 713.33 T +2 F +(CDEV_NO) 198 696.33 T +(TFOUND:) 245.94 696.33 T +0 F +(Cannot \336nd speci\336ed data in cde) 344.29 696.33 T +(vData.) 489.07 696.33 T +2 F +(CDEV_TIMEOUT) 198 679.33 T +(:) 275.94 679.33 T +0 F +(Time out.) 344.29 679.33 T +2 F +(CDEV_CONVER) 198 662.33 T +(T) 273.92 662.33 T +(:) 279.63 662.33 T +0 F +(cde) 344.29 662.33 T +(vData con) 360.11 662.33 T +(v) 404.93 662.33 T +(ersion error) 409.68 662.33 T +(.) 460.3 662.33 T +2 F +(CDEV_OUT) 198 645.33 T +(OFRANGE:) 252.05 645.33 T +0 F +(V) 344.29 645.33 T +(alue out of r) 350.26 645.33 T +(ange f) 402.97 645.33 T +(or de) 430.47 645.33 T +(vice attr) 452.96 645.33 T +(ib) 488.12 645.33 T +(ute) 495.7 645.33 T +(.) 509.45 645.33 T +2 F +(CDEV_NO) 198 628.33 T +(A) 245.84 628.33 T +(CCESS:) 252.66 628.33 T +0 F +(Insuf\336cient access to perf) 344.29 628.33 T +(or) 456.82 628.33 T +(m request.) 465.96 628.33 T +2 F +(CDEV_A) 198 611.33 T +(CCESSCHANGED:) 238.16 611.33 T +0 F +(Change in access per) 344.29 611.33 T +(mission of de) 441.25 611.33 T +(vice) 499.86 611.33 T +(.) 517.49 611.33 T +(9.) 180 594.33 T +(Because the monitorOn command is a single message that ma) 198 594.33 T +(y gener) 476.15 594.33 T +(ate man) 509.4 594.33 T +(y) 545.38 594.33 T +(responses) 198 582.33 T +(, the de) 243.98 582.33 T +(v) 277.04 582.33 T +(eloper ma) 281.79 582.33 T +(y ha) 325.95 582.33 T +(v) 344.65 582.33 T +(e dif\336culty in deter) 349.4 582.33 T +(mining when the last reply) 430.24 582.33 T +(has been receiv) 198 570.33 T +(ed. In order to accomodate this) 268.34 570.33 T +(, the de) 408.82 570.33 T +(v) 441.88 570.33 T +(eloper ma) 446.63 570.33 T +(y call the) 490.79 570.33 T +(cde) 198 558.33 T +(vCallbac) 213.82 558.33 T +(k::isT) 251.96 558.33 T +(r) 274.65 558.33 T +(ansactionDone\050\051 method to deter) 277.88 558.33 T +(mine if the callbac) 424.31 558.33 T +(k that is) 504.14 558.33 T +(being processed is the last one that is associated with that request. The ser) 198 546.33 T +(vice) 534.58 546.33 T +-0.48 (de) 198 534.33 P +-0.48 (v) 208.82 534.33 P +-0.48 (eloper is e) 213.57 534.33 P +-0.48 (xpected to use the cde) 258.44 534.33 P +-0.48 (vCallbac) 356.83 534.33 P +-0.48 (k::\336reCallbac) 394.97 534.33 P +-0.48 (k method to ensure that) 452.56 534.33 P +(this par) 198 522.33 T +(ameter is set to the proper v) 230.69 522.33 T +(alue) 354.94 522.33 T +(.) 373.69 522.33 T +2 F +(\322monitorOff) 72 493.33 T +(\323) 128.96 493.33 T +(Messa) 72 481.33 T +(g) 102.47 481.33 T +(e) 108.68 481.33 T +0 F +3.47 (The) 180 493.33 P +3 F +3.47 (\322monitorOff) 203.48 493.33 P +3.47 (\323) 254.09 493.33 P +0 F +3.47 ( v) 257.42 493.33 P +3.47 (erb can be joined with an) 268.42 493.33 P +3.47 (y) 396.8 493.33 P +3 F +3.47 (attr) 408.06 493.33 P +3.47 (ib) 422.66 493.33 P +3.47 (ute) 430.24 493.33 P +0 F +3.47 ( of a de) 444.14 493.33 P +3.47 (vice to f) 487.61 493.33 P +3.47 (or) 528.72 493.33 P +3.47 (m a) 537.86 493.33 P +4.44 (\322) 180 481.33 P +3 F +4.44 (monitorOff) 183.33 481.33 P +0 F +4.44 (\323 message) 230.61 481.33 P +4.44 (. This message is tells the cde) 281.58 481.33 P +4.44 (vDe) 441.85 481.33 P +4.44 (vice to deactiv) 459.33 481.33 P +4.44 (ate a) 531.32 481.33 P +(monitorOn command that w) 180 469.33 T +(as pre) 302.67 469.33 T +(viously set on one or more of its attr) 330.16 469.33 T +(ib) 488.71 469.33 T +(utes) 496.29 469.33 T +(.) 515.04 469.33 T +1.5 (This message should alw) 180 452.33 P +1.5 (a) 296.6 452.33 P +1.5 (ys be called using the) 301.86 452.33 P +3 F +1.5 (sendCallbac) 408.27 452.33 P +1.5 (k) 463.09 452.33 P +0 F +1.5 ( method in order to) 468.09 452.33 P +(specify the address of the callbac) 180 440.33 T +(k function that w) 327.65 440.33 T +(as used in creating the monitor) 399.76 440.33 T +(.) 535.99 440.33 T +(The ser) 180 423.33 T +(vice chec) 214.2 423.33 T +(ks the f) 255.68 423.33 T +(ollo) 287.62 423.33 T +(wing things to deter) 303.03 423.33 T +(mine which monitor is to be remo) 389.99 423.33 T +(v) 536.55 423.33 T +(ed.) 541.3 423.33 T +2 F +(de) 198 406.33 T +(vice) 209.52 406.33 T +0 F +1.94 (The ser) 344.29 406.33 P +1.94 (vice will locate all activ) 380.43 406.33 P +1.94 (e monitors that) 487.97 406.33 P +(ha) 344.43 394.33 T +(v) 355.35 394.33 T +(e been placed on the speci\336ed de) 360.1 394.33 T +(vice) 509.34 394.33 T +(.) 526.97 394.33 T +2 F +(attrib) 198 377.33 T +(ute) 222.8 377.33 T +0 F +0.82 (F) 344.29 377.33 P +0.82 (rom the list of obtained abo) 349.95 377.33 P +0.82 (v) 474.51 377.33 P +0.82 (e) 479.26 377.33 P +0.82 (, the ser) 484.67 377.33 P +0.82 (vice will) 522.74 377.33 P +5.25 (locate all activ) 344.43 365.33 P +5.25 (e monitors on the speci\336ed) 417.49 365.33 P +(attr) 344.43 353.33 T +(ib) 359.03 353.33 T +(ute) 366.61 353.33 T +(.) 380.36 353.33 T +2 F +(function) 198 336.33 T +0 F +2.53 (F) 344.29 336.33 P +2.53 (rom the list obtained abo) 349.95 336.33 P +2.53 (v) 469.4 336.33 P +2.53 (e) 474.15 336.33 P +2.53 (, the ser) 479.56 336.33 P +2.53 (vice will) 521.03 336.33 P +0.28 (locate all activ) 344.43 324.33 P +0.28 (e monitors that ha) 407.54 324.33 P +0.28 (v) 488.21 324.33 P +0.28 (e the speci\336ed) 492.96 324.33 P +0.98 (callbac) 344.43 312.33 P +0.98 (k function. If this v) 375.35 312.33 P +0.98 (alue is NULL, then all) 459.05 312.33 P +(elements from the pre) 344.43 300.33 T +(vious list will be remo) 441.39 300.33 T +(v) 535.7 300.33 T +(ed.) 540.45 300.33 T +2 F +(userar) 198 283.33 T +(g) 228.42 283.33 T +0 F +2.53 (F) 344.29 283.33 P +2.53 (rom the list obtained abo) 349.95 283.33 P +2.53 (v) 469.4 283.33 P +2.53 (e) 474.15 283.33 P +2.53 (, the ser) 479.56 283.33 P +2.53 (vice will) 521.03 283.33 P +2.52 (locate and remo) 344.43 271.33 P +2.52 (v) 421.03 271.33 P +2.52 (e all monitors that ha) 425.78 271.33 P +2.52 (v) 528.49 271.33 P +2.52 (e the) 533.24 271.33 P +0.33 (same user argument. If this v) 344.43 259.33 P +0.33 (alue is NULL, then) 474.76 259.33 P +4.99 (all elements from the pre) 344.43 247.33 P +4.99 (vious list will be) 474.13 247.33 P +(remo) 344.43 235.33 T +(v) 367.06 235.33 T +(ed.) 371.81 235.33 T +(The f) 180 218.33 T +(ollo) 202.49 218.33 T +(wing steps should be e) 217.9 218.33 T +(x) 319.32 218.33 T +(ecuted in order to submit a) 324.02 218.33 T +3 F +(\322monitorOff) 445.19 218.33 T +(\323) 495.8 218.33 T +0 F +( message) 499.13 218.33 T +(.) 542.33 218.33 T +(1.) 180 201.33 T +(Obtain a pointer to the) 198 201.33 T +3 F +(cde) 299.73 201.33 T +(vDe) 315.55 201.33 T +(vice) 333.03 201.33 T +0 F +( object f) 350.81 201.33 T +(or the de) 385.53 201.33 T +(vice that y) 424.7 201.33 T +(ou wish to address) 469.52 201.33 T +(.) 552.74 201.33 T +(2.) 180 177.33 T +(Create a message str) 198 177.33 T +(ing b) 293.74 177.33 T +(y concatenating the) 315.22 177.33 T +3 F +(attr) 404.72 177.33 T +(ib) 419.32 177.33 T +(ute) 426.9 177.33 T +0 F +(that y) 443.58 177.33 T +(ou wish to address) 467.84 177.33 T +-0.42 (to the) 198 165.33 P +3 F +-0.42 (\322monitorOff) 224.96 165.33 P +-0.42 (\323) 275.57 165.33 P +0 F +-0.42 ( v) 278.9 165.33 P +-0.42 (erb) 286.02 165.33 P +-0.42 (. F) 300.07 165.33 P +-0.42 (or instance) 311.02 165.33 P +-0.42 (, to monitor a proper) 359.36 165.33 P +-0.42 (ty of the) 448.13 165.33 P +3 F +-0.42 (bdl) 485.23 165.33 P +0 F +-0.42 ( attr) 498.57 165.33 P +-0.42 (ib) 515.53 165.33 P +-0.42 (ute of a) 523.11 165.33 P +(de) 198 153.33 T +(vice) 208.82 153.33 T +(, the message str) 226.45 153.33 T +(ing should be:) 303.3 153.33 T +4 F +(\322monitorOn bdl\323) 368.34 153.33 T +0 F +(.) 447.23 153.33 T +(3.) 180 129.33 T +(Optionally) 198 129.33 T +(, use the cde) 241.46 129.33 T +(vDe) 298.42 129.33 T +(vice object created in step 1 and the message str) 315.9 129.33 T +(ing) 533.38 129.33 T +(created in step 2 to obtain a pointer to a) 198 117.33 T +3 F +(cde) 377 117.33 T +(vRequestObject) 392.82 117.33 T +0 F +(object.) 466.74 117.33 T +(4.) 180 93.33 T +(Create a) 198 93.33 T +3 F +(cde) 239.13 93.33 T +(vCallbac) 254.95 93.33 T +(k) 293.09 93.33 T +0 F +( object that contains the address of the cde) 298.09 93.33 T +(vCallbac) 488.46 93.33 T +(k) 526.6 93.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "21" 29 +%%Page: "22" 30 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 54 739 T +(ault Ser) 77.74 739 T +(vice Beha) 109.03 739 T +(vior f) 148.37 739 T +(or Standard Messages) 167.6 739 T +0 10 Q +(22) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +-0.39 (function and a v) 180 713.33 P +-0.39 (oid pointer to the user argument that w) 249.17 713.33 P +-0.39 (as or) 417.47 713.33 P +-0.39 (iginally pro) 439.45 713.33 P +-0.39 (vided to the) 486.7 713.33 P +(monitorOn message) 180 701.33 T +(.) 269.88 701.33 T +(5.) 162 677.33 T +(Use the) 180 677.33 T +4 F +(sendCallbac) 217.24 677.33 T +(k) 275.95 677.33 T +0 F +( message to submit the message to the de) 281.51 677.33 T +(vice) 469.64 677.33 T +(.) 487.27 677.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "22" 30 +%%Page: "23" 31 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 353.86 739 T +(ault Ser) 377.6 739 T +(vice Beha) 408.89 739 T +(vior f) 448.23 739 T +(or Standard Messages) 467.46 739 T +0 10 Q +(23) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (The f) 180 713.33 P +2.12 (ollo) 204.6 713.33 P +2.12 (wing e) 220.01 713.33 P +2.12 (xample illustr) 250.73 713.33 P +2.12 (ates ho) 311.09 713.33 P +2.12 (w to use the) 345.85 713.33 P +3 F +2.12 (\322monitorOn\323) 411.01 713.33 P +0 F +2.12 ( and) 464.35 713.33 P +3 F +2.12 (\322monitorOff) 490.82 713.33 P +2.12 (\323) 541.43 713.33 P +0 F +2.12 ( to) 544.76 713.33 P +1.24 (install and remo) 180 701.33 P +1.24 (v) 252.9 701.33 P +1.24 (e monitors) 257.65 701.33 P +1.24 (. This e) 305.42 701.33 P +1.24 (xample also demonstr) 340.38 701.33 P +1.24 (ates the to correct w) 440.55 701.33 P +1.24 (a) 535.39 701.33 P +1.24 (y to) 540.65 701.33 P +(utiliz) 180 689.33 T +(e the cde) 199.85 689.33 T +(vCallbac) 240.69 689.33 T +(k function.) 278.83 689.33 T +3 9 Q +(Figure 5: Def) 180 656 T +(ault beha) 234.25 656 T +(vior of the \322monitorOn\323 and \322monitorOff) 271.1 656 T +(\323 messages) 426.69 656 T +180 81 558 720 C +180 82.38 558 653 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.71 84.66 559.29 641.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +179.75 90.29 553.7 647 R +7 X +V +0 X +N +185 94.17 547.11 643.33 R +7 X +V +5 9 Q +0 X +(#include ) 185 637.33 T +(#include ) 185 626.33 T +(#include ) 185 615.33 T +(#include ) 185 604.33 T +(#include ) 185 593.33 T +(// ****************************************************************) 185 571.33 T +(// * This is the callback function that will be executed each time) 185 560.33 T +(// * one of my monitored values changes.) 185 549.33 T +(// ****************************************************************) 185 538.33 T +(void callback \050int status, void * userarg,) 185 527.33 T +( cdevRequestObject & req, cdevData & data\051) 257 516.33 T +({) 203 505.33 T +(switch\050status\051) 203 494.33 T +({) 221 483.33 T +(// *********************************************************) 221 472.33 T +(// * If I receive one of these message then I know that) 221 461.33 T +(// * updated data is available in the cdevData object.) 221 450.33 T +(// *********************************************************) 221 439.33 T +(case CDEV_SUCCESS:) 221 428.33 T +(case CDEV_RECONNECTED:) 221 417.33 T +(// ******************************************************) 239 406.33 T +(// * I will call the getType method to determine if the) 239 395.33 T +(// * value attribuite is present in the cdevData object.) 239 384.33 T +(// * If it is, then I will known that it is responsible) 239 373.33 T +(// * for triggering this callback.) 239 362.33 T +(// ******************************************************) 239 351.33 T +(if\050data.getType\050\322value\323\051!=CDEV_INVALID\051) 239 340.33 T +({) 257 329.33 T +(// **************************************************) 257 318.33 T +(// * I have specified that I wanted status and) 257 307.33 T +(// * severity to be returned as context whenever the) 257 296.33 T +(// * value property has changed. Therefore, I will) 257 285.33 T +(// * output all of these properties.) 257 274.33 T +(// **************************************************) 257 263.33 T +(double * valPtr;) 257 252.33 T +(char * statPtr;) 257 241.33 T +(char * sevPtr;) 257 230.33 T +(data.find\050\322value\323, \050void *&\051valPtr\051;) 257 219.33 T +(data.find\050\322status\323, \050void *&\051statPtr\051;) 257 208.33 T +(data.find\050\322severity\323, \050void *&\051sevPtr\051;) 257 197.33 T +(printf\050\322Val:%f, status:%s, severity:%s\323,) 257 186.33 T +(*valPtr, statPtr, sevPtr\051;) 293 175.33 T +(}) 257 164.33 T +(// ******************************************************) 239 153.33 T +(// * I will call the getType method of the cdevData) 239 142.33 T +(// * object to determine if the controlHigh property is) 239 131.33 T +(// * present. If it is, I will know that it triggered) 239 120.33 T +(// * this callback.) 239 109.33 T +(// ******************************************************) 239 98.33 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "23" 31 +%%Page: "24" 32 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 54 739 T +(ault Ser) 77.74 739 T +(vice Beha) 109.03 739 T +(vior f) 148.37 739 T +(or Standard Messages) 167.6 739 T +0 10 Q +(24) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Figure 5: Def) 162 714 T +(ault beha) 216.25 714 T +(vior of the \322monitorOn\323 and \322monitorOff) 253.1 714 T +(\323 messages \050contin) 408.69 714 T +(ued\051) 484.62 714 T +162 81 540 720 C +162 83.21 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.21 85.16 541.79 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +162.25 89.12 536.2 705 R +7 X +V +0 X +N +167.5 93.84 529.61 701.33 R +7 X +V +5 9 Q +0 X +(else if\050getType\050\322controlHigh\323\051!=CDEV_INVALID\051) 221.5 695.33 T +({) 239.5 684.33 T +(double * controlPtr;) 239.5 673.33 T +(data.find\050\322controlHigh\323, \050void *&\051 controlPtr\051;) 239.5 662.33 T +(printf\050\322Control High is now %f\134n\323, *controlPtr\051;) 239.5 651.33 T +(}) 239.5 640.33 T +(break;) 203.5 629.33 T +(// *********************************************************) 203.5 607.33 T +(// * This status indicates that the connection has been lost) 203.5 596.33 T +(// * between the application and the server.) 203.5 585.33 T +(// *********************************************************) 203.5 574.33 T +(case CDEV_DISCONNECTED:) 203.5 563.33 T +(fprintf\050stderr, \322Connection lost to server\134n\323\051;) 221.5 552.33 T +(break;) 221.5 541.33 T +(// *********************************************************) 203.5 519.33 T +(// * This status indicates that an error occurred while) 203.5 508.33 T +(// * installing or operating the monitor.) 203.5 497.33 T +(// *********************************************************) 203.5 486.33 T +(case CDEV_ERROR:) 203.5 475.33 T +(fprintf\050stderr, \322Error while monitoring\323\051;) 221.5 464.33 T +(break;) 221.5 453.33 T +(}) 203.5 442.33 T +(}) 185.5 431.33 T +(void main\050\051) 167.5 409.33 T +({) 185.5 398.33 T +(cdevSystem * system;) 185.5 387.33 T +(cdevDevice * dev;) 185.5 376.33 T +(cdevRequestObject * req;) 185.5 365.33 T +(cdevData ctx;) 185.5 354.33 T +(// ***********************************************************) 185.5 332.33 T +(// * Construct a cdevCallback object that has a pointer to the) 185.5 321.33 T +(// * cdevCallback function and a NULL user argument.) 185.5 310.33 T +(// ***********************************************************) 185.5 299.33 T +(cdevCallback cb\050callback, NULL\051;) 185.5 288.33 T +(// ***********************************************************) 185.5 266.33 T +(// * Obtain a pointer to the default cdevSystem in order to) 185.5 255.33 T +(// * accomodate polling.) 185.5 244.33 T +(// ***********************************************************) 185.5 233.33 T +(system = &cdevSystem::defaultSystem\050\051;) 185.5 222.33 T +(// ***********************************************************) 185.5 200.33 T +(// * Obtain a pointer to the cdevDevice MQB1S01) 185.5 189.33 T +(// ***********************************************************) 185.5 178.33 T +(dev = cdevDevice::attachPtr\050\322MQB1S01\323\051;) 185.5 167.33 T +(// ***********************************************************) 185.5 145.33 T +(// * Obtain a pointer to the cdevRequestObject for the) 185.5 134.33 T +(// * \322monitorOff bdl\323 message on device \322MQB1S01\323.) 185.5 123.33 T +(// ***********************************************************) 185.5 112.33 T +(req = dev->getRequestObject\050\322MQB1S01\323, \322monitorOn bdl\323\051;) 185.5 101.33 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "24" 32 +%%Page: "25" 33 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 353.86 739 T +(ault Ser) 377.6 739 T +(vice Beha) 408.89 739 T +(vior f) 448.23 739 T +(or Standard Messages) 467.46 739 T +0 10 Q +(25) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 5: Def) 180 714 T +(ault beha) 234.25 714 T +(vior of the \322monitorOn\323 and \322monitorOff) 271.1 714 T +(\323 messages \050contin) 426.69 714 T +(ued\051) 502.62 714 T +180 81 558 720 C +180 86.21 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.21 195.16 559.79 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +180.25 199.95 554.2 705 R +7 X +V +0 X +N +185.5 204.67 547.61 701.33 R +7 X +V +5 9 Q +0 X +(// ###########################################################) 203.5 684.33 T +(// # Setup the context to indicate the data that should be) 203.5 673.33 T +(// # returned whenever one of the values is changed.) 203.5 662.33 T +(// ###########################################################) 203.5 651.33 T +(// ***********************************************************) 203.5 629.33 T +(// * Any time the \322value\323 property changes, I want to receive) 203.5 618.33 T +(// * the \322status\323 and \322severity\323 properties.) 203.5 607.33 T +(// ***********************************************************) 203.5 596.33 T +(ctx.insert\050\322value\323, 3\051;) 203.5 585.33 T +(ctx.insert\050\322status\323, 1\051;) 203.5 574.33 T +(ctx.insert\050\322severity\323, 1\051;) 203.5 563.33 T +(// ***********************************************************) 203.5 541.33 T +(// * Any time the \322controlhigh\323 property changes, I only want) 203.5 530.33 T +(// * to receive its new value.) 203.5 519.33 T +(// ***********************************************************) 203.5 508.33 T +(ctx.insert\050\322controlHigh\323, 2\051;) 203.5 497.33 T +(// ***********************************************************) 203.5 475.33 T +(// * Set the context of the cdevRequestObject to the new) 203.5 464.33 T +(// * context.) 203.5 453.33 T +(// ***********************************************************) 203.5 442.33 T +(req->setContext\050ctx\051;) 203.5 431.33 T +(// ************************************************************) 203.5 409.33 T +(// * Submit the \322monitorOn\323 message using the sendCallback) 203.5 398.33 T +(// * method of the cdevRequestObject.) 203.5 387.33 T +(// ************************************************************) 203.5 376.33 T +(if\050req->sendCallback\050NULL, cb\051==CDEV_SUCCESS\051) 203.5 365.33 T +({) 221.5 354.33 T +(// ********************************************************) 221.5 343.33 T +(// * Pend for 60 second.) 221.5 332.33 T +(// ********************************************************) 221.5 321.33 T +(system->pend\05060.0\051;) 221.5 310.33 T +(// ********************************************************) 221.5 288.33 T +(// * Send a \322monitorOff bdl\323 message to disable the monitor) 221.5 277.33 T +(// * that was just installed.) 221.5 266.33 T +(// ********************************************************) 221.5 255.33 T +(dev->sendCallback\050\322monitorOff bdl\323, NULL, cb\051;) 221.5 244.33 T +(}) 221.5 233.33 T +(else fprintf\050stderr, \322Failed to install monitor\134n\323\051;) 203.5 222.33 T +(}) 203.5 211.33 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "25" 33 +%%Page: "26" 34 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 54 739 T +(vice: A Sample cde) 100.79 739 T +(v Ser) 177.55 739 T +(vice) 198.83 739 T +0 10 Q +(26) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(9.) 141.32 710.67 T +4 F +(demoSer) 162 710.67 T +(vice) 222.05 710.67 T +2 F +(: A Sample cde) 249.29 710.67 T +(v Ser) 349.45 710.67 T +(vice) 383.83 710.67 T +2 10 Q +(Over) 54 673.33 T +(vie) 76.89 673.33 T +(w of the) 90.64 673.33 T +(demoSer) 54 661.33 T +(vice) 96.89 661.33 T +0 F +0.54 (The) 162 673.33 P +3 F +0.54 (demoSer) 182.54 673.33 P +0.54 (vice) 223.41 673.33 P +0 F +0.54 (ser) 244.51 673.33 P +0.54 (vice is a sample cde) 258.7 673.33 P +0.54 (v ser) 350.57 673.33 P +0.54 (vice that oper) 373.08 673.33 P +0.54 (ates on a vir) 434.08 673.33 P +0.54 (tual control) 490.55 673.33 P +0.93 (system. F) 162 661.33 P +0.93 (or the pur) 205.97 661.33 P +0.93 (poses of this illustr) 250.92 661.33 P +0.93 (ation, this control system is represented b) 335.85 661.33 P +0.93 (y a) 525.73 661.33 P +(g) 162 649.33 T +(roup of demoDe) 167.46 649.33 T +(vice classes) 238.86 649.33 T +(.) 292.61 649.33 T +2 F +(The demoDe) 54 620.33 T +(vice) 113.86 620.33 T +(Object) 54 608.33 T +0 F +1.76 (Each demoDe) 162 620.33 P +1.76 (vice object represents a single de) 226.82 620.33 P +1.76 (vice that has tw) 383.74 620.33 P +1.76 (o v) 457.84 620.33 P +1.76 (alue attr) 472.7 620.33 P +1.76 (ib) 510.74 620.33 P +1.76 (utes:) 518.32 620.33 P +4 F +(BDL) 162 608.33 T +0 F +( and) 182.55 608.33 T +4 F +(V) 204.79 608.33 T +(AL.) 210.66 608.33 T +0 F +( Each of these tw) 232.33 608.33 T +(o attr) 311.72 608.33 T +(ib) 334.66 608.33 T +(utes has the f) 342.24 608.33 T +(ollo) 401.98 608.33 T +(wing proper) 417.39 608.33 T +(ties:) 470.03 608.33 T +(1.) 162 591.33 T +4 F +(v) 180 591.33 T +(alue:) 185.36 591.33 T +0 F +(This is the doub) 250.83 591.33 T +(le precision v) 321.22 591.33 T +(alue of the attr) 379.32 591.33 T +(ib) 443.4 591.33 T +(ute) 450.98 591.33 T +(.) 464.73 591.33 T +(2.) 162 567.33 T +4 F +(status:) 180 567.33 T +0 F +(This is the current status of the attr) 250.83 567.33 T +(ib) 404.94 567.33 T +(ute) 412.52 567.33 T +(, it ma) 426.27 567.33 T +(y ha) 453.2 567.33 T +(v) 471.9 567.33 T +(e one of the) 476.65 567.33 T +(f) 251.67 555.33 T +(ollo) 254.15 555.33 T +(wing v) 269.56 555.33 T +(alues) 297.65 555.33 T +(.) 321.4 555.33 T +2 F +(0) 250.83 531.33 T +0 F +(No error) 279.5 531.33 T +(.) 315.67 531.33 T +2 F +(1) 250.83 519.33 T +0 F +(The) 279.5 519.33 T +3 F +(v) 299.51 519.33 T +(alue) 304.26 519.33 T +0 F +( proper) 323.16 519.33 T +(ty is belo) 355.24 519.33 T +(w the r) 394.55 519.33 T +(ange speci\336ed b) 424.46 519.33 T +(y the) 497.08 519.33 T +3 F +(controlLo) 279.17 507.33 T +(w) 320.15 507.33 T +0 F +( proper) 327.37 507.33 T +(ty) 359.45 507.33 T +(.) 366.23 507.33 T +2 F +(2) 250.83 495.33 T +0 F +(The) 279.5 495.33 T +3 F +(v) 299.51 495.33 T +(alue) 304.26 495.33 T +0 F +( proper) 323.16 495.33 T +(ty is belo) 355.24 495.33 T +(w the r) 394.55 495.33 T +(ange speci\336ed b) 424.46 495.33 T +(y the) 497.08 495.33 T +3 F +(alar) 279.17 483.33 T +(mLo) 296.09 483.33 T +(w) 315.39 483.33 T +0 F +( proper) 322.61 483.33 T +(ty) 354.69 483.33 T +(.) 361.47 483.33 T +2 F +(3) 250.83 471.33 T +0 F +(The) 279.5 471.33 T +3 F +(v) 299.51 471.33 T +(alue) 304.26 471.33 T +0 F +(proper) 325.94 471.33 T +(ty is abo) 355.24 471.33 T +(v) 392.33 471.33 T +(e the r) 397.08 471.33 T +(ange speci\336ed b) 425.33 471.33 T +(y the) 497.95 471.33 T +3 F +(alar) 279.17 459.33 T +(mHigh) 296.09 459.33 T +0 F +( proper) 324.98 459.33 T +(ty) 357.06 459.33 T +(.) 363.84 459.33 T +2 F +(4) 250.83 447.33 T +0 F +(The) 279.5 447.33 T +3 F +(v) 299.51 447.33 T +(alue) 304.26 447.33 T +0 F +(proper) 325.94 447.33 T +(ty is abo) 355.24 447.33 T +(v) 392.33 447.33 T +(e the r) 397.08 447.33 T +(ange speci\336ed b) 425.33 447.33 T +(y the) 497.95 447.33 T +3 F +(controlHigh) 279.17 435.33 T +0 F +( proper) 329.74 435.33 T +(ty) 361.82 435.33 T +(.) 368.6 435.33 T +(3.) 162 411.33 T +2 F +(se) 180 411.33 T +(verity:) 190.97 411.33 T +0 F +(This is a str) 250.83 411.33 T +(ing that descr) 302.1 411.33 T +(ibes the current) 362.28 411.33 T +3 F +(status) 433.98 411.33 T +0 F +(of the attr) 463.44 411.33 T +(ib) 505.84 411.33 T +(ute) 513.42 411.33 T +(.) 527.17 411.33 T +(4.) 162 387.33 T +2 F +(units:) 180 387.33 T +0 F +(These are the units that are used to e) 250.83 387.33 T +(xpress the v) 416.74 387.33 T +(alue proper) 470.4 387.33 T +(ties) 521.38 387.33 T +(of the attr) 251.67 375.33 T +(ib) 294.07 375.33 T +(ute) 301.65 375.33 T +(.) 315.4 375.33 T +(5.) 162 351.33 T +2 F +(contr) 180 351.33 T +(olLo) 204.8 351.33 T +(w:) 225.76 351.33 T +0 F +-0.47 (This is a doub) 250.83 351.33 P +-0.47 (le precision n) 311.48 351.33 P +-0.47 (umber re\337ecting the minim) 369.36 351.33 P +-0.47 (um ph) 485.67 351.33 P +-0.47 (ysical) 512.69 351.33 P +(v) 251.67 339.33 T +(alue f) 256.42 339.33 T +(or the attr) 280.58 339.33 T +(ib) 323.53 339.33 T +(ute) 331.11 339.33 T +(.) 344.86 339.33 T +(6.) 162 315.33 T +2 F +(contr) 180 315.33 T +(olHigh:) 204.8 315.33 T +0 F +(This is a doub) 250.83 315.33 T +(le precision n) 312.88 315.33 T +(umber re\337ecting the maxim) 371.69 315.33 T +(um) 492.18 315.33 T +(ph) 251.67 303.33 T +(ysical v) 262.49 303.33 T +(alue f) 295.02 303.33 T +(or the attr) 319.18 303.33 T +(ib) 362.13 303.33 T +(ute) 369.71 303.33 T +(.) 383.46 303.33 T +(7.) 162 279.33 T +2 F +(alarmLo) 180 279.33 T +(w:) 218.75 279.33 T +0 F +(This is a doub) 250.83 279.33 T +(le precision n) 312.88 279.33 T +(umber re\337ecting the lo) 371.69 279.33 T +(w) 470.47 279.33 T +(er alar) 477.59 279.33 T +(m) 506.18 279.33 T +(threshold f) 251.67 267.33 T +(or this attr) 298.06 267.33 T +(ib) 342.67 267.33 T +(ute) 350.25 267.33 T +(.) 364 267.33 T +(8.) 162 243.33 T +2 F +(alarmHigh:) 180 243.33 T +0 F +(This is a doub) 250.83 243.33 T +(le precision n) 312.88 243.33 T +(umber re\337ecting the upper alar) 371.69 243.33 T +(m) 508.11 243.33 T +(threshold f) 251.67 231.33 T +(or this attr) 298.06 231.33 T +(ib) 342.67 231.33 T +(ute) 350.25 231.33 T +(.) 364 231.33 T +-0.02 (The complete source code f) 162 207.33 P +-0.02 (or the demoDe) 285 207.33 P +-0.02 (vice class and its instances are pro) 350.79 207.33 P +-0.02 (vided in) 505.56 207.33 P +(the f) 162 195.33 T +(ollo) 181.16 195.33 T +(wing source code e) 196.57 195.33 T +(xamples) 282.42 195.33 T +(.) 319.5 195.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "26" 34 +%%Page: "27" 35 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 397.17 739 T +(vice: A Sample cde) 443.96 739 T +(v Ser) 520.72 739 T +(vice) 542 739 T +0 10 Q +(27) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 6: demoDe) 180 714 T +(vice) 254.26 714 T +(.h: Header \336le f) 270.13 714 T +(or de) 330.89 714 T +(vices used b) 351.13 714 T +(y the demoSer) 400.97 714 T +(vice) 459.77 714 T +180 81 558 720 C +180 81 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.71 84.17 559.29 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +179.75 88.28 553.7 705 R +7 X +V +0 X +N +185 93 547.11 701.33 R +7 X +V +5 9 Q +0 X +(#ifndef _DEMO_DEVICE_H_) 185 695.33 T +(#define _DEMO_DEVICE_H_) 185 684.33 T +(#include ) 185 662.33 T +(enum demoStatus {) 185 640.33 T +(NORMAL=0, ERROR_LOW, ALARM_LOW, ALARM_HIGH, ERROR_HIGH };) 203 629.33 T +(// ****************************************************************) 185 607.33 T +(// * struct demoAttrib:) 185 596.33 T +(// *) 185 585.33 T +(The demoAttrib structure contains all of the properties) 206.6 585.33 T +(// *) 185 574.33 T +(that are supported by a single attribute of a demoDevice) 206.6 574.33 T +(// *) 185 563.33 T +(structure.) 206.6 563.33 T +(// ****************************************************************) 185 552.33 T +(typedef struct) 185 541.33 T +({) 203 530.33 T +(char) 203 519.33 T +(name [32];) 224.6 519.33 T +(// Name of this attribute) 300.2 519.33 T +(char) 203 508.33 T +(units [32];) 224.6 508.33 T +(// Units that value is measured in) 300.2 508.33 T +(double) 203 497.33 T +(value;) 235.4 497.33 T +(// Value of the attribute) 267.8 497.33 T +(double) 203 486.33 T +(controlLow;) 235.4 486.33 T +(// Minimum value of the attribute) 294.8 486.33 T +(double) 203 475.33 T +(controlHigh;) 235.4 475.33 T +(// Maximum value of the attribute) 300.2 475.33 T +(double) 203 464.33 T +(alarmLow;) 235.4 464.33 T +(// Minimum value resulting in alarm) 284 464.33 T +(double) 203 453.33 T +(alarmHigh;) 235.4 453.33 T +(// Maximum value resulting in alarm) 289.4 453.33 T +(} demoAttrib;) 203 442.33 T +(// ****************************************************************) 185 409.33 T +(// * class demoDevice:) 185 398.33 T +(// *) 185 387.33 T +(The demoDevice structure is a crude representation of a) 206.6 387.33 T +(// *) 185 376.33 T +(control system device. Although these devices are not) 206.6 376.33 T +(// *) 185 365.33 T +(attached to physical hardware, they support the concept of) 206.6 365.33 T +(// *) 185 354.33 T +(value, units, control limits, display limits, alarm limits,) 206.6 354.33 T +(// *) 185 343.33 T +(alarm status and alarm severity.) 206.6 343.33 T +(// *) 185 332.33 T +(// *) 185 321.33 T +(The demoService is designed to provide a cdev interface to) 206.6 321.33 T +(// *) 185 310.33 T +(these devices. Note that this device knows nothing about) 206.6 310.33 T +(// *) 185 299.33 T +(cdev or any component of cdev. It is entirely the) 206.6 299.33 T +(// *) 185 288.33 T +(responsibility of cdev to accomodate the device with little) 206.6 288.33 T +(// *) 185 277.33 T +(or no alterations.) 206.6 277.33 T +(// ****************************************************************) 185 266.33 T +(class demoDevice) 185 255.33 T +({) 185 244.33 T +(private:) 185 233.33 T +(char *) 203 222.33 T +(name;) 267.8 222.33 T +(// Name of this device) 294.8 222.33 T +(demoAttrib *) 203 211.33 T +(attr;) 267.8 211.33 T +(// List of embedded attributes) 294.8 211.33 T +(size_t) 203 200.33 T +(count;) 235.4 200.33 T +(// Number of embedded attributes) 267.8 200.33 T +(public:) 185 178.33 T +(demoDevice \050 char * Name, demoAttrib * Attr, size_t Count \051;) 203 167.33 T +(~demoDevice\050 void \051;) 203 156.33 T +(char * getName) 203 134.33 T +(\050 void \051;) 278.6 134.33 T +(// Get name of the device) 327.2 134.33 T +(size_t getCount) 203 123.33 T +(\050 void \051;) 284 123.33 T +(// Get number of attributes) 332.6 123.33 T +(int getIndex) 203 112.33 T +(\050 char *Attr \051;) 284 112.33 T +(// Get index of Attr) 365 112.33 T +(char * getUnits) 203 101.33 T +(\050 int idx \051;) 284 101.33 T +(// Get units of measure) 348.8 101.33 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "27" 35 +%%Page: "28" 36 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 54 739 T +(vice: A Sample cde) 100.79 739 T +(v Ser) 177.55 739 T +(vice) 198.83 739 T +0 10 Q +(28) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Figure 6: demoDe) 162 714 T +(vice) 236.26 714 T +(.h: \050contin) 252.13 714 T +(ued\051) 291.55 714 T +(Figure 7: demoDe) 162 381.17 T +(vice) 236.26 381.17 T +(.cc: C++ source f) 252.13 381.17 T +(or the demoDe) 319.89 381.17 T +(vice class) 379.14 381.17 T +162 81 540 720 C +162 445.17 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.71 448.33 541.29 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +161.75 452.45 535.7 705 R +7 X +V +0 X +N +167 458.84 529.11 701.33 R +7 X +V +5 9 Q +0 X +(double getValue) 185 695.33 T +(\050 int idx \051;) 266 695.33 T +(// Get attribute value) 330.8 695.33 T +(double getControlLow) 185 684.33 T +(\050 int idx \051;) 293 684.33 T +(// Get min control value) 357.8 684.33 T +(double getControlHigh) 185 673.33 T +(\050 int idx \051;) 298.4 673.33 T +(// Get max control value) 363.2 673.33 T +(double getAlarmLow) 185 662.33 T +(\050 int idx \051;) 282.2 662.33 T +(// Get min alarm value) 347 662.33 T +(double getAlarmHigh) 185 651.33 T +(\050 int idx \051;) 287.6 651.33 T +(// Get max alarm value) 352.4 651.33 T +(demoStatus getStatus) 185 640.33 T +(\050 int idx \051;) 293 640.33 T +(// Get alarm status) 357.8 640.33 T +(char * getSeverity) 185 629.33 T +(\050 int idx \051;) 303.8 629.33 T +(// Get alarm severity) 368.6 629.33 T +(int setValue \050 int idx, double val \051;) 185 607.33 T +(// Set the attribute value) 384.8 607.33 T +(};) 167 596.33 T +(// ****************************************************************) 167 574.33 T +(// * These are the names of the demoDevices that will exists in) 167 563.33 T +(// * this demonstration control system.) 167 552.33 T +(// ****************************************************************) 167 541.33 T +(extern demoDevice DEVICE0;) 167 530.33 T +(extern demoDevice DEVICE1;) 167 519.33 T +(extern demoDevice DEVICE2;) 167 508.33 T +(extern demoDevice DEVICE3;) 167 497.33 T +(extern demoDevice DEVICE4;) 167 486.33 T +(#endif /* _DEMO_DEVICE_H_ */) 167 464.33 T +162 81 540 720 C +0 0 612 792 C +162 81 540 720 C +162 106.5 540 378.17 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.71 108.83 541.29 366.74 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +161.75 113.79 535.7 372.17 R +7 X +V +0 X +N +166.17 117.67 528.28 369.33 R +7 X +V +5 9 Q +0 X +(#include ) 166.17 363.33 T +(#include \322demoDevice.h\323) 166.17 352.33 T +(// ****************************************************************) 166.17 330.33 T +(// * demoDevice::demoDevice :) 166.17 319.33 T +(// *) 166.17 308.33 T +(This is the constructor for the demoDevice. It assigns the) 193.17 308.33 T +(// * value passed in the Name parameter as the name of the device,) 166.17 297.33 T +(// * and it uses the array provided in the Attr parameter as its) 166.17 286.33 T +(// * list of attributes. The number of attributes in the array) 166.17 275.33 T +(// * should be provided in the Count parameter.) 166.17 264.33 T +(// ****************************************************************) 166.17 253.33 T +(demoDevice::demoDevice \050char *Name, demoAttrib *Attr, size_t Count\051) 166.17 242.33 T +(: attr\050Attr\051, count\050Count\051) 184.17 231.33 T +({) 184.17 220.33 T +(name = Name?strdup\050Name\051:NULL;) 184.17 209.33 T +(}) 184.17 198.33 T +(// ****************************************************************) 166.17 176.33 T +(// * demoDevice::~demoDevice :) 166.17 165.33 T +(// *) 166.17 154.33 T +-0.46 (This is the destructor for the demoDevice, it deletes the name) 193.17 154.33 P +(// * string that was allocated in the constructor.) 166.17 143.33 T +(// ****************************************************************) 166.17 132.33 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "28" 36 +%%Page: "29" 37 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 397.17 739 T +(vice: A Sample cde) 443.96 739 T +(v Ser) 520.72 739 T +(vice) 542 739 T +0 10 Q +(29) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 7: demoDe) 180 714 T +(vice) 254.26 714 T +(.cc: \050contin) 270.13 714 T +(ued\051) 313.55 714 T +180 81 558 720 C +180 81 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.71 84.17 559.29 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +179.75 88.28 553.7 705 R +7 X +V +0 X +N +185 93 547.11 701.33 R +7 X +V +5 9 Q +0 X +(demoDevice::~demoDevice \050 void \051) 185 695.33 T +({) 203 684.33 T +(if\050name!=NULL\051 delete name;) 203 673.33 T +(}) 203 662.33 T +(// ****************************************************************) 185 640.33 T +(// * demoDevice::getName :) 185 629.33 T +(// *) 185 618.33 T +(This function allows the caller to obtain the name of the) 212 618.33 T +(// * demoDevice) 185 607.33 T +(// ****************************************************************) 185 596.33 T +(char * demoDevice::getName \050 void \051) 185 585.33 T +({) 203 574.33 T +(return name;) 203 563.33 T +(}) 203 552.33 T +(// ****************************************************************) 185 530.33 T +(// * demoDevice::getCount :) 185 519.33 T +(// *) 185 508.33 T +(This function returns the number of attributes in this) 212 508.33 T +(// * demoDevice.) 185 497.33 T +(// ****************************************************************) 185 486.33 T +(size_t demoDevice::getCount \050 void \051) 185 475.33 T +({) 203 464.33 T +(return count;) 203 453.33 T +(}) 203 442.33 T +(// ****************************************************************) 185 420.33 T +(// * demoDevice::getIndex :) 185 409.33 T +(// *) 185 398.33 T +-0.46 (This method allows the caller to obtain the index of a specific) 212 398.33 P +-0.34 (// * attribute by name. If the value returned is less than 0, then) 185 387.33 P +(// * the attribute does not exist on this device.) 185 376.33 T +(// ****************************************************************) 185 365.33 T +(int demoDevice::getIndex \050 char * Attr \051) 185 354.33 T +({) 203 343.33 T +(for\050int i=count-1; i>=0 && strcmp\050Attr, attr[i].name\051!=0; i--\051;) 203 332.33 T +(return i;) 203 321.33 T +(}) 203 310.33 T +(// ****************************************************************) 185 288.33 T +(// * demoDevice::getUnits :) 185 277.33 T +(// *) 185 266.33 T +(This method returns the units of measure used by the attribute) 212 266.33 T +(// * at the specified index. Returns NULL if the index is out of) 185 255.33 T +(// * range.) 185 244.33 T +(// ****************************************************************) 185 233.33 T +(char * demoDevice::getUnits \050 int idx \051) 185 222.33 T +({) 203 211.33 T +(return \050idx>=0 && idx=0 && idx=0 && idx=0 && idx=0 && idx=0 && idx=0 && idx=0 && idx attr[idx].controlLow &&) 221 222.33 T +( val < attr[idx].controlHigh \051) 221 211.33 T +({) 239 200.33 T +(attr[idx].value = val;) 239 189.33 T +(result = 0;) 239 178.33 T +(}) 239 167.33 T +(}) 221 156.33 T +(return result;) 203 145.33 T +(}) 203 134.33 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "31" 39 +%%Page: "32" 40 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 54 739 T +(vice: A Sample cde) 100.79 739 T +(v Ser) 177.55 739 T +(vice) 198.83 739 T +0 10 Q +(32) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Figure 7: demoDe) 162 714 T +(vice) 236.26 714 T +(.cc: \050contin) 252.13 714 T +(ued\051) 295.55 714 T +2 10 Q +(The demoSer) 54 170.17 T +(vice) 117.45 170.17 T +(Object) 54 158.17 T +0 F +0.34 (The) 162 170.17 P +3 F +0.34 (demoSer) 182.35 170.17 P +0.34 (vice) 223.23 170.17 P +0 F +0.34 ( C++ class is der) 241.01 170.17 P +0.34 (iv) 317.01 170.17 P +0.34 (ed from the) 323.98 170.17 P +3 F +0.34 (cde) 378.37 170.17 P +0.34 (vSer) 394.19 170.17 P +0.34 (vice) 415.05 170.17 P +0 F +0.34 ( class) 432.83 170.17 P +0.34 (. It maintains a list) 458.59 170.17 P +1.28 (of ref) 162 158.17 P +1.28 (erences to the de) 185.77 158.17 P +1.28 (vices that are de\336ned in the) 266.58 158.17 P +3 F +1.28 (demoDe) 399.34 158.17 P +1.28 (vice) 436.83 158.17 P +0 F +1.28 ( source code) 454.61 158.17 P +1.28 (. This) 514.27 158.17 P +0.54 (class also pro) 162 146.17 P +0.54 (vides the mechanisms that its request objects will use to comm) 224.05 146.17 P +0.54 (unicate) 507.76 146.17 P +(with these de) 162 134.17 T +(vices) 220.62 134.17 T +(.) 243.25 134.17 T +162 195.83 540 720 C +162 212.83 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.71 215.83 541.29 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +161.75 220.79 535.7 705 R +7 X +V +0 X +N +167 227.17 529.11 701.33 R +7 X +V +5 9 Q +0 X +(// ****************************************************************) 167 695.33 T +(// * These are the attribute definitions that will be used to) 167 684.33 T +(// * construct the fictitious devices in the demo control system.) 167 673.33 T +(// * The values and names used here are inconsequential.) 167 662.33 T +(// ****************************************************************) 167 651.33 T +(demoAttrib DEVICE0Attrib [2] =) 167 640.33 T +({) 185 629.33 T +({ \322VAL\323, \322amps\323, 0.0, -30.0, 30.0, -20.0, 20.0 },) 185 618.33 T +({ \322BDL\323, \322gauss-meters\323, 0.0, -14.0, 7.0, -10.0, 5.0 }) 185 607.33 T +(};) 185 596.33 T +(demoAttrib DEVICE1Attrib [2] =) 167 574.33 T +({) 185 563.33 T +({ \322VAL\323, \322amps\323, 0.0, -20.0, 20.0, -15.0, 15.0 },) 185 552.33 T +({ \322BDL\323, \322gauss-meters\323, 0.0, -10.0, 10.0, -7.5, 7.5 }) 185 541.33 T +(};) 185 530.33 T +(demoAttrib DEVICE2Attrib [2] =) 167 508.33 T +({) 185 497.33 T +({ \322VAL\323, \322amps\323, 0.25, -12.0, 10.0, -9.0, 7.0 },) 185 486.33 T +({ \322BDL\323, \322gauss-meters\323, 1.0, -10.0, 10.0, -7.5, 7.5 }) 185 475.33 T +(};) 185 464.33 T +(demoAttrib DEVICE3Attrib [2] =) 167 442.33 T +({) 185 431.33 T +({ \322VAL\323, \322amps\323, 1.25, -12.0, 10.0, -9.0, 7.0 },) 185 420.33 T +({ \322BDL\323, \322gauss-meters\323, 8.0, -10.0, 10.0, -7.5, 7.5 }) 185 409.33 T +(};) 185 398.33 T +(demoAttrib DEVICE4Attrib [2] =) 167 376.33 T +({) 185 365.33 T +({ \322VAL\323, \322amps\323, 11.25, -12.0, 13.0, -9.0, 10.0 },) 185 354.33 T +({ \322BDL\323, \322gauss-meters\323, 8.0, -10.0, 10.0, -7.5, 8.25 }) 185 343.33 T +(};) 185 332.33 T +(// ****************************************************************) 167 310.33 T +(// * Instances of the ficticious devices in out control system.) 167 299.33 T +-2.54 (// ****************************************************************) 167 288.33 P +(demoDevice DEVICE0\050\322DEVICE0\323, DEVICE0Attrib, 2\051;) 167 277.33 T +(demoDevice DEVICE1\050\322DEVICE1\323, DEVICE1Attrib, 2\051;) 167 266.33 T +(demoDevice DEVICE2\050\322DEVICE2\323, DEVICE2Attrib, 2\051;) 167 255.33 T +(demoDevice DEVICE3\050\322DEVICE3\323, DEVICE3Attrib, 2\051;) 167 244.33 T +(demoDevice DEVICE4\050\322DEVICE4\323, DEVICE4Attrib, 2\051;) 167 233.33 T +162 195.83 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "32" 40 +%%Page: "33" 41 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 397.17 739 T +(vice: A Sample cde) 443.96 739 T +(v Ser) 520.72 739 T +(vice) 542 739 T +0 10 Q +(33) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(The) 72 713.33 T +2 9 Q +(enqueueT) 72 702 T +(ransaction) 113.79 702 T +2 10 Q +(Method) 72 690.33 T +0 F +1.37 (The) 180 713.33 P +3 F +1.37 (demoSer) 201.38 713.33 P +1.37 (vice) 242.25 713.33 P +0 F +1.37 ( class uses a queueing scheme to manage outbound tr) 260.03 713.33 P +1.37 (ansaction) 515.2 713.33 P +0.28 (objects) 180 701.33 P +0.28 (. Whene) 211.53 701.33 P +0.28 (v) 248.75 701.33 P +0.28 (er a request object wishes to submit a message to the ser) 253.5 701.33 P +0.28 (vice) 512.58 701.33 P +0.28 (, it will) 530.21 701.33 P +0.57 (call the ser) 180 689.33 P +0.57 (vice\325) 229.79 689.33 P +0.57 (s) 249.29 689.33 P +3 F +0.57 (enqueueT) 257.64 689.33 P +0.57 (r) 301.46 689.33 P +0.57 (ansaction) 304.69 689.33 P +0 F +0.57 (method. This method receiv) 350.84 689.33 P +0.57 (es a pointer to the) 475.68 689.33 P +3 F +0.44 (cde) 180 677.33 P +0.44 (vT) 195.82 677.33 P +0.44 (r) 205.73 677.33 P +0.44 (anObj) 208.96 677.33 P +0 F +0.44 ( object that contains inf) 235.64 677.33 P +0.44 (or) 339.37 677.33 P +0.44 (mation about the tr) 348.51 677.33 P +0.44 (ansaction. It also receiv) 433.11 677.33 P +0.44 (es a) 538.66 677.33 P +-0.02 (pointer to a cde) 180 665.33 P +-0.02 (vData object that contains an) 248.56 665.33 P +-0.02 (y inf) 377.28 665.33 P +-0.02 (or) 395.3 665.33 P +-0.02 (mation that the ser) 404.44 665.33 P +-0.02 (vice will need to) 487.49 665.33 P +(complete the request.) 180 653.33 T +1.77 (Messages passed to the) 180 636.33 P +3 F +1.77 (enqueueT) 298.23 636.33 P +1.77 (r) 342.07 636.33 P +1.77 (ansaction) 345.3 636.33 P +0 F +1.77 ( method will be stored in an inter) 388.1 636.33 P +1.77 (nal) 544.66 636.33 P +0.89 (link) 180 624.33 P +0.89 (ed-list until the) 194.8 624.33 P +3 F +0.89 (pend) 264.72 624.33 P +0 F +0.89 (or) 290.63 624.33 P +3 F +0.89 (poll) 303.19 624.33 P +0 F +0.89 (methods are called. The) 322.42 624.33 P +3 F +0.89 (pend) 436.04 624.33 P +0 F +0.89 ( and) 458.28 624.33 P +3 F +0.89 (poll) 482.3 624.33 P +0 F +0.89 ( methods are) 497.86 624.33 P +(responsib) 180 612.33 T +(le f) 223.15 612.33 T +(or tr) 236.19 612.33 T +(ansf) 253.87 612.33 T +(err) 272.47 612.33 T +(ing the messages to the) 284.84 612.33 T +3 F +(processT) 393.79 612.33 T +(r) 433.71 612.33 T +(ansaction) 436.94 612.33 T +0 F +( method.) 479.74 612.33 T +2 F +(The) 72 585.33 T +2 9 Q +(pr) 72 574 T +(ocessT) 80.82 574 T +(ransaction) 111.11 574 T +2 10 Q +(Method) 72 562.33 T +0 F +3.03 (The) 180 585.33 P +3 F +3.03 (processT) 203.04 585.33 P +3.03 (r) 242.96 585.33 P +3.03 (ansaction) 246.19 585.33 P +0 F +3.03 ( method is where all messages sent to the ser) 288.99 585.33 P +3.03 (vice are) 519.96 585.33 P +1.35 (dispatched to the under) 180 573.33 P +1.35 (lying) 288.71 573.33 P +3 F +1.35 (demoDe) 313.4 573.33 P +1.35 (vice) 350.89 573.33 P +0 F +1.35 ( control system. Unlik) 368.67 573.33 P +1.35 (e the) 467.54 573.33 P +3 F +1.35 (pend) 495.26 573.33 P +0 F +1.35 (and) 521.63 573.33 P +3 F +1.35 (poll) 542.44 573.33 P +0 F +4.3 (methods which restr) 180 561.33 P +4.3 (ict their activity to a caller speci\336ed per) 278.22 561.33 P +4.3 (iod of time) 479.65 561.33 P +4.3 (, the) 534.24 561.33 P +3 F +3.05 (processT) 180 549.33 P +3.05 (r) 219.92 549.33 P +3.05 (ansaction) 223.15 549.33 P +0 F +3.05 ( method oper) 265.95 549.33 P +3.05 (ates without regard to time) 330.87 549.33 P +3.05 (. It will process one) 460.76 549.33 P +-0.19 (complete message bef) 180 537.33 P +-0.19 (ore retur) 279.92 537.33 P +-0.19 (ning. Because this is a pr) 317.77 537.33 P +-0.19 (iv) 428.7 537.33 P +-0.19 (ate member function, it ma) 435.67 537.33 P +-0.19 (y) 553 537.33 P +(only be called b) 180 525.33 T +(y methods that e) 249.28 525.33 T +(xist within the class) 322.91 525.33 T +(.) 408.34 525.33 T +2 F +(The) 72 496.33 T +(ne) 72 484.33 T +(wDemoSer) 83.52 484.33 T +(vice) 135.3 484.33 T +(Function) 72 472.33 T +0 F +-0.22 (This is the ser) 180 496.33 P +-0.22 (vice speci\336c loader function f) 241.9 496.33 P +-0.22 (or the) 368.57 496.33 P +3 F +-0.22 (demoSer) 396.48 496.33 P +-0.22 (vice) 437.36 496.33 P +0 F +-0.22 ( object. It is called once) 455.14 496.33 P +-0.05 (b) 180 484.33 P +-0.05 (y the) 185.36 484.33 P +3 F +-0.05 (cde) 209.71 484.33 P +-0.05 (vSystem) 225.53 484.33 P +0 F +-0.05 ( object in order to instantiate a single instance of the) 263.87 484.33 P +3 F +-0.05 (demoSer) 496.72 484.33 P +-0.05 (vice) 537.59 484.33 P +0 F +-0.05 (.) 555.22 484.33 P +0.5 (If more than one cde) 180 472.33 P +0.5 (vSystem object is used b) 273.42 472.33 P +0.5 (y an application, the) 385.83 472.33 P +3 F +0.5 (ne) 479.55 472.33 P +0.5 (wDemoSer) 490.47 472.33 P +0.5 (vice) 540.22 472.33 P +0 F +(function ma) 180 460.33 T +(y be called more than once) 231.39 460.33 T +(.) 351.3 460.33 T +2 F +(The cde) 72 431.33 T +(vSelector) 109.64 431.33 T +(Object) 72 419.33 T +0 F +-0.23 (Each) 180 431.33 P +3 F +-0.23 (demoSer) 205.34 431.33 P +-0.23 (vice) 246.21 431.33 P +0 F +-0.23 ( object contains one instance of the) 263.98 431.33 P +3 F +-0.23 (cde) 421.88 431.33 P +-0.23 (vSelector) 437.7 431.33 P +0 F +-0.23 ( class) 479.38 431.33 P +-0.23 (. This object) 504.56 431.33 P +0.1 (giv) 180 419.33 P +0.1 (es the ser) 192.53 419.33 P +0.1 (vice a \336le descr) 236.94 419.33 P +0.1 (iptor that it ma) 306.29 419.33 P +0.1 (y pro) 369.64 419.33 P +0.1 (vide to the) 391.82 419.33 P +3 F +0.1 (cde) 441.04 419.33 P +0.1 (vSystem) 456.86 419.33 P +0 F +0.1 ( object f) 495.2 419.33 P +0.1 (or use) 530.11 419.33 P +0.19 (in the) 180 407.33 P +3 F +0.19 (select) 207.62 407.33 P +0 F +0.19 ( function. The ser) 233.74 407.33 P +0.19 (vice ma) 311.87 407.33 P +0.19 (y then manipulate the state of the \336le descr) 346.21 407.33 P +0.19 (iptor) 538.55 407.33 P +2.21 (b) 180 395.33 P +2.21 (y using the) 185.36 395.33 P +3 F +2.21 (cde) 243.14 395.33 P +2.21 (vSelector) 258.96 395.33 P +0 F +2.21 ( interf) 300.64 395.33 P +2.21 (ace to indicate that one of its under) 327.56 395.33 P +2.21 (lying de) 498.85 395.33 P +2.21 (vices) 535.22 395.33 P +(requires attention.) 180 383.33 T +2 F +(The VERB) 72 354.33 T +(En) 72 342.33 T +(umeration) 84.68 342.33 T +0 F +-0.17 (This en) 180 354.33 P +-0.17 (umer) 212.52 354.33 P +-0.17 (ated type de\336nes a unique integer v) 235.2 354.33 P +-0.17 (alue f) 392.35 354.33 P +-0.17 (or each of the v) 416.34 354.33 P +-0.17 (erbs that ma) 484.33 354.33 P +-0.17 (y be) 539.27 354.33 P +(applied to attr) 180 342.33 T +(ib) 240.74 342.33 T +(utes compr) 248.32 342.33 T +(ising de) 297.93 342.33 T +(vices in this ser) 332.09 342.33 T +(vice) 400.74 342.33 T +(.) 418.37 342.33 T +2 F +(The A) 72 313.33 T +(TTR) 98.88 313.33 T +(En) 72 301.33 T +(umeration) 84.68 301.33 T +0 F +0.13 (This en) 180 313.33 P +0.13 (umer) 212.82 313.33 P +0.13 (ated type de\336nes a unique integer identi\336er f) 235.5 313.33 P +0.13 (or each of the attr) 432.88 313.33 P +0.13 (ib) 511.93 313.33 P +0.13 (utes that) 519.51 313.33 P +(are compr) 180 301.33 T +(ise a de) 225.16 301.33 T +(vice within this ser) 259.88 301.33 T +(vice) 341.31 301.33 T +(.) 358.94 301.33 T +3 9 Q +(Figure 8: demoSer) 180 268 T +(vice) 257.3 268 T +(.h: Header \336le f) 273.17 268 T +(or the demoSer) 333.93 268 T +(vice class) 396.23 268 T +180 81 558 320 C +180 82.5 558 265 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.71 84 559.29 253.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +179.75 88.12 553.7 259 R +7 X +V +0 X +N +184.17 91.17 550.45 255.33 R +7 X +V +5 9 Q +0 X +(#ifndef _DEMO_SERVICE_H_) 184.17 249.33 T +(#define _DEMO_SERVICE_H_ 1) 184.17 238.33 T +(#include ) 184.17 216.33 T +(#include ) 184.17 205.33 T +(#include ) 184.17 194.33 T +(// ****************************************************************) 184.17 172.33 T +(// * The demoDevice.h file defines the behavior of the demoDevice) 184.17 161.33 T +(// * objects. These objects are crude representations of control) 184.17 150.33 T +(// * system hardware interfaces. The structure and operation of) 184.17 139.33 T +(// * these objects are for illustration purposes only, and are) 184.17 128.33 T +(// * significantly less important than the cdev objects.) 184.17 117.33 T +(// ****************************************************************) 184.17 106.33 T +(#include ) 184.17 95.33 T +180 81 558 320 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "33" 41 +%%Page: "34" 42 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 54 739 T +(vice: A Sample cde) 100.79 739 T +(v Ser) 177.55 739 T +(vice) 198.83 739 T +0 10 Q +(34) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Figure 8: demoSer) 162 714 T +(vice) 239.3 714 T +(.h: \050contin) 255.17 714 T +(ued\051) 294.6 714 T +162 81 540 720 C +162 85 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.71 87.33 541.29 703.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +161.75 91.45 535.7 709 R +7 X +V +0 X +N +166.17 94.5 532.45 705.33 R +7 X +V +5 9 Q +0 X +(#define DEMO_SERVICE_NAME \322demoService\323) 166.17 699.33 T +(// ****************************************************************) 166.17 677.33 T +(// * Service Loader:) 166.17 666.33 T +(// * The first step in building a new service is to construct a) 166.17 655.33 T +(// * service loader function. This function will allow cdev to) 166.17 644.33 T +(// * dynamically initialize a service by name.) 166.17 633.33 T +(// *) 166.17 622.33 T +(// * The function should adhere to this naming convention...) 166.17 611.33 T +(// * cdevService * newXXX \050char * name, cdevSystem * system\051;) 166.17 600.33 T +(// * Where \324XXX\325 should be replaced with the name of the) 166.17 589.33 T +(// * service class with the first character capitalized.) 166.17 578.33 T +(// *) 166.17 567.33 T +(// * The function should also be declared as \324extern \322C\323\325 to allow) 166.17 556.33 T +(// * it to be called and loaded from within an external shared) 166.17 545.33 T +(// * library module.) 166.17 534.33 T +(// *) 166.17 523.33 T +(// * This function serves only to construct a new instance of) 166.17 512.33 T +(// * the specified service, and return it to the instanciating) 166.17 501.33 T +(// * cdevSystem object.) 166.17 490.33 T +(// ****************************************************************) 166.17 479.33 T +(extern \322C\323 cdevService *) 166.17 468.33 T +(newDemoService \050 char * name, cdevSystem * system \051;) 166.17 457.33 T +(// ****************************************************************) 166.17 435.33 T +(// * demoService:) 166.17 424.33 T +(// * This class provides the mechanisms that the cdev system will) 166.17 413.33 T +(// * use to communicate with the demo service.) 166.17 402.33 T +(// *) 166.17 391.33 T +(// *) 166.17 380.33 T +-0.09 (Note that this service is inherited from the cdevService class) 193.17 380.33 P +(// * and receives much of its functionality from that class.) 166.17 369.33 T +(// ****************************************************************) 166.17 358.33 T +(class demoService : public cdevService) 166.17 347.33 T +({) 166.17 336.33 T +(friend class demoRequestObject;) 166.17 325.33 T +(public:) 166.17 314.33 T +(// *************************************************************) 184.17 303.33 T +(// * Tags used by the service and its associate classes.) 184.17 292.33 T +(// *************************************************************) 184.17 281.33 T +(static int VALUE_TAG;) 184.17 270.33 T +(static int STATUS_TAG;) 184.17 259.33 T +(static int SEVERITY_TAG;) 184.17 248.33 T +(static int UNITS_TAG;) 184.17 237.33 T +(static int CTRLHIGH_TAG;) 184.17 226.33 T +(static int CTRLLOW_TAG;) 184.17 215.33 T +(static int ALRMHIGH_TAG;) 184.17 204.33 T +(static int ALRMLOW_TAG;) 184.17 193.33 T +(// *************************************************************) 184.17 171.33 T +(// * demoService::VERB) 184.17 160.33 T +(// *) 184.17 149.33 T +(This is the enumerated list of verbs that are supported by) 205.77 149.33 T +(// *) 184.17 138.33 T +(devices in this service.) 205.77 138.33 T +(// *************************************************************) 184.17 127.33 T +(enum VERB {) 184.17 116.33 T +(INVALID_VERB=0x00,) 202.17 105.33 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "34" 42 +%%Page: "35" 43 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 397.17 739 T +(vice: A Sample cde) 443.96 739 T +(v Ser) 520.72 739 T +(vice) 542 739 T +0 10 Q +(35) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 8: demoSer) 180 714 T +(vice) 257.3 714 T +(.h: \050contin) 273.17 714 T +(ued\051) 312.6 714 T +180 81 558 720 C +180 85 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.71 87.33 559.29 703.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +179.75 91.45 553.7 709 R +7 X +V +0 X +N +184.17 94.5 550.45 705.33 R +7 X +V +5 9 Q +0 X +(GET =0x01, // \322get\323 - obtains a device value) 220.17 699.33 T +(SET =0x02, // \322set\323 - sets a device value) 220.17 688.33 T +(VERB_MASK =0xff) 220.17 677.33 T +(};) 220.17 666.33 T +(// *************************************************************) 202.17 644.33 T +(// * demoService::ATTR) 202.17 633.33 T +(// * This is a list of the data items that may be operated on) 202.17 622.33 T +(// * using some or all of the demoService::VERB elements.) 202.17 611.33 T +(// *************************************************************) 202.17 600.33 T +(enum ATTR {) 202.17 589.33 T +(INVALID_ATTR=0x0000,) 220.17 578.33 T +(VAL =0x0100, // \322VAL\323 - value of the device) 220.17 567.33 T +(BDL =0x0200, // \322BDL\323 - bdl value of the device) 220.17 556.33 T +(ATTR_MASK =0xff00) 220.17 545.33 T +(};) 220.17 534.33 T +(// *************************************************************) 202.17 512.33 T +(// * demoService::demoService :) 202.17 501.33 T +(// * This constructor is responsible for performing all service) 202.17 490.33 T +(// * initialization. Returns nothing.) 202.17 479.33 T +(// *************************************************************) 202.17 468.33 T +(demoService \050char * name,) 202.17 457.33 T +( cdevSystem & system = cdevSystem::defaultSystem\050\051\051;) 256.17 446.33 T +(// *************************************************************) 202.17 424.33 T +(// * demoService::getFd) 202.17 413.33 T +-0.23 (// * This function will return the list of file descriptors that) 202.17 402.33 P +(// * the demoService is using. This will allow the file) 202.17 391.33 T +(// * descriptors to be used in global select and poll calls) 202.17 380.33 T +(// * performed at the cdevSystem class level.) 202.17 369.33 T +(// *) 202.17 358.33 T +(// * Returns CDEV_SUCCESS on success or an enumerated error.) 202.17 347.33 T +(// *************************************************************) 202.17 336.33 T +(int getFd \050 int * &fd, int & numFd \051;) 202.17 325.33 T +(// *************************************************************) 202.17 303.33 T +(// * demoService::flush :) 202.17 292.33 T +(// * This function flushes all communications buffers that the) 202.17 281.33 T +(// * service may have open.) 202.17 270.33 T +(// *) 202.17 259.33 T +(// * Returns CDEV_SUCCESS on success or an enumerated error.) 202.17 248.33 T +(// *************************************************************) 202.17 237.33 T +(int flush \050 void \051;) 202.17 226.33 T +(// *************************************************************) 202.17 204.33 T +(// * demoService::poll :) 202.17 193.33 T +-0.25 (// * This function polls the file descriptors used by the service) 202.17 182.33 P +(// * until one of them becomes active or a discrete amount of) 202.17 171.33 T +(// * time has expired.) 202.17 160.33 T +(// *) 202.17 149.33 T +(// * Returns CDEV_SUCCESS on success or an enumerated error.) 202.17 138.33 T +(// *************************************************************) 202.17 127.33 T +(int poll \050 void \051;) 202.17 116.33 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "35" 43 +%%Page: "36" 44 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 54 739 T +(vice: A Sample cde) 100.79 739 T +(v Ser) 177.55 739 T +(vice) 198.83 739 T +0 10 Q +(36) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Figure 8: demoSer) 162 714 T +(vice) 239.3 714 T +(.h: \050contin) 255.17 714 T +(ued\051) 294.6 714 T +162 81 540 720 C +162 84 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.71 86.33 541.29 702.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +161.75 90.45 535.7 708 R +7 X +V +0 X +N +166.17 93.5 532.45 704.33 R +7 X +V +5 9 Q +0 X +(// *************************************************************) 184.17 698.33 T +(// * demoService::pend :) 184.17 687.33 T +(// * Pends until the named file descriptor \050or any descriptor) 184.17 676.33 T +(// * if fd = -1\051 is ready. Will pend forever if the descriptor) 184.17 665.33 T +(// * does not become active.) 184.17 654.33 T +(// *) 184.17 643.33 T +(// * Returns CDEV_SUCCESS on success or an enumerated error.) 184.17 632.33 T +(// *************************************************************) 184.17 621.33 T +(int pend \050 int fd = -1 \051;) 184.17 610.33 T +(// *************************************************************) 184.17 588.33 T +(// * demoService::pend :) 184.17 577.33 T +(// * Pends until the named file descriptor \050or any descriptor) 184.17 566.33 T +(// * if fd = -1\051 is ready. Will pend for no longer than the) 184.17 555.33 T +(// * user specified number of seconds.) 184.17 544.33 T +(// *) 184.17 533.33 T +(// *) 184.17 522.33 T +(Returns CDEV_SUCCESS on success or an enumerated error.) 205.77 522.33 T +(// *************************************************************) 184.17 511.33 T +(int pend \050 double seconds, int fd = -1 \051;) 184.17 500.33 T +(// *************************************************************) 184.17 478.33 T +(// * demoService::getNameServer :) 184.17 467.33 T +-0.68 (// * This function should obtain the default name server for this) 184.17 456.33 P +(// * object. It does nothing for now.) 184.17 445.33 T +(// *************************************************************) 184.17 434.33 T +(int getNameServer\050cdevDevice * &ns\051;) 184.17 423.33 T +(// *************************************************************) 184.17 401.33 T +(// * demoService::getRequestObject :) 184.17 390.33 T +-0.21 (// * This is the interface that cdev objects will use to obtain a) 184.17 379.33 P +-0.34 (// * demoRequestObject object. The demoRequestObject represents) 184.17 368.33 P +(// * a combined device/message pair that is associated with the) 184.17 357.33 T +(// * demoService.) 184.17 346.33 T +(// *) 184.17 335.33 T +(// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.) 184.17 324.33 T +(// *************************************************************) 184.17 313.33 T +(int getRequestObject \050char * device, char * message,) 184.17 302.33 T +( cdevRequestObject * &req\051;) 292.17 291.33 T +(protected:) 166.17 269.33 T +(// *************************************************************) 184.17 258.33 T +(// * demoService::~demoService :) 184.17 247.33 T +(// * The destructor is protected to prevent it from being called) 184.17 236.33 T +(// * directly. The destructor performs any clean-up or shutdown) 184.17 225.33 T +(// * operations. Returns nothing.) 184.17 214.33 T +(// *************************************************************) 184.17 203.33 T +(~demoService \050 void \051;) 184.17 192.33 T +(// *************************************************************) 184.17 170.33 T +(// * demoService::enqueueTransaction :) 184.17 159.33 T +-0.25 (// * Allows the caller to place a cdevTranObj object and cdevData) 184.17 148.33 P +(// * object into the outgoing queue.) 184.17 137.33 T +(// *************************************************************) 184.17 126.33 T +(int enqueueTransaction \050 cdevTranObj * obj, cdevData * inbound\051;) 184.17 115.33 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "36" 44 +%%Page: "37" 45 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 397.17 739 T +(vice: A Sample cde) 443.96 739 T +(v Ser) 520.72 739 T +(vice) 542 739 T +0 10 Q +(37) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 8: demoSer) 180 714 T +(vice) 257.3 714 T +(.h: \050contin) 273.17 714 T +(ued\051) 312.6 714 T +180 81 558 720 C +180 84 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.71 86.33 559.29 702.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +179.75 90.45 553.7 708 R +7 X +V +0 X +N +184.17 93.5 550.45 704.33 R +7 X +V +5 9 Q +0 X +(// *************************************************************) 202.17 698.33 T +(// * demoService::defCallback :) 202.17 687.33 T +(// * This function is a default callback for the service.) 202.17 676.33 T +(// *************************************************************) 202.17 665.33 T +(static void defCallback \050int, void *, cdevRequestObject &,) 202.17 654.33 T +(cdevData &\051;) 328.17 643.33 T +(private:) 184.17 632.33 T +(// *************************************************************) 202.17 621.33 T +(// * Queue of transaction information. This queue is used to) 202.17 610.33 T +-0.62 (// * manage incoming requests and their associated data. It is a) 202.17 599.33 P +(// * simple single-linked list. Data hiding is not violated by) 202.17 588.33 T +-0.58 (// * the public data in this class, because the entire class is a) 202.17 577.33 P +(// * private element of the demoService class.) 202.17 566.33 T +(// * This mini-class maintains a duplicate copy of the inbound) 202.17 555.33 T +-0.48 (// * data so that the user is free to delete it. It also makes a) 202.17 544.33 P +-0.68 (// * copy of any pertinent context variables as they existed when) 202.17 533.33 P +(// * the object was created.) 202.17 522.33 T +(// *************************************************************) 202.17 511.33 T +(class cdevTranNode) 202.17 500.33 T +({) 202.17 489.33 T +(public:) 202.17 478.33 T +(cdevTranNode * next;) 220.17 467.33 T +(cdevTranObj * obj;) 220.17 456.33 T +(cdevData inbound;) 220.17 445.33 T +(int VALUE_CTX;) 220.17 434.33 T +(int STATUS_CTX;) 220.17 423.33 T +(int SEVERITY_CTX;) 220.17 412.33 T +(int UNITS_CTX;) 220.17 401.33 T +(int CTRLHIGH_CTX;) 220.17 390.33 T +(int CTRLLOW_CTX;) 220.17 379.33 T +(int ALRMHIGH_CTX;) 220.17 368.33 T +(int ALRMLOW_CTX;) 220.17 357.33 T +(inline cdevTranNode \050 cdevTranObj * Obj, cdevData *Inbound\051;) 220.17 335.33 T +(inline ~cdevTranNode \050 void \051 {}) 220.17 324.33 T +(} * transactions;) 202.17 313.33 T +(// *************************************************************) 202.17 291.33 T +(// * demoService::processTransaction :) 202.17 280.33 T +(// * This function will take a cdevTranObj and will locate the) 202.17 269.33 T +(// * demoDevice. It will then interpret the verb and attribute) 202.17 258.33 T +(// * and will execute the correct command on the demoDevice.) 202.17 247.33 T +(// *) 202.17 236.33 T +(// * Note:) 202.17 225.33 T +(This object is responsible for deleting the) 256.17 225.33 T +(// * cdevTranObj after it has been processed.) 202.17 214.33 T +(// *************************************************************) 202.17 203.33 T +(int processTransaction \050 demoService::cdevTranNode * node\051;) 202.17 192.33 T +(// *************************************************************) 202.17 170.33 T +(// * This is an array of pointer to the demoDevice objects that) 202.17 159.33 T +(// * this service will manipulate. These object are crude) 202.17 148.33 T +(// * representations of a hardware device interface.) 202.17 137.33 T +(// *************************************************************) 202.17 126.33 T +(demoDevice *devices[5];) 202.17 115.33 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "37" 45 +%%Page: "38" 46 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 54 739 T +(vice: A Sample cde) 100.79 739 T +(v Ser) 177.55 739 T +(vice) 198.83 739 T +0 10 Q +(38) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Figure 8: demoSer) 162 714 T +(vice) 239.3 714 T +(.h: \050contin) 255.17 714 T +(ued\051) 294.6 714 T +162 81 540 720 C +162 85 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.21 87.33 541.79 703.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +162.25 91.45 536.2 709 R +7 X +V +0 X +N +166.67 94.5 532.95 705.33 R +7 X +V +5 9 Q +0 X +(// *************************************************************) 184.67 699.33 T +-0.25 (// * Default cdevCallback object for the service and the request) 184.67 688.33 P +(// * object) 184.67 677.33 T +(// *************************************************************) 184.67 666.33 T +(cdevCallback callback;) 184.67 655.33 T +(// *************************************************************) 184.67 633.33 T +(// * The cdevSelector object is used to provide a file) 184.67 622.33 T +(// * descriptor that the cdevService can use to pend for I/O) 184.67 611.33 T +(// * events in the absence of any real I/O descriptors.) 184.67 600.33 T +(// *************************************************************) 184.67 589.33 T +(cdevSelector selector;) 184.67 578.33 T +(int readfd[1];) 184.67 567.33 T +(};) 166.67 556.33 T +(// ****************************************************************) 166.67 523.33 T +(// * demoService::cdevTranNode::cdevTranNode :) 166.67 512.33 T +(// *) 166.67 501.33 T +(This is the constructor for the cdevTranNode class.) 193.67 501.33 T +(// ****************************************************************) 166.67 490.33 T +(demoService::cdevTranNode::cdevTranNode) 166.67 479.33 T +(\050 cdevTranObj * Obj, cdevData * Inbound \051) 184.67 468.33 T +(: next\050NULL\051, obj\050Obj\051, VALUE_CTX\0501\051, STATUS_CTX\0500\051,) 184.67 457.33 T +( SEVERITY_CTX\0500\051, UNITS_CTX\0500\051, CTRLHIGH_CTX\0500\051,) 184.67 446.33 T +( CTRLLOW_CTX\0500\051, ALRMHIGH_CTX\0500\051, ALRMLOW_CTX\0500\051) 184.67 435.33 T +({) 184.67 424.33 T +(// *************************************************************) 184.67 413.33 T +(// * Make a duplicate copy of the inbound data) 184.67 402.33 T +(// *************************************************************) 184.67 391.33 T +(if\050Inbound!=NULL\051 inbound = *Inbound;) 184.67 380.33 T +(// *************************************************************) 184.67 358.33 T +-0.21 (// * Extract the pertinent context values. Note that I am using) 184.67 347.33 P +-0.21 (// * the tag values defined in the service for speed, however, I) 184.67 336.33 P +(// * could simply use the character string equivalents for) 184.67 325.33 T +(// * simplicity.) 184.67 314.33 T +(// *************************************************************) 184.67 303.33 T +(if\050obj!=NULL\051) 184.67 292.33 T +({) 202.67 281.33 T +(cdevData & context = obj->reqObj_->getContext\050\051;) 202.67 270.33 T +(context.get\050demoService::VALUE_TAG, &VALUE_CTX\051;) 202.67 259.33 T +(context.get\050demoService::STATUS_TAG, &STATUS_CTX\051;) 202.67 248.33 T +(context.get\050demoService::SEVERITY_TAG, &SEVERITY_CTX\051;) 202.67 237.33 T +(context.get\050demoService::UNITS_TAG, &UNITS_CTX\051;) 202.67 226.33 T +(context.get\050demoService::CTRLHIGH_TAG, &CTRLHIGH_CTX\051;) 202.67 215.33 T +(context.get\050demoService::CTRLLOW_TAG, &CTRLLOW_CTX\051;) 202.67 204.33 T +(context.get\050demoService::ALRMHIGH_TAG, &ALRMHIGH_CTX\051;) 202.67 193.33 T +(context.get\050demoService::ALRMLOW_TAG, &ALRMLOW_CTX\051;) 202.67 182.33 T +(}) 202.67 171.33 T +(}) 184.67 160.33 T +(#endif /* _DEMO_SERVICE_H_ */) 166.67 138.33 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "38" 46 +%%Page: "39" 47 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 397.17 739 T +(vice: A Sample cde) 443.96 739 T +(v Ser) 520.72 739 T +(vice) 542 739 T +0 10 Q +(39) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 9: demoSer) 180 714 T +(vice) 257.3 714 T +(.cc: Source code f) 273.17 714 T +(or the demoSer) 344.93 714 T +(vice class) 407.23 714 T +180 81 558 720 C +180 84 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.21 86.33 559.79 702.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +180.25 90.45 554.2 708 R +7 X +V +0 X +N +184.67 93.5 550.95 704.33 R +7 X +V +5 9 Q +0 X +(#include ) 184.67 698.33 T +(#include ) 184.67 687.33 T +(#include ) 184.67 676.33 T +(#include ) 184.67 665.33 T +(#include ) 184.67 654.33 T +(#include ) 184.67 643.33 T +(// ****************************************************************) 184.67 621.33 T +(// * newDemoService:) 184.67 610.33 T +(// * This function is called by cdev to perform the initial) 184.67 599.33 T +-0.07 (// * instanciation of a demo device service. This function is used) 184.67 588.33 P +(// * to perform dynamic name resolution for the services that are) 184.67 577.33 T +(// * specified within the DDL file or the name server.) 184.67 566.33 T +(// ****************************************************************) 184.67 555.33 T +(cdevService * newDemoService \050 char * name, cdevSystem * system \051) 184.67 544.33 T +({) 202.67 533.33 T +(return new demoService\050name, *system\051;) 202.67 522.33 T +(}) 202.67 511.33 T +(// ****************************************************************) 184.67 489.33 T +(// * demoService::demoService :) 184.67 478.33 T +(// * This constructor is responsible for performing all service) 184.67 467.33 T +(// * initialization. Returns nothing.) 184.67 456.33 T +(// ****************************************************************) 184.67 445.33 T +(demoService::demoService \050 char * name, cdevSystem & system\051) 184.67 434.33 T +(: cdevService \050name, system\051, transactions\050NULL\051,) 202.67 423.33 T +( callback \050defCallback, NULL\051) 202.67 412.33 T +({) 202.67 401.33 T +(// ************************************************************) 202.67 390.33 T +(// * Obtain the values of the static tags used by this service) 202.67 379.33 T +(// ************************************************************) 202.67 368.33 T +(cdevData::tagC2I\050\322value\323, &VALUE_TAG\051;) 202.67 357.33 T +(cdevData::tagC2I\050\322status\323, &STATUS_TAG\051;) 202.67 346.33 T +(cdevData::tagC2I\050\322severity\323, &SEVERITY_TAG\051;) 202.67 335.33 T +(cdevData::tagC2I\050\322units\323, &UNITS_TAG\051;) 202.67 324.33 T +(cdevData::tagC2I\050\322controlHigh\323, &CTRLHIGH_TAG\051;) 202.67 313.33 T +(cdevData::tagC2I\050\322controlLow\323, &CTRLLOW_TAG\051;) 202.67 302.33 T +(cdevData::tagC2I\050\322alarmHigh\323, &ALRMHIGH_TAG\051;) 202.67 291.33 T +(cdevData::tagC2I\050\322alarmLow\323, &ALRMLOW_TAG\051;) 202.67 280.33 T +(// ************************************************************) 202.67 258.33 T +(// * At this point, I will transfer pointers to the external) 202.67 247.33 T +(// * demoDevice objects into my array of demoDevice pointers.) 202.67 236.33 T +(// *************************************************************) 202.67 225.33 T +(devices[0] = &DEVICE0;) 202.67 214.33 T +(devices[1] = &DEVICE1;) 202.67 203.33 T +(devices[2] = &DEVICE2;) 202.67 192.33 T +(devices[3] = &DEVICE3;) 202.67 181.33 T +(devices[4] = &DEVICE4;) 202.67 170.33 T +(}) 202.67 159.33 T +(// ****************************************************************) 184.67 137.33 T +(// * demoService::~demoService :) 184.67 126.33 T +(// * The destructor is protected to prevent it from being called) 184.67 115.33 T +(// * directly. The destructor performs any clean-up or shutdown) 184.67 104.33 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "39" 47 +%%Page: "40" 48 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 54 739 T +(vice: A Sample cde) 100.79 739 T +(v Ser) 177.55 739 T +(vice) 198.83 739 T +0 10 Q +(40) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Figure 9: demoSer) 162 714 T +(vice) 239.3 714 T +(.cc: \050contin) 255.17 714 T +(ued\051) 298.59 714 T +162 81 540 720 C +162 84 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.21 86.33 541.79 702.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +162.25 90.45 536.2 708 R +7 X +V +0 X +N +166.67 93.5 532.95 704.33 R +7 X +V +5 9 Q +0 X +(// * operations. Returns nothing.) 166.67 698.33 T +(// ****************************************************************) 166.67 687.33 T +(demoService::~demoService \050 void \051) 166.67 676.33 T +({) 184.67 665.33 T +(// *************************************************************) 184.67 654.33 T +-0.25 (// * Delete all outstanding transaction object nodes. Note that) 184.67 643.33 P +(// * typically a transaction object should not be deleted until) 184.67 632.33 T +(// * after it has been processed, because a group object may be) 184.67 621.33 T +(// * waiting on it. However, the removeFromGrps method will) 184.67 610.33 T +(// * remove the transaction object from any groups that may be) 184.67 599.33 T +(// * waiting for it.) 184.67 588.33 T +(// *************************************************************) 184.67 577.33 T +(while\050transactions != NULL\051) 184.67 566.33 T +({) 202.67 555.33 T +(cdevTranNode * node = transactions;) 202.67 544.33 T +(transactions = node->next;) 202.67 533.33 T +(if\050node->obj!=NULL\051) 202.67 522.33 T +({) 220.67 511.33 T +(if\050node->obj->status\050\051!=-1\051 node->obj->removeFromGrps\050\051;) 220.67 500.33 T +(delete node->obj;) 220.67 489.33 T +(}) 220.67 478.33 T +(delete node;) 202.67 467.33 T +(}) 202.67 456.33 T +(}) 184.67 445.33 T +(// ****************************************************************) 166.67 423.33 T +(// * demoService::getFd) 166.67 412.33 T +-0.08 (// * This function will return the list of file descriptors that the) 166.67 401.33 P +(// * demoService is using. This will allow the file descriptors to) 166.67 390.33 T +(// * be used in global select and poll calls performed at the) 166.67 379.33 T +(// * cdevSystem class level.) 166.67 368.33 T +(// *) 166.67 357.33 T +(// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.) 166.67 346.33 T +(// ****************************************************************) 166.67 335.33 T +(int demoService::getFd \050 int * &fd, int & numFd \051) 166.67 324.33 T +({) 184.67 313.33 T +(readfd[0] = selector.readfd\050\051;) 184.67 302.33 T +(fd = readfd;) 184.67 291.33 T +(numFd = 1;) 184.67 280.33 T +(return CDEV_SUCCESS;) 184.67 269.33 T +(}) 184.67 258.33 T +(// ****************************************************************) 166.67 225.33 T +(// * demoService::flush :) 166.67 214.33 T +(// * This function flushes all communications buffers that the) 166.67 203.33 T +(// * service may have open.) 166.67 192.33 T +(// * Returns CDEV_SUCCESS on success or an enumerated error.) 166.67 181.33 T +(// * Note: This service does not use communications buffers.) 166.67 170.33 T +(// ****************************************************************) 166.67 159.33 T +(int demoService::flush \050 void \051) 166.67 148.33 T +({) 184.67 137.33 T +(return CDEV_SUCCESS;) 184.67 126.33 T +(}) 184.67 115.33 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "40" 48 +%%Page: "41" 49 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 397.17 739 T +(vice: A Sample cde) 443.96 739 T +(v Ser) 520.72 739 T +(vice) 542 739 T +0 10 Q +(41) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 9: demoSer) 180 714 T +(vice) 257.3 714 T +(.cc: \050contin) 273.17 714 T +(ued\051) 316.59 714 T +180 81 558 720 C +180 85 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.21 87.33 559.79 703.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +180.25 91.45 554.2 709 R +7 X +V +0 X +N +184.67 94.5 550.95 705.33 R +7 X +V +5 9 Q +0 X +(// ****************************************************************) 184.67 699.33 T +(// * demoService::poll :) 184.67 688.33 T +(// * This function submits a pend request that is short enough to) 184.67 677.33 T +-0.07 (// * allow only one cdevTranObj to be dequeued and submitted to the) 184.67 666.33 P +(// * demoDevice for processing.) 184.67 655.33 T +(// * Returns CDEV_SUCCESS on success or an enumerated error.) 184.67 644.33 T +(// ****************************************************************) 184.67 633.33 T +(int demoService::poll \050 void \051) 184.67 622.33 T +({) 202.67 611.33 T +(return pend\0500.0001\051;) 202.67 600.33 T +(}) 202.67 589.33 T +(// ****************************************************************) 184.67 567.33 T +(// * demoService::pend :) 184.67 556.33 T +-0.53 (// * This function will process all of the cdevTranObj messages that) 184.67 545.33 P +(// * are residing in the queue.) 184.67 534.33 T +(// * Returns CDEV_SUCCESS on success or an enumerated error.) 184.67 523.33 T +(// ****************************************************************) 184.67 512.33 T +(int demoService::pend \050 int \051) 184.67 501.33 T +({) 202.67 490.33 T +(while\050transactions != NULL\051) 202.67 479.33 T +({) 220.67 468.33 T +(cdevTranNode * node = transactions;) 220.67 457.33 T +(transactions = node->next;) 220.67 446.33 T +(processTransaction \050node\051;) 220.67 435.33 T +(}) 220.67 424.33 T +(selector.purge\050\051;) 202.67 413.33 T +(return CDEV_SUCCESS;) 202.67 402.33 T +(}) 202.67 391.33 T +(// ****************************************************************) 184.67 369.33 T +(// * demoService::pend :) 184.67 358.33 T +(// * Pends until the named file descriptor \050or any file descriptor) 184.67 347.33 T +(// * if fd = -1\051 is ready. Will pend for no longer than the user) 184.67 336.33 T +(// * specified number of seconds.) 184.67 325.33 T +(// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.) 184.67 314.33 T +(// ****************************************************************) 184.67 303.33 T +(int demoService::pend \050 double seconds, int \051) 184.67 292.33 T +({) 202.67 281.33 T +(cdevTimeValue t\050seconds\051;) 202.67 270.33 T +(cdevClock timer;) 202.67 259.33 T +(timer.schedule\050NULL, t\051;) 202.67 237.33 T +(while\050transactions!=NULL && !timer.expired\050\051\051) 202.67 215.33 T +({) 220.67 204.33 T +(cdevTranNode * node = transactions;) 220.67 193.33 T +(transactions = node->next;) 220.67 182.33 T +(processTransaction\050node\051;) 220.67 171.33 T +(selector.removeEvent\050\051;) 220.67 160.33 T +(}) 220.67 149.33 T +(if\050transactions==NULL\051 selector.purge\050\051;) 202.67 127.33 T +(return CDEV_SUCCESS;) 202.67 116.33 T +(}) 202.67 105.33 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "41" 49 +%%Page: "42" 50 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 54 739 T +(vice: A Sample cde) 100.79 739 T +(v Ser) 177.55 739 T +(vice) 198.83 739 T +0 10 Q +(42) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Figure 9: demoSer) 162 714 T +(vice) 239.3 714 T +(.cc: \050contin) 255.17 714 T +(ued\051) 298.59 714 T +162 81 540 720 C +162 85 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.71 87.33 541.29 703.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +161.75 91.45 535.7 709 R +7 X +V +0 X +N +166.17 94.5 532.45 705.33 R +7 X +V +5 9 Q +0 X +(// ****************************************************************) 166.17 699.33 T +(// * demoService::getRequestObject :) 166.17 688.33 T +(// * This is the interface that cdev objects will use to obtain a) 166.17 677.33 T +(// * demoRequestObject object. The demoRequestObject represents a) 166.17 666.33 T +(// * combined device and message pair that is associated with the) 166.17 655.33 T +(// * demoService.) 166.17 644.33 T +(// *) 166.17 633.33 T +(// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error.) 166.17 622.33 T +(// ****************************************************************) 166.17 611.33 T +(int demoService::getRequestObject \050 char * device, char * message,) 166.17 600.33 T +(cdevRequestObject * &req\051) 346.17 589.33 T +({) 184.17 578.33 T +(req = new demoRequestObject \050device, message, system_\051;) 184.17 567.33 T +(return \050req ? CDEV_SUCCESS : CDEV_ERROR\051;) 184.17 556.33 T +(}) 184.17 545.33 T +(// ****************************************************************) 166.17 523.33 T +(// * demoService::enqueueTransaction :) 166.17 512.33 T +(// * Allows the caller to place a cdevTranObj object and cdevData) 166.17 501.33 T +(// * object into the outgoing queue. This function also calls the) 166.17 490.33 T +(// * selector.insertEvent\050\051 method to activate the file descriptor.) 166.17 479.33 T +(// ****************************************************************) 166.17 468.33 T +(int demoService::enqueueTransaction \050 cdevTranObj * obj,) 166.17 457.33 T +( cdevData * inbound \051) 346.17 446.33 T +({) 184.17 435.33 T +(int result = CDEV_SUCCESS;) 184.17 424.33 T +(if\050obj!=NULL\051) 184.17 402.33 T +({) 202.17 391.33 T +(cdevTranNode * node = transactions, * prev = NULL;) 202.17 380.33 T +(while\050node!=NULL\051) 202.17 369.33 T +({) 220.17 358.33 T +(prev = node;) 220.17 347.33 T +(node = prev->next;) 220.17 336.33 T +(}) 220.17 325.33 T +(node = new cdevTranNode\050obj, inbound\051;) 202.17 314.33 T +(if\050prev==NULL\051 transactions = node;) 202.17 303.33 T +(else prev->next = node;) 202.17 292.33 T +(selector.insertEvent\050\051;) 202.17 281.33 T +(}) 202.17 270.33 T +(else result = CDEV_INVALIDARG;) 184.17 259.33 T +(return result;) 184.17 237.33 T +(}) 184.17 226.33 T +(// ****************************************************************) 166.17 204.33 T +(// * demoService::processTransaction :) 166.17 193.33 T +(// * This function will take a cdevTranNode and will locate the) 166.17 182.33 T +-0.45 (// * device associated with it. It will then interpret the verb and) 166.17 171.33 P +(// * attribute and will execute the correct command on the device.) 166.17 160.33 T +(// *) 166.17 149.33 T +(// * Note:) 166.17 138.33 T +(This object is responsible for deleting the cdevTranNode) 220.17 138.33 T +(// * after it has been processed.) 166.17 127.33 T +(// ****************************************************************) 166.17 116.33 T +(int demoService::processTransaction \050 cdevTranNode * node \051) 166.17 105.33 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "42" 50 +%%Page: "43" 51 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 397.17 739 T +(vice: A Sample cde) 443.96 739 T +(v Ser) 520.72 739 T +(vice) 542 739 T +0 10 Q +(43) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 9: demoSer) 180 714 T +(vice) 257.3 714 T +(.cc: \050contin) 273.17 714 T +(ued\051) 316.59 714 T +180 81 558 720 C +180 84 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.21 86.33 559.79 702.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +180.25 90.45 554.2 708 R +7 X +V +0 X +N +184.67 93.5 550.95 704.33 R +7 X +V +5 9 Q +0 X +({) 202.67 698.33 T +(cdevTranObj * obj = node->obj;) 202.67 687.33 T +(demoRequestObject * reqObj =) 202.67 676.33 T +(obj?\050demoRequestObject *\051obj->reqObj_:NULL;) 220.67 665.33 T +(cdevData * out =) 202.67 654.33 T +(obj?obj->resultData_:NULL;) 220.67 643.33 T +(char * name =) 202.67 632.33 T +(obj?\050char *\051obj->reqObj_->device\050\051.name\050\051:NULL;) 220.67 621.33 T +(int result = CDEV_SUCCESS;) 202.67 610.33 T +(int idx = 0;) 202.67 599.33 T +(cdevData data;) 202.67 588.33 T +(// *************************************************************) 202.67 566.33 T +(// * Ensure that if the obj is valid it has a valid cdevData) 202.67 555.33 T +(// * object for its result.) 202.67 544.33 T +(// *************************************************************) 202.67 533.33 T +(if\050obj!=NULL && obj->resultData_==NULL\051 obj->resultData_=&data;) 202.67 522.33 T +(out = obj?obj->resultData_:NULL;) 202.67 511.33 T +(// *************************************************************) 202.67 489.33 T +(// * Ensure that a valid transaction object was submitted.) 202.67 478.33 T +(// * Remembering to produce an error that the user can catch.) 202.67 467.33 T +(// *************************************************************) 202.67 456.33 T +(if\050obj==NULL\051 result=) 202.67 445.33 T +(reqObj->emitError\050CDEV_INVALIDARG, \322service\323\051;) 220.67 434.33 T +(// *************************************************************) 202.67 412.33 T +(// * Test to ensure that the device name specified is valid and) 202.67 401.33 T +(// * obtain the index to the demoDevice in the array. A better) 202.67 390.33 T +(// * implementation might cache a pointer to the specific device) 202.67 379.33 T +(// * within the demoRequestObject.) 202.67 368.33 T +(// *************************************************************) 202.67 357.33 T +(else if\050strncmp\050reqObj->device\050\051.name\050\051, \322DEVICE\323, 6\051!=0 ||) 202.67 346.33 T +(\050idx = atoi\050reqObj->device\050\051.name\050\051+6\051\051<0 || idx > 9\051) 220.67 335.33 T +({) 220.67 324.33 T +(result = reqObj->emitError\050CDEV_INVALIDSVC, \322service\323\051;) 220.67 313.33 T +(}) 220.67 302.33 T +(// *************************************************************) 202.67 280.33 T +(// * Process the specific message.) 202.67 269.33 T +(// *************************************************************) 202.67 258.33 T +(else if\050result==CDEV_SUCCESS\051) 202.67 247.33 T +({) 220.67 236.33 T +(int attr = -1;) 220.67 225.33 T +(// *********************************************************) 220.67 203.33 T +(// * Obtain the index of the attribute within the demoDevice) 220.67 192.33 T +(// *********************************************************) 220.67 181.33 T +(if\050\050reqObj->command\050\051 & ATTR_MASK\051==VAL\051) 220.67 170.33 T +(attr=devices[idx]->getIndex\050\322VAL\323\051;) 238.67 159.33 T +(else if\050\050reqObj->command\050\051 & ATTR_MASK\051==BDL\051) 220.67 137.33 T +(attr=devices[idx]->getIndex\050\322BDL\323\051;) 238.67 126.33 T +(switch\050reqObj->command\050\051\051) 220.67 104.33 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "43" 51 +%%Page: "44" 52 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 54 739 T +(vice: A Sample cde) 100.79 739 T +(v Ser) 177.55 739 T +(vice) 198.83 739 T +0 10 Q +(44) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Figure 9: demoSer) 162 714 T +(vice) 239.3 714 T +(.cc: \050contin) 255.17 714 T +(ued\051) 298.59 714 T +162 81 540 720 C +162 84 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.71 86.33 541.29 702.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +161.75 90.45 535.7 708 R +7 X +V +0 X +N +166.17 93.5 532.45 704.33 R +7 X +V +5 9 Q +0 X +({) 220.17 698.33 T +(// *****************************************************) 220.17 687.33 T +(// * \322get VAL\323 || \322get BDL\323 messages) 220.17 676.33 T +(// *) 220.17 665.33 T +(This will populate the outbound cdevData object) 247.17 665.33 T +(// *) 220.17 654.33 T +(with all of the context items that were in) 241.77 654.33 T +(// *) 220.17 643.33 T +(place when the transaction object was created.) 241.77 643.33 T +(// *****************************************************) 220.17 632.33 T +(case GET | VAL:) 220.17 621.33 T +(case GET | BDL:) 220.17 610.33 T +(if\050node->VALUE_CTX\051) 220.17 599.33 T +(out->insert\050VALUE_TAG,) 238.17 588.33 T +( devices[idx]->getValue\050attr\051\051;) 292.17 577.33 T +(if\050node->STATUS_CTX\051) 220.17 566.33 T +(out->insert\050STATUS_TAG,) 238.17 555.33 T +( devices[idx]->getStatus\050attr\051\051;) 292.17 544.33 T +(if\050node->SEVERITY_CTX\051) 220.17 533.33 T +(out->insert\050SEVERITY_TAG,) 238.17 522.33 T +( devices[idx]->getSeverity\050attr\051\051;) 292.17 511.33 T +(if\050node->UNITS_CTX\051) 220.17 500.33 T +(out->insert\050UNITS_TAG,) 238.17 489.33 T +( devices[idx]->getUnits\050attr\051\051;) 292.17 478.33 T +(if\050node->CTRLLOW_CTX\051) 220.17 467.33 T +(out->insert\050CTRLLOW_TAG,) 238.17 456.33 T +( devices[idx]->getControlLow\050attr\051\051;) 292.17 445.33 T +(if\050node->CTRLHIGH_CTX\051) 220.17 434.33 T +(out->insert\050CTRLHIGH_TAG,) 238.17 423.33 T +( devices[idx]->getControlHigh\050attr\051\051;) 292.17 412.33 T +(if\050node->ALRMLOW_CTX\051) 220.17 401.33 T +(out->insert\050ALRMLOW_TAG,) 238.17 390.33 T +( devices[idx]->getAlarmLow\050attr\051\051;) 292.17 379.33 T +(if\050node->ALRMHIGH_CTX\051) 220.17 368.33 T +(out->insert\050ALRMHIGH_TAG,) 238.17 357.33 T +( devices[idx]->getAlarmHigh\050attr\051\051;) 292.17 346.33 T +(break;) 220.17 335.33 T +(// *****************************************************) 220.17 313.33 T +(// * \322set VAL\323 || \322set BDL\323 message. These messages) 220.17 302.33 T +(// * will allow the caller to set the current value of) 220.17 291.33 T +(// * the device. This section ensures that an error) 220.17 280.33 T +(// * is emitted if the operation fails.) 220.17 269.33 T +(// *****************************************************) 220.17 258.33 T +(case SET | VAL:) 220.17 247.33 T +(if\050node->inbound.getType\050VALUE_TAG\051==CDEV_DOUBLE\051) 220.17 236.33 T +({) 238.17 225.33 T +(double val;) 238.17 214.33 T +(size_t elems = 0;) 238.17 203.33 T +(node->inbound.getElems\050VALUE_TAG, &elems\051;) 238.17 181.33 T +(if\050elems==1 &&) 238.17 170.33 T +( node->inbound.get\050VALUE_TAG, &val\051==CDEV_SUCCESS\051) 238.17 159.33 T +({) 256.17 148.33 T +(if\050devices[idx]->setValue\050attr, val\051==0\051) 256.17 137.33 T +({) 274.17 126.33 T +(result = CDEV_SUCCESS;) 274.17 115.33 T +(}) 274.17 104.33 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "44" 52 +%%Page: "45" 53 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 397.17 739 T +(vice: A Sample cde) 443.96 739 T +(v Ser) 520.72 739 T +(vice) 542 739 T +0 10 Q +(45) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 9: demoSer) 180 714 T +(vice) 257.3 714 T +(.cc: \050contin) 273.17 714 T +(ued\051) 316.59 714 T +180 81 558 720 C +180 84 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.71 86.33 559.29 702.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +179.75 90.45 553.7 708 R +7 X +V +0 X +N +184.17 93.5 550.45 704.33 R +7 X +V +5 9 Q +0 X +(else) 274.17 698.33 T +({) 292.17 687.33 T +(system_.reportError) 292.17 676.33 T +(\0502, demoService::name\050\051, *reqObj,) 310.17 665.33 T +(\322Value out of range for this device\134n\323,\051;) 310.17 654.33 T +(result = CDEV_INVALIDARG;) 292.17 643.33 T +(}) 292.17 632.33 T +(}) 274.17 621.33 T +(else result =) 256.17 610.33 T +(reqObj->emitError\050CDEV_CONFLICT, \322service\323\051;) 274.17 599.33 T +(}) 256.17 588.33 T +(else result =) 238.17 577.33 T +(reqObj->emitError\050CDEV_INVALIDARG, \322service\323\051;) 256.17 566.33 T +(break;) 238.17 555.33 T +(// *****************************************************) 238.17 533.33 T +(// * Invalid combination of verb and attribute) 238.17 522.33 T +(// *****************************************************) 238.17 511.33 T +(default:) 238.17 500.33 T +(result = reqObj->emitError\050CDEV_ERROR, \322service\323\051;) 238.17 489.33 T +(break;) 238.17 478.33 T +(}) 238.17 467.33 T +(// ********************************************************) 220.17 445.33 T +(// * Fire the user specified callback function to give the) 220.17 434.33 T +(// * user the result.) 220.17 423.33 T +(// ********************************************************) 220.17 412.33 T +(if\050obj->userCallback_!=NULL\051) 220.17 401.33 T +({) 238.17 390.33 T +(\050*\050obj->userCallback_->callbackFunction\050\051\051\051) 238.17 379.33 T +(\050result==CDEV_SUCCESS?CDEV_SUCCESS:CDEV_ERROR,) 256.17 368.33 T +( obj->userCallback_->userarg\050\051,) 256.17 357.33 T +( *reqObj,) 256.17 346.33 T +( *out\051;) 256.17 335.33 T +(}) 238.17 324.33 T +(}) 220.17 313.33 T +(// ************************************************************) 202.17 291.33 T +(// * Delete the cdevTranNode object.) 202.17 280.33 T +(// ************************************************************) 202.17 269.33 T +(if\050node!=NULL\051) 202.17 258.33 T +({) 220.17 247.33 T +(if\050node->obj!=NULL\051) 220.17 236.33 T +({) 238.17 225.33 T +(node->obj->removeFromGrps\050\051;) 238.17 214.33 T +(delete node->obj;) 238.17 203.33 T +(}) 238.17 192.33 T +(delete node;) 220.17 181.33 T +(}) 220.17 170.33 T +(// ************************************************************) 202.17 148.33 T +(// * Return the result.) 202.17 137.33 T +(// ************************************************************) 202.17 126.33 T +(return result;) 202.17 115.33 T +(}) 202.17 104.33 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "45" 53 +%%Page: "46" 54 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 54 739 T +(vice: A Sample cde) 100.79 739 T +(v Ser) 177.55 739 T +(vice) 198.83 739 T +0 10 Q +(46) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Figure 9: demoSer) 162 714 T +(vice) 239.3 714 T +(.cc: \050contin) 255.17 714 T +(ued\051) 298.59 714 T +2 10 Q +(The) 54 555 T +2 9 Q +(demoRequestObject) 54 543.67 T +2 10 Q +( Object) 54 532 T +0 F +1.86 (The) 162 555 P +3 F +1.86 (demoRequestObject) 183.87 555 P +0 F +1.86 ( C++ class is der) 275.02 555 P +1.86 (iv) 357.08 555 P +1.86 (ed from the) 364.05 555 P +3 F +1.86 (cde) 422.99 555 P +1.86 (vRequestObject) 438.81 555 P +0 F +1.86 ( class) 509.95 555 P +1.86 (.) 537.22 555 P +0.02 (When the caller uses the) 162 543 P +3 F +0.02 (cde) 274.92 543 P +0.02 (vDe) 290.74 543 P +0.02 (vice) 308.22 543 P +0 F +0.02 ( object to submit a suppor) 326 543 P +0.02 (ted message to one of) 440.98 543 P +1.72 (the) 162 531 P +3 F +1.72 (demoDe) 180.4 531 P +1.72 (vices) 217.89 531 P +0 F +1.72 (, a) 240.52 531 P +3 F +1.72 (demoRequestObject) 257.85 531 P +0 F +1.72 ( is created. This object de\336nes the) 349 531 P +3 F +1.72 (send,) 515.54 531 P +1.4 (sendNoBloc) 162 519 P +1.4 (k) 215.71 519 P +0 F +1.4 ( and) 220.71 519 P +3 F +1.4 (sendCallbac) 245.76 519 P +1.4 (k) 300.58 519 P +0 F +1.4 ( methods that are used to submit messages to the) 305.58 519 P +3 F +9.34 (demoSer) 162 507 P +9.34 (vice) 202.87 507 P +0 F +9.34 ( object. This request object restr) 220.65 507 P +9.34 (icts itself to using the) 409.8 507 P +3 F +1.01 (enqueueT) 162 495 P +1.01 (r) 205.83 495 P +1.01 (ansaction) 209.06 495 P +0 F +1.01 (method of the) 255.65 495 P +3 F +1.01 (demoSer) 322.61 495 P +1.01 (vice) 363.48 495 P +0 F +1.01 ( object to submit messages) 381.26 495 P +1.01 (. A real) 506.3 495 P +0 (implementation might precalculate and cache man) 162 483 P +0 (y of the data v) 384.69 483 P +0 (ar) 447.24 483 P +0 (iab) 456.28 483 P +0 (les and pointers) 469.42 483 P +2.5 (within the request object. These v) 162 471 P +2.5 (ar) 323.19 471 P +2.5 (iab) 332.23 471 P +2.5 (le can be retr) 345.37 471 P +2.5 (ie) 411.37 471 P +2.5 (v) 418.85 471 P +2.5 (ed b) 423.6 471 P +2.5 (y the ser) 445.36 471 P +2.5 (vice dur) 489 471 P +2.5 (ing) 526.66 471 P +(successiv) 162 459 T +(e e) 205.09 459 T +(x) 218.69 459 T +(ecutions of the message) 223.39 459 T +(.) 331.63 459 T +3 9 Q +(Figure 10: demoRequestObject.h: Header \336le f) 162 425.67 T +(or the demoRequestObject class) 350.32 425.67 T +162 580.67 540 720 C +162 597.67 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.71 603.33 541.29 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +161.75 608.29 535.7 705 R +7 X +V +0 X +N +166.17 613.01 532.45 701.33 R +7 X +V +5 9 Q +0 X +(// ****************************************************************) 166.17 695.33 T +(// * demoService::defCallback :) 166.17 684.33 T +(// * This function is a default callback function for the service.) 166.17 673.33 T +(// ****************************************************************) 166.17 662.33 T +(void demoService::defCallback \050 int, void *, cdevRequestObject &,) 166.17 651.33 T +(cdevData &\051) 328.17 640.33 T +({) 184.17 629.33 T +(}) 184.17 618.33 T +162 580.67 540 720 C +0 0 612 792 C +162 81 540 561.67 C +162 84.33 540 422.67 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.71 85.84 541.29 411.24 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +161.75 89.95 535.7 416.67 R +7 X +V +0 X +N +166.17 93.84 532.45 413 R +7 X +V +5 9 Q +0 X +(#ifndef _DEMO_REQUEST_OBJECT_H_) 166.17 407 T +(#define _DEMO_REQUEST_OBJECT_H_) 166.17 396 T +(#include ) 166.17 374 T +(#include ) 166.17 363 T +(#include ) 166.17 352 T +(#include ) 166.17 341 T +(// ****************************************************************) 166.17 319 T +(// * class demoRequestObject:) 166.17 308 T +-0.09 (// * The demoRequestObject class provides the interface for sending) 166.17 297 P +(// * messages to a demoDevice. All device/message commands are) 166.17 286 T +(// * routed) 166.17 275 T +(// * through a demoRequestObject either directly or indirectly.) 166.17 264 T +(// *) 166.17 253 T +(// * Note that this object is inherited from the standard) 166.17 242 T +(// * cdevRequestObject and derives most of its functionality from) 166.17 231 T +(// * that class.) 166.17 220 T +(// ****************************************************************) 166.17 209 T +(class demoRequestObject : public cdevRequestObject) 166.17 198 T +({) 166.17 187 T +(public:) 166.17 176 T +(// ************************************************************) 184.17 165 T +(// * demoRequestObject::demoRequestObject :) 184.17 154 T +(// * This constructor initializes a device/message combination) 184.17 143 T +(// * associated with a demoDevice. Returns nothing.) 184.17 132 T +(// ************************************************************) 184.17 121 T +(demoRequestObject \050 char * device, char * message,) 184.17 110 T +(cdevSystem & system=cdevSystem::defaultSystem\050\051\051;) 202.17 99 T +162 81 540 561.67 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "46" 54 +%%Page: "47" 55 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 397.17 739 T +(vice: A Sample cde) 443.96 739 T +(v Ser) 520.72 739 T +(vice) 542 739 T +0 10 Q +(47) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 10: demoRequestObject.h: \050contin) 180 714 T +(ued\051) 346.99 714 T +180 81 558 720 C +180 84 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.71 86.33 559.29 702.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +179.75 90.45 553.7 708 R +7 X +V +0 X +N +184.17 93.5 550.45 704.33 R +7 X +V +5 9 Q +0 X +(// *************************************************************) 202.17 698.33 T +(// * demoRequestObject::~demoRequestObject :) 202.17 687.33 T +(// * This destructor performs any deallocation operations) 202.17 676.33 T +(// * necessary, prior to the destruction of the object.) 202.17 665.33 T +(// * Returns nothing.) 202.17 654.33 T +(// *************************************************************) 202.17 643.33 T +(~demoRequestObject \050 void \051 {}) 202.17 632.33 T +(// *************************************************************) 202.17 610.33 T +(// * demoRequestObject::send :) 202.17 599.33 T +(// * The send interface is used to provide synchronous I/O with) 202.17 588.33 T +(// * the service.) 202.17 577.33 T +(// *) 202.17 566.33 T +(// * Returns CDEV_SUCCESS on success or an enumerated error.) 202.17 555.33 T +(// *************************************************************) 202.17 544.33 T +(int send \050 cdevData & in, cdevData & out \051) 202.17 533.33 T +({ return send\050&in, &out\051; }) 220.17 522.33 T +(int send \050 cdevData * in, cdevData & out \051) 202.17 511.33 T +({ return send\050in, &out\051; }) 220.17 500.33 T +(int send \050 cdevData & in, cdevData * out \051) 202.17 489.33 T +({ return send\050&in, out\051; }) 220.17 478.33 T +(int send \050 cdevData * in, cdevData * out \051;) 202.17 467.33 T +(// *************************************************************) 202.17 445.33 T +(// * demoRequestObject::sendNoBlock :) 202.17 434.33 T +(// * The sendNoBlock interface is used in concert with cdevGroup) 202.17 423.33 T +(// * or cdevSystem to execute a series of operations.) 202.17 412.33 T +(// *) 202.17 401.33 T +(// * Returns CDEV_SUCCESS on success or an enumerated error.) 202.17 390.33 T +(// *************************************************************) 202.17 379.33 T +(int sendNoBlock \050cdevData & in, cdevData & out\051) 202.17 368.33 T +({ return sendNoBlock\050&in, &out\051; }) 220.17 357.33 T +(int sendNoBlock \050cdevData * in, cdevData & out\051) 202.17 346.33 T +({ return sendNoBlock\050in, &out\051; }) 220.17 335.33 T +(int sendNoBlock \050cdevData & in, cdevData * out\051) 202.17 324.33 T +({ return sendNoBlock\050&in, out\051; }) 220.17 313.33 T +(int sendNoBlock \050cdevData * in, cdevData * out\051;) 202.17 302.33 T +(// *************************************************************) 202.17 280.33 T +(// * demoRequestObject::sendCallback :) 202.17 269.33 T +(// * The sendCallback interface provides asynch communications) 202.17 258.33 T +(// * with the service.) 202.17 247.33 T +(// *) 202.17 236.33 T +(// *) 202.17 225.33 T +(Returns CDEV_SUCCESS on success or an enumerated error.) 223.77 225.33 T +(// *************************************************************) 202.17 214.33 T +(int sendCallback \050cdevData & in, cdevCallback & callback\051) 202.17 203.33 T +({ return sendCallback\050&in, callback\051; }) 220.17 192.33 T +(int sendCallback \050cdevData * in, cdevCallback & callback\051;) 202.17 181.33 T +(// *************************************************************) 202.17 159.33 T +(// * demoRequestObject::emitError :) 202.17 148.33 T +(// * This method is used to emit a descriptive error if a) 202.17 137.33 T +(// * failure occurs while transmitting or receiving a message.) 202.17 126.33 T +(// *************************************************************) 202.17 115.33 T +(int emitError \050 int result, char * function \051;) 202.17 104.33 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "47" 55 +%%Page: "48" 56 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 54 739 T +(vice: A Sample cde) 100.79 739 T +(v Ser) 177.55 739 T +(vice) 198.83 739 T +0 10 Q +(48) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Figure 10: demoRequestObject.h: \050contin) 162 714 T +(ued\051) 328.99 714 T +(Figure 11: demoRequestObject.cc: Source f) 162 357 T +(or the demoRequestObject class) 339.31 357 T +162 81 540 720 C +162 421 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.71 424.17 541.29 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +161.75 429.12 535.7 705 R +7 X +V +0 X +N +166.17 433.01 532.45 701.33 R +7 X +V +5 9 Q +0 X +(// *************************************************************) 184.17 695.33 T +(// * demoRequestObject::className :) 184.17 684.33 T +(// * This function returns the name of the class as a constant) 184.17 673.33 T +(// * string) 184.17 662.33 T +(// *************************************************************) 184.17 651.33 T +(const char * className \050 void \051 const) 184.17 640.33 T +({) 202.17 629.33 T +(return \322demoRequestObject\323;) 202.17 618.33 T +(}) 202.17 607.33 T +(// *************************************************************) 184.17 585.33 T +(// * demoRequestObject::command :) 184.17 574.33 T +(// * Returns the combined verb and attr that describe this) 184.17 563.33 T +(// * demoRequestObject. This command is used by the demoService) 184.17 552.33 T +-0.25 (// * to determine the operation that is specified by this object.) 184.17 541.33 P +(// *************************************************************) 184.17 530.33 T +(int command \050 void \051 { return \050verb | attr\051; }) 184.17 519.33 T +(private:) 166.17 497.33 T +(demoService::VERB verb;) 184.17 486.33 T +(demoService::ATTR attr;) 184.17 475.33 T +(};) 184.17 464.33 T +(#endif /* _DEMO_REQUEST_OBJECT_H_ */) 166.17 442.33 T +162 81 540 720 C +0 0 612 792 C +162 81 540 720 C +162 97.34 540 354 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.71 99.67 541.29 342.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +161.75 104.62 535.7 348 R +7 X +V +0 X +N +166.17 109.34 532.45 344.33 R +7 X +V +5 9 Q +0 X +(#include ) 166.17 338.33 T +(#include ) 166.17 327.33 T +(// ****************************************************************) 166.17 305.33 T +(// * demoRequestObject::demoRequestObject :) 166.17 294.33 T +(// * This constructor initializes the internals of a device/message) 166.17 283.33 T +(// * pair associated with the compound device.) 166.17 272.33 T +(// *) 166.17 261.33 T +(// * Returns nothing.) 166.17 250.33 T +(// ****************************************************************) 166.17 239.33 T +(demoRequestObject::demoRequestObject) 166.17 228.33 T +(\050 char *device, char *message, cdevSystem & system\051) 184.17 217.33 T +(: cdevRequestObject\050device, message, system\051,) 184.17 206.33 T +( verb\050demoService::INVALID_VERB\051,) 184.17 195.33 T +( attr\050demoService::INVALID_ATTR\051) 184.17 184.33 T +({) 184.17 173.33 T +(char Verb[32];) 184.17 162.33 T +(char Attr[32];) 184.17 151.33 T +(char * mptr = message;) 184.17 140.33 T +(char * vptr = Verb;) 184.17 129.33 T +(char * aptr = Attr;) 184.17 118.33 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "48" 56 +%%Page: "49" 57 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 397.17 739 T +(vice: A Sample cde) 443.96 739 T +(v Ser) 520.72 739 T +(vice) 542 739 T +0 10 Q +(49) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 11: demoRequestObject.cc: \050contin) 180 714 T +(ued\051) 350.98 714 T +180 81 558 720 C +180 84 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.71 86.33 559.29 702.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +179.75 90.45 553.7 708 R +7 X +V +0 X +N +184.17 93.5 550.45 704.33 R +7 X +V +5 9 Q +0 X +(// *************************************************************) 202.17 698.33 T +(// * Extract the verb and the attribute from the message string) 202.17 687.33 T +(// * that was provided by the caller.) 202.17 676.33 T +(// *************************************************************) 202.17 665.33 T +(while\050*mptr && isspace\050*mptr\051\051 mptr++;) 202.17 654.33 T +(while\050*mptr && !isspace\050*mptr\051\051 *\050vptr++\051 = *\050mptr++\051;) 202.17 643.33 T +(*vptr = 0;) 202.17 632.33 T +(while\050*mptr && isspace\050*mptr\051\051 mptr++;) 202.17 621.33 T +(while\050*mptr && !isspace\050*mptr\051\051 *\050aptr++\051 = *\050mptr++\051;) 202.17 610.33 T +(*aptr = 0;) 202.17 599.33 T +(// *************************************************************) 202.17 577.33 T +(// * Evaluate the Verb element and assign the appropriate value) 202.17 566.33 T +(// * to the enumerated verb variable.) 202.17 555.33 T +(// *************************************************************) 202.17 544.33 T +(if \050!strcmp\050Verb, \322get\323\051\051 verb = demoService::GET;) 202.17 533.33 T +(else if\050!strcmp\050Verb, \322set\323\051\051 verb = demoService::SET;) 202.17 522.33 T +(// *************************************************************) 202.17 500.33 T +(// * Evaluate the Attr element and assign the appropriate value) 202.17 489.33 T +(// * to the enumerated attr variable.) 202.17 478.33 T +(// *************************************************************) 202.17 467.33 T +(if \050!strcmp\050Attr, \322VAL\323\051\051 attr = demoService::VAL;) 202.17 456.33 T +(else if\050!strcmp\050Attr, \322BDL\323\051\051 attr = demoService::BDL;) 202.17 445.33 T +(}) 202.17 434.33 T +(// ****************************************************************) 184.17 412.33 T +(// * demoRequestObject::sendNoBlock :) 184.17 401.33 T +(// *) 184.17 390.33 T +(This function allows the caller to submit an asynchronous) 211.17 390.33 T +(// * message to the server for processing.) 184.17 379.33 T +(// ****************************************************************) 184.17 368.33 T +(int demoRequestObject::sendNoBlock \050cdevData * in, cdevData * out\051) 184.17 357.33 T +({) 202.17 346.33 T +(// *************************************************************) 202.17 335.33 T +(// * Get a pointer to the demoService to handle this request) 202.17 324.33 T +(// *************************************************************) 202.17 313.33 T +(demoService * svc = \050demoService *\051service_;) 202.17 302.33 T +(// *************************************************************) 202.17 280.33 T +(// * Construct a cdev transaction object to track this) 202.17 269.33 T +(// * transaction. Use the disableDeleteCbk method to prevent the) 202.17 258.33 T +(// * cdevCallback object from being deleted by the cdevTranObj.) 202.17 247.33 T +(// *************************************************************) 202.17 236.33 T +(cdevTranObj * xobj =) 202.17 225.33 T +(new cdevTranObj\050&system_, this, out, &svc->callback\051;) 220.17 214.33 T +(xobj->disableDeleteCbk\050\051;) 202.17 203.33 T +(// *************************************************************) 202.17 181.33 T +(// * Enqueue the transaction object so that it may be processed) 202.17 170.33 T +(// * later. The result returned by the enqueueTransaction) 202.17 159.33 T +(// * function is returned by this function.) 202.17 148.33 T +(// *************************************************************) 202.17 137.33 T +(return emitError) 202.17 126.33 T +(\050svc->enqueueTransaction\050xobj, in\051, \322sendNoBlock\323\051;) 220.17 115.33 T +(}) 202.17 104.33 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "49" 57 +%%Page: "50" 58 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 54 739 T +(vice: A Sample cde) 100.79 739 T +(v Ser) 177.55 739 T +(vice) 198.83 739 T +0 10 Q +(50) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Figure 11: demoRequestObject.cc: \050contin) 162 714 T +(ued\051) 332.98 714 T +162 81 540 720 C +162 84 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.21 86.33 541.79 702.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +162.25 90.45 536.2 708 R +7 X +V +0 X +N +166.67 93.5 532.95 704.33 R +7 X +V +5 9 Q +0 X +(// ****************************************************************) 166.67 698.33 T +(// * demoRequestObject::sendCallback :) 166.67 687.33 T +(// *) 166.67 676.33 T +(This function allows the caller to submit an asynchronous) 193.67 676.33 T +(// * message to the server for processing.) 166.67 665.33 T +(// ****************************************************************) 166.67 654.33 T +(int demoRequestObject::sendCallback) 166.67 643.33 T +(\050cdevData * in, cdevCallback & callback\051) 184.67 632.33 T +({) 184.67 621.33 T +(// ************************************************************) 184.67 610.33 T +(// * Get a pointer to the demoService to handle this request) 184.67 599.33 T +(// ************************************************************) 184.67 588.33 T +(demoService * svc = \050demoService *\051service_;) 184.67 577.33 T +(// ************************************************************) 184.67 555.33 T +(// * Make a cdev transaction object to track this transaction.) 184.67 544.33 T +(// * Note that the user specified callback object is provided) 184.67 533.33 T +(// * to the object and that no cdevData object is provided for) 184.67 522.33 T +(// * the result.) 184.67 511.33 T +(// ************************************************************) 184.67 500.33 T +(cdevTranObj * xobj =) 184.67 489.33 T +(new cdevTranObj\050&system_, this, NULL, &callback\051;) 202.67 478.33 T +(xobj->disableDeleteCbk\050\051;) 184.67 467.33 T +(// ************************************************************) 184.67 445.33 T +(// * Enqueue the transaction object so that it may be processed) 184.67 434.33 T +(// * later. The result returned by the enqueueTransaction) 184.67 423.33 T +(// * function is returned by this function.) 184.67 412.33 T +(// ************************************************************) 184.67 401.33 T +(return emitError) 184.67 390.33 T +(\050svc->enqueueTransaction\050xobj, in\051, \322sendCallback\323\051;) 202.67 379.33 T +(}) 184.67 368.33 T +(// ****************************************************************) 166.67 346.33 T +(// * demoRequestObject::send :) 166.67 335.33 T +(// *) 166.67 324.33 T +-0.09 (The send interface is used for synchronous I/O with the service.) 188.27 324.33 P +(// *) 166.67 313.33 T +(Returns CDEV_SUCCESS on success or CDEV_ERROR on error.) 188.27 313.33 T +(// *) 166.67 302.33 T +(Note:) 188.27 302.33 T +-0.57 (Do not delete the transaction object, it will be deleted by) 215.27 302.33 P +(// * the processTransaction method in the service.) 166.67 291.33 T +(// ****************************************************************) 166.67 280.33 T +(int demoRequestObject::send \050 cdevData * in, cdevData * out \051) 166.67 269.33 T +({) 184.67 258.33 T +(int result = CDEV_SUCCESS;) 184.67 247.33 T +(cdevTranObj * xobj;) 184.67 236.33 T +(// *************************************************************) 184.67 214.33 T +(// * Get a pointer to the demoService to handle this request) 184.67 203.33 T +(// *************************************************************) 184.67 192.33 T +(demoService * svc = \050demoService *\051service_;) 184.67 181.33 T +(// *************************************************************) 184.67 159.33 T +(// * Construct a group object that can be used to pend for the) 184.67 148.33 T +(// * completion of the send event.) 184.67 137.33 T +(// *************************************************************) 184.67 126.33 T +(cdevGroup group\050DEFAULT_BLOCK_SIZE, system\050\051\051;) 184.67 115.33 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "50" 58 +%%Page: "51" 59 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 397.17 739 T +(vice: A Sample cde) 443.96 739 T +(v Ser) 520.72 739 T +(vice) 542 739 T +0 10 Q +(51) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 11: demoRequestObject.cc: \050contin) 180 714 T +(ued\051) 350.98 714 T +180 81 558 720 C +180 84 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.21 86.33 559.79 702.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +180.25 90.45 554.2 708 R +7 X +V +0 X +N +184.67 93.5 550.95 704.33 R +7 X +V +5 9 Q +0 X +(// *************************************************************) 202.67 698.33 T +(// * Start the group prior to creating the transaction object.) 202.67 687.33 T +(// *************************************************************) 202.67 676.33 T +(group.start\050\051;) 202.67 665.33 T +(// *************************************************************) 202.67 643.33 T +(// * Construct a cdev transaction object to track this) 202.67 632.33 T +(// * transaction. Note that the callback object that exists) 202.67 621.33 T +(// * within the service is specified as the callback object for) 202.67 610.33 T +(// * this transaction.) 202.67 599.33 T +(// *************************************************************) 202.67 588.33 T +(xobj = new cdevTranObj\050&system_, this, out, &svc->callback\051;) 202.67 577.33 T +(xobj->disableDeleteCbk\050\051;) 202.67 566.33 T +(// *************************************************************) 202.67 544.33 T +-0.19 (// * End the group and prepare to pend for the completion of the) 202.67 533.33 P +(// * task.) 202.67 522.33 T +(// *************************************************************) 202.67 511.33 T +(group.end\050\051;) 202.67 500.33 T +(// *************************************************************) 202.67 478.33 T +(// * Enqueue the transaction object so that it may be processed) 202.67 467.33 T +(// * later.) 202.67 456.33 T +(// *************************************************************) 202.67 445.33 T +(if\050\050result=svc->enqueueTransaction\050xobj, in\051\051==CDEV_SUCCESS\051) 202.67 434.33 T +({) 220.67 423.33 T +(// *********************************************************) 220.67 412.33 T +(// * Pend for a period of not more than 5 seconds, or until) 220.67 401.33 T +(// * the message has been completed.) 220.67 390.33 T +(// *********************************************************) 220.67 379.33 T +(result = group.pend\0505.0\051;) 220.67 368.33 T +(}) 220.67 357.33 T +(// *************************************************************) 202.67 335.33 T +(// * Use the reportError function to report an error if one) 202.67 324.33 T +(// * occurred.) 202.67 313.33 T +(// *************************************************************) 202.67 302.33 T +(return emitError\050result, \322send\323\051;) 202.67 291.33 T +(}) 202.67 280.33 T +(// ****************************************************************) 184.67 258.33 T +(// * demoRequestObject::emitError :) 184.67 247.33 T +(// * This method is used to emit a descriptive error if a failure) 184.67 236.33 T +(// * occurs while transmitting or receiving a message.) 184.67 225.33 T +(// ****************************************************************) 184.67 214.33 T +(int demoRequestObject::emitError \050 int result, char * function \051) 184.67 203.33 T +({) 202.67 192.33 T +(switch\050result\051) 202.67 181.33 T +({) 220.67 170.33 T +(case CDEV_SUCCESS:) 220.67 159.33 T +(system\050\051.reportError\050CDEV_SEVERITY_INFO, service\050\051.name\050\051,) 220.67 148.33 T +(*this, \322%s operation successful\134n\323, function\051;) 238.67 137.33 T +(break;) 220.67 126.33 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "51" 59 +%%Page: "52" 60 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 54 739 T +(vice: A Sample cde) 100.79 739 T +(v Ser) 177.55 739 T +(vice) 198.83 739 T +0 10 Q +(52) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(Figure 11: demoRequestObject.cc: \050contin) 162 714 T +(ued\051) 332.98 714 T +162 81 540 720 C +162 83 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.21 85.33 541.79 701.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +162.25 89.45 536.2 707 R +7 X +V +0 X +N +166.67 92.5 532.95 703.33 R +7 X +V +5 9 Q +0 X +(case CDEV_INVALIDOBJ:) 202.67 697.33 T +(system\050\051.reportError\050CDEV_SEVERITY_ERROR, service\050\051.name\050\051,) 202.67 686.33 T +(*this, \322Invalid object detecting in %s operation\134n\323,) 220.67 675.33 T +(function\051;) 220.67 664.33 T +(break;) 202.67 653.33 T +(case CDEV_INVALIDARG:) 202.67 631.33 T +(system\050\051.reportError\050CDEV_SEVERITY_ERROR, service\050\051.name\050\051,) 202.67 620.33 T +(*this,) 220.67 609.33 T +(\322Invalid argument for \134\323%s\134\323 message in %s operation\134n\323,) 220.67 598.33 T +(message\050\051, function\051;) 220.67 587.33 T +(break;) 202.67 576.33 T +(case CDEV_INVALIDSVC:) 202.67 554.33 T +(system\050\051.reportError\050CDEV_SEVERITY_SEVERE, service\050\051.name\050\051,) 202.67 543.33 T +(*this, \322Wrong service loaded during dynamic loading\134n\323\051;) 220.67 532.33 T +(break;) 202.67 521.33 T +(case CDEV_NOTCONNECTED:) 202.67 499.33 T +(system\050\051.reportError\050CDEV_SEVERITY_ERROR, service\050\051.name\050\051,) 202.67 488.33 T +(*this, \322Network connection error in %s operation\134n\323,) 220.67 477.33 T +(function\051;) 220.67 466.33 T +(break;) 202.67 455.33 T +(case CDEV_IOFAILED:) 202.67 433.33 T +(system\050\051.reportError\050CDEV_SEVERITY_ERROR, service\050\051.name\050\051,) 202.67 422.33 T +(*this, \322I/O failure during %s operation\134n\323, function\051;) 220.67 411.33 T +(break;) 202.67 400.33 T +(case CDEV_CONFLICT:) 202.67 378.33 T +(system\050\051.reportError\050CDEV_SEVERITY_WARN, service\050\051.name\050\051,) 202.67 367.33 T +(*this,) 202.67 356.33 T +(\322Data type provided is inconsistent with \134\323%s\134\323 message\134n\323,) 202.67 345.33 T +(message\050\051\051;) 202.67 334.33 T +(break;) 202.67 323.33 T +(case CDEV_NOTFOUND:) 202.67 301.33 T +(system\050\051.reportError\050CDEV_SEVERITY_WARN, service\050\051.name\050\051,) 202.67 290.33 T +(*this,) 202.67 279.33 T +(\322Tagged data item missing from cdevData in %s operation\134n\323,) 202.67 268.33 T +(function\051;) 202.67 257.33 T +(break;) 202.67 246.33 T +(case CDEV_TIMEOUT:) 202.67 224.33 T +(system\050\051.reportError\050CDEV_SEVERITY_WARN, service\050\051.name\050\051,) 202.67 213.33 T +(*this,) 220.67 202.33 T +(\322Timed-out while waiting for response in %s operation\134n\323,) 220.67 191.33 T +(function\051;) 220.67 180.33 T +(break;) 202.67 169.33 T +(case CDEV_CONVERT:) 202.67 147.33 T +(system\050\051.reportError\050CDEV_SEVERITY_WARN, service\050\051.name\050\051,) 202.67 136.33 T +(*this, \322Data conversion error in %s operation\134n\323,) 220.67 125.33 T +(function\051;) 220.67 114.33 T +(break;) 202.67 103.33 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "52" 60 +%%Page: "53" 61 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 397.17 739 T +(vice: A Sample cde) 443.96 739 T +(v Ser) 520.72 739 T +(vice) 542 739 T +0 10 Q +(53) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 9 Q +(Figure 11: demoRequestObject.cc: \050contin) 180 714 T +(ued\051) 350.98 714 T +2 10 Q +(Make\336le f) 72 488.33 T +(or the) 117.37 488.33 T +(demoSer) 72 476.33 T +(vice) 114.89 476.33 T +0 F +1.02 (The f) 180 488.33 P +1.02 (ollo) 203.51 488.33 P +1.02 (wing) 218.92 488.33 P +3 F +1.02 (Mak) 243.28 488.33 P +1.02 (e\336le) 261.97 488.33 P +0 F +1.02 ( can be used to b) 280.31 488.33 P +1.02 (uild the shared object f) 361.93 488.33 P +1.02 (or the) 466.33 488.33 P +3 F +1.02 (demoSer) 496.72 488.33 P +1.02 (vice) 537.59 488.33 P +0 F +1.02 (.) 555.22 488.33 P +1.01 (This mak) 180 476.33 P +1.01 (e\336le uses the) 221.37 476.33 P +3 F +1.01 (Mak) 286.1 476.33 P +1.01 (e\336le) 304.79 476.33 P +1.01 (.common) 322.98 476.33 P +0 F +1.01 (of the cde) 367.89 476.33 P +1.01 (v system f) 413.54 476.33 P +1.01 (or its base) 460.27 476.33 P +1.01 (. It has the) 508.27 476.33 P +0.81 (additional requirement that the) 180 464.33 P +3 F +0.81 (CDEVSHOBJ) 321.11 464.33 P +0 F +0.81 ( en) 382.23 464.33 P +0.81 (vironment v) 396.74 464.33 P +0.81 (ar) 448.99 464.33 P +0.81 (iab) 458.03 464.33 P +0.81 (le m) 471.17 464.33 P +0.81 (ust be de\336ned.) 490.77 464.33 P +(This v) 180 452.33 T +(ar) 206.42 452.33 T +(iab) 215.46 452.33 T +(le de\336nes where the shared objects used b) 228.6 452.33 T +(y cde) 418.5 452.33 T +(v should be stored.) 442.1 452.33 T +3 9 Q +(Figure 12: Mak) 180 419 T +(e\336le f) 242.34 419 T +(or the demoSer) 263.58 419 T +(vice) 325.88 419 T +180 514 558 720 C +180 531 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.71 533.33 559.29 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +179.75 538.29 553.7 705 R +7 X +V +0 X +N +184.17 543.84 550.45 701.33 R +7 X +V +5 9 Q +0 X +(case CDEV_DISCONNECTED:) 220.17 695.33 T +(system\050\051.reportError\050CDEV_SEVERITY_WARN, service\050\051.name\050\051,) 220.17 684.33 T +(*this, \322Disconnected from service during %s operation\134n\323,) 238.17 673.33 T +(function\051;) 238.17 662.33 T +(break;) 220.17 651.33 T +(case CDEV_RECONNECTED:) 220.17 629.33 T +(system\050\051.reportError\050CDEV_SEVERITY_INFO, service\050\051.name\050\051,) 220.17 618.33 T +(*this, \322Reconnected to service during %s operation\134n\323,) 238.17 607.33 T +(function\051;) 238.17 596.33 T +(break;) 220.17 585.33 T +(}) 220.17 574.33 T +(return result;) 202.17 563.33 T +(}) 202.17 552.33 T +180 514 558 720 C +0 0 612 792 C +180 81 558 495 C +180 96.84 558 416 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.71 99.17 559.29 404.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +179.75 104.12 553.7 410 R +7 X +V +0 X +N +184.17 107.17 550.45 406.33 R +7 X +V +5 9 Q +0 X +(###################################################################) 184.17 400.33 T +(# Makefile for demoService shared object) 184.17 389.33 T +(###################################################################) 184.17 378.33 T +(CDEVROOT = $\050CDEV\051) 184.17 367.33 T +(SHOBJ=YES) 184.17 356.33 T +(include $\050CDEVROOT\051/src/Makefile.common) 184.17 345.33 T +(LIBS =) 184.17 323.33 T +(-L$\050LIBDIR\051 -lcdev -ly -ll -lm) 221.97 323.33 T +(OBJS = demoService.o demoRequestObject.o demoDevice.o) 184.17 312.33 T +(CLASS_INCLUDES = -I.) 184.17 301.33 T +(CXXEXTRA = -Aa +a1 -z +z -pta -g $\050CLASS_INCLUDES\051) 184.17 290.33 T +(all: demoService.so) 184.17 268.33 T +(demoService.so : $\050OBJS\051) 184.17 246.33 T +(@echo Creating demoService shared object) 202.17 235.33 T +(@rm -f demoService.so) 202.17 224.33 T +(CC -b -o demoService.so $\050OBJS\051) 202.17 213.33 T +(@cp demoService.so $\050CDEVSHOBJ\051/demoService.so) 202.17 202.33 T +(@echo done) 202.17 191.33 T +(clean:) 184.17 169.33 T +(@echo Cleaning up source directory) 202.17 158.33 T +(@rm -rf *.so *.a *~ *.o core ptrepository TC.Cache) 202.17 147.33 T +(@echo done) 202.17 136.33 T +180 81 558 495 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "53" 61 +%%Page: "54" 62 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. demoSer) 54 739 T +(vice: A Sample cde) 100.79 739 T +(v Ser) 177.55 739 T +(vice) 198.83 739 T +0 10 Q +(54) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(De) 54 713.33 T +(vice De\336nition) 66.63 713.33 T +(File f) 54 701.33 T +(or the) 77.14 701.33 T +(demoSer) 54 689.33 T +(vice) 96.89 689.33 T +0 F +0.71 (The f) 162 713.33 P +0.71 (ollo) 185.2 713.33 P +0.71 (wing) 200.61 713.33 P +3 F +0.71 (De) 224.65 713.33 P +0.71 (vice De\336nition Language \050DDL\051) 237.13 713.33 P +0 F +0.71 ( \336le de\336nes the v) 378.2 713.33 P +0.71 (erbs and attr) 455.82 713.33 P +0.71 (ib) 513.52 713.33 P +0.71 (utes) 521.1 713.33 P +0.05 (suppor) 162 701.33 P +0.05 (ted b) 192.97 701.33 P +0.05 (y the demoDe) 215.05 701.33 P +0.05 (vice) 277.09 701.33 P +0.05 (. It them de\336nes the instances of demo de) 294.72 701.33 P +0.05 (vices that are) 480.44 701.33 P +3.43 (a) 162 689.33 P +3.43 (v) 167.36 689.33 P +3.43 (ailab) 172.11 689.33 P +3.43 (le f) 193.03 689.33 P +3.43 (or use) 209.5 689.33 P +3.43 (. This DDL \336le ma) 240.57 689.33 P +3.43 (y be used in conjunction with the) 333.44 689.33 P +3 F +3.43 (cde) 504.74 689.33 P +3.43 (vUtil) 520.56 689.33 P +0 F +(application to comm) 162 677.33 T +(unicate with the) 250.82 677.33 T +3 F +(demoDe) 323.08 677.33 T +(vice) 360.57 677.33 T +0 F +( control system.) 378.35 677.33 T +3 9 Q +(Figure 13: De) 162 644 T +(vice De\336nition Language \336le f) 218.75 644 T +(or the demoSer) 336.04 644 T +(vice) 398.34 644 T +162 81 540 720 C +162 257.67 540 641 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.71 260 541.29 629.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +161.75 264.12 535.7 635 R +7 X +V +0 X +N +166.17 268.01 532.45 631.33 R +7 X +V +5 9 Q +0 X +(/*) 166.17 625.33 T +( * Service definitions) 166.17 614.33 T +( */) 166.17 603.33 T +(service demo {) 166.17 592.33 T +(tags {XYZ}) 184.17 581.33 T +(}) 184.17 570.33 T +(/*) 166.17 548.33 T +( * Class definitions) 166.17 537.33 T +( */) 166.17 526.33 T +(class demoDevice {) 166.17 515.33 T +(verbs { get, set}) 184.17 504.33 T +(attributes) 184.17 493.33 T +({) 202.17 482.33 T +(VAL demo {};) 202.17 471.33 T +(BDL demo {};) 202.17 460.33 T +(}) 202.17 449.33 T +(}) 184.17 438.33 T +(/*) 166.17 416.33 T +( * Device instanciations) 166.17 405.33 T +( */) 166.17 394.33 T +(demoDevice :) 166.17 383.33 T +(DEVICE0) 184.17 372.33 T +(DEVICE1) 184.17 361.33 T +(DEVICE2) 184.17 350.33 T +(DEVICE3) 184.17 339.33 T +(DEVICE4;) 184.17 328.33 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "54" 62 +%%Trailer +%%BoundingBox: 0 0 612 792 +%%PageOrder: Ascend +%%Pages: 62 +%%DocumentFonts: Helvetica +%%+ Times-BoldItalic +%%+ Helvetica-Bold +%%+ Helvetica-Oblique +%%+ Helvetica-BoldOblique +%%+ Courier-Bold +%%+ Courier-BoldOblique +%%EOF diff --git a/doc/ps/cdevTutorial.ps b/doc/ps/cdevTutorial.ps new file mode 100755 index 0000000..f1f6d63 --- /dev/null +++ b/doc/ps/cdevTutorial.ps @@ -0,0 +1,21342 @@ +%!PS-Adobe-3.0 +%%BoundingBox: (atend) +%%Pages: (atend) +%%PageOrder: (atend) +%%DocumentFonts: (atend) +%%Creator: Frame 5.0 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +% +% Frame ps_prolog 5.0, for use with Frame 5.0 products +% This ps_prolog file is Copyright (c) 1986-1995 Frame Technology +% Corporation. All rights reserved. This ps_prolog file may be +% freely copied and distributed in conjunction with documents created +% using FrameMaker, FrameMaker/SGML and FrameViewer as long as this +% copyright notice is preserved. +% +% FrameMaker users specify the proper paper size for each print job in the +% "Print" dialog's "Printer Paper Size" "Width" and "Height~ fields. If the +% printer that the PS file is sent to does not support the requested paper +% size, or if there is no paper tray of the proper size currently installed, +% then the job will not be printed. The following flag, if set to true, will +% cause the job to print on the default paper in such cases. +/FMAllowPaperSizeMismatch false def +% +% Frame products normally print colors as their true color on a color printer +% or as shades of gray, based on luminance, on a black-and white printer. The +% following flag, if set to true, forces all non-white colors to print as pure +% black. This has no effect on bitmap images. +/FMPrintAllColorsAsBlack false def +% +% Frame products can either set their own line screens or use a printer's +% default settings. Three flags below control this separately for no +% separations, spot separations and process separations. If a flag +% is true, then the default printer settings will not be changed. If it is +% false, Frame products will use their own settings from a table based on +% the printer's resolution. +/FMUseDefaultNoSeparationScreen true def +/FMUseDefaultSpotSeparationScreen true def +/FMUseDefaultProcessSeparationScreen false def +% +% For any given PostScript printer resolution, Frame products have two sets of +% screen angles and frequencies for printing process separations, which are +% recomended by Adobe. The following variable chooses the higher frequencies +% when set to true or the lower frequencies when set to false. This is only +% effective if the appropriate FMUseDefault...SeparationScreen flag is false. +/FMUseHighFrequencyScreens true def +% +% The following is a set of predefined optimal frequencies and angles for various +% common dpi settings. This is taken from "Advances in Color Separation Using +% PostScript Software Technology," from Adobe Systems (3/13/89 P.N. LPS 0043) +% and corrolated with information which is in various PPD (4.0) files. +% +% The "dpiranges" figure is the minimum dots per inch device resolution which +% can support this setting. The "low" and "high" values are controlled by the +% setting of the FMUseHighFrequencyScreens flag above. The "TDot" flags control +% the use of the "Yellow Triple Dot" feature whereby the frequency id divided by +% three, but the dot function is "trippled" giving a block of 3x3 dots per cell. +% +% PatFreq is a compromise pattern frequency for ps Level 2 printers which is close +% to the ideal WYSIWYG pattern frequency of 9 repetitions/inch but does not beat +% (too badly) against the screen frequencies of any separations for that DPI. +/dpiranges [ 2540 2400 1693 1270 1200 635 600 0 ] def +/CMLowFreqs [ 100.402 94.8683 89.2289 100.402 94.8683 66.9349 63.2456 47.4342 ] def +/YLowFreqs [ 95.25 90.0 84.65 95.25 90.0 70.5556 66.6667 50.0 ] def +/KLowFreqs [ 89.8026 84.8528 79.8088 89.8026 84.8528 74.8355 70.7107 53.033 ] def +/CLowAngles [ 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 ] def +/MLowAngles [ 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 ] def +/YLowTDot [ true true false true true false false false ] def +/CMHighFreqs [ 133.87 126.491 133.843 108.503 102.523 100.402 94.8683 63.2456 ] def +/YHighFreqs [ 127.0 120.0 126.975 115.455 109.091 95.25 90.0 60.0 ] def +/KHighFreqs [ 119.737 113.137 119.713 128.289 121.218 89.8026 84.8528 63.6395 ] def +/CHighAngles [ 71.5651 71.5651 71.5651 70.0169 70.0169 71.5651 71.5651 71.5651 ] def +/MHighAngles [ 18.4349 18.4349 18.4349 19.9831 19.9831 18.4349 18.4349 18.4349 ] def +/YHighTDot [ false false true false false true true false ] def +/PatFreq [ 10.5833 10.0 9.4055 10.5833 10.0 10.5833 10.0 9.375 ] def +% +% PostScript Level 2 printers contain an "Accurate Screens" feature which can +% improve process separation rendering at the expense of compute time. This +% flag is ignored by PostScript Level 1 printers. +/FMUseAcccurateScreens true def +% +% The following PostScript procedure defines the spot function that Frame +% products will use for process separations. You may un-comment-out one of +% the alternative functions below, or use your own. +% +% Dot function +/FMSpotFunction {abs exch abs 2 copy add 1 gt + {1 sub dup mul exch 1 sub dup mul add 1 sub } + {dup mul exch dup mul add 1 exch sub }ifelse } def +% +% Line function +% /FMSpotFunction { pop } def +% +% Elipse function +% /FMSpotFunction { dup 5 mul 8 div mul exch dup mul exch add +% sqrt 1 exch sub } def +% +% +/FMversion (5.0) def +/fMLevel1 /languagelevel where {pop languagelevel} {1} ifelse 2 lt def +/FMPColor + fMLevel1 { + false + /colorimage where {pop pop true} if + } { + true + } ifelse +def +/FrameDict 400 dict def +systemdict /errordict known not {/errordict 10 dict def + errordict /rangecheck {stop} put} if +% The readline in PS 23.0 doesn't recognize cr's as nl's on AppleTalk +FrameDict /tmprangecheck errordict /rangecheck get put +errordict /rangecheck {FrameDict /bug true put} put +FrameDict /bug false put +mark +% Some PS machines read past the CR, so keep the following 3 lines together! +currentfile 5 string readline +00 +0000000000 +cleartomark +errordict /rangecheck FrameDict /tmprangecheck get put +FrameDict /bug get { + /readline { + /gstring exch def + /gfile exch def + /gindex 0 def + { + gfile read pop + dup 10 eq {exit} if + dup 13 eq {exit} if + gstring exch gindex exch put + /gindex gindex 1 add def + } loop + pop + gstring 0 gindex getinterval true + } bind def + } if +/FMshowpage /showpage load def +/FMquit /quit load def +/FMFAILURE { + dup = flush + FMshowpage + /Helvetica findfont 12 scalefont setfont + 72 200 moveto show + 72 220 moveto show + FMshowpage + FMquit + } def +/FMVERSION { + FMversion ne { + (Frame product version does not match ps_prolog! Check installation;) + (also check ~/fminit and ./fminit for old versions) FMFAILURE + } if + } def +/FMBADEPSF { + (Adobe's PostScript Language Reference Manual, 2nd Edition, section H.2.4) + (says your EPS file is not valid, as it calls X ) + dup dup (X) search pop exch pop exch pop length + 5 -1 roll + putinterval + FMFAILURE + } def +/fmConcatProcs + { + /proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def + newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx +}def +FrameDict begin [ + /ALDsave + /FMdicttop + /FMoptop + /FMpointsize + /FMsaveobject + /b + /bitmapsave + /blut + /bpside + /bs + /bstring + /bwidth + /c + /cf + /cs + /cynu + /depth + /edown + /fh + /fillvals + /fw + /fx + /fy + /g + /gfile + /gindex + /grnt + /gryt + /gstring + /height + /hh + /i + /im + /indx + /is + /k + /kk + /landscape + /lb + /len + /llx + /lly + /m + /magu + /manualfeed + /n + /offbits + /onbits + /organgle + /orgbangle + /orgbfreq + /orgbproc + /orgbxfer + /orgfreq + /orggangle + /orggfreq + /orggproc + /orggxfer + /orgmatrix + /orgproc + /orgrangle + /orgrfreq + /orgrproc + /orgrxfer + /orgxfer + /pagesave + /paperheight + /papersizedict + /paperwidth + /pos + /pwid + /r + /rad + /redt + /sl + /str + /tran + /u + /urx + /ury + /val + /width + /width + /ws + /ww + /x + /x1 + /x2 + /xindex + /xpoint + /xscale + /xx + /y + /y1 + /y2 + /yelu + /yindex + /ypoint + /yscale + /yy +] { 0 def } forall +/FmBD {bind def} bind def +systemdict /pdfmark known { + /fMAcrobat true def + + /FmPD /pdfmark load def + + + /FmPT /show load def + + + currentdistillerparams /CoreDistVersion get 2000 ge { + + + /FmPD2 /pdfmark load def + + + + + + /FmPA { mark exch /Dest exch 5 3 roll + /View [ /XYZ null 6 -2 roll FmDC exch pop null] /DEST FmPD + }FmBD + } { + + /FmPD2 /cleartomark load def + /FmPA {pop pop pop}FmBD + } ifelse +} { + + /fMAcrobat false def + /FmPD /cleartomark load def + /FmPD2 /cleartomark load def + /FmPT /pop load def + /FmPA {pop pop pop}FmBD +} ifelse +/FmDC { + transform fMDefaultMatrix itransform cvi exch cvi exch +}FmBD +/FmBx { + dup 3 index lt {3 1 roll exch} if + 1 index 4 index lt {4 -1 roll 3 1 roll exch 4 1 roll} if +}FmBD +/FMnone 0 def +/FMcyan 1 def +/FMmagenta 2 def +/FMyellow 3 def +/FMblack 4 def +/FMcustom 5 def +/fMNegative false def +/FrameSepIs FMnone def +/FrameSepBlack 0 def +/FrameSepYellow 0 def +/FrameSepMagenta 0 def +/FrameSepCyan 0 def +/FrameSepRed 1 def +/FrameSepGreen 1 def +/FrameSepBlue 1 def +/FrameCurGray 1 def +/FrameCurPat null def +/FrameCurColors [ 0 0 0 1 0 0 0 ] def +/FrameColorEpsilon .001 def +/eqepsilon { + sub dup 0 lt {neg} if + FrameColorEpsilon le +} bind def +/FrameCmpColorsCMYK { + 2 copy 0 get exch 0 get eqepsilon { + 2 copy 1 get exch 1 get eqepsilon { + 2 copy 2 get exch 2 get eqepsilon { + 3 get exch 3 get eqepsilon + } {pop pop false} ifelse + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/FrameCmpColorsRGB { + 2 copy 4 get exch 0 get eqepsilon { + 2 copy 5 get exch 1 get eqepsilon { + 6 get exch 2 get eqepsilon + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/RGBtoCMYK { + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 3 copy + 2 copy + le { pop } { exch pop } ifelse + 2 copy + le { pop } { exch pop } ifelse + dup dup dup + 6 1 roll + 4 1 roll + 7 1 roll + sub + 6 1 roll + sub + 5 1 roll + sub + 4 1 roll +} bind def +/CMYKtoRGB { + dup dup 4 -1 roll add + 5 1 roll 3 -1 roll add + 4 1 roll add + 1 exch sub dup 0 lt {pop 0} if 3 1 roll + 1 exch sub dup 0 lt {pop 0} if exch + 1 exch sub dup 0 lt {pop 0} if exch +} bind def +/FrameSepInit { + 1.0 RealSetgray +} bind def +/FrameSetSepColor { + /FrameSepBlue exch def + /FrameSepGreen exch def + /FrameSepRed exch def + /FrameSepBlack exch def + /FrameSepYellow exch def + /FrameSepMagenta exch def + /FrameSepCyan exch def + /FrameSepIs FMcustom def + setCurrentScreen +} bind def +/FrameSetCyan { + /FrameSepBlue 1.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 1.0 def + /FrameSepIs FMcyan def + setCurrentScreen +} bind def + +/FrameSetMagenta { + /FrameSepBlue 1.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 1.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMmagenta def + setCurrentScreen +} bind def + +/FrameSetYellow { + /FrameSepBlue 0.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 1.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMyellow def + setCurrentScreen +} bind def + +/FrameSetBlack { + /FrameSepBlue 0.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 1.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMblack def + setCurrentScreen +} bind def + +/FrameNoSep { + /FrameSepIs FMnone def + setCurrentScreen +} bind def +/FrameSetSepColors { + FrameDict begin + [ exch 1 add 1 roll ] + /FrameSepColors + exch def end + } bind def +/FrameColorInSepListCMYK { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsCMYK + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/FrameColorInSepListRGB { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsRGB + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/RealSetgray /setgray load def +/RealSetrgbcolor /setrgbcolor load def +/RealSethsbcolor /sethsbcolor load def +end +/setgray { + FrameDict begin + FrameSepIs FMnone eq + { RealSetgray } + { + FrameSepIs FMblack eq + { RealSetgray } + { FrameSepIs FMcustom eq + FrameSepRed 0 eq and + FrameSepGreen 0 eq and + FrameSepBlue 0 eq and { + RealSetgray + } { + 1 RealSetgray pop + } ifelse + } ifelse + } ifelse + end +} bind def +/setrgbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetrgbcolor } + { + 3 copy [ 4 1 roll ] + FrameColorInSepListRGB + { + FrameSepBlue eq exch + FrameSepGreen eq and exch + FrameSepRed eq and + { 0 } { 1 } ifelse + } + { + FMPColor { + RealSetrgbcolor + currentcmykcolor + } { + RGBtoCMYK + } ifelse + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end +} bind def +/sethsbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSethsbcolor } + { + RealSethsbcolor + currentrgbcolor + setrgbcolor + } + ifelse + end +} bind def +FrameDict begin +/setcmykcolor where { + pop /RealSetcmykcolor /setcmykcolor load def +} { + /RealSetcmykcolor { + 4 1 roll + 3 { 3 index add 0 max 1 min 1 exch sub 3 1 roll} repeat + RealSetrgbcolor pop + } bind def +} ifelse +userdict /setcmykcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetcmykcolor } + { + 4 copy [ 5 1 roll ] + FrameColorInSepListCMYK + { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + { 0 } { 1 } ifelse + } + { + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end + } bind put +fMLevel1 { + + + + /patScreenDict 7 dict dup begin + <0f1e3c78f0e1c387> [ 45 { pop } {exch pop} .5 2 sqrt] FmBD + <0f87c3e1f0783c1e> [ 135 { pop } {exch pop} .5 2 sqrt] FmBD + [ 0 { pop } dup .5 2 ] FmBD + [ 90 { pop } dup .5 2 ] FmBD + <8142241818244281> [ 45 { 2 copy lt {exch} if pop} dup .75 2 sqrt] FmBD + <03060c183060c081> [ 45 { pop } {exch pop} .875 2 sqrt] FmBD + <8040201008040201> [ 135 { pop } {exch pop} .875 2 sqrt] FmBD + end def +} { + + /patProcDict 5 dict dup begin + <0f1e3c78f0e1c387> { 3 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <0f87c3e1f0783c1e> { 3 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + <8142241818244281> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -1 -1 moveto 9 9 lineto stroke } bind def + <03060c183060c081> { 1 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <8040201008040201> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + end def + /patDict 15 dict dup begin + /PatternType 1 def + /PaintType 2 def + /TilingType 3 def + /BBox [ 0 0 8 8 ] def + /XStep 8 def + /YStep 8 def + /PaintProc { + begin + patProcDict bstring known { + patProcDict bstring get exec + } { + 8 8 true [1 0 0 -1 0 8] bstring imagemask + } ifelse + end + } bind def + end def +} ifelse +/combineColor { + FrameSepIs FMnone eq + { + graymode fMLevel1 or not { + + [/Pattern [/DeviceCMYK]] setcolorspace + FrameCurColors 0 4 getinterval aload pop FrameCurPat setcolor + } { + FrameCurColors 3 get 1.0 ge { + FrameCurGray RealSetgray + } { + fMAcrobat not FMPColor graymode and and { + 0 1 3 { + FrameCurColors exch get + 1 FrameCurGray sub mul + } for + RealSetcmykcolor + } { + 4 1 6 { + FrameCurColors exch get + graymode { + 1 exch sub 1 FrameCurGray sub mul 1 exch sub + } { + 1.0 lt {FrameCurGray} {1} ifelse + } ifelse + } for + RealSetrgbcolor + } ifelse + } ifelse + } ifelse + } { + FrameCurColors 0 4 getinterval aload + FrameColorInSepListCMYK { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + FrameSepIs FMcustom eq and + { FrameCurGray } { 1 } ifelse + } { + FrameSepIs FMblack eq + {FrameCurGray 1.0 exch sub mul 1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop FrameCurGray 1.0 exch sub mul 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + graymode fMLevel1 or not { + + [/Pattern [/DeviceGray]] setcolorspace + FrameCurPat setcolor + } { + graymode not fMLevel1 and { + + dup 1 lt {pop FrameCurGray} if + } if + RealSetgray + } ifelse + } ifelse +} bind def +/savematrix { + orgmatrix currentmatrix pop + } bind def +/restorematrix { + orgmatrix setmatrix + } bind def +/fMDefaultMatrix matrix defaultmatrix def +/fMatrix2 matrix def +/dpi 72 0 fMDefaultMatrix dtransform + dup mul exch dup mul add sqrt def + +/freq dpi dup 72 div round dup 0 eq {pop 1} if 8 mul div def +/sangle 1 0 fMDefaultMatrix dtransform exch atan def + sangle fMatrix2 rotate + fMDefaultMatrix fMatrix2 concatmatrix + dup 0 get /sflipx exch def + 3 get /sflipy exch def +/screenIndex { + 0 1 dpiranges length 1 sub { dup dpiranges exch get 1 sub dpi le {exit} {pop} ifelse } for +} bind def +/getCyanScreen { + FMUseHighFrequencyScreens { CHighAngles CMHighFreqs} {CLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getMagentaScreen { + FMUseHighFrequencyScreens { MHighAngles CMHighFreqs } {MLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getYellowScreen { + FMUseHighFrequencyScreens { YHighTDot YHighFreqs} { YLowTDot YLowFreqs } ifelse + screenIndex dup 3 1 roll get 3 1 roll get { 3 div + {2 { 1 add 2 div 3 mul dup floor sub 2 mul 1 sub exch} repeat + FMSpotFunction } } {/FMSpotFunction load } ifelse + 0.0 exch +} bind def +/getBlackScreen { + FMUseHighFrequencyScreens { KHighFreqs } { KLowFreqs } ifelse + screenIndex get 45.0 /FMSpotFunction load +} bind def +/getSpotScreen { + getBlackScreen +} bind def +/getCompositeScreen { + getBlackScreen +} bind def +/FMSetScreen + fMLevel1 { /setscreen load + }{ { + 8 dict begin + /HalftoneType 1 def + /SpotFunction exch def + /Angle exch def + /Frequency exch def + /AccurateScreens FMUseAcccurateScreens def + currentdict end sethalftone + } bind } ifelse +def +/setDefaultScreen { + FMPColor { + orgrxfer cvx orggxfer cvx orgbxfer cvx orgxfer cvx setcolortransfer + } + { + orgxfer cvx settransfer + } ifelse + orgfreq organgle orgproc cvx setscreen +} bind def +/setCurrentScreen { + FrameSepIs FMnone eq { + FMUseDefaultNoSeparationScreen { + setDefaultScreen + } { + getCompositeScreen FMSetScreen + } ifelse + } { + FrameSepIs FMcustom eq { + FMUseDefaultSpotSeparationScreen { + setDefaultScreen + } { + getSpotScreen FMSetScreen + } ifelse + } { + FMUseDefaultProcessSeparationScreen { + setDefaultScreen + } { + FrameSepIs FMcyan eq { + getCyanScreen FMSetScreen + } { + FrameSepIs FMmagenta eq { + getMagentaScreen FMSetScreen + } { + FrameSepIs FMyellow eq { + getYellowScreen FMSetScreen + } { + getBlackScreen FMSetScreen + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse +} bind def +end + +/FMDOCUMENT { + array /FMfonts exch def + /#copies exch def + FrameDict begin + 0 ne /manualfeed exch def + /paperheight exch def + /paperwidth exch def + 0 ne /fMNegative exch def + 0 ne /edown exch def + /yscale exch def + /xscale exch def + fMLevel1 { + manualfeed {setmanualfeed} if + /FMdicttop countdictstack 1 add def + /FMoptop count def + setpapername + manualfeed {true} {papersize} ifelse + {manualpapersize} {false} ifelse + {desperatepapersize} {false} ifelse + {papersizefailure} if + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + } + {2 dict + dup /PageSize [paperwidth paperheight] put + manualfeed {dup /ManualFeed manualfeed put} if + {setpagedevice} stopped {papersizefailure} if + } + ifelse + + FMPColor { + currentcolorscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + cvlit /orgbproc exch def + /orgbangle exch def + /orgbfreq exch def + cvlit /orggproc exch def + /orggangle exch def + /orggfreq exch def + cvlit /orgrproc exch def + /orgrangle exch def + /orgrfreq exch def + currentcolortransfer + fMNegative { + 1 1 4 { + pop { 1 exch sub } fmConcatProcs 4 1 roll + } for + 4 copy + setcolortransfer + } if + cvlit /orgxfer exch def + cvlit /orgbxfer exch def + cvlit /orggxfer exch def + cvlit /orgrxfer exch def + } { + currentscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + + currenttransfer + fMNegative { + { 1 exch sub } fmConcatProcs + dup settransfer + } if + cvlit /orgxfer exch def + } ifelse + end +} def +/FMBEGINPAGE { + FrameDict begin + /pagesave save def + 3.86 setmiterlimit + /landscape exch 0 ne def + landscape { + 90 rotate 0 exch dup /pwid exch def neg translate pop + }{ + pop /pwid exch def + } ifelse + edown { [-1 0 0 1 pwid 0] concat } if + 0 0 moveto paperwidth 0 lineto paperwidth paperheight lineto + 0 paperheight lineto 0 0 lineto 1 setgray fill + xscale yscale scale + /orgmatrix matrix def + gsave +} def +/FMENDPAGE { + grestore + pagesave restore + end + showpage + } def +/FMFONTDEFINE { + FrameDict begin + findfont + ReEncode + 1 index exch + definefont + FMfonts 3 1 roll + put + end + } def +/FMFILLS { + FrameDict begin dup + array /fillvals exch def + dict /patCache exch def + end + } def +/FMFILL { + FrameDict begin + fillvals 3 1 roll put + end + } def +/FMNORMALIZEGRAPHICS { + newpath + 1 setlinewidth + 0 setlinecap + 0 0 0 sethsbcolor + 0 setgray + } bind def +/FMBEGINEPSF { + end + /FMEPSF save def + /showpage {} def +% See Adobe's "PostScript Language Reference Manual, 2nd Edition", page 714. +% "...the following operators MUST NOT be used in an EPS file:" (emphasis ours) + /banddevice {(banddevice) FMBADEPSF} def + /clear {(clear) FMBADEPSF} def + /cleardictstack {(cleardictstack) FMBADEPSF} def + /copypage {(copypage) FMBADEPSF} def + /erasepage {(erasepage) FMBADEPSF} def + /exitserver {(exitserver) FMBADEPSF} def + /framedevice {(framedevice) FMBADEPSF} def + /grestoreall {(grestoreall) FMBADEPSF} def + /initclip {(initclip) FMBADEPSF} def + /initgraphics {(initgraphics) FMBADEPSF} def + /quit {(quit) FMBADEPSF} def + /renderbands {(renderbands) FMBADEPSF} def + /setglobal {(setglobal) FMBADEPSF} def + /setpagedevice {(setpagedevice) FMBADEPSF} def + /setshared {(setshared) FMBADEPSF} def + /startjob {(startjob) FMBADEPSF} def + /lettertray {(lettertray) FMBADEPSF} def + /letter {(letter) FMBADEPSF} def + /lettersmall {(lettersmall) FMBADEPSF} def + /11x17tray {(11x17tray) FMBADEPSF} def + /11x17 {(11x17) FMBADEPSF} def + /ledgertray {(ledgertray) FMBADEPSF} def + /ledger {(ledger) FMBADEPSF} def + /legaltray {(legaltray) FMBADEPSF} def + /legal {(legal) FMBADEPSF} def + /statementtray {(statementtray) FMBADEPSF} def + /statement {(statement) FMBADEPSF} def + /executivetray {(executivetray) FMBADEPSF} def + /executive {(executive) FMBADEPSF} def + /a3tray {(a3tray) FMBADEPSF} def + /a3 {(a3) FMBADEPSF} def + /a4tray {(a4tray) FMBADEPSF} def + /a4 {(a4) FMBADEPSF} def + /a4small {(a4small) FMBADEPSF} def + /b4tray {(b4tray) FMBADEPSF} def + /b4 {(b4) FMBADEPSF} def + /b5tray {(b5tray) FMBADEPSF} def + /b5 {(b5) FMBADEPSF} def + FMNORMALIZEGRAPHICS + [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall + fx fw 2 div add fy fh 2 div add translate + rotate + fw 2 div neg fh 2 div neg translate + fw urx llx sub div fh ury lly sub div scale + llx neg lly neg translate + /FMdicttop countdictstack 1 add def + /FMoptop count def + } bind def +/FMENDEPSF { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMEPSF restore + FrameDict begin + } bind def +FrameDict begin +/setmanualfeed { +%%BeginFeature *ManualFeed True + statusdict /manualfeed true put +%%EndFeature + } bind def +/max {2 copy lt {exch} if pop} bind def +/min {2 copy gt {exch} if pop} bind def +/inch {72 mul} def +/pagedimen { + paperheight sub abs 16 lt exch + paperwidth sub abs 16 lt and + {/papername exch def} {pop} ifelse + } bind def +/setpapername { + /papersizedict 14 dict def + papersizedict begin + /papername /unknown def + /Letter 8.5 inch 11.0 inch pagedimen + /LetterSmall 7.68 inch 10.16 inch pagedimen + /Tabloid 11.0 inch 17.0 inch pagedimen + /Ledger 17.0 inch 11.0 inch pagedimen + /Legal 8.5 inch 14.0 inch pagedimen + /Statement 5.5 inch 8.5 inch pagedimen + /Executive 7.5 inch 10.0 inch pagedimen + /A3 11.69 inch 16.5 inch pagedimen + /A4 8.26 inch 11.69 inch pagedimen + /A4Small 7.47 inch 10.85 inch pagedimen + /B4 10.125 inch 14.33 inch pagedimen + /B5 7.16 inch 10.125 inch pagedimen + end + } bind def +/papersize { + papersizedict begin + /Letter {lettertray letter} def + /LetterSmall {lettertray lettersmall} def + /Tabloid {11x17tray 11x17} def + /Ledger {ledgertray ledger} def + /Legal {legaltray legal} def + /Statement {statementtray statement} def + /Executive {executivetray executive} def + /A3 {a3tray a3} def + /A4 {a4tray a4} def + /A4Small {a4tray a4small} def + /B4 {b4tray b4} def + /B5 {b5tray b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + statusdict begin stopped end + } bind def +/manualpapersize { + papersizedict begin + /Letter {letter} def + /LetterSmall {lettersmall} def + /Tabloid {11x17} def + /Ledger {ledger} def + /Legal {legal} def + /Statement {statement} def + /Executive {executive} def + /A3 {a3} def + /A4 {a4} def + /A4Small {a4small} def + /B4 {b4} def + /B5 {b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + stopped + } bind def +/desperatepapersize { + statusdict /setpageparams known + { + paperwidth paperheight 0 1 + statusdict begin + {setpageparams} stopped + end + } {true} ifelse + } bind def +/papersizefailure { + FMAllowPaperSizeMismatch not + { +(The requested paper size is not available in any currently-installed tray) +(Edit the PS file to "FMAllowPaperSizeMismatch true" to use default tray) + FMFAILURE } if + } def +/DiacriticEncoding [ +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl +/numbersign /dollar /percent /ampersand /quotesingle /parenleft +/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K +/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash +/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h +/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar +/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute +/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis +/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis +/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve +/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex +/udieresis /dagger /.notdef /cent /sterling /section /bullet +/paragraph /germandbls /registered /copyright /trademark /acute +/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef +/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown +/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef +/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde +/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright +/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis +/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl +/periodcentered /quotesinglbase /quotedblbase /perthousand +/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute +/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve +/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron +/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +] def +/ReEncode { + dup + length + dict begin + { + 1 index /FID ne + {def} + {pop pop} ifelse + } forall + 0 eq {/Encoding DiacriticEncoding def} if + currentdict + end + } bind def +FMPColor + + { + /BEGINBITMAPCOLOR { + BITMAPCOLOR} def + /BEGINBITMAPCOLORc { + BITMAPCOLORc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUECOLOR } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUECOLORc } def + /BEGINBITMAPCMYK { + BITMAPCMYK } def + /BEGINBITMAPCMYKc { + BITMAPCMYKc } def + } + + { + /BEGINBITMAPCOLOR { + BITMAPGRAY} def + /BEGINBITMAPCOLORc { + BITMAPGRAYc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUEGRAY } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUEGRAYc } def + /BEGINBITMAPCMYK { + BITMAPCMYKGRAY } def + /BEGINBITMAPCMYKc { + BITMAPCMYKGRAYc } def + } +ifelse +/K { + FMPrintAllColorsAsBlack { + dup 1 eq 2 index 1 eq and 3 index 1 eq and not + {7 {pop} repeat 0 0 0 1 0 0 0} if + } if + FrameCurColors astore + pop combineColor +} bind def +/graymode true def +fMLevel1 { + /fmGetFlip { + fMatrix2 exch get mul 0 lt { -1 } { 1 } ifelse + } FmBD +} if +/setPatternMode { + fMLevel1 { + 2 index patScreenDict exch known { + pop pop + patScreenDict exch get aload pop + freq + mul + 5 2 roll + fMatrix2 currentmatrix 1 get 0 ne { + 3 -1 roll 90 add 3 1 roll + sflipx 1 fmGetFlip sflipy 2 fmGetFlip neg mul + } { + sflipx 0 fmGetFlip sflipy 3 fmGetFlip mul + } ifelse + 0 lt {exch pop} {pop} ifelse + fMNegative { + {neg} fmConcatProcs + } if + bind + + + + systemdict /setscreen get exec + /FrameCurGray exch def + } { + /bwidth exch def + /bpside exch def + /bstring exch def + /onbits 0 def /offbits 0 def + freq sangle landscape {90 add} if + {/ypoint exch def + /xpoint exch def + /xindex xpoint 1 add 2 div bpside mul cvi def + /yindex ypoint 1 add 2 div bpside mul cvi def + bstring yindex bwidth mul xindex 8 idiv add get + 1 7 xindex 8 mod sub bitshift and 0 ne fMNegative {not} if + {/onbits onbits 1 add def 1} + {/offbits offbits 1 add def 0} + ifelse + } + setscreen + offbits offbits onbits add div fMNegative {1.0 exch sub} if + /FrameCurGray exch def + } ifelse + } { + pop pop + dup patCache exch known { + patCache exch get + } { + dup + patDict /bstring 3 -1 roll put + patDict + 9 PatFreq screenIndex get div dup matrix scale + makepattern + dup + patCache 4 -1 roll 3 -1 roll put + } ifelse + /FrameCurGray 0 def + /FrameCurPat exch def + } ifelse + /graymode false def + combineColor +} bind def +/setGrayScaleMode { + graymode not { + /graymode true def + fMLevel1 { + setCurrentScreen + } if + } if + /FrameCurGray exch def + combineColor +} bind def +/normalize { + transform round exch round exch itransform + } bind def +/dnormalize { + dtransform round exch round exch idtransform + } bind def +/lnormalize { + 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop + } bind def +/H { + lnormalize setlinewidth + } bind def +/Z { + setlinecap + } bind def + +/PFill { + graymode fMLevel1 or not { + gsave 1 setgray eofill grestore + } if +} bind def +/PStroke { + graymode fMLevel1 or not { + gsave 1 setgray stroke grestore + } if + stroke +} bind def +/X { + fillvals exch get + dup type /stringtype eq + {8 1 setPatternMode} + {setGrayScaleMode} + ifelse + } bind def +/V { + PFill gsave eofill grestore + } bind def +/Vclip { + clip + } bind def +/Vstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/N { + PStroke + } bind def +/Nclip { + strokepath clip newpath + } bind def +/Nstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/M {newpath moveto} bind def +/E {lineto} bind def +/D {curveto} bind def +/O {closepath} bind def +/L { + /n exch def + newpath + normalize + moveto + 2 1 n {pop normalize lineto} for + } bind def +/Y { + L + closepath + } bind def +/R { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + x1 y1 + x2 y1 + x2 y2 + x1 y2 + 4 Y + } bind def +/rarc + {rad + arcto + } bind def +/RR { + /rad exch def + normalize + /y2 exch def + /x2 exch def + normalize + /y1 exch def + /x1 exch def + mark + newpath + { + x1 y1 rad add moveto + x1 y2 x2 y2 rarc + x2 y2 x2 y1 rarc + x2 y1 x1 y1 rarc + x1 y1 x1 y2 rarc + closepath + } stopped {x1 y1 x2 y2 R} if + cleartomark + } bind def +/RRR { + /rad exch def + normalize /y4 exch def /x4 exch def + normalize /y3 exch def /x3 exch def + normalize /y2 exch def /x2 exch def + normalize /y1 exch def /x1 exch def + newpath + normalize moveto + mark + { + x2 y2 x3 y3 rarc + x3 y3 x4 y4 rarc + x4 y4 x1 y1 rarc + x1 y1 x2 y2 rarc + closepath + } stopped + {x1 y1 x2 y2 x3 y3 x4 y4 newpath moveto lineto lineto lineto closepath} if + cleartomark + } bind def +/C { + grestore + gsave + R + clip + setCurrentScreen +} bind def +/CP { + grestore + gsave + Y + clip + setCurrentScreen +} bind def +/F { + FMfonts exch get + FMpointsize scalefont + setfont + } bind def +/Q { + /FMpointsize exch def + F + } bind def +/T { + moveto show + } bind def +/RF { + rotate + 0 ne {-1 1 scale} if + } bind def +/TF { + gsave + moveto + RF + show + grestore + } bind def +/P { + moveto + 0 32 3 2 roll widthshow + } bind def +/PF { + gsave + moveto + RF + 0 32 3 2 roll widthshow + grestore + } bind def +/S { + moveto + 0 exch ashow + } bind def +/SF { + gsave + moveto + RF + 0 exch ashow + grestore + } bind def +/B { + moveto + 0 32 4 2 roll 0 exch awidthshow + } bind def +/BF { + gsave + moveto + RF + 0 32 4 2 roll 0 exch awidthshow + grestore + } bind def +/G { + gsave + newpath + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill fill + grestore + } bind def +/Gstrk { + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/Gclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GG { + gsave + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill + fill + grestore + } bind def +/GGclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GGstrk { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/A { + gsave + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/Aclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/Astrk { + Gstrk +} bind def +/AA { + gsave + savematrix + newpath + + 3 index 2 div add exch 4 index 2 div sub exch + + normalize 3 index 2 div sub exch 4 index 2 div add exch + translate + rotate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/AAclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/AAstrk { + GGstrk +} bind def +/BEGINPRINTCODE { + /FMdicttop countdictstack 1 add def + /FMoptop count 7 sub def + /FMsaveobject save def + userdict begin + /showpage {} def + FMNORMALIZEGRAPHICS + 3 index neg 3 index neg translate + } bind def +/ENDPRINTCODE { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMsaveobject restore + } bind def +/gn { + 0 + { 46 mul + cf read pop + 32 sub + dup 46 lt {exit} if + 46 sub add + } loop + add + } bind def +/cfs { + /str sl string def + 0 1 sl 1 sub {str exch val put} for + str def + } bind def +/ic [ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 + {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx} + {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx} + {19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} + {13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh} + {4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh} + {13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl} + {7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl} + {0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl} + {10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl} + ] def +/ms { + /sl exch def + /val 255 def + /ws cfs + /im cfs + /val 0 def + /bs cfs + /cs cfs + } bind def +400 ms +/ip { + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip { + + + bis ris copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + ris gis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + gis bis copy pop + dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip4 { + + + kis cis copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + cis mis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + mis yis copy pop + dup dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + yis kis copy pop + 3 mul is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/wh { + /len exch def + /pos exch def + ws 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/bl { + /len exch def + /pos exch def + bs 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/s1 1 string def +/fl { + /len exch def + /pos exch def + /val cf s1 readhexstring pop 0 get def + pos 1 pos len add 1 sub {im exch val put} for + pos len + } bind def +/hx { + 3 copy getinterval + cf exch readhexstring pop pop + } bind def +/wbytes { + dup dup + 8 gt { pop 8 idiv mul } + { 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse } ifelse + } bind def +/BEGINBITMAPBWc { + 1 {} COMMONBITMAPc + } bind def +/BEGINBITMAPGRAYc { + 8 {} COMMONBITMAPc + } bind def +/BEGINBITMAP2BITc { + 2 {} COMMONBITMAPc + } bind def +/COMMONBITMAPc { + + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + cvtProc + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} image + bitmapsave restore + grestore + } bind def +/BEGINBITMAPBW { + 1 {} COMMONBITMAP + } bind def +/BEGINBITMAPGRAY { + 8 {} COMMONBITMAP + } bind def +/BEGINBITMAP2BIT { + 2 {} COMMONBITMAP + } bind def +/COMMONBITMAP { + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + cvtProc + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} image + bitmapsave restore + grestore + } bind def +/ngrayt 256 array def +/nredt 256 array def +/nbluet 256 array def +/ngreent 256 array def +fMLevel1 { +/colorsetup { + currentcolortransfer + /gryt exch def + /blut exch def + /grnt exch def + /redt exch def + 0 1 255 { + /indx exch def + /cynu 1 red indx get 255 div sub def + /magu 1 green indx get 255 div sub def + /yelu 1 blue indx get 255 div sub def + /kk cynu magu min yelu min def + /u kk currentundercolorremoval exec def +% /u 0 def + nredt indx 1 0 cynu u sub max sub redt exec put + ngreent indx 1 0 magu u sub max sub grnt exec put + nbluet indx 1 0 yelu u sub max sub blut exec put + ngrayt indx 1 kk currentblackgeneration exec sub gryt exec put + } for + {255 mul cvi nredt exch get} + {255 mul cvi ngreent exch get} + {255 mul cvi nbluet exch get} + {255 mul cvi ngrayt exch get} + setcolortransfer + {pop 0} setundercolorremoval + {} setblackgeneration + } bind def +} +{ +/colorSetup2 { + [ /Indexed /DeviceRGB 255 + {dup red exch get 255 div + exch dup green exch get 255 div + exch blue exch get 255 div} + ] setcolorspace +} bind def +} ifelse +/fakecolorsetup { + /tran 256 string def + 0 1 255 {/indx exch def + tran indx + red indx get 77 mul + green indx get 151 mul + blue indx get 28 mul + add add 256 idiv put} for + currenttransfer + {255 mul cvi tran exch get 255.0 div} + exch fmConcatProcs settransfer +} bind def +/BITMAPCOLOR { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + fMLevel1 { + colorsetup + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} {is} {is} true 3 colorimage + } { + colorSetup2 + /is width depth wbytes string def + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {cf is readhexstring pop} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPCOLORc { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + fMLevel1 { + colorsetup + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} {is} {is} true 3 colorimage + } { + colorSetup2 + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {ip} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLORc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris} {gis} {bis} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYKc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip4 pop cis} {mis} {yis} {kis} true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLOR { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf gis readhexstring pop } + { cf bis readhexstring pop } + true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYK { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /mis width string def + /yis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf mis readhexstring pop } + { cf yis readhexstring pop } + { cf kis readhexstring pop } + true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUEGRAYc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris gis bis width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAYc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop cis mis yis kis width cgray} image + bitmapsave restore + grestore + } bind def +/cgray { + /ww exch def + /k exch def + /y exch def + /m exch def + /c exch def + 0 1 ww 1 sub { /i exch def c i get m i get y i get k i get CMYKtoRGB + .144 mul 3 1 roll .587 mul 3 1 roll .299 mul add add + c i 3 -1 roll floor cvi put } for + c + } bind def +/gray { + /ww exch def + /b exch def + /g exch def + /r exch def + 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul + b i get .114 mul add add r i 3 -1 roll floor cvi put } for + r + } bind def +/BITMAPTRUEGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf gis readhexstring pop + cf bis readhexstring pop width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /yis width string def + /mis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf mis readhexstring pop + cf yis readhexstring pop + cf kis readhexstring pop width cgray} image + bitmapsave restore + grestore + } bind def +/BITMAPGRAY { + 8 {fakecolorsetup} COMMONBITMAP + } bind def +/BITMAPGRAYc { + 8 {fakecolorsetup} COMMONBITMAPc + } bind def +/ENDBITMAP { + } bind def +end + /ALDmatrix matrix def ALDmatrix currentmatrix pop +/StartALD { + /ALDsave save def + savematrix + ALDmatrix setmatrix + } bind def +/InALD { + restorematrix + } bind def +/DoneALD { + ALDsave restore + } bind def +/I { setdash } bind def +/J { [] 0 setdash } bind def +%%EndProlog +%%BeginSetup +(5.0) FMVERSION +1 1 0 0 612 792 0 1 16 FMDOCUMENT +0 0 /Helvetica FMFONTDEFINE +1 0 /Times-BoldItalic FMFONTDEFINE +2 0 /Helvetica-Bold FMFONTDEFINE +3 0 /Helvetica-BoldOblique FMFONTDEFINE +4 0 /Helvetica-Oblique FMFONTDEFINE +5 0 /Courier-Bold FMFONTDEFINE +6 0 /Courier-BoldOblique FMFONTDEFINE +32 FMFILLS +0 0 FMFILL +1 0.1 FMFILL +2 0.3 FMFILL +3 0.5 FMFILL +4 0.7 FMFILL +5 0.9 FMFILL +6 0.97 FMFILL +7 1 FMFILL +8 <0f1e3c78f0e1c387> FMFILL +9 <0f87c3e1f0783c1e> FMFILL +10 FMFILL +11 FMFILL +12 <8142241818244281> FMFILL +13 <03060c183060c081> FMFILL +14 <8040201008040201> FMFILL +16 1 FMFILL +17 0.9 FMFILL +18 0.7 FMFILL +19 0.5 FMFILL +20 0.3 FMFILL +21 0.1 FMFILL +22 0.03 FMFILL +23 0 FMFILL +24 FMFILL +25 FMFILL +26 <3333333333333333> FMFILL +27 <0000ffff0000ffff> FMFILL +28 <7ebddbe7e7dbbd7e> FMFILL +29 FMFILL +30 <7fbfdfeff7fbfdfe> FMFILL +%%EndSetup +%%Page: "i" 1 +%%BeginPaperSize: Letter +%%EndPaperSize +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(i) 555.78 57 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 720 558 720 2 L +0.5 H +2 Z +N +72 72 558 72 2 L +N +72 504 558 504 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 32 Q +(A CDEV T) 198 662.67 T +(utorial) 340.85 662.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 12 Q +(T) 198 638 T +(ec) 204.61 638 T +(hniques f) 217.84 638 T +(or using the Contr) 270.94 638 T +(ol De) 374.7 638 T +(vice Interface) 403.86 638 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(Chip W) 198 610 T +(atson, Jie Chen, Danjin W) 236.86 610 T +(u, W) 375.22 610 T +(alt Ak) 399.41 610 T +(ers) 429.18 610 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 198 582 T +(ersion 1.5 - December 9, 1996) 205.04 582 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(TJNAF - Thomas Jeff) 198 554 T +(erson National Acceler) 311.66 554 T +(ator F) 432.25 554 T +(acility) 463 554 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "i" 1 +%%Page: "ii" 2 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(ii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(TRADEMARKS:) 54 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(UNIX is a registered tr) 180 569.33 T +(ademar) 278.26 569.33 T +(k of A) 312.31 569.33 T +(T&T in the USA and other countr) 336.68 569.33 T +(ies) 481.9 569.33 T +(.) 494.53 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(VxW) 180 545.33 T +(or) 200.81 545.33 T +(ks is a register tr) 209.85 545.33 T +(ademar) 283.1 545.33 T +(k of Wind Riv) 317.15 545.33 T +(er Systems) 375.8 545.33 T +(.) 425.66 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The X Windo) 180 521.33 T +(w System is a tr) 237.65 521.33 T +(ademar) 308.12 521.33 T +(k of Massachusetts Institute of T) 342.17 521.33 T +(echnology) 484.37 521.33 T +(.) 528.95 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(OSF/Motif and Motif are tr) 180 497.33 T +(ademar) 294.94 497.33 T +(ks of Open Softw) 328.99 497.33 T +(are F) 404.99 497.33 T +(oundation, Inc.) 428.03 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ultr) 180 473.33 T +(ix and DEC are registered tr) 195.7 473.33 T +(ademar) 319.53 473.33 T +(ks of Digital Equipment Cor) 353.58 473.33 T +(por) 475.03 473.33 T +(ation.) 489.38 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(HPUX is a registered tr) 180 449.33 T +(ademar) 282.15 449.33 T +(k of He) 316.2 449.33 T +(wlett P) 347.68 449.33 T +(ac) 377.29 449.33 T +(kard.) 387.65 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(SURA/CEB) 54 344.33 T +(AF:) 105.92 344.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.44 (The Southeaster) 180 344.33 P +4.44 (n Univ) 258.62 344.33 P +4.44 (ersities Research Association \050SURA\051 oper) 291.15 344.33 P +4.44 (ates the) 499.98 344.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.01 (Contin) 180 332.33 P +2.01 (uous Electron Beam Acceler) 208.8 332.33 P +2.01 (ator F) 340.89 332.33 P +2.01 (acility \050CEBAF\051 f) 368.52 332.33 P +2.01 (or the United States) 445.59 332.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Depar) 180 320.33 T +(tment of Energy under contr) 207.63 320.33 T +(act DE-A) 331.48 320.33 T +(C05-84ER40150.) 371.19 320.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DISCLAIMER:) 54 218.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.49 (This repor) 180 218.33 P +0.49 (t w) 225.9 218.33 P +0.49 (as prepared as an account of w) 239.02 218.33 P +0.49 (or) 381.4 218.33 P +0.49 (k sponsored b) 390.44 218.33 P +0.49 (y the United States) 454.03 218.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.18 (go) 180 206.33 P +2.18 (v) 190.97 206.33 P +2.18 (er) 195.72 206.33 P +2.18 (nment. Neither the United States nor the United States Depar) 204.86 206.33 P +2.18 (tment of) 501.68 206.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.04 (Energy) 180 194.33 P +1.04 (, nor an) 210.68 194.33 P +1.04 (y of their emplo) 246.52 194.33 P +1.04 (y) 317.69 194.33 P +1.04 (ees) 322.49 194.33 P +1.04 (, mak) 338.46 194.33 P +1.04 (es an) 363.75 194.33 P +1.04 (y w) 389.1 194.33 P +1.04 (arr) 404.99 194.33 P +1.04 (anty) 417.11 194.33 P +1.04 (, e) 435.01 194.33 P +1.04 (xpress or implied, or) 446.86 194.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.83 (assumes an) 180 182.33 P +1.83 (y legal liability or responsibility f) 235.59 182.33 P +1.83 (or the accur) 383.89 182.33 P +1.83 (acy) 440.24 182.33 P +1.83 (, completeness) 454.8 182.33 P +1.83 (, or) 523.72 182.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.68 (usefulness of an) 180 170.33 P +3.68 (y inf) 260.02 170.33 P +3.68 (or) 281.74 170.33 P +3.68 (mation, appar) 290.88 170.33 P +3.68 (atus) 355.59 170.33 P +3.68 (, product or process disclosed, or) 374.34 170.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.46 (represents that its use w) 180 158.33 P +2.46 (ould not infr) 298.11 158.33 P +2.46 (inge pr) 355.42 158.33 P +2.46 (iv) 388.59 158.33 P +2.46 (ately o) 395.56 158.33 P +2.46 (wned r) 427.33 158.33 P +2.46 (ights) 459.95 158.33 P +2.46 (. Ref) 480.92 158.33 P +2.46 (erence) 509.43 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.6 (herein to an) 180 146.33 P +1.6 (y speci\336c commercial product, process) 235.85 146.33 P +1.6 (, or ser) 413.79 146.33 P +1.6 (vice b) 448.4 146.33 P +1.6 (y tr) 475.92 146.33 P +1.6 (ade name) 491.3 146.33 P +1.6 (,) 537.22 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (mar) 180 134.33 P +2.12 (k, man) 197.37 134.33 P +2.12 (uf) 229.4 134.33 P +2.12 (acturer) 237.44 134.33 P +2.12 (, or otherwise) 268.06 134.33 P +2.12 (, does not necessar) 332.17 134.33 P +2.12 (ily constitute or imply its) 425.94 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (endorsement, recommendation, or f) 180 122.33 P +1.08 (a) 341.33 122.33 P +1.08 (v) 346.69 122.33 P +1.08 (or) 351.44 122.33 P +1.08 (ing b) 360.48 122.33 P +1.08 (y the United States go) 383.03 122.33 P +1.08 (v) 485.57 122.33 P +1.08 (er) 490.32 122.33 P +1.08 (nment or) 499.46 122.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (an) 180 110.33 P +0.83 (y agency thereof) 190.97 110.33 P +0.83 (. The vie) 266.26 110.33 P +0.83 (w and opinions of the authors e) 309.67 110.33 P +0.83 (xpressed herein do) 453.3 110.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.94 (not necessar) 180 98.33 P +1.94 (ily state or re\337ect those of the United States go) 239.34 98.33 P +1.94 (v) 464.01 98.33 P +1.94 (er) 468.76 98.33 P +1.94 (nment or an) 477.9 98.33 P +1.94 (y) 535 98.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(agency thereof) 180 86.33 T +(.) 245.85 86.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DOCUMENT D) 54 668.33 T +(A) 121.37 668.33 T +(TE:) 127.69 668.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(T) 180 668.33 T +(ab) 184.91 668.33 T +(le of ontents gener) 195.83 668.33 T +(ated: December 9, 1996 11:46 am) 278.56 668.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "ii" 2 +%%Page: "iii" 3 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iii) 551.34 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(T) 180 710.67 T +(ab) 187.43 710.67 T +(le of Contents) 203.63 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198 684.33 T +(v) 210.48 684.33 T +(eloping CDEV Applications) 215.23 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 336.38 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 672.33 T +(er) 210.73 672.33 T +(vie) 219.92 672.33 T +(w) 232.5 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Steps in De) 198.2 660.33 T +(v) 249.59 660.33 T +(eloping a CDEV Application) 254.34 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 378.08 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 180 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198 648.33 T +(v) 210.48 648.33 T +(eloping De) 215.23 648.33 T +(vice De\336nition Language Files) 262.73 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . .) 397.54 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198.2 636.33 T +(vice De\336nition Language \050DDL\051 File Ov) 210.68 636.33 T +(er) 383.82 636.33 T +(vie) 393.01 636.33 T +(w) 405.59 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . .) 414.22 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ser) 198.2 624.33 T +(vice De\336nitions) 214.06 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Class De\336nitions) 198.2 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 198.2 600.33 T +(erb De\336nitions) 204.07 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Class Inher) 198.2 588.33 T +(itance) 248.92 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Attr) 198.2 576.33 T +(ib) 213.91 576.33 T +(ute De\336nitions) 221.49 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 286.34 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Attr) 198.2 564.33 T +(ib) 213.91 564.33 T +(ute Ser) 221.49 564.33 T +(vice Data) 254.03 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 297.46 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Message De\336nitions) 198.2 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 289.12 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198.2 540.33 T +(vice Instances) 210.68 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198.2 528.33 T +(vice Name Substitution) 210.68 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 314.14 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De) 198.2 516.33 T +(vice Name Aliasing) 210.68 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 297.46 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(De\336ning cde) 198.2 504.33 T +(vCollections) 253.48 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(#include Directiv) 198.2 492.33 T +(e) 271.3 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample DDL) 198.2 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 255.76 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 180 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the cde) 198 468.33 T +(vSystem Object) 258.84 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 330.82 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 456.33 T +(er) 210.73 456.33 T +(vie) 219.92 456.33 T +(w of the cde) 232.5 456.33 T +(vSystem Class) 286.12 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 353.06 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 198.2 444.33 T +(lic Functions of the cde) 215.79 444.33 T +(vSystem Class) 317.76 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 386.42 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachRef) 216 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachPtr) 216 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(def) 216 408.33 T +(aultSystem) 229.6 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getDe) 216 396.33 T +(vice) 242.38 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getRequestObject) 216 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 297.46 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(10) 546.88 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(name) 216 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pre\336x) 216 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pre\336x) 216 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\337ush) 216 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(poll) 216 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 233.52 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pend) 216 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(pend) 216 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getFd) 216 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(11) 546.88 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(addFdChanged) 216 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 286.34 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Callbac) 508.74 276.33 T +(k) 541.88 276.33 T +(12) 546.88 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(autoErrorOn) 216 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 546.88 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(autoErrorOff) 216 252.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 252.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 546.88 252.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(repor) 216 240.33 T +(tError) 239.74 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 266.88 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12) 546.88 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setErrorHandler) 216 228.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 289.12 228.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 228.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setThreshold) 216 216.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 216.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(13) 546.88 216.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample Code) 198.2 204.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 204.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 546.88 204.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 180 192.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the cde) 198 192.33 T +(vDe) 258.84 192.33 T +(vice Object) 276.32 192.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 328.04 192.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 192.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 180.33 T +(er) 210.73 180.33 T +(vie) 219.92 180.33 T +(w of the cde) 232.5 180.33 T +(vDe) 286.12 180.33 T +(vice Class) 303.6 180.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 350.28 180.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 180.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 198.2 168.33 T +(lic Functions of the cde) 215.79 168.33 T +(vDe) 317.76 168.33 T +(vice Class) 335.24 168.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 380.86 168.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 168.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachRef) 216 156.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 156.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 156.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachPtr) 216 144.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 144.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 144.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(detach) 216 132.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 132.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 132.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(detach) 216 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(16) 546.88 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getRequestObject) 216 108.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 297.46 108.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 546.88 108.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(name) 216 96.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 96.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 546.88 96.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(system) 216 84.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 84.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 546.88 84.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iii" 3 +%%Page: "iv" 4 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iv) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(setConte) 198 713.33 T +(xt) 237.72 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 528.88 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getConte) 198 701.33 T +(xt) 238.28 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 528.88 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setPr) 198 689.33 T +(iv) 221.49 689.33 T +(ate) 228.46 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 528.88 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getPr) 198 677.33 T +(iv) 222.05 677.33 T +(ate) 229.02 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 528.88 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(send) 198 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 222.4 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(17) 528.88 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendNoBloc) 198 653.33 T +(k) 251.71 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 528.88 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendCallbac) 198 641.33 T +(k) 252.82 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 528.88 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample Code) 180.2 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(19) 528.88 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Attaching to a cde) 180.2 617.33 T +(vDe) 259.95 617.33 T +(vice Object) 277.43 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 328.04 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(19) 528.88 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Getting and Setting Conte) 180.2 605.33 T +(xt f) 294.97 605.33 T +(or a cde) 308.01 605.33 T +(vDe) 343.84 605.33 T +(vice) 361.32 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . .) 380.86 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(20) 528.88 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sending Messages to a De) 180.2 593.33 T +(vice Synchronously) 299.96 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . .) 386.42 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(21) 528.88 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sending Messages to a De) 180.2 581.33 T +(vice Asynchronously) 299.96 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . .) 391.98 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(22) 528.88 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using sendNoBloc) 180.2 569.33 T +(k) 262.25 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(23) 528.88 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Managing sendNoBloc) 180.2 557.33 T +(k Messages with the cde) 280.6 557.33 T +(vSystem object) 389.79 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . .) 458.7 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(23) 528.88 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Grouping sendNoBloc) 180.2 545.33 T +(k Messages with cde) 277.82 545.33 T +(vGroup) 370.33 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . .) 405.88 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(23) 528.88 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using def) 180.2 533.33 T +(erred g) 222.14 533.33 T +(roups f) 253.72 533.33 T +(or repeating lists of oper) 283.99 533.33 T +(ations) 391.16 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . .) 419.78 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(24) 528.88 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using sendCallbac) 180.2 521.33 T +(k) 263.36 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(24) 528.88 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 162 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the cde) 180 509.33 T +(vRequestObject Object) 240.84 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 344.72 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 528.88 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180.2 497.33 T +(er) 192.73 497.33 T +(vie) 201.92 497.33 T +(w of the cde) 214.5 497.33 T +(vRequestObject Class) 268.12 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 369.74 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 528.88 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 180.2 485.33 T +(lic Member Functions of the cde) 197.79 485.33 T +(vRequestObject Class) 339.21 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . .) 439.24 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 528.88 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachRef) 198 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 528.88 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachRef) 198 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 528.88 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachPtr) 198 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(28) 528.88 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attachPtr) 198 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(29) 528.88 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(detach) 198 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 230.74 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(29) 528.88 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(detach) 198 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 230.74 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(29) 528.88 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(message) 198 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(29) 528.88 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(de) 198 389.33 T +(vice) 208.82 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 227.96 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(29) 528.88 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(system) 198 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 230.74 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(29) 528.88 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ser) 198 365.33 T +(vice) 212.19 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 230.74 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(29) 528.88 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getState) 198 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 236.3 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(29) 528.88 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getAccess) 198 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(29) 528.88 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setConte) 198 329.33 T +(xt) 237.72 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(30) 528.88 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getConte) 198 317.33 T +(xt) 238.28 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(30) 528.88 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getPr) 198 305.33 T +(iv) 222.05 305.33 T +(ate) 229.02 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(30) 528.88 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setPr) 198 293.33 T +(iv) 221.49 293.33 T +(ate) 228.46 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 244.64 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(30) 528.88 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(send) 198 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 222.4 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(30) 528.88 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendNoBloc) 198 269.33 T +(k) 251.71 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(31) 528.88 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendCallbac) 198 257.33 T +(k) 252.82 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(31) 528.88 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample Code) 180.2 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(31) 528.88 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Attaching to a cde) 180.2 233.33 T +(vRequestObject Object) 259.95 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 364.18 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 528.88 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Getting and Setting Conte) 180.2 221.33 T +(xt f) 294.97 221.33 T +(or a cde) 308.01 221.33 T +(vRequestObject) 343.84 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . .) 417 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(33) 528.88 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sending Messages to a De) 180.2 209.33 T +(vice Synchronously) 299.96 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . .) 386.42 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(34) 528.88 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sending Messages to a De) 180.2 197.33 T +(vice Asynchronously) 299.96 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . .) 391.98 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(35) 528.88 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using sendNoBloc) 180.2 185.33 T +(k) 262.25 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(35) 528.88 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Managing sendNoBloc) 180.2 173.33 T +(k Messages with the cde) 280.6 173.33 T +(vSystem object) 389.79 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . .) 458.7 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(35) 528.88 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Grouping sendNoBloc) 180.2 161.33 T +(k Messages with cde) 277.82 161.33 T +(vGroup) 370.33 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . .) 405.88 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(35) 528.88 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using def) 180.2 149.33 T +(erred g) 222.14 149.33 T +(roups f) 253.72 149.33 T +(or repeating lists of oper) 283.99 149.33 T +(ations) 391.16 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . .) 419.78 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(36) 528.88 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using sendCallbac) 180.2 137.33 T +(k) 263.36 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 269.66 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(36) 528.88 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 162 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the cde) 180 125.33 T +(vData Object) 240.84 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 300.24 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(40) 528.88 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180.2 113.33 T +(er) 192.73 113.33 T +(vie) 201.92 113.33 T +(w of the cde) 214.5 113.33 T +(vData Class) 268.12 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 322.48 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(40) 528.88 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180.2 101.33 T +(vData T) 196.02 101.33 T +(ags) 229.83 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(40) 528.88 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(XDR P) 180.2 89.33 T +(ac) 210.36 89.33 T +(kaging of cde) 220.72 89.33 T +(vData Objects) 279.9 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 344.72 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(40) 528.88 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iv" 4 +%%Page: "v" 5 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(v) 553 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pub) 198.2 713.33 T +(lic Functions of the cde) 215.79 713.33 T +(vData Class) 317.76 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 372.52 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(40) 546.88 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(tagC2I) 216 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(40) 546.88 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(tagI2C) 216 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 247.42 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(40) 546.88 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(inser) 216 677.33 T +(tT) 238.07 677.33 T +(ag) 245.76 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(40) 546.88 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(oper) 216 665.33 T +(ator =) 235.91 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(40) 546.88 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Cast oper) 216 653.33 T +(ators) 259.25 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(41) 546.88 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(asciiDump) 216 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(41) 546.88 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(xdrSiz) 216 629.33 T +(e) 243.63 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(41) 546.88 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(xdrExpor) 216 617.33 T +(t) 256.41 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(41) 546.88 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(xdrExpor) 216 605.33 T +(t) 256.41 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(41) 546.88 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(xdrImpor) 216 593.33 T +(t) 255.85 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(41) 546.88 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(remo) 216 581.33 T +(v) 238.63 581.33 T +(e) 243.38 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(41) 546.88 581.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(changeT) 216 569.33 T +(ag) 253.71 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 266.88 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(42) 546.88 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getT) 216 557.33 T +(ype) 234.81 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 252.98 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(42) 546.88 557.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getDim) 216 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 250.2 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(42) 546.88 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getElems) 216 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(42) 546.88 533.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(getBounds) 216 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(43) 546.88 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(setBounds) 216 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(43) 546.88 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(inser) 216 497.33 T +(t \050scalar\051) 238.07 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(43) 546.88 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(inser) 216 485.33 T +(t \050arr) 238.07 485.33 T +(a) 259.08 485.33 T +(y\051) 264.34 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 275.22 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(44) 546.88 485.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(inser) 216 473.33 T +(t \050char) 238.07 473.33 T +(acter str) 266.31 473.33 T +(ing\051) 302.58 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 319.7 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(44) 546.88 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(get) 216 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 230.74 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(44) 546.88 461.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(get \050char) 216 449.33 T +(acter str) 255.36 449.33 T +(ing\051) 291.63 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 308.58 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\336nd) 216 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 233.52 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample Code) 198.2 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 261.32 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 180 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the cde) 198 413.33 T +(vDirector) 258.84 413.33 T +(y De) 299.14 413.33 T +(vice) 319.4 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 339.16 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(56) 546.88 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 198.2 401.33 T +(vDirector) 214.02 401.33 T +(y De) 254.32 401.33 T +(vice) 274.58 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 294.68 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(56) 546.88 401.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Attaching to the cde) 198.2 389.33 T +(vDirector) 286.29 389.33 T +(y) 326.59 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 333.6 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(56) 546.88 389.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Messages Suppor) 198.2 377.33 T +(ted b) 279.19 377.33 T +(y cde) 301.23 377.33 T +(vDirector) 324.83 377.33 T +(y) 365.13 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 372.52 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(56) 546.88 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322quer) 198.2 365.33 T +(y\323) 221.84 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 230.74 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(57) 546.88 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322quer) 198.2 353.33 T +(yClass\323) 221.84 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 255.76 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(58) 546.88 353.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322quer) 198.2 341.33 T +(yAttr) 221.84 341.33 T +(ib) 242.55 341.33 T +(utes\323) 250.13 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(59) 546.88 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322quer) 198.2 329.33 T +(yMessages\323) 221.84 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(60) 546.88 329.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322quer) 198.2 317.33 T +(yV) 221.84 317.33 T +(erbs\323) 232.71 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 255.76 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(61) 546.88 317.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322ser) 198.2 305.33 T +(vice\323) 215.72 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(62) 546.88 305.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322ser) 198.2 293.33 T +(viceData\323) 215.72 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 258.54 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(63) 546.88 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322update\323) 198.2 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 236.3 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(64) 546.88 281.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322v) 198.2 269.33 T +(alidate\323) 206.28 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 239.08 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(65) 546.88 269.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8.) 180 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Def) 198 257.33 T +(ault Ser) 213.26 257.33 T +(vice Beha) 248.02 257.33 T +(vior f) 291.73 257.33 T +(or Standard Messages) 313.1 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . .) 414.22 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(67) 546.88 257.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 245.33 T +(er) 210.73 245.33 T +(vie) 219.92 245.33 T +(w) 232.5 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(67) 546.88 245.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322get\323 Message) 198.2 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(67) 546.88 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322set\323 Message) 198.2 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 264.1 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(68) 546.88 221.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322monitorOn\323 Message) 198.2 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 297.46 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(70) 546.88 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_SUCCESS) 216 197.33 T +0 F +(:) 297.68 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 303.02 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(71) 546.88 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_DISCONNECTED) 216 185.33 T +0 F +(:) 329.34 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 333.6 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(71) 546.88 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_RECONNECTED) 216 173.33 T +0 F +(:) 326.56 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 330.82 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(71) 546.88 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_ERR) 216 161.33 T +(OR) 270.25 161.33 T +0 F +(:) 285.25 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 289.12 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(71) 546.88 161.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_INV) 216 149.33 T +(ALIDOBJ) 265.21 149.33 T +0 F +(:) 309.1 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 314.14 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(71) 546.88 149.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_INV) 216 137.33 T +(ALID) 265.21 137.33 T +(ARG) 288.14 137.33 T +0 F +(:) 310.36 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 314.14 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(71) 546.88 137.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_INV) 216 125.33 T +(ALIDSVC) 265.21 125.33 T +0 F +(:) 309.1 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 314.14 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(71) 546.88 125.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_NO) 216 113.33 T +(TCONNECTED) 263.94 113.33 T +0 F +(:) 333.38 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 336.38 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(71) 546.88 113.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_IOF) 216 101.33 T +(AILED) 265.21 101.33 T +0 F +(:) 295.21 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 300.24 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(71) 546.88 101.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_CONFLICT) 216 89.33 T +0 F +(:) 299.69 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 303.02 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(72) 546.88 89.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "v" 5 +%%Page: "vi" 6 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(vi) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(CDEV_NO) 198 713.33 T +(TFOUND) 245.94 713.33 T +0 F +(:) 287.6 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(72) 528.88 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_TIMEOUT) 198 701.33 T +0 F +(:) 276.14 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 280.78 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(72) 528.88 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_CONVER) 198 689.33 T +(T) 273.92 689.33 T +0 F +(:) 279.83 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 283.56 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(72) 528.88 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_OUT) 198 677.33 T +(OFRANGE) 252.05 677.33 T +0 F +(:) 302.05 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 305.8 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(72) 528.88 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_NO) 198 665.33 T +(A) 245.84 665.33 T +(CCESS) 252.66 665.33 T +0 F +(:) 287.11 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 291.9 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(72) 528.88 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(CDEV_A) 198 653.33 T +(CCESSCHANGED) 238.16 653.33 T +0 F +(:) 323.16 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 328.04 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(72) 528.88 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\322monitorOff) 180.2 641.33 T +(\323 Message) 230.81 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 278 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(72) 528.88 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(de) 198 629.33 T +(vice) 208.82 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 227.96 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(72) 528.88 629.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attr) 198 617.33 T +(ib) 212.6 617.33 T +(ute) 220.18 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 236.3 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(72) 528.88 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(function) 198 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 233.52 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(72) 528.88 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(user) 198 593.33 T +(arg) 217.35 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 233.52 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(72) 528.88 593.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "vi" 6 +%%Page: "vii" 7 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(vii) 548.56 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(List of Figures) 180 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(Figure 1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Service definitions in the CDEV DDL file) 234 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..................................................) 411.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 2.) 180 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV DDL class definition containing a list of verbs) 234 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...............................) 464.26 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 3.) 180 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV DDL class definition using inheritance) 234 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..........................................) 433.68 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 4.) 180 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV DDL class definition containing a list of attributes) 234 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.........................) 480.94 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 5.) 180 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV DDL class definition containing a list of messages) 234 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................) 486.5 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 6.) 180 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CDEV DDL class definition to instantiate a list of devices) 234 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................) 483.72 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 7.) 180 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Implementing device name substitution in a CDEV DDL file) 234 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(....................) 494.84 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 8.) 180 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Implementing device name aliasing in a CDEV DDL file) 234 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..........................) 478.16 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 9.) 180 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdevCollection Definition in the CDEV DDL File) 234 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(......................................) 444.8 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 10.) 180 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the #include directive in a CDEV DDL file) 234 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(......................................) 444.8 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 11.) 180 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sample complete DDL file) 234 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................................................................) 350.28 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 12.) 180 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Methods for obtaining a cdevSystem object) 234 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........................................) 425.34 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(14) 546.88 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 13.) 180 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Installing a user specified error handler) 234 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.................................................) 408.66 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(15) 546.88 540.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 14.) 180 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Return codes generated by the send method) 234 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................................) 433.68 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(18) 546.88 528.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 15.) 180 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Attaching to a cdevDevice object) 234 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........................................................) 380.86 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(19) 546.88 516.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 16.) 180 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Altering the context of a cdevDevice object) 234 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........................................) 425.34 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(20) 546.88 504.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 17.) 180 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the send method of a cdevDevice object) 234 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.....................................) 442.02 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(22) 546.88 492.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 18.) 180 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using sendNoBlock to communicate with a cdevDevice) 234 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................) 478.16 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(23) 546.88 480.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 19.) 180 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the sendCallback method of a cdevDevice object) 234 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................) 480.94 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(26) 546.88 468.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 20.) 180 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Return codes generated by the send method) 234 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................................) 433.68 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(31) 546.88 456.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 21.) 180 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Obtaining a cdevRequestObject from a cdevDevice object) 234 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................) 492.06 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(32) 546.88 444.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 22.) 180 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Altering the context of a cdevRequestObject object) 234 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...............................) 458.7 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(33) 546.88 432.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 23.) 180 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the send method of a cdevRequestObject object) 234 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................) 478.16 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(34) 546.88 420.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 24.) 180 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using sendNoBlock to communicate with a cdevRequestObject) 234 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........) 514.3 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(35) 546.88 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 25.) 180 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the sendCallback method of a cdevRequestObject object) 234 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........) 514.3 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(38) 546.88 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 26.) 180 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using insertTag to add a new tag) 234 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........................................................) 380.86 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(45) 546.88 384.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 27.) 180 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using tagC2I and tagI2C to determine cdevData tag identifiers) 234 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(............) 511.52 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(46) 546.88 372.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 28.) 180 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Inserting and retrieving scalar data items using a cdevData object) 234 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......) 525.42 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(46) 546.88 360.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 29.) 180 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the changeTag method of the cdevData object) 234 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........................) 469.82 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(47) 546.88 348.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 30.) 180 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using one-dimensional arrays with cdevData objects) 234 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(............................) 467.04 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(48) 546.88 336.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 31.) 180 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using multi-dimensional arrays with cdevData objects) 234 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..........................) 472.6 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(50) 546.88 324.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 32.) 180 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using character strings with cdevData objects) 234 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................................) 436.46 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(52) 546.88 312.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 33.) 180 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using character string arrays with cdevData objects) 234 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.............................) 464.26 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(52) 546.88 300.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 34.) 180 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the find method of the cdevData object) 234 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........................................) 433.68 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(54) 546.88 288.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 35.) 180 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Attaching to the cdevDirectory device) 234 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(....................................................) 400.32 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(56) 546.88 276.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 36.) 180 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdevData Input/Output associated with a \322query\323 message) 234 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...................) 492.06 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(57) 546.88 264.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 37.) 180 252.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the \322query\323 Message with a cdevDirectory device) 234 252.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................) 480.94 252.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(58) 546.88 252.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 38.) 180 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdevData input/output associated with a \322queryClass\323 message) 234 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........) 514.3 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(58) 546.88 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 39.) 180 228.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the \322queryClass\323 message with a cdevDirectory device) 234 228.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..............) 505.96 228.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(59) 546.88 228.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 40.) 180 216.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdevData input/output associated with a \322queryAttributes\323 message) 234 216.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.....) 530.98 216.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(59) 546.88 216.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 41.) 180 204.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the \322queryAttributes\323 message with a cdevDirectory device) 234 204.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(........) 522.64 204.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(60) 546.88 204.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 42.) 180 192.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdevData input/output associated with a \322queryMessages\323 message) 234 192.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...) 536.54 192.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(60) 546.88 192.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 43.) 180 180.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the \322queryMessages\323 message with a cdevDirectory device) 234 180.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......) 525.42 180.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(61) 546.88 180.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 44.) 180 168.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdevData input/output associated with a \322queryVerbs\323 message) 234 168.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..........) 517.08 168.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(61) 546.88 168.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 45.) 180 156.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the \322queryVerbs\323 message with a cdevDirectory device) 234 156.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..............) 505.96 156.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(62) 546.88 156.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 46.) 180 144.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdevData input/output associated with a \322service\323 message) 234 144.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.................) 497.62 144.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(62) 546.88 144.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 47.) 180 132.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the \322service\323 message with a cdevDirectory device) 234 132.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.....................) 486.5 132.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(63) 546.88 132.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 48.) 180 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdevData input/output associated with a \322serviceData\323 message) 234 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..........) 517.08 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(63) 546.88 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 49.) 180 108.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the \322serviceData\323 message with a cdevDirectory device) 234 108.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.............) 508.74 108.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(64) 546.88 108.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 50.) 180 96.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdevData input/output associated with a \322update\323 message) 234 96.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..................) 494.84 96.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(64) 546.88 96.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 51.) 180 84.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the \322update\323 message with a cdevDirectory device) 234 84.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.....................) 486.5 84.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(65) 546.88 84.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "vii" 7 +%%Page: "viii" 8 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(viii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(Figure 52.) 162 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdevData input/output associated with a \322validate\323 message) 216 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.................) 480.94 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(65) 528.88 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 53.) 162 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the \322update\323 message with a cdevDirectory device) 216 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(......................) 467.04 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(66) 528.88 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 54.) 162 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Default behavior of the \322get\323 and \322set\323 messages) 216 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..................................) 433.68 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(68) 528.88 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 55.) 162 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Default behavior of the \322monitorOn\323 and \322monitorOff\323 messages) 216 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(...........) 497.62 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(73) 528.88 677.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "viii" 8 +%%Page: "1" 9 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. De) 424.94 739 T +(v) 446.18 739 T +(eloping CDEV Applications) 450.46 739 T +0 10 Q +(1) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(1.) 159.32 710.67 T +(De) 180 710.67 T +(veloping CDEV Applications) 197.68 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w) 108.64 673.33 T +0 F +-0.01 (The pur) 180 673.33 P +-0.01 (pose of this section is to descr) 214.74 673.33 P +-0.01 (ibe the steps that a CDEV user m) 348.76 673.33 P +-0.01 (ust perf) 496.95 673.33 P +-0.01 (or) 529.98 673.33 P +-0.01 (m in) 539.12 673.33 P +0 (order to eff) 180 661.33 P +0 (ectiv) 228.07 661.33 P +0 (ely de) 248.38 661.33 P +0 (v) 274.76 661.33 P +0 (elop a CDEV application. This section assumes that the user is) 279.51 661.33 P +1.23 (either using one of the CDEV ser) 180 649.33 P +1.23 (vices pro) 333.85 649.33 P +1.23 (vided in the CDEV distr) 374.93 649.33 P +1.23 (ib) 483.37 649.33 P +1.23 (ution, or has a) 490.95 649.33 P +4.69 (local or third par) 180 637.33 P +4.69 (ty de) 266.17 637.33 P +4.69 (v) 292.24 637.33 P +4.69 (eloped CDEV ser) 296.99 637.33 P +4.69 (vice with which the application will) 383.93 637.33 P +(comm) 180 625.33 T +(unicate) 207.12 625.33 T +(.) 239.21 625.33 T +2 F +(Steps in) 72 596.33 T +(De) 72 584.33 T +(veloping a) 84.63 584.33 T +(CDEV Application) 72 572.33 T +0 F +(1.) 180 596.33 T +2 F +(Construct a CDEV de) 198 596.33 T +(vice de\336nition \336le) 298.42 596.33 T +(.) 383.09 596.33 T +0 F +(The CDEV de) 388.65 596.33 T +(vice de\336nition \336le is the) 450.04 596.33 T +(roadmap that CDEV uses to de\336ne ser) 198 584.33 T +(vices and deter) 369.49 584.33 T +(mine which de) 437.55 584.33 T +(vice and) 501.16 584.33 T +(message combinations are associated with those ser) 198 572.33 T +(vices) 432.84 572.33 T +(. This \336le should be) 455.47 572.33 T +-0.19 (constr) 198 560.33 P +-0.19 (ucted and de\336ned in the) 225.38 560.33 P +3 F +-0.19 (CDEVDDL) 333.93 560.33 P +0 F +-0.19 ( en) 382.26 560.33 P +-0.19 (vironment v) 395.77 560.33 P +-0.19 (ar) 447 560.33 P +-0.19 (iab) 456.04 560.33 P +-0.19 (le pr) 469.18 560.33 P +-0.19 (ior to e) 488.59 560.33 P +-0.19 (x) 518.47 560.33 P +-0.19 (ecuting) 523.17 560.33 P +(a CDEV application. Chec) 198 548.33 T +(k with the CDEV adminstr) 316.18 548.33 T +(ator to deter) 430 548.33 T +(mine if this \336le) 484.17 548.33 T +(already e) 198 536.33 T +(xists on y) 238.83 536.33 T +(our system.) 280.31 536.33 T +(2.) 180 512.33 T +2 F +(Design and write y) 198 512.33 T +(our sour) 286.11 512.33 T +(ce code) 326.47 512.33 T +(.) 363.91 512.33 T +0 F +( This step is intentional broad in scope) 366.69 512.33 T +(because the capabilities pro) 198 500.33 T +(vided b) 321.8 500.33 T +(y v) 353.84 500.33 T +(ar) 366.37 500.33 T +(ious CDEV ser) 375.41 500.33 T +(vices ma) 441.28 500.33 T +(y be completely) 480.43 500.33 T +-0.08 (dissimilar in nature) 198 488.33 P +-0.08 (. The pr) 281.05 488.33 P +-0.08 (imar) 315.51 488.33 P +-0.08 (y capability that CDEV pro) 335.25 488.33 P +-0.08 (vides is standardization) 451.51 488.33 P +(of the interf) 198 476.33 T +(ace betw) 247.73 476.33 T +(een an) 287.65 476.33 T +(y application and an) 318.08 476.33 T +(y under) 406.87 476.33 T +(lying CDEV ser) 440.37 476.33 T +(vice) 508.46 476.33 T +(.) 526.09 476.33 T +(3.) 180 452.33 T +2 F +(Compile and link application with the CDEV librar) 198 452.33 T +(y) 432.6 452.33 T +(.) 437.36 452.33 T +0 F +(This step requires the) 442.92 452.33 T +-0.19 (source code to include the necessar) 198 440.33 P +-0.19 (y CDEV C++ header \336les and linking with the) 357.42 440.33 P +2 F +(libcde) 198 428.33 T +(v) 226.75 428.33 T +(.sl) 231.51 428.33 T +0 F +( or) 242.63 428.33 T +2 F +(libcde) 257.08 428.33 T +(v) 285.83 428.33 T +(.a) 290.59 428.33 T +0 F +( libr) 298.93 428.33 T +(ar) 314.94 428.33 T +(ies) 323.98 428.33 T +(.) 336.61 428.33 T +(4.) 180 404.33 T +2 F +(Set an) 198 404.33 T +(y required en) 227.81 404.33 T +(vir) 290.21 404.33 T +(onment v) 302.24 404.33 T +(ariab) 346.49 404.33 T +(les.) 370.29 404.33 T +0 F +( The pr) 386.97 404.33 T +(imar) 418.8 404.33 T +(y en) 438.54 404.33 T +(vironment v) 457.24 404.33 T +(ar) 508.67 404.33 T +(iab) 517.71 404.33 T +(les) 530.85 404.33 T +(required b) 198 392.33 T +(y CDEV are) 242.82 392.33 T +2 F +(CDEVSHOBJ) 298.39 392.33 T +0 F +(and) 363.4 392.33 T +2 F +( CDEVDDL) 380.08 392.33 T +0 F +(. CDEVSHOBJ is used to) 431.19 392.33 T +(located shared objects) 198 380.33 T +(, and cde) 297.9 380.33 T +(vddl is used to specify the complete path to the) 338.74 380.33 T +(CDEV de) 198 368.33 T +(vice de\336nition \336le) 239.38 368.33 T +(. Individual ser) 315.37 368.33 T +(vices ma) 380.14 368.33 T +(y ha) 419.29 368.33 T +(v) 437.99 368.33 T +(e additional requirements) 442.74 368.33 T +(.) 554.86 368.33 T +(5.) 180 344.33 T +2 F +(Ex) 198 344.33 T +(ecute y) 210.13 344.33 T +(our application.) 244.34 344.33 T +4 F +4.44 (Note: Applications link) 180 320.33 P +4.44 (ed with the archiv) 287.05 320.33 P +4.44 (e libr) 377.94 320.33 P +4.44 (ar) 403.95 320.33 P +4.44 (y are not capab) 413.14 320.33 P +4.44 (le of loading) 495.2 320.33 P +(dynamically loadab) 180 308.33 T +(le CDEV ser) 264.83 308.33 T +(vices) 320.14 308.33 T +(.) 342.77 308.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "1" 9 +%%Page: "2" 10 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. De) 54 739 T +(v) 75.24 739 T +(eloping De) 79.51 739 T +(vice De\336nition Language Files) 122.26 739 T +0 10 Q +(2) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(2.) 141.32 710.67 T +(De) 162 710.67 T +(veloping De) 179.68 710.67 T +(vice De\336nition Langua) 258.82 710.67 T +(g) 408.05 710.67 T +(e Files) 416.74 710.67 T +2 10 Q +(De) 54 673.33 T +(vice De\336nition) 66.63 673.33 T +(Langua) 54 661.33 T +(g) 89.46 661.33 T +(e \050DDL\051) 95.67 661.33 T +(File Over) 54 649.33 T +(vie) 96.9 649.33 T +(w) 110.65 649.33 T +0 F +0.7 (The De) 162 673.33 P +0.7 (vice De\336nition Language File or DDL File is the roadmap that CDEV uses to) 195.19 673.33 P +0.64 (associate cer) 162 661.33 P +0.64 (tain de) 221.95 661.33 P +0.64 (vice and message combinations with a CDEV ser) 252.31 661.33 P +0.64 (vice) 475.52 661.33 P +0.64 (. The DDL) 493.15 661.33 P +2.43 (\336le pro) 162 649.33 P +2.43 (vides the mechanism f) 194.29 649.33 P +2.43 (or de\336ning) 300.75 649.33 P +4 F +2.43 (ser) 355.07 649.33 P +2.43 (vice de\336nitions) 369.26 649.33 P +2.43 (, class de\336nitions) 437.12 649.33 P +0 F +2.43 ( and) 518.11 649.33 P +4 F +(instance de\336nitions) 162 637.33 T +(.) 246.89 637.33 T +2 F +-0.13 (Ser) 54 608.33 P +-0.13 (vice De\336nitions) 70.22 608.33 P +0 F +0.21 (The ser) 162 608.33 P +0.21 (vice de\336nition is used to pub) 196.41 608.33 P +0.21 (licly de\336ne the e) 322.86 608.33 P +0.21 (xistence of a CDEV ser) 394.88 608.33 P +0.21 (vice) 499.37 608.33 P +0.21 (. The) 517 608.33 P +1.76 (ser) 162 596.33 P +1.76 (vice de\336nition declares the name of the ser) 176.19 596.33 P +1.76 (vice and the names of an) 378.93 596.33 P +1.76 (y special) 499.33 596.33 P +(cde) 162 584.33 T +(vData tags that the ser) 177.82 584.33 T +(vice will use) 278.73 584.33 T +(. The f) 331.92 584.33 T +(ollo) 359.97 584.33 T +(wing is a simple ser) 375.38 584.33 T +(vice de\336nition.) 462.92 584.33 T +4 9 Q +(Figure 1: Ser) 162 551 T +(vice de\336nitions in the CDEV DDL \336le) 216.79 551 T +0 10 Q +2.68 (The ser) 162 329.52 P +2.68 (vice de\336nition abo) 198.88 329.52 P +2.68 (v) 284.14 329.52 P +2.68 (e de\336nes the ser) 288.89 329.52 P +2.68 (vice \322x\323 and ser) 371.18 329.52 P +2.68 (vice \322y\323. Dur) 447.89 329.52 P +2.68 (ing the) 507.3 329.52 P +0.26 (e) 162 317.52 P +0.26 (x) 167.26 317.52 P +0.26 (ecution of a CDEV application, when a de) 171.96 317.52 P +0.26 (vice and message combination is related) 358.05 317.52 P +1.03 (to the \322x\323 ser) 162 305.52 P +1.03 (vice) 221.52 305.52 P +1.03 (, CDEV will attempt to load the dynamic libr) 239.15 305.52 P +1.03 (ar) 439.03 305.52 P +1.03 (y f) 448.22 305.52 P +1.03 (or the ser) 459.51 305.52 P +1.03 (vice) 504.11 305.52 P +1.03 (. By) 521.74 305.52 P +0.42 (con) 162 293.52 P +0.42 (v) 177.92 293.52 P +0.42 (ention the name of the libr) 182.67 293.52 P +0.42 (ar) 300.29 293.52 P +0.42 (y will be \322xSer) 309.48 293.52 P +0.42 (vice) 373.27 293.52 P +0.42 (.so\323, where \322x\323 is the name of the) 390.89 293.52 P +(ser) 162 281.52 T +(vice within the DDL \336le) 176.19 281.52 T +(.) 277.18 281.52 T +2.25 (The ser) 162 264.53 P +2.25 (vice de\336nition also de\336nes the tags \322tag1\323 and \322tag2\323 in conjunction with) 198.45 264.53 P +0.3 (ser) 162 252.53 P +0.3 (vice \322x\323. These tags will be used later to de\336ne special ser) 176.19 252.53 P +0.3 (vice data that is related) 435.98 252.53 P +(to a speci\336c de) 162 240.53 T +(vice attr) 228.4 240.53 T +(ib) 263.56 240.53 T +(ute) 271.14 240.53 T +(. Ser) 284.89 240.53 T +(vice \322y\323 has no special tags associated with it.) 306.31 240.53 T +0.18 (This e) 162 223.53 P +0.18 (xample also illustr) 189.11 223.53 P +0.18 (ates the f) 268.83 223.53 P +0.18 (or) 310.04 223.53 P +0.18 (mats of comments within the DDL \336le) 319.18 223.53 P +0.18 (. The syntax) 485.17 223.53 P +(of the DDL \336le accommodates the use of C style m) 162 211.53 T +(ulti-line comments) 386.99 211.53 T +(.) 467.41 211.53 T +2 F +(Class De\336nitions) 54 182.53 T +0 F +2.45 (The class de\336nition is used within the DDL \336le to declare a collection of) 162 182.53 P +4 F +2.45 (v) 513.17 182.53 P +2.45 (erbs) 517.92 182.53 P +0 F +2.45 (,) 537.22 182.53 P +4 F +(attr) 162 170.53 T +(ib) 176.6 170.53 T +(utes) 184.18 170.53 T +0 F +( or) 203.08 170.53 T +4 F +(messages) 217.53 170.53 T +0 F +(that ma) 265.88 170.53 T +(y be applied to one or more CDEV de) 298.93 170.53 T +(vice instances) 464.82 170.53 T +(.) 527.47 170.53 T +2 F +(V) 54 141.53 T +(erb De\336nitions) 60.17 141.53 T +0 F +0.09 (The f) 162 141.53 P +0.09 (ollo) 184.58 141.53 P +0.09 (wing e) 199.99 141.53 P +0.09 (xamples sho) 228.68 141.53 P +0.09 (ws the syntax f) 284.76 141.53 P +0.09 (or declar) 350.88 141.53 P +0.09 (ing a class de\336nition that contains) 390.02 141.53 P +(only a list of v) 162 129.53 T +(erbs) 222.33 129.53 T +(.) 241.63 129.53 T +162 208.19 540 615 C +162 360.19 540 548 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.76 365.5 541.33 536.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +161.79 371.12 535.74 542 R +7 X +V +0 X +N +167.04 373.75 528.32 537.05 R +7 X +V +5 9 Q +0 X +(/*) 167.04 531.05 T +( * Definition of service X) 167.04 520.05 T +( */) 167.04 509.05 T +(service x) 167.04 498.05 T +({) 185.04 487.05 T +(tags { tag1, tag2 }) 185.04 476.05 T +(}) 185.04 465.05 T +(/*) 167.04 443.05 T +( * Definition of service y) 167.04 432.05 T +( */) 167.04 421.05 T +(service y) 167.04 410.05 T +({) 185.04 399.05 T +(tags {}) 185.04 388.05 T +(}) 185.04 377.05 T +403.29 508.25 526.62 524.92 R +7 X +V +0 X +N +3 F +(\322ser) 424.96 513.3 T +(vice\323 K) 443.06 513.3 T +(e) 473.94 513.3 T +(yw) 478.81 513.3 T +(or) 490.64 513.3 T +(d) 499.45 513.3 T +199.91 509.39 200.88 506.3 189.13 505.97 198.93 512.48 4 Y +0.1 H +N +199.91 509.39 200.88 506.3 189.13 505.97 198.93 512.48 4 Y +V +403.13 516.75 223.12 516.75 199.95 509.4 3 L +2 Z +N +402.96 486.08 526.29 502.75 R +7 X +V +0.5 H +0 Z +0 X +N +(Ser) 435.06 491.14 T +(vice Name) 449.66 491.14 T +236.16 496.75 235.69 493.55 224.97 498.39 236.62 499.96 4 Y +0.1 H +N +236.16 496.75 235.69 493.55 224.97 498.39 236.62 499.96 4 Y +V +402.29 493.42 258.96 493.42 236.21 496.75 3 L +2 Z +N +403.46 428.08 526.79 444.75 R +7 X +V +0.5 H +0 Z +0 X +N +(\322ta) 431.48 433.14 T +(gs\323 K) 443.89 433.14 T +(e) 467.76 433.14 T +(yw) 472.63 433.14 T +(or) 484.45 433.14 T +(d) 493.27 433.14 T +248.12 463.6 244.88 463.6 248.12 474.9 251.37 463.6 4 Y +0.1 H +N +248.12 463.6 244.88 463.6 248.12 474.9 251.37 463.6 4 Y +V +403.13 459.25 248.12 459.25 248.12 463.55 3 L +2 Z +N +209.08 467.49 207.17 464.87 199.94 474.14 210.99 470.11 4 Y +0 Z +N +209.08 467.49 207.17 464.87 199.94 474.14 210.99 470.11 4 Y +V +403.13 440.92 245.62 440.92 209.12 467.46 3 L +2 Z +N +402.54 451.55 525.88 468.22 R +7 X +V +0.5 H +0 Z +0 X +N +(List of T) 439.36 456.61 T +(a) 473.64 456.61 T +(gs) 478.55 456.61 T +162 208.19 540 615 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "2" 10 +%%Page: "3" 11 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. De) 369.68 739 T +(v) 390.92 739 T +(eloping De) 395.2 739 T +(vice De\336nition Language Files) 437.95 739 T +0 10 Q +(3) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +(Figure 2: CDEV DDL class de\336nition containing a list of v) 180 714 T +(erbs) 408.86 714 T +0 10 Q +1.19 (In the abo) 180 555.86 P +1.19 (v) 226.71 555.86 P +1.19 (e e) 231.46 555.86 P +1.19 (xample) 246.25 555.86 P +1.19 (, the \322) 278.33 555.86 P +4 F +1.19 (stdio) 306.28 555.86 P +0 F +1.19 (\323 class is de\336ned and it is declared to contain f) 327.4 555.86 P +1.19 (our) 543.55 555.86 P +1.13 (v) 180 543.86 P +1.13 (erbs:) 184.75 543.86 P +4 F +1.13 (get, set, monitorOn) 210.9 543.86 P +0 F +1.13 (and) 302.12 543.86 P +4 F +1.13 ( monitorOff) 318.8 543.86 P +1.13 (.) 369.1 543.86 P +0 F +1.13 (An) 375.79 543.86 P +1.13 (y other class that is der) 387.87 543.86 P +1.13 (iv) 496.52 543.86 P +1.13 (ed from this) 503.49 543.86 P +(class) 180 531.86 T +(, or an) 202.63 531.86 T +(y de) 230.83 531.86 T +(vice that is instantiated from this class will inher) 249.43 531.86 T +(it these f) 459.09 531.86 T +(our v) 496.59 531.86 T +(erbs) 518.57 531.86 T +(.) 537.87 531.86 T +2 F +(Class Inheritance) 72 502.86 T +0 F +-0.26 (The CDEV DDL \336le suppor) 180 502.86 P +-0.26 (ts the notion of inher) 298.83 502.86 P +-0.26 (iting one class from another class) 388.54 502.86 P +-0.26 (. The) 535.47 502.86 P +0.67 (pre-e) 180 490.86 P +0.67 (xisting class is called the) 203.04 490.86 P +4 F +0.67 (super-class) 318.66 490.86 P +0 F +0.67 (, while the class that is inher) 369.63 490.86 P +0.67 (iting from the) 498.86 490.86 P +0.04 (pre-e) 180 478.86 P +0.04 (xisting class is called the) 203.04 478.86 P +4 F +0.04 (sub-class) 315.5 478.86 P +0 F +0.04 (. T) 357.58 478.86 P +0.04 (o specify inher) 368.1 478.86 P +0.04 (itance within the CDEV DDL) 432.8 478.86 P +1.27 (\336le) 180 466.86 P +1.27 (, the syntax is similar to the syntax used in C++. The name of the ne) 192.63 466.86 P +1.27 (w class is) 512.69 466.86 P +(f) 180 454.86 T +(ollo) 182.48 454.86 T +(w) 197.89 454.86 T +(ed b) 205.01 454.86 T +(y a colon, which is f) 224.27 454.86 T +(ollo) 310.67 454.86 T +(w) 326.08 454.86 T +(ed b) 333.2 454.86 T +(y the name of the) 352.46 454.86 T +4 F +(super-class) 432.51 454.86 T +0 F +(.) 483.48 454.86 T +4 F +-0.01 (In order to suppor) 180 437.86 P +-0.01 (t the possibility of a colon as a char) 259.31 437.86 P +-0.01 (acter in the class name) 414.79 437.86 P +-0.01 (, a space) 517.43 437.86 P +(m) 180 425.86 T +(ust separ) 188.23 425.86 T +(ate the name of the class and the colon.) 229.26 425.86 T +0 F +1.76 (In the ne) 180 408.86 P +1.76 (xt e) 222.14 408.86 P +1.76 (xample) 239.73 408.86 P +1.76 (, the \322magnetIO\323 class is de\336ned. This class inher) 271.8 408.86 P +1.76 (its from the) 505.02 408.86 P +4 F +-0.04 (\322stdio\323) 180 396.86 P +0 F +-0.04 ( class) 207.78 396.86 P +-0.04 (, and receiv) 233.15 396.86 P +-0.04 (es the v) 284.51 396.86 P +-0.04 (erbs) 319.2 396.86 P +4 F +-0.04 (get, set, monitorOn, and monitorOff) 341.39 396.86 P +-0.04 (.) 497.67 396.86 P +0 F +-0.04 (T) 503.19 396.86 P +-0.04 (o this list of) 508.1 396.86 P +(v) 180 384.86 T +(erbs) 184.75 384.86 T +(, it adds a ne) 204.05 384.86 T +(w v) 261.11 384.86 T +(erb:) 275.86 384.86 T +4 F +(\322reset\323) 295.87 384.86 T +0 F +(.) 324.76 384.86 T +4 9 Q +(Figure 3: CDEV DDL class de\336nition using inher) 180 351.52 T +(itance) 374.2 351.52 T +2 10 Q +(Attrib) 72 167.22 T +(ute) 98.46 167.22 T +(De\336nitions) 72 155.22 T +0 F +0.77 (Class de\336nitions are also used to de\336ne) 180 167.22 P +4 F +0.77 (attr) 364.95 167.22 P +0.77 (ib) 379.55 167.22 P +0.77 (utes) 387.13 167.22 P +0 F +0.77 (. An attr) 405.88 167.22 P +0.77 (ib) 442.6 167.22 P +0.77 (ute is a component of a) 450.18 167.22 P +2.24 (CDEV de) 180 155.22 P +2.24 (vice that can be combined with a) 223.62 155.22 P +4 F +2.24 (v) 387.12 155.22 P +2.24 (erb) 391.87 155.22 P +0 F +2.24 ( to de\336ne a message) 406.32 155.22 P +2.24 (. When an) 507.95 155.22 P +4 F +-0.01 (attr) 180 143.22 P +-0.01 (ib) 194.6 143.22 P +-0.01 (ute) 202.18 143.22 P +0 F +-0.01 ( is declared within a class) 216.08 143.22 P +-0.01 (, CDEV will assume that the) 329.27 143.22 P +4 F +-0.01 (attr) 455.94 143.22 P +-0.01 (ib) 470.54 143.22 P +-0.01 (ute) 478.12 143.22 P +0 F +-0.01 ( suppor) 492.02 143.22 P +-0.01 (ts each) 525.77 143.22 P +(of the) 180 131.22 T +4 F +(v) 207.8 131.22 T +(erbs) 212.55 131.22 T +0 F +( that e) 232 131.22 T +(xist within the class) 259.5 131.22 T +(.) 344.93 131.22 T +180 528.52 558 720 C +180 586.52 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.64 589.33 560.22 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +180.68 593.29 554.63 705 R +7 X +V +0 X +N +185.93 597.59 547.21 700.93 R +7 X +V +5 9 Q +0 X +(class stdio) 185.93 672.93 T +({) 203.93 661.93 T +(verbs { get, set, monitorOn, monitorOff }) 203.93 650.93 T +(}) 203.93 639.93 T +420.6 681.83 543.93 698.5 R +7 X +V +0 X +N +3 F +(\322c) 446.65 686.89 T +(lass\323 K) 455.98 686.89 T +(e) 486.86 686.89 T +(yw) 491.73 686.89 T +(or) 503.55 686.89 T +(d) 512.37 686.89 T +217.21 682.97 218.19 679.88 206.43 679.55 216.23 686.06 4 Y +0.1 H +N +217.21 682.97 218.19 679.88 206.43 679.55 216.23 686.06 4 Y +V +420.43 690.33 240.43 690.33 217.26 682.99 3 L +2 Z +N +420.26 659.67 543.6 676.33 R +7 X +V +0.5 H +0 Z +0 X +N +(Class Name) 456.42 664.72 T +253.46 670.34 252.99 667.13 242.27 671.97 253.93 673.54 4 Y +0.1 H +N +253.46 670.34 252.99 667.13 242.27 671.97 253.93 673.54 4 Y +V +419.6 667 276.26 667 253.51 670.33 3 L +2 Z +N +420.76 601.67 544.1 618.33 R +7 X +V +0.5 H +0 Z +0 X +N +(\322verbs\323 K) 445.98 606.72 T +(e) 487.86 606.72 T +(yw) 492.73 606.72 T +(or) 504.55 606.72 T +(d) 513.38 606.72 T +420.43 624.5 543.76 641.17 R +7 X +V +0 X +N +(List of V) 455.06 629.55 T +(erbs) 490.12 629.55 T +311.26 637.18 308.02 637.18 311.26 648.48 314.5 637.18 4 Y +0.1 H +N +311.26 637.18 308.02 637.18 311.26 648.48 314.5 637.18 4 Y +V +420.43 632.83 311.26 632.83 311.26 637.13 3 L +2 Z +N +225.98 640.56 223.93 638.05 217.24 647.72 228.04 643.07 4 Y +0 Z +N +225.98 640.56 223.93 638.05 217.24 647.72 228.04 643.07 4 Y +V +420.43 610.33 262.93 610.33 226.02 640.53 3 L +2 Z +N +180 528.52 558 720 C +0 0 612 792 C +180 192.88 558 509.52 C +180 209.88 558 348.52 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.64 228.52 560.22 337.09 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +180.68 232.48 554.63 342.52 R +7 X +V +0 X +N +185.93 238.75 547.21 338.23 R +7 X +V +5 9 Q +0 X +(class stdio) 185.93 332.23 T +({) 203.93 321.23 T +(verbs { get, set, monitorOn, monitorOff }) 203.93 310.23 T +(}) 203.93 299.23 T +(class magnetIO : stdio) 185.93 277.23 T +({) 203.93 266.23 T +(verbs { reset }) 203.93 255.23 T +(}) 203.93 244.23 T +413.76 241.83 537.1 258.5 R +7 X +V +0 X +N +3 F +(Space Here Is Required) 425.16 246.89 T +413.43 288.83 536.76 305.5 R +7 X +V +0 X +N +(Name of Sub-Class) 434.09 293.89 T +413.93 265 537.26 281.67 R +7 X +V +0 X +N +(Name of P) 429.22 270.05 T +(arent-Class) 472.96 270.05 T +246.14 289.52 247.79 286.74 236.42 283.76 244.49 292.31 4 Y +0.1 H +N +246.14 289.52 247.79 286.74 236.42 283.76 244.49 292.31 4 Y +V +413.76 298 260.43 298 246.18 289.55 3 L +2 Z +N +272.82 269.22 271.1 266.48 263.25 275.24 274.55 271.97 4 Y +0 Z +N +272.82 269.22 271.1 266.48 263.25 275.24 274.55 271.97 4 Y +V +413.76 250.16 303.17 250.16 272.86 269.2 3 L +2 Z +N +318.08 277.26 317.62 274.32 307.82 278.86 318.54 280.2 4 Y +0.5 H +0 Z +N +318.08 277.26 317.62 274.32 307.82 278.86 318.54 280.2 4 Y +V +413.93 274 339.03 274 318.33 277.22 3 L +2 Z +N +180 192.88 558 509.52 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "3" 11 +%%Page: "4" 12 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. De) 54 739 T +(v) 75.24 739 T +(eloping De) 79.51 739 T +(vice De\336nition Language Files) 122.26 739 T +0 10 Q +(4) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Attrib) 54 713.33 T +(ute Ser) 80.46 713.33 T +(vice) 114.46 713.33 T +(Data) 54 701.33 T +0 F +0.77 (When the attr) 162 713.33 P +0.77 (ib) 223.72 713.33 P +0.77 (ute is de\336ned, the user m) 231.3 713.33 P +0.77 (ust de\336ne the name of the ser) 347.33 713.33 P +0.77 (vice that will) 484.56 713.33 P +0.27 (receiv) 162 701.33 P +0.27 (e the messages associated with it, and an) 188.42 701.33 P +0.27 (y) 375.8 701.33 P +4 F +0.27 (ser) 383.85 701.33 P +0.27 (vice data) 398.04 701.33 P +0 F +0.27 ( that is associated with) 438.33 701.33 P +1.76 (it. This ser) 162 689.33 P +1.76 (vice data is de\336ned using the tag names that are declared in the) 211.94 689.33 P +4 F +1.76 (tags) 521.1 689.33 P +0 F +(section of the ser) 162 677.33 T +(vice de\336nition.) 238.45 677.33 T +0.31 (The f) 162 660.33 P +0.31 (ollo) 184.8 660.33 P +0.31 (wing e) 200.21 660.33 P +0.31 (xample declares the class) 229.12 660.33 P +4 F +0.31 (\322element\323.) 348.19 660.33 P +0 F +0.31 (This class inher) 396.29 660.33 P +0.31 (its its v) 466.52 660.33 P +0.31 (erbs from) 497.46 660.33 P +0.53 (the) 162 648.33 P +4 F +0.53 (\322stdio\323) 179.21 648.33 P +0 F +0.53 (class) 210.3 648.33 P +0.53 (. Each attr) 232.93 648.33 P +0.53 (ib) 279.71 648.33 P +0.53 (ute is associated with a) 287.29 648.33 P +4 F +0.53 (ser) 396.09 648.33 P +0.53 (vice) 410.28 648.33 P +0 F +0.53 ( name and is f) 428.06 648.33 P +0.53 (ollo) 492.68 648.33 P +0.53 (w) 508.09 648.33 P +0.53 (ed b) 515.21 648.33 P +0.53 (y) 535 648.33 P +(ser) 162 636.33 T +(vice data.) 176.19 636.33 T +4 9 Q +(Figure 4: CDEV DDL class de\336nition containing a list of attr) 162 603 T +(ib) 399.73 603 T +(utes) 406.55 603 T +0 10 Q +1.9 (Ser) 162 204.02 P +1.9 (vice data also suppor) 177.86 204.02 P +1.9 (ts the notion of e) 278.44 204.02 P +1.9 (xpression replacement. If the char) 359.66 204.02 P +1.9 (acter) 517.77 204.02 P +0.49 (str) 162 192.02 P +0.49 (ing) 173.26 192.02 P +3 F +0.49 (\322<>\323) 189.87 192.02 P +0 F +0.49 (appears in the ser) 214.82 192.02 P +0.49 (vice data, it will be replaced with the instance name of) 296.64 192.02 P +(the de) 162 180.02 T +(vice that is instantiated from this class) 189.5 180.02 T +(.) 357.19 180.02 T +2 F +(Messa) 54 151.02 T +(g) 84.47 151.02 T +(e) 90.68 151.02 T +(De\336nitions) 54 139.02 T +0 F +0.9 (A message de\336nition can be declared within a CDEV DDL class de\336nition to de\336ne) 162 151.02 P +0.17 (one w) 162 139.02 P +0.17 (ord atomic commands) 188.75 139.02 P +0.17 (. Unlik) 287.31 139.02 P +0.17 (e attr) 315.06 139.02 P +0.17 (ib) 338.18 139.02 P +0.17 (utes and v) 345.76 139.02 P +0.17 (erbs) 391.99 139.02 P +0.17 (, a message is a stand-alone) 411.29 139.02 P +(instr) 162 127.02 T +(uction that can be sent to a de) 181.04 127.02 T +(vice) 314.72 127.02 T +(.) 332.35 127.02 T +0.5 (The str) 162 110.02 P +0.5 (ucture of a) 193.77 110.02 P +4 F +0.5 (message) 245.29 110.02 P +0 F +0.5 ( de\336nition is similar to the) 285.86 110.02 P +4 F +0.5 (attr) 403.89 110.02 P +0.5 (ib) 418.49 110.02 P +0.5 (ute) 426.07 110.02 P +0 F +0.5 ( de\336nition. The entr) 439.97 110.02 P +0.5 (ies) 527.22 110.02 P +2.54 (in this section contain the name of the ser) 162 98.02 P +2.54 (vice and special ser) 367.17 98.02 P +2.54 (vice data that is) 462.9 98.02 P +(associated with the message) 162 86.02 T +(.) 290.24 86.02 T +162 176.69 540 720 C +162 234.69 540 600 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.93 239.16 541.5 588.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +161.96 244.79 535.92 594 R +7 X +V +0 X +N +167.21 249.39 528.49 589.71 R +7 X +V +5 9 Q +0 X +(/*****************************) 167.21 583.71 T +( * Definition of service X) 167.21 572.71 T +( *****************************/) 167.21 561.71 T +(service x) 167.21 550.71 T +({) 185.21 539.71 T +(tags { tag1, tag2 }) 185.21 528.71 T +(}) 185.21 517.71 T +(/*****************************) 167.21 495.71 T +( * Definition of stdio class) 167.21 484.71 T +( *****************************/) 167.21 473.71 T +(class stdio) 167.21 462.71 T +({) 185.21 451.71 T +(verbs { get, set, monitorOn, monitorOff }) 185.21 440.71 T +(}) 185.21 429.71 T +(/*****************************) 167.21 407.71 T +( * Definition of element class) 167.21 396.71 T +( *****************************/) 167.21 385.71 T +(class element : stdio) 167.21 374.71 T +({) 185.21 363.71 T +(attributes) 185.21 352.71 T +({) 203.21 341.71 T +(value1 x {tag1=1.0, tag2=Value};) 203.21 330.71 T +(}) 203.21 319.71 T +(}) 185.21 308.71 T +382.27 407.67 520.48 425.17 R +7 X +V +0 X +N +3 F +(\322attrib) 406.52 413.14 T +(utes\323 K) 433.34 413.14 T +(e) 465.21 413.14 T +(yw) 470.08 413.14 T +(or) 481.91 413.14 T +(d) 490.73 413.14 T +381.88 378.83 520.1 396.33 R +7 X +V +0 X +N +(Attrib) 418.83 384.3 T +(ute Name) 442.64 384.3 T +382.46 270.83 520.67 288.33 R +7 X +V +0 X +N +(Name of Associated Ser) 391.25 276.3 T +(vice) 494.37 276.3 T +382.44 298.67 520.65 316.17 R +7 X +V +0 X +N +(Special Ser) 407.48 304.14 T +(vice Data) 456.1 304.14 T +251 355.18 251 352.21 240.62 355.17 250.99 358.16 4 Y +N +251 355.18 251 352.21 240.62 355.17 250.99 358.16 4 Y +V +382.21 416.83 347.55 416.83 347.55 355.33 251.25 355.18 4 L +2 Z +N +229.04 340.2 229.71 337.3 218.93 337.87 228.38 343.1 4 Y +0 Z +N +229.04 340.2 229.71 337.3 218.93 337.87 228.38 343.1 4 Y +V +381.38 387.67 355.05 387.67 355.05 352.83 283.22 352.67 229.29 340.25 5 L +2 Z +N +283.36 319.04 281.74 316.54 274.64 324.67 284.97 321.53 4 Y +0 Z +N +283.36 319.04 281.74 316.54 274.64 324.67 284.97 321.53 4 Y +V +382.21 306.83 302.21 306.83 283.57 318.9 3 L +2 Z +N +320.46 319.55 318.76 321.99 328.97 325.48 322.16 317.11 4 Y +0 Z +N +320.46 319.55 318.76 321.99 328.97 325.48 322.16 317.11 4 Y +V +302.21 306.83 320.25 319.4 2 L +2 Z +N +241.71 315.55 238.74 315.55 241.71 325.93 244.69 315.55 4 Y +0 Z +N +241.71 315.55 238.74 315.55 241.71 325.93 244.69 315.55 4 Y +V +382.21 279.33 241.71 279.33 241.71 315.3 3 L +2 Z +N +382.38 349.17 520.6 366.67 R +7 X +V +0 Z +0 X +N +(Semi-Colon Line T) 391.5 354.64 T +(erminator) 469.97 354.64 T +409.33 331.83 409.33 328.86 398.95 331.83 409.33 334.81 4 Y +N +409.33 331.83 409.33 328.86 398.95 331.83 409.33 334.81 4 Y +V +447.21 349.33 447.21 331.83 409.58 331.83 3 L +2 Z +N +162 176.69 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "4" 12 +%%Page: "5" 13 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. De) 369.68 739 T +(v) 390.92 739 T +(eloping De) 395.2 739 T +(vice De\336nition Language Files) 437.95 739 T +0 10 Q +(5) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.4 (The f) 180 713.33 P +0.4 (ollo) 202.89 713.33 P +0.4 (wing e) 218.3 713.33 P +0.4 (xample sho) 247.31 713.33 P +0.4 (ws a class that contains a single message de\336nition. Note) 298.69 713.33 P +(that the class does not de\336ne an) 180 701.33 T +(y v) 323.83 701.33 T +(erbs or attr) 336.36 701.33 T +(ib) 384.86 701.33 T +(utes) 392.44 701.33 T +(.) 411.19 701.33 T +4 9 Q +(Figure 5: CDEV DDL class de\336nition containing a list of messages) 180 668 T +2 10 Q +(De) 72 362.02 T +(vice Instances) 84.63 362.02 T +0 F +1.95 (The) 180 362.02 P +4 F +1.95 ( de) 197.23 362.02 P +1.95 (vice instances) 212.77 362.02 P +0 F +1.95 (section is where de) 282.24 362.02 P +1.95 (vices are created from class de\336nitions) 373.37 362.02 P +1.95 (.) 555.22 362.02 P +1.08 (Each de) 180 350.02 P +1.08 (vice that is instantiated from a class inher) 217.47 350.02 P +1.08 (its all of the v) 408.02 350.02 P +1.08 (erbs) 470.44 350.02 P +1.08 (, attr) 489.74 350.02 P +1.08 (ib) 510.98 350.02 P +1.08 (utes and) 518.56 350.02 P +(messages from that class) 180 338.02 T +(, as w) 293.22 338.02 T +(ell as from each class that it inher) 319.24 338.02 T +(its from.) 467.78 338.02 T +-0.05 (The syntax f) 180 321.02 P +-0.05 (or instantiating a de) 234.07 321.02 P +-0.05 (vice is as f) 320.9 321.02 P +-0.05 (ollo) 367.13 321.02 P +-0.05 (ws: the name of the class) 382.54 321.02 P +-0.05 (, f) 494.98 321.02 P +-0.05 (ollo) 502.97 321.02 P +-0.05 (w) 518.38 321.02 P +-0.05 (ed b) 525.5 321.02 P +-0.05 (y a) 544.71 321.02 P +0.07 (colon, f) 180 309.02 P +0.07 (ollo) 212.01 309.02 P +0.07 (w) 227.42 309.02 P +0.07 (ed b) 234.54 309.02 P +0.07 (y the list of de) 253.87 309.02 P +0.07 (vice names that are being de\336ned. The f) 315.55 309.02 P +0.07 (ollo) 494.17 309.02 P +0.07 (wing \336gure) 509.58 309.02 P +(sho) 180 297.02 T +(ws the syntax f) 195.97 297.02 T +(or de\336ning a list of de) 261.81 297.02 T +(vices of the) 356.56 297.02 T +4 F +(\322element) 409.92 297.02 T +0 F +(\323 class) 448.82 297.02 T +(.) 477.56 297.02 T +4 9 Q +(Figure 6: CDEV DDL class de\336nition to instantiate a list of de) 180 263.69 T +(vices) 424.33 263.69 T +180 387.69 558 720 C +180 404.69 558 665 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.29 409.16 559.86 653.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +180.32 413.95 554.27 659 R +7 X +V +0 X +N +185.57 418.56 546.85 654.71 R +7 X +V +5 9 Q +0 X +(/*****************************) 185.57 648.71 T +( * Definition of service X) 185.57 637.71 T +( *****************************/) 185.57 626.71 T +(service x) 185.57 615.71 T +({) 203.57 604.71 T +(tags { tag1, tag2 }) 203.57 593.71 T +(}) 203.57 582.71 T +(/*****************************) 185.57 560.71 T +( * Definition of element class) 185.57 549.71 T +( *****************************/) 185.57 538.71 T +(class element) 185.57 527.71 T +({) 203.57 516.71 T +(messages) 203.57 505.71 T +({) 221.57 494.71 T +(on x {tag1=<>.Val, tag2=Text};) 221.57 483.71 T +(}) 221.57 472.71 T +(}) 203.57 461.71 T +405.62 559.33 543.84 576.83 R +7 X +V +0 X +N +3 F +(\322messa) 428.53 564.8 T +(g) 460.96 564.8 T +(es\323 K) 466.55 564.8 T +(e) 489.92 564.8 T +(yw) 494.79 564.8 T +(or) 506.61 564.8 T +(d) 515.43 564.8 T +405.24 530.5 543.46 548 R +7 X +V +0 X +N +(Messa) 441.83 535.97 T +(g) 469.26 535.97 T +(e Name) 474.85 535.97 T +405.82 422.5 544.03 440 R +7 X +V +0 X +N +(Ser) 445.36 427.97 T +(vice Name) 459.96 427.97 T +405.8 450.33 544.01 467.83 R +7 X +V +0 X +N +(De) 420.2 455.8 T +(vice Name Placeholder) 431.56 455.8 T +262.19 506.86 262.2 503.89 251.81 506.83 262.18 509.84 4 Y +N +262.19 506.86 262.2 503.89 251.81 506.83 262.18 509.84 4 Y +V +405.57 568.5 378.12 568.5 378.12 507.17 262.44 506.86 4 L +2 Z +N +237.36 492.63 238.37 489.83 227.59 489.14 236.36 495.43 4 Y +0 Z +N +237.36 492.63 238.37 489.83 227.59 489.14 236.36 495.43 4 Y +V +404.74 539.33 385.57 539.33 385.57 504 270.07 504.33 237.6 492.72 5 L +2 Z +N +295.51 473.73 293.37 471.66 288.29 481.18 297.64 475.8 4 Y +0 Z +N +295.51 473.73 293.37 471.66 288.29 481.18 297.64 475.8 4 Y +V +405.57 458.5 310.26 458.5 295.68 473.55 3 L +2 Z +N +239.74 467.21 236.76 467.21 239.74 477.59 242.71 467.21 4 Y +0 Z +N +239.74 467.21 236.76 467.21 239.74 477.59 242.71 467.21 4 Y +V +405.57 431 239.74 431 239.74 466.96 3 L +2 Z +N +180 387.69 558 720 C +0 0 612 792 C +180 81 558 368.69 C +180 138.71 558 260.69 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.93 142.35 559.5 249.26 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +179.96 147.14 553.08 254.69 R +7 X +V +0 X +N +185.21 152.58 546.49 250.4 R +7 X +V +5 9 Q +0 X +(/*****************************) 185.21 244.4 T +( * Instantiation of devices) 185.21 233.4 T +( *****************************/) 185.21 222.4 T +(element :) 185.21 200.4 T +(device1) 203.21 189.4 T +(device2) 203.21 178.4 T +(device3;) 203.21 167.4 T +259.7 168.73 259.7 165.49 248.39 168.73 259.7 171.97 4 Y +0.1 H +N +259.7 168.73 259.7 165.49 248.39 168.73 259.7 171.97 4 Y +V +405.71 168.73 259.75 168.73 2 L +7 X +V +2 Z +0 X +N +259.95 182.64 260.34 179.42 248.73 181.25 259.55 185.86 4 Y +0 Z +N +259.95 182.64 260.34 179.42 248.73 181.25 259.55 185.86 4 Y +V +405.71 190.4 322.74 190.4 260 182.65 3 L +2 Z +N +259.2 202.06 259.2 198.82 247.9 202.06 259.2 205.3 4 Y +0 Z +N +259.2 202.06 259.2 198.82 247.9 202.06 259.2 205.3 4 Y +V +405.71 212.9 383.14 202.06 259.25 202.06 3 L +2 Z +N +213.42 213.17 214.9 210.29 203.38 207.98 211.93 216.05 4 Y +0 Z +N +213.42 213.17 214.9 210.29 203.38 207.98 211.93 216.05 4 Y +V +405.71 233.73 357.38 233.73 357.38 220.4 227.38 220.4 213.46 213.2 5 L +2 Z +N +405.77 203.73 543.98 221.23 R +7 X +V +0.5 H +0 Z +0 X +N +3 F +(Colon Separator) 439.87 209.2 T +405.38 182.4 543.6 199.9 R +7 X +V +0 X +N +(List of De) 442.8 187.87 T +(vices) 483.67 187.87 T +405.88 160.23 544.1 177.73 R +7 X +V +0 X +N +(Semi-Colon List T) 416.25 165.7 T +(erminator) 492.22 165.7 T +405.43 224.9 543.65 242.4 R +7 X +V +0 X +N +(Class Name to Instanciate) 418.77 230.37 T +180 81 558 368.69 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "5" 13 +%%Page: "6" 14 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. De) 54 739 T +(v) 75.24 739 T +(eloping De) 79.51 739 T +(vice De\336nition Language Files) 122.26 739 T +0 10 Q +(6) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(De) 54 713.33 T +(vice Name) 66.63 713.33 T +(Substitution) 54 701.33 T +0 F +0.93 (As descr) 162 713.33 P +0.93 (ibed ear) 201.98 713.33 P +0.93 (lier) 239.19 713.33 P +0.93 (, angle br) 252.02 713.33 P +0.93 (aces \322<>\323 in the ser) 295.46 713.33 P +0.93 (vice data de\336nition f) 385.63 713.33 P +0.93 (or an attr) 476.49 713.33 P +0.93 (ib) 518.52 713.33 P +0.93 (ute) 526.1 713.33 P +3.24 (will be replaced with the name of its associated de) 162 701.33 P +3.24 (vice) 413.23 701.33 P +3.24 (. A name substitution) 430.86 701.33 P +1.81 (technique is a) 162 689.33 P +1.81 (v) 227.12 689.33 P +1.81 (ailab) 231.87 689.33 P +1.81 (le that allo) 252.79 689.33 P +1.81 (ws the DDL wr) 301.84 689.33 P +1.81 (iter to specify that a diff) 372.43 689.33 P +1.81 (erent de) 484.02 689.33 P +1.81 (vice) 522.22 689.33 P +1.15 (name should be inser) 162 677.33 P +1.15 (ted. The substitution de) 261.46 677.33 P +1.15 (vice name is speci\336ed in conjunction) 372.5 677.33 P +(with the actual de) 162 665.33 T +(vice name when the de) 239.52 665.33 T +(vice is instanciated.) 342.05 665.33 T +0.5 (The f) 162 648.33 P +0.5 (ollo) 184.99 648.33 P +0.5 (wing e) 200.4 648.33 P +0.5 (xample illustr) 229.49 648.33 P +0.5 (ates the syntax f) 288.23 648.33 P +0.5 (or instantiating a de) 362.23 648.33 P +0.5 (vice and speci\336ng a) 450.69 648.33 P +-0.18 (substitute name f) 162 636.33 P +-0.18 (or it. In this e) 237.49 636.33 P +-0.18 (xample) 293.71 636.33 P +-0.18 (, the str) 325.79 636.33 P +-0.18 (ing \322) 358.92 636.33 P +4 F +-0.18 (de) 378.19 636.33 P +-0.18 (vice1) 389.01 636.33 P +0 F +-0.18 (\323 will be substituted where) 412.35 636.33 P +-0.18 (v) 526.36 636.33 P +-0.18 (er) 531.11 636.33 P +(the str) 162 624.33 T +(ing) 189.94 624.33 T +4 F +(\322de) 206.06 624.33 T +(v1\323) 220.21 624.33 T +0 F +( w) 234.1 624.33 T +(ould nor) 244 624.33 T +(mally be used.) 280.38 624.33 T +4 9 Q +(Figure 7: Implementing de) 162 591 T +(vice name substitution in a CDEV DDL \336le) 268.78 591 T +2 10 Q +(De) 54 423.36 T +(vice Name) 66.63 423.36 T +(Aliasing) 54 411.36 T +0 F +0.88 (De) 162 423.36 P +0.88 (vice name aliasing is a more po) 174.48 423.36 P +0.88 (w) 319.68 423.36 P +0.88 (erful alter) 326.8 423.36 P +0.88 (nativ) 369.61 423.36 P +0.88 (e to de) 390.48 423.36 P +0.88 (vice name substitution. A) 422.53 423.36 P +3.12 (de) 162 411.36 P +3.12 (vice\325) 172.82 411.36 P +3.12 (s alias ma) 192.32 411.36 P +3.12 (y be used in applications to obtain and comm) 243.26 411.36 P +3.12 (unicate with its) 468.19 411.36 P +2.33 (corresponding de) 162 399.36 P +2.33 (vice) 241.29 399.36 P +2.33 (. De) 258.92 399.36 P +2.33 (vice name aliases are speci\336ed in the DDL \336le on an) 284.39 399.36 P +(individual basis b) 162 387.36 T +(y using the) 237.94 387.36 T +4 F +(alias) 289.08 387.36 T +0 F +( k) 309.64 387.36 T +(e) 317.22 387.36 T +(yw) 322.58 387.36 T +(ord.) 334.7 387.36 T +0.47 (The syntax f) 162 370.36 P +0.47 (or adding an alias to a de) 217.1 370.36 P +0.47 (vice is illustr) 331.88 370.36 P +0.47 (ated in the e) 386.6 370.36 P +0.47 (xample belo) 442.74 370.36 P +0.47 (w) 496.96 370.36 P +0.47 (. In this) 503.58 370.36 P +1.36 (e) 162 358.36 P +1.36 (xample) 167.26 358.36 P +1.36 (, the alias) 199.34 358.36 P +4 F +1.36 (\322de) 248.99 358.36 P +1.36 (v1\323) 263.14 358.36 P +0 F +1.36 ( can be used interchangab) 277.04 358.36 P +1.36 (ly with the actual de) 400.12 358.36 P +1.36 (vice name) 493.07 358.36 P +4 F +(\322de) 162 346.36 T +(vice1\323.) 176.15 346.36 T +4 9 Q +(Figure 8: Implementing de) 162 313.02 T +(vice name aliasing in a CDEV DDL \336le) 268.78 313.02 T +2 10 Q +(De\336ning) 54 151.38 T +(cde) 54 139.38 T +(vCollections) 71.08 139.38 T +0 F +0.82 (A cde) 162 151.38 P +0.82 (vCollection de) 188.09 151.38 P +0.82 (vice can be implemented in one of tw) 251.41 151.38 P +0.82 (o w) 421.56 151.38 P +0.82 (a) 437.78 151.38 P +0.82 (ys; the de) 443.04 151.38 P +0.82 (v) 487.74 151.38 P +0.82 (eloper can) 492.49 151.38 P +-0.23 (create an empty cde) 162 139.38 P +-0.23 (vCollection dynamically and add de) 251.62 139.38 P +-0.23 (vices to it, or a collection entr) 407.13 139.38 P +-0.23 (y) 535 139.38 P +0.96 (can be placed in the CDEV DDL \336le that identi\336es the collection and its constituent) 162 127.38 P +0.82 (de) 162 115.38 P +0.82 (vices) 172.82 115.38 P +0.82 (. The syntax f) 195.45 115.38 P +0.82 (or de\336ning a cde) 257.63 115.38 P +0.82 (vCollection de) 333.71 115.38 P +0.82 (vice in the CDEV DDL \336le is as) 397.02 115.38 P +(f) 162 103.38 T +(ollo) 164.48 103.38 T +(ws) 179.89 103.38 T +(.) 191.96 103.38 T +162 449.02 540 720 C +162 466.02 540 588 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.93 469.66 541.5 576.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +161.96 474.45 535.08 582 R +7 X +V +0 X +N +167.21 479.89 528.49 577.71 R +7 X +V +5 9 Q +0 X +(/*****************************) 167.21 571.71 T +( * Device name substitution) 167.21 560.71 T +( *****************************/) 167.21 549.71 T +(element :) 167.21 527.71 T +(dev1 {device1}) 185.21 516.71 T +(device2) 185.21 505.71 T +(device3;) 185.21 494.71 T +214.07 530.42 216.16 527.94 205.44 523.12 211.98 532.89 4 Y +0.1 H +N +214.07 530.42 216.16 527.94 205.44 523.12 211.98 532.89 4 Y +V +387.71 561.04 344.17 561.04 344.17 541.41 227.07 541.41 214.11 530.45 5 L +2 Z +N +387.77 531.04 525.98 548.54 R +7 X +V +0.5 H +0 Z +0 X +N +3 F +(De) 400.18 536.51 T +(vice Name to Substitute) 411.55 536.51 T +387.43 552.21 525.65 569.71 R +7 X +V +0 X +N +(Actual De) 413.59 557.68 T +(vice Name) 454.96 557.68 T +251 527.32 251.88 524.47 241.08 524.27 250.12 530.16 4 Y +N +251 527.32 251.88 524.47 241.08 524.27 250.12 530.16 4 Y +V +388.21 540 362.21 540 362.21 532 266.21 532 251.24 527.39 5 L +2 Z +N +162 449.02 540 720 C +0 0 612 792 C +162 177.05 540 430.02 C +162 188.05 540 310.02 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.64 191.69 542.22 298.59 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.68 196.48 535.8 304.02 R +7 X +V +0 X +N +167.93 201.91 529.21 299.73 R +7 X +V +5 9 Q +0 X +(/*****************************) 167.93 293.73 T +( * Device name aliasing) 167.93 282.73 T +( *****************************/) 167.93 271.73 T +(alias dev1 device1) 167.93 216.73 T +214.78 228.44 216.88 225.97 206.15 221.14 212.69 230.91 4 Y +0.1 H +N +214.78 228.44 216.88 225.97 206.15 221.14 212.69 230.91 4 Y +V +388.43 259.07 344.89 259.07 344.89 239.43 227.78 239.43 214.82 228.47 5 L +2 Z +N +388.48 229.07 526.7 246.57 R +7 X +V +0.5 H +0 Z +0 X +N +3 F +(Actual De) 414.64 234.53 T +(vice Name) 456.01 234.53 T +388.15 250.23 526.36 267.73 R +7 X +V +0 X +N +(Alias De) 417.3 255.7 T +(vice Name) 452.68 255.7 T +251.71 225.34 252.59 222.5 241.79 222.29 250.84 228.19 4 Y +N +251.71 225.34 252.59 222.5 241.79 222.29 250.84 228.19 4 Y +V +388.93 238.02 362.93 238.02 362.93 230.02 266.93 230.02 251.95 225.42 5 L +2 Z +N +388.15 271.23 526.36 288.73 R +7 X +V +0 Z +0 X +N +(\322alias\323 K) 422.81 276.7 T +(e) 460.69 276.7 T +(yw) 465.56 276.7 T +(or) 477.38 276.7 T +(d) 486.2 276.7 T +180.93 233.28 183.9 233.28 180.93 222.91 177.95 233.28 4 Y +N +180.93 233.28 183.9 233.28 180.93 222.91 177.95 233.28 4 Y +V +387.93 281 351.93 281 305.93 247.29 180.93 247.29 180.93 233.53 5 L +2 Z +N +162 177.05 540 430.02 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "6" 14 +%%Page: "7" 15 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. De) 369.68 739 T +(v) 390.92 739 T +(eloping De) 395.2 739 T +(vice De\336nition Language Files) 437.95 739 T +0 10 Q +(7) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +(Figure 9: cde) 180 714 T +(vCollection De\336nition in the CDEV DDL File) 234.76 714 T +0 10 Q +0.64 (In the e) 180 539.48 P +0.64 (xample abo) 214.34 539.48 P +0.64 (v) 266.51 539.48 P +0.64 (e tw) 271.26 539.48 P +0.64 (o cde) 290.14 539.48 P +0.64 (vCollections are de\336ned. A cde) 314.94 539.48 P +0.64 (vCollection de\336nition is) 455.02 539.48 P +0.36 (star) 180 527.48 P +0.36 (ted b) 197.07 527.48 P +0.36 (y using the k) 219.47 527.48 P +0.36 (e) 276.47 527.48 P +0.36 (yw) 281.83 527.48 P +0.36 (ord \322) 293.95 527.48 P +3 F +0.36 (collection) 314.87 527.48 P +0 F +0.36 (\323, f) 361.55 527.48 P +0.36 (ollo) 373.27 527.48 P +0.36 (w) 388.68 527.48 P +0.36 (ed b) 395.8 527.48 P +0.36 (y a space and then the name of) 415.42 527.48 P +1.4 (the collection. Note that the name of the collection m) 180 515.48 P +1.4 (ust be unique and cannot be) 424.81 515.48 P +(shared with an) 180 503.48 T +(y other de) 244.88 503.48 T +(vice in the CDEV system.) 289.05 503.48 T +1.34 (The de) 180 486.48 P +1.34 (vice name is f) 212.17 486.48 P +1.34 (ollo) 277.03 486.48 P +1.34 (w) 292.44 486.48 P +1.34 (ed b) 299.56 486.48 P +1.34 (y a white space char) 320.16 486.48 P +1.34 (acter \050) 416.57 486.48 P +3 F +1.34 (whic) 446.26 486.48 P +1.34 (h is required) 468.39 486.48 P +0 F +1.34 (\051, and) 531.09 486.48 P +0.61 (then a colon, f) 180 474.48 P +0.61 (ollo) 244.35 474.48 P +0.61 (w) 259.76 474.48 P +0.61 (ed b) 266.88 474.48 P +0.61 (y another white space char) 286.75 474.48 P +0.61 (acter and then the list of de) 408.6 474.48 P +0.61 (vices) 532.59 474.48 P +0.61 (.) 555.22 474.48 P +1.21 (The de) 180 462.48 P +1.21 (vice names that are in the list ma) 212.04 462.48 P +1.21 (y be separ) 366.34 462.48 P +1.21 (ated b) 415.34 462.48 P +1.21 (y either white space of a) 444.14 462.48 P +3 F +(comma) 180 450.48 T +0 F +( delimiter) 215.01 450.48 T +(. The list of de) 255.07 450.48 T +(vices is ter) 317.58 450.48 T +(minated b) 365.06 450.48 T +(y a) 408.77 450.48 T +3 F +(semicolon) 424.89 450.48 T +0 F +(.) 474.35 450.48 T +1.04 (The current implementation of the CDEV DDL is order dependent. Because of this) 180 433.48 P +1.04 (,) 555.22 433.48 P +0.21 (the de) 180 421.48 P +0.21 (v) 207.71 421.48 P +0.21 (eloper should place the collection de\336nitions after the de\336nitions of all de) 212.46 421.48 P +0.21 (vices) 535.22 421.48 P +(and aliases) 180 409.48 T +(.) 230.43 409.48 T +2 F +(#inc) 72 380.48 T +(lude Directive) 91.81 380.48 T +0 F +0.27 (The) 180 380.48 P +4 F +0.27 (#include) 200.28 380.48 P +0 F +0.27 (directiv) 240.57 380.48 P +0.27 (e is suppor) 271.99 380.48 P +0.27 (ted within the CDEV DDL \336le syntax. This directiv) 321.85 380.48 P +0.27 (e is) 542.17 380.48 P +1.96 (used to include the contents of another DDL \336le within the current DDL \336le) 180 368.48 P +1.96 (. The) 533.25 368.48 P +(syntax is the same as its C language counter) 180 356.48 T +(par) 379.28 356.48 T +(t.) 394.13 356.48 T +4 9 Q +(Figure 10: Using the #include directiv) 180 323.14 T +(e in a CDEV DDL \336le) 330.34 323.14 T +180 406.14 558 720 C +180 570.14 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +187.43 574.57 551 707.43 R +7 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +0 X +N +5 9 Q +(collection cDevice1 :) 196.43 698.14 T +(device0,) 196.43 687.14 T +(device1,) 196.43 676.14 T +(device2) 196.43 665.14 T +(;) 196.43 654.14 T +(collection cDevice2 :) 196.43 632.14 T +(device3) 196.43 621.14 T +(device4) 196.43 610.14 T +(device5) 196.43 599.14 T +(;) 196.43 588.14 T +180 570.14 558 711 R +1 H +0 Z +N +180 406.14 558 720 C +0 0 612 792 C +180 81 558 387.14 C +180 284 558 320.14 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.93 288.48 557.84 308.71 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +179.96 292.43 553.08 314.14 R +7 X +V +0 X +N +185.21 297.87 546.49 309.85 R +7 X +V +5 9 Q +0 X +(#include \322filename.ddl\323) 185.21 303.85 T +180 81 558 387.14 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "7" 15 +%%Page: "8" 16 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. De) 54 739 T +(v) 75.24 739 T +(eloping De) 79.51 739 T +(vice De\336nition Language Files) 122.26 739 T +0 10 Q +(8) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Sample DDL) 54 713.33 T +0 F +3.35 (The f) 162 713.33 P +3.35 (ollo) 187.84 713.33 P +3.35 (wing sample DDL \336le demonstr) 203.24 713.33 P +3.35 (ates all current f) 354.9 713.33 P +3.35 (eatures of the De) 435.77 713.33 P +3.35 (vice) 522.22 713.33 P +(De\336nition Language) 162 701.33 T +(.) 250.79 701.33 T +4 9 Q +(Figure 11: Sample complete DDL \336le) 162 668 T +162 81 540 720 C +162 205.36 540 665 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.29 209.66 540.19 653.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.32 213.62 535.44 659 R +7 X +V +0 X +N +167.57 218.06 530.85 654.71 R +7 X +V +5 9 Q +0 X +(/*****************************************************************) 167.57 648.71 T +( * Service Definitions:) 167.57 637.71 T +( * This section contains the definitions for individual services.) 167.57 626.71 T +( *****************************************************************/) 167.57 615.71 T +(/*****************************************************************) 167.57 593.71 T +( * ca Service \050channel access\051) 167.57 582.71 T +( * The library caService.so will be loaded and called whenever a) 167.57 571.71 T +( * call to this service needs to be executed.) 167.57 560.71 T +( *) 167.57 549.71 T +( * This services support the following special tags:) 167.57 538.71 T +( * PV = Process Variable: this tag is used to specify the) 167.57 527.71 T +( * actual name of the attribute that is being) 167.57 516.71 T +( * defined.) 167.57 505.71 T +( * READONLY = This is a logical tag that indicates if the) 167.57 494.71 T +( * attribute is readonly \0501\051 or read/write \0500\051.) 167.57 483.71 T +( *****************************************************************/) 167.57 472.71 T +(service ca {) 167.57 461.71 T +(tags { PV, READONLY }) 185.57 450.71 T +(}) 185.57 439.71 T +(/*****************************************************************) 167.57 417.71 T +( * Class Definitions) 167.57 406.71 T +( * This section contains the definition for individual classes.) 167.57 395.71 T +( *****************************************************************/) 167.57 384.71 T +(/*****************************************************************) 167.57 362.71 T +( * stdio Class:) 167.57 351.71 T +( * This class defines the basic set of verbs that will be) 167.57 340.71 T +( * supported by all other classes in this DDL file. The verbs) 167.57 329.71 T +( * declared in this class are:) 167.57 318.71 T +( * get = Get the value of an attribute of a device) 167.57 307.71 T +( * set = Set the value of an attribute of a device) 167.57 296.71 T +( * monitorOn = Monitor changes of an attribute\325s value) 167.57 285.71 T +( * monitorOff = End monitoring changes of an attribute\325s value) 167.57 274.71 T +( *****************************************************************/) 167.57 263.71 T +(class stdio {) 167.57 252.71 T +(verbs { get, set, monitorOn, monitorOff }) 185.57 241.71 T +(}) 185.57 230.71 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "8" 16 +%%Page: "9" 17 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. De) 369.68 739 T +(v) 390.92 739 T +(eloping De) 395.2 739 T +(vice De\336nition Language Files) 437.95 739 T +0 10 Q +(9) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +(Figure 11: Sample complete DDL \336le \050contin) 180 714 T +(ued\051) 358.97 714 T +180 81 558 720 C +180 165.81 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.29 169.57 558.19 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +180.32 173.64 553.44 705 R +7 X +V +0 X +N +185.57 179.32 546.85 700.71 R +7 X +V +5 9 Q +0 X +(/*****************************************************************) 185.57 694.71 T +( * magnet Class:) 185.57 683.71 T +( * This class inherits its list of verbs from the stdio class. It) 185.57 672.71 T +( * then adds a list of attributes that these verbs may operate) 185.57 661.71 T +( * on. The following attributes are specified.) 185.57 650.71 T +( *) 185.57 639.71 T +( * current : The current attribute will be serviced by ca.) 185.57 628.71 T +( * bdl : The bdl attribute will be serviced by ca.) 185.57 617.71 T +( * length : The length attribute will be serviced by ca.) 185.57 606.71 T +( *) 185.57 595.71 T +( * This class also supports the messages \322on\323 and \322off\323. For) 185.57 584.71 T +( * illustration purposes, these messages will operate on the val) 185.57 573.71 T +( * field, and therefore, have the same service data.) 185.57 562.71 T +-0.52 ( *****************************************************************/) 185.57 551.71 P +(class magnet : stdio) 185.57 540.71 T +({) 203.57 529.71 T +(attributes {) 203.57 518.71 T +(current ca {PV=<>.VAL, READONLY=0};) 221.57 507.71 T +(bdl ca {PV=BDL_<>.VAL, READONLY=0};) 221.57 496.71 T +(length ca {PV=LEN_<>.VAL, READONLY=1};) 221.57 485.71 T +(}) 221.57 474.71 T +(messages {) 203.57 463.71 T +(on ca {PV=<>.VAL, READONLY=0};) 221.57 452.71 T +(off ca {PV=<>.VAL, READONLY=0};) 221.57 441.71 T +(}) 221.57 430.71 T +(}) 203.57 419.71 T +(/*****************************************************************) 185.57 397.71 T +( * Device Instances:) 185.57 386.71 T +( * This section contains the instantiations of individual devices.) 185.57 375.71 T +-0.52 ( *****************************************************************/) 185.57 364.71 P +(/*****************************************************************) 185.57 342.71 T +( * The following is a list of devices that are memebers of the) 185.57 331.71 T +( * magnet class. That means that each of these devices supports) 185.57 320.71 T +( * all of the attributes, verbs and messages that are defined by) 185.57 309.71 T +( * the magnet class and the stdio class that it inherits from.) 185.57 298.71 T +-0.52 ( *****************************************************************/) 185.57 287.71 P +(magnet :) 185.57 276.71 T +(MQB1S01) 203.57 265.71 T +(MQB1S02) 203.57 254.71 T +(MQB1S03) 203.57 243.71 T +(MQB1S04) 203.57 232.71 T +(/*****************************************************************) 185.57 210.71 T +( * End of Device Definition File) 185.57 199.71 T +-0.52 ( *****************************************************************/) 185.57 188.71 P +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "9" 17 +%%Page: "10" 18 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Using the cde) 54 739 T +(vSystem Object) 118.76 739 T +0 10 Q +(10) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(3.) 141.32 710.67 T +(Using the) 162 710.67 T +3 F +(cde) 229.68 710.67 T +(vSystem) 253.59 710.67 T +2 F +(Object) 315.06 710.67 T +2 10 Q +(Over) 54 673.33 T +(vie) 76.89 673.33 T +(w of the) 90.64 673.33 T +(cde) 54 661.33 T +(vSystem Class) 71.08 661.33 T +0 F +0.29 (The cde) 162 673.33 P +0.29 (vSystem C++ class can be descr) 198.12 673.33 P +0.29 (ibed as a comm) 345.33 673.33 P +0.29 (unications junction betw) 416.68 673.33 P +0.29 (een) 523.32 673.33 P +1.33 (a CDEV application and CDEV ser) 162 661.33 P +1.33 (vices) 322.34 661.33 P +1.33 (. The cde) 344.97 661.33 P +1.33 (vSystem object is responsib) 389.02 661.33 P +1.33 (le f) 516.74 661.33 P +1.33 (or) 531.11 661.33 P +3.7 (inter) 162 649.33 P +3.7 (preting the de) 181.75 649.33 P +3.7 (vice de\336nition \336le) 249.99 649.33 P +3.7 (, dynamically loading CDEV ser) 333.38 649.33 P +3.7 (vices upon) 488.5 649.33 P +2.38 (request, detecting and responding to I/O e) 162 637.33 P +2.38 (v) 362.77 637.33 P +2.38 (ents) 367.52 637.33 P +2.38 (, and pro) 386.27 637.33 P +2.38 (viding a mechanism f) 430.35 637.33 P +2.38 (or) 531.11 637.33 P +(polling ser) 162 625.33 T +(vices f) 207.87 625.33 T +(or updates) 235.91 625.33 T +(.) 283.01 625.33 T +2.15 (Currently) 162 608.33 P +2.15 (, only the def) 201.56 608.33 P +2.15 (ault cde) 264.96 608.33 P +2.15 (vSystem object ma) 301.83 608.33 P +2.15 (y be used within an application.) 390.3 608.33 P +2.99 (Ultimately) 162 596.33 P +2.99 (, m) 204.89 596.33 P +2.99 (ultiple cde) 221.67 596.33 P +2.99 (vSystem objects ma) 269.38 596.33 P +2.99 (y be created, and each of them will) 364.54 596.33 P +(maintain individual copies of CDEV ser) 162 584.33 T +(vices and de) 334.58 584.33 T +(vices within them.) 390.42 584.33 T +1.29 (Most CDEV classes that are accessed directly b) 162 567.33 P +1.29 (y applications ha) 383.7 567.33 P +1.29 (v) 460.56 567.33 P +1.29 (e static f) 465.31 567.33 P +1.29 (actor) 504.84 567.33 P +1.29 (ies) 527.22 567.33 P +0.39 (\050special constr) 162 555.33 P +0.39 (uctors\051. An) 227 555.33 P +0.39 (y CDEV object that is constr) 275.6 555.33 P +0.39 (ucted b) 402.2 555.33 P +0.39 (y one of these f) 435.19 555.33 P +0.39 (actor) 504.84 555.33 P +0.39 (ies) 527.22 555.33 P +(is automatically a member of the) 162 543.33 T +4 F +(def) 308.72 543.33 T +(ault) 322.32 543.33 T +0 F +( cde) 338.44 543.33 T +(vSystem.) 357.04 543.33 T +2 F +(Pub) 54 514.33 T +(lic Functions) 72.79 514.33 T +(of the) 54 502.33 T +(cde) 54 490.33 T +(vSystem Class) 71.08 490.33 T +(attac) 162 514.33 T +(hRef) 185.24 514.33 T +4 F +(static cde) 261.29 514.33 T +(vSystem& attachRef\050char *name) 303.23 514.33 T +(, char *pre\336x\051;) 448.13 514.33 T +0 F +1.82 (Obtains a ref) 261.29 497.33 P +1.82 (erence to a ne) 321.87 497.33 P +1.82 (w or e) 391.06 497.33 P +1.82 (xisting cde) 421.62 497.33 P +1.82 (vSystem object) 470.38 497.33 P +0.84 (that has the speci\336ed name) 261.43 485.33 P +0.84 (. The) 386.94 485.33 P +4 F +0.84 (pre\336x) 414.19 485.33 P +0 F +0.84 ( par) 438.64 485.33 P +0.84 (ameter is optional,) 456.62 485.33 P +0.88 (b) 261.43 473.33 P +0.88 (ut, if pro) 266.79 473.33 P +0.88 (vided will be prepended to the name of each) 304.52 473.33 P +4 F +0.88 (de) 511.4 473.33 P +0.88 (vice) 522.22 473.33 P +0 F +0.09 (that is requested through the named cde) 261.43 461.33 P +0.09 (vSystem object bef) 441.2 461.33 P +0.09 (ore) 525.55 461.33 P +(it is f) 261.43 449.33 T +(ound in the de) 281.69 449.33 T +(vice de\336nition \336le) 344.77 449.33 T +(.) 420.76 449.33 T +2 F +(attac) 162 425.33 T +(hPtr) 185.24 425.33 T +4 F +(static cde) 261.29 425.33 T +(vSystem* attachPtr\050char *name) 303.23 425.33 T +(, char *pre\336x\051;) 442.57 425.33 T +0 F +0.83 (Obtains a pointer to a ne) 261.29 408.33 P +0.83 (w or e) 374.73 408.33 P +0.83 (xisting cde) 403.32 408.33 P +0.83 (vSystem object that) 451.08 408.33 P +(has the speci\336ed name) 261.43 396.33 T +(. The) 364.11 396.33 T +4 F +(pre\336x) 389.68 396.33 T +0 F +( par) 414.13 396.33 T +(ameter is optional, b) 431.26 396.33 T +(ut, if) 521.1 396.33 T +0.65 (pro) 261.43 384.33 P +0.65 (vided will be prepended to the name of each) 275.73 384.33 P +4 F +0.65 (de) 480.63 384.33 P +0.65 (vice) 491.45 384.33 P +0 F +0.65 ( that is) 509.23 384.33 P +1.55 (requested through the named cde) 261.43 372.33 P +1.55 (vSystem object bef) 417.41 372.33 P +1.55 (ore it is) 504.68 372.33 P +(f) 261.43 360.33 T +(ound in the de) 263.91 360.33 T +(vice de\336nition \336le) 326.99 360.33 T +(.) 402.98 360.33 T +2 F +(defaultSystem) 162 336.33 T +4 F +(static cde) 261.29 336.33 T +(vSystem &def) 303.23 336.33 T +(aultSystem \050v) 364.62 336.33 T +(oid\051;) 424.94 336.33 T +0 F +0.68 (Obtains a ref) 261.29 319.33 P +0.68 (erence to the def) 319.6 319.33 P +0.68 (ault cde) 396.4 319.33 P +0.68 (vSystem object. In most) 431.8 319.33 P +0.05 (applications this mechanism is used to access the cde) 261.43 307.33 P +0.05 (vSystem) 501.66 307.33 P +(object.) 261.43 295.33 T +2 F +(g) 162 271.33 T +(etDe) 168.21 271.33 T +(vice) 189.73 271.33 T +4 F +(cde) 261.29 271.33 T +(vDe) 277.11 271.33 T +(vice* getDe) 294.59 271.33 T +(vice \050char *de) 345.42 271.33 T +(vice\051;) 406.25 271.33 T +0 F +-0.06 (Retr) 261.29 254.33 P +-0.06 (ie) 280.33 254.33 P +-0.06 (v) 287.81 254.33 P +-0.06 (es a pointer to a cde) 292.56 254.33 P +-0.06 (vDe) 382.56 254.33 P +-0.06 (vice object b) 400.04 254.33 P +-0.06 (y name) 455.3 254.33 P +-0.06 (. The object) 487.87 254.33 P +0.09 (that is retur) 261.43 242.33 P +0.09 (ned b) 311.88 242.33 P +0.09 (y this function will be o) 336.78 242.33 P +0.09 (wned and controlled b) 437.11 242.33 P +0.09 (y) 535 242.33 P +1.28 (the cde) 261.43 230.33 P +1.28 (vSystem object that created it. This means that) 295.21 230.33 P +4 F +1.28 (\337ush,) 516.1 230.33 P +1.09 (poll) 261.43 218.33 P +0 F +1.09 (and) 280.86 218.33 P +4 F +1.09 ( pend) 297.54 218.33 P +0 F +1.09 ( commands m) 323.65 218.33 P +1.09 (ust be routed through the o) 388.51 218.33 P +1.09 (wning) 513.88 218.33 P +(cde) 261.43 206.33 T +(vSystem object in order to eff) 277.25 206.33 T +(ect this cde) 406.45 206.33 T +(vDe) 456.73 206.33 T +(vice object.) 474.21 206.33 T +2 F +(g) 162 182.33 T +(etRequestObject) 168.21 182.33 T +4 F +(int getRequestObject \050) 261.29 182.33 T +(char *de) 367.86 182.33 T +(vice) 404.8 182.33 T +(, char *msg,) 422.43 182.33 T +(cde) 367.86 170.33 T +(vRequestObject &req\051;) 383.68 170.33 T +0 F +0.16 (Retr) 261.29 153.33 P +0.16 (ie) 280.33 153.33 P +0.16 (v) 287.81 153.33 P +0.16 (es a ref) 292.56 153.33 P +0.16 (erence to a cde) 325.92 153.33 P +0.16 (vRequestObject from a speci\336ed) 395.03 153.33 P +0.62 (de) 261.43 141.33 P +0.62 (vice name and message name) 272.25 141.33 P +0.62 (. The object that is produced) 410.74 141.33 P +6 (b) 261.43 129.33 P +6 (y this function will be o) 266.79 129.33 P +6 (wned and controlled b) 396.69 129.33 P +6 (y the) 512.32 129.33 P +1.1 (cde) 261.43 117.33 P +1.1 (vSystem object that created it. This means that) 277.25 117.33 P +4 F +1.1 (\337ush, poll) 496.67 117.33 P +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "10" 18 +%%Page: "11" 19 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Using the cde) 430.22 739 T +(vSystem Object) 494.98 739 T +0 10 Q +(11) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.52 (and) 279.43 713.33 P +4 F +3.52 ( pend) 296.11 713.33 P +0 F +3.52 ( commands m) 324.65 713.33 P +3.52 (ust be routed through the o) 394.37 713.33 P +3.52 (wning) 531.88 713.33 P +1.34 (cde) 279.43 701.33 P +1.34 (vSystem object in order to eff) 295.25 701.33 P +1.34 (ect this cde) 431.13 701.33 P +1.34 (vRequestObject.) 484.08 701.33 P +(Retur) 279.43 689.33 T +(ns) 304.13 689.33 T +4 F +(CDEV_SUCCESS) 317.47 689.33 T +0 F +( or an en) 399.15 689.33 T +(umer) 438.52 689.33 T +(ated error code) 461.2 689.33 T +(.) 528.86 689.33 T +2 F +(name) 180 665.33 T +4 F +(char *name \050v) 279.29 665.33 T +(oid\051;) 341.28 665.33 T +0 F +(Retur) 279.29 648.33 T +(ns the name of this cde) 303.99 648.33 T +(vSystem object.) 407.08 648.33 T +2 F +(pre\336x) 180 624.33 T +4 F +(char *pre\336x \050v) 279.29 624.33 T +(oid\051;) 340.72 624.33 T +0 F +1.5 (Retr) 279.29 607.33 P +1.5 (ie) 298.33 607.33 P +1.5 (v) 305.81 607.33 P +1.5 (es a pointer to the pre\336x str) 310.56 607.33 P +1.5 (ing that is currently being) 440.86 607.33 P +1 (used b) 279.43 595.33 P +1 (y the cde) 310.26 595.33 P +1 (vSystem object. See the) 352.54 595.33 P +4 F +1 (attachPtr) 467.17 595.33 P +0 F +1 ( entr) 507.19 595.33 P +1 (y f) 528.5 595.33 P +1 (or a) 539.77 595.33 P +(descr) 279.43 583.33 T +(iption of the pre\336x str) 304.03 583.33 T +(ing.) 397 583.33 T +2 F +(pre\336x) 180 559.33 T +4 F +(v) 279.29 559.33 T +(oid pre\336x \050char *pre\051;) 284.04 559.33 T +0 F +-0.05 (Changes the pre\336x str) 279.29 542.33 P +-0.05 (ing that is being used b) 377.1 542.33 P +-0.05 (y the cde) 479.48 542.33 P +-0.05 (vSystem) 519.66 542.33 P +1.5 (object. See the) 279.43 530.33 P +4 F +1.5 (attachPtr) 353.41 530.33 P +0 F +1.5 ( entr) 393.43 530.33 P +1.5 (y f) 415.23 530.33 P +1.5 (or a descr) 426.99 530.33 P +1.5 (iption of the pre\336x) 474.59 530.33 P +(str) 279.43 518.33 T +(ing.) 290.69 518.33 T +2 F +(\337ush) 180 494.33 T +4 F +(int \337ush \050v) 279.29 494.33 T +(oid\051;) 324.61 494.33 T +0 F +2.79 (Flushes an) 279.29 477.33 P +2.79 (y pending outbound requests to their respectiv) 330.84 477.33 P +2.79 (e) 552.44 477.33 P +(ser) 279.43 465.33 T +(vices) 293.62 465.33 T +(.) 316.25 465.33 T +2 F +(poll) 180 441.33 T +4 F +(int poll \050v) 279.29 441.33 T +(oid\051;) 319.05 441.33 T +0 F +0.4 (Directly polls each of the cde) 279.29 424.33 P +0.4 (vSystem\325) 408.79 424.33 P +0.4 (s under) 448.85 424.33 P +0.4 (lying ser) 482.75 424.33 P +0.4 (vices f) 520.67 424.33 P +0.4 (or) 549.11 424.33 P +3.66 (activity) 279.43 412.33 P +3.66 (, and deliv) 308.99 412.33 P +3.66 (ers an) 361.64 412.33 P +3.66 (y asynchronous callbac) 392.94 412.33 P +3.66 (ks that are) 503.99 412.33 P +(ready) 279.43 400.33 T +(.) 303.44 400.33 T +2 F +(pend) 180 376.33 T +4 F +(int pend \050int fd\051;) 279.29 376.33 T +0 F +0.01 (W) 279.29 359.33 P +0.01 (aits f) 288.33 359.33 P +0.01 (or a def) 309.16 359.33 P +0.01 (ault per) 342.8 359.33 P +0.01 (iod of time f) 376.31 359.33 P +0.01 (or the speci\336ed \336le descr) 427.74 359.33 P +0.01 (iptor) 538.55 359.33 P +1.27 (to ha) 279.43 347.33 P +1.27 (v) 302.74 347.33 P +1.27 (e an I/O e) 307.49 347.33 P +1.27 (v) 354.92 347.33 P +1.27 (ent. If the fd par) 359.67 347.33 P +1.27 (ameter is not pro) 434.69 347.33 P +1.27 (vided, the) 513.37 347.33 P +2.77 (cde) 279.43 335.33 P +2.77 (vSystem object will w) 295.25 335.33 P +2.77 (ait f) 397.87 335.33 P +2.77 (or an I/O e) 416.46 335.33 P +2.77 (v) 471.72 335.33 P +2.77 (ent on an) 476.47 335.33 P +2.77 (y of its) 523.56 335.33 P +0.23 (contained \336le descr) 279.43 323.33 P +0.23 (iptors) 366.19 323.33 P +0.23 (. When an e) 390.49 323.33 P +0.23 (v) 444.81 323.33 P +0.23 (ent occurs on one of the) 449.56 323.33 P +1.13 (\336le descr) 279.43 311.33 P +1.13 (iptors) 320.72 311.33 P +1.13 (, the cde) 345.02 311.33 P +1.13 (vSystem object will call the respectiv) 385.34 311.33 P +1.13 (e) 552.44 311.33 P +7.66 (cde) 279.43 299.33 P +7.66 (vSer) 295.25 299.33 P +7.66 (vice to process the e) 316.11 299.33 P +7.66 (v) 438.15 299.33 P +7.66 (ent and dispatch an) 442.9 299.33 P +7.66 (y) 553 299.33 P +(asynchronous callbac) 279.43 287.33 T +(ks that are ready) 375.38 287.33 T +(.) 448.86 287.33 T +2 F +(pend) 180 263.33 T +4 F +(int pend \050doub) 279.29 263.33 T +(le seconds) 343.02 263.33 T +(, int fd\051;) 390.67 263.33 T +0 F +0.11 (Processes all I/O e) 279.29 246.33 P +0.11 (v) 363.23 246.33 P +0.11 (ents that occur on the \336le descr) 367.98 246.33 P +0.11 (iptor dur) 507.72 246.33 P +0.11 (ing) 544.66 246.33 P +0.13 (the speci\336ed per) 279.43 234.33 P +0.13 (iod of time) 353.22 234.33 P +0.13 (. If the fd par) 399.46 234.33 P +0.13 (ameter is not pro) 456.04 234.33 P +0.13 (vided,) 531.32 234.33 P +2.61 (the cde) 279.43 222.33 P +2.61 (vSystem object will w) 314.54 222.33 P +2.61 (ait f) 416.66 222.33 P +2.61 (or I/O e) 435.09 222.33 P +2.61 (v) 473.35 222.33 P +2.61 (ents on all of its) 478.1 222.33 P +0.23 (contained \336le descr) 279.43 210.33 P +0.23 (iptors) 366.19 210.33 P +0.23 (. When an e) 390.49 210.33 P +0.23 (v) 444.81 210.33 P +0.23 (ent occurs on one of the) 449.56 210.33 P +1.13 (\336le descr) 279.43 198.33 P +1.13 (iptors) 320.72 198.33 P +1.13 (, the cde) 345.02 198.33 P +1.13 (vSystem object will call the respectiv) 385.34 198.33 P +1.13 (e) 552.44 198.33 P +7.66 (cde) 279.43 186.33 P +7.66 (vSer) 295.25 186.33 P +7.66 (vice to process the e) 316.11 186.33 P +7.66 (v) 438.15 186.33 P +7.66 (ent and dispatch an) 442.9 186.33 P +7.66 (y) 553 186.33 P +(asynchronous callbac) 279.43 174.33 T +(ks that are ready) 375.38 174.33 T +(.) 448.86 174.33 T +2 F +(g) 180 150.33 T +(etFd) 186.21 150.33 T +4 F +(int getFd \050int fd[], int &n) 279.29 150.33 T +(umFD\051;) 382.58 150.33 T +0 F +0.72 (Retr) 279.29 133.33 P +0.72 (ie) 298.33 133.33 P +0.72 (v) 305.81 133.33 P +0.72 (es a list of \336le descr) 310.56 133.33 P +0.72 (iptors that are contained within the) 402.11 133.33 P +0.16 (cde) 279.43 121.33 P +0.16 (vSystem object. The fd arr) 295.25 121.33 P +0.16 (a) 412.51 121.33 P +0.16 (y m) 417.77 121.33 P +0.16 (ust be preallocated, and the) 433.94 121.33 P +3.58 (maxim) 279.43 109.33 P +3.58 (um n) 308.77 109.33 P +3.58 (umber of elements should be speci\336ed in the) 334.48 109.33 P +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "11" 19 +%%Page: "12" 20 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Using the cde) 54 739 T +(vSystem Object) 118.76 739 T +0 10 Q +(12) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +3.91 (n) 261.43 713.33 P +3.91 (umFD par) 266.89 713.33 P +3.91 (ameter) 315.15 713.33 P +3.91 (. Upon completion, the fd arr) 345.77 713.33 P +3.91 (a) 491.37 713.33 P +3.91 (y will be) 496.63 713.33 P +3.3 (populated with the list of \336le descr) 261.43 701.33 P +3.3 (iptors) 431.43 701.33 P +3.3 (, and the n) 455.73 701.33 P +3.3 (umFD) 512.78 701.33 P +(par) 261.43 689.33 T +(ameter will contain the actual count.) 275.78 689.33 T +2 F +(ad) 162 665.33 T +(dFdChang) 173.57 665.33 T +(ed) 223.11 665.33 T +(Callbac) 234.78 665.33 T +(k) 270.15 665.33 T +4 F +(int addFdChangedCallbac) 261.29 653.33 T +(k \050cde) 376.7 653.33 T +(vFdChangedCallbac) 403.63 653.33 T +(k cbk,) 494.02 653.33 T +( v) 261.29 641.33 T +(oid*user) 393.92 641.33 T +(arg\051) 430.5 641.33 T +0 F +4.57 (Adds a ne) 261.29 624.33 P +4.57 (w function to be called each time a ser) 315.26 624.33 P +4.57 (vice) 522.22 624.33 P +1.62 (announces to the system that it has opened or closed a \336le) 261.43 612.33 P +(descr) 261.43 600.33 T +(iptor) 286.03 600.33 T +(. The function will be called with 3 arguments:) 304.98 600.33 T +4 F +( v) 261.29 583.33 T +(oid \050*cde) 268.82 583.33 T +(vFdChangedCallbac) 307.98 583.33 T +(k\051 \050int fd, int opened,) 398.37 583.33 T +( v) 261.29 571.33 T +(oid *user) 427.28 571.33 T +(arg\051) 466.64 571.33 T +0 F +0.45 (The \336rst argument speci\336es the \336le descr) 261.29 554.33 P +0.45 (iptor) 446.43 554.33 P +0.45 (, the second is 1) 465.38 554.33 P +2.08 (f) 261.43 542.33 P +2.08 (or opened, 0 f) 263.91 542.33 P +2.08 (or closed, and the last argument is the user) 331.57 542.33 P +(speci\336ed argument.) 261.43 530.33 T +2 F +(autoErr) 162 506.33 T +(orOn) 197.36 506.33 T +4 F +(int autoErrorOn \050v) 261.29 506.33 T +(oid\051;) 340.51 506.33 T +0 F +1.71 (Inf) 261.29 489.33 P +1.71 (or) 272.11 489.33 P +1.71 (ms the cde) 281.25 489.33 P +1.71 (vSystem object that it should use its inter) 333.27 489.33 P +1.71 (nal) 526.66 489.33 P +1.36 (def) 261.43 477.33 P +1.36 (ault error handler to process an) 275.03 477.33 P +1.36 (y error messages that are) 420.63 477.33 P +3.17 (gener) 261.43 465.33 P +3.17 (ated b) 286.9 465.33 P +3.17 (y objects within its control. This is the def) 317.67 465.33 P +3.17 (ault) 523.88 465.33 P +(oper) 261.43 453.33 T +(ating condition f) 281.34 453.33 T +(or the cde) 351.08 453.33 T +(vSystem object.) 395.25 453.33 T +2 F +(autoErr) 162 429.33 T +(orOff) 197.36 429.33 T +4 F +(int autoErrorOff \050v) 261.29 429.33 T +(oid\051;) 340.51 429.33 T +0 F +2.78 (Inf) 261.29 412.33 P +2.78 (or) 272.11 412.33 P +2.78 (ms the cde) 281.25 412.33 P +2.78 (vSystem object that it should use the user) 335.42 412.33 P +-0.1 (supplied error handling function to process an) 261.43 400.33 P +-0.1 (y error messages) 462.97 400.33 P +(that are gener) 261.43 388.33 T +(ated b) 323.59 388.33 T +(y objects within its control.) 351.19 388.33 T +2 F +(repor) 162 364.33 T +(tErr) 187.76 364.33 T +(or) 205.34 364.33 T +4 F +(int repor) 261.29 364.33 T +(tError \050) 298.37 364.33 T +(int se) 333.57 364.33 T +(v) 357.17 364.33 T +(er) 361.92 364.33 T +(ity) 370.96 364.33 T +(, char *name) 379.96 364.33 T +(,) 436.5 364.33 T +(cde) 333.57 352.33 T +(vRequestObject *obj,) 349.39 352.33 T +(char *f) 333.57 340.33 T +(or) 362.17 340.33 T +(matStr) 371.31 340.33 T +(ing,...\051;) 400.91 340.33 T +0 F +4.13 (Emits an error message) 261.29 323.33 P +4.13 (. The se) 379.68 323.33 P +4.13 (v) 423.77 323.33 P +4.13 (er) 428.52 323.33 P +4.13 (ity \336eld indicates the) 437.56 323.33 P +4 F +1.09 (se) 261.43 311.33 P +1.09 (v) 271.69 311.33 P +1.09 (er) 276.44 311.33 P +1.09 (ity) 285.48 311.33 P +0 F +1.09 ( of the error) 295.48 311.33 P +1.09 (, the) 349.93 311.33 P +4 F +1.09 (name) 374.34 311.33 P +0 F +1.09 ( str) 399.35 311.33 P +1.09 (ing identi\336es the object that) 414.48 311.33 P +11.86 (gener) 261.43 299.33 P +11.86 (ated the error) 286.9 299.33 P +11.86 (, the) 370.16 299.33 P +4 F +11.86 (obj) 416.13 299.33 P +0 F +11.86 (par) 444.12 299.33 P +11.86 (ameter is the) 458.47 299.33 P +1.32 (cde) 261.43 287.33 P +1.32 (vRequestObject that w) 277.25 287.33 P +1.32 (as in use when the error occurred,) 380.34 287.33 P +0.71 (and the) 261.43 275.33 P +4 F +0.71 (f) 298.99 275.33 P +0.71 (or) 301.47 275.33 P +0.71 (matStr) 310.61 275.33 P +0.71 (ing) 340.21 275.33 P +0 F +0.71 (and additional par) 357.03 275.33 P +0.71 (ameters \050...\051 should be) 437.84 275.33 P +2.71 (f) 261.43 263.33 P +2.71 (or) 263.91 263.33 P +2.71 (matted in the same manner as the par) 273.05 263.33 P +2.71 (ameters used b) 460.87 263.33 P +2.71 (y) 535 263.33 P +(pr) 261.43 251.33 T +(intf) 270.47 251.33 T +(.) 283.51 251.33 T +0.9 (The integer used b) 261.29 234.33 P +0.9 (y se) 347.16 234.33 P +0.9 (v) 366.09 234.33 P +0.9 (er) 370.84 234.33 P +0.9 (ity should ha) 379.88 234.33 P +0.9 (v) 437.61 234.33 P +0.9 (e one of the f) 442.36 234.33 P +0.9 (ollo) 504.03 234.33 P +0.9 (wing) 519.44 234.33 P +(v) 261.43 222.33 T +(alues indicating the se) 266.18 222.33 T +(v) 364.82 222.33 T +(er) 369.57 222.33 T +(ity of the error that has occurred.) 378.61 222.33 T +2 F +(CDEV_SEVERITY_INFO:) 261.29 205.33 T +0 F +(No error) 396 205.33 T +(.) 432.17 205.33 T +2 F +(CDEV_SEVERITY_W) 261.29 188.33 T +(ARN:) 358.49 188.33 T +0 F +(An error occurred that should) 396 188.33 T +(not impact contin) 396 176.33 T +(ued) 471.49 176.33 T +(processing.) 396 164.33 T +2 F +(CDEV_SEVERITY_ERR) 261.29 147.33 T +(OR:) 370.56 147.33 T +0 F +-0.36 (An error occurred and should be) 396 147.33 P +(corrected bef) 396 135.33 T +(ore contin) 454.06 135.33 T +(uing.) 497.87 135.33 T +2 F +(CDEV_SEVERITY_SEVERE:) 261.29 118.33 T +0 F +(A se) 396 118.33 T +(v) 415.71 118.33 T +(ere or f) 420.46 118.33 T +(atal error has) 451.84 118.33 T +(occurred and CDEV cannot) 396 106.33 T +(contin) 396 94.33 T +(ue nor) 422.58 94.33 T +(mal e) 451.18 94.33 T +(x) 475.33 94.33 T +(ecution.) 480.03 94.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "12" 20 +%%Page: "13" 21 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Using the cde) 430.22 739 T +(vSystem Object) 494.98 739 T +0 10 Q +(13) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(setErr) 180 713.33 T +(orHandler) 208.7 713.33 T +4 F +(v) 279.29 713.33 T +(oid setErrorHandler \050cde) 284.04 713.33 T +(vErrorHandler handler\051;) 392.66 713.33 T +0 F +2.41 (Used to to install a user speci\336ed error handler) 279.29 696.33 P +2.41 (. This error) 504.84 696.33 P +0.68 (handler will be called when an error occurs if the) 279.43 684.33 P +4 F +0.68 (autoErrorOff) 502.98 684.33 P +0 F +0 (method has been used to disab) 279.43 672.33 P +0 (le the def) 418.75 672.33 P +0 (ault error handler) 459.58 672.33 P +0 (. The) 535.21 672.33 P +6.28 (user pro) 279.43 660.33 P +6.28 (vided error handler should ha) 322.24 660.33 P +6.28 (v) 477.22 660.33 P +6.28 (e the f) 481.97 660.33 P +6.28 (ollo) 522.03 660.33 P +6.28 (wing) 537.44 660.33 P +(prototype:) 279.43 648.33 T +4 F +(v) 279.29 631.33 T +(oid handler \050int se) 284.04 631.33 T +(v) 363.22 631.33 T +(er) 367.97 631.33 T +(ity) 377.01 631.33 T +(, char *te) 386.01 631.33 T +(xt, cde) 425.73 631.33 T +(vRequestObject *obj\051;) 454.89 631.33 T +0 F +4.89 (The) 279.29 614.33 P +4 F +4.89 (se) 304.19 614.33 P +4.89 (v) 314.45 614.33 P +4.89 (er) 319.2 614.33 P +4.89 (ity) 328.24 614.33 P +0 F +4.89 ( par) 338.24 614.33 P +4.89 (ameter will contain one of the integers) 360.26 614.33 P +0.81 (speci\336ed in the) 279.43 602.33 P +4 F +0.81 (repor) 351.34 602.33 P +0.81 (tError) 375.08 602.33 P +0 F +0.81 (documentation, the) 403.67 602.33 P +4 F +0.81 (te) 493.12 602.33 P +0.81 (xt) 501.16 602.33 P +0 F +0.81 ( par) 508.94 602.33 P +0.81 (ameter) 526.88 602.33 P +2.11 (will contain the te) 279.43 590.33 P +2.11 (xt of the error) 362.17 590.33 P +2.11 (, and the) 427.48 590.33 P +4 F +2.11 (obj) 475.52 590.33 P +0 F +2.11 ( par) 488.86 590.33 P +2.11 (ameter will) 508.11 590.33 P +0.37 (contain the cde) 279.43 578.33 P +0.37 (vRequestObject that w) 347.69 578.33 P +0.37 (as in use when the error) 448.88 578.33 P +(occurred.) 279.43 566.33 T +2 F +(setThreshold) 180 542.33 T +4 F +(v) 279.29 542.33 T +(oid setThreshold \050int errorThreshold\051;) 284.04 542.33 T +0 F +0.77 (Used to specify the le) 279.29 525.33 P +0.77 (v) 377.66 525.33 P +0.77 (el of se) 382.41 525.33 P +0.77 (v) 415.88 525.33 P +0.77 (er) 420.63 525.33 P +0.77 (ity at which errors should be) 429.67 525.33 P +2.4 (submitted to the error handler) 279.43 513.33 P +2.4 (. The v) 419.71 513.33 P +2.4 (alue of) 454.83 513.33 P +4 F +2.4 (errorThreshold) 492.43 513.33 P +0 F +0.23 (should be one of the se) 279.43 501.33 P +0.23 (v) 384.26 501.33 P +0.23 (er) 389.01 501.33 P +0.23 (ity le) 398.05 501.33 P +0.23 (v) 418.54 501.33 P +0.23 (els speci\336ed in the) 423.29 501.33 P +4 F +0.23 (repor) 509.26 501.33 P +0.23 (tError) 533 501.33 P +0 F +(method.) 279.43 489.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "13" 21 +%%Page: "14" 22 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Using the cde) 54 739 T +(vSystem Object) 118.76 739 T +0 10 Q +(14) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Sample Code) 54 713.33 T +0 F +1.57 (The f) 162 713.33 P +1.57 (ollo) 186.06 713.33 P +1.57 (wing sample application sho) 201.47 713.33 P +1.57 (ws the use of the three methods f) 331.07 713.33 P +1.57 (or obtain a) 489.61 713.33 P +-0.15 (cde) 162 701.33 P +-0.15 (vSystem object. F) 177.82 701.33 P +-0.15 (or e) 256.69 701.33 P +-0.15 (xamples of ho) 273.47 701.33 P +-0.15 (w to use the \337ush, poll and pend methods) 335.27 701.33 P +-0.15 (, see) 518.47 701.33 P +(the documentation f) 162 689.33 T +(or the cde) 249.53 689.33 T +(vDe) 293.7 689.33 T +(vice object.) 311.18 689.33 T +4 9 Q +(Figure 12: Methods f) 162 656 T +(or obtaining a cde) 246.77 656 T +(vSystem object) 318.04 656 T +0 10 Q +2.9 (The f) 162 221.33 P +2.9 (ollo) 187.39 221.33 P +2.9 (wing sample application illustr) 202.8 221.33 P +2.9 (ates ho) 343.66 221.33 P +2.9 (w to install a user speci\336ed error) 379.21 221.33 P +(handler into the def) 162 209.33 T +(ault cde) 247.31 209.33 T +(vSystem object.) 282.03 209.33 T +162 81 540 720 C +162 235 540 653 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.64 230 542.22 645.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.68 240.41 537.23 650.57 R +7 X +V +0 X +N +167.93 242.55 532.54 646.23 R +7 X +V +5 9 Q +0 X +(#include ) 167.93 640.23 T +(void main\050\051) 167.93 618.23 T +({) 185.93 607.23 T +(// ************************************************************) 185.93 596.23 T +(// * The first and most common approach is to directly request) 185.93 585.23 T +(// *) 185.93 574.23 T +(a reference to the default cdevSystem.) 207.53 574.23 T +(// ************************************************************) 185.93 563.23 T +(cdevSystem & default = cdevSystem::defaultSystem\050\051;) 185.93 552.23 T +(// ************************************************************) 185.93 530.23 T +(// * Get a pointer to the name of the default cdevSystem.) 185.93 519.23 T +(// ************************************************************) 185.93 508.23 T +(char * sysName = default.name\050\051;) 185.93 497.23 T +(// ************************************************************) 185.93 475.23 T +(// * Use the attachRef method to obtain a reference to the) 185.93 464.23 T +(// * default cdevSystem by name.) 185.93 453.23 T +(// ************************************************************) 185.93 442.23 T +(cdevSystem & default2 = cdevSystem::attachRef\050sysName\051;) 185.93 431.23 T +(// ************************************************************) 185.93 409.23 T +(// * Finally, use the attachPtr method to obtain a pointer to) 185.93 398.23 T +(// * the default cdevSystem by name. Additionally, set the) 185.93 387.23 T +(// * prefix for the default system to \322TEST\323.) 185.93 376.23 T +(// ************************************************************) 185.93 365.23 T +(cdevSystem * default3 = cdevSystem::attachPtr\050sysName, \322TEST\323\051;) 185.93 354.23 T +(// ************************************************************) 185.93 332.23 T +(// * Output the name and prefix for all three systems.) 185.93 321.23 T +(// ************************************************************) 185.93 310.23 T +(printf\050\322%s:%s\134n\323, default.name\050\051, default.prefix\050\051\051;) 185.93 299.23 T +(printf\050\322%s:%s\134n\323, default1.name\050\051, default1.prefix\050\051\051;) 185.93 288.23 T +(printf\050\322%s:%s\134n\323, default2->name\050\051, default2->prefix\050\051\051;) 185.93 277.23 T +(}) 185.93 266.23 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "14" 22 +%%Page: "15" 23 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Using the cde) 430.22 739 T +(vSystem Object) 494.98 739 T +0 10 Q +(15) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +(Figure 13: Installing a user speci\336ed error handler) 180 714 T +180 81 558 720 C +180 325.33 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.93 331.95 559.5 703.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +179.96 336.74 553.92 708.57 R +7 X +V +0 X +N +185.21 340.02 546.49 703.38 R +7 X +V +5 9 Q +0 X +(#include ) 185.21 697.38 T +-0.52 (// ****************************************************************) 185.21 675.38 P +(// * This the default error handler. It simply outputs the error.) 185.21 664.38 T +-0.52 (// ****************************************************************) 185.21 653.38 P +(void myHandler\050int severity, char *text, cdevRequestObject &obj\051) 185.21 642.38 T +({) 203.21 631.38 T +(if\050severity>0\051) 203.21 620.38 T +({) 221.21 609.38 T +(fprintf\050stderr, \322ERROR \050%i\051: %s\134n\323, severity, text\051;) 221.21 598.38 T +(}) 221.21 587.38 T +(else) 203.21 576.38 T +( fprintf\050INFORMATION: %s\134n\323, text\051;) 224.82 576.38 T +(}) 203.21 565.38 T +(void main\050\051) 185.21 543.38 T +({) 203.21 532.38 T +(// ************************************************************) 203.21 521.38 T +(// * Obtain a reference to the default cdevSystem.) 203.21 510.38 T +(// ************************************************************) 203.21 499.38 T +(cdevSystem & default = cdevSystem::defaultSystem\050\051;) 203.21 488.38 T +(// ************************************************************) 203.21 466.38 T +(// * Call the setErrorHandler method to install the new) 203.21 455.38 T +(// * errorHandler.) 203.21 444.38 T +(// ************************************************************) 203.21 433.38 T +(default.setErrorHandler\050myHandler\051;) 203.21 422.38 T +(// ************************************************************) 203.21 400.38 T +(// * Turn off auto error handling to tell the system to use) 203.21 389.38 T +(// * the new user specified error handing function.) 203.21 378.38 T +(// ************************************************************) 203.21 367.38 T +(default.autoErrorOff\050\051;) 203.21 356.38 T +(}) 203.21 345.38 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "15" 23 +%%Page: "16" 24 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. Using the cde) 54 739 T +(vDe) 118.76 739 T +(vice Object) 134.5 739 T +0 10 Q +(16) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(4.) 141.32 710.67 T +(Using the) 162 710.67 T +3 F +(cde) 229.68 710.67 T +(vDe) 253.59 710.67 T +(vice) 279.05 710.67 T +2 F +(Object) 310.19 710.67 T +2 10 Q +(Over) 54 673.33 T +(vie) 76.89 673.33 T +(w of the) 90.64 673.33 T +(cde) 54 661.33 T +(vDe) 71.08 661.33 T +(vice Class) 89.27 661.33 T +0 F +2.37 (The cde) 162 673.33 P +2.37 (vDe) 200.2 673.33 P +2.37 (vice C++ class is the user\325) 217.68 673.33 P +2.37 (s pr) 345.17 673.33 P +2.37 (imar) 364.36 673.33 P +2.37 (y interf) 384.1 673.33 P +2.37 (ace to CDEV) 416.18 673.33 P +2.37 (. In f) 477.46 673.33 P +2.37 (act, it is) 501.36 673.33 P +-0.22 (possib) 162 661.33 P +-0.22 (le to de) 190.7 661.33 P +-0.22 (v) 222.76 661.33 P +-0.22 (elop complete CDEV applications using only cde) 227.51 661.33 P +-0.22 (vDe) 441 661.33 P +-0.22 (vice and cde) 458.48 661.33 P +-0.22 (vData) 513.88 661.33 P +1.22 (objects) 162 649.33 P +1.22 (. The cde) 193.53 649.33 P +1.22 (vDe) 237.36 649.33 P +1.22 (vice class de\336nes the basic interf) 254.84 649.33 P +1.22 (ace that all applications m) 406.82 649.33 P +1.22 (ust) 526.66 649.33 P +(use to tr) 162 637.33 T +(ansmit messages to a CDEV ser) 198.03 637.33 T +(vice) 342.82 637.33 T +(.) 360.45 637.33 T +3.33 (A cde) 162 620.33 P +3.33 (vDe) 190.6 620.33 P +3.33 (vice ma) 208.08 620.33 P +3.33 (y be created using the static member functions) 245.56 620.33 P +3 F +3.33 (attac) 481.76 620.33 P +3.33 (hPtr) 505 620.33 P +0 F +3.33 ( or) 525 620.33 P +3 F +1.84 (attac) 162 608.33 P +1.84 (hRef) 185.24 608.33 P +0 F +1.84 (. If one of these methods is used, the de) 207.16 608.33 P +1.84 (vice will be created within the) 401.31 608.33 P +-0.07 (conte) 162 596.33 P +-0.07 (xt of the def) 186.16 596.33 P +-0.07 (ault) 237.91 596.33 P +4 F +-0.07 (cde) 256.74 596.33 P +-0.07 (vSystem) 272.56 596.33 P +0 F +-0.07 (. If the application wishes to create a de) 310.9 596.33 P +-0.07 (vice within a) 485.68 596.33 P +0.53 (cde) 162 584.33 P +0.53 (vSystem other than the def) 177.82 584.33 P +0.53 (ault, it m) 299.15 584.33 P +0.53 (ust use the) 337.9 584.33 P +3 F +0.53 (g) 391.19 584.33 P +0.53 (etDe) 397.4 584.33 P +0.53 (vice) 418.92 584.33 P +0 F +0.53 ( method of the desired) 438.38 584.33 P +(cde) 162 572.33 T +(vSystem object.) 177.82 572.33 T +1.31 (A cde) 162 555.33 P +1.31 (vDe) 188.58 555.33 P +1.31 (vice object is bound b) 206.06 555.33 P +1.31 (y name to a speci\336c de) 307.27 555.33 P +1.31 (vice when it is instantiated.) 415.81 555.33 P +1.23 (Ho) 162 543.33 P +1.23 (w) 174.63 543.33 P +1.23 (e) 181.75 543.33 P +1.23 (v) 187.01 543.33 P +1.23 (er) 191.76 543.33 P +1.23 (, the under) 200.15 543.33 P +1.23 (lying ser) 250.56 543.33 P +1.23 (vice is not selected until a message is speci\336ed with a) 289.32 543.33 P +3 F +0.46 (send) 162 531.33 P +0 F +0.46 ( command. Theref) 185.34 531.33 P +0.46 (ore) 267.11 531.33 P +0.46 (, simply creating a de) 281.4 531.33 P +0.46 (vice does not ensure that the de) 377.43 531.33 P +0.46 (vice) 522.22 531.33 P +(name is v) 162 519.33 T +(alid, nor that it suppor) 204.54 519.33 T +(ts a giv) 301.1 519.33 T +(en message) 332.53 519.33 T +(.) 386.85 519.33 T +1.13 (Messages ma) 162 502.33 P +1.13 (y be sent to a de) 225.07 502.33 P +1.13 (vice using one of the three send member functions) 304.35 502.33 P +1.13 (,) 537.22 502.33 P +0.82 (these are:) 162 490.33 P +3 F +0.82 (send, sendNoBloc) 210.9 490.33 P +0.82 (k) 298.76 490.33 P +4 F +0.82 (, and) 304.32 490.33 P +3 F +0.82 (sendCallbac) 330.98 490.33 P +0.82 (k) 389.7 490.33 P +0 F +0.82 (. The syntax and functionality of) 395.26 490.33 P +(these methods is descr) 162 478.33 T +(ibed in the section belo) 264.97 478.33 T +(w) 367.1 478.33 T +(.) 373.72 478.33 T +2.48 (Input and output to the speci\336ed send methods is managed through the use of) 162 461.33 P +0.57 (cde) 162 449.33 P +0.57 (vData objects) 177.82 449.33 P +0.57 (. Unlik) 238.82 449.33 P +0.57 (e the cde) 266.98 449.33 P +0.57 (vDe) 308.96 449.33 P +0.57 (vice object which is bound to a speci\336c system,) 326.44 449.33 P +0.76 (the cde) 162 437.33 P +0.76 (vData object is completely independent. These objects store the data v) 195.26 437.33 P +0.76 (alues) 516.1 437.33 P +1.21 (\050called) 162 425.33 P +4 F +1.21 (proper) 195.44 425.33 P +1.21 (ties) 224.74 425.33 P +0 F +1.21 (\051 that are sent to and receiv) 240.3 425.33 P +1.21 (ed from de) 369.06 425.33 P +1.21 (vices) 418.99 425.33 P +1.21 (. The application ma) 441.62 425.33 P +1.21 (y) 535 425.33 P +0.47 (indicate the) 162 413.33 P +4 F +0.47 (proper) 216.85 413.33 P +0.47 (ties) 246.15 413.33 P +0 F +0.47 ( that it wishes to receiv) 261.71 413.33 P +0.47 (e as output from the cde) 364.94 413.33 P +0.47 (vDe) 474.81 413.33 P +0.47 (vice object) 492.29 413.33 P +(b) 162 401.33 T +(y specifying them in a special cde) 167.36 401.33 T +(vData object called the) 316.01 401.33 T +4 F +(conte) 419.95 401.33 T +(xt) 444.11 401.33 T +0 F +(.) 451.89 401.33 T +0.28 (Examples at the end of this section will illustr) 162 384.33 P +0.28 (ate the correct w) 362.01 384.33 P +0.28 (a) 436.63 384.33 P +0.28 (ys to implement these) 441.89 384.33 P +(oper) 162 372.33 T +(ations) 181.91 372.33 T +(.) 208.44 372.33 T +2 F +(Pub) 54 343.33 T +(lic Functions) 72.79 343.33 T +(of the cde) 54 331.33 T +(vDe) 101.08 331.33 T +(vice) 119.27 331.33 T +(Class) 54 319.33 T +(attac) 162 343.33 T +(hRef) 185.24 343.33 T +4 F +(static cde) 261.29 343.33 T +(vDe) 303.23 343.33 T +(vice& attachRef \050char *name\051;) 320.71 343.33 T +0 F +3.38 (Obtains a ref) 261.29 326.33 P +3.38 (erence to a cde) 324.99 326.33 P +3.38 (vDe) 403.76 326.33 P +3.38 (vice object b) 421.24 326.33 P +3.38 (y name) 483.37 326.33 P +3.38 (. By) 519.39 326.33 P +4.63 (def) 261.43 314.33 P +4.63 (ault, the ne) 275.03 314.33 P +4.63 (w object will be managed b) 333.57 314.33 P +4.63 (y the def) 476.56 314.33 P +4.63 (ault) 523.88 314.33 P +(cde) 261.43 302.33 T +(vSystem.) 277.25 302.33 T +2 F +(attac) 162 278.33 T +(hPtr) 185.24 278.33 T +4 F +(static cde) 261.29 278.33 T +(vDe) 303.23 278.33 T +(vice* attachPtr \050char *name\051;) 320.71 278.33 T +0 F +-0.05 (Obtains a pointer to a cde) 261.29 261.33 P +-0.05 (vDe) 375.26 261.33 P +-0.05 (vice object speci\336ed b) 392.74 261.33 P +-0.05 (y name) 490.22 261.33 P +-0.05 (. By) 522.82 261.33 P +4.63 (def) 261.43 249.33 P +4.63 (ault, the ne) 275.03 249.33 P +4.63 (w object will be managed b) 333.57 249.33 P +4.63 (y the def) 476.56 249.33 P +4.63 (ault) 523.88 249.33 P +(cde) 261.43 237.33 T +(vSystem.) 277.25 237.33 T +2 F +(detac) 162 213.33 T +(h) 188.02 213.33 T +4 F +(static v) 261.29 213.33 T +(oid detach \050cde) 292.16 213.33 T +(vDe) 360.23 213.33 T +(vice& de) 377.71 213.33 T +(v\051;) 415.76 213.33 T +0 F +1.26 (Remo) 261.29 196.33 P +1.26 (v) 287.81 196.33 P +1.26 (es a ref) 292.56 196.33 P +1.26 (erenced cde) 328.12 196.33 P +1.26 (vDe) 384.11 196.33 P +1.26 (vice object from its associated) 401.59 196.33 P +-0.22 (cde) 261.43 184.33 P +-0.22 (vSystem object. Ordinar) 277.25 184.33 P +-0.22 (y applications should ne) 383.81 184.33 P +-0.22 (v) 489.56 184.33 P +-0.22 (er use this) 494.31 184.33 P +(command.) 261.43 172.33 T +2 F +(detac) 162 148.33 T +(h) 188.02 148.33 T +4 F +(static v) 261.29 148.33 T +(oid detach \050cde) 292.16 148.33 T +(vDe) 360.23 148.33 T +(vice* de) 377.71 148.33 T +(v\051;) 412.98 148.33 T +0 F +3.37 (Detaches the cde) 261.29 131.33 P +3.37 (vDe) 345.54 131.33 P +3.37 (vice object speci\336ed b) 363.02 131.33 P +3.37 (y de) 470.74 131.33 P +3.37 (v from its) 492.71 131.33 P +2.47 (associated cde) 261.43 119.33 P +2.47 (vSystem object. Ordinar) 330.3 119.33 P +2.47 (y applications should) 442.24 119.33 P +(ne) 261.43 107.33 T +(v) 272.25 107.33 T +(er use this command.) 277 107.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "16" 24 +%%Page: "17" 25 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. Using the cde) 432.99 739 T +(vDe) 497.75 739 T +(vice Object) 513.49 739 T +0 10 Q +(17) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(g) 180 713.33 T +(etRequestObject) 186.21 713.33 T +4 F +(cde) 279.29 713.33 T +(vRequestObject* getRequestObject \050char *msg\051;) 295.11 713.33 T +0 F +1.66 (Obtains a ser) 279.29 696.33 P +1.66 (vice speci\336c request object. This function uses) 342.38 696.33 P +0.48 (the name of the de) 279.43 684.33 P +0.48 (vice speci\336ed within the cde) 364.45 684.33 P +0.48 (vDe) 490.02 684.33 P +0.48 (vice object,) 507.5 684.33 P +1.94 (and the message pro) 279.43 672.33 P +1.94 (vided b) 379.04 672.33 P +1.94 (y the caller to deter) 413.01 672.33 P +1.94 (mine which) 506.05 672.33 P +0.31 (CDEV ser) 279.43 660.33 P +0.31 (vice will be used to ser) 324.5 660.33 P +0.31 (vice this request. The ser) 426.95 660.33 P +0.31 (vice) 540.22 660.33 P +1.44 (is then loaded \050if necessar) 279.43 648.33 P +1.44 (y\051, and is contacted to pro) 402.21 648.33 P +1.44 (vided a) 524.32 648.33 P +4.84 (request object f) 279.43 636.33 P +4.84 (or the de) 357.19 636.33 P +4.84 (vice/message combination. This) 406.04 636.33 P +0.48 (cde) 279.43 624.33 P +0.48 (vRequestObject will then be used to comm) 295.25 624.33 P +0.48 (unicate with the) 487.56 624.33 P +(ser) 279.43 612.33 T +(vice directly) 293.62 612.33 T +(.) 344.85 612.33 T +2 F +(name) 180 588.33 T +4 F +(const char *name \050v) 279.29 588.33 T +(oid\051 const;) 367.96 588.33 T +0 F +(Retur) 279.29 571.33 T +(ns the name of the de) 303.99 571.33 T +(vice) 400.42 571.33 T +(.) 418.05 571.33 T +2 F +(system) 180 547.33 T +4 F +(cde) 279.29 547.33 T +(vSystem& system \050v) 295.11 547.33 T +(oid\051 const;) 385.43 547.33 T +0 F +1.06 (Obtains a ref) 279.29 530.33 P +1.06 (erence to the under) 338.36 530.33 P +1.06 (lying cde) 428.4 530.33 P +1.06 (vSystem object that) 468.62 530.33 P +(manages this de) 279.43 518.33 T +(vice) 352.5 518.33 T +(.) 370.13 518.33 T +2 F +(setConte) 180 494.33 T +(xt) 222.63 494.33 T +4 F +(int setConte) 279.29 494.33 T +(xt \050cde) 332.35 494.33 T +(vData& cxt\051;) 362.06 494.33 T +0 F +0.17 (Used to inser) 279.29 477.33 P +0.17 (t a cde) 338.93 477.33 P +0.17 (vData object containing tagged v) 368.98 477.33 P +0.17 (alues that) 514.47 477.33 P +0.16 (control optional beha) 279.43 465.33 P +0.16 (vior of the under) 372.38 465.33 P +0.16 (lying de) 445.28 465.33 P +0.16 (vice) 479.6 465.33 P +0.16 (. The conte) 497.23 465.33 P +0.16 (xt) 550.22 465.33 P +4.55 (is often used to specify which proper) 279.43 453.33 P +4.55 (ties \050v) 468.86 453.33 P +4.55 (alue) 499.83 453.33 P +4.55 (, status) 518.58 453.33 P +4.55 (,) 555.22 453.33 P +0.52 (se) 279.43 441.33 P +0.52 (v) 289.69 441.33 P +0.52 (er) 294.44 441.33 P +0.52 (ity\051 a de) 303.48 441.33 P +0.52 (vice retur) 339.79 441.33 P +0.52 (ns in response to a \322get\323 message) 381.68 441.33 P +0.52 (. It is) 535.84 441.33 P +1.78 (impor) 279.43 429.33 P +1.78 (tant to note that an) 304.83 429.33 P +1.78 (y change made to the conte) 395.2 429.33 P +1.78 (xt of a) 527.2 429.33 P +4 F +9.76 (cde) 279.43 417.33 P +9.76 (vDe) 295.25 417.33 P +9.76 (vice) 312.73 417.33 P +0 F +9.76 ( will automatically be propagated to all) 330.51 417.33 P +4 F +1.17 (cde) 279.43 405.33 P +1.17 (vRequestObjects) 295.25 405.33 P +0 F +1.17 ( created from that de) 371.39 405.33 P +1.17 (vice) 468.04 405.33 P +1.17 (. Theref) 485.67 405.33 P +1.17 (ore) 521 405.33 P +1.17 (, an) 535.3 405.33 P +1.17 (y) 553 405.33 P +1.01 (message speci\336c conte) 279.43 393.33 P +1.01 (xt settings should be speci\336ed directly) 385.09 393.33 P +(to the cde) 279.43 381.33 T +(vRequestObject, r) 323.05 381.33 T +(ather than to the cde) 402.98 381.33 T +(vDe) 494.41 381.33 T +(vice) 511.89 381.33 T +(.) 529.52 381.33 T +2 F +(g) 180 357.33 T +(etConte) 186.21 357.33 T +(xt) 223.28 357.33 T +4 F +(cde) 279.29 357.33 T +(vData & getConte) 295.11 357.33 T +(xt \050v) 373.74 357.33 T +(oid\051;) 392.38 357.33 T +0 F +0.63 (Retr) 279.29 340.33 P +0.63 (ie) 298.33 340.33 P +0.63 (v) 305.81 340.33 P +0.63 (es a ref) 310.56 340.33 P +0.63 (erence to the cde) 344.87 340.33 P +0.63 (vData object that contains the) 423.73 340.33 P +(conte) 279.43 328.33 T +(xt f) 303.59 328.33 T +(or a speci\336c de) 316.63 328.33 T +(vice) 383.58 328.33 T +(.) 401.21 328.33 T +2 F +(setPriv) 180 304.33 T +(ate) 213.15 304.33 T +4 F +(v) 279.29 304.33 T +(oid setPr) 284.04 304.33 T +(iv) 323.65 304.33 T +(ate \050v) 330.62 304.33 T +(oid * data\051;) 355.38 304.33 T +0 F +1.64 (Associates a user speci\336ed data object with this cde) 279.29 287.33 P +1.64 (vDe) 522.74 287.33 P +1.64 (vice) 540.22 287.33 P +0.93 (object. The pointer can be retr) 279.43 275.33 P +0.93 (ie) 417.64 275.33 P +0.93 (v) 425.12 275.33 P +0.93 (ed later using the) 429.87 275.33 P +4 F +0.93 (getPr) 513.08 275.33 P +0.93 (iv) 537.13 275.33 P +0.93 (ate) 544.1 275.33 P +0 F +(method.) 279.43 263.33 T +2 F +(g) 180 239.33 T +(etPriv) 186.21 239.33 T +(ate) 213.8 239.33 T +4 F +(v) 279.29 239.33 T +(oid * getPr) 284.04 239.33 T +(iv) 330.88 239.33 T +(ate \050v) 337.85 239.33 T +(oid\051;) 362.61 239.33 T +0 F +2.09 (Retr) 279.29 222.33 P +2.09 (ie) 298.33 222.33 P +2.09 (v) 305.81 222.33 P +2.09 (es a pointer to a data object that w) 310.56 222.33 P +2.09 (as placed in this) 480.02 222.33 P +(cde) 279.43 210.33 T +(vDe) 295.25 210.33 T +(vice object using the setPr) 312.73 210.33 T +(iv) 429.6 210.33 T +(ate function.) 436.57 210.33 T +2 F +(send) 180 186.33 T +4 F +(int send \050char *msg, cde) 279.29 186.33 T +(vData &out, cde) 386.81 186.33 T +(vData& result\051;) 457.66 186.33 T +(int send \050char *msg, cde) 279.29 174.33 T +(vData *out, cde) 386.81 174.33 T +(vData& result\051;) 454.88 174.33 T +(int send \050char *msg, cde) 279.29 162.33 T +(vData &out, cde) 386.81 162.33 T +(vData* result\051;) 457.66 162.33 T +(int send \050char *msg, cde) 279.29 150.33 T +(vData *out, cde) 386.81 150.33 T +(vData* result\051;) 454.88 150.33 T +0 F +1.74 (The send function is the standard method f) 279.29 133.33 P +1.74 (or synchronously) 480.68 133.33 P +0.17 (comm) 279.43 121.33 P +0.17 (unicating with a de) 306.55 121.33 P +0.17 (vice) 389.59 121.33 P +0.17 (. The caller pro) 407.22 121.33 P +0.17 (vides the message) 474.28 121.33 P +0.71 (as a char) 279.43 109.33 P +0.71 (acter str) 321.88 109.33 P +0.71 (ing in the) 358.86 109.33 P +4 F +0.71 (msg) 404.34 109.33 P +0 F +0.71 (par) 426.72 109.33 P +0.71 (ameter) 441.07 109.33 P +0.71 (. The) 471.69 109.33 P +4 F +0.71 (out) 498.67 109.33 P +0 F +0.71 (cde) 516.06 109.33 P +0.71 (vData) 531.88 109.33 P +0.15 (object contains an) 279.43 97.33 P +0.15 (y proper) 360.18 97.33 P +0.15 (ty v) 397.41 97.33 P +0.15 (alues that the de) 412.88 97.33 P +0.15 (vice will need to) 486.97 97.33 P +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "17" 25 +%%Page: "18" 26 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. Using the cde) 54 739 T +(vDe) 118.76 739 T +(vice Object) 134.5 739 T +0 10 Q +(18) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +1.53 (perf) 261.43 713.33 P +1.53 (or) 278.36 713.33 P +1.53 (m the task. The) 287.5 713.33 P +4 F +1.53 (result) 365.34 713.33 P +0 F +1.53 ( cde) 389.79 713.33 P +1.53 (vData object will contain the) 409.92 713.33 P +0.64 (output proper) 261.43 701.33 P +0.64 (ties that resulted from the call. This function will) 321.95 701.33 P +(retur) 261.43 689.33 T +(n one of the error code de\336ned in cde) 282.24 689.33 T +(vErrCode) 448.15 689.33 T +(.h.) 490.23 689.33 T +4 9 Q +(Figure 14: Retur) 162 656 T +(n codes gener) 229.75 656 T +(ated b) 286.7 656 T +(y the send method) 311.54 656 T +2 10 Q +(sendNoBloc) 162 346.19 T +(k) 220.14 346.19 T +4 F +-0.01 (int sendNoBloc) 261.29 346.19 P +-0.01 (k\050char *msg, cde) 328.33 346.19 P +-0.01 (vData &out, cde) 403.04 346.19 P +-0.01 (vData &result\051;) 473.88 346.19 P +(int sendNoBloc) 261.29 334.19 T +(k\050char *msg, cde) 328.34 334.19 T +(vData *out, cde) 403.06 334.19 T +(vData &result\051;) 471.13 334.19 T +(int sendNoBloc) 261.29 322.19 T +(k\050char *msg, cde) 328.34 322.19 T +(vData &out, cde) 403.06 322.19 T +(vData *result\051;) 473.91 322.19 T +(int sendNoBloc) 261.29 310.19 T +(k\050char *msg, cde) 328.34 310.19 T +(vData *out, cde) 403.06 310.19 T +(vData *result\051;) 471.13 310.19 T +0 F +3.34 (The) 261.29 293.19 P +4 F +3.34 (sendNoBloc) 284.63 293.19 P +3.34 (k) 338.34 293.19 P +0 F +3.34 ( method uses the same par) 343.34 293.19 P +3.34 (ameters and) 481.08 293.19 P +1.51 (syntax as the) 261.43 281.19 P +4 F +1.51 (send) 327.67 281.19 P +0 F +1.51 ( method. Ho) 349.36 281.19 P +1.51 (w) 406.7 281.19 P +1.51 (e) 413.82 281.19 P +1.51 (v) 419.08 281.19 P +1.51 (er) 423.83 281.19 P +1.51 (, r) 432.22 281.19 P +1.51 (ather than w) 442.53 281.19 P +1.51 (aiting f) 500.43 281.19 P +1.51 (or) 531.11 281.19 P +0.89 (the under) 261.43 269.19 P +0.89 (lying ser) 304.72 269.19 P +0.89 (vice to respond to the request, this function) 343.14 269.19 P +7.31 (will retur) 261.43 257.19 P +7.31 (n immediately) 306.21 257.19 P +7.31 (. The caller m) 374.21 257.19 P +7.31 (ust utiliz) 456.61 257.19 P +7.31 (e some) 499.9 257.19 P +0.68 (synchronization method such as a cde) 261.43 245.19 P +0.68 (vGroup object to detect) 434.59 245.19 P +0.12 (when this tr) 261.43 233.19 P +0.12 (ansaction has been completed, or test f) 312.71 233.19 P +0.12 (or ne) 487.7 233.19 P +0.12 (w data) 510.42 233.19 P +(within the result data object.) 261.43 221.19 T +2 F +(sendCallbac) 162 197.19 T +(k) 220.71 197.19 T +4 F +(int sendCallbac) 261.29 197.19 T +(k \050) 329.45 197.19 T +(char *msg,) 340.56 197.19 T +(cde) 393.91 197.19 T +(vData &out,) 409.73 197.19 T +(cde) 333.57 185.19 T +(vCallbac) 349.39 185.19 T +(k &callbac) 387.53 185.19 T +(k\051;) 432.9 185.19 T +(int sendCallbac) 261.29 173.19 T +(k \050) 329.45 173.19 T +(char *msg, cde) 340.56 173.19 T +(vData *out,) 406.95 173.19 T +(cde) 333.57 161.19 T +(vCallbac) 349.39 161.19 T +(k &callbac) 387.53 161.19 T +(k\051;) 432.9 161.19 T +0 F +6.06 (The sendCallbac) 261.29 144.19 P +6.06 (k function is the standard method f) 342.18 144.19 P +6.06 (or) 531.11 144.19 P +3.54 (asynchronously comm) 261.43 132.19 P +3.54 (unicating with a de) 364.34 132.19 P +3.54 (vice) 457.48 132.19 P +3.54 (. Rather than) 475.11 132.19 P +1.95 (pro) 261.43 120.19 P +1.95 (viding a result cde) 275.73 120.19 P +1.95 (vData object, this method requires the) 361.86 120.19 P +2.49 (user to pro) 261.43 108.19 P +2.49 (vide the address of a cde) 314.07 108.19 P +2.49 (vCallbac) 437.96 108.19 P +2.49 (k object. This) 476.1 108.19 P +162 81 540 720 C +162 366.86 540 653 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.29 370.38 541.86 645.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.32 374.33 536.27 650.57 R +7 X +V +0 X +N +167.57 376.78 528.85 646.71 R +7 X +V +5 10 Q +0 X +(CDEV_SUCCESS: The message was processed successfully.) 167.57 640.04 T +(CDEV_ERROR: Failed to process message.) 167.57 626.04 T +(CDEV_INVALIDOBJ: Invalid CDEV request object used.) 167.57 612.04 T +(CDEV_INVALIDARG: Invalid argument passed to CDEV call.) 167.57 598.04 T +(CDEV_INVALIDSVC: Wrong service during dynamic loading.) 167.57 584.04 T +(CDEV_NOTCONNECTED: Not connected to low level network) 167.57 570.04 T +( service.) 167.57 556.04 T +(CDEV_IOFAILED: Low level network service IO failed.) 167.57 542.04 T +(CDEV_CONFLICT: Conflicts of data types or tags.) 167.57 528.05 T +(CDEV_NOTFOUND: Cannot find specified data in cdevData.) 167.57 514.05 T +(CDEV_TIMEOUT: Time out.) 167.57 500.05 T +(CDEV_CONVERT: cdevData conversion error.) 167.57 486.05 T +(CDEV_OUTOFRANGE: Value out of range for device attribute.) 167.57 472.05 T +(CDEV_NOACCESS: Insufficient access to perform request.) 167.57 458.05 T +(CDEV_ACCESSCHANGED: Change in access permission of device.) 167.57 444.05 T +(CDEV_DISCONNECTED: The service has lost contact with the) 167.57 430.05 T +( device.) 167.57 416.05 T +-1.07 (CDEV_RECONNECTED: The service has regained contact with the) 167.57 402.05 P +( device.) 167.57 388.05 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "18" 26 +%%Page: "19" 27 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. Using the cde) 432.99 739 T +(vDe) 497.75 739 T +(vice Object) 513.49 739 T +0 10 Q +(19) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.4 (object contains a user supplied pointer and the address of a) 279.43 713.33 P +3.42 (function to call when the message has been successfully) 279.43 701.33 P +(processed.) 279.43 689.33 T +2 F +(Sample Code) 72 660.33 T +0 F +2.6 (The f) 180 660.33 P +2.6 (ollo) 205.09 660.33 P +2.6 (wing sample applications illustr) 220.5 660.33 P +2.6 (ate man) 365.46 660.33 P +2.6 (y of the uses of the cde) 404.04 660.33 P +2.6 (vDe) 522.74 660.33 P +2.6 (vice) 540.22 660.33 P +0.38 (object. Additionally) 180 648.33 P +0.38 (, these e) 262.75 648.33 P +0.38 (xamples sho) 301.57 648.33 P +0.38 (w in depth usage of the cde) 357.93 648.33 P +0.38 (vData object and) 482.2 648.33 P +(the concept of conte) 180 636.33 T +(xt.) 269.76 636.33 T +2 F +(Attac) 72 607.33 T +(hing to a) 96.9 607.33 T +(cde) 72 595.33 T +(vDe) 89.08 595.33 T +(vice Object) 107.27 595.33 T +0 F +1.97 (Within a cde) 180 607.33 P +1.97 (vSystem object, a cde) 238.66 607.33 P +1.97 (vDe) 342.09 607.33 P +1.97 (vice is created only once f) 359.57 607.33 P +1.97 (or an) 484.18 607.33 P +1.97 (y speci\336ed) 508.79 607.33 P +0.9 (de) 180 595.33 P +0.9 (vice name) 190.82 595.33 P +0.9 (. After that, all requests f) 237.14 595.33 P +0.9 (or that de) 349.75 595.33 P +0.9 (vice are giv) 393.51 595.33 P +0.9 (en a pointer to the same) 445.64 595.33 P +(cde) 180 583.33 T +(vDe) 195.82 583.33 T +(vice object. This technique is called) 213.3 583.33 T +4 F +(attaching) 372.81 583.33 T +0 F +( to a de) 413.39 583.33 T +(vice) 446.45 583.33 T +(.) 464.08 583.33 T +4.51 (There are tw) 180 566.33 P +4.51 (o approaches to attaching to a cde) 245.06 566.33 P +4.51 (vDe) 425.27 566.33 P +4.51 (vice; through a speci\336c) 442.75 566.33 P +-0.1 (cde) 180 554.33 P +-0.1 (vSystem object, or through the cde) 195.82 554.33 P +-0.1 (vDe) 349.54 554.33 P +-0.1 (vice interf) 367.02 554.33 P +-0.1 (ace) 409.42 554.33 P +-0.1 (. Attaching to the de) 425.39 554.33 P +-0.1 (vice using) 513.64 554.33 P +1.39 (the cde) 180 542.33 P +1.39 (vSystem object has the bene\336t of making it possib) 213.89 542.33 P +1.39 (le to manage the de) 446.57 542.33 P +1.39 (vice) 540.22 542.33 P +2.49 (through a system other than the def) 180 530.33 P +2.49 (ault system. Using the cde) 352.5 530.33 P +2.49 (vDe) 479.42 530.33 P +2.49 (vice interf) 496.9 530.33 P +2.49 (ace) 541.88 530.33 P +1.42 (directly alw) 180 518.33 P +1.42 (a) 230.72 518.33 P +1.42 (ys places the ne) 235.98 518.33 P +1.42 (w de) 312.29 518.33 P +1.42 (vice in the def) 334.52 518.33 P +1.42 (ault system, b) 400.17 518.33 P +1.42 (ut has the bene\336t of) 464.49 518.33 P +1.95 (reducing the comple) 180 506.33 P +1.95 (xity of the source code b) 273.63 506.33 P +1.95 (y hiding the use of the cde) 391.55 506.33 P +1.95 (vSystem) 519.66 506.33 P +(object.) 180 494.33 T +0.8 (The ne) 180 477.33 P +0.8 (xt e) 211.63 477.33 P +0.8 (xample illustr) 228.25 477.33 P +0.8 (ates ho) 287.29 477.33 P +0.8 (w to attach to a cde) 320.73 477.33 P +0.8 (vDe) 411.15 477.33 P +0.8 (vice using the) 428.63 477.33 P +4 F +0.8 (attachRef) 494.94 477.33 P +0 F +0.8 ( and) 537.74 477.33 P +-0.25 (the) 180 465.33 P +4 F +-0.25 (attachPtr) 196.43 465.33 P +0 F +-0.25 ( methods) 236.45 465.33 P +-0.25 (. The) 277.18 465.33 P +4 F +-0.25 (attachRef) 302.25 465.33 P +0 F +-0.25 ( method allo) 345.05 465.33 P +-0.25 (ws the caller to obtain a ref) 398.86 465.33 P +-0.25 (erence to) 516.56 465.33 P +0.36 (the cde) 180 453.33 P +0.36 (vDe) 212.86 453.33 P +0.36 (vice object, while the) 230.34 453.33 P +4 F +0.36 (attachPtr) 326.82 453.33 P +0 F +0.36 ( method allo) 366.84 453.33 P +0.36 (ws the user to obtain a pointer) 421.88 453.33 P +1.72 (to the same object. This e) 180 441.33 P +1.72 (xample also demonstr) 307.32 441.33 P +1.72 (ates the long hand approach f) 408.48 441.33 P +1.72 (or) 549.11 441.33 P +(retr) 180 429.33 T +(ie) 195.15 429.33 T +(ving a cde) 202.63 429.33 T +(vDe) 247.91 429.33 T +(vice pointer from the system object.) 265.39 429.33 T +4 9 Q +(Figure 15: Attaching to a cde) 180 396 T +(vDe) 297.3 396 T +(vice object) 313.03 396 T +180 81 558 614 C +180 113.17 558 393 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.93 115.38 559.5 385.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +179.96 119.57 553.92 390.57 R +7 X +V +0 X +N +185.21 121.97 546.49 386.79 R +7 X +V +5 9 Q +0 X +(#include ) 185.21 380.79 T +(#include ) 185.21 369.79 T +(void main\050\051) 185.21 347.79 T +({) 203.21 336.79 T +(// ************************************************************) 203.21 325.79 T +(// * Use the attachPtr and attachRef methods to attach to) 203.21 314.79 T +(// * devices \322MQB1S01\323 && \322MQB1S02\323.) 203.21 303.79 T +(// ************************************************************) 203.21 292.79 T +(cdevDevice * devicePtr = cdevDevice::attachPtr\050\322MQB1S01\323\051;) 203.21 281.79 T +(cdevDevice & deviceRef = cdevDevice::attachRef\050\322MQB1S02\323\051;) 203.21 270.78 T +(// ************************************************************) 203.21 248.78 T +(// * To use the long-hand approach, obtain a pointer to the) 203.21 237.78 T +(// * default cdevSystem \050or any other cdevSystem object\051.) 203.21 226.78 T +(// ************************************************************) 203.21 215.78 T +(cdevSystem & default = cdevSystem::defaultSystem\050\051;) 203.21 204.78 T +(// ************************************************************) 203.21 182.78 T +(// * Next, use the getDevice method of the system to obtain) 203.21 171.78 T +(// * a pointer to the specific device \050MQB1S03\051.) 203.21 160.78 T +(// ************************************************************) 203.21 149.78 T +(cdevDevice * dev = default.getDevice\050\322MQB1S03\323\051;) 203.21 138.78 T +(}) 203.21 127.78 T +180 81 558 614 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "19" 27 +%%Page: "20" 28 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. Using the cde) 54 739 T +(vDe) 118.76 739 T +(vice Object) 134.5 739 T +0 10 Q +(20) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(Getting and) 54 713.33 T +-0.81 (Setting Conte) 54 701.33 P +-0.81 (xt f) 118.04 701.33 P +-0.81 (or) 132.03 701.33 P +(a cde) 54 689.33 T +(vDe) 79.42 689.33 T +(vice) 97.61 689.33 T +0 F +0.42 (In CDEV) 162 713.33 P +0.42 (,) 200.07 713.33 P +4 F +0.42 (conte) 206.04 713.33 P +0.42 (xt) 230.2 713.33 P +0 F +0.42 ( ref) 237.98 713.33 P +0.42 (ers to a collection of options that ma) 252.55 713.33 P +0.42 (y be used to alter the w) 415.24 713.33 P +0.42 (a) 520.98 713.33 P +0.42 (y a) 526.24 713.33 P +1.38 (CDEV de) 162 701.33 P +1.38 (vice responds to a speci\336c message) 204.76 701.33 P +1.38 (. Ho) 372.15 701.33 P +1.38 (w conte) 391.72 701.33 P +1.38 (xt inf) 427.26 701.33 P +1.38 (or) 449.46 701.33 P +1.38 (mation eff) 458.6 701.33 P +1.38 (ects the) 503.6 701.33 P +-0.14 (bahvior of a de) 162 689.33 P +-0.14 (vice is de\336ned b) 227.44 689.33 P +-0.14 (y the associated cde) 298.53 689.33 P +-0.14 (vSer) 388.98 689.33 P +-0.14 (vice) 409.84 689.33 P +-0.14 (. Conte) 427.47 689.33 P +-0.14 (xt ma) 461.92 689.33 P +-0.14 (y be used to) 485.93 689.33 P +1.22 (set an) 162 677.33 P +1.22 (y n) 190.31 677.33 P +1.22 (umber of I/O options) 204.77 677.33 P +1.22 (, such as timeouts) 298.88 677.33 P +1.22 (, data acquisition speci\336cations) 382.98 677.33 P +1.22 (, or) 524.33 677.33 P +-0.1 (\337ags to control optional retur) 162 665.33 P +-0.1 (n data. The conte) 288.02 665.33 P +-0.1 (xt is stored and retr) 370.61 665.33 P +-0.1 (ie) 455.96 665.33 P +-0.1 (v) 463.44 665.33 P +-0.1 (ed in the f) 468.19 665.33 P +-0.1 (or) 511.51 665.33 P +-0.1 (m of) 520.65 665.33 P +(a cde) 162 653.33 T +(vData object containing a collection of tagged data items \050called) 186.16 653.33 T +4 F +(proper) 471.3 653.33 T +(ties) 500.6 653.33 T +0 F +(\051.) 516.16 653.33 T +1.15 (The e) 162 636.33 P +1.15 (xample belo) 188.42 636.33 P +1.15 (w illustr) 243.32 636.33 P +1.15 (ates ho) 277.7 636.33 P +1.15 (w the caller ma) 311.5 636.33 P +1.15 (y obtain a cop) 381.88 636.33 P +1.15 (y of the conte) 447.28 636.33 P +1.15 (xt of a) 510.46 636.33 P +-0.21 (de) 162 624.33 P +-0.21 (vice) 172.82 624.33 P +-0.21 (, install a ne) 190.45 624.33 P +-0.21 (w conte) 242.99 624.33 P +-0.21 (xt f) 276.94 624.33 P +-0.21 (or a speci\336c call, and then restore the pre) 289.77 624.33 P +-0.21 (vious conte) 471.23 624.33 P +-0.21 (xt to) 521.31 624.33 P +(the de) 162 612.33 T +(vice) 189.5 612.33 T +(.) 207.13 612.33 T +4 F +0.17 (Note: Whene) 162 595.33 P +0.17 (v) 220.23 595.33 P +0.17 (er the conte) 224.98 595.33 P +0.17 (xt of a de) 277.82 595.33 P +0.17 (vice is directly manipulated, each of its under) 319.16 595.33 P +0.17 (lying) 519.44 595.33 P +1.21 (cde) 162 583.33 P +1.21 (vRequestObjects are updated to re\337ect the ne) 177.82 583.33 P +1.21 (w change) 388.87 583.33 P +1.21 (. Theref) 432.73 583.33 P +1.21 (ore) 468.1 583.33 P +1.21 (, alter) 482.4 583.33 P +1.21 (ing the) 508.77 583.33 P +0.48 (conte) 162 571.33 P +0.48 (xt directly in the cde) 186.16 571.33 P +0.48 (vDe) 276.13 571.33 P +0.48 (vice is not recommended. The pref) 293.61 571.33 P +0.48 (erred approach is to) 449.64 571.33 P +(obtain a cop) 162 559.33 T +(y of the cde) 216.18 559.33 T +(vRequestObject and alter the conte) 267.58 559.33 T +(xt there) 424.03 559.33 T +(.) 457.23 559.33 T +4 9 Q +(Figure 16: Alter) 162 526 T +(ing the conte) 226.16 526 T +(xt of a cde) 277.42 526 T +(vDe) 318.68 526 T +(vice object) 334.41 526 T +162 81 540 720 C +162 134.59 540 523 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.29 138.23 541.86 515.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.32 143.14 536.27 521.29 R +7 X +V +0 X +N +167.57 146.48 528.85 516 R +7 X +V +5 9 Q +0 X +(#include ) 167.57 510 T +(#include ) 167.57 499 T +(#include ) 167.57 488 T +(void main\050\051) 167.57 466 T +({) 185.57 455 T +(// ************************************************************) 185.57 444 T +(// * Obtain a pointer to the cdevDevice \322MQB1S01\323) 185.57 433 T +(// ************************************************************) 185.57 422 T +(cdevDevice * devicePtr = cdevDevice::attachPtr\050\322MQB1S01\323\051;) 185.57 411 T +(cdevData oldContext, newContext;) 185.57 400 T +(// ************************************************************) 185.57 378 T +(// * Indicate in the newContext cdevData object that devices) 185.57 367 T +(// * should return their value, status and severity information) 185.57 356 T +(// ************************************************************) 185.57 345 T +(newContext.insert\050\322value\323, 1\051;) 185.57 334 T +(newContext.insert\050\322status\323, 1\051;) 185.57 323 T +(newContext.insert\050\322severity\323, 1\051;) 185.57 312 T +(// ************************************************************) 185.57 290 T +(// * Preserve the contexts of the original device context, and) 185.57 279 T +(// * then install the new device context.) 185.57 268 T +(// ************************************************************) 185.57 257 T +(oldContext = devicePtr->getContext\050\051;) 185.57 246 T +(devicePtr->setContext\050newContext\051;) 185.57 235 T +(// ************************************************************) 185.57 213 T +(// * After performing the context specific operations, restore) 185.57 202 T +(// * the old context to the device.) 185.57 191 T +(// ************************************************************) 185.57 180 T +(devicePtr->setContext\050oldContext\051;) 185.57 169 T +(}) 185.57 158 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "20" 28 +%%Page: "21" 29 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. Using the cde) 432.99 739 T +(vDe) 497.75 739 T +(vice Object) 513.49 739 T +0 10 Q +(21) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +-1.4 (Sending Messa) 72 713.33 P +-1.4 (g) 143.29 713.33 P +-1.4 (es) 149.51 713.33 P +(to a De) 72 701.33 T +(vice) 105.19 701.33 T +(Sync) 72 689.33 T +(hr) 95.8 689.33 T +(onousl) 105.6 689.33 T +(y) 138.23 689.33 T +0 F +1.01 (In most CDEV applications) 180 713.33 P +1.01 (, the caller will w) 301.8 713.33 P +1.01 (ant to send a message to a de) 378.47 713.33 P +1.01 (vice and) 519.75 713.33 P +1.46 (then w) 180 701.33 P +1.46 (ait until a response is receiv) 210.77 701.33 P +1.46 (ed. In order to do this) 341.2 701.33 P +1.46 (, the) 442.85 701.33 P +4 F +1.46 (send) 468.01 701.33 P +0 F +1.46 ( method of the) 489.69 701.33 P +0.5 (cde) 180 689.33 P +0.5 (vDe) 195.82 689.33 P +0.5 (vice object should be used. The) 213.3 689.33 P +4 F +0.5 (send) 359.68 689.33 P +0 F +0.5 ( method receiv) 381.36 689.33 P +0.5 (es three par) 447.68 689.33 P +0.5 (ameters; the) 501.92 689.33 P +0.27 (message to be sent, a cde) 180 677.33 P +0.27 (vData object containing data required b) 298.33 677.33 P +0.27 (y the de) 473.44 677.33 P +0.27 (vice) 509.26 677.33 P +0.27 (, and a) 526.89 677.33 P +(cde) 180 665.33 T +(vData object to receiv) 195.82 665.33 T +(e the data retur) 291.72 665.33 T +(ned b) 359.79 665.33 T +(y the de) 384.61 665.33 T +(vice) 419.89 665.33 T +(.) 437.52 665.33 T +1.48 (The f) 180 648.33 P +1.48 (ollo) 203.97 648.33 P +1.48 (wing e) 219.38 648.33 P +1.48 (xample demonstr) 249.45 648.33 P +1.48 (ates reading an attr) 327.52 648.33 P +1.48 (ib) 418.26 648.33 P +1.48 (ute of a de) 425.84 648.33 P +1.48 (vice and handling) 477.23 648.33 P +2.5 (each class of error inline) 180 636.33 P +2.5 (. A retur) 298.21 636.33 P +2.5 (n code of) 339.03 636.33 P +4 F +2.5 (CDEV_SUCCESS) 390.45 636.33 P +0 F +2.5 (indicates that the) 477.4 636.33 P +(message w) 180 624.33 T +(as successfully tr) 230.42 624.33 T +(ansmitted and processed.) 306.45 624.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "21" 29 +%%Page: "22" 30 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. Using the cde) 54 739 T +(vDe) 118.76 739 T +(vice Object) 134.5 739 T +0 10 Q +(22) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Figure 17: Using the send method of a cde) 162 714 T +(vDe) 334.32 714 T +(vice object) 350.05 714 T +2 10 Q +-1.4 (Sending Messa) 54 117.28 P +-1.4 (g) 125.29 117.28 P +-1.4 (es) 131.51 117.28 P +(to a De) 54 105.28 T +(vice) 87.19 105.28 T +(Async) 54 93.28 T +(hr) 83.91 93.28 T +(onousl) 93.71 93.28 T +(y) 126.34 93.28 T +0 F +1.9 (There are tw) 162 117.28 P +1.9 (o methods pro) 221.82 117.28 P +1.9 (vided b) 289.39 117.28 P +1.9 (y the cde) 323.32 117.28 P +1.9 (vDe) 367.39 117.28 P +1.9 (vice object f) 384.87 117.28 P +1.9 (or sending messages) 441.17 117.28 P +(asynchronously;) 162 105.28 T +4 F +(sendNoBloc) 237.03 105.28 T +(k) 290.74 105.28 T +0 F +( and) 295.74 105.28 T +4 F +(sendCallbac) 317.98 105.28 T +(k) 372.8 105.28 T +0 F +(.) 377.8 105.28 T +162 142.95 540 720 C +162 142.95 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.93 146.23 541.5 703.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +161.96 150.43 535.92 709.29 R +7 X +V +0 X +N +167.21 155.64 528.49 705.49 R +7 X +V +5 9 Q +0 X +(#include ) 167.21 699.49 T +(#include ) 167.21 688.49 T +(void main\050\051) 167.21 666.49 T +({) 185.21 655.49 T +(// ************************************************************) 185.21 644.49 T +(// * Obtain a pointer to the cdevDevice \322MQB1S01\323) 185.21 633.49 T +(// ************************************************************) 185.21 622.49 T +(cdevDevice * device = cdevDevice::attachPtr\050\322MQB1S01\323\051;) 185.21 611.49 T +(cdevData input, output;) 185.21 600.49 T +(double value = 0.0;) 185.21 589.49 T +(// ************************************************************) 185.21 567.49 T +(// * Use the send method to obtain the value from the device.) 185.21 556.49 T +(// * Because there is no outbound data, the parameter is NULL.) 185.21 545.49 T +(// ************************************************************) 185.21 534.49 T +(switch\050device->send\050\322get bdl\323, NULL, &output\051\051) 185.21 523.49 T +({) 203.21 512.49 T +(// **** Message transmitted and processed successfuly. ****) 203.21 501.49 T +(case CDEV_SUCCESS:) 203.21 490.49 T +(output.get\050\322value\323, &value\051;) 221.21 479.49 T +(printf\050\322Value of MQB1S01 is %f\134n\323, value\051;) 221.21 468.49 T +(break;) 221.21 457.49 T +(// ****** Unknown device or device/message mismatch ******) 203.21 435.49 T +(case CDEV_INVALIDOBJ:) 203.21 424.49 T +(printf\050\322Unknown device or device/message mismatch\134n\323\051;) 221.21 413.49 T +(break;) 221.21 402.49 T +(// * Communications error between application and service *) 203.21 380.49 T +(case CDEV_NOTCONNECTED:) 203.21 369.49 T +(case CDEV_IOFAILED:) 203.21 358.49 T +(case CDEV_TIMEOUT:) 203.21 347.49 T +(printf\050\322Communications error while sending\134n\323\051;) 221.21 336.49 T +(break;) 221.21 325.49 T +(// ******************* Generic error **********************) 203.21 303.49 T +(case CDEV_ERROR:) 203.21 292.49 T +(case default:) 203.21 281.49 T +(printf\050\322Unable to send message\134n\323\051;) 221.21 270.49 T +(break;) 221.21 259.49 T +(}) 203.21 248.49 T +(// ************************************************************) 185.21 226.49 T +(// * Increment the value, and use the \322set bdl\323 command) 185.21 215.49 T +(// ************************************************************) 185.21 204.49 T +(value += 1.0;) 185.21 193.49 T +(input.insert\050\322value\323, value\051;) 185.21 182.49 T +(device->send\050\322set bdl\323, &input, NULL\051;) 185.21 171.49 T +(}) 185.21 160.49 T +162 142.95 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "22" 30 +%%Page: "23" 31 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. Using the cde) 432.99 739 T +(vDe) 497.75 739 T +(vice Object) 513.49 739 T +0 10 Q +(23) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Using) 72 713.33 T +(sendNoBloc) 72 701.33 T +(k) 130.14 701.33 T +0 F +0.25 (The) 180 713.33 P +4 F +0.25 (sendNoBloc) 200.26 713.33 P +0.25 (k) 253.97 713.33 P +0 F +0.25 (method is identical in interf) 262 713.33 P +0.25 (ace to the) 381.09 713.33 P +4 F +0.25 (send) 428.54 713.33 P +0 F +0.25 ( method, ho) 450.22 713.33 P +0.25 (w) 503.39 713.33 P +0.25 (e) 510.51 713.33 P +0.25 (v) 515.77 713.33 P +0.25 (er) 520.52 713.33 P +0.25 (, if it is) 528.91 713.33 P +0.75 (unab) 180 701.33 P +0.75 (le to immediately tr) 202.04 701.33 P +0.75 (ansmit to and receiv) 288.1 701.33 P +0.75 (e a response from the de) 379.59 701.33 P +0.75 (vice) 494.21 701.33 P +0.75 (, it will not) 511.85 701.33 P +-0.27 (w) 180 689.33 P +-0.27 (ait. In order to deter) 187.07 689.33 P +-0.27 (mine if a) 273.53 689.33 P +4 F +-0.27 (sendNoBloc) 313.3 689.33 P +-0.27 (k) 367.01 689.33 P +0 F +-0.27 ( oper) 372.01 689.33 P +-0.27 (ation has completed successfully) 394.43 689.33 P +-0.27 (, the) 538.8 689.33 P +1.9 (caller m) 180 677.33 P +1.9 (ust poll the) 216.8 677.33 P +4 F +1.9 (cde) 273.64 677.33 P +1.9 (vSystem) 289.46 677.33 P +0 F +1.9 ( object, implement a g) 327.8 677.33 P +1.9 (rouping scheme using the) 437.8 677.33 P +4 F +(cde) 180 665.33 T +(vGroup) 195.82 665.33 T +0 F +(object, or e) 231.39 665.33 T +(xplicitly test f) 280.56 665.33 T +(or ne) 336.94 665.33 T +(w data in the result data object.) 359.53 665.33 T +2 F +(Mana) 72 636.33 T +(ging) 97.46 636.33 T +(sendNoBloc) 72 624.33 T +(k) 130.14 624.33 T +(Messa) 72 612.33 T +(g) 102.47 612.33 T +(es with) 108.68 612.33 T +(the cde) 72 600.33 T +(vSystem) 106.86 600.33 T +(object) 72 588.33 T +0 F +0.71 (T) 180 636.33 P +0.71 (o manage asynchronous messages using the cde) 184.91 636.33 P +0.71 (vSystem object, the caller should) 408.99 636.33 P +3.3 (use the) 180 624.33 P +4 F +3.3 (pend) 222.17 624.33 P +0 F +3.3 ( or) 244.41 624.33 P +4 F +3.3 (poll) 265.45 624.33 P +0 F +3.3 ( method. These methods will submit the message to the) 281.01 624.33 P +1.38 (under) 180 612.33 P +1.38 (lying de) 205.72 612.33 P +1.38 (vice) 241.26 612.33 P +1.38 (, and will w) 258.89 612.33 P +1.38 (ait f) 311.78 612.33 P +1.38 (or a per) 328.98 612.33 P +1.38 (iod of time f) 366.35 612.33 P +1.38 (or a response to arr) 421.87 612.33 P +1.38 (iv) 514.8 612.33 P +1.38 (e) 521.77 612.33 P +1.38 (. If all) 527.18 612.33 P +0.93 (messages ha) 180 600.33 P +0.93 (v) 240.2 600.33 P +0.93 (e not been processed dur) 244.95 600.33 P +0.93 (ing the speci\336ed \050or def) 362.24 600.33 P +0.93 (ault\051 per) 469.61 600.33 P +0.93 (iod of time) 507.37 600.33 P +0.93 (,) 555.22 600.33 P +1.34 (these methods will retur) 180 588.33 P +1.34 (n a) 289.86 588.33 P +4 F +1.34 (CDEV_TIMEOUT) 309.22 588.33 P +0 F +1.34 ( status code) 387.56 588.33 P +1.34 (. If all tr) 444.02 588.33 P +1.34 (ansactions ha) 484.85 588.33 P +1.34 (v) 547.69 588.33 P +1.34 (e) 552.44 588.33 P +(been processed, these methods will retur) 180 576.33 T +(n a) 362.55 576.33 T +4 F +(CDEV_SUCCESS) 379.23 576.33 T +0 F +( status code) 460.91 576.33 T +(.) 514.68 576.33 T +2 F +(Gr) 72 547.33 T +(ouping) 83.47 547.33 T +(sendNoBloc) 72 535.33 T +(k) 130.14 535.33 T +(Messa) 72 523.33 T +(g) 102.47 523.33 T +(es with) 108.68 523.33 T +(cde) 72 511.33 T +(vGr) 89.08 511.33 T +(oup) 106.11 511.33 T +0 F +1.13 (An alter) 180 547.33 P +1.13 (nativ) 215.85 547.33 P +1.13 (e w) 236.71 547.33 P +1.13 (a) 253.26 547.33 P +1.13 (y to manage messages tr) 258.52 547.33 P +1.13 (ansmitted with sendNoBloc) 375.23 547.33 P +1.13 (k is to create) 497.9 547.33 P +0.25 (and) 180 535.33 P +4 F +0.25 (star) 199.71 535.33 P +0.25 (t) 216.78 535.33 P +0 F +0.25 ( a) 219.56 535.33 P +4 F +0.25 (cde) 231.18 535.33 P +0.25 (vGroup) 247.01 535.33 P +0 F +0.25 ( object pr) 279.8 535.33 P +0.25 (ior to sending the \336rst message) 321.58 535.33 P +0.25 (. The application then) 461.64 535.33 P +0.15 (tr) 180 523.33 P +0.15 (ansmits all of the messages that it wishes to manage within a single g) 186.01 523.33 P +0.15 (roup) 495.8 523.33 P +0.15 (. Once all) 515.46 523.33 P +0.01 (messages ha) 180 511.33 P +0.01 (v) 239.28 511.33 P +0.01 (e been tr) 244.03 511.33 P +0.01 (ansmitted, the caller will) 283.41 511.33 P +4 F +0.01 (end) 392.36 511.33 P +0 F +0.01 ( the) 409.04 511.33 P +4 F +0.01 (cde) 428.51 511.33 P +0.01 (vGroup) 444.33 511.33 P +0 F +0.01 ( and then ma) 477.12 511.33 P +0.01 (y call) 535.21 511.33 P +4.15 (the) 180 499.33 P +4 F +4.15 (pend) 200.83 499.33 P +0 F +4.15 (member function of the) 230 499.33 P +4 F +4.15 (cde) 351.65 499.33 P +4.15 (vGroup) 367.47 499.33 P +0 F +4.15 ( object until the retur) 400.26 499.33 P +4.15 (n v) 507.71 499.33 P +4.15 (alue is) 524.95 499.33 P +4 F +0.12 (CDEV_SUCCESS) 180 487.33 P +0.12 (.) 261.48 487.33 P +0 F +0.12 (The caller should alw) 267.16 487.33 P +0.12 (a) 361.29 487.33 P +0.12 (ys specify a discrete amount of time to w) 366.55 487.33 P +0.12 (ait) 547.44 487.33 P +-0.1 (when using the) 180 475.33 P +4 F +-0.1 (pend) 249.73 475.33 P +0 F +-0.1 ( oper) 271.97 475.33 P +-0.1 (ation, otherwise) 294.55 475.33 P +-0.1 (, the application can enter an inde\336nite w) 364.33 475.33 P +-0.1 (ait.) 544.66 475.33 P +4 F +1.54 (Note: Once a cde) 180 458.33 P +1.54 (vGroup object has been star) 262.15 458.33 P +1.54 (ted, it will remain open until its end) 394.35 458.33 P +0.19 (method is e) 180 446.33 P +0.19 (x) 231.77 446.33 P +0.19 (ecuted) 236.47 446.33 P +3 F +0.19 (OR) 269.45 446.33 P +4 F +0.19 (until the pend method of the cde) 287.42 446.33 P +0.19 (vGroup object is e) 431.12 446.33 P +0.19 (x) 511.97 446.33 P +0.19 (ecuted. If) 516.67 446.33 P +0.04 (a sendNoBloc) 180 434.33 P +0.04 (k is e) 242.09 434.33 P +0.04 (x) 265.2 434.33 P +0.04 (ecuted after the g) 269.9 434.33 P +0.04 (roup has been ended, it will not be managed b) 347.74 434.33 P +0.04 (y) 553 434.33 P +(that g) 180 422.33 T +(roup) 204.92 422.33 T +(.) 224.58 422.33 T +0 F +-0.24 (The e) 180 405.33 P +-0.24 (xample belo) 205.03 405.33 P +-0.24 (w illustr) 258.54 405.33 P +-0.24 (ates ho) 291.53 405.33 P +-0.24 (w to tr) 323.93 405.33 P +-0.24 (ansmit m) 350.58 405.33 P +-0.24 (ultiple messages to a de) 390.79 405.33 P +-0.24 (vice using the) 497.35 405.33 P +4 F +(sendNoBloc) 180 393.33 T +(k) 233.71 393.33 T +0 F +( method and the) 238.71 393.33 T +4 F +(cde) 313.76 393.33 T +(vGroup) 329.58 393.33 T +0 F +( object.) 362.37 393.33 T +4 9 Q +(Figure 18: Using sendNoBloc) 180 360 T +(k to comm) 299.37 360 T +(unicate with a cde) 340.79 360 T +(vDe) 412.55 360 T +(vice) 428.28 360 T +180 81 558 554 C +180 139.43 558 357 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.57 142.12 559.15 349.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +179.61 146.91 553.56 355.29 R +7 X +V +0 X +N +184.86 152.14 546.14 351 R +7 X +V +5 9 Q +0 X +(#include ) 184.86 345 T +(#include ) 184.86 334 T +(#include ) 184.86 323 T +(void main\050\051) 184.86 301 T +({) 202.86 290 T +(// ************************************************************) 202.86 279 T +(// * Obtain a pointer to the cdevDevice \322MQB1S01\323 and \322MQB1S02\323) 202.86 268 T +(// ************************************************************) 202.86 257 T +(cdevDevice * device1 = cdevDevice::attachPtr\050\322MQB1S01\323\051;) 202.86 246 T +(cdevDevice * device2 = cdevDevice::attachPtr\050\322MQB1S02\323\051;) 202.86 235 T +(cdevGroup group;) 202.86 224 T +(cdevData output1, output2;) 202.86 213 T +(// ************************************************************) 202.86 191 T +(// * Start the cdevGroup object to group all of the requests.) 202.86 180 T +(// ************************************************************) 202.86 169 T +(group.start\050\051;) 202.86 158 T +180 81 558 554 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "23" 31 +%%Page: "24" 32 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. Using the cde) 54 739 T +(vDe) 118.76 739 T +(vice Object) 134.5 739 T +0 10 Q +(24) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Figure 18: Using sendNoBloc) 162 714 T +(k to comm) 281.37 714 T +(unicate with a cde) 322.79 714 T +(vDe) 394.55 714 T +(vice \050contin) 410.28 714 T +(ued\051) 455.71 714 T +2 10 Q +(Using def) 54 368.36 T +(erred) 99.46 368.36 T +(gr) 54 356.36 T +(oups f) 63.8 356.36 T +(or) 93.6 356.36 T +(repeating lists of) 54 344.36 T +(operations) 54 332.36 T +0 F +0.3 (A cde) 162 368.36 P +0.3 (vGroup ma) 187.57 368.36 P +0.3 (y be placed into a) 237.04 368.36 P +4 F +0.3 (def) 319.71 368.36 P +0.3 (erred) 333.31 368.36 P +0 F +0.3 ( mode pr) 356.65 368.36 P +0.3 (ior to star) 396.86 368.36 P +0.3 (ting it, and in this case) 439.55 368.36 P +0.37 (messages will not be tr) 162 356.36 P +0.37 (ansmitted until the g) 265.08 356.36 P +0.37 (roup is \337ushed. After all oper) 355.58 356.36 P +0.37 (ations within) 484.61 356.36 P +0.47 (the g) 162 344.36 P +0.47 (roup ha) 184.61 344.36 P +0.47 (v) 218.78 344.36 P +0.47 (e completed, the g) 223.53 344.36 P +0.47 (roup ma) 307.1 344.36 P +0.47 (y be \337ushed again, causing the same set of) 343.94 344.36 P +(oper) 162 332.36 T +(ations to be e) 181.91 332.36 T +(x) 241.65 332.36 T +(ecuted again. See the ref) 246.35 332.36 T +(erence man) 357.79 332.36 T +(ual f) 410.49 332.36 T +(or details) 429.09 332.36 T +(.) 469.51 332.36 T +2 F +(Using) 54 303.36 T +(sendCallbac) 54 291.36 T +(k) 112.71 291.36 T +0 F +-0.09 (The) 162 303.36 P +4 F +-0.09 (sendCallbac) 181.92 303.36 P +-0.09 (k) 236.74 303.36 P +0 F +-0.09 (method pro) 244.42 303.36 P +-0.09 (vides the second mechanism f) 294.76 303.36 P +-0.09 (or tr) 428.59 303.36 P +-0.09 (ansmitting messages) 446.17 303.36 P +1.51 (asynchronously) 162 291.36 P +1.51 (. This method is used in CDEV f) 230.47 291.36 P +1.51 (or a v) 382.48 291.36 P +1.51 (ar) 410.26 291.36 P +1.51 (iety of pur) 419.3 291.36 P +1.51 (poses) 466.54 291.36 P +1.51 (, the most) 493.07 291.36 P +0 (common of these is to estab) 162 279.36 P +0 (lish monitors on a speci\336c cde) 286.84 279.36 P +0 (vDe) 419.9 279.36 P +0 (vice attr) 437.38 279.36 P +0 (ib) 472.54 279.36 P +0 (ute) 480.12 279.36 P +0 (. Once the) 493.87 279.36 P +0.95 (monitor has been estab) 162 267.36 P +0.95 (lished, the user speci\336ed callbac) 269.15 267.36 P +0.95 (k function will be contacted) 416.7 267.36 P +(whene) 162 255.36 T +(v) 191.16 255.36 T +(er the proper) 195.91 255.36 T +(ty\325) 253.56 255.36 T +(s v) 263.06 255.36 T +(alue is altered.) 275.59 255.36 T +1.58 (This method is more comple) 162 238.36 P +1.58 (x than the others because it) 293.59 238.36 P +2 F +1.58 (REQ) 428.67 238.36 P +1.58 (UIRES) 450.24 238.36 P +0 F +1.58 ( the caller to) 480.8 238.36 P +0.05 (utiliz) 162 226.36 P +0.05 (e a) 181.85 226.36 P +4 F +0.05 (cde) 198.64 226.36 P +0.05 (vSystem) 214.46 226.36 P +0 F +0.05 (object in order to poll the under) 255.63 226.36 P +0.05 (lying ser) 393.96 226.36 P +0.05 (vices) 431.55 226.36 P +0.05 (, and it requires the) 454.18 226.36 P +1.52 (caller to prede\336ne a) 162 214.36 P +4 F +1.52 (cde) 258.67 214.36 P +1.52 (vCallbac) 274.49 214.36 P +1.52 (kFunction) 312.63 214.36 P +0 F +1.52 ( to be e) 355.98 214.36 P +1.52 (x) 393.6 214.36 P +1.52 (ecuted when the message has) 398.3 214.36 P +(been processed.) 162 202.36 T +0.87 (The) 162 185.36 P +4 F +0.87 (cde) 182.88 185.36 P +0.87 (vCallbac) 198.7 185.36 P +0.87 (kFunction) 236.84 185.36 P +0 F +0.87 (has a v) 283.83 185.36 P +0.87 (er) 317.55 185.36 P +0.87 (y speci\336c prototype that the caller m) 326.74 185.36 P +0.87 (ust comply) 491.34 185.36 P +0.47 (with. The user speci\336ed callbac) 162 173.36 P +0.47 (k function m) 302.6 173.36 P +0.47 (ust be of type v) 357.34 173.36 P +0.47 (oid, and m) 426.77 173.36 P +0.47 (ust receiv) 474.29 173.36 P +0.47 (e the) 517.29 173.36 P +(f) 162 161.36 T +(ollo) 164.48 161.36 T +(wing par) 179.89 161.36 T +(ameters) 217.58 161.36 T +(.) 253.55 161.36 T +(1.) 162 144.36 T +2 F +(int status) 180 144.36 T +0 F +(: This is equiv) 224.45 144.36 T +(alent to the retur) 285.33 144.36 T +(n status of a synchronous) 358.4 144.36 T +4 F +(send) 475.13 144.36 T +0 F +( call. It) 496.81 144.36 T +(should receiv) 180 132.36 T +(e one of the error codes that are de\336ned in) 238.66 132.36 T +4 F +(cde) 430.44 132.36 T +(vErrCode) 446.26 132.36 T +(.h) 488.34 132.36 T +0 F +(.) 496.68 132.36 T +(2.) 162 108.36 T +2 F +(v) 180 108.36 T +(oid * ar) 185.26 108.36 T +(g) 219.01 108.36 T +0 F +(: This is a pointer to data that w) 225.12 108.36 T +(as speci\336ed b) 363.93 108.36 T +(y the user when creating) 424.87 108.36 T +(the) 180 96.36 T +4 F +(cde) 196.68 96.36 T +(vCallbac) 212.5 96.36 T +(k) 250.64 96.36 T +0 F +( object.) 255.64 96.36 T +162 394.02 540 720 C +162 394.02 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.93 396.59 541.5 703.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +161.96 402.33 535.92 709.29 R +7 X +V +0 X +N +167.21 406.1 528.49 705 R +7 X +V +5 9 Q +0 X +(// ************************************************************) 185.21 699 T +(// * Use the sendNoBlock command to transmit the messages to) 185.21 688 T +(// * the selected devices. The \322get VAL\323 message requires no) 185.21 677 T +(// * input, so the outbound cdevData object is NULL.) 185.21 666 T +(// ************************************************************) 185.21 655 T +(device1->sendNoBlock\050\322get VAL\323, NULL, &output1\051;) 185.21 644 T +(device2->sendNoBlock\050\322get VAL\323, NULL, &output2\051;) 185.21 633 T +(// ************************************************************) 185.21 611 T +(// * Use the end method to terminate the group.) 185.21 600 T +(// ************************************************************) 185.21 589 T +(group.end\050\051;) 185.21 578 T +(// ************************************************************) 185.21 556 T +(// * Use the pend method of the group to wait for 1 second) 185.21 545 T +(// * for all of the messages to be processed. The allFinished) 185.21 534 T +(// * method can be used to obtain the completioon status of) 185.21 523 T +(// * the group \0500=NOT DONE, 1=DONE\051.) 185.21 512 T +(// *) 185.21 501 T +(// * As a simple example, this function will wait no more than) 185.21 490 T +(// * 5 seconds for all messages to be processed.) 185.21 479 T +(// ************************************************************) 185.21 468 T +(for\050int i=0; i<5 && !group.allFinished\050\051; i++\051) 185.21 457 T +({) 203.21 446 T +(group.pend\0501.0\051;) 203.21 435 T +(}) 203.21 424 T +(}) 185.21 413 T +162 394.02 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "24" 32 +%%Page: "25" 33 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. Using the cde) 432.99 739 T +(vDe) 497.75 739 T +(vice Object) 513.49 739 T +0 10 Q +(25) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 180 713.33 T +2 F +(cde) 198 713.33 T +(vRequestObject & obj) 215.08 713.33 T +0 F +(: This is the) 318.99 713.33 T +4 F +(cde) 372.9 713.33 T +(vRequestObject) 388.72 713.33 T +0 F +(that the system used) 462.64 713.33 T +(to tr) 198 701.33 T +(ansmit the message to the de) 215.13 701.33 T +(vice) 346.01 701.33 T +(.) 363.64 701.33 T +(4.) 180 677.33 T +2 F +-0.01 (cde) 198 677.33 P +-0.01 (vData & data) 215.08 677.33 P +0 F +-0.01 (: This is the cde) 275.62 677.33 P +-0.01 (vData object that contains the output gener) 345.29 677.33 P +-0.01 (ated) 535.77 677.33 P +(b) 198 665.33 T +(y the de) 203.36 665.33 T +(vice when it processed the message) 238.64 665.33 T +(.) 399.67 665.33 T +4.46 (The) 180 641.33 P +4 F +4.46 (cde) 204.47 641.33 P +4.46 (vCallbac) 220.29 641.33 P +4.46 (kFunction) 258.43 641.33 P +0 F +4.46 ( and a user pro) 301.78 641.33 P +4.46 (vided argument are passed to the) 386.73 641.33 P +4 F +0.62 (sendCallbac) 180 629.33 P +0.62 (k) 234.82 629.33 P +0 F +0.62 (method through the use of the) 243.23 629.33 P +4 F +0.62 (cde) 383.17 629.33 P +0.62 (vCallbac) 398.99 629.33 P +0.62 (k) 437.14 629.33 P +0 F +0.62 ( object. The) 442.14 629.33 P +4 F +0.62 (cde) 499.04 629.33 P +0.62 (vCallbac) 514.86 629.33 P +0.62 (k) 553 629.33 P +0 F +(object is a simple container class) 180 617.33 T +(.) 326.01 617.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "25" 33 +%%Page: "26" 34 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. Using the cde) 54 739 T +(vDe) 118.76 739 T +(vice Object) 134.5 739 T +0 10 Q +(26) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Figure 19: Using the sendCallbac) 162 714 T +(k method of a cde) 297.38 714 T +(vDe) 368.65 714 T +(vice object) 384.38 714 T +162 81 540 720 C +162 140.93 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.29 143.85 541.86 703.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.32 147.93 536.27 709.29 R +7 X +V +0 X +N +167.57 151.35 528.85 702.59 R +7 X +V +5 9 Q +0 X +(#include ) 167.57 696.59 T +(#include ) 167.57 685.59 T +(#incldue ) 167.57 674.59 T +(#include ) 167.57 663.59 T +(#include ) 167.57 652.59 T +-0.52 (// ****************************************************************) 167.57 630.59 P +(// * callback:) 167.57 619.59 T +(// * This is the callback function that will be called when the) 167.57 608.59 T +(// * message has been processed to completion. This function is) 167.57 597.59 T +(// * disregarding CDEV_DISCONNECTED and CDEV_RECONNECTED messages.) 167.57 586.59 T +-0.52 (// ****************************************************************) 167.57 575.59 P +(void callback\050int status,) 167.57 564.59 T +(void * arg,) 239.57 553.59 T +(cdevRequestObject & req,) 239.57 542.59 T +(cdevData & data\051) 239.57 531.59 T +({) 185.57 520.59 T +(double result;) 185.57 509.59 T +(int & userFlag = *arg;) 185.57 498.59 T +(// ************************************************************) 185.57 476.59 T +(// * Save the completion status and print the result) 185.57 465.59 T +(// ************************************************************) 185.57 454.59 T +(if\050status!=CDEV_DISCONNECTED && status!=CDEV_RECONNECTED\051) 185.57 443.59 T +({) 203.57 432.59 T +(userFlag = status;) 203.57 421.59 T +(data.get\050\322value\323, &result\051;) 203.57 410.59 T +(printf\050\322I have received value %f\323, result\051;) 203.57 399.59 T +(}) 203.57 388.59 T +(}) 185.57 377.59 T +(void main\050\051) 167.57 355.59 T +({) 185.57 344.59 T +(// ************************************************************) 185.57 333.59 T +(// * Integer flag for detecting callback completion) 185.57 322.59 T +(// ************************************************************) 185.57 311.59 T +(int userFlag = 100;) 185.57 300.59 T +(// ************************************************************) 185.57 278.59 T +(// * Obtain a reference to the default system.) 185.57 267.59 T +(// ************************************************************) 185.57 256.59 T +(cdevSystem & default = cdevSystem::defaultSystem\050\051;) 185.57 245.59 T +(// ************************************************************) 185.57 223.59 T +(// * Obtain a pointer to the device \322MQB1S01\323.) 185.57 212.59 T +(// ************************************************************) 185.57 201.59 T +(cdevDevice * device = default.getDevice\050\322MQB1S01\323\051;) 185.57 190.59 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "26" 34 +%%Page: "27" 35 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(4. Using the cde) 432.99 739 T +(vDe) 497.75 739 T +(vice Object) 513.49 739 T +0 10 Q +(27) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +(Figure 19: Using the sendCallbac) 180 714 T +(k method of a cde) 315.38 714 T +(vDe) 386.65 714 T +(vice object \050contin) 402.38 714 T +(ued\051) 474.32 714 T +180 81 558 720 C +180 473.19 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.93 475.28 559.5 703.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +179.96 479.36 553.92 709.29 R +7 X +V +0 X +N +185.21 485.07 546.49 704.24 R +7 X +V +5 9 Q +0 X +(// ************************************************************) 203.21 698.24 T +(// * Construct the cdevCallback object that will be used to) 203.21 687.24 T +(// * specify the callback function and the user argument.) 203.21 676.24 T +(// ************************************************************) 203.21 665.24 T +(cdevCallback cb\050callback, &userFlag\051;) 203.21 654.24 T +(// ************************************************************) 203.21 632.24 T +(// * Transmit the message to the device using the sendCallback) 203.21 621.24 T +(// * mechanism. Since the message requires no outbound data,) 203.21 610.24 T +(// * the outbound cdevData object is NULL.) 203.21 599.24 T +(// ************************************************************) 203.21 588.24 T +(if\050device->sendCallback\050\322get current\323, NULL, cb\051==CDEV_SUCCESS\051) 203.21 577.24 T +({) 221.21 566.24 T +(// *********************************************************) 221.21 555.24 T +(// * Now, poll the cdevSystem object until the message has) 221.21 544.24 T +(// * been successfully processed.) 221.21 533.24 T +(// *********************************************************) 221.21 522.24 T +(while\050userFlag==100\051 default.poll\050\051;) 221.21 511.24 T +(}) 221.21 500.24 T +(}) 203.21 489.24 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "27" 35 +%%Page: "28" 36 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Using the cde) 54 739 T +(vRequestObject Object) 118.76 739 T +0 10 Q +(28) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(5.) 141.32 710.67 T +(Using the) 162 710.67 T +3 F +(cde) 229.68 710.67 T +(vRequestObject) 253.59 710.67 T +2 F +(Object) 364.06 710.67 T +2 9 Q +(Over) 54 676 T +(vie) 74.6 676 T +(w of the) 86.98 676 T +(cde) 54 665 T +(vRequestObject) 69.37 665 T +(Class) 54 654 T +0 10 Q +-0.05 (The) 162 675.33 P +4 F +-0.05 (cde) 181.96 675.33 P +-0.05 (vRequestObject) 197.78 675.33 P +0 F +-0.05 ( C++ class is the pro) 268.92 675.33 P +-0.05 (vides the user with a higher perf) 359.7 675.33 P +-0.05 (or) 500.85 675.33 P +-0.05 (mance) 509.99 675.33 P +0.84 (interf) 162 663.33 P +0.84 (ace to de) 183.93 663.33 P +0.84 (vices in CDEV) 226.46 663.33 P +0.84 (. Each time a) 290.8 663.33 P +4 F +0.84 (cde) 355.31 663.33 P +0.84 (vDe) 371.13 663.33 P +0.84 (vice) 388.61 663.33 P +0 F +0.84 ( receiv) 406.39 663.33 P +0.84 (es a message str) 436.43 663.33 P +0.84 (ing, it) 515.26 663.33 P +4.58 (m) 162 651.33 P +4.58 (ust parse the message and then connect to the appropr) 170.23 651.33 P +4.58 (iate ser) 457.32 651.33 P +4.58 (vice) 495 651.33 P +4.58 (. The) 512.63 651.33 P +4 F +1.3 (cde) 162 639.33 P +1.3 (vRequestObject) 177.82 639.33 P +0 F +1.3 ( allo) 248.96 639.33 P +1.3 (ws the user to bind a) 268.45 639.33 P +4 F +1.3 (de) 371.3 639.33 P +1.3 (vice) 382.12 639.33 P +0 F +1.3 ( name to a) 399.9 639.33 P +4 F +1.3 (message) 455.13 639.33 P +0 F +1.3 (and then) 499.78 639.33 P +0.72 (connect to the under) 162 627.33 P +0.72 (lying ser) 255.49 627.33 P +0.72 (vice only) 293.74 627.33 P +3 F +0.72 (once) 336.87 627.33 P +0 F +0.72 (. Thereafter) 360.06 627.33 P +0.72 (, the) 411.97 627.33 P +4 F +0.72 (cde) 435.66 627.33 P +0.72 (vRequestObject) 451.48 627.33 P +0 F +0.72 ( will) 522.62 627.33 P +0.45 (remain connected to the ser) 162 615.33 P +0.45 (vice and can process its associated message with m) 288.06 615.33 P +0.45 (uch) 523.88 615.33 P +(higher ef\336ciency) 162 603.33 T +(.) 233.25 603.33 T +0.07 (A) 162 586.33 P +4 F +0.07 (cde) 171.52 586.33 P +0.07 (vRequestObject) 187.34 586.33 P +0 F +0.07 ( ma) 258.48 586.33 P +0.07 (y be created using the static member functions) 274.92 586.33 P +3 F +0.07 (attac) 485.02 586.33 P +0.07 (hPtr) 508.26 586.33 P +0 F +0.07 ( or) 528.26 586.33 P +3 F +1.98 (attac) 162 574.33 P +1.98 (hRef) 185.24 574.33 P +0 F +1.98 (. If one of these methods is used, the object will be created within the) 207.16 574.33 P +-0.07 (conte) 162 562.33 P +-0.07 (xt of the def) 186.16 562.33 P +-0.07 (ault) 237.91 562.33 P +4 F +-0.07 (cde) 256.74 562.33 P +-0.07 (vSystem) 272.56 562.33 P +0 F +-0.07 (. If the application wishes to create a de) 310.9 562.33 P +-0.07 (vice within a) 485.68 562.33 P +4 F +1.77 (cde) 162 550.33 P +1.77 (vSystem) 177.82 550.33 P +0 F +1.77 ( other than the def) 216.16 550.33 P +1.77 (ault, it m) 304.09 550.33 P +1.77 (ust \336rst obtain a pointer to the associated) 345.32 550.33 P +4 F +1.95 (cde) 162 538.33 P +1.95 (vDe) 177.82 538.33 P +1.95 (vice) 195.3 538.33 P +0 F +1.95 ( object from the desired system, and then use the) 213.08 538.33 P +3 F +1.95 (g) 454.33 538.33 P +1.95 (etRequestObject) 460.54 538.33 P +0 F +(method of that) 162 526.33 T +4 F +(cde) 228.71 526.33 T +(vDe) 244.53 526.33 T +(vice) 262.01 526.33 T +0 F +(.) 279.64 526.33 T +1.14 (The message associated with a) 162 509.33 P +4 F +1.14 (cde) 310.56 509.33 P +1.14 (vRequestObject) 326.38 509.33 P +0 F +1.14 ( ma) 397.52 509.33 P +1.14 (y be sent to a de) 415.04 509.33 P +1.14 (vice using) 494.4 509.33 P +3.07 (one of the three send member functions) 162 497.33 P +3.07 (, these are:) 357.01 497.33 P +3 F +3.07 (send, sendNoBloc) 419.02 497.33 P +3.07 (k) 509.13 497.33 P +4 F +3.07 (, and) 514.69 497.33 P +3 F +1.93 (sendCallbac) 162 485.33 P +1.93 (k) 220.71 485.33 P +0 F +1.93 (. The syntax and functionality of these methods is descr) 226.27 485.33 P +1.93 (ibed in the) 490 485.33 P +(section belo) 162 473.33 T +(w) 215.21 473.33 T +(.) 221.83 473.33 T +2.48 (Input and output to the speci\336ed send methods is managed through the use of) 162 456.33 P +4 F +0.75 (cde) 162 444.33 P +0.75 (vData) 177.82 444.33 P +0 F +0.75 ( objects) 203.94 444.33 P +0.75 (. Unlik) 239 444.33 P +0.75 (e the) 267.33 444.33 P +4 F +0.75 (cde) 293.84 444.33 P +0.75 (vRequestObject) 309.66 444.33 P +0 F +0.75 ( object which is bound to a speci\336c) 380.8 444.33 P +0.23 (system, the) 162 432.33 P +4 F +0.23 (cde) 216.38 432.33 P +0.23 (vData) 232.2 432.33 P +0 F +0.23 ( object is completely independent. These objects store the data) 258.32 432.33 P +0.38 (v) 162 420.33 P +0.38 (alues \050called) 166.75 420.33 P +4 F +0.38 (proper) 226.41 420.33 P +0.38 (ties) 255.71 420.33 P +0 F +0.38 (\051 that are sent to and receiv) 271.27 420.33 P +0.38 (ed from de) 395 420.33 P +0.38 (vices) 443.25 420.33 P +0.38 (. The application) 465.88 420.33 P +5.67 (ma) 162 408.33 P +5.67 (y indicate the) 175.59 408.33 P +4 F +5.67 (proper) 254.29 408.33 P +5.67 (ties) 283.59 408.33 P +0 F +5.67 ( that it wishes to receiv) 299.15 408.33 P +5.67 (e as output from the) 428.39 408.33 P +4 F +0.33 (cde) 162 396.33 P +0.33 (vRequestObject) 177.82 396.33 P +0 F +0.33 ( object b) 248.96 396.33 P +0.33 (y specifying them in a special) 287.22 396.33 P +4 F +0.33 (cde) 422.03 396.33 P +0.33 (vData) 437.85 396.33 P +0 F +0.33 ( object called the) 463.97 396.33 P +4 F +(conte) 162 384.33 T +(xt) 186.16 384.33 T +0 F +(.) 193.94 384.33 T +0.28 (Examples at the end of this section will illustr) 162 367.33 P +0.28 (ate the correct w) 362.01 367.33 P +0.28 (a) 436.63 367.33 P +0.28 (ys to implement these) 441.89 367.33 P +(oper) 162 355.33 T +(ations) 181.91 355.33 T +(.) 208.44 355.33 T +2 9 Q +(Pub) 54 329 T +(lic Member) 70.91 329 T +(Functions of the) 54 318 T +(cde) 54 307 T +(vRequestObject) 69.37 307 T +(Class) 54 296 T +2 10 Q +(attac) 162 328.33 T +(hRef) 185.24 328.33 T +4 F +-0.3 (static cde) 261.29 328.33 S +-0.3 (vRequestObject& attachRef \050char *de) 300.23 328.33 S +-0.3 (vice) 456.17 328.33 S +-0.3 (, char * msg\051;) 472.6 328.33 S +0 F +5.63 (Obtains a ref) 261.29 311.33 P +5.63 (erence to a) 329.49 311.33 P +4 F +5.63 (cde) 399.18 311.33 P +5.63 (vRequestObject) 415.01 311.33 P +0 F +5.63 ( object b) 486.14 311.33 P +5.63 (y) 535 311.33 P +0.64 (specifying the name of the de) 261.43 299.33 P +0.64 (vice and the message str) 394.94 299.33 P +0.64 (ing. By) 508.79 299.33 P +4.63 (def) 261.43 287.33 P +4.63 (ault, the ne) 275.03 287.33 P +4.63 (w object will be managed b) 333.57 287.33 P +4.63 (y the def) 476.56 287.33 P +4.63 (ault) 523.88 287.33 P +4 F +(cde) 261.43 275.33 T +(vSystem) 277.25 275.33 T +0 F +(.) 315.59 275.33 T +2 F +(attac) 162 251.33 T +(hRef) 185.24 251.33 T +4 F +-0.5 (static cde) 261.29 251.33 S +-0.5 (vRequestObject& attachRef \050cde) 298.23 251.33 S +-0.5 (vDe) 428.55 251.33 S +-0.5 (vice &de) 444.53 251.33 S +-0.5 (v) 478.58 251.33 S +-0.5 (, char * msg\051;) 482.28 251.33 S +0 F +5.63 (Obtains a ref) 261.29 234.33 P +5.63 (erence to a) 329.49 234.33 P +4 F +5.63 (cde) 399.18 234.33 P +5.63 (vRequestObject) 415.01 234.33 P +0 F +5.63 ( object b) 486.14 234.33 P +5.63 (y) 535 234.33 P +0.49 (pro) 261.43 222.33 P +0.49 (viding a ref) 275.73 222.33 P +0.49 (erence to the associated) 325.32 222.33 P +4 F +0.49 (cde) 439.02 222.33 P +0.49 (vDe) 454.84 222.33 P +0.49 (vice) 472.32 222.33 P +0 F +0.49 ( object and) 490.1 222.33 P +-0.07 (the message str) 261.43 210.33 P +-0.07 (ing. By def) 332.59 210.33 P +-0.07 (ault, the ne) 379.41 210.33 P +-0.07 (w object will be managed) 428.55 210.33 P +(b) 261.43 198.33 T +(y the def) 266.79 198.33 T +(ault) 304.85 198.33 T +4 F +(cde) 323.75 198.33 T +(vSystem) 339.57 198.33 T +0 F +(.) 377.91 198.33 T +2 F +(attac) 162 174.33 T +(hPtr) 185.24 174.33 T +4 F +-0.5 (static cde) 261.29 174.33 S +-0.5 (vRequestObject* attachPtr \050char *de) 298.23 174.33 S +-0.5 (vice) 441.61 174.33 S +-0.5 (, char * msg\051;) 457.24 174.33 S +0 F +2.04 (Obtains a pointer to a) 261.29 157.33 P +4 F +2.04 (cde) 369.87 157.33 P +2.04 (vRequestObject) 385.69 157.33 P +0 F +2.04 ( b) 456.83 157.33 P +2.04 (y specifying the) 467 157.33 P +-0.24 (name of the de) 261.43 145.33 P +-0.24 (vice and the message str) 327.13 145.33 P +-0.24 (ing. By def) 437.5 145.33 P +-0.24 (ault, the ne) 483.97 145.33 P +-0.24 (w) 532.78 145.33 P +(object will be managed b) 261.43 133.33 T +(y the def) 371.28 133.33 T +(ault) 409.34 133.33 T +4 F +(cde) 428.24 133.33 T +(vSystem) 444.06 133.33 T +0 F +(.) 482.4 133.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "28" 36 +%%Page: "29" 37 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Using the cde) 400.7 739 T +(vRequestObject Object) 465.46 739 T +0 10 Q +(29) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(attac) 180 713.33 T +(hPtr) 203.24 713.33 T +4 F +-0.5 (static cde) 279.29 713.33 S +-0.5 (vRequestObject* attachPtr \050cde) 316.23 713.33 S +-0.5 (vDe) 440.99 713.33 S +-0.5 (vice &de) 456.97 713.33 S +-0.5 (v) 491.02 713.33 S +-0.5 (, char * msg\051;) 494.72 713.33 S +0 F +3.59 (Obtains a pointer to a) 279.29 696.33 P +4 F +3.59 (cde) 395.6 696.33 P +3.59 (vRequestObject) 411.42 696.33 P +0 F +3.59 ( b) 482.56 696.33 P +3.59 (y pro) 494.29 696.33 P +3.59 (viding a) 519.96 696.33 P +5.54 (ref) 279.43 684.33 P +5.54 (erence to the associated) 290.8 684.33 P +4 F +5.54 (cde) 424.7 684.33 P +5.54 (vDe) 440.52 684.33 P +5.54 (vice) 458 684.33 P +0 F +5.54 ( object and the) 475.78 684.33 P +0.29 (message str) 279.43 672.33 P +0.29 (ing. By def) 334.33 672.33 P +0.29 (ault, the ne) 381.86 672.33 P +0.29 (w object will be managed b) 431.71 672.33 P +0.29 (y) 553 672.33 P +(the def) 279.43 660.33 T +(ault) 309.71 660.33 T +4 F +(cde) 328.61 660.33 T +(vSystem) 344.43 660.33 T +0 F +(.) 382.77 660.33 T +2 F +(detac) 180 636.33 T +(h) 206.02 636.33 T +4 F +(static v) 279.29 636.33 T +(oid detach \050cde) 310.16 636.33 T +(vRequestObject& de) 378.23 636.33 T +(v\051;) 469.64 636.33 T +0 F +3.92 (Remo) 279.29 619.33 P +3.92 (v) 305.81 619.33 P +3.92 (es a ref) 310.56 619.33 P +3.92 (erenced cde) 351.44 619.33 P +3.92 (vRequestObject object from its) 410.09 619.33 P +2.47 (associated cde) 279.43 607.33 P +2.47 (vSystem object. Ordinar) 348.3 607.33 P +2.47 (y applications should) 460.24 607.33 P +(ne) 279.43 595.33 T +(v) 290.25 595.33 T +(er use this command.) 295 595.33 T +2 F +(detac) 180 571.33 T +(h) 206.02 571.33 T +4 F +(static v) 279.29 571.33 T +(oid detach \050cde) 310.16 571.33 T +(vRequestObject* de) 378.23 571.33 T +(v\051;) 466.86 571.33 T +0 F +0.55 (Detaches the cde) 279.29 554.33 P +0.55 (vRequestObject object speci\336ed b) 357.9 554.33 P +0.55 (y de) 510.52 554.33 P +0.55 (v from) 529.67 554.33 P +-0.07 (its associated cde) 279.43 542.33 P +-0.07 (vSystem object. Ordinar) 358.47 542.33 P +-0.07 (y applications should) 465.32 542.33 P +(ne) 279.43 530.33 T +(v) 290.25 530.33 T +(er use this command.) 295 530.33 T +2 F +(messa) 180 506.33 T +(g) 211.03 506.33 T +(e) 217.24 506.33 T +4 F +(char *message \050v) 279.29 506.33 T +(oid\051 const;) 356.84 506.33 T +0 F +3.82 (Retr) 279.29 489.33 P +3.82 (ie) 298.33 489.33 P +3.82 (v) 305.81 489.33 P +3.82 (es the message str) 310.56 489.33 P +3.82 (ing that is associated with this) 406.64 489.33 P +(cde) 279.43 477.33 T +(vRequestObject.) 295.25 477.33 T +2 F +(de) 180 453.33 T +(vice) 191.52 453.33 T +4 F +(cde) 279.29 453.33 T +(vDe) 295.11 453.33 T +(vice &de) 312.59 453.33 T +(vice \050v) 350.64 453.33 T +(oid\051 const;) 379.28 453.33 T +0 F +5.41 (Retr) 279.29 436.33 P +5.41 (ie) 298.33 436.33 P +5.41 (v) 305.81 436.33 P +5.41 (es a ref) 310.56 436.33 P +5.41 (erence to the cde) 354.42 436.33 P +5.41 (vDe) 447.6 436.33 P +5.41 (vice object that is) 465.08 436.33 P +(associated with this cde) 279.43 424.33 T +(vRequestObject.) 384.73 424.33 T +2 F +(system) 180 400.33 T +4 F +(cde) 279.29 400.33 T +(vSystem& system \050v) 295.11 400.33 T +(oid\051 const;) 385.43 400.33 T +0 F +0.14 (Retr) 279.29 383.33 P +0.14 (ie) 298.33 383.33 P +0.14 (v) 305.81 383.33 P +0.14 (es a ref) 310.56 383.33 P +0.14 (erence to the under) 343.88 383.33 P +0.14 (lying cde) 431.17 383.33 P +0.14 (vSystem object that) 470.46 383.33 P +(manages this cde) 279.43 371.33 T +(vRequestObject.) 357.5 371.33 T +2 F +(ser) 180 347.33 T +(vice) 195.11 347.33 T +4 F +(cde) 279.29 347.33 T +(vSer) 295.11 347.33 T +(vice& ser) 315.97 347.33 T +(vice \050v) 357.39 347.33 T +(oid\051 const;) 386.03 347.33 T +0 F +0.1 (Retr) 279.29 330.33 P +0.1 (ie) 298.33 330.33 P +0.1 (v) 305.81 330.33 P +0.1 (es a ref) 310.56 330.33 P +0.1 (erence to the under) 343.81 330.33 P +0.1 (lying cde) 430.98 330.33 P +0.1 (vSer) 470.24 330.33 P +0.1 (vice object that) 491.1 330.33 P +(this cde) 279.43 318.33 T +(vRequestObject is attached to) 313.59 318.33 T +(.) 446.59 318.33 T +2 F +(g) 180 294.33 T +(etState) 186.21 294.33 T +4 F +(int getState \050v) 279.29 294.33 T +(oid\051;) 340.74 294.33 T +0 F +-0.15 (Obtains the state of the under) 279.29 277.33 P +-0.15 (lying de) 410.42 277.33 P +-0.15 (vice) 444.43 277.33 P +-0.15 (. This function retur) 462.06 277.33 P +-0.15 (ns) 547.44 277.33 P +(one of the f) 279.43 265.33 T +(ollo) 329.17 265.33 T +(wing v) 344.58 265.33 T +(alues as de\336ned in) 372.67 265.33 T +4 F +(cde) 458.83 265.33 T +(vErrCode) 474.65 265.33 T +(.h) 516.73 265.33 T +0 F +(.) 525.07 265.33 T +2 F +(CDEV_ST) 279.29 248.33 T +(A) 324.51 248.33 T +(TE_CONNECTED:) 330.83 248.33 T +0 F +(Object is connected.) 441 248.33 T +2 F +(CDEV_ST) 279.29 231.33 T +(A) 324.51 231.33 T +(TE_NO) 330.83 231.33 T +(TCONNECTED:) 363.77 231.33 T +0 F +(Object is not connected.) 441 231.33 T +2 F +(CDEV_ST) 279.29 214.33 T +(A) 324.51 214.33 T +(TE_INV) 330.83 214.33 T +(ALID:) 365.04 214.33 T +0 F +(Object is in) 441 214.33 T +(v) 490.26 214.33 T +(alid.) 495.01 214.33 T +3.16 (The ser) 279.29 180.33 P +3.16 (vice de) 316.65 180.33 P +3.16 (v) 351.2 180.33 P +3.16 (eloper is responsib) 355.95 180.33 P +3.16 (le f) 446 180.33 P +3.16 (or implementing this) 462.2 180.33 P +(function correctly in the ser) 279.43 168.33 T +(vice related cde) 399.22 168.33 T +(vRequestObject.) 468.95 168.33 T +2 F +(g) 180 144.33 T +(etAccess) 186.21 144.33 T +4 F +(int getAccess \050v) 279.29 144.33 T +(oid\051;) 349.62 144.33 T +0 F +5.3 (Obtains access control inf) 279.29 127.33 P +5.3 (or) 409.39 127.33 P +5.3 (mation about the under) 418.53 127.33 P +5.3 (lying) 537.44 127.33 P +2.27 (de) 279.43 115.33 P +2.27 (vice) 290.25 115.33 P +2.27 (. This function retur) 307.88 115.33 P +2.27 (ns one of the f) 400.54 115.33 P +2.27 (ollo) 472.71 115.33 P +2.27 (wing v) 488.12 115.33 P +2.27 (alues as) 518.49 115.33 P +(de\336ned in cde) 279.43 103.33 T +(vErrCode) 341.39 103.33 T +(.h.) 383.47 103.33 T +2 F +(CDEV_A) 279.29 86.33 T +(CCESS_NONE:) 319.45 86.33 T +0 F +(No access to attr) 423 86.33 T +(ib) 498.18 86.33 T +(ute) 505.76 86.33 T +(.) 519.51 86.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "29" 37 +%%Page: "30" 38 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Using the cde) 54 739 T +(vRequestObject Object) 118.76 739 T +0 10 Q +(30) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(CDEV_A) 261.29 713.33 T +(CCESS_READONL) 301.45 713.33 T +(Y) 389.7 713.33 T +(:) 395.87 713.33 T +0 F +(Read-only access) 405 713.33 T +(.) 484.32 713.33 T +2 F +(CDEV_A) 261.29 696.33 T +(CCESS_WRITE:) 301.45 696.33 T +0 F +(Read-wr) 405 696.33 T +(ite access) 442.93 696.33 T +(.) 487.24 696.33 T +3.16 (The ser) 261.29 679.33 P +3.16 (vice de) 298.65 679.33 P +3.16 (v) 333.2 679.33 P +3.16 (eloper is responsib) 337.95 679.33 P +3.16 (le f) 428 679.33 P +3.16 (or implementing this) 444.2 679.33 P +(function correctly in the ser) 261.43 667.33 T +(vice related cde) 381.22 667.33 T +(vRequestObject.) 450.95 667.33 T +2 F +(setConte) 162 643.33 T +(xt) 204.63 643.33 T +4 F +(int setConte) 261.29 643.33 T +(xt \050cde) 314.35 643.33 T +(vData& cxt\051;) 344.06 643.33 T +0 F +0.17 (Used to inser) 261.29 626.33 P +0.17 (t a cde) 320.93 626.33 P +0.17 (vData object containing tagged v) 350.98 626.33 P +0.17 (alues that) 496.47 626.33 P +0.16 (control optional beha) 261.43 614.33 P +0.16 (vior of the under) 354.38 614.33 P +0.16 (lying de) 427.28 614.33 P +0.16 (vice) 461.6 614.33 P +0.16 (. The conte) 479.23 614.33 P +0.16 (xt) 532.22 614.33 P +4.55 (is often used to specify which proper) 261.43 602.33 P +4.55 (ties \050v) 450.86 602.33 P +4.55 (alue) 481.83 602.33 P +4.55 (, status) 500.58 602.33 P +4.55 (,) 537.22 602.33 P +0.41 (se) 261.43 590.33 P +0.41 (v) 271.69 590.33 P +0.41 (er) 276.44 590.33 P +0.41 (ity\051 a de) 285.48 590.33 P +0.41 (vice retur) 321.56 590.33 P +0.41 (ns in response to a \322get\323 message) 363.34 590.33 P +0.41 (. The) 516.8 590.33 P +2.61 (ser) 261.43 578.33 P +2.61 (vice de) 275.62 578.33 P +2.61 (v) 309.61 578.33 P +2.61 (eloper ma) 314.36 578.33 P +2.61 (y o) 361.13 578.33 P +2.61 (v) 376.93 578.33 P +2.61 (err) 381.68 578.33 P +2.61 (ide the def) 394.05 578.33 P +2.61 (ault beha) 445.66 578.33 P +2.61 (vior of this) 489.21 578.33 P +(method to better accomodate the requirements of the ser) 261.43 566.33 T +(vice) 514.08 566.33 T +(.) 531.71 566.33 T +2 F +(g) 162 542.33 T +(etConte) 168.21 542.33 T +(xt) 205.28 542.33 T +4 F +(cde) 261.29 542.33 T +(vData & getConte) 277.11 542.33 T +(xt \050v) 355.74 542.33 T +(oid\051;) 374.38 542.33 T +0 F +0.63 (Retr) 261.29 525.33 P +0.63 (ie) 280.33 525.33 P +0.63 (v) 287.81 525.33 P +0.63 (es a ref) 292.56 525.33 P +0.63 (erence to the cde) 326.87 525.33 P +0.63 (vData object that contains the) 405.73 525.33 P +6.79 (conte) 261.43 513.33 P +6.79 (xt f) 285.59 513.33 P +6.79 (or a speci\336c cde) 305.42 513.33 P +6.79 (vRequestObject. The ser) 397.74 513.33 P +6.79 (vice) 522.22 513.33 P +0.93 (de) 261.43 501.33 P +0.93 (v) 272.25 501.33 P +0.93 (eloper ma) 277 501.33 P +0.93 (y o) 322.09 501.33 P +0.93 (v) 336.21 501.33 P +0.93 (err) 340.96 501.33 P +0.93 (ide the def) 353.33 501.33 P +0.93 (ault beha) 401.59 501.33 P +0.93 (vior of this method to) 443.46 501.33 P +(better accomodate the requirements of the ser) 261.43 489.33 T +(vice) 466.83 489.33 T +(.) 484.46 489.33 T +2 F +(g) 162 465.33 T +(etPriv) 168.21 465.33 T +(ate) 195.8 465.33 T +4 F +(v) 261.29 465.33 T +(oid * getPr) 266.04 465.33 T +(iv) 312.88 465.33 T +(ate \050v) 319.85 465.33 T +(oid\051;) 344.61 465.33 T +0 F +2.09 (Retr) 261.29 448.33 P +2.09 (ie) 280.33 448.33 P +2.09 (v) 287.81 448.33 P +2.09 (es a pointer to a data object that w) 292.56 448.33 P +2.09 (as placed in this) 462.02 448.33 P +(object using the setPr) 261.43 436.33 T +(iv) 357.74 436.33 T +(ate function.) 364.71 436.33 T +2 F +(setPriv) 162 412.33 T +(ate) 195.15 412.33 T +4 F +(v) 261.29 412.33 T +(oid setPr) 266.04 412.33 T +(iv) 305.65 412.33 T +(ate \050v) 312.62 412.33 T +(oid * data\051;) 337.38 412.33 T +0 F +9.56 (Associates a user speci\336ed data object with this) 261.29 395.33 P +4 F +1.78 (cde) 261.43 383.33 P +1.78 (vRequestObject) 277.25 383.33 P +0 F +1.78 (. The pointer can be retr) 348.39 383.33 P +1.78 (ie) 464.17 383.33 P +1.78 (v) 471.65 383.33 P +1.78 (ed later using) 476.4 383.33 P +(the) 261.43 371.33 T +4 F +(getPr) 278.11 371.33 T +(iv) 302.16 371.33 T +(ate) 309.13 371.33 T +0 F +( method.) 323.03 371.33 T +2 F +(send) 162 347.33 T +4 F +(int send \050cde) 261.29 347.33 T +(vData &out, cde) 318.24 347.33 T +(vData& result\051;) 389.09 347.33 T +(int send \050cde) 261.29 335.33 T +(vData *out, cde) 318.24 335.33 T +(vData& result\051;) 386.31 335.33 T +(int send \050cde) 261.29 323.33 T +(vData &out, cde) 318.24 323.33 T +(vData* result\051;) 389.09 323.33 T +(int send \050cde) 261.29 311.33 T +(vData *out, cde) 318.24 311.33 T +(vData* result\051;) 386.31 311.33 T +0 F +1.74 (The send function is the standard method f) 261.29 294.33 P +1.74 (or synchronously) 462.68 294.33 P +5.38 (comm) 261.43 282.33 P +5.38 (unicating with a de) 288.55 282.33 P +5.38 (vice) 387.21 282.33 P +5.38 (. The) 404.84 282.33 P +4 F +5.38 (out) 441.16 282.33 P +0 F +5.38 (cde) 463.22 282.33 P +5.38 (vData object) 479.04 282.33 P +3.44 (contains an) 261.43 270.33 P +3.44 (y proper) 315.86 270.33 P +3.44 (ty v) 356.38 270.33 P +3.44 (alues that the de) 375.14 270.33 P +3.44 (vice will need to) 459.1 270.33 P +1.53 (perf) 261.43 258.33 P +1.53 (or) 278.36 258.33 P +1.53 (m the task. The) 287.5 258.33 P +4 F +1.53 (result) 365.34 258.33 P +0 F +1.53 ( cde) 389.79 258.33 P +1.53 (vData object will contain the) 409.92 258.33 P +3.82 (output proper) 261.43 246.33 P +3.82 (ties that resulted from the call. The ser) 325.13 246.33 P +3.82 (vice) 522.22 246.33 P +1.67 (de) 261.43 234.33 P +1.67 (v) 272.25 234.33 P +1.67 (eloper is responsib) 277 234.33 P +1.67 (le f) 364.07 234.33 P +1.67 (or implementing this method in the) 378.79 234.33 P +1.09 (ser) 261.43 222.33 P +1.09 (vice speci\336ed cde) 275.62 222.33 P +1.09 (vRequestObject. This function will retur) 356.43 222.33 P +1.09 (n) 534.44 222.33 P +(one of the error code de\336ned in cde) 261.43 210.33 T +(vErrCode) 419 210.33 T +(.h.) 461.08 210.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "30" 38 +%%Page: "31" 39 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Using the cde) 400.7 739 T +(vRequestObject Object) 465.46 739 T +0 10 Q +(31) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +(Figure 20: Retur) 180 714 T +(n codes gener) 247.75 714 T +(ated b) 304.7 714 T +(y the send method) 329.54 714 T +2 10 Q +(sendNoBloc) 180 404.19 T +(k) 238.14 404.19 T +4 F +(int sendNoBloc) 279.29 404.19 T +(k \050cde) 346.34 404.19 T +(vData &out, cde) 373.27 404.19 T +(vData &result\051;) 444.12 404.19 T +(int sendNoBloc) 279.29 392.19 T +(k \050cde) 346.34 392.19 T +(vData *out, cde) 373.27 392.19 T +(vData &result\051;) 441.34 392.19 T +(int sendNoBloc) 279.29 380.19 T +(k \050cde) 346.34 380.19 T +(vData &out, cde) 373.27 380.19 T +(vData *result\051;) 444.12 380.19 T +(int sendNoBloc) 279.29 368.19 T +(k \050cde) 346.34 368.19 T +(vData *out, cde) 373.27 368.19 T +(vData *result\051;) 441.34 368.19 T +0 F +3.34 (The) 279.29 351.19 P +4 F +3.34 (sendNoBloc) 302.63 351.19 P +3.34 (k) 356.34 351.19 P +0 F +3.34 ( method uses the same par) 361.34 351.19 P +3.34 (ameters and) 499.08 351.19 P +1.51 (syntax as the) 279.43 339.19 P +4 F +1.51 (send) 345.67 339.19 P +0 F +1.51 ( method. Ho) 367.36 339.19 P +1.51 (w) 424.7 339.19 P +1.51 (e) 431.82 339.19 P +1.51 (v) 437.08 339.19 P +1.51 (er) 441.83 339.19 P +1.51 (, r) 450.22 339.19 P +1.51 (ather than w) 460.53 339.19 P +1.51 (aiting f) 518.43 339.19 P +1.51 (or) 549.11 339.19 P +0.89 (the under) 279.43 327.19 P +0.89 (lying ser) 322.72 327.19 P +0.89 (vice to respond to the request, this function) 361.14 327.19 P +0.54 (will retur) 279.43 315.19 P +0.54 (n immediately) 317.44 315.19 P +0.54 (.The caller ma) 378.65 315.19 P +0.54 (y use a cde) 442.77 315.19 P +0.54 (vGroup object) 495.21 315.19 P +1.44 (in order to detect when the tr) 279.43 303.19 P +1.44 (ansaction has been completed.) 415.27 303.19 P +3.14 (The ser) 279.43 291.19 P +3.14 (vice de) 316.78 291.19 P +3.14 (v) 351.3 291.19 P +3.14 (eloper is responsib) 356.05 291.19 P +3.14 (le f) 446.06 291.19 P +3.14 (or implementing this) 462.24 291.19 P +(method in the ser) 279.43 279.19 T +(vice\325) 356.99 279.19 T +(s cde) 376.49 279.19 T +(vRequestObject.) 400.09 279.19 T +2 F +(sendCallbac) 180 255.19 T +(k) 238.71 255.19 T +4 F +(int sendCallbac) 279.29 255.19 T +(k \050cde) 347.45 255.19 T +(vData &out, cde) 374.38 255.19 T +(vCallbac) 445.23 255.19 T +(k &callbac) 483.37 255.19 T +(k\051;) 528.74 255.19 T +(int sendCallbac) 279.29 243.19 T +(k \050cde) 347.45 243.19 T +(vData *out, cde) 374.38 243.19 T +(vCallbac) 442.45 243.19 T +(k &callbac) 480.59 243.19 T +(k\051;) 525.96 243.19 T +0 F +-0.05 (The) 180 226.19 P +4 F +-0.05 (sendCallbac) 199.96 226.19 P +-0.05 (k) 254.78 226.19 P +0 F +-0.05 (function is the standard method f) 262.51 226.19 P +-0.05 (or asynchronously comm) 407.04 226.19 P +-0.05 (unicating) 517.98 226.19 P +-0.23 (with a de) 180 214.19 P +-0.23 (vice) 219.27 214.19 P +-0.23 (. Rather than pro) 236.9 214.19 P +-0.23 (viding a) 311.11 214.19 P +4 F +-0.23 (result) 347.9 214.19 P +0 F +-0.23 ( cde) 372.35 214.19 P +-0.23 (vData object, this method requires the) 390.72 214.19 P +1.68 (user to pro) 180 202.19 P +1.68 (vide the address of a cde) 231.01 202.19 P +1.68 (vCallbac) 350.83 202.19 P +1.68 (k object. This object contains a user) 388.97 202.19 P +1.15 (supplied pointer and the address of a function to call when the message has been) 180 190.19 P +1.45 (successfully processed. The ser) 180 178.19 P +1.45 (vice de) 326.93 178.19 P +1.45 (v) 359.76 178.19 P +1.45 (eloper is responsib) 364.51 178.19 P +1.45 (le f) 451.13 178.19 P +1.45 (or implementing this) 465.62 178.19 P +(method in the ser) 180 166.19 T +(vice speci\336ed cde) 257.56 166.19 T +(vRequestObject.) 336.18 166.19 T +2 F +(Sample Code) 72 137.19 T +0 F +8.25 (The f) 180 137.19 P +8.25 (ollo) 210.74 137.19 P +8.25 (wing sample applications illustr) 226.15 137.19 P +8.25 (ate man) 388.04 137.19 P +8.25 (y of the uses of the) 432.27 137.19 P +0.85 (cde) 180 125.19 P +0.85 (vRequestObject object. Additionally) 195.82 125.19 P +0.85 (, these e) 353.8 125.19 P +0.85 (xamples sho) 393.55 125.19 P +0.85 (w in depth usage of the) 450.38 125.19 P +(cde) 180 113.19 T +(vData object and the concept of conte) 195.82 113.19 T +(xt.) 363.4 113.19 T +180 162.86 558 720 C +180 424.86 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.29 428.38 559.86 703.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +180.32 432.33 554.27 708.57 R +7 X +V +0 X +N +185.57 434.78 546.85 704.71 R +7 X +V +5 10 Q +0 X +(CDEV_SUCCESS: The message was processed successfully.) 185.57 698.04 T +(CDEV_ERROR: Failed to process message.) 185.57 684.04 T +(CDEV_INVALIDOBJ: Invalid CDEV request object used.) 185.57 670.04 T +(CDEV_INVALIDARG: Invalid argument passed to CDEV call.) 185.57 656.04 T +(CDEV_INVALIDSVC: Wrong service during dynamic loading.) 185.57 642.04 T +(CDEV_NOTCONNECTED: Not connected to low level network) 185.57 628.04 T +( service.) 185.57 614.04 T +(CDEV_IOFAILED: Low level network service IO failed.) 185.57 600.04 T +(CDEV_CONFLICT: Conflicts of data types or tags.) 185.57 586.04 T +(CDEV_NOTFOUND: Cannot find specified data in cdevData.) 185.57 572.04 T +(CDEV_TIMEOUT: Time out.) 185.57 558.04 T +(CDEV_CONVERT: cdevData conversion error.) 185.57 544.04 T +(CDEV_OUTOFRANGE: Value out of range for device attribute.) 185.57 530.05 T +(CDEV_NOACCESS: Insufficient access to perform request.) 185.57 516.05 T +(CDEV_ACCESSCHANGED: Change in access permission of device.) 185.57 502.05 T +(CDEV_DISCONNECTED: The service has lost contact with the) 185.57 488.05 T +( device.) 185.57 474.05 T +-1.07 (CDEV_RECONNECTED: The service has regained contact with the) 185.57 460.05 P +( device.) 185.57 446.05 T +180 162.86 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "31" 39 +%%Page: "32" 40 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Using the cde) 54 739 T +(vRequestObject Object) 118.76 739 T +0 10 Q +(32) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Attac) 54 714 T +(hing to a) 76.41 714 T +(cde) 54 703 T +(vRequestObject) 69.37 703 T +(Object) 54 692 T +0 10 Q +2.73 (Within a cde) 162 713.33 P +2.73 (vSystem object, a cde) 222.18 713.33 P +2.73 (vRequestObject is created only once f) 327.88 713.33 P +2.73 (or an) 509.63 713.33 P +2.73 (y) 535 713.33 P +0.83 (speci\336ed) 162 701.33 P +4 F +0.83 (de) 205.07 701.33 P +0.83 (vice name) 215.89 701.33 P +0 F +0.83 ( /) 262.29 701.33 P +4 F +0.83 (message str) 272.29 701.33 P +0.83 (ing) 327.73 701.33 P +0 F +0.83 ( combination. After that, all requests f) 341.07 701.33 P +0.83 (or that) 510.82 701.33 P +4.01 (combination are giv) 162 689.33 P +4.01 (en a pointer to the same cde) 256.46 689.33 P +4.01 (vRequestObject object. This) 406.94 689.33 P +(technique is called) 162 677.33 T +4 F +(attaching) 247.04 677.33 T +0 F +( to a cde) 287.62 677.33 T +(vRequestObject.) 325.68 677.33 T +1.25 (There are tw) 162 660.33 P +1.25 (o approaches to attaching to a) 220.53 660.33 P +4 F +1.25 (cde) 365.36 660.33 P +1.25 (vRequestObject) 381.17 660.33 P +0 F +1.25 (; through a speci\336c) 452.31 660.33 P +4 F +2.69 (cde) 162 648.33 P +2.69 (vDe) 177.82 648.33 P +2.69 (vice) 195.3 648.33 P +0 F +2.69 ( object, or through the) 213.08 648.33 P +4 F +2.69 (cde) 326.57 648.33 P +2.69 (vRequestObject) 342.39 648.33 P +0 F +2.69 ( interf) 413.53 648.33 P +2.69 (ace) 440.92 648.33 P +2.69 (. Attaching to the) 456.89 648.33 P +0.86 (de) 162 636.33 P +0.86 (vice using the) 172.82 636.33 P +4 F +0.86 (cde) 239.31 636.33 P +0.86 (vDe) 255.13 636.33 P +0.86 (vice) 272.61 636.33 P +0 F +0.86 ( object has the bene\336t of making it possib) 290.39 636.33 P +0.86 (le to manage) 480.48 636.33 P +2.22 (the) 162 624.33 P +4 F +2.22 (cde) 180.9 624.33 P +2.22 (vRequestObject) 196.72 624.33 P +0 F +2.22 ( using the) 267.86 624.33 P +4 F +2.22 (cde) 320.66 624.33 P +2.22 (vSystem) 336.48 624.33 P +0 F +2.22 ( object associated with that de) 374.82 624.33 P +2.22 (vice) 519.59 624.33 P +2.22 (,) 537.22 624.33 P +0.66 (r) 162 612.33 P +0.66 (ather than using the def) 165.23 612.33 P +0.66 (ault system. Using the) 272.64 612.33 P +4 F +0.66 (cde) 376.44 612.33 P +0.66 (vRequestObject) 392.26 612.33 P +0 F +0.66 ( interf) 463.4 612.33 P +0.66 (ace directly) 488.77 612.33 P +0.84 (alw) 162 600.33 P +0.84 (a) 176.85 600.33 P +0.84 (ys places the ne) 182.11 600.33 P +0.84 (w request object into the def) 256.68 600.33 P +0.84 (ault system, b) 385.64 600.33 P +0.84 (ut has the bene\336t of) 448.81 600.33 P +0.64 (reducing the comple) 162 588.33 P +0.64 (xity of the source code b) 253.01 588.33 P +0.64 (y hiding the use of the) 364.39 588.33 P +4 F +0.64 (cde) 468.82 588.33 P +0.64 (vDe) 484.64 588.33 P +0.64 (vice) 502.12 588.33 P +0 F +0.64 ( and) 519.9 588.33 P +(the) 162 576.33 T +4 F +(cde) 178.68 576.33 T +(vSystem) 194.5 576.33 T +0 F +( objects) 232.84 576.33 T +(.) 267.15 576.33 T +1.27 (The e) 162 559.33 P +1.27 (xample belo) 188.54 559.33 P +1.27 (w illustr) 243.57 559.33 P +1.27 (ates ho) 278.07 559.33 P +1.27 (w to attach to a cde) 311.99 559.33 P +1.27 (vRequestObject with a de) 404.77 559.33 P +1.27 (vice) 522.22 559.33 P +(named \322MQB1S01\323 and the message \322get V) 162 547.33 T +(AL) 356.29 547.33 T +(\323 using the cde) 367.12 547.33 T +(vDe) 432.41 547.33 T +(vice interf) 449.89 547.33 T +(ace) 492.38 547.33 T +(.) 508.35 547.33 T +4 9 Q +(Figure 21: Obtaining a cde) 162 514 T +(vRequestObject from a cde) 270.29 514 T +(vDe) 379.06 514 T +(vice object) 394.79 514 T +162 81 540 720 C +162 85.57 540 511 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +167.93 86.71 541.5 503.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +161.96 90.79 535.92 508.57 R +7 X +V +0 X +N +167.21 94.58 528.49 504.76 R +7 X +V +5 9 Q +0 X +(#include ) 167.21 498.76 T +(#include ) 167.21 487.76 T +(#include ) 167.21 476.76 T +(void main\050\051) 167.21 454.76 T +({) 185.21 443.76 T +(// ************************************************************) 185.21 432.76 T +(// * LONG-HAND METHOD) 185.21 421.76 T +(// * The first step in this approach is to obtain a pointer or) 185.21 410.76 T +(// * reference to the desired system. For this example, the) 185.21 399.76 T +(// * defaultSystem will be used.) 185.21 388.76 T +(// ************************************************************) 185.21 377.76 T +(cdevSystem & default = cdevSystem::defaultSystem\050\051;) 185.21 366.76 T +(// ************************************************************) 185.21 344.76 T +(// * Next, use the getDevice method of the system to obtain) 185.21 333.76 T +(// * a pointer to the specific device.) 185.21 322.76 T +(// ************************************************************) 185.21 311.76 T +(cdevDevice * device = default.getDevice\050\322MQB1S01\323\051;) 185.21 300.76 T +(// ************************************************************) 185.21 278.76 T +(// * Finally, use the getRequestObject method of the cdevDevice) 185.21 267.76 T +(// * class to obtain a cdevRequestObject for the message) 185.21 256.76 T +(// * \322get VAL\323 on device \322MQB1S01\323.) 185.21 245.76 T +(// ************************************************************) 185.21 234.76 T +(cdevRequestObject *req = device->getRequestObject\050\322get bdl\323\051;) 185.21 223.76 T +(// ************************************************************) 185.21 201.76 T +(// * SHORT-HAND METHOD) 185.21 190.76 T +(// * The following shortcut code directly creates a) 185.21 179.76 T +(// * cdevRequestObject and installs it in the default) 185.21 168.76 T +(// * cdevSystem object.) 185.21 157.76 T +(// ************************************************************) 185.21 146.76 T +(cdevRequestObject *req1 =) 185.21 135.76 T +(cdevRequestObject::attachPtr\050\322MQB1S01\323, \322get bdl\323\051;) 203.21 124.76 T +(}) 185.21 113.76 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "32" 40 +%%Page: "33" 41 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Using the cde) 400.7 739 T +(vRequestObject Object) 465.46 739 T +0 10 Q +(33) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 9 Q +(Getting and Setting) 72 714 T +(Conte) 72 703 T +(xt f) 97.36 703 T +(or a) 110.68 703 T +(cde) 72 692 T +(vRequestObject) 87.37 692 T +0 10 Q +0.42 (In CDEV) 180 713.33 P +0.42 (,) 218.07 713.33 P +4 F +0.42 (conte) 224.04 713.33 P +0.42 (xt) 248.2 713.33 P +0 F +0.42 ( ref) 255.98 713.33 P +0.42 (ers to a collection of options that ma) 270.55 713.33 P +0.42 (y be used to alter the w) 433.24 713.33 P +0.42 (a) 538.98 713.33 P +0.42 (y a) 544.24 713.33 P +1.38 (CDEV de) 180 701.33 P +1.38 (vice responds to a speci\336c message) 222.76 701.33 P +1.38 (. Ho) 390.15 701.33 P +1.38 (w conte) 409.72 701.33 P +1.38 (xt inf) 445.26 701.33 P +1.38 (or) 467.46 701.33 P +1.38 (mation eff) 476.6 701.33 P +1.38 (ects the) 521.6 701.33 P +-0.14 (bahvior of a de) 180 689.33 P +-0.14 (vice is de\336ned b) 245.44 689.33 P +-0.14 (y the associated cde) 316.53 689.33 P +-0.14 (vSer) 406.98 689.33 P +-0.14 (vice) 427.84 689.33 P +-0.14 (. Conte) 445.47 689.33 P +-0.14 (xt ma) 479.92 689.33 P +-0.14 (y be used to) 503.93 689.33 P +1.22 (set an) 180 677.33 P +1.22 (y n) 208.31 677.33 P +1.22 (umber of I/O options) 222.77 677.33 P +1.22 (, such as timeouts) 316.88 677.33 P +1.22 (, data acquisition speci\336cations) 400.98 677.33 P +1.22 (, or) 542.33 677.33 P +-0.1 (\337ags to control optional retur) 180 665.33 P +-0.1 (n data. The conte) 306.02 665.33 P +-0.1 (xt is stored and retr) 388.61 665.33 P +-0.1 (ie) 473.96 665.33 P +-0.1 (v) 481.44 665.33 P +-0.1 (ed in the f) 486.19 665.33 P +-0.1 (or) 529.51 665.33 P +-0.1 (m of) 538.65 665.33 P +(a cde) 180 653.33 T +(vData object containing a collection of tagged data items \050called) 204.16 653.33 T +4 F +(proper) 489.3 653.33 T +(ties) 518.6 653.33 T +0 F +(\051.) 534.16 653.33 T +1.15 (The e) 180 636.33 P +1.15 (xample belo) 206.42 636.33 P +1.15 (w illustr) 261.33 636.33 P +1.15 (ates ho) 295.7 636.33 P +1.15 (w the caller ma) 329.5 636.33 P +1.15 (y obtain a cop) 399.88 636.33 P +1.15 (y of the conte) 465.28 636.33 P +1.15 (xt of a) 528.47 636.33 P +2.04 (cde) 180 624.33 P +2.04 (vRequestObject, install a ne) 195.82 624.33 P +2.04 (w conte) 326.24 624.33 P +2.04 (xt f) 362.44 624.33 P +2.04 (or a speci\336c call, and then restore the) 377.52 624.33 P +(pre) 180 612.33 T +(vious conte) 194.15 612.33 T +(xt to the object.) 244.43 612.33 T +4 9 Q +(Figure 22: Alter) 180 579 T +(ing the conte) 244.16 579 T +(xt of a cde) 295.42 579 T +(vRequestObject object) 336.68 579 T +180 81 558 720 C +180 169.26 558 576 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.93 173.73 559.5 568.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +179.96 178.64 553.92 574.29 R +7 X +V +0 X +N +185.21 182.14 546.49 568.76 R +7 X +V +5 9 Q +0 X +(#include ) 185.21 562.76 T +(#include ) 185.21 551.76 T +(#include ) 185.21 540.76 T +(#include ) 185.21 529.76 T +(void main\050\051) 185.21 507.76 T +({) 203.21 496.76 T +(cdevData oldContext, newContext;) 203.21 485.76 T +(// ************************************************************) 203.21 474.76 T +(// * Obtain a cdevRequestObject for \322MQB1S01\323 / \322get bdl\323) 203.21 463.76 T +(// ************************************************************) 203.21 452.76 T +(cdevRequestObject *req =) 203.21 441.76 T +(cdevRequestObject::attachPtr\050\322MQB1S01\323, \322get bdl\323\051;) 221.21 430.76 T +(// ************************************************************) 203.21 408.76 T +(// * Indicate in the newContext cdevData object that this) 203.21 397.76 T +(// * device should return its value, status and severity) 203.21 386.76 T +(// ************************************************************) 203.21 375.76 T +(newContext.insert\050\322value\323, 1\051;) 203.21 364.76 T +(newContext.insert\050\322status\323, 1\051;) 203.21 353.76 T +(newContext.insert\050\322severity\323, 1\051;) 203.21 342.76 T +(// ************************************************************) 203.21 320.76 T +(// * Preserve the contexts of the original device context, and) 203.21 309.76 T +(// * then install the new device context.) 203.21 298.76 T +(// ************************************************************) 203.21 287.76 T +(oldContext = req->getContext\050\051;) 203.21 276.76 T +(req->setContext\050newContext\051;) 203.21 265.76 T +(// ************************************************************) 203.21 243.76 T +(// * After performing the context specific operations, restore) 203.21 232.76 T +(// * the old context to the device.) 203.21 221.76 T +(// ************************************************************) 203.21 210.76 T +(req->setContext\050oldContext\051;) 203.21 199.76 T +(}) 203.21 188.76 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "33" 41 +%%Page: "34" 42 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Using the cde) 54 739 T +(vRequestObject Object) 118.76 739 T +0 10 Q +(34) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +-1.4 (Sending Messa) 54 713.33 P +-1.4 (g) 125.29 713.33 P +-1.4 (es) 131.51 713.33 P +(to a De) 54 701.33 T +(vice) 87.19 701.33 T +(Sync) 54 689.33 T +(hr) 77.8 689.33 T +(onousl) 87.6 689.33 T +(y) 120.23 689.33 T +0 F +1.01 (In most CDEV applications) 162 713.33 P +1.01 (, the caller will w) 283.8 713.33 P +1.01 (ant to send a message to a de) 360.47 713.33 P +1.01 (vice and) 501.75 713.33 P +1.46 (then w) 162 701.33 P +1.46 (ait until a response is receiv) 192.77 701.33 P +1.46 (ed. In order to do this) 323.2 701.33 P +1.46 (, the) 424.85 701.33 P +4 F +1.46 (send) 450.01 701.33 P +0 F +1.46 ( method of the) 471.69 701.33 P +0.44 (cde) 162 689.33 P +0.44 (vRequestObject object ma) 177.82 689.33 P +0.44 (y be used. The) 295.68 689.33 P +4 F +0.44 (send) 366.38 689.33 P +0 F +0.44 ( method receiv) 388.06 689.33 P +0.44 (es tw) 454.28 689.33 P +0.44 (o par) 477.97 689.33 P +0.44 (ameters;) 501.1 689.33 P +0.87 (a cde) 162 677.33 P +0.87 (vData object containing data required b) 187.03 677.33 P +0.87 (y the de) 365.14 677.33 P +0.87 (vice) 402.15 677.33 P +0.87 (, and a cde) 419.79 677.33 P +0.87 (vData object to) 471.57 677.33 P +(receiv) 162 665.33 T +(e the data retur) 188.42 665.33 T +(ned b) 256.49 665.33 T +(y the de) 281.31 665.33 T +(vice) 316.59 665.33 T +(.) 334.22 665.33 T +0.2 (The f) 162 648.33 P +0.2 (ollo) 184.69 648.33 P +0.2 (wing e) 200.1 648.33 P +0.2 (xample demonstr) 228.91 648.33 P +0.2 (ates ho) 305.7 648.33 P +0.2 (w to read an attr) 338.55 648.33 P +0.2 (ib) 411.77 648.33 P +0.2 (ute of a de) 419.35 648.33 P +0.2 (vice) 466.92 648.33 P +0.2 (, and handle) 484.55 648.33 P +2.09 (each class of error inline) 162 636.33 P +2.09 (. A retur) 278.59 636.33 P +2.09 (n code of CDEV_SUCCESS indicates that the) 323.47 636.33 P +(message w) 162 624.33 T +(as successfully tr) 212.42 624.33 T +(ansmitted and processed.) 288.45 624.33 T +4 9 Q +(Figure 23: Using the send method of a cde) 162 591 T +(vRequestObject object) 334.32 591 T +162 81 540 720 C +162 87.81 540 588 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.64 89.78 542.22 580.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.68 93.74 536.63 586.29 R +7 X +V +0 X +N +167.93 98.47 529.21 584.17 R +7 X +V +5 9 Q +0 X +(#include ) 167.93 578.17 T +(#include ) 167.93 567.17 T +(void main\050\051) 167.93 545.17 T +({) 185.93 534.17 T +(// ************************************************************) 185.93 523.17 T +(// * Obtain a cdevRequestObject for \322MQB1S01\323 / \322get bdl\323) 185.93 512.17 T +(// ************************************************************) 185.93 501.17 T +(cdevRequestObject *req =) 185.93 490.17 T +(cdevRequestObject::attachPtr\050\322MQB1S01\323, \322get bdl\323\051;) 203.93 479.17 T +(cdevData input, output;) 185.93 468.17 T +(double value = 0.0;) 185.93 457.17 T +(// ************************************************************) 185.93 435.17 T +(// * Use the send method to obtain the value from the device.) 185.93 424.17 T +(// * Since there is no outbound data, the parameter is NULL) 185.93 413.17 T +(// ************************************************************) 185.93 402.17 T +(switch\050req->send\050NULL, &output\051\051) 185.93 391.17 T +({) 203.93 380.17 T +(// **** Message transmitted and processed successfuly. ****) 203.93 369.17 T +(case CDEV_SUCCESS:) 203.93 358.17 T +(output.get\050\322value\323, &value\051;) 221.93 347.17 T +(printf\050\322Value of MQB1S01 is %f\134n\323, value\051;) 221.93 336.17 T +(break;) 221.93 325.17 T +(// ******* Unknown device or device/message mismatch ******) 203.93 303.17 T +(case CDEV_INVALIDOBJ:) 203.93 292.17 T +(printf\050\322Unknown device or device/message mismatch\134n\323\051;) 221.93 281.17 T +(break;) 221.93 270.17 T +(// * Communications error between application and service *) 203.93 248.17 T +(case CDEV_NOTCONNECTED:) 203.93 237.17 T +(case CDEV_IOFAILED:) 203.93 226.17 T +(case CDEV_TIMEOUT:) 203.93 215.17 T +(printf\050\322Communications error while sending\134n\323\051;) 221.93 204.17 T +(break;) 221.93 193.17 T +(// ************ A generic error has occurred *************) 203.93 171.17 T +(case CDEV_ERROR:) 203.93 160.17 T +(case default:) 203.93 149.17 T +(printf\050\322Unable to send message\134n\323\051;) 221.93 138.17 T +(break;) 221.93 127.17 T +(}) 203.93 116.17 T +(}) 185.93 105.17 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "34" 42 +%%Page: "35" 43 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Using the cde) 400.7 739 T +(vRequestObject Object) 465.46 739 T +0 10 Q +(35) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +-1.4 (Sending Messa) 72 713.33 P +-1.4 (g) 143.29 713.33 P +-1.4 (es) 149.51 713.33 P +(to a De) 72 701.33 T +(vice) 105.19 701.33 T +(Async) 72 689.33 T +(hr) 101.91 689.33 T +(onousl) 111.71 689.33 T +(y) 144.34 689.33 T +0 F +3.33 (There are tw) 180 713.33 P +3.33 (o methods pro) 242.7 713.33 P +3.33 (vided b) 313.13 713.33 P +3.33 (y the cde) 348.51 713.33 P +3.33 (vRequestObject object f) 395.45 713.33 P +3.33 (or sending) 507.98 713.33 P +(messages asynchronously;) 180 701.33 T +4 F +(sendNoBloc) 303.38 701.33 T +(k) 357.09 701.33 T +0 F +( and) 362.09 701.33 T +4 F +(sendCallbac) 384.33 701.33 T +(k) 439.15 701.33 T +0 F +(.) 444.15 701.33 T +2 F +(Using) 72 660.33 T +(sendNoBloc) 72 648.33 T +(k) 130.14 648.33 T +0 F +0.25 (The) 180 660.33 P +4 F +0.25 (sendNoBloc) 200.26 660.33 P +0.25 (k) 253.97 660.33 P +0 F +0.25 (method is identical in interf) 262 660.33 P +0.25 (ace to the) 381.09 660.33 P +4 F +0.25 (send) 428.54 660.33 P +0 F +0.25 ( method, ho) 450.22 660.33 P +0.25 (w) 503.39 660.33 P +0.25 (e) 510.51 660.33 P +0.25 (v) 515.77 660.33 P +0.25 (er) 520.52 660.33 P +0.25 (, if it is) 528.91 660.33 P +0.75 (unab) 180 648.33 P +0.75 (le to immediately tr) 202.04 648.33 P +0.75 (ansmit to and receiv) 288.1 648.33 P +0.75 (e a response from the de) 379.59 648.33 P +0.75 (vice) 494.21 648.33 P +0.75 (, it will not) 511.85 648.33 P +-0.27 (w) 180 636.33 P +-0.27 (ait. In order to deter) 187.07 636.33 P +-0.27 (mine if a) 273.53 636.33 P +4 F +-0.27 (sendNoBloc) 313.3 636.33 P +-0.27 (k) 367.01 636.33 P +0 F +-0.27 ( oper) 372.01 636.33 P +-0.27 (ation has completed successfully) 394.43 636.33 P +-0.27 (, the) 538.8 636.33 P +-0.1 (caller m) 180 624.33 P +-0.1 (ust poll the) 214.8 624.33 P +4 F +-0.1 (cde) 265.64 624.33 P +-0.1 (vSystem) 281.46 624.33 P +0 F +-0.1 ( object, use the) 319.8 624.33 P +4 F +-0.1 (cde) 392.67 624.33 P +-0.1 (vGroup) 408.49 624.33 P +0 F +-0.1 (object, or e) 443.96 624.33 P +-0.1 (xplicitly test f) 492.93 624.33 P +-0.1 (or) 549.11 624.33 P +(ne) 180 612.33 T +(w data in the result object.) 190.92 612.33 T +2 F +(Mana) 72 583.33 T +(ging) 97.46 583.33 T +(sendNoBloc) 72 571.33 T +(k) 130.14 571.33 T +(Messa) 72 559.33 T +(g) 102.47 559.33 T +(es with) 108.68 559.33 T +(the cde) 72 547.33 T +(vSystem) 106.86 547.33 T +(object) 72 535.33 T +0 F +0.71 (T) 180 583.33 P +0.71 (o manage asynchronous messages using the cde) 184.91 583.33 P +0.71 (vSystem object, the caller should) 408.99 583.33 P +3.3 (use the) 180 571.33 P +4 F +3.3 (pend) 222.17 571.33 P +0 F +3.3 ( or) 244.41 571.33 P +4 F +3.3 (poll) 265.45 571.33 P +0 F +3.3 ( method. These methods will submit the message to the) 281.01 571.33 P +1.38 (under) 180 559.33 P +1.38 (lying de) 205.72 559.33 P +1.38 (vice) 241.26 559.33 P +1.38 (, and will w) 258.89 559.33 P +1.38 (ait f) 311.78 559.33 P +1.38 (or a per) 328.98 559.33 P +1.38 (iod of time f) 366.35 559.33 P +1.38 (or a response to arr) 421.87 559.33 P +1.38 (iv) 514.8 559.33 P +1.38 (e) 521.77 559.33 P +1.38 (. If all) 527.18 559.33 P +0.93 (messages ha) 180 547.33 P +0.93 (v) 240.2 547.33 P +0.93 (e not been processed dur) 244.95 547.33 P +0.93 (ing the speci\336ed \050or def) 362.24 547.33 P +0.93 (ault\051 per) 469.61 547.33 P +0.93 (iod of time) 507.37 547.33 P +0.93 (,) 555.22 547.33 P +1.34 (these methods will retur) 180 535.33 P +1.34 (n a) 289.86 535.33 P +4 F +1.34 (CDEV_TIMEOUT) 309.22 535.33 P +0 F +1.34 ( status code) 387.56 535.33 P +1.34 (. If all tr) 444.02 535.33 P +1.34 (ansactions ha) 484.85 535.33 P +1.34 (v) 547.69 535.33 P +1.34 (e) 552.44 535.33 P +(been processed, these methods will retur) 180 523.33 T +(n a) 362.55 523.33 T +4 F +(CDEV_SUCCESS) 379.23 523.33 T +0 F +( status code) 460.91 523.33 T +(.) 514.68 523.33 T +2 F +(Gr) 72 494.33 T +(ouping) 83.47 494.33 T +(sendNoBloc) 72 482.33 T +(k) 130.14 482.33 T +(Messa) 72 470.33 T +(g) 102.47 470.33 T +(es with) 108.68 470.33 T +(cde) 72 458.33 T +(vGr) 89.08 458.33 T +(oup) 106.11 458.33 T +0 F +0.88 (An alter) 180 494.33 P +0.88 (nativ) 215.59 494.33 P +0.88 (e w) 236.46 494.33 P +0.88 (a) 252.76 494.33 P +0.88 (y to manage messages tr) 258.02 494.33 P +0.88 (ansmitted with) 373.72 494.33 P +4 F +0.88 (sendNoBloc) 442.17 494.33 P +0.88 (k) 495.88 494.33 P +0 F +0.88 (, is to create) 500.88 494.33 P +0.68 (and) 180 482.33 P +4 F +0.68 (star) 200.14 482.33 P +0.68 (t) 217.21 482.33 P +0 F +0.68 ( a) 219.99 482.33 P +4 F +0.68 (cde) 232.47 482.33 P +0.68 (vGroup) 248.29 482.33 P +0 F +0.68 ( object pr) 281.08 482.33 P +0.68 (ior to sending the \336rst message) 323.72 482.33 P +0.68 (. The application will) 465.93 482.33 P +-0.14 (then tr) 180 470.33 P +-0.14 (ansmit all of the messages that it wishes to manage within a single g) 208.1 470.33 P +-0.14 (roup) 509.02 470.33 P +-0.14 (. Once) 528.68 470.33 P +0.39 (all messages ha) 180 458.33 P +0.39 (v) 252.83 458.33 P +0.39 (e been tr) 257.58 458.33 P +0.39 (ansmitted, the caller will) 297.74 458.33 P +4 F +0.39 (end) 408.22 458.33 P +0 F +0.39 ( the) 424.9 458.33 P +4 F +0.39 (cde) 445.14 458.33 P +0.39 (vGroup) 460.96 458.33 P +0 F +0.39 ( and then ma) 493.76 458.33 P +0.39 (y) 553 458.33 P +2.46 (call the) 180 446.33 P +4 F +2.46 (pend) 219.39 446.33 P +0 F +2.46 (member function of the) 246.87 446.33 P +4 F +2.46 (cde) 361.77 446.33 P +2.46 (vGroup) 377.59 446.33 P +0 F +2.46 ( object until the retur) 410.38 446.33 P +2.46 (n v) 511.08 446.33 P +2.46 (alue is) 526.64 446.33 P +4 F +0.12 (CDEV_SUCCESS) 180 434.33 P +0.12 (.) 261.48 434.33 P +0 F +0.12 (The caller should alw) 267.16 434.33 P +0.12 (a) 361.29 434.33 P +0.12 (ys specify a discrete amount of time to w) 366.55 434.33 P +0.12 (ait) 547.44 434.33 P +-0.1 (when using the) 180 422.33 P +4 F +-0.1 (pend) 249.73 422.33 P +0 F +-0.1 ( oper) 271.97 422.33 P +-0.1 (ation, otherwise) 294.55 422.33 P +-0.1 (, the application can enter an inde\336nite w) 364.33 422.33 P +-0.1 (ait.) 544.66 422.33 P +4 F +1.54 (Note: Once a cde) 180 405.33 P +1.54 (vGroup object has been star) 262.15 405.33 P +1.54 (ted, it will remain open until its end) 394.35 405.33 P +0.19 (method is e) 180 393.33 P +0.19 (x) 231.77 393.33 P +0.19 (ecuted) 236.47 393.33 P +3 F +0.19 (OR) 269.45 393.33 P +4 F +0.19 (until the pend method of the cde) 287.42 393.33 P +0.19 (vGroup object is e) 431.12 393.33 P +0.19 (x) 511.97 393.33 P +0.19 (ecuted. If) 516.67 393.33 P +0.04 (a sendNoBloc) 180 381.33 P +0.04 (k is e) 242.09 381.33 P +0.04 (x) 265.2 381.33 P +0.04 (ecuted after the g) 269.9 381.33 P +0.04 (roup has been ended, it will not be managed b) 347.74 381.33 P +0.04 (y) 553 381.33 P +(that g) 180 369.33 T +(roup) 204.92 369.33 T +(.) 224.58 369.33 T +4 9 Q +(Figure 24: Using sendNoBloc) 180 336 T +(k to comm) 299.37 336 T +(unicate with a cde) 340.79 336 T +(vRequestObject) 412.55 336 T +180 81 558 501 C +180 83.17 558 333 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.93 86.81 559.5 325.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +179.96 91 553.92 331.29 R +7 X +V +0 X +N +185.21 95.17 546.49 327 R +7 X +V +5 9 Q +0 X +(#include ) 185.21 321 T +(#include ) 185.21 310 T +(#include ) 185.21 299 T +(void main\050\051) 185.21 277 T +({) 203.21 266 T +(cdevRequestObject *req1, *req2;) 203.21 255 T +(cdevGroup group;) 203.21 244 T +(cdevData output1, output2;) 203.21 233 T +(// ************************************************************) 203.21 222 T +(// * Obtain cdevRequestObjects for \322MQB1S01\323 and \322MQB1S02\323) 203.21 211 T +(// ************************************************************) 203.21 200 T +(req1 = cdevRequestObject::attachPtr\050\322MQB1S01\323, \322get bdl\323\051;) 203.21 189 T +(req2 = cdevRequestObject::attachPtr\050\322MQB1S02\323, \322get bdl\323\051;) 203.21 178 T +(// ************************************************************) 203.21 156 T +(// * Start the cdevGroup object to group all of the requests.) 203.21 145 T +(// ************************************************************) 203.21 134 T +(group.start\050\051;) 203.21 123 T +180 81 558 501 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "35" 43 +%%Page: "36" 44 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Using the cde) 54 739 T +(vRequestObject Object) 118.76 739 T +0 10 Q +(36) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Figure 24: Using sendNoBloc) 162 714 T +(k to comm) 281.37 714 T +(unicate with a cde) 322.79 714 T +(vRequestObject \050contin) 394.55 714 T +(ued\051) 488 714 T +2 10 Q +(Using def) 54 367.64 T +(erred) 99.46 367.64 T +(gr) 54 355.64 T +(oups f) 63.8 355.64 T +(or) 93.6 355.64 T +(repeating lists of) 54 343.64 T +(operations) 54 331.64 T +0 F +0.3 (A cde) 162 367.64 P +0.3 (vGroup ma) 187.57 367.64 P +0.3 (y be placed into a) 237.04 367.64 P +4 F +0.3 (def) 319.71 367.64 P +0.3 (erred) 333.31 367.64 P +0 F +0.3 ( mode pr) 356.65 367.64 P +0.3 (ior to star) 396.86 367.64 P +0.3 (ting it, and in this case) 439.55 367.64 P +0.37 (messages will not be tr) 162 355.64 P +0.37 (ansmitted until the g) 265.08 355.64 P +0.37 (roup is \337ushed. After all oper) 355.58 355.64 P +0.37 (ations within) 484.61 355.64 P +0.47 (the g) 162 343.64 P +0.47 (roup ha) 184.61 343.64 P +0.47 (v) 218.78 343.64 P +0.47 (e completed, the g) 223.53 343.64 P +0.47 (roup ma) 307.1 343.64 P +0.47 (y be \337ushed again, causing the same set of) 343.94 343.64 P +(oper) 162 331.64 T +(ations to be e) 181.91 331.64 T +(x) 241.65 331.64 T +(ecuted again.) 246.35 331.64 T +2 F +(Using) 54 302.64 T +(sendCallbac) 54 290.64 T +(k) 112.71 290.64 T +0 F +-0.09 (The) 162 302.64 P +4 F +-0.09 (sendCallbac) 181.92 302.64 P +-0.09 (k) 236.74 302.64 P +0 F +-0.09 (method pro) 244.42 302.64 P +-0.09 (vides the second mechanism f) 294.76 302.64 P +-0.09 (or tr) 428.59 302.64 P +-0.09 (ansmitting messages) 446.17 302.64 P +1.51 (asynchronously) 162 290.64 P +1.51 (. This method is used in CDEV f) 230.47 290.64 P +1.51 (or a v) 382.48 290.64 P +1.51 (ar) 410.26 290.64 P +1.51 (iety of pur) 419.3 290.64 P +1.51 (poses) 466.54 290.64 P +1.51 (, the most) 493.07 290.64 P +1.71 (common of these is to estab) 162 278.64 P +1.71 (lish monitors on a speci\336c de) 295.43 278.64 P +1.71 (vice proper) 432.08 278.64 P +1.71 (ty) 483.65 278.64 P +1.71 (. Once the) 490.43 278.64 P +0.95 (monitor has been estab) 162 266.64 P +0.95 (lished, the user speci\336ed callbac) 269.15 266.64 P +0.95 (k function will be contacted) 416.7 266.64 P +(whene) 162 254.64 T +(v) 191.16 254.64 T +(er the proper) 195.91 254.64 T +(ty\325) 253.56 254.64 T +(s v) 263.06 254.64 T +(alue is altered.) 275.59 254.64 T +0 (This method is more comple) 162 237.64 P +0 (x than the others because it requires the caller to utiliz) 287.28 237.64 P +0 (e a) 526.1 237.64 P +4 F +-0.04 (cde) 162 225.64 P +-0.04 (vSystem) 177.82 225.64 P +0 F +-0.04 (object in order to poll the under) 218.9 225.64 P +-0.04 (lying ser) 356.7 225.64 P +-0.04 (vices) 394.19 225.64 P +-0.04 (, and it requires the caller to) 416.82 225.64 P +2.95 (prede\336ne a) 162 213.64 P +4 F +2.95 (cde) 220.7 213.64 P +2.95 (vCallbac) 236.52 213.64 P +2.95 (kFunction) 274.66 213.64 P +0 F +2.95 ( to be e) 318.01 213.64 P +2.95 (x) 359.92 213.64 P +2.95 (ecuted when the message has been) 364.61 213.64 P +(processed.) 162 201.64 T +0.87 (The) 162 184.64 P +4 F +0.87 (cde) 182.88 184.64 P +0.87 (vCallbac) 198.7 184.64 P +0.87 (kFunction) 236.84 184.64 P +0 F +0.87 (has a v) 283.83 184.64 P +0.87 (er) 317.55 184.64 P +0.87 (y speci\336c prototype that the caller m) 326.74 184.64 P +0.87 (ust comply) 491.34 184.64 P +0.47 (with. The user speci\336ed callbac) 162 172.64 P +0.47 (k function m) 302.6 172.64 P +0.47 (ust be of type v) 357.34 172.64 P +0.47 (oid, and m) 426.77 172.64 P +0.47 (ust receiv) 474.29 172.64 P +0.47 (e the) 517.29 172.64 P +(f) 162 160.64 T +(ollo) 164.48 160.64 T +(wing par) 179.89 160.64 T +(ameters) 217.58 160.64 T +(.) 253.55 160.64 T +(1.) 162 143.64 T +2 F +(int status) 180 143.64 T +0 F +(: This is equiv) 224.45 143.64 T +(alent to the retur) 285.33 143.64 T +(n status of a synchronous) 358.4 143.64 T +4 F +(send) 475.13 143.64 T +0 F +(call. It) 499.59 143.64 T +(should receiv) 180 131.64 T +(e one of the v) 238.66 131.64 T +(alues as de\336ned in) 299.01 131.64 T +4 F +(cde) 385.17 131.64 T +(vErrCode) 400.99 131.64 T +(.h) 443.07 131.64 T +0 F +(.) 451.41 131.64 T +(2.) 162 107.64 T +2 F +(v) 180 107.64 T +(oid * ar) 185.26 107.64 T +(g) 219.01 107.64 T +0 F +(: This is a pointer to data that w) 225.12 107.64 T +(as speci\336ed b) 363.93 107.64 T +(y the user when creating) 424.87 107.64 T +(the) 180 95.64 T +4 F +(cde) 196.68 95.64 T +(vCallbac) 212.5 95.64 T +(k) 250.64 95.64 T +0 F +( object.) 255.64 95.64 T +162 393.31 540 720 C +162 393.31 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.29 396.23 541.86 703.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.32 401.14 536.27 709.29 R +7 X +V +0 X +N +167.57 406.64 528.85 704.64 R +7 X +V +5 9 Q +0 X +(// ************************************************************) 185.57 698.64 T +(// * Use the sendNoBlock command to transmit the messages to) 185.57 687.64 T +(// * the selected devices. The \322get bdl\323 message requires no) 185.57 676.64 T +(// * input, so the outbound cdevData object is NULL.) 185.57 665.64 T +(// ************************************************************) 185.57 654.64 T +(req1->sendNoBlock\050NULL, &output1\051;) 185.57 643.64 T +(req2->sendNoBlock\050NULL, &output2\051;) 185.57 632.64 T +(// ************************************************************) 185.57 610.64 T +(// * Use the end method to terminate the group.) 185.57 599.64 T +(// ************************************************************) 185.57 588.64 T +(group.end\050\051;) 185.57 577.64 T +(// ************************************************************) 185.57 555.64 T +(// * Use the pend method of the group to wait for 1 second) 185.57 544.64 T +(// * for all of the messages to be processed. The allFinished) 185.57 533.64 T +(// * method can be used to obtain the completion status of) 185.57 522.64 T +(// * the group \0500=NOT DONE, 1=DONE\051.) 185.57 511.64 T +(// *) 185.57 500.64 T +(// * As a simple example, this function will wait no more than) 185.57 489.64 T +(// * 5 seconds for all messages to be processed.) 185.57 478.64 T +(// ************************************************************) 185.57 467.64 T +(for\050int i=0; i<5 && !group.allFinished\050\051; i++\051) 185.57 456.64 T +({) 203.57 445.64 T +(group.pend\0501.0\051;) 203.57 434.64 T +(}) 203.57 423.64 T +(}) 185.57 412.64 T +162 393.31 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "36" 44 +%%Page: "37" 45 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Using the cde) 400.7 739 T +(vRequestObject Object) 465.46 739 T +0 10 Q +(37) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 180 713.33 T +2 F +(cde) 198 713.33 T +(vRequestObject & obj) 215.08 713.33 T +0 F +(: This is the) 318.99 713.33 T +4 F +(cde) 372.9 713.33 T +(vRequestObject) 388.72 713.33 T +0 F +(that the system used) 462.64 713.33 T +(to tr) 198 701.33 T +(ansmit the message to the de) 215.13 701.33 T +(vice) 346.01 701.33 T +(.) 363.64 701.33 T +(4.) 180 677.33 T +2 F +-0.01 (cde) 198 677.33 P +-0.01 (vData & data) 215.08 677.33 P +0 F +-0.01 (: This is the cde) 275.62 677.33 P +-0.01 (vData object that contains the output gener) 345.29 677.33 P +-0.01 (ated) 535.77 677.33 P +(b) 198 665.33 T +(y the de) 203.36 665.33 T +(vice when it processed the message) 238.64 665.33 T +(.) 399.67 665.33 T +4.46 (The) 180 641.33 P +4 F +4.46 (cde) 204.47 641.33 P +4.46 (vCallbac) 220.29 641.33 P +4.46 (kFunction) 258.43 641.33 P +0 F +4.46 ( and a user pro) 301.78 641.33 P +4.46 (vided argument are passed to the) 386.73 641.33 P +4 F +0.62 (sendCallbac) 180 629.33 P +0.62 (k) 234.82 629.33 P +0 F +0.62 (method through the use of the) 243.23 629.33 P +4 F +0.62 (cde) 383.17 629.33 P +0.62 (vCallbac) 398.99 629.33 P +0.62 (k) 437.14 629.33 P +0 F +0.62 ( object. The) 442.14 629.33 P +4 F +0.62 (cde) 499.04 629.33 P +0.62 (vCallbac) 514.86 629.33 P +0.62 (k) 553 629.33 P +0 F +(object is a simple container class) 180 617.33 T +(.) 326.01 617.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "37" 45 +%%Page: "38" 46 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Using the cde) 54 739 T +(vRequestObject Object) 118.76 739 T +0 10 Q +(38) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Figure 25: Using the sendCallbac) 162 714 T +(k method of a cde) 297.38 714 T +(vRequestObject object) 368.65 714 T +162 81 540 720 C +162 139.97 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.29 141.23 541.86 703.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.32 146.02 536.27 709.29 R +7 X +V +0 X +N +167.57 149.35 528.85 702.93 R +7 X +V +5 9 Q +0 X +(#include ) 167.57 696.93 T +(#include ) 167.57 685.93 T +(#include ) 167.57 674.93 T +(#include ) 167.57 663.93 T +(#include ) 167.57 652.93 T +-0.52 (// ****************************************************************) 167.57 630.93 P +(// * callback:) 167.57 619.93 T +(// * This is the callback function that will be called when the) 167.57 608.93 T +(// * message has been processed to completion. This function is) 167.57 597.93 T +(// * disregarding CDEV_DISCONNECTED and CDEV_RECONNECTED messages.) 167.57 586.93 T +-0.52 (// ****************************************************************) 167.57 575.93 P +(void callback\050int status,) 167.57 564.93 T +(void * arg,) 239.57 553.93 T +(cdevRequestObject & req,) 239.57 542.93 T +(cdevData & data\051) 239.57 531.93 T +({) 185.57 520.93 T +(double result;) 185.57 509.93 T +(int & userFlag = *arg;) 185.57 498.93 T +(// ************************************************************) 185.57 476.93 T +(// * Save the completion status and print the result) 185.57 465.93 T +(// ************************************************************) 185.57 454.93 T +(if\050status!=CDEV_DISCONNECTED && status!=CDEV_RECONNECTED\051) 185.57 443.93 T +({) 203.57 432.93 T +(userFlag = status;) 203.57 421.93 T +(data.get\050\322value\323, &result\051;) 203.57 410.93 T +(printf\050\322I have received value %f\323, result\051;) 203.57 399.93 T +(}) 203.57 388.93 T +(}) 185.57 377.93 T +(void main\050\051) 167.57 355.93 T +({) 185.57 344.93 T +(// ************************************************************) 185.57 333.93 T +(// * Integer flag for detecting callback completion) 185.57 322.93 T +(// ************************************************************) 185.57 311.93 T +(int userFlag = 100;) 185.57 300.93 T +(// ************************************************************) 185.57 278.93 T +(// * Obtain a reference to the default system.) 185.57 267.93 T +(// ************************************************************) 185.57 256.93 T +(cdevSystem & default = cdevSystem::defaultSystem\050\051;) 185.57 245.93 T +(// ************************************************************) 185.57 223.93 T +(// * Obtain a cdevRequestObject for \322MQB1S01\323 / \322get bdl\323.) 185.57 212.93 T +(// ************************************************************) 185.57 201.93 T +(cdevRequestObject * req =) 185.57 190.93 T +(default.getDevice\050\322MQB1S01\323\051->getRequestObject\050\322get bdl\323\051;) 203.57 179.93 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "38" 46 +%%Page: "39" 47 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Using the cde) 400.7 739 T +(vRequestObject Object) 465.46 739 T +0 10 Q +(39) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +(Figure 25: Using the sendCallbac) 180 714 T +(k method of a cde) 315.38 714 T +(vRequestObject object \050contin) 386.65 714 T +(ued\051) 506.61 714 T +180 81 558 720 C +180 474.02 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.57 476.12 559.15 703.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +179.61 480.19 553.56 709.29 R +7 X +V +0 X +N +184.86 485.37 546.14 705.07 R +7 X +V +5 9 Q +0 X +(// ************************************************************) 202.86 699.07 T +(// * Construct the cdevCallback object that will be used to) 202.86 688.07 T +(// * specify the callback function and the user argument.) 202.86 677.07 T +(// ************************************************************) 202.86 666.07 T +(cdevCallback cb\050callback, &userFlag\051;) 202.86 655.07 T +(// ************************************************************) 202.86 633.07 T +(// * Transmit the message to the device using the sendCallback) 202.86 622.07 T +(// * mechanism. Since the message requires no outbound data,) 202.86 611.07 T +(// * the outbound cdevData object is NULL.) 202.86 600.07 T +(// ************************************************************) 202.86 589.07 T +(if\050req->sendCallback\050NULL, cb\051==CDEV_SUCCESS\051) 202.86 578.07 T +({) 220.86 567.07 T +(// *********************************************************) 220.86 556.07 T +(// * Now, poll the cdevSystem object until the message has) 220.86 545.07 T +(// * been successfully processed.) 220.86 534.07 T +(// *********************************************************) 220.86 523.07 T +(while\050userFlag==100\051 default.poll\050\051;) 220.86 512.07 T +(}) 220.86 501.07 T +(}) 202.86 490.07 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "39" 47 +%%Page: "40" 48 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Using the cde) 54 739 T +(vData Object) 118.76 739 T +0 10 Q +(40) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(6.) 141.32 710.67 T +(Using the) 162 710.67 T +3 F +(cde) 229.68 710.67 T +(vData) 253.59 710.67 T +2 F +(Object) 295.6 710.67 T +2 10 Q +(Over) 54 673.33 T +(vie) 76.89 673.33 T +(w of the) 90.64 673.33 T +(cde) 54 661.33 T +(vData Class) 71.08 661.33 T +0 F +1.33 (The cde) 162 673.33 P +1.33 (vData C++ class is a self descr) 199.16 673.33 P +1.33 (ibing data object. This class is the pr) 344.59 673.33 P +1.33 (imar) 515.26 673.33 P +1.33 (y) 535 673.33 P +1.68 (mechanism f) 162 661.33 P +1.68 (or data interchange within the CDEV system. The cde) 220.06 661.33 P +1.68 (vData object is) 471.06 661.33 P +0.59 (capab) 162 649.33 P +0.59 (le of stor) 189.04 649.33 P +0.59 (ing and retr) 228.72 649.33 P +0.59 (ie) 280.63 649.33 P +0.59 (ving tagged data items of all the pr) 288.11 649.33 P +0.59 (imitiv) 445.26 649.33 P +0.59 (e data types) 467.78 649.33 P +0.59 (, as) 523.29 649.33 P +0.65 (w) 162 637.33 P +0.65 (ell as char) 169.12 637.33 P +0.65 (acter str) 215.88 637.33 P +0.65 (ings and time stamps) 252.8 637.33 P +0.65 (. These data items ma) 349.06 637.33 P +0.65 (y be scalar or m) 450.28 637.33 P +0.65 (ulti-) 523.89 637.33 P +(dimensional arr) 162 625.33 T +(a) 230.25 625.33 T +(ys) 235.51 625.33 T +(.) 245.36 625.33 T +2 F +(cde) 54 596.33 T +(vData T) 71.08 596.33 T +(a) 106.4 596.33 T +(gs) 111.86 596.33 T +0 F +0.66 (A tag is a unique 32 bit integer that ma) 162 596.33 P +0.66 (y be de\336ned b) 338.84 596.33 P +0.66 (y the CDEV system, individual) 403.43 596.33 P +0.69 (ser) 162 584.33 P +0.69 (vices or b) 176.19 584.33 P +0.69 (y an application. Each tag integer has a corresponding char) 220.15 584.33 P +0.69 (acter str) 489.7 584.33 P +0.69 (ing) 526.66 584.33 P +0.13 (identi\336er) 162 572.33 P +0.13 (. By using the char) 199.29 572.33 P +0.13 (acter str) 282.54 572.33 P +0.13 (ing identi\336er to obtain the integer tag, applications) 318.95 572.33 P +(and ser) 162 560.33 T +(vices are insulated from prob) 195.65 560.33 T +(lems caused b) 323.83 560.33 T +(y inter) 388.1 560.33 T +(nal tag ren) 415.58 560.33 T +(umber) 462.73 560.33 T +(ing.) 491.22 560.33 T +2 F +(XDR P) 54 531.33 T +(ac) 84.26 531.33 T +(ka) 95.18 531.33 T +(ging of) 106.2 531.33 T +(cde) 54 519.33 T +(vData Objects) 71.08 519.33 T +0 F +0.23 (In addition to stor) 162 531.33 P +0.23 (ing data, the cde) 239.54 531.33 P +0.23 (vData object can also encapsulate its contents into) 313.86 531.33 P +2.46 (an XDR b) 162 519.33 P +2.46 (uff) 210.06 519.33 P +2.46 (er f) 220.88 519.33 P +2.46 (or por) 237.49 519.33 P +2.46 (tab) 266.47 519.33 P +2.46 (le tr) 280.17 519.33 P +2.46 (anspor) 299.19 519.33 P +2.46 (t betw) 330.16 519.33 P +2.46 (een platf) 359.2 519.33 P +2.46 (or) 399.72 519.33 P +2.46 (ms) 408.86 519.33 P +2.46 (. The b) 422.04 519.33 P +2.46 (uff) 457.88 519.33 P +2.46 (er can then be) 468.7 519.33 P +-0.1 (decoded and reassemb) 162 507.33 P +-0.1 (led into a cde) 266.09 507.33 P +-0.1 (vData when it has been receiv) 324.96 507.33 P +-0.1 (ed. T) 458.13 507.33 P +-0.1 (o ensure best) 479.62 507.33 P +0.4 (perf) 162 495.33 P +0.4 (or) 178.93 495.33 P +0.4 (mance) 188.07 495.33 P +0.4 (, the XDR mechanism only tr) 217.93 495.33 P +0.4 (anspor) 347.07 495.33 P +0.4 (ts the tag integer v) 378.04 495.33 P +0.4 (alues) 461.64 495.33 P +0.4 (, r) 485.39 495.33 P +0.4 (ather than) 494.57 495.33 P +1.36 (the tag char) 162 483.33 P +1.36 (acter str) 217.43 483.33 P +1.36 (ing v) 255.06 483.33 P +1.36 (alues) 277.29 483.33 P +1.36 (. Theref) 301.04 483.33 P +1.36 (ore) 336.56 483.33 P +1.36 (, client/ser) 350.86 483.33 P +1.36 (v) 398.09 483.33 P +1.36 (er applications using the XDR) 402.84 483.33 P +0.54 (tr) 162 471.33 P +0.54 (anspor) 168.01 471.33 P +0.54 (t m) 198.98 471.33 P +0.54 (ust v) 213.31 471.33 P +0.54 (er) 234.72 471.33 P +0.54 (ify that the) 243.76 471.33 P +0.54 (y are using the same v) 290.78 471.33 P +0.54 (ersion of CDEV in order to a) 393.82 471.33 P +0.54 (v) 521.91 471.33 P +0.54 (oid) 526.66 471.33 P +(tag n) 162 459.33 T +(umber mismatches) 184.14 459.33 T +(.) 268.45 459.33 T +2 F +(Pub) 54 430.33 T +(lic Functions) 72.79 430.33 T +(of the cde) 54 418.33 T +(vData) 101.08 418.33 T +(Class) 54 406.33 T +(ta) 162 430.33 T +(gC2I) 170.79 430.33 T +4 F +(static int tagC2I \050char *ctag, int *tag\051;) 261.29 430.33 T +0 F +2.68 (Con) 261.29 413.33 P +2.68 (v) 279.43 413.33 P +2.68 (er) 284.18 413.33 P +2.68 (ts a char) 293.47 413.33 P +2.68 (acter str) 337.08 413.33 P +2.68 (ing tag name to its unique integer) 376.04 413.33 P +6.27 (identi\336er) 261.43 401.33 P +6.27 (. The function retur) 298.72 401.33 P +6.27 (ns CDEV_SUCCESS if the) 401.71 401.33 P +14.1 (con) 261.43 389.33 P +14.1 (v) 277.35 389.33 P +14.1 (ersion w) 282.1 389.33 P +14.1 (as successful, otherwise it retur) 333.29 389.33 P +14.1 (ns) 529.44 389.33 P +(CDEV_ERR) 261.43 377.33 T +(OR.) 315.68 377.33 T +2 F +(ta) 162 353.33 T +(gI2C) 170.79 353.33 T +4 F +(static int tagI2C \050int tag, char * &ctag\051;) 261.29 353.33 T +0 F +1.04 (Con) 261.29 336.33 P +1.04 (v) 279.43 336.33 P +1.04 (er) 284.18 336.33 P +1.04 (ts a unique integer tag n) 293.47 336.33 P +1.04 (umber to its related char) 405.88 336.33 P +1.04 (acter) 517.77 336.33 P +4.8 (str) 261.43 324.33 P +4.8 (ing tag. The function retur) 272.69 324.33 P +4.8 (ns CDEV_SUCCESS if the) 406.11 324.33 P +14.1 (con) 261.43 312.33 P +14.1 (v) 277.35 312.33 P +14.1 (ersion w) 282.1 312.33 P +14.1 (as successful, otherwise it retur) 333.29 312.33 P +14.1 (ns) 529.44 312.33 P +(CDEV_ERR) 261.43 300.33 T +(OR.) 315.68 300.33 T +2 F +(inser) 162 276.33 T +(tT) 186.1 276.33 T +(a) 194.74 276.33 T +(g) 200.2 276.33 T +4 F +(static v) 261.29 276.33 T +(oid inser) 292.16 276.33 T +(tT) 330.35 276.33 T +(ag\050int tag, char *ctag\051;) 338.04 276.33 T +0 F +-0.21 (Adds a ne) 261.29 259.33 P +-0.21 (w) 305.7 259.33 P +-0.21 (, unique tag identi\336er to the static tab) 312.32 259.33 P +-0.21 (le of tags) 474.07 259.33 P +-0.21 (. Both) 514.08 259.33 P +3.67 (the tag integer and the char) 261.43 247.33 P +3.67 (acter str) 402.01 247.33 P +3.67 (ing m) 441.95 247.33 P +3.67 (ust be unique) 469.98 247.33 P +3.67 (.) 537.22 247.33 P +0.97 (Retur) 261.43 235.33 P +0.97 (ns CDEV_SUCCESS on success) 286.13 235.33 P +0.97 (, or CDEV_ERR) 436.71 235.33 P +0.97 (OR on) 510.13 235.33 P +(f) 261.43 223.33 T +(ailure) 263.91 223.33 T +(.) 288.21 223.33 T +2 F +(operator =) 162 199.33 T +4 F +(cde) 261.29 199.33 T +(vData & oper) 277.11 199.33 T +(ator = \050cde) 335.37 199.33 T +(vData & data\051;) 383.15 199.33 T +0 F +1.37 (This is the assignment oper) 261.29 182.33 P +1.37 (ator f) 388.92 182.33 P +1.37 (or the class) 412.77 182.33 P +1.37 (. It will cop) 466.48 182.33 P +1.37 (y the) 516.96 182.33 P +0.7 (e) 261.43 170.33 P +0.7 (xact contents of the cde) 266.69 170.33 P +0.7 (vData object speci\336ed b) 374.81 170.33 P +0.7 (y data to the) 482.86 170.33 P +(current cde) 261.43 158.33 T +(vData object.) 311.15 158.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "40" 48 +%%Page: "41" 49 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Using the cde) 441.22 739 T +(vData Object) 505.98 739 T +0 10 Q +(41) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(Cast operator) 180 713.33 T +(s) 244.86 713.33 T +4 F +(oper) 279.29 713.33 T +(ator char \050v) 299.2 713.33 T +(oid\051;) 349.52 713.33 T +(oper) 279.29 701.33 T +(ator shor) 299.2 701.33 T +(t \050v) 339.06 701.33 T +(oid\051;) 352.7 701.33 T +(oper) 279.29 689.33 T +(ator unsigned shor) 299.2 689.33 T +(t \050v) 382.42 689.33 T +(oid\051;) 396.06 689.33 T +(oper) 279.29 677.33 T +(ator int \050v) 299.2 677.33 T +(oid\051;) 340.63 677.33 T +(oper) 279.29 665.33 T +(ator unsigned int \050v) 299.2 665.33 T +(oid\051;) 383.99 665.33 T +(oper) 279.29 653.33 T +(ator long \050v) 299.2 653.33 T +(oid\051;) 348.97 653.33 T +(oper) 279.29 641.33 T +(ator unsigned long \050v) 299.2 641.33 T +(oid\051;) 392.33 641.33 T +(oper) 279.29 629.33 T +(ator \337oat \050v) 299.2 629.33 T +(oid\051;) 348.97 629.33 T +(oper) 279.29 617.33 T +(ator doub) 299.2 617.33 T +(le \050v) 341.25 617.33 T +(oid\051;) 359.89 617.33 T +0 F +0.11 (Directly e) 279.29 600.33 P +0.11 (xtr) 320.76 600.33 P +0.11 (acts a scalar v) 331.77 600.33 P +0.11 (alue that is stored in the \322v) 395.75 600.33 P +0.11 (alue\323 data) 513.42 600.33 P +-0.2 (item, and retur) 279.43 588.33 P +-0.2 (ns it as the v) 343.76 588.33 P +-0.2 (alue of the current cde) 398.85 588.33 P +-0.2 (vData object.) 497.26 588.33 P +2 F +(asciiDump) 180 564.33 T +4 F +(v) 279.29 564.33 T +(oid asciiDump \050FILE * fp\051;) 284.04 564.33 T +0 F +0.34 (Outputs the complete contents of the cde) 279.29 547.33 P +0.34 (vData object to a \336le) 463.39 547.33 P +0.34 (.) 555.22 547.33 P +(If no \336le pointer is speci\336ed, then stdout will be used.) 279.43 535.33 T +2 F +(xdrSiz) 180 511.33 T +(e) 210.11 511.33 T +4 F +(int xdrSiz) 279.29 511.33 T +(e \050siz) 320.26 511.33 T +(e_t * b) 344 511.33 T +(ufLen, siz) 372.71 511.33 T +(e_t * elementCount\051;) 415.36 511.33 T +0 F +-0.1 (Calculates the siz) 279.29 494.33 P +-0.1 (e of the b) 357.29 494.33 P +-0.1 (uff) 398.48 494.33 P +-0.1 (er \050) 409.3 494.33 P +4 F +-0.1 (b) 424.2 494.33 P +-0.1 (ufLen) 429.56 494.33 P +0 F +-0.1 (\051 that will be required to) 454.58 494.33 P +1.43 (store this cde) 279.43 482.33 P +1.43 (vData object as represented b) 341.45 482.33 P +1.43 (y XDR. The total) 480.36 482.33 P +0.35 (n) 279.43 470.33 P +0.35 (umber of data items \050) 284.89 470.33 P +4 F +0.35 (elementCount) 380.79 470.33 P +0 F +0.35 (\051 that will be placed in the) 443.04 470.33 P +0.03 (b) 279.43 458.33 P +0.03 (uff) 284.79 458.33 P +0.03 (er is also calculated. The v) 295.61 458.33 P +0.03 (alues obtained from this function) 413.91 458.33 P +0.46 (ma) 279.43 446.33 P +0.46 (y be passed to the) 293.02 446.33 P +4 F +0.46 (xdrExpor) 379.84 446.33 P +0.46 (t) 420.25 446.33 P +0 F +0.46 ( method in order to use a pre-) 423.03 446.33 P +(allocated data b) 279.43 434.33 T +(uff) 349.83 434.33 T +(er) 360.65 434.33 T +(.) 369.04 434.33 T +2 F +(xdrExpor) 180 410.33 T +(t) 224.1 410.33 T +4 F +(int xdrExpor) 279.29 410.33 T +(t \050char ** b) 333.04 410.33 T +(uf) 380.08 410.33 T +(, siz) 388.12 410.33 T +(e_t * b) 405.75 410.33 T +(ufLen\051;) 434.46 410.33 T +0 F +3.17 (Allocates a b) 279.29 393.33 P +3.17 (uff) 342.67 393.33 P +3.17 (er \050) 353.49 393.33 P +4 F +3.17 (b) 371.66 393.33 P +3.17 (uf) 377.02 393.33 P +0 F +3.17 (\051 of suf\336cient siz) 385.36 393.33 P +3.17 (e to hold the XDR) 466.4 393.33 P +0.8 (representation of this cde) 279.43 381.33 P +0.8 (vData object. It will then tr) 393.8 381.33 P +0.8 (anslate all) 512.18 381.33 P +-0.23 (data items stored within the object to XDR and wr) 279.43 369.33 P +-0.23 (ite this data to) 496.45 369.33 P +1.18 (the b) 279.43 357.33 P +1.18 (uff) 302.65 357.33 P +1.18 (er) 313.48 357.33 P +1.18 (. The siz) 321.86 357.33 P +1.18 (e of the allocated b) 361.87 357.33 P +1.18 (uff) 450.9 357.33 P +1.18 (er will be pro) 461.72 357.33 P +1.18 (vided to) 521.8 357.33 P +(the caller in the) 279.43 345.33 T +4 F +(b) 350.02 345.33 T +(ufLen) 355.38 345.33 T +0 F +( v) 380.4 345.33 T +(ar) 387.93 345.33 T +(iab) 396.97 345.33 T +(le) 410.11 345.33 T +(.) 417.74 345.33 T +2 F +(xdrExpor) 180 321.33 T +(t) 224.1 321.33 T +4 F +(int xdrExpor) 279.29 321.33 T +(t \050char * b) 333.04 321.33 T +(uf) 376.19 321.33 T +(, siz) 384.23 321.33 T +(e_t b) 401.86 321.33 T +(ufLen, siz) 423.9 321.33 T +(e_t count\051;) 466.55 321.33 T +0 F +6.96 (P) 279.29 304.33 P +6.96 (opulates the preallocated b) 285.46 304.33 P +6.96 (uff) 426.2 304.33 P +6.96 (er \050) 437.02 304.33 P +4 F +6.96 (b) 458.97 304.33 P +6.96 (uf) 464.33 304.33 P +0 F +6.96 (\051 with the XDR) 472.67 304.33 P +2.48 (representation of the contents of this cde) 279.43 292.33 P +2.48 (vData object. The) 474.67 292.33 P +1.86 (b) 279.43 280.33 P +1.86 (uff) 284.79 280.33 P +1.86 (er length \050) 295.61 280.33 P +4 F +1.86 (b) 344.36 280.33 P +1.86 (ufLen) 349.72 280.33 P +0 F +1.86 (\051 and n) 374.74 280.33 P +1.86 (umber of elements \050) 409.49 280.33 P +4 F +1.86 (count) 504 280.33 P +0 F +1.86 (\051 m) 528.46 280.33 P +1.86 (ust) 544.66 280.33 P +(ha) 279.43 268.33 T +(v) 290.35 268.33 T +(e been calculated in adv) 295.1 268.33 T +(ance using the) 402.69 268.33 T +4 F +(xdrSiz) 470.51 268.33 T +(e) 498.14 268.33 T +0 F +( method.) 503.7 268.33 T +2 F +(xdrImpor) 180 244.33 T +(t) 223.54 244.33 T +4 F +(int xdrImpor) 279.29 244.33 T +(t \050char * b) 332.48 244.33 T +(uf) 375.63 244.33 T +(, siz) 383.67 244.33 T +(e_t b) 401.3 244.33 T +(ufLen\051;) 423.34 244.33 T +0 F +8.32 (Decodes the caller supplied b) 279.29 227.33 P +8.32 (uff) 443.53 227.33 P +8.32 (er \050) 454.35 227.33 P +4 F +8.32 (b) 477.67 227.33 P +8.32 (uf) 483.02 227.33 P +0 F +8.32 (\051 from XDR) 491.36 227.33 P +2.99 (representation and populates the cde) 279.43 215.33 P +2.99 (vData object with the) 456.2 215.33 P +1.51 (contents) 279.43 203.33 P +1.51 (. The caller m) 317.08 203.33 P +1.51 (ust specify the n) 382.08 203.33 P +1.51 (umber of b) 458.78 203.33 P +1.51 (ytes in the) 509.4 203.33 P +(XDR b) 279.43 191.33 T +(uff) 308.68 191.33 T +(er \050) 319.5 191.33 T +4 F +(b) 334.5 191.33 T +(ufLen) 339.86 191.33 T +0 F +(\051.) 364.88 191.33 T +2 F +(remo) 180 167.33 T +(ve) 204.25 167.33 T +4 F +(v) 279.29 167.33 T +(oid remo) 284.04 167.33 T +(v) 322.79 167.33 T +(e\050v) 327.54 167.33 T +(oid\051;) 341.18 167.33 T +(v) 279.29 155.33 T +(oid remo) 284.04 155.33 T +(v) 322.79 155.33 T +(e\050int tag\051;) 327.54 155.33 T +(v) 279.29 143.33 T +(oid remo) 284.04 143.33 T +(v) 322.79 143.33 T +(e\050char * ctag\051;) 327.54 143.33 T +0 F +1.53 (Remo) 279.29 126.33 P +1.53 (v) 305.81 126.33 P +1.53 (es the data item speci\336ed b) 310.56 126.33 P +1.53 (y the unique tag name or) 439.73 126.33 P +1.65 (integer from this cde) 279.43 114.33 P +1.65 (vData object. If the tag is not speci\336ed,) 374.68 114.33 P +(then all data items will be remo) 279.43 102.33 T +(v) 416.55 102.33 T +(ed from the object.) 421.3 102.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "41" 49 +%%Page: "42" 50 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Using the cde) 54 739 T +(vData Object) 118.76 739 T +0 10 Q +(42) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(c) 162 713.33 T +(hang) 167.46 713.33 T +(eT) 191.45 713.33 T +(a) 202.32 713.33 T +(g) 207.78 713.33 T +4 F +(int changeT) 261.29 713.33 T +(ag\050int oldT) 312.34 713.33 T +(ag, int ne) 358.38 713.33 T +(wT) 399.32 713.33 T +(ag\051;) 411.45 713.33 T +(int changeT) 261.29 701.33 T +(ag\050int oldT) 312.34 701.33 T +(ag, char *c_ne) 358.38 701.33 T +(wT) 422.66 701.33 T +(ag\051;) 434.79 701.33 T +(int changeT) 261.29 689.33 T +(ag\050char *c_oldT) 312.34 689.33 T +(ag, int ne) 381.72 689.33 T +(wT) 422.66 689.33 T +(ag\051;) 434.79 689.33 T +(int changeT) 261.29 677.33 T +(ag\050char *c_oldT) 312.34 677.33 T +(ag, char *c_ne) 381.72 677.33 T +(wT) 446 677.33 T +(ag\051;) 458.13 677.33 T +2.17 (Retags) 261.29 660.33 P +0 F +2.17 ( a data item that is currently stored in the cde) 292.97 660.33 P +2.17 (vData) 513.88 660.33 P +-0.17 (object from \322oldT) 261.43 648.33 P +-0.17 (ag\323 to \322ne) 334.9 648.33 P +-0.17 (wT) 377.16 648.33 P +-0.17 (ag\323. By using this method the data) 389.29 648.33 P +0.49 (can be renamed inter) 261.43 636.33 P +0.49 (nally without ha) 357.63 636.33 P +0.49 (ving to perf) 427.32 636.33 P +0.49 (or) 477.46 636.33 P +0.49 (m a cop) 486.6 636.33 P +0.49 (y or) 522.84 636.33 P +7.54 (remo) 261.43 624.33 P +7.54 (v) 284.06 624.33 P +7.54 (al. This function is o) 288.81 624.33 P +7.54 (v) 407.18 624.33 P +7.54 (er) 411.93 624.33 P +7.54 (loaded to suppor) 420.97 624.33 P +7.54 (t an) 510.93 624.33 P +7.54 (y) 535 624.33 P +(per) 261.43 612.33 T +(m) 276.13 612.33 T +(utation of char) 284.36 612.33 T +(acter str) 347.63 612.33 T +(ing tag or integer tag identi\336er) 383.9 612.33 T +(.) 515.69 612.33 T +2 F +(g) 162 588.33 T +(etT) 168.21 588.33 T +(ype) 182.61 588.33 T +4 F +(cde) 261.29 588.33 T +(vDataT) 277.11 588.33 T +(ypes getT) 308.14 588.33 T +(ype\050int tag\051;) 350.85 588.33 T +(cde) 261.29 576.33 T +(vDataT) 277.11 576.33 T +(ypes getT) 308.14 576.33 T +(ype\050char *ctag\051;) 350.85 576.33 T +0 F +2.12 (Retr) 261.29 559.33 P +2.12 (ie) 280.33 559.33 P +2.12 (v) 287.81 559.33 P +2.12 (es the en) 292.56 559.33 P +2.12 (umer) 337.83 559.33 P +2.12 (ated data type of the speci\336ed tagged) 360.51 559.33 P +7.51 (data item within this cde) 261.43 547.33 P +7.51 (vData object. The f) 397.88 547.33 P +7.51 (ollo) 504.03 547.33 P +7.51 (wing) 519.44 547.33 P +(en) 261.43 535.33 T +(umer) 272.45 535.33 T +(ated types are de\336ned in the \336le) 295.13 535.33 T +4 F +(cde) 439.66 535.33 T +(vT) 455.48 535.33 T +(ypes) 465.39 535.33 T +(.h) 486.36 535.33 T +0 F +(.) 494.7 535.33 T +2 F +(CDEV_BYTE) 261.29 518.33 T +0 F +(8 bit unsigned char) 360 518.33 T +(acter) 444.39 518.33 T +2 F +(CDEV_INT16) 261.29 501.33 T +0 F +(16 bit signed integer) 360 501.33 T +2 F +(CDEV_UINT16) 261.29 484.33 T +0 F +(16 bit unsigned integer) 360 484.33 T +2 F +(CDEV_INT32) 261.29 467.33 T +0 F +(32 bit signed integer) 360 467.33 T +2 F +(CDEV_UINT32) 261.29 450.33 T +0 F +(32 bit unsigned integer) 360 450.33 T +2 F +(CDEV_FLO) 261.29 433.33 T +(A) 314.13 433.33 T +(T) 320.45 433.33 T +0 F +(single precision \337oating point) 360 433.33 T +2 F +(CDEV_DOUBLE) 261.29 416.33 T +0 F +(doub) 360 416.33 T +(le precision \337oating point) 382.04 416.33 T +2 F +(CDEV_STRING) 261.29 399.33 T +0 F +(NULL ter) 360 399.33 T +(minated char) 400.26 399.33 T +(acter str) 457.96 399.33 T +(ing) 494.23 399.33 T +2 F +(CDEV_TIMEST) 261.29 382.33 T +(AMP) 330.4 382.33 T +0 F +(CDEV time stamp) 360 382.33 T +2 F +(CDEV_INV) 261.29 365.33 T +(ALID) 310.5 365.33 T +0 F +(in) 360 365.33 T +(v) 367.58 365.33 T +(alid or unkno) 372.33 365.33 T +(wn data type) 429.43 365.33 T +2 F +(g) 162 341.33 T +(etDim) 168.21 341.33 T +4 F +(int getDim\050int tag, siz) 261.29 341.33 T +(e_t *dim\051;) 354.5 341.33 T +(int getDim\050char *ctag, siz) 261.29 329.33 T +(e_t *dim\051;) 372.28 329.33 T +0 F +1.18 (Retr) 261.29 312.33 P +1.18 (ie) 280.33 312.33 P +1.18 (v) 287.81 312.33 P +1.18 (es the n) 292.56 312.33 P +1.18 (umber of dimensions in a data item that is an) 330.4 312.33 P +1.38 (arr) 261.43 300.33 P +1.38 (a) 273.55 300.33 P +1.38 (y) 278.81 300.33 P +1.38 (. If dim is 0, then the data item is scalar) 282.81 300.33 P +1.38 (, otherwise) 469.57 300.33 P +1.38 (, the) 519.16 300.33 P +4.56 (data item is a \322dim\323 dimensional arr) 261.43 288.33 P +4.56 (a) 444.82 288.33 P +4.56 (y) 450.08 288.33 P +4.56 (. This function is) 454.08 288.33 P +0.42 (o) 261.43 276.33 P +0.42 (v) 266.84 276.33 P +0.42 (er) 271.59 276.33 P +0.42 (loaded to suppor) 280.63 276.33 P +0.42 (t either the integer tag or char) 356.36 276.33 P +0.42 (acter str) 489.97 276.33 P +0.42 (ing) 526.66 276.33 P +(tag.) 261.43 264.33 T +2 F +(g) 162 240.33 T +(etElems) 168.21 240.33 T +4 F +(int getElems\050int tag, siz) 261.29 240.33 T +(e_t *elems\051;) 364.51 240.33 T +(int getElems\050char *ctag, siz) 261.29 228.33 T +(e_t *elems\051;) 382.29 228.33 T +0 F +1.08 (Retr) 261.29 211.33 P +1.08 (ie) 280.33 211.33 P +1.08 (v) 287.81 211.33 P +1.08 (es the n) 292.56 211.33 P +1.08 (umber of data elements in all dimensions of a) 330.19 211.33 P +2.22 (m) 261.43 199.33 P +2.22 (ulti-dimensional arr) 269.66 199.33 P +2.22 (a) 356.24 199.33 P +2.22 (y) 361.5 199.33 P +2.22 (. If elems is 1, then the data item is) 365.5 199.33 P +-0.14 (scalar) 261.43 187.33 P +-0.14 (, otherwise) 287.6 187.33 P +-0.14 (, the data item is an arr) 335.66 187.33 P +-0.14 (a) 436.96 187.33 P +-0.14 (y of \322elems\323 elements) 442.22 187.33 P +-0.14 (.) 537.22 187.33 P +0.61 (This function is o) 261.43 175.33 P +0.61 (v) 338.13 175.33 P +0.61 (er) 342.88 175.33 P +0.61 (loaded to suppor) 351.92 175.33 P +0.61 (t either the integer tag or) 428.02 175.33 P +(char) 261.43 163.33 T +(acter str) 280.78 163.33 T +(ing tag.) 317.05 163.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "42" 50 +%%Page: "43" 51 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Using the cde) 441.22 739 T +(vData Object) 505.98 739 T +0 10 Q +(43) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(g) 180 713.33 T +(etBounds) 186.21 713.33 T +4 F +(int getBounds\050) 279.29 713.33 T +(int tag,) 351.57 713.33 T +(cde) 351.57 701.33 T +(vBounds * bounds) 367.39 701.33 T +(,) 448.4 701.33 T +(siz) 351.57 689.33 T +(e_t n) 363.64 689.33 T +(umBounds\051;) 385.78 689.33 T +(int getBounds\050) 279.29 677.33 T +(char * ctag,) 351.57 677.33 T +(cde) 351.57 665.33 T +(vBounds * bounds) 367.39 665.33 T +(,) 448.4 665.33 T +(siz) 351.57 653.33 T +(e_t n) 363.64 653.33 T +(umBounds\051;) 385.78 653.33 T +0 F +0.59 (Obtains the bounding dimensions of the arr) 279.29 636.33 P +0.59 (a) 473.92 636.33 P +0.59 (y speci\336ed b) 479.18 636.33 P +0.59 (y the) 535.73 636.33 P +2.38 (caller pro) 279.43 624.33 P +2.38 (vided tag. The cde) 322.78 624.33 P +2.38 (vBounds str) 411.87 624.33 P +2.38 (ucture contains tw) 467.2 624.33 P +2.38 (o) 552.44 624.33 P +0.81 (integers: offset and length. The length v) 279.43 612.33 P +0.81 (ar) 459.71 612.33 P +0.81 (iab) 468.76 612.33 P +0.81 (le represents the) 481.89 612.33 P +1.49 (n) 279.43 600.33 P +1.49 (umber of data elements in that dimension of the arr) 284.89 600.33 P +1.49 (a) 524.46 600.33 P +1.49 (y) 529.72 600.33 P +1.49 (. The) 533.72 600.33 P +1.39 (offset integer is pro) 279.43 588.33 P +1.39 (vided f) 368.49 588.33 P +1.39 (or use in specifying the position of) 399.04 588.33 P +1.63 (arr) 279.43 576.33 P +1.63 (a) 291.55 576.33 P +1.63 (ys that are sub-sets of the actual data. A v) 296.81 576.33 P +1.63 (ersion of this) 498.04 576.33 P +0.9 (function is a) 279.43 564.33 P +0.9 (v) 334.4 564.33 P +0.9 (ailab) 339.15 564.33 P +0.9 (le that uses an arr) 360.07 564.33 P +0.9 (a) 443.62 564.33 P +0.9 (y of integers r) 448.88 564.33 P +0.9 (ather than) 512.07 564.33 P +4.3 (the cde) 279.43 552.33 P +4.3 (vBounds str) 316.23 552.33 P +4.3 (ucture) 373.48 552.33 P +4.3 (. This function is o) 401.12 552.33 P +4.3 (v) 498.77 552.33 P +4.3 (er) 503.52 552.33 P +4.3 (loaded to) 512.56 552.33 P +(suppor) 279.43 540.33 T +(t either the integer tag or char) 310.4 540.33 T +(acter str) 441.48 540.33 T +(ing tag.) 477.75 540.33 T +2 F +(setBounds) 180 516.33 T +4 F +(int setBounds\050) 279.29 516.33 T +(int tag,) 351.57 516.33 T +(cde) 351.57 504.33 T +(vBounds * bounds) 367.39 504.33 T +(,) 448.4 504.33 T +(siz) 351.57 492.33 T +(e_t n) 363.64 492.33 T +(umBounds\051;) 385.78 492.33 T +(int setBounds\050) 279.29 480.33 T +(char * ctag,) 351.57 480.33 T +(cde) 351.57 468.33 T +(vBounds * bounds) 367.39 468.33 T +(,) 448.4 468.33 T +(siz) 351.57 456.33 T +(e_t n) 363.64 456.33 T +(umBounds\051;) 385.78 456.33 T +0 F +-0.13 (Speci\336es the bounding dimensions of a m) 279.29 439.33 P +-0.13 (ulti-dimensional arr) 463.51 439.33 P +-0.13 (a) 547.74 439.33 P +-0.13 (y) 553 439.33 P +0.12 (of data. In order to use this function, the n) 279.43 427.33 P +0.12 (umber of dimensions) 464.95 427.33 P +2.1 (in the arr) 279.43 415.33 P +2.1 (a) 322.99 415.33 P +2.1 (y m) 328.25 415.33 P +2.1 (ust be speci\336ed as a par) 346.36 415.33 P +2.1 (ameter to the inser) 465.15 415.33 P +2.1 (t) 555.22 415.33 P +0.23 (command when placing the data into the cde) 279.43 403.33 P +0.23 (vData object. The) 479.17 403.33 P +0.44 (cde) 279.43 391.33 P +0.44 (vBounds str) 295.25 391.33 P +0.44 (ucture contains tw) 348.65 391.33 P +0.44 (o integers: offset and length.) 430.03 391.33 P +0.36 (The length v) 279.43 379.33 P +0.36 (ar) 334.94 379.33 P +0.36 (iab) 343.98 379.33 P +0.36 (le represents the n) 357.12 379.33 P +0.36 (umber of data elements in) 440.93 379.33 P +1.31 (that dimension of the arr) 279.43 367.33 P +1.31 (a) 392.39 367.33 P +1.31 (y) 397.65 367.33 P +1.31 (. The offset integer is pro) 401.65 367.33 P +1.31 (vided f) 518.64 367.33 P +1.31 (or) 549.11 367.33 P +0.4 (use in specifying the position of arr) 279.43 355.33 P +0.4 (a) 435.68 355.33 P +0.4 (ys that are sub-sets of the) 440.95 355.33 P +0.6 (actual data. A v) 279.43 343.33 P +0.6 (ersion of this function is a) 349.9 343.33 P +0.6 (v) 465.5 343.33 P +0.6 (ailab) 470.25 343.33 P +0.6 (le that uses an) 491.17 343.33 P +1.92 (arr) 279.43 331.33 P +1.92 (a) 291.55 331.33 P +1.92 (y of integers r) 296.81 331.33 P +1.92 (ather than the cde) 363.05 331.33 P +1.92 (vBounds str) 449.12 331.33 P +1.92 (ucture) 503.99 331.33 P +1.92 (. This) 531.63 331.33 P +3.08 (function is o) 279.43 319.33 P +3.08 (v) 338.8 319.33 P +3.08 (er) 343.55 319.33 P +3.08 (loaded to suppor) 352.59 319.33 P +3.08 (t either the integer tag or) 433.64 319.33 P +(char) 279.43 307.33 T +(acter str) 298.78 307.33 T +(ing tag.) 335.05 307.33 T +2 F +(inser) 180 283.33 T +(t \050) 204.1 283.33 T +3 F +(scalar) 213.54 283.33 T +2 F +(\051) 242.45 283.33 T +4 F +(int inser) 279.29 283.33 T +(t \050int tag, BYTE data\051;) 314.7 283.33 T +(int inser) 279.29 271.33 T +(t \050int tag, shor) 314.7 271.33 T +(t data\051;) 376.24 271.33 T +(int inser) 279.29 259.33 T +(t \050int tag, unsigned shor) 314.7 259.33 T +(t data\051;) 419.6 259.33 T +(int inser) 279.29 247.33 T +(t \050int tag, int data\051;) 314.7 247.33 T +(int inser) 279.29 235.33 T +(t \050int tag, unsigned int data\051;) 314.7 235.33 T +(int inser) 279.29 223.33 T +(t \050int tag, long data\051;) 314.7 223.33 T +(int inser) 279.29 211.33 T +(t \050int tag, unsigned long data\051;) 314.7 211.33 T +(int inser) 279.29 199.33 T +(t \050int tag, \337oat data\051;) 314.7 199.33 T +(int inser) 279.29 187.33 T +(t \050int tag, doub) 314.7 187.33 T +(le data\051;) 378.43 187.33 T +(int inser) 279.29 175.33 T +(t \050int tag, cde) 314.7 175.33 T +(v_TS_ST) 372.21 175.33 T +(AMP data\051;) 412.69 175.33 T +0 F +0.61 (These methods allo) 279.29 158.33 P +0.61 (w the user to inser) 367.61 158.33 P +0.61 (t a single data item into) 452.14 158.33 P +2.02 (the cde) 279.43 146.33 P +2.02 (vData object using the speci\336ed tag. If another data) 313.95 146.33 P +0.79 (item already occupies that tag within the cde) 279.43 134.33 P +0.79 (vData object, the) 481.39 134.33 P +2.63 (ne) 279.43 122.33 P +2.63 (w data item will o) 290.35 122.33 P +2.63 (v) 376.84 122.33 P +2.63 (err) 381.59 122.33 P +2.63 (ide the old one) 393.96 122.33 P +2.63 (. Although only the) 467.29 122.33 P +6.15 (integer tag prototypes are sho) 279.43 110.33 P +6.15 (wn, these functions are) 436.73 110.33 P +2.28 (o) 279.43 98.33 P +2.28 (v) 284.84 98.33 P +2.28 (er) 289.59 98.33 P +2.28 (loaded to suppor) 298.63 98.33 P +2.28 (t both the integer and char) 378.08 98.33 P +2.28 (acter str) 506.11 98.33 P +2.28 (ing) 544.66 98.33 P +(data tags) 279.43 86.33 T +(.) 320.42 86.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "43" 51 +%%Page: "44" 52 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Using the cde) 54 739 T +(vData Object) 118.76 739 T +0 10 Q +(44) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(inser) 162 713.33 T +(t \050arra) 186.1 713.33 T +(y\051) 214.24 713.33 T +4 F +(int inser) 261.29 713.33 T +(t \050int tag, BYTE * data, siz) 296.7 713.33 T +(e_t len, siz) 411.05 713.33 T +(e_t ndim\051;) 458.7 713.33 T +(int inser) 261.29 701.33 T +(t \050int tag, shor) 296.7 701.33 T +(t * data, siz) 358.24 701.33 T +(e_t len, siz) 407.56 701.33 T +(e_t ndim\051;) 455.21 701.33 T +-0.28 (int inser) 261.29 689.33 P +-0.28 (t \050int tag, unsigned shor) 296.42 689.33 P +-0.28 (t * data, siz) 400.22 689.33 P +-0.28 (e_t len, siz) 448.72 689.33 P +-0.28 (e_t ndim\051;) 495.82 689.33 P +(int inser) 261.29 677.33 T +(t \050int tag, int * data, siz) 296.7 677.33 T +(e_t len, siz) 395.49 677.33 T +(e_t ndim\051;) 443.14 677.33 T +(int inser) 261.29 665.33 T +(t \050int tag, unsigned int * data, siz) 296.7 665.33 T +(e_t len, siz) 438.85 665.33 T +(e_t ndim\051;) 486.5 665.33 T +(int inser) 261.29 653.33 T +(t \050int tag, long * data, siz) 296.7 653.33 T +(e_t len, siz) 403.83 653.33 T +(e_t ndim\051;) 451.48 653.33 T +(int inser) 261.29 641.33 T +(t \050int tag, unsigned long * data, siz) 296.7 641.33 T +(e_t len, siz) 447.19 641.33 T +(e_t ndim\051;) 494.84 641.33 T +(int inser) 261.29 629.33 T +(t \050int tag, \337oat * data, siz) 296.7 629.33 T +(e_t len, siz) 403.83 629.33 T +(e_t ndim\051;) 451.48 629.33 T +(int inser) 261.29 617.33 T +(t \050int tag, doub) 296.7 617.33 T +(le * data, siz) 360.43 617.33 T +(e_t len, siz) 414.75 617.33 T +(e_t ndim\051;) 462.4 617.33 T +0 F +-0.27 (These methods allo) 261.29 600.33 P +-0.27 (w the user to inser) 347.87 600.33 P +-0.27 (t arr) 428.9 600.33 P +-0.27 (a) 446.31 600.33 P +-0.27 (y data items into the) 451.57 600.33 P +0.86 (cde) 261.43 588.33 P +0.86 (vData object using the speci\336ed tag. The len par) 277.25 588.33 P +0.86 (ameter is) 498.02 588.33 P +0.04 (used to specify the total n) 261.43 576.33 P +0.04 (umber of items in the arr) 374.94 576.33 P +0.04 (a) 483.42 576.33 P +0.04 (y) 488.68 576.33 P +0.04 (. The ndim) 492.68 576.33 P +0.87 (par) 261.43 564.33 P +0.87 (ameter is used to specify the n) 275.78 564.33 P +0.87 (umber of dimensions in the) 416.49 564.33 P +1.47 (arr) 261.43 552.33 P +1.47 (a) 273.55 552.33 P +1.47 (y \0501 b) 278.81 552.33 P +1.47 (y def) 306.56 552.33 P +1.47 (ault\051. Although only the integer tag prototypes) 329.41 552.33 P +0.44 (are sho) 261.43 540.33 P +0.44 (wn, these functions are o) 295.07 540.33 P +0.44 (v) 407.86 540.33 P +0.44 (er) 412.61 540.33 P +0.44 (loaded to suppor) 421.65 540.33 P +0.44 (t both the) 497.42 540.33 P +(integer and char) 261.43 528.33 T +(acter str) 333.59 528.33 T +(ing data tags) 369.86 528.33 T +(.) 426.97 528.33 T +2 F +(inser) 162 504.33 T +(t \050c) 186.1 504.33 T +(haracter string\051) 201 504.33 T +4 F +(int inser) 261.29 492.33 T +(t \050int tag, char * data\051;) 296.7 492.33 T +(int inser) 261.29 480.33 T +(t \050int tag, char ** data, siz) 296.7 480.33 T +(e_t len, siz) 408.27 480.33 T +(e_t ndim\051;) 455.92 480.33 T +0 F +1.82 (These methods are used to add NULL ter) 261.29 463.33 P +1.82 (minated char) 458.25 463.33 P +1.82 (acter) 517.77 463.33 P +0.93 (str) 261.43 451.33 P +0.93 (ings to the cde) 272.69 451.33 P +0.93 (vData object. These methods diff) 340.21 451.33 P +0.93 (er from the) 489.8 451.33 P +0.62 (others because a single char) 261.43 439.33 P +0.62 (acter str) 391.64 439.33 P +0.62 (ing is treated as a scalar) 428.53 439.33 P +3.34 (v) 261.43 427.33 P +3.34 (alue) 266.18 427.33 P +3.34 (. The len par) 284.93 427.33 P +3.34 (ameter \050where used\051 speci\336es the total) 351 427.33 P +0 (n) 261.43 415.33 P +0 (umber of char) 266.89 415.33 P +0 (acter str) 328.49 415.33 P +0 (ings in the arr) 364.76 415.33 P +0 (a) 425.24 415.33 P +0 (y) 430.5 415.33 P +0 (. The ndim par) 434.5 415.33 P +0 (ameter is) 498.88 415.33 P +1.54 (used to specify the n) 261.43 403.33 P +1.54 (umber of dimensions in the arr) 359.21 403.33 P +1.54 (a) 501.85 403.33 P +1.54 (y \0501 b) 507.11 403.33 P +1.54 (y) 535 403.33 P +1.46 (def) 261.43 391.33 P +1.46 (ault\051. Although only the integer tag prototypes are sho) 275.03 391.33 P +1.46 (wn,) 524.44 391.33 P +0.3 (these functions are o) 261.43 379.33 P +0.3 (v) 355.01 379.33 P +0.3 (er) 359.76 379.33 P +0.3 (loaded to suppor) 368.8 379.33 P +0.3 (t both the integer and) 444.29 379.33 P +(char) 261.43 367.33 T +(acter str) 280.78 367.33 T +(ing data tags) 317.05 367.33 T +(.) 374.16 367.33 T +2 F +(g) 162 343.33 T +(et) 168.21 343.33 T +4 F +(int get\050int tag, BYTE * data\051;) 261.29 343.33 T +(int get\050int tag, shor) 261.29 331.33 T +(t * data\051;) 344.51 331.33 T +(int get\050int tag, unsigned shor) 261.29 319.33 T +(t * data\051;) 387.87 319.33 T +(int get\050int tag, int * data\051;) 261.29 307.33 T +(int get\050int tag, unsigned int * data\051;) 261.29 295.33 T +(int get\050int tag, long * data\051;) 261.29 283.33 T +(int get\050int tag, unsigned long * data\051;) 261.29 271.33 T +(int get\050int tag, \337oat * data\051;) 261.29 259.33 T +(int get\050int tag, doub) 261.29 247.33 T +(le * data\051;) 346.7 247.33 T +(int get\050int tag, cde) 261.29 235.33 T +(v_TS_ST) 340.48 235.33 T +(AMP * data\051;) 380.96 235.33 T +0 F +1.2 (These methods are used to retr) 261.29 218.33 P +1.2 (ie) 406.93 218.33 P +1.2 (v) 414.41 218.33 P +1.2 (e scalar v) 419.16 218.33 P +1.2 (alues and arr) 464.09 218.33 P +1.2 (a) 524.74 218.33 P +1.2 (ys) 530 218.33 P +2.59 (that are stored in the cde) 261.43 206.33 P +2.59 (vData object. When retr) 384.72 206.33 P +2.59 (ie) 497.69 206.33 P +2.59 (ving an) 505.17 206.33 P +-0.02 (arr) 261.43 194.33 P +-0.02 (a) 273.55 194.33 P +-0.02 (y) 278.81 194.33 P +-0.02 (, it is the caller\325) 282.81 194.33 P +-0.02 (s responsibility to call the) 348.37 194.33 P +4 F +-0.02 (getElems) 462.21 194.33 P +0 F +-0.02 ( method) 503.89 194.33 P +2.12 (to obtain the n) 261.43 182.33 P +2.12 (umber of elements and then pre-allocate the) 331.07 182.33 P +1.19 (b) 261.43 170.33 P +1.19 (uff) 266.79 170.33 P +1.19 (er to receiv) 277.61 170.33 P +1.19 (e the data. If the receiving data type does not) 329.19 170.33 P +1.71 (match the data type stored in the cde) 261.43 158.33 P +1.71 (vData object, then the) 437.61 158.33 P +1.89 (data will be con) 261.43 146.33 P +1.89 (v) 335.81 146.33 P +1.89 (er) 340.56 146.33 P +1.89 (ted to the ne) 349.85 146.33 P +1.89 (w type when it is e) 410.91 146.33 P +1.89 (xtr) 501.75 146.33 P +1.89 (acted.) 512.76 146.33 P +2.88 (Although only the integer tag prototypes are sho) 261.43 134.33 P +2.88 (wn, these) 494.32 134.33 P +3.74 (functions are o) 261.43 122.33 P +3.74 (v) 334.36 122.33 P +3.74 (er) 339.11 122.33 P +3.74 (loaded to suppor) 348.15 122.33 P +3.74 (t both the integer and) 430.52 122.33 P +(char) 261.43 110.33 T +(acter str) 280.78 110.33 T +(ing data tags) 317.05 110.33 T +(.) 374.16 110.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "44" 52 +%%Page: "45" 53 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Using the cde) 441.22 739 T +(vData Object) 505.98 739 T +0 10 Q +(45) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(g) 180 713.33 T +(et \050c) 186.21 713.33 T +(haracter string\051) 206.67 713.33 T +4 F +(int get\050int tag, char * data, siz) 279.29 701.33 T +(e_t len\051;) 408.65 701.33 T +(int get\050int tag, char ** data\051;) 279.29 689.33 T +0 F +3.13 (These methods are used to retr) 279.29 672.33 P +3.13 (ie) 434.61 672.33 P +3.13 (v) 442.09 672.33 P +3.13 (e char) 446.84 672.33 P +3.13 (acter str) 477.66 672.33 P +3.13 (ings and) 517.07 672.33 P +3.29 (arr) 279.43 660.33 P +3.29 (a) 291.55 660.33 P +3.29 (ys of char) 296.81 660.33 P +3.29 (acter str) 346.65 660.33 P +3.29 (ings from a cde) 386.21 660.33 P +3.29 (vData object. When) 464.15 660.33 P +0.99 (obtaining a single char) 279.43 648.33 P +0.99 (acter str) 382.36 648.33 P +0.99 (ing, the length of the allocated) 419.62 648.33 P +0.76 (b) 279.43 636.33 P +0.76 (uff) 284.79 636.33 P +0.76 (er m) 295.61 636.33 P +0.76 (ust be speci\336ed in the) 316.27 636.33 P +4 F +0.76 (len) 419.58 636.33 P +0 F +0.76 ( par) 432.92 636.33 P +0.76 (ameter) 450.82 636.33 P +0.76 (. When obtaining) 481.44 636.33 P +1.38 (an arr) 279.43 624.33 P +1.38 (a) 306.83 624.33 P +1.38 (y of char) 312.09 624.33 P +1.38 (acter str) 353.1 624.33 P +1.38 (ings) 390.74 624.33 P +1.38 (, the caller m) 408.93 624.33 P +1.38 (ust pre-allocate the) 470.2 624.33 P +0.23 (POINTERS f) 279.43 612.33 P +0.23 (or each element in the arr) 336.05 612.33 P +0.23 (a) 451.06 612.33 P +0.23 (y) 456.32 612.33 P +0.23 (. The cde) 460.32 612.33 P +0.23 (vData object) 502.18 612.33 P +1.15 (will allocate suf\336cient memor) 279.43 600.33 P +1.15 (y to each of the pointers to hold) 410.43 600.33 P +7.18 (the individual char) 279.43 588.33 P +7.18 (acter str) 374.27 588.33 P +7.18 (ings) 417.72 588.33 P +7.18 (. It then becomes the) 435.91 588.33 P +-0.19 (responsibility of the caller to free the memor) 279.43 576.33 P +-0.19 (y assigned to those) 472.39 576.33 P +1.86 (pointers) 279.43 564.33 P +1.86 (. If the receiving data type does not match the data) 314.85 564.33 P +3.32 (type stored in the cde) 279.43 552.33 P +3.32 (vData object, then the data will be) 388.01 552.33 P +1.02 (con) 279.43 540.33 P +1.02 (v) 295.35 540.33 P +1.02 (er) 300.1 540.33 P +1.02 (ted to the ne) 309.39 540.33 P +1.02 (w type when it is e) 367.85 540.33 P +1.02 (xtr) 454.34 540.33 P +1.02 (acted. Although only) 465.35 540.33 P +3.3 (the integer tag prototypes are sho) 279.43 528.33 P +3.3 (wn, these functions are) 445.29 528.33 P +2.28 (o) 279.43 516.33 P +2.28 (v) 284.84 516.33 P +2.28 (er) 289.59 516.33 P +2.28 (loaded to suppor) 298.63 516.33 P +2.28 (t both the integer and char) 378.08 516.33 P +2.28 (acter str) 506.11 516.33 P +2.28 (ing) 544.66 516.33 P +(data tags) 279.43 504.33 T +(.) 320.42 504.33 T +2 F +(\336nd) 180 480.33 T +4 F +(int \336nd\050int tag, v) 279.29 480.33 T +(oid* &data\051;) 349.63 480.33 T +(int \336nd\050char * ctag, v) 279.29 468.33 T +(oid* &data\051;) 370.19 468.33 T +0 F +0.32 (Retr) 279.29 451.33 P +0.32 (ie) 298.33 451.33 P +0.32 (v) 305.81 451.33 P +0.32 (es a pointer to the data within the cde) 310.56 451.33 P +0.32 (vData object. The) 479 451.33 P +0.21 (caller is responsib) 279.43 439.33 P +0.21 (le f) 359.68 439.33 P +0.21 (or ensur) 372.93 439.33 P +0.21 (ing that the receiving pointer is of) 409.98 439.33 P +-0.22 (the correct data type f) 279.43 427.33 P +-0.22 (or the data within the object. This function) 374.98 427.33 P +0.91 (is o) 279.43 415.33 P +0.91 (v) 295.76 415.33 P +0.91 (er) 300.51 415.33 P +0.91 (loaded to suppor) 309.55 415.33 P +0.91 (t both integer and char) 386.27 415.33 P +0.91 (acter str) 489.88 415.33 P +0.91 (ing tag) 527.07 415.33 P +(identi\336ers) 279.43 403.33 T +(.) 322.07 403.33 T +2 F +(Sample Code) 72 374.33 T +0 F +0.07 (The f) 180 374.33 P +0.07 (ollo) 202.56 374.33 P +0.07 (wing sample prog) 217.97 374.33 P +0.07 (r) 296.36 374.33 P +0.07 (am sho) 299.59 374.33 P +0.07 (ws the steps necessar) 332.3 374.33 P +0.07 (y to add a ne) 431.72 374.33 P +0.07 (w tag char) 489.61 374.33 P +0.07 (acter) 535.77 374.33 P +0.97 (str) 180 362.33 P +0.97 (ing and tag integer to the global CDEV tag tab) 191.26 362.33 P +0.97 (le) 403.8 362.33 P +0.97 (. This method is most frequently) 411.43 362.33 P +(used b) 180 350.33 T +(y the CDEV system and CDEV ser) 209.82 350.33 T +(vices) 363.5 350.33 T +(.) 386.13 350.33 T +4 9 Q +(Figure 26: Using inser) 180 317 T +(tT) 270.89 317 T +(ag to add a ne) 277.81 317 T +(w tag) 335.18 317 T +180 81 558 381 C +180 107.26 558 314 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +237.71 109.95 611.29 306.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +231.75 114.74 605.7 312.29 R +7 X +V +0 X +N +237 117.7 598.28 309.03 R +7 X +V +5 9 Q +0 X +(#include ) 237 303.03 T +(void main\050\051) 237 281.03 T +({) 255 270.03 T +(// ************************************************************) 255 259.03 T +(// * Unique tag number and character string) 255 248.03 T +(// ************************************************************) 255 237.03 T +(int tag = 100;) 255 226.03 T +(char * tagName = \322testTag\323;) 255 215.03 T +(// ************************************************************) 255 193.03 T +(// * Insert the new tag) 255 182.03 T +(// ************************************************************) 255 171.03 T +(cdevData::insertTag\050tag, tagName\051;) 255 160.03 T +(printf\050\322Inserted tag %s as tag number %i\134n\323, tagName, tag\051;) 255 149.03 T +(}) 255 138.03 T +180 81 558 381 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "45" 53 +%%Page: "46" 54 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Using the cde) 54 739 T +(vData Object) 118.76 739 T +0 10 Q +(46) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0.99 (The f) 162 713.33 P +0.99 (ollo) 185.48 713.33 P +0.99 (wing sample application illustr) 200.89 713.33 P +0.99 (ates the steps necessar) 336.02 713.33 P +0.99 (y to con) 444.91 713.33 P +0.99 (v) 481.71 713.33 P +0.99 (er) 486.46 713.33 P +0.99 (t betw) 495.75 713.33 P +0.99 (een) 523.32 713.33 P +(char) 162 701.33 T +(acter str) 181.35 701.33 T +(ing and integer tag v) 217.62 701.33 T +(alues using the) 307.98 701.33 T +4 F +(tagI2C) 378.02 701.33 T +0 F +( and) 407.48 701.33 T +4 F +(tagC2I) 429.72 701.33 T +0 F +( methods) 459.18 701.33 T +(.) 500.16 701.33 T +4 9 Q +(Figure 27: Using tagC2I and tagI2C to deter) 162 668 T +(mine cde) 339.32 668 T +(vData tag identi\336ers) 375.56 668 T +0 10 Q +0.22 (The f) 162 335.1 P +0.22 (ollo) 184.71 335.1 P +0.22 (wing sample application sho) 200.12 335.1 P +0.22 (ws the steps necessar) 325.66 335.1 P +0.22 (y to place scalar data into) 425.54 335.1 P +1.05 (a cde) 162 323.1 P +1.05 (vData object using the) 187.21 323.1 P +4 F +1.05 (inser) 293.15 323.1 P +1.05 (t) 315.22 323.1 P +0 F +1.05 ( method and then retr) 318 323.1 P +1.05 (ie) 417.98 323.1 P +1.05 (v) 425.46 323.1 P +1.05 (e the data using the) 430.21 323.1 P +4 F +1.05 (get) 526.1 323.1 P +0 F +(method.) 162 311.1 T +4 9 Q +(Figure 28: Inser) 162 277.76 T +(ting and retr) 227.89 277.76 T +(ie) 276.05 277.76 T +(ving scalar data items using a cde) 282.78 277.76 T +(vData object) 418.07 277.76 T +162 81 540 720 C +162 365.76 540 665 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +219.71 370.12 593.29 657.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +213.75 376.57 587.7 663.29 R +7 X +V +0 X +N +219 382.04 580.28 658.59 R +7 X +V +5 9 Q +0 X +(#include ) 219 652.59 T +(void main\050\051) 219 630.59 T +({) 237 619.59 T +(int tag;) 237 608.59 T +(char * tagName;) 237 597.59 T +(// ************************************************************) 237 586.59 T +(// * Insert a new tag into cdevData to illustrate this function) 237 575.59 T +(// ************************************************************) 237 564.59 T +(cdevData::insertTag\050100, \322testTag\323\051;) 237 553.59 T +(// ************************************************************) 237 531.59 T +(// * Now use the command tagI2C to obtain the character string) 237 520.59 T +(// * name of the tag from the tag number.) 237 509.6 T +(// ************************************************************) 237 498.6 T +(cdevData::tagI2C\050100, tagName\051;) 237 487.6 T +(// ************************************************************) 237 465.6 T +(// * Using the newly obtained character string, call tagC2I to) 237 454.6 T +(// * obtain the integer tag value.) 237 443.6 T +(// ************************************************************) 237 432.6 T +(cdevData::tagC2I\050tagName, &tag\051;) 237 421.6 T +(printf\050\322Tag name %s is tag number %i\323, tagName, tag\051;) 237 399.6 T +(}) 237 388.6 T +162 81 540 720 C +0 0 612 792 C +162 81 540 720 C +162 82.05 540 274.76 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.29 85.92 541.86 266.9 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.32 90.5 536.27 273.05 R +7 X +V +0 X +N +167.57 94.07 528.85 270.7 R +7 X +V +5 9 Q +0 X +(#include ) 167.57 264.7 T +(void main\050\051) 167.57 242.7 T +({) 185.57 231.7 T +(cdevData data;) 185.57 220.7 T +(int x;) 185.57 209.7 T +(double y;) 185.57 198.7 T +(// ************************************************************) 185.57 176.7 T +(// Insert a short integer as the \322value\323 property.) 185.57 165.7 T +(// ************************************************************) 185.57 154.7 T +(data.insert\050\322value\323, \050short int\0511\051;) 185.57 143.7 T +(// ************************************************************) 185.57 121.7 T +(// * Insert a double as the \322status\323 property) 185.57 110.7 T +(// ************************************************************) 185.57 99.7 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "46" 54 +%%Page: "47" 55 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Using the cde) 441.22 739 T +(vData Object) 505.98 739 T +0 10 Q +(47) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +(Figure 28: Inser) 180 714 T +(ting and retr) 245.89 714 T +(ie) 294.05 714 T +(ving scalar data items using a cde) 300.78 714 T +(vData object \050contin) 436.07 714 T +(ued\051) 515.51 714 T +0 10 Q +0.59 (The f) 180 501.1 P +0.59 (ollo) 203.08 501.1 P +0.59 (wing e) 218.49 501.1 P +0.59 (xample illustr) 247.68 501.1 P +0.59 (ates the proper usage of the changeT) 306.51 501.1 P +0.59 (ag method to alter) 475.63 501.1 P +(the tag identi\336er of a data item stored in the cde) 180 489.1 T +(vData object.) 390.93 489.1 T +4 9 Q +(Figure 29: Using the changeT) 180 455.76 T +(ag method of the cde) 299.98 455.76 T +(vData object) 384.26 455.76 T +180 81 558 720 C +180 531.76 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.93 536.95 559.5 703.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +179.96 540.91 553.92 709.29 R +7 X +V +0 X +N +185.21 546.22 546.49 704.37 R +7 X +V +5 9 Q +0 X +(data.insert\050\322status\323, \050double\0512.0\051;) 203.21 698.37 T +(// ************************************************************) 203.21 676.37 T +(// * Get the short stored in the \322value\323 property as a double) 203.21 665.37 T +(// ************************************************************) 203.21 654.37 T +(data.get\050\322value\323, &y\051;) 203.21 643.37 T +(printf\050\322value is %f\134n\323, y\051;) 203.21 632.37 T +(// ************************************************************) 203.21 610.37 T +(// * Get the double stored in the \322status\323 property as an int) 203.21 599.37 T +(// ************************************************************) 203.21 588.37 T +(data.get\050\322status\323, &x\051;) 203.21 577.37 T +(printf\050\322status is %i\134n\323, x\051;) 203.21 566.37 T +(}) 203.21 555.37 T +180 81 558 720 C +0 0 612 792 C +180 81 558 720 C +180 156.03 558 452.76 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +187.36 162.05 560.93 444.9 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +181.39 167.67 555.34 451.05 R +7 X +V +0 X +N +186.64 173.08 547.92 446.41 R +7 X +V +5 9 Q +0 X +(#include ) 186.64 440.41 T +(void main\050\051) 186.64 418.41 T +({) 204.64 407.41 T +(cdevData data;) 204.64 396.41 T +(short int x;) 204.64 385.41 T +(// ************************************************************) 204.64 363.41 T +(// Insert a short integer as the \322value\323 property.) 204.64 352.41 T +(// ************************************************************) 204.64 341.41 T +(data.insert\050\322value\323, \050short int\0511\051;) 204.64 330.41 T +(// ************************************************************) 204.64 308.41 T +(// * Use the changeTag method to convert the tag identifier) 204.64 297.41 T +(// * for the data item from \322value\323 to \322status\323.) 204.64 286.41 T +(// ************************************************************) 204.64 275.41 T +(data.changeTag\050\322value\323, \322status\323\051;) 204.64 264.41 T +(// ************************************************************) 204.64 242.41 T +(// * Use the get method to retrieve the short integer from the) 204.64 231.41 T +(// * \322status\323 property.) 204.64 220.41 T +(// ************************************************************) 204.64 209.41 T +(data.get\050\322status\323, &x\051;) 204.64 198.41 T +(printf\050\322Retrieved %i from the status property\134n\323, x\051;) 204.64 187.41 T +(}) 204.64 176.41 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "47" 55 +%%Page: "48" 56 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Using the cde) 54 739 T +(vData Object) 118.76 739 T +0 10 Q +(48) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0.7 (The f) 162 713.33 P +0.7 (ollo) 185.19 713.33 P +0.7 (wing sample application illustr) 200.6 713.33 P +0.7 (ates ho) 334.87 713.33 P +0.7 (w to use the cde) 368.23 713.33 P +0.7 (vData object to inser) 443.56 713.33 P +0.7 (t) 537.22 713.33 P +(and retr) 162 701.33 T +(ie) 196.61 701.33 T +(v) 204.09 701.33 T +(e a 1 dimensional arr) 208.84 701.33 T +(a) 302.11 701.33 T +(y of doub) 307.37 701.33 T +(les) 348.31 701.33 T +(.) 360.94 701.33 T +4 9 Q +(Figure 30: Using one-dimensional arr) 162 668 T +(a) 312.46 668 T +(ys with cde) 317.2 668 T +(vData objects) 361.44 668 T +162 81 540 720 C +162 117 540 665 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.64 160.12 542.22 657.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.68 166.57 536.63 663.29 R +7 X +V +0 X +N +167.93 170.54 529.21 658.31 R +7 X +V +5 9 Q +0 X +(#include ) 167.93 652.31 T +(void main\050\051) 167.93 630.31 T +({) 185.93 619.31 T +(cdevData data;) 185.93 608.31 T +(size_t count;) 185.93 597.31 T +(double inArray[5] = {1.0, 2.0, 3.0, 4.0, 5.0};) 185.93 586.31 T +(double *outArray;) 185.93 575.31 T +(// ************************************************************) 185.93 553.31 T +(// * Use the insert method to add the array to the value) 185.93 542.31 T +(// * property of the cdevData object.) 185.93 531.31 T +(// ************************************************************) 185.93 520.31 T +(data.insert\050\322value\323, inArray, 5\051;) 185.93 509.31 T +(// ************************************************************) 185.93 487.31 T +(// * Now we will extract the data that we just inserted.) 185.93 476.31 T +(// * First, use the getElems method to determine the number of) 185.93 465.31 T +(// * elements in the array.) 185.93 454.31 T +(// ************************************************************) 185.93 443.31 T +(data.getElems\050\322value\323, &count\051;) 185.93 432.31 T +(// ************************************************************) 185.93 410.31 T +(// * Next allocate an array of doubles sufficient to hold) 185.93 399.31 T +(// * the array stored in the cdevData object.) 185.93 388.31 T +(// ************************************************************) 185.93 377.31 T +(outArray = new double[count];) 185.93 366.31 T +(// ************************************************************) 185.93 344.31 T +(// * Finally, retrieve the data from the cdevData object using) 185.93 333.31 T +(// * the get method.) 185.93 322.31 T +(// ************************************************************) 185.93 311.31 T +(data.get\050\322value\323, outArray\051;) 185.93 300.31 T +(// ************************************************************) 185.93 278.31 T +(// * Output the result and then free any locally allocated) 185.93 267.31 T +(// * memory.) 185.93 256.31 T +(// ************************************************************) 185.93 245.31 T +(for \050int i=0; i) 167.21 697.8 T +(void main\050\051) 167.21 675.8 T +({) 185.21 664.8 T +(cdevData data;) 185.21 653.8 T +(int i;) 185.21 642.8 T +(size_t nElems=1;) 185.21 631.8 T +(size_t nDim =1;) 185.21 620.8 T +(cdevBounds inbounds[2];) 185.21 609.8 T +(double inarray[2][5] =) 185.21 598.8 T +({) 185.21 587.8 T +({0.0, 1.0, 2.0, 3.0, 4.0},) 185.21 576.8 T +({5.0, 6.0, 7.0, 8.0, 9.0}) 185.21 565.8 T +(};) 185.21 554.8 T +(double * outarray;) 185.21 532.8 T +(cdevBounds * outbounds;) 185.21 521.8 T +(// ############################################################) 185.21 499.8 T +(// # Inserting multi-dimensional data into a cdevData object.) 185.21 488.8 T +(// ############################################################) 185.21 477.8 T +(// ************************************************************) 185.21 455.8 T +(// * Set the length of each dimension of the array within the) 185.21 444.8 T +(// * cdevBounds structure. Also, set the offset to 0 for each) 185.21 433.8 T +(// * dimension to specify that this array begins at the origen;) 185.21 422.8 T +(// ************************************************************) 185.21 411.8 T +(inbounds[0].offset = 0;) 185.21 389.8 T +(// Offset of first dimension) 309.41 389.8 T +(inbounds[0].length = 2;) 185.21 378.8 T +(// Length of first dimension) 309.41 378.8 T +(inbounds[1].offset = 0;) 185.21 356.8 T +(// Offset of second dimension) 309.41 356.8 T +(inbounds[1].length = 5;) 185.21 345.8 T +(// Length of second dimension) 309.41 345.8 T +(// ************************************************************) 185.21 323.8 T +(// * Use the insert method to add the array to the value) 185.21 312.8 T +(// * property of the cdevData object. The third parameter) 185.21 301.8 T +(// * specifies the exact number of elements that will be added,) 185.21 290.8 T +(// * while the fourth parameter specifies that this will be a) 185.21 279.8 T +(// * two dimensional array.) 185.21 268.8 T +(// ************************************************************) 185.21 257.8 T +(data.insert\050\322value\323, \050double *\051inarray, 10, 2\051;) 185.21 246.8 T +(// ************************************************************) 185.21 224.8 T +(// * Use the setBounds method to specify the bounding) 185.21 213.8 T +(// * dimensions of the multi-dimensional array.) 185.21 202.8 T +(// ************************************************************) 185.21 191.8 T +(data.setBounds\050\322value\323, inbounds, 2\051;) 185.21 180.8 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "50" 58 +%%Page: "51" 59 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Using the cde) 441.22 739 T +(vData Object) 505.98 739 T +0 10 Q +(51) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +(Figure 31: Using m) 180 714 T +(ulti-dimensional arr) 258.43 714 T +(a) 334.36 714 T +(ys with cde) 339.09 714 T +(vData objects \050contin) 383.34 714 T +(ued\051) 467.28 714 T +180 81 558 720 C +180 100.17 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.64 142 560.22 703.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +180.68 146.74 554.63 709.29 R +7 X +V +0 X +N +185.93 151.24 547.21 703.66 R +7 X +V +5 9 Q +0 X +(// ############################################################) 203.93 697.66 T +(// # Retrieving multi-dimensional data from a cdevData object.) 203.93 686.66 T +(// ############################################################) 203.93 675.66 T +(// ************************************************************) 203.93 653.66 T +(// * Call the getDim method to obtain the number of dimensions) 203.93 642.66 T +(// * in the array.) 203.93 631.66 T +(// ************************************************************) 203.93 620.66 T +(data.getDim\050\322value\323, &nDim\051;) 203.93 609.66 T +(// ************************************************************) 203.93 587.66 T +(// * Allocate a cdevBounds structure of sufficient size to) 203.93 576.66 T +(// * hold all dimensions of the array.) 203.93 565.66 T +(// ************************************************************) 203.93 554.66 T +(outbounds = new cdevBounds[nDim];) 203.93 543.66 T +(// ************************************************************) 203.93 521.66 T +(// * Use the getBounds methods to obtain the bounding) 203.93 510.65 T +(// * dimensions of the array.) 203.93 499.65 T +(// ************************************************************) 203.93 488.65 T +(data.getBounds\050\322value\323, outbounds, 2\051;) 203.93 477.65 T +(// ************************************************************) 203.93 455.65 T +(// * Calculate the number of elements in the complete array.) 203.93 444.65 T +(// * This step is shown for illustrative purposes only. The) 203.93 433.65 T +(// * result of this operation should be the same value that) 203.93 422.65 T +(// * would be returned by the getElems method.) 203.93 411.65 T +(// ************************************************************) 203.93 400.65 T +(for\050i=0; i) 167.57 630.67 T +(void main\050\051) 167.57 608.67 T +({) 185.57 597.67 T +(cdevData data;) 185.57 586.67 T +(char * inString = \322This is my test string\323;) 185.57 575.67 T +(char outString[50];) 185.57 564.67 T +(// ************************************************************) 185.57 542.67 T +(// * Use the insert method to insert the character string into) 185.57 531.67 T +(// * the cdevData object.) 185.57 520.67 T +(// ************************************************************) 185.57 509.67 T +(data.insert\050\322value\323, inString\051;) 185.57 498.67 T +(// ************************************************************) 185.57 476.67 T +(// * Next, use the get function to retrieve the string. The) 185.57 465.67 T +(// * maximum length of the string to be retrieved is specified) 185.57 454.67 T +(// * by the third parameter \05050\051.) 185.57 443.67 T +(// ************************************************************) 185.57 432.67 T +(data.get\050\322value\323, outString, 50\051;) 185.57 421.67 T +(printf\050\322String is: %s\134n\323, outString\051;) 185.57 399.67 T +(}) 185.57 388.67 T +162 81 540 720 C +0 0 612 792 C +162 81 540 720 C +162 82.5 540 212.5 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.29 87.67 541.86 204.64 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.32 93.24 536.27 210.79 R +7 X +V +0 X +N +167.57 95.69 528.85 209.61 R +7 X +V +5 9 Q +0 X +(#include ) 167.57 203.61 T +(void main\050\051) 167.57 181.61 T +({) 185.57 170.61 T +(cdevData data;) 185.57 159.61 T +(char ** outString;) 185.57 148.61 T +(size_t nElems;) 185.57 137.61 T +(int i;) 185.57 126.61 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "52" 60 +%%Page: "53" 61 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Using the cde) 441.22 739 T +(vData Object) 505.98 739 T +0 10 Q +(53) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +(Figure 33: Using char) 180 714 T +(acter str) 268.44 714 T +(ing arr) 301.09 714 T +(a) 326.5 714 T +(ys with cde) 331.24 714 T +(vData objects \050contin) 375.48 714 T +(ued\051) 459.42 714 T +180 81 558 720 C +180 86.83 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.29 150.33 559.86 703.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +180.32 154.24 554.27 709.29 R +7 X +V +0 X +N +185.57 160.17 546.85 703.73 R +7 X +V +5 9 Q +0 X +(char * inStrings[10] =) 203.57 697.73 T +({) 221.57 686.73 T +(\322string 0\323,) 221.57 675.73 T +(\322string 1\323,) 221.57 664.73 T +(\322string 2\323,) 221.57 653.73 T +(\322string 3\323,) 221.57 642.73 T +(\322string 4\323,) 221.57 631.73 T +(\322string 5\323,) 221.57 620.73 T +(\322string 6\323,) 221.57 609.73 T +(\322string 7\323,) 221.57 598.73 T +(\322string 8\323,) 221.57 587.73 T +(\322string 9\323) 221.57 576.73 T +(};) 221.57 565.73 T +(// ############################################################) 203.57 543.73 T +(// # Inserting character string arrays) 203.57 532.73 T +(// ############################################################) 203.57 521.73 T +(// ************************************************************) 203.57 499.73 T +(// * Place the array of character strings into the cdevData) 203.57 488.73 T +(// * object using the insert command. \050by default, ndim=1\051) 203.57 477.73 T +(// ************************************************************) 203.57 466.73 T +(data.insert\050\322value\323, inStrings, 10\051;) 203.57 455.73 T +(// ############################################################) 203.57 433.73 T +(// # Retrieving character string arrays) 203.57 422.73 T +(// ############################################################) 203.57 411.73 T +(// ************************************************************) 203.57 389.73 T +(// * Use the getElems function to determine the total number) 203.57 378.73 T +(// * of STRINGS that will be retrieved.) 203.57 367.73 T +(// ************************************************************) 203.57 356.73 T +(data.getElems\050\322value\323, &nElems\051;) 203.57 345.73 T +(// ************************************************************) 203.57 323.73 T +(// * Allocate an array of pointers, 1 for each element.) 203.57 312.73 T +(// ************************************************************) 203.57 301.73 T +(outString = new char *[nElems];) 203.57 290.73 T +(// ************************************************************) 203.57 268.73 T +(// * Use the get method to retrive the data from cdevData.) 203.57 257.73 T +(// ************************************************************) 203.57 246.73 T +(data.get\050\322value\323, outString\051;) 203.57 235.73 T +(// ************************************************************) 203.57 213.73 T +(// * Output the data recieved from the cdevData object.) 203.57 202.73 T +(// ************************************************************) 203.57 191.73 T +(for\050i=0; i) 167.57 417.04 T +(void main\050\051) 167.57 395.04 T +({) 185.57 384.04 T +(char * inStrings[10] =) 185.57 373.04 T +({) 203.57 362.04 T +(\322string 0\323,) 203.57 351.04 T +(\322string 1\323,) 203.57 340.04 T +(\322string 2\323,) 203.57 329.04 T +(\322string 3\323,) 203.57 318.04 T +(\322string 4\323,) 203.57 307.04 T +(\322string 5\323,) 203.57 296.04 T +(\322string 6\323,) 203.57 285.04 T +(\322string 7\323,) 203.57 274.04 T +(\322string 8\323,) 203.57 263.04 T +(\322string 9\323) 203.57 252.04 T +(};) 203.57 241.04 T +(cdevData data;) 185.57 230.04 T +(cdevDataTypes datatype;) 185.57 219.04 T +(char ** outString;) 185.57 208.04 T +(size_t nElems;) 185.57 197.04 T +(int i;) 185.57 186.04 T +(// ************************************************************) 185.57 164.04 T +(// * Place the array of character strings into the cdevData) 185.57 153.04 T +(// * object using the insert command.) 185.57 142.04 T +(// ************************************************************) 185.57 131.04 T +(data.insert\050\322value\323, inStrings, 10\051;) 185.57 120.04 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "54" 62 +%%Page: "55" 63 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(6. Using the cde) 441.22 739 T +(vData Object) 505.98 739 T +0 10 Q +(55) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +(Figure 34: Using the \336nd method of the cde) 180 714 T +(vData object \050contin) 354.83 714 T +(ued\051) 434.27 714 T +180 81 558 720 C +180 371 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.29 374.5 559.86 703.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +180.32 379.24 554.27 709.29 R +7 X +V +0 X +N +185.57 384.97 546.85 707.04 R +7 X +V +5 9 Q +0 X +(// ############################################################) 203.57 701.04 T +(// # Retrieving a pointer to the data using the find method) 203.57 690.04 T +(// ############################################################) 203.57 679.04 T +(// ************************************************************) 203.57 657.04 T +(// * For this example, we are going to ensure that the value) 203.57 646.04 T +(// * we are obtaining is an array of strings.) 203.57 635.04 T +(// * The getType method will be caller to ensure that the) 203.57 624.04 T +(// * data type of the value is CDEV_STRING, and then the) 203.57 613.04 T +(// * getElems method will be called to make sure that their) 203.57 602.04 T +(// * is more than one string in the cdevData object.) 203.57 591.04 T +(// ************************************************************) 203.57 580.04 T +(datatype = data.getType\050\322value\323\051;) 203.57 569.04 T +(data.getElems\050\322value\323, &nElems\051;) 203.57 558.04 T +(if\050datatype==CDEV_STRING && nElems>0\051) 203.57 536.04 T +({) 221.57 525.04 T +(// ********************************************************) 221.57 514.04 T +(// * Call find to obtain a copy of the data.) 221.57 503.04 T +(// ********************************************************) 221.57 492.04 T +(data.find\050\322value\323, \050void *&\051outString\051;) 221.57 481.04 T +(// ********************************************************) 221.57 459.04 T +(// * Output the data recieved from the cdevData object.) 221.57 448.04 T +(// ********************************************************) 221.57 437.04 T +(while\050outString[i]!=NULL\051) 221.57 426.04 T +(printf\050\322String %i: %s\134n\323, i++, outString[i]\051;) 239.57 415.04 T +(}) 221.57 404.04 T +(}) 203.57 393.04 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "55" 63 +%%Page: "56" 64 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. Using the cde) 54 739 T +(vDirector) 118.76 739 T +(y De) 155.03 739 T +(vice) 173.27 739 T +0 10 Q +(56) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(7.) 141.32 710.67 T +(Using the) 162 710.67 T +3 F +(cde) 229.68 710.67 T +(vDirector) 253.59 710.67 T +(y) 315.19 710.67 T +2 F +( De) 322.97 710.67 T +(vice) 344.55 710.67 T +2 10 Q +(cde) 54 673.33 T +(vDirector) 71.08 673.33 T +(y) 115.08 673.33 T +(De) 54 661.33 T +(vice) 66.63 661.33 T +0 F +-0.28 (The cde) 162 673.33 P +-0.28 (vDirector) 197.55 673.33 P +-0.28 (y de) 237.85 673.33 P +-0.28 (vice is a cde) 256.18 673.33 P +-0.28 (vDe) 310.07 673.33 P +-0.28 (vice object that pro) 327.55 673.33 P +-0.28 (vides an interf) 410.5 673.33 P +-0.28 (ace to director) 471.89 673.33 P +-0.28 (y) 535 673.33 P +1.25 (ser) 162 661.33 P +1.25 (vices within CDEV) 176.19 661.33 P +1.25 (. Director) 259.13 661.33 P +1.25 (y ser) 301.24 661.33 P +1.25 (vices allo) 324.46 661.33 P +1.25 (w an application to obtain data that is) 366.69 661.33 P +1.02 (speci\336ed in the de) 162 649.33 P +1.02 (vice de\336nition \336le \050DDL \336le\051. Inf) 245.35 649.33 P +1.02 (or) 387.95 649.33 P +1.02 (mation in the DDL \336le identi\336es) 397.09 649.33 P +4 F +(ser) 162 637.33 T +(vices) 176.19 637.33 T +0 F +(,) 198.82 637.33 T +4 F +(de) 204.38 637.33 T +(vices) 215.2 637.33 T +0 F +( and) 237.98 637.33 T +4 F +(messages) 260.22 637.33 T +0 F +(that are suppor) 308.57 637.33 T +(ted b) 376.23 637.33 T +(y CDEV) 398.27 637.33 T +(.) 432.58 637.33 T +2 F +(Attac) 54 608.33 T +(hing to the) 78.9 608.33 T +(cde) 54 596.33 T +(vDirector) 71.08 596.33 T +(y) 115.08 596.33 T +0 F +0.64 (The cde) 162 608.33 P +0.64 (vDirector) 198.47 608.33 P +0.64 (y de) 238.77 608.33 P +0.64 (vice can be accessed in the same manner as an) 258.01 608.33 P +0.64 (y other CDEV) 477.59 608.33 P +3.26 (de) 162 596.33 P +3.26 (vice) 172.82 596.33 P +3.26 (. Their are tw) 190.45 596.33 P +3.26 (o methods f) 258.49 596.33 P +3.26 (or obtaining a cde) 316.97 596.33 P +3.26 (vDirector) 405.95 596.33 P +3.26 (y de) 446.25 596.33 P +3.26 (vice) 468.12 596.33 P +3.26 (. The \336rst) 485.75 596.33 P +0.08 (approach is to get a pointer or ref) 162 584.33 P +0.08 (erence to a cde) 309.58 584.33 P +0.08 (vDe) 378.46 584.33 P +0.08 (vice object with the de) 395.94 584.33 P +0.08 (vice name) 494.35 584.33 P +(set to cde) 162 572.33 T +(vDirector) 205.06 572.33 T +(y:) 245.36 572.33 T +4 F +(\322) 258.7 572.33 T +3 F +(cde) 262.03 572.33 T +(vDe) 279.11 572.33 T +(vice::attac) 297.3 572.33 T +(hPtr\050\322cde) 346.66 572.33 T +(vDirector) 392.07 572.33 T +(y\323\051) 436.07 572.33 T +4 F +(\323 .) 449.96 572.33 T +0 F +0.23 (The second approach allo) 162 555.33 P +0.23 (ws the caller to obtain a pointer to the director) 277.6 555.33 P +0.23 (y object from) 482.3 555.33 P +(the system object.) 162 543.33 T +2.87 (The e) 162 526.33 P +2.87 (xample belo) 190.14 526.33 P +2.87 (w illustr) 246.76 526.33 P +2.87 (ates using the system object to obtain a pointer to a) 282.86 526.33 P +(cde) 162 514.33 T +(vDirector) 177.82 514.33 T +(y de) 218.12 514.33 T +(vice) 236.72 514.33 T +(.) 254.35 514.33 T +4 9 Q +(Figure 35: Attaching to the cde) 162 484 T +(vDirector) 286.8 484 T +(y de) 323.07 484 T +(vice) 339.81 484 T +2 10 Q +(Messa) 54 159.21 T +(g) 84.47 159.21 T +(es) 90.68 159.21 T +(Suppor) 54 147.21 T +(ted b) 89.2 147.21 T +(y) 112.89 147.21 T +(cde) 54 135.21 T +(vDirector) 71.08 135.21 T +(y) 115.08 135.21 T +0 F +3.21 (An application comm) 162 159.21 P +3.21 (unicates with the cde) 261.14 159.21 P +3.21 (vDirector) 363.86 159.21 P +3.21 (y de) 404.16 159.21 P +3.21 (vice through the use of) 425.97 159.21 P +5.34 (prede\336ned message str) 162 147.21 P +5.34 (ings) 277.33 147.21 P +5.34 (. The f) 295.52 147.21 P +5.34 (ollo) 334.26 147.21 P +5.34 (wing messages are suppor) 349.67 147.21 P +5.34 (ted b) 485.59 147.21 P +5.34 (y the) 512.97 147.21 P +(cde) 162 135.21 T +(vDirector) 177.82 135.21 T +(y de) 218.12 135.21 T +(vice) 236.72 135.21 T +(.) 254.35 135.21 T +4 F +(1.) 162 118.21 T +3 F +(quer) 180 118.21 T +(y:) 201.77 118.21 T +0 F +(Identify the) 269.14 118.21 T +4 F +(de) 320.84 118.21 T +(vices) 331.66 118.21 T +0 F +( that are members of a DDL) 354.44 118.21 T +4 F +(class) 480.6 118.21 T +0 F +(.) 503.23 118.21 T +(2.) 162 94.21 T +3 F +(quer) 180 94.21 T +(yClass:) 201.77 94.21 T +0 F +(Identify the DDL) 269.14 94.21 T +4 F +(class) 343.62 94.21 T +0 F +( from which a) 366.4 94.21 T +4 F +(de) 428.64 94.21 T +(vice) 439.46 94.21 T +0 F +(is instantiated.) 460.02 94.21 T +162 184.88 540 615 C +162 201.88 540 481 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.29 206 541.86 469.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.32 212.45 536.27 475 R +7 X +V +0 X +N +167.57 217.17 528.85 471.33 R +7 X +V +5 9 Q +0 X +(// ***************************************************************) 167.57 465.33 T +(// * Include required CDEV header files) 167.57 454.33 T +(// ***************************************************************) 167.57 443.33 T +(#include ) 167.57 432.33 T +(#include ) 167.57 421.33 T +(void main\050\051) 167.57 399.33 T +({) 185.57 388.33 T +(// ***********************************************************) 185.57 377.33 T +(// * Obtain a reference to the default cdevSystem object) 185.57 366.33 T +(// ***********************************************************) 185.57 355.33 T +(cdevSystem & system = cdevSystem::defaultSystem\050\051;) 185.57 344.33 T +(// ***********************************************************) 185.57 322.33 T +(// * Obtain a pointer to the \322cdevDirectory\323 device using the) 185.57 311.33 T +(// * getDevice member function of the default cdevSystem) 185.57 300.33 T +(// * object.) 185.57 289.33 T +(// ***********************************************************) 185.57 278.33 T +(cdevDevice * directory = system.getDevice\050\322cdevDirectory\323\051;) 185.57 267.33 T +(.) 185.57 256.33 T +(.) 185.57 245.33 T +(.) 185.57 234.33 T +(}) 185.57 223.33 T +162 184.88 540 615 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "56" 64 +%%Page: "57" 65 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. Using the cde) 422.73 739 T +(vDirector) 487.49 739 T +(y De) 523.76 739 T +(vice) 542 739 T +0 10 Q +(57) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 180 713.33 T +3 F +(quer) 198 713.33 T +(yAttrib) 219.77 713.33 T +(utes:) 251.79 713.33 T +0 F +(Identify all) 287.14 713.33 T +4 F +(attr) 334.94 713.33 T +(ib) 349.54 713.33 T +(utes) 357.12 713.33 T +0 F +( suppor) 376.02 713.33 T +(ted b) 409.77 713.33 T +(y a) 431.81 713.33 T +4 F +(de) 447.93 713.33 T +(vice) 458.75 713.33 T +0 F +( or a DDL) 476.53 713.33 T +4 F +(class) 522.1 713.33 T +(.) 544.73 713.33 T +0 F +(4.) 180 689.33 T +3 F +(quer) 198 689.33 T +(yMessa) 219.77 689.33 T +(g) 255.8 689.33 T +(es:) 262.01 689.33 T +0 F +(Identify all) 287.14 689.33 T +4 F +(messages) 334.94 689.33 T +0 F +( suppor) 380.51 689.33 T +(ted b) 414.26 689.33 T +(y a) 436.3 689.33 T +4 F +(de) 452.42 689.33 T +(vice) 463.24 689.33 T +0 F +( or DDL) 481.02 689.33 T +4 F +(class) 518.25 689.33 T +(.) 540.88 689.33 T +0 F +(5.) 180 665.33 T +3 F +(quer) 198 665.33 T +(yV) 219.77 665.33 T +(erbs:) 231.5 665.33 T +0 F +(Identify all) 287.14 665.33 T +4 F +(v) 334.94 665.33 T +(erbs) 339.69 665.33 T +0 F +( suppor) 359.14 665.33 T +(ted b) 392.89 665.33 T +(y a) 414.93 665.33 T +4 F +(de) 431.05 665.33 T +(vice) 441.87 665.33 T +0 F +( or DDL) 459.65 665.33 T +4 F +(class) 496.88 665.33 T +(.) 519.51 665.33 T +0 F +(6.) 180 641.33 T +3 F +(ser) 198 641.33 T +(vice:) 213.11 641.33 T +0 F +(Identify the) 287.14 641.33 T +4 F +(ser) 338.84 641.33 T +(vice) 353.03 641.33 T +0 F +( that is used b) 370.81 641.33 T +(y a) 432.87 641.33 T +4 F +(de) 448.99 641.33 T +(vice/message) 459.81 641.33 T +0 F +( pair) 520.94 641.33 T +(.) 539.89 641.33 T +(7.) 180 617.33 T +3 F +(ser) 198 617.33 T +(viceData:) 213.11 617.33 T +0 F +(Identify) 287.14 617.33 T +4 F +(ser) 322.16 617.33 T +(vice) 336.35 617.33 T +0 F +( data speci\336ed f) 354.13 617.33 T +(or a) 423.87 617.33 T +4 F +(de) 443.88 617.33 T +(vice/message) 454.7 617.33 T +0 F +( pair) 515.83 617.33 T +(.) 534.78 617.33 T +(8.) 180 593.33 T +3 F +(update:) 198 593.33 T +0 F +(Add inf) 287.14 593.33 T +(or) 317.97 593.33 T +(mation to the) 327.11 593.33 T +4 F +(cde) 387.7 593.33 T +(vDirector) 403.52 593.33 T +(y) 443.82 593.33 T +0 F +( data str) 448.82 593.33 T +(ucture) 485.1 593.33 T +(.) 512.74 593.33 T +(9.) 180 569.33 T +3 F +(v) 198 569.33 T +(alidate:) 203.36 569.33 T +0 F +(V) 287.14 569.33 T +(er) 293.01 569.33 T +(ify that a) 302.05 569.33 T +4 F +(de) 342.63 569.33 T +(vice) 353.45 569.33 T +0 F +( or DDL) 371.23 569.33 T +4 F +(class) 408.46 569.33 T +0 F +( contains cer) 431.24 569.33 T +(tain proper) 488.33 569.33 T +(ties) 536.53 569.33 T +(.) 551.94 569.33 T +2 F +(\322quer) 72 540.33 T +(y\323) 98.77 540.33 T +0 F +0.3 (The \322quer) 180 540.33 P +0.3 (y\323 message is submitted to the cde) 223.95 540.33 P +0.3 (vDirector) 379.97 540.33 P +0.3 (y object in order to obtain a list) 420.27 540.33 P +0.12 (of matching) 180 528.33 P +4 F +0.12 (de) 234.72 528.33 P +0.12 (vices) 245.54 528.33 P +0 F +0.12 ( that are instantiated from a speci\336ed DDL) 268.32 528.33 P +4 F +0.12 (class) 458.85 528.33 P +0 F +0.12 (. The class name) 481.48 528.33 P +1.35 (is speci\336ed as an absolute str) 180 516.33 P +1.35 (ing. The de) 318.05 516.33 P +1.35 (vice name ma) 370.47 516.33 P +1.35 (y be speci\336ed either as an) 435.1 516.33 P +(absolute str) 180 504.33 T +(ing or as a) 231.84 504.33 T +4 F +(regular e) 281.31 504.33 T +(xpression) 320.47 504.33 T +0 F +(.) 363.26 504.33 T +0.3 (The request is submitted to the cde) 180 487.33 P +0.3 (vDirector) 337.71 487.33 P +0.3 (y de) 378.01 487.33 P +0.3 (vice through its) 396.92 487.33 P +4 F +0.3 (send) 467.86 487.33 P +0 F +0.3 (,) 489.54 487.33 P +4 F +0.3 (sendCallbac) 495.4 487.33 P +0.3 (k) 550.22 487.33 P +0 F +0.3 (,) 555.22 487.33 P +0.08 (or) 180 475.33 P +4 F +0.08 (sendNoBloc) 191.75 475.33 P +0.08 (k) 245.46 475.33 P +0 F +0.08 ( interf) 250.46 475.33 P +0.08 (ace) 275.25 475.33 P +0.08 (. The f) 291.22 475.33 P +0.08 (ollo) 319.43 475.33 P +0.08 (wing tab) 334.84 475.33 P +0.08 (le sho) 371.96 475.33 P +0.08 (ws the inputs that m) 398.57 475.33 P +0.08 (ust be placed in) 487.72 475.33 P +0.99 (the inbound cde) 180 463.33 P +0.99 (vData object pr) 252.83 463.33 P +0.99 (ior to submitting the command, and the outputs that) 322.21 463.33 P +(can be retr) 180 451.33 T +(ie) 227.95 451.33 T +(v) 235.43 451.33 T +(ed when the command is completed.) 240.18 451.33 T +4 9 Q +(Figure 36: cde) 180 418 T +(vData Input/Output associated with a \322quer) 239.76 418 T +(y\323 message) 410.62 418 T +0 10 Q +1.35 (The f) 180 284.33 P +1.35 (ollo) 203.84 284.33 P +1.35 (wing \336gure sho) 219.25 284.33 P +1.35 (ws the source code necessar) 289.06 284.33 P +1.35 (y to request the names of all) 424.27 284.33 P +4 F +(de) 180 272.33 T +(vices) 190.82 272.33 T +0 F +( that are members of the DDL) 213.6 272.33 T +4 F +(class) 348.1 272.33 T +0 F +( \322magnet\323.) 370.88 272.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(T) 180.4 390.33 T +(ag Name) 185.31 390.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data T) 264.32 390.33 T +(ype) 293.13 390.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Content) 427.42 390.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Message Input) 77.43 370.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(de) 168.57 370.33 T +(vice) 180.09 370.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 245.71 370.33 T +(acter str) 265.07 370.33 T +(ing) 301.33 370.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Regular e) 335.86 370.33 T +(xpression identifying the de) 378.91 370.33 T +(vice names) 499.78 370.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(that should be retr) 335.86 358.33 T +(ie) 416.61 358.33 T +(v) 424.09 358.33 T +(ed.) 428.84 358.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(c) 168.57 340.33 T +(lass) 173.93 340.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 245.71 340.33 T +(acter str) 265.07 340.33 T +(ing) 301.33 340.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the DDL class that the de) 335.86 340.33 T +(vices should) 488.41 340.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(be instantiated from.) 335.86 328.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Message Output) 77.43 310.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(v) 168.57 310.33 T +(alue) 173.93 310.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(arr) 245.71 310.33 T +(a) 257.83 310.33 T +(y of str) 263.1 310.33 T +(ings) 293.26 310.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Names of matching de) 335.86 310.33 T +(vices) 435.6 310.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +73.43 402 73.43 304 2 L +V +2 H +0 Z +N +164.57 404 164.57 302 2 L +V +0.5 H +N +241.71 404 241.71 302 2 L +V +N +331.86 404 331.86 302 2 L +V +N +558 402 558 304 2 L +V +2 H +N +72.43 403 559 403 2 L +V +N +74.43 382.25 557 382.25 2 L +V +0.5 H +N +74.43 379.75 557 379.75 2 L +V +N +72.43 351 559 351 2 L +V +N +74.43 322.25 557 322.25 2 L +V +N +74.43 319.75 557 319.75 2 L +V +N +72.43 303 559 303 2 L +V +2 H +N +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "57" 65 +%%Page: "58" 66 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. Using the cde) 54 739 T +(vDirector) 118.76 739 T +(y De) 155.03 739 T +(vice) 173.27 739 T +0 10 Q +(58) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Figure 37: Using the \322quer) 162 714 T +(y\323 Message with a cde) 269.32 714 T +(vDirector) 358.58 714 T +(y de) 394.85 714 T +(vice) 411.59 714 T +2 10 Q +(\322quer) 54 271.32 T +(yClass\323) 80.77 271.32 T +0 F +-0.16 (The \322quer) 162 271.32 P +-0.16 (yClass\323 message is submitted to the cde) 205.49 271.32 P +-0.16 (vDirector) 383.76 271.32 P +-0.16 (y object in order to identify) 424.06 271.32 P +(the name of the DDL) 162 259.32 T +4 F +(class) 257.05 259.32 T +0 F +( that a) 279.83 259.32 T +4 F +(de) 310.41 259.32 T +(vice) 321.23 259.32 T +0 F +( is instantiated from.) 339.01 259.32 T +(The request is submitted to the cde) 162 242.32 T +(vDirector) 317.89 242.32 T +(y de) 358.19 242.32 T +(vice through its send, sendCallbac) 376.79 242.32 T +(k,) 528.88 242.32 T +(or sendNoBloc) 162 230.32 T +(k interf) 227.38 230.32 T +(ace) 257.09 230.32 T +(. The f) 273.06 230.32 T +(ollo) 301.11 230.32 T +(wing tab) 316.52 230.32 T +(le sho) 353.56 230.32 T +(ws the inputs that m) 380.09 230.32 T +(ust be placed in) 468.92 230.32 T +(the inbound cde) 162 218.32 T +(vData object pr) 232.86 218.32 T +(ior to submitting the command, and the outputs that) 300.26 218.32 T +(can be retr) 162 206.32 T +(ie) 209.95 206.32 T +(v) 217.43 206.32 T +(ed when the command is completed.) 222.18 206.32 T +4 9 Q +(Figure 38: cde) 162 172.99 T +(vData input/output associated with a \322quer) 221.76 172.99 T +(yClass\323 message) 390.11 172.99 T +162 296.99 540 720 C +0 0 0 1 0 0 0 K +162 296.99 540 711 C +0 0 0 1 0 0 0 K +170.21 302.38 536.29 705.24 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +165.08 307.29 532.37 709.83 R +7 X +V +0 X +N +170.24 310.67 525.08 704.21 R +7 X +V +5 9 Q +0 X +(#include ) 170.24 698.21 T +(#include ) 170.24 687.21 T +(#include ) 170.24 676.21 T +(void main\050\051) 170.24 654.21 T +({) 188.24 643.21 T +(// ***********************************************************) 188.24 632.21 T +(// * Use the shorthand method to obtain a pointer to the) 188.24 621.21 T +(// * cdevDirectory device within the default system.) 188.24 610.21 T +(// ***********************************************************) 188.24 599.21 T +(cdevDevice *dir = cdevDevice::attachPtr\050\322cdevDirectory\323\051;) 188.24 588.21 T +(cdevData input, output;) 188.24 577.21 T +(// ***********************************************************) 188.24 555.21 T +(// * Insert the name of the DDL class and the regular) 188.24 544.21 T +(// * expression for the device.) 188.24 533.21 T +(// ***********************************************************) 188.24 522.21 T +(input.insert\050\322class\323, \322magnet\323\051;) 188.24 511.21 T +(input.insert\050\322device\323, \322.*\323\051;) 188.24 500.21 T +(// ***********************************************************) 188.24 478.21 T +(// * Submit the request to the cdevDirectory object using the) 188.24 467.21 T +(// * send command.) 188.24 456.21 T +(// ***********************************************************) 188.24 445.21 T +(if\050dir->send\050\322query\323, input, output\051==CDEV_SUCCESS\051) 188.24 434.21 T +({) 206.24 423.21 T +(// ********************************************************) 206.24 412.21 T +(// * If the command was successful, obtain a pointer to the) 206.24 401.21 T +(// * list of names and output them on stdout.) 206.24 390.21 T +(// ********************************************************) 206.24 379.21 T +(char ** ptr;) 206.24 368.21 T +(output.find\050\322value\323, ptr\051;) 206.24 357.21 T +(while\050*ptr!=NULL\051 fprintf\050stdout, \322%s\134n\323, ptr++\051;) 206.24 346.21 T +(}) 206.24 335.21 T +(}) 188.24 324.21 T +0 0 0 1 0 0 0 K +162 296.99 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 10 Q +0 X +0 0 0 1 0 0 0 K +(T) 162.4 145.32 T +(ag Name) 167.31 145.32 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data T) 246.32 145.32 T +(ype) 275.13 145.32 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Content) 409.42 145.32 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Message Input) 59.43 125.32 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(de) 150.57 125.32 T +(vice) 162.09 125.32 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 227.71 125.32 T +(acter str) 247.07 125.32 T +(ing) 283.33 125.32 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the de) 317.86 125.32 T +(vice to be quer) 385.93 125.32 T +(ied.) 451.67 125.32 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Message Output) 59.43 107.32 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(v) 150.57 107.32 T +(alue) 155.93 107.32 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 227.71 107.32 T +(acter str) 247.07 107.32 T +(ing) 283.33 107.32 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Names of the associated class) 317.86 107.32 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +55.43 156.99 55.43 100.99 2 L +V +2 H +0 Z +N +146.57 158.99 146.57 98.99 2 L +V +0.5 H +N +223.71 158.99 223.71 98.99 2 L +V +N +313.86 158.99 313.86 98.99 2 L +V +N +540 156.99 540 100.99 2 L +V +2 H +N +54.43 157.99 541 157.99 2 L +V +N +56.43 137.24 539 137.24 2 L +V +0.5 H +N +56.43 134.74 539 134.74 2 L +V +N +56.43 119.24 539 119.24 2 L +V +N +56.43 116.74 539 116.74 2 L +V +N +54.43 99.99 541 99.99 2 L +V +2 H +N +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "58" 66 +%%Page: "59" 67 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. Using the cde) 422.73 739 T +(vDirector) 487.49 739 T +(y De) 523.76 739 T +(vice) 542 739 T +0 10 Q +(59) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.56 (The f) 180 713.33 P +0.56 (ollo) 203.05 713.33 P +0.56 (wing \336gure sho) 218.46 713.33 P +0.56 (ws the source code necessar) 286.69 713.33 P +0.56 (y to deter) 418.74 713.33 P +0.56 (mine the name of the) 461.81 713.33 P +(DDL class from which the de) 180 701.33 T +(vice \322MQB1S01\323 is der) 306.96 701.33 T +(iv) 407.69 701.33 T +(ed.) 414.66 701.33 T +4 9 Q +(Figure 39: Using the \322quer) 180 668 T +(yClass\323 message with a cde) 287.32 668 T +(vDirector) 399.08 668 T +(y de) 435.35 668 T +(vice) 452.09 668 T +2 10 Q +(\322quer) 72 321.1 T +(yAttrib) 98.77 321.1 T +(utes\323) 130.79 321.1 T +0 F +1.4 (The \322quer) 180 321.1 P +1.4 (yAttr) 225.05 321.1 P +1.4 (ib) 245.76 321.1 P +1.4 (utes\323 message is submitted to the cde) 253.34 321.1 P +1.4 (vDirector) 429.84 321.1 P +1.4 (y object in order to) 470.14 321.1 P +(obtain a list of all) 180 309.1 T +4 F +(attr) 257.26 309.1 T +(ib) 271.86 309.1 T +(utes) 279.44 309.1 T +0 F +( that are contained within a speci\336ed) 298.34 309.1 T +4 F +(de) 462.87 309.1 T +(vice) 473.69 309.1 T +0 F +( or DDL) 491.47 309.1 T +4 F +(class) 528.7 309.1 T +0 F +(.) 551.33 309.1 T +0.3 (The request is submitted to the cde) 180 292.1 P +0.3 (vDirector) 337.71 292.1 P +0.3 (y de) 378.01 292.1 P +0.3 (vice through its) 396.92 292.1 P +4 F +0.3 (send) 467.86 292.1 P +0 F +0.3 (,) 489.54 292.1 P +4 F +0.3 (sendCallbac) 495.4 292.1 P +0.3 (k) 550.22 292.1 P +0 F +0.3 (,) 555.22 292.1 P +0.08 (or) 180 280.1 P +4 F +0.08 (sendNoBloc) 191.75 280.1 P +0.08 (k) 245.46 280.1 P +0 F +0.08 ( interf) 250.46 280.1 P +0.08 (ace) 275.25 280.1 P +0.08 (. The f) 291.22 280.1 P +0.08 (ollo) 319.43 280.1 P +0.08 (wing tab) 334.84 280.1 P +0.08 (le sho) 371.96 280.1 P +0.08 (ws the inputs that m) 398.57 280.1 P +0.08 (ust be placed in) 487.72 280.1 P +0.99 (the inbound cde) 180 268.1 P +0.99 (vData object pr) 252.83 268.1 P +0.99 (ior to submitting the command, and the outputs that) 322.21 268.1 P +(can be retr) 180 256.1 T +(ie) 227.95 256.1 T +(v) 235.43 256.1 T +(ed when the command is completed.) 240.18 256.1 T +4 9 Q +(Figure 40: cde) 180 222.76 T +(vData input/output associated with a \322quer) 239.76 222.76 T +(yAttr) 408.11 222.76 T +(ib) 426.75 222.76 T +(utes\323 message) 433.58 222.76 T +0 10 Q +1.35 (The f) 180 113.1 P +1.35 (ollo) 203.84 113.1 P +1.35 (wing \336gure sho) 219.25 113.1 P +1.35 (ws the source code necessar) 289.06 113.1 P +1.35 (y to request the names of all) 424.27 113.1 P +4 F +(attr) 180 101.1 T +(ib) 194.6 101.1 T +(utes) 202.18 101.1 T +0 F +( that are de\336ned within the DDL) 221.08 101.1 T +4 F +(class) 363.93 101.1 T +0 F +( \322magnet\323.) 386.71 101.1 T +180 346.76 558 720 C +180.25 346.76 557.75 665 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +185.21 354.88 553.79 660.24 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +183.42 358 551.54 663.17 R +7 X +V +0 X +N +188.59 360.57 544.21 658.9 R +7 X +V +5 9 Q +0 X +(#include ) 188.59 652.9 T +(#include ) 188.59 641.9 T +(#include ) 188.59 630.9 T +(void main\050\051) 188.59 608.9 T +({) 206.59 597.9 T +(cdevDevice *dir = cdevDevice::attachPtr\050\322cdevDirectory\323\051;) 206.59 586.9 T +(cdevData input, output;) 206.59 575.9 T +(// ***********************************************************) 206.59 553.9 T +(// * Insert the name of the DDL class.) 206.59 542.9 T +(// ***********************************************************) 206.59 531.9 T +(input.insert\050\322device\323, \322MQB1S01\323\051;) 206.59 520.9 T +(// ***********************************************************) 206.59 498.9 T +(// * Submit the request to the cdevDirectory object.) 206.59 487.9 T +(// ***********************************************************) 206.59 476.9 T +(if\050dir->send\050\322queryClass\323, input, output\051==CDEV_SUCCESS\051) 206.59 465.9 T +({) 224.59 454.9 T +(// *******************************************************) 224.59 443.9 T +(// * If successful, output the name of the DDL class.) 224.59 432.9 T +(// *******************************************************) 224.59 421.9 T +(char * ptr;) 224.59 410.9 T +(output.find\050\322value\323, ptr\051;) 224.59 399.9 T +(fprintf\050stdout, \322MQB1S01 is a %s\134n\323, value\051;) 224.59 388.9 T +(}) 224.59 377.9 T +(}) 206.59 366.9 T +180 346.76 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 10 Q +0 X +0 0 0 1 0 0 0 K +(T) 180.4 195.1 T +(ag Name) 185.31 195.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data T) 264.32 195.1 T +(ype) 293.13 195.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Content) 427.42 195.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Message Input) 77.43 175.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(de) 168.57 175.1 T +(vice) 180.09 175.1 T +0 F +(or) 202.33 175.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(char) 245.71 175.1 T +(acter str) 265.07 175.1 T +(ing) 301.33 175.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the de) 335.86 175.1 T +(vice to be quer) 403.93 175.1 T +(ied.) 469.67 175.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(c) 168.57 157.1 T +(lass) 173.93 157.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 245.71 157.1 T +(acter str) 265.07 157.1 T +(ing) 301.33 157.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the DDL class to be quer) 335.86 157.1 T +(ied.) 486.63 157.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Message Output) 77.43 139.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(v) 168.57 139.1 T +(alue) 173.93 139.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(arr) 245.71 139.1 T +(a) 257.83 139.1 T +(y of str) 263.1 139.1 T +(ings) 293.26 139.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Names of matching attr) 335.86 139.1 T +(ib) 439.38 139.1 T +(utes) 446.96 139.1 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +73.43 206.76 73.43 132.76 2 L +V +2 H +0 Z +N +164.57 208.76 164.57 130.76 2 L +V +0.5 H +N +241.71 208.76 241.71 130.76 2 L +V +N +331.86 208.76 331.86 130.76 2 L +V +N +558 206.76 558 132.76 2 L +V +2 H +N +72.43 207.76 559 207.76 2 L +V +N +74.43 187.01 557 187.01 2 L +V +0.5 H +N +74.43 184.51 557 184.51 2 L +V +N +72.43 167.76 559 167.76 2 L +V +N +74.43 151.01 557 151.01 2 L +V +N +74.43 148.51 557 148.51 2 L +V +N +72.43 131.76 559 131.76 2 L +V +2 H +N +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "59" 67 +%%Page: "60" 68 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. Using the cde) 54 739 T +(vDirector) 118.76 739 T +(y De) 155.03 739 T +(vice) 173.27 739 T +0 10 Q +(60) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Figure 41: Using the \322quer) 162 697 T +(yAttr) 269.32 697 T +(ib) 287.95 697 T +(utes\323 message with a cde) 294.78 697 T +(vDirector) 396.55 697 T +(y de) 432.82 697 T +(vice) 449.56 697 T +2 10 Q +(\322quer) 54 302.67 T +(yMessa) 80.77 302.67 T +(g) 116.8 302.67 T +(es\323) 123.01 302.67 T +0 F +1.09 (The \322quer) 162 302.67 P +1.09 (yMessages\323 message is submitted to the cde) 206.74 302.67 P +1.09 (vDirector) 413.07 302.67 P +1.09 (y object in order to) 453.37 302.67 P +-0.04 (obtain a list of all) 162 290.67 P +4 F +-0.04 (messages) 239.06 290.67 P +0 F +-0.04 ( that are contained within a speci\336ed) 284.63 290.67 P +4 F +-0.04 (de) 448.88 290.67 P +-0.04 (vice) 459.7 290.67 P +0 F +-0.04 ( or DDL) 477.48 290.67 P +4 F +-0.04 (class) 514.59 290.67 P +0 F +-0.04 (.) 537.22 290.67 P +0.3 (The request is submitted to the cde) 162 273.67 P +0.3 (vDirector) 319.71 273.67 P +0.3 (y de) 360.01 273.67 P +0.3 (vice through its) 378.92 273.67 P +4 F +0.3 (send) 449.86 273.67 P +0 F +0.3 (,) 471.54 273.67 P +4 F +0.3 (sendCallbac) 477.4 273.67 P +0.3 (k) 532.22 273.67 P +0 F +0.3 (,) 537.22 273.67 P +0.08 (or) 162 261.67 P +4 F +0.08 (sendNoBloc) 173.75 261.67 P +0.08 (k) 227.46 261.67 P +0 F +0.08 ( interf) 232.46 261.67 P +0.08 (ace) 257.25 261.67 P +0.08 (. The f) 273.22 261.67 P +0.08 (ollo) 301.43 261.67 P +0.08 (wing tab) 316.84 261.67 P +0.08 (le sho) 353.96 261.67 P +0.08 (ws the inputs that m) 380.57 261.67 P +0.08 (ust be placed in) 469.72 261.67 P +0.99 (the inbound cde) 162 249.67 P +0.99 (vData object pr) 234.83 249.67 P +0.99 (ior to submitting the command, and the outputs that) 304.21 249.67 P +(can be retr) 162 237.67 T +(ie) 209.95 237.67 T +(v) 217.43 237.67 T +(ed when the command is completed.) 222.18 237.67 T +4 9 Q +(Figure 42: cde) 162 204.33 T +(vData input/output associated with a \322quer) 221.76 204.33 T +(yMessages\323 message) 390.11 204.33 T +162 328.33 540 720 C +162 328.33 540 694 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.88 355.78 542.45 682.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.92 359.98 536.87 688 R +7 X +V +0 X +N +168.17 362.73 529.45 683.41 R +7 X +V +5 9 Q +0 X +(#include ) 168.17 677.41 T +(#include ) 168.17 666.41 T +(#include ) 168.17 655.41 T +(void main\050\051) 168.17 633.41 T +({) 186.17 622.41 T +(cdevDevice *dir = cdevDevice::attachPtr\050\322cdevDirectory\323\051;) 186.17 611.41 T +(cdevData input, output;) 186.17 600.41 T +(// ***********************************************************) 186.17 578.41 T +(// * Insert the name of the DDL class.) 186.17 567.41 T +(// ***********************************************************) 186.17 556.41 T +(input.insert\050\322class\323, \322magnet\323\051;) 186.17 545.41 T +(// ***********************************************************) 186.17 523.42 T +(// * Submit the request to the cdevDirectory object using the) 186.17 512.42 T +(// * send command.) 186.17 501.42 T +(// ***********************************************************) 186.17 490.42 T +(if\050dir->send\050\322queryAttributes\323, input, output\051==CDEV_SUCCESS\051) 186.17 479.42 T +({) 204.17 468.42 T +(// *******************************************************) 204.17 457.42 T +(// * If the command was successful, obtain a pointer to) 204.17 446.42 T +(// * the list of attributes and output them on stdout.) 204.17 435.42 T +(// *******************************************************) 204.17 424.42 T +(char ** ptr;) 204.17 413.42 T +(output.find\050\322value\323, ptr\051;) 204.17 402.42 T +(while\050*ptr!=NULL\051 fprintf\050stdout, \322%s\134n\323, ptr++\051;) 204.17 391.42 T +(}) 204.17 380.42 T +(}) 186.17 369.42 T +162 328.33 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 10 Q +0 X +0 0 0 1 0 0 0 K +(T) 162.4 176.67 T +(ag Name) 167.31 176.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data T) 246.32 176.67 T +(ype) 275.13 176.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Content) 409.42 176.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Message Input) 59.43 156.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(de) 150.57 156.67 T +(vice) 162.09 156.67 T +0 F +(or) 184.33 156.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(char) 227.71 156.67 T +(acter str) 247.07 156.67 T +(ing) 283.33 156.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the de) 317.86 156.67 T +(vice to be quer) 385.93 156.67 T +(ied.) 451.67 156.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(c) 150.57 138.67 T +(lass) 155.93 138.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 227.71 138.67 T +(acter str) 247.07 138.67 T +(ing) 283.33 138.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the DDL class to be quer) 317.86 138.67 T +(ied.) 468.63 138.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Message Output) 59.43 120.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(v) 150.57 120.67 T +(alue) 155.93 120.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(arr) 227.71 120.67 T +(a) 239.84 120.67 T +(y of str) 245.1 120.67 T +(ings) 275.26 120.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Names of matching messages) 317.86 120.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +55.43 188.33 55.43 114.33 2 L +V +2 H +0 Z +N +146.57 190.33 146.57 112.33 2 L +V +0.5 H +N +223.71 190.33 223.71 112.33 2 L +V +N +313.86 190.33 313.86 112.33 2 L +V +N +540 188.33 540 114.33 2 L +V +2 H +N +54.43 189.33 541 189.33 2 L +V +N +56.43 168.58 539 168.58 2 L +V +0.5 H +N +56.43 166.08 539 166.08 2 L +V +N +54.43 149.33 541 149.33 2 L +V +N +56.43 132.58 539 132.58 2 L +V +N +56.43 130.08 539 130.08 2 L +V +N +54.43 113.33 541 113.33 2 L +V +2 H +N +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "60" 68 +%%Page: "61" 69 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. Using the cde) 422.73 739 T +(vDirector) 487.49 739 T +(y De) 523.76 739 T +(vice) 542 739 T +0 10 Q +(61) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.35 (The f) 180 713.33 P +1.35 (ollo) 203.84 713.33 P +1.35 (wing \336gure sho) 219.25 713.33 P +1.35 (ws the source code necessar) 289.06 713.33 P +1.35 (y to request the names of all) 424.27 713.33 P +4 F +(messages) 180 701.33 T +0 F +( that are de\336ned within the DDL) 225.57 701.33 T +4 F +(class) 368.42 701.33 T +0 F +(\322magnet\323.) 393.98 701.33 T +4 9 Q +(Figure 43: Using the \322quer) 180 668 T +(yMessages\323 message with a cde) 287.32 668 T +(vDirector) 417.59 668 T +(y de) 453.86 668 T +(vice) 470.6 668 T +2 10 Q +(\322quer) 72 341.21 T +(yV) 98.77 341.21 T +(erbs\323) 110.5 341.21 T +0 F +0.19 (The \322quer) 180 341.21 P +0.19 (yV) 223.84 341.21 P +0.19 (erbs\323 message is submitted to the cde) 234.71 341.21 P +0.19 (vDirector) 404.49 341.21 P +0.19 (y object in order to obtain) 444.79 341.21 P +(a list of all) 180 329.21 T +4 F +(v) 227.24 329.21 T +(erbs) 231.99 329.21 T +0 F +( that are contained within a speci\336ed) 251.44 329.21 T +4 F +(de) 415.97 329.21 T +(vice) 426.79 329.21 T +0 F +( or DDL) 444.57 329.21 T +4 F +(class) 481.8 329.21 T +0 F +(.) 504.43 329.21 T +0.3 (The request is submitted to the cde) 180 312.21 P +0.3 (vDirector) 337.71 312.21 P +0.3 (y de) 378.01 312.21 P +0.3 (vice through its) 396.92 312.21 P +4 F +0.3 (send) 467.86 312.21 P +0 F +0.3 (,) 489.54 312.21 P +4 F +0.3 (sendCallbac) 495.4 312.21 P +0.3 (k) 550.22 312.21 P +0 F +0.3 (,) 555.22 312.21 P +0.08 (or) 180 300.21 P +4 F +0.08 (sendNoBloc) 191.75 300.21 P +0.08 (k) 245.46 300.21 P +0 F +0.08 ( interf) 250.46 300.21 P +0.08 (ace) 275.25 300.21 P +0.08 (. The f) 291.22 300.21 P +0.08 (ollo) 319.43 300.21 P +0.08 (wing tab) 334.84 300.21 P +0.08 (le sho) 371.96 300.21 P +0.08 (ws the inputs that m) 398.57 300.21 P +0.08 (ust be placed in) 487.72 300.21 P +0.99 (the inbound cde) 180 288.21 P +0.99 (vData object pr) 252.83 288.21 P +0.99 (ior to submitting the command, and the outputs that) 322.21 288.21 P +(can be retr) 180 276.22 T +(ie) 227.95 276.22 T +(v) 235.43 276.22 T +(ed when the command is completed.) 240.18 276.22 T +4 9 Q +(Figure 44: cde) 180 242.88 T +(vData input/output associated with a \322quer) 239.76 242.88 T +(yV) 408.11 242.88 T +(erbs\323 message) 417.9 242.88 T +0 10 Q +1.35 (The f) 180 133.22 P +1.35 (ollo) 203.84 133.22 P +1.35 (wing \336gure sho) 219.25 133.22 P +1.35 (ws the source code necessar) 289.06 133.22 P +1.35 (y to request the names of all) 424.27 133.22 P +4 F +(v) 180 121.22 T +(erbs) 184.75 121.22 T +0 F +( that are de\336ned within the DDL) 204.2 121.22 T +4 F +(class) 347.05 121.22 T +0 F +(\322magnet\323.) 372.61 121.22 T +180 366.88 558 720 C +180 366.88 558 665 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.46 373.33 560.04 653.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +180.5 378 554.45 659 R +7 X +V +0 X +N +185.75 380.36 547.03 655.07 R +7 X +V +5 9 Q +0 X +(#include ) 185.75 649.07 T +(#include ) 185.75 638.07 T +(#include ) 185.75 627.07 T +(void main\050\051) 185.75 605.07 T +({) 203.75 594.07 T +(cdevDevice *dir = cdevDevice::attachPtr\050\322cdevDirectory\323\051;) 203.75 583.07 T +(cdevData input, output;) 203.75 572.07 T +(// ***********************************************************) 203.75 550.07 T +(// * Insert the name of the DDL class.) 203.75 539.07 T +(// ***********************************************************) 203.75 528.07 T +(input.insert\050\322class\323, \322magnet\323\051;) 203.75 517.07 T +(// ***********************************************************) 203.75 495.07 T +(// * Submit the request to the cdevDirectory object using the) 203.75 484.07 T +(// * send command, and output the result if successful.) 203.75 473.07 T +(// ***********************************************************) 203.75 462.07 T +(if\050dir->send\050\322queryMessages\323, input, output\051==CDEV_SUCCESS\051) 203.75 451.07 T +({) 221.75 440.07 T +(char ** ptr;) 221.75 429.07 T +(output.find\050\322value\323, ptr\051;) 221.75 418.07 T +(while\050*ptr!=NULL\051 fprintf\050stdout, \322%s\134n\323, ptr++\051;) 221.75 407.07 T +(}) 221.75 396.07 T +(}) 203.75 385.07 T +180 366.88 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 10 Q +0 X +0 0 0 1 0 0 0 K +(T) 180.4 215.22 T +(ag Name) 185.31 215.22 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data T) 264.32 215.22 T +(ype) 293.13 215.22 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Content) 427.42 215.22 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Message Input) 77.43 195.22 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(de) 168.57 195.22 T +(vice) 180.09 195.22 T +0 F +(or) 202.33 195.22 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(char) 245.71 195.22 T +(acter str) 265.07 195.22 T +(ing) 301.33 195.22 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the de) 335.86 195.22 T +(vice to be quer) 403.93 195.22 T +(ied.) 469.67 195.22 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(c) 168.57 177.22 T +(lass) 173.93 177.22 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 245.71 177.22 T +(acter str) 265.07 177.22 T +(ing) 301.33 177.22 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the DDL class to be quer) 335.86 177.22 T +(ied.) 486.63 177.22 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Message Output) 77.43 159.22 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(v) 168.57 159.22 T +(alue) 173.93 159.22 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 245.71 159.22 T +(acter str) 265.07 159.22 T +(ings) 301.33 159.22 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Names of matching v) 335.86 159.22 T +(erbs) 429.53 159.22 T +(.) 448.83 159.22 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +73.43 226.88 73.43 152.88 2 L +V +2 H +0 Z +N +164.57 228.88 164.57 150.88 2 L +V +0.5 H +N +241.71 228.88 241.71 150.88 2 L +V +N +331.86 228.88 331.86 150.88 2 L +V +N +558 226.88 558 152.88 2 L +V +2 H +N +72.43 227.88 559 227.88 2 L +V +N +74.43 207.13 557 207.13 2 L +V +0.5 H +N +74.43 204.63 557 204.63 2 L +V +N +72.43 187.88 559 187.88 2 L +V +N +74.43 171.13 557 171.13 2 L +V +N +74.43 168.63 557 168.63 2 L +V +N +72.43 151.88 559 151.88 2 L +V +2 H +N +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "61" 69 +%%Page: "62" 70 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. Using the cde) 54 739 T +(vDirector) 118.76 739 T +(y De) 155.03 739 T +(vice) 173.27 739 T +0 10 Q +(62) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Figure 45: Using the \322quer) 162 714 T +(yV) 269.32 714 T +(erbs\323 message with a cde) 279.1 714 T +(vDirector) 381.37 714 T +(y de) 417.64 714 T +(vice) 434.38 714 T +2 10 Q +(\322ser) 54 369.1 T +(vice\323) 74.11 369.1 T +0 F +1.37 (The \322ser) 162 369.1 P +1.37 (vice\323 message is submitted to the cde) 200.9 369.1 P +1.37 (vDirector) 376.12 369.1 P +1.37 (y object in order to identify) 416.42 369.1 P +0.84 (which CDEV) 162 357.1 P +4 F +0.84 (ser) 222.58 357.1 P +0.84 (vice) 236.77 357.1 P +0 F +0.84 ( will respond to a speci\336ed) 254.55 357.1 P +4 F +0.84 (de) 379.65 357.1 P +0.84 (vice) 390.47 357.1 P +0 F +0.84 ( /) 408.25 357.1 P +4 F +0.84 (message) 418.27 357.1 P +0 F +0.84 ( combination. The) 458.84 357.1 P +0.29 (caller speci\336es the) 162 345.1 P +4 F +0.29 (de) 247.91 345.1 P +0.29 (vice) 258.73 345.1 P +0 F +0.29 ( name and the) 276.51 345.1 P +4 F +0.29 (message) 344.4 345.1 P +0 F +0.29 ( str) 384.97 345.1 P +0.29 (ing in the) 399.31 345.1 P +4 F +0.29 (input) 443.55 345.1 P +0 F +0.29 ( cde) 465.23 345.1 P +0.29 (vData object) 484.12 345.1 P +-0.27 (and can retr) 162 333.1 P +-0.27 (ie) 214.97 333.1 P +-0.27 (v) 222.45 333.1 P +-0.27 (e the result from the v) 227.2 333.1 P +-0.27 (alue entr) 322.32 333.1 P +-0.27 (y in the resulting) 361.26 333.1 P +4 F +-0.27 (output) 435.78 333.1 P +0 F +-0.27 ( cde) 463.58 333.1 P +-0.27 (vData object.) 481.91 333.1 P +(This message will nor) 162 321.1 T +(mally only be used inter) 258.38 321.1 T +(nally b) 363.67 321.1 T +(y CDEV) 392.37 321.1 T +(.) 426.68 321.1 T +0.3 (The request is submitted to the cde) 162 304.1 P +0.3 (vDirector) 319.71 304.1 P +0.3 (y de) 360.01 304.1 P +0.3 (vice through its) 378.92 304.1 P +4 F +0.3 (send) 449.86 304.1 P +0 F +0.3 (,) 471.54 304.1 P +4 F +0.3 (sendCallbac) 477.4 304.1 P +0.3 (k) 532.22 304.1 P +0 F +0.3 (,) 537.22 304.1 P +0.08 (or) 162 292.1 P +4 F +0.08 (sendNoBloc) 173.75 292.1 P +0.08 (k) 227.46 292.1 P +0 F +0.08 ( interf) 232.46 292.1 P +0.08 (ace) 257.25 292.1 P +0.08 (. The f) 273.22 292.1 P +0.08 (ollo) 301.43 292.1 P +0.08 (wing tab) 316.84 292.1 P +0.08 (le sho) 353.96 292.1 P +0.08 (ws the inputs that m) 380.57 292.1 P +0.08 (ust be placed in) 469.72 292.1 P +0.99 (the inbound cde) 162 280.1 P +0.99 (vData object pr) 234.83 280.1 P +0.99 (ior to submitting the command, and the outputs that) 304.21 280.1 P +(can be retr) 162 268.09 T +(ie) 209.95 268.09 T +(v) 217.43 268.09 T +(ed when the command is completed.) 222.18 268.09 T +4 9 Q +(Figure 46: cde) 162 234.76 T +(vData input/output associated with a \322ser) 221.76 234.76 T +(vice\323 message) 384.61 234.76 T +0 10 Q +1.54 (The f) 162 113.09 P +1.54 (ollo) 186.03 113.09 P +1.54 (wing \336gure sho) 201.44 113.09 P +1.54 (ws the source code necessar) 271.63 113.09 P +1.54 (y to resolv) 407.6 113.09 P +1.54 (e the name of the) 456 113.09 P +(ser) 162 101.09 T +(vice that will respond to the de) 176.19 101.09 T +(vice \322DEV1\323 and the message \322get V) 310.4 101.09 T +(AL) 471.89 101.09 T +(\323.) 482.72 101.09 T +162 394.76 540 720 C +162 394.76 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.88 404.33 542.45 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.92 410.43 536.87 705 R +7 X +V +0 X +N +168.17 412.9 529.45 700.88 R +7 X +V +5 9 Q +0 X +(#include ) 168.17 694.88 T +(#include ) 168.17 683.88 T +(#include ) 168.17 672.88 T +(void main\050\051) 168.17 650.88 T +({) 186.17 639.88 T +(cdevDevice *dir = cdevDevice::attachPtr\050\322cdevDirectory\323\051;) 186.17 628.88 T +(cdevData input;) 186.17 617.88 T +(cdevData output;) 186.17 606.88 T +(// ***********************************************************) 186.17 584.88 T +(// * Insert the name of the DDL class.) 186.17 573.88 T +(// ***********************************************************) 186.17 562.88 T +(input.insert\050\322class\323, \322magnet\323\051;) 186.17 551.88 T +(// ***********************************************************) 186.17 529.88 T +(// * Submit the request to the cdevDirectory object using the) 186.17 518.88 T +(// * send command, and output the result if successful.) 186.17 507.88 T +(// ***********************************************************) 186.17 496.88 T +(if\050dir->send\050\322queryVerbs\323, input, output\051==CDEV_SUCCESS\051) 186.17 485.88 T +({) 204.17 474.88 T +(char ** ptr;) 204.17 463.88 T +(output.find\050\322value\323, ptr\051;) 204.17 452.88 T +(while\050*ptr!=NULL\051 fprintf\050stdout, \322%s\134n\323, ptr++\051;) 204.17 441.88 T +(}) 204.17 430.88 T +(}) 186.17 419.88 T +162 394.76 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 10 Q +0 X +0 0 0 1 0 0 0 K +(T) 162.4 207.09 T +(ag Name) 167.31 207.09 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data T) 246.32 207.09 T +(ype) 275.13 207.09 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Content) 409.42 207.09 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Message Input) 59.43 187.09 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(de) 150.57 187.09 T +(vice) 162.09 187.09 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 227.71 187.09 T +(acter str) 247.07 187.09 T +(ing) 283.33 187.09 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the CDEV de) 317.86 187.09 T +(vice) 416.49 187.09 T +(.) 434.12 187.09 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(messa) 150.57 169.09 T +(g) 181.6 169.09 T +(e) 187.81 169.09 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 227.71 169.09 T +(acter str) 247.07 169.09 T +(ing) 283.33 169.09 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the message) 317.86 169.09 T +(.) 415.53 169.09 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Message Output) 59.43 151.09 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(v) 150.57 151.09 T +(alue) 155.93 151.09 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 227.71 151.09 T +(acter str) 247.07 151.09 T +(ing) 283.33 151.09 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the ser) 317.86 151.09 T +(vice that will respond to the) 389.3 151.09 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(speci\336ed de) 317.86 139.09 T +(vice and message) 370.92 139.09 T +(.) 451.36 139.09 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +55.43 218.76 55.43 132.76 2 L +V +2 H +0 Z +N +146.57 220.76 146.57 130.76 2 L +V +0.5 H +N +223.71 220.76 223.71 130.76 2 L +V +N +313.86 220.76 313.86 130.76 2 L +V +N +540 218.76 540 132.76 2 L +V +2 H +N +54.43 219.76 541 219.76 2 L +V +N +56.43 199.01 539 199.01 2 L +V +0.5 H +N +56.43 196.51 539 196.51 2 L +V +N +54.43 179.76 541 179.76 2 L +V +N +56.43 163.01 539 163.01 2 L +V +N +56.43 160.51 539 160.51 2 L +V +N +54.43 131.76 541 131.76 2 L +V +2 H +N +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "62" 70 +%%Page: "63" 71 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. Using the cde) 422.73 739 T +(vDirector) 487.49 739 T +(y De) 523.76 739 T +(vice) 542 739 T +0 10 Q +(63) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +(Figure 47: Using the \322ser) 180 697 T +(vice\323 message with a cde) 281.81 697 T +(vDirector) 382.57 697 T +(y de) 418.84 697 T +(vice) 435.58 697 T +2 10 Q +(\322ser) 72 358.21 T +(viceData\323) 92.11 358.21 T +0 F +-0.02 (The \322ser) 180 358.21 P +-0.02 (viceData\323 message is submitted to the cde) 217.51 358.21 P +-0.02 (vDirector) 405.51 358.21 P +-0.02 (y object in order to obtain) 445.81 358.21 P +4 F +0.7 (ser) 180 346.21 P +0.7 (vice) 194.19 346.21 P +0 F +0.7 ( speci\336c data that is associated with a) 211.97 346.21 P +4 F +0.7 (de) 387.69 346.21 P +0.7 (vice) 398.51 346.21 P +0 F +0.7 ( or a) 416.29 346.21 P +4 F +0.7 (message) 441.19 346.21 P +0 F +0.7 (. The inf) 481.61 346.21 P +0.7 (or) 518.85 346.21 P +0.7 (mation) 527.99 346.21 P +0.42 (will be retur) 180 334.21 P +0.42 (ned to the caller in the output cde) 232.22 334.21 P +0.42 (vData object in the f) 382.76 334.21 P +0.42 (or) 472.54 334.21 P +0.42 (m of tagged data) 481.68 334.21 P +0.85 (items) 180 322.21 P +0.85 (. This message will nor) 203.74 322.21 P +0.85 (mally only be used in the de) 309.07 322.21 P +0.85 (v) 437.79 322.21 P +0.85 (elopment of a ne) 442.54 322.21 P +0.85 (w CDEV) 519.37 322.21 P +(ser) 180 310.21 T +(vice) 194.19 310.21 T +(.) 211.82 310.21 T +0.3 (The request is submitted to the cde) 180 293.21 P +0.3 (vDirector) 337.71 293.21 P +0.3 (y de) 378.01 293.21 P +0.3 (vice through its) 396.92 293.21 P +4 F +0.3 (send) 467.86 293.21 P +0 F +0.3 (,) 489.54 293.21 P +4 F +0.3 (sendCallbac) 495.4 293.21 P +0.3 (k) 550.22 293.21 P +0 F +0.3 (,) 555.22 293.21 P +0.08 (or) 180 281.21 P +4 F +0.08 (sendNoBloc) 191.75 281.21 P +0.08 (k) 245.46 281.21 P +0 F +0.08 ( interf) 250.46 281.21 P +0.08 (ace) 275.25 281.21 P +0.08 (. The f) 291.22 281.21 P +0.08 (ollo) 319.43 281.21 P +0.08 (wing tab) 334.84 281.21 P +0.08 (le sho) 371.96 281.21 P +0.08 (ws the inputs that m) 398.57 281.21 P +0.08 (ust be placed in) 487.72 281.21 P +0.99 (the inbound cde) 180 269.21 P +0.99 (vData object pr) 252.83 269.21 P +0.99 (ior to submitting the command, and the outputs that) 322.21 269.21 P +(can be retr) 180 257.21 T +(ie) 227.95 257.21 T +(v) 235.43 257.21 T +(ed when the command is completed.) 240.18 257.21 T +4 9 Q +(Figure 48: cde) 180 223.88 T +(vData input/output associated with a \322ser) 239.76 223.88 T +(viceData\323 message) 402.61 223.88 T +0 10 Q +2.23 (The f) 180 102.21 P +2.23 (ollo) 204.72 102.21 P +2.23 (wing \336gure sho) 220.13 102.21 P +2.23 (ws the source code necessar) 291.68 102.21 P +2.23 (y to obtain the ser) 430.4 102.21 P +2.23 (viceData) 519.1 102.21 P +(associated with the de) 180 90.21 T +(vice \322DEV1\323 and the message \322get V) 278.64 90.21 T +(AL) 440.13 90.21 T +(\323.) 450.96 90.21 T +180 383.88 558 720 C +180 383.88 558 694 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.46 392.33 560.04 682.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +180.5 397.12 554.45 688 R +7 X +V +0 X +N +185.75 399.56 547.03 683.93 R +7 X +V +5 9 Q +0 X +(#include ) 185.75 677.93 T +(#include ) 185.75 666.93 T +(#include ) 185.75 655.93 T +(void main\050\051) 185.75 633.93 T +({) 203.75 622.93 T +(cdevDevice *dir = cdevDevice::attachPtr\050\322cdevDirectory\323\051;) 203.75 611.93 T +(cdevData input, output;) 203.75 600.93 T +(// ************************************************************) 203.75 578.93 T +(// * Insert the name of the device and message to be resolved.) 203.75 567.93 T +(// ************************************************************) 203.75 556.93 T +(input.insert\050\322device\323, \322DEV1\323\051;) 203.75 545.93 T +(input.insert\050\322message\323, \322get VAL\323\051;) 203.75 534.93 T +(// ************************************************************) 203.75 512.93 T +(// Submit the request to the cdevDirectory object using the) 203.75 501.93 T +(// send command, and output the result if successful.) 203.75 490.93 T +(// ************************************************************) 203.75 479.93 T +(if\050dir->send\050\322service\323, input, output\051==CDEV_SUCCESS\051) 203.75 468.93 T +({) 221.75 457.93 T +(char * ptr;) 221.75 446.93 T +(output.find\050\322value\323, ptr\051;) 221.75 435.93 T +(fprintf\050stdout, \322Service name is:%s\134n\323, ptr\051;) 221.75 424.93 T +(}) 221.75 413.93 T +(}) 203.75 402.93 T +180 383.88 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 10 Q +0 X +0 0 0 1 0 0 0 K +(T) 180.4 196.21 T +(ag Name) 185.31 196.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data T) 264.32 196.21 T +(ype) 293.13 196.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Content) 427.42 196.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Message Input) 77.43 176.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(de) 168.57 176.21 T +(vice) 180.09 176.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 245.71 176.21 T +(acter str) 265.07 176.21 T +(ing) 301.33 176.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the CDEV de) 335.86 176.21 T +(vice) 434.49 176.21 T +(.) 452.12 176.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(messa) 168.57 158.21 T +(g) 199.6 158.21 T +(e) 205.81 158.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 245.71 158.21 T +(acter str) 265.07 158.21 T +(ing) 301.33 158.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the message) 335.86 158.21 T +(.) 433.53 158.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Message Output) 77.43 140.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(\050ser) 168.57 140.21 T +(vice) 187.01 140.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(speci\336c\051) 168.57 128.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 245.71 140.21 T +(acter str) 265.07 140.21 T +(ing) 301.33 140.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data items speci\336ed in the ser) 335.86 140.21 T +(vice data section) 470.1 140.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(f) 335.86 128.21 T +(or the speci\336ed de) 338.34 128.21 T +(vice / message combination.) 419.75 128.21 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +73.43 207.88 73.43 121.88 2 L +V +2 H +0 Z +N +164.57 209.88 164.57 119.88 2 L +V +0.5 H +N +241.71 209.88 241.71 119.88 2 L +V +N +331.86 209.88 331.86 119.88 2 L +V +N +558 207.88 558 121.88 2 L +V +2 H +N +72.43 208.88 559 208.88 2 L +V +N +74.43 188.13 557 188.13 2 L +V +0.5 H +N +74.43 185.63 557 185.63 2 L +V +N +72.43 168.88 559 168.88 2 L +V +N +74.43 152.13 557 152.13 2 L +V +N +74.43 149.63 557 149.63 2 L +V +N +72.43 120.88 559 120.88 2 L +V +2 H +N +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "63" 71 +%%Page: "64" 72 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. Using the cde) 54 739 T +(vDirector) 118.76 739 T +(y De) 155.03 739 T +(vice) 173.27 739 T +0 10 Q +(64) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Figure 49: Using the \322ser) 162 697 T +(viceData\323 message with a cde) 263.81 697 T +(vDirector) 383.58 697 T +(y de) 419.85 697 T +(vice) 436.59 697 T +2 10 Q +(\322update\323) 54 365.88 T +0 F +0.02 (The \322update\323 message is submitted to the cde) 162 365.88 P +0.02 (vDirector) 365.26 365.88 P +0.02 (y object in order to add ne) 405.56 365.88 P +0.02 (w or) 521.09 365.88 P +1.85 (updated class de\336nitions or de) 162 353.88 P +1.85 (vice instances to the inter) 304.18 353.88 P +1.85 (nal de) 424.68 353.88 P +1.85 (vice de\336nition data) 453.47 353.88 P +0.03 (str) 162 341.88 P +0.03 (uctures) 173.26 341.88 P +0.03 (. The data that is submitted in the input cde) 205.9 341.88 P +0.03 (vData object is in the same f) 397.06 341.88 P +0.03 (or) 522.53 341.88 P +0.03 (m) 531.67 341.88 P +(as a corresponding entr) 162 329.88 T +(y in the CDEV DDL \336le) 267.35 329.88 T +(.) 368.34 329.88 T +0.3 (The request is submitted to the cde) 162 312.88 P +0.3 (vDirector) 319.71 312.88 P +0.3 (y de) 360.01 312.88 P +0.3 (vice through its) 378.92 312.88 P +4 F +0.3 (send) 449.86 312.88 P +0 F +0.3 (,) 471.54 312.88 P +4 F +0.3 (sendCallbac) 477.4 312.88 P +0.3 (k) 532.22 312.88 P +0 F +0.3 (,) 537.22 312.88 P +0.08 (or) 162 300.88 P +4 F +0.08 (sendNoBloc) 173.75 300.88 P +0.08 (k) 227.46 300.88 P +0 F +0.08 ( interf) 232.46 300.88 P +0.08 (ace) 257.25 300.88 P +0.08 (. The f) 273.22 300.88 P +0.08 (ollo) 301.43 300.88 P +0.08 (wing tab) 316.84 300.88 P +0.08 (le sho) 353.96 300.88 P +0.08 (ws the inputs that m) 380.57 300.88 P +0.08 (ust be placed in) 469.72 300.88 P +0.99 (the inbound cde) 162 288.88 P +0.99 (vData object pr) 234.83 288.88 P +0.99 (ior to submitting the command, and the outputs that) 304.21 288.88 P +(can be retr) 162 276.88 T +(ie) 209.95 276.88 T +(v) 217.43 276.88 T +(ed when the command is completed.) 222.18 276.88 T +4 9 Q +(Figure 50: cde) 162 243.55 T +(vData input/output associated with a \322update\323 message) 221.76 243.55 T +0 10 Q +0.02 (The f) 162 109.88 P +0.02 (ollo) 184.51 109.88 P +0.02 (wing \336gure sho) 199.92 109.88 P +0.02 (ws the source code necessar) 267.06 109.88 P +0.02 (y to inser) 396.94 109.88 P +0.02 (t the class de\336nition f) 437.95 109.88 P +0.02 (or) 531.11 109.88 P +2.44 (the \322stdio\323 class into the de) 162 97.88 P +2.44 (vice de\336nition data str) 293.42 97.88 P +2.44 (ucture using the cde) 397.62 97.88 P +2.44 (vDirector) 494.7 97.88 P +2.44 (y) 535 97.88 P +(object.) 162 85.88 T +162 391.55 540 720 C +162 391.55 540 694 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.88 397.33 542.45 682.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.92 402.12 536.87 688 R +7 X +V +0 X +N +168.17 407.02 529.45 684 R +7 X +V +5 9 Q +0 X +(#include ) 168.17 678 T +(#include ) 168.17 667 T +(#include ) 168.17 656 T +(void main\050\051) 168.17 634 T +({) 186.17 623 T +(cdevDevice *dir = cdevDevice::attachPtr\050\322cdevDirectory\323\051;) 186.17 612 T +(cdevData input, output;) 186.17 601 T +(// ***********************************************************) 186.17 579 T +(// * Insert the name of the device and message to be resolved.) 186.17 568 T +(// ***********************************************************) 186.17 557 T +(input.insert\050\322device\323, \322DEV1\323\051;) 186.17 546 T +(input.insert\050\322message\323, \322get VAL\323\051;) 186.17 535 T +(// ***********************************************************) 186.17 513 T +(// * Submit the request to the cdevDirectory object using the) 186.17 502 T +(// * send command, and output the result \050using asciiDump\051 if) 186.17 491 T +(// * successful.) 186.17 480 T +(// ***********************************************************) 186.17 469 T +(if\050dir->send\050\322serviceData\323, input, output\051==CDEV_SUCCESS\051) 186.17 458 T +({) 204.17 447 T +(output.asciiDump\050stdout\051;) 204.17 436 T +(}) 204.17 425 T +(}) 186.17 414 T +162 391.55 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 10 Q +0 X +0 0 0 1 0 0 0 K +(T) 162.4 215.88 T +(ag Name) 167.31 215.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data T) 246.32 215.88 T +(ype) 275.13 215.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Content) 409.42 215.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Message Input) 59.43 195.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(v) 150.57 195.88 T +(alue) 155.93 195.88 T +0 F +(or) 178.72 195.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(char) 227.71 195.88 T +(acter str) 247.07 195.88 T +(ing) 283.33 195.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ASCII te) 317.86 195.88 T +(xt de\336nition of a DDL class or de) 354.8 195.88 T +(vice) 498.45 195.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(instanciation.) 317.86 183.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(\336le) 150.57 165.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 227.71 165.88 T +(acter str) 247.07 165.88 T +(ing) 283.33 165.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Complete path to the \336le containing the updated) 317.86 165.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(DDL inf) 317.86 153.88 T +(or) 350.9 153.88 T +(mation.) 360.04 153.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Message Output) 59.43 135.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(v) 150.57 135.88 T +(alue) 155.93 135.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(integer) 227.71 135.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Boolean completion status of the oper) 317.86 135.88 T +(ation.) 485.63 135.88 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +55.43 227.55 55.43 129.55 2 L +V +2 H +0 Z +N +146.57 229.55 146.57 127.55 2 L +V +0.5 H +N +223.71 229.55 223.71 127.55 2 L +V +N +313.86 229.55 313.86 127.55 2 L +V +N +540 227.55 540 129.55 2 L +V +2 H +N +54.43 228.55 541 228.55 2 L +V +N +56.43 207.8 539 207.8 2 L +V +0.5 H +N +56.43 205.3 539 205.3 2 L +V +N +54.43 176.55 541 176.55 2 L +V +N +56.43 147.8 539 147.8 2 L +V +N +56.43 145.3 539 145.3 2 L +V +N +54.43 128.55 541 128.55 2 L +V +2 H +N +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "64" 72 +%%Page: "65" 73 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. Using the cde) 422.73 739 T +(vDirector) 487.49 739 T +(y De) 523.76 739 T +(vice) 542 739 T +0 10 Q +(65) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +(Figure 51: Using the \322update\323 message with a cde) 180 697 T +(vDirector) 381.32 697 T +(y de) 417.59 697 T +(vice) 434.33 697 T +2 10 Q +(\322v) 72 356.36 T +(alidate\323) 82.36 356.36 T +0 F +0.2 (The \322v) 180 356.36 P +0.2 (alidate\323 message is submitted to the cde) 208.29 356.36 P +0.2 (vDirector) 388.19 356.36 P +0.2 (y object in order to v) 428.49 356.36 P +0.2 (er) 519.3 356.36 P +0.2 (ify that) 528.34 356.36 P +2.08 (a combination of) 180 344.36 P +4 F +2.08 (de) 262.39 344.36 P +2.08 (vice) 273.21 344.36 P +2.08 (, DDL class) 290.84 344.36 P +2.08 (, v) 345.97 344.36 P +2.08 (erb) 358.36 344.36 P +2.08 (, attr) 372.41 344.36 P +2.08 (ib) 394.65 344.36 P +2.08 (ute) 402.23 344.36 P +0 F +2.08 (or) 420.99 344.36 P +4 F +2.08 (message) 434.74 344.36 P +0 F +2.08 (represent a v) 480.17 344.36 P +2.08 (alid) 542.44 344.36 P +(combination.) 180 332.36 T +1.08 (At least one of) 180 315.36 P +4 F +1.08 (de) 251.02 315.36 P +1.08 (vice) 261.84 315.36 P +0 F +1.08 ( or) 279.62 315.36 P +4 F +1.08 (DDL class) 296.23 315.36 P +0 F +1.08 ( m) 342.87 315.36 P +1.08 (ust be speci\336ed when using this message) 354.95 315.36 P +1.08 (. If) 545.8 315.36 P +-0.19 (both are speci\336ed, the cde) 180 303.36 P +-0.19 (vDirector) 296.23 303.36 P +-0.19 (y object will con\336r) 336.53 303.36 P +-0.19 (m that the) 414.57 303.36 P +4 F +-0.19 (de) 461.25 303.36 P +-0.19 (vice) 472.07 303.36 P +0 F +-0.19 ( is a member of) 489.85 303.36 P +(the speci\336ed) 180 291.36 T +4 F +( DDL class) 236.14 291.36 T +0 F +(.) 284.33 291.36 T +1.02 (If) 180 274.36 P +4 F +1.02 (v) 189.36 274.36 P +1.02 (erb) 194.11 274.36 P +1.02 (, attr) 208.16 274.36 P +1.02 (ib) 229.33 274.36 P +1.02 (ute) 236.91 274.36 P +0 F +1.02 (or) 254.61 274.36 P +4 F +1.02 ( message) 263.5 274.36 P +0 F +1.02 (are included, the cde) 311.66 274.36 P +1.02 (vDirector) 407.24 274.36 P +1.02 (y object will deter) 447.54 274.36 P +1.02 (mine if) 527.53 274.36 P +(each of them are members of the speci\336ed) 180 262.36 T +4 F +(de) 372.31 262.36 T +(vice) 383.13 262.36 T +0 F +(and/or) 403.69 262.36 T +4 F +( DDL class) 432.04 262.36 T +(.) 480.23 262.36 T +0 F +0.3 (The request is submitted to the cde) 180 245.36 P +0.3 (vDirector) 337.71 245.36 P +0.3 (y de) 378.01 245.36 P +0.3 (vice through its) 396.92 245.36 P +4 F +0.3 (send) 467.86 245.36 P +0 F +0.3 (,) 489.54 245.36 P +4 F +0.3 (sendCallbac) 495.4 245.36 P +0.3 (k) 550.22 245.36 P +0 F +0.3 (,) 555.22 245.36 P +0.08 (or) 180 233.36 P +4 F +0.08 (sendNoBloc) 191.75 233.36 P +0.08 (k) 245.46 233.36 P +0 F +0.08 ( interf) 250.46 233.36 P +0.08 (ace) 275.25 233.36 P +0.08 (. The f) 291.22 233.36 P +0.08 (ollo) 319.43 233.36 P +0.08 (wing tab) 334.84 233.36 P +0.08 (le sho) 371.96 233.36 P +0.08 (ws the inputs that m) 398.57 233.36 P +0.08 (ust be placed in) 487.72 233.36 P +0.99 (the inbound cde) 180 221.36 P +0.99 (vData object pr) 252.83 221.36 P +0.99 (ior to submitting the command, and the outputs that) 322.21 221.36 P +(can be retr) 180 209.36 T +(ie) 227.95 209.36 T +(v) 235.43 209.36 T +(ed when the command is completed.) 240.18 209.36 T +4 9 Q +(Figure 52: cde) 180 176.02 T +(vData input/output associated with a \322v) 239.76 176.02 T +(alidate\323 message) 394.11 176.02 T +180 382.02 558 720 C +180 382.02 558 694 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.46 385.66 560.04 682.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +180.5 392.95 554.45 688 R +7 X +V +0 X +N +185.75 398.02 547.03 683.88 R +7 X +V +5 9 Q +0 X +(#include ) 185.75 677.88 T +(#include ) 185.75 666.88 T +(#include ) 185.75 655.88 T +(void main\050\051) 185.75 633.88 T +({) 203.75 622.88 T +(cdevDevice *dir = cdevDevice::attachPtr\050\322cdevDirectory\323\051;) 203.75 611.88 T +(cdevData input, output;) 203.75 600.88 T +(// ***********************************************************) 203.75 578.88 T +(// * Class definition to insert.) 203.75 567.88 T +(// ***********************************************************) 203.75 556.88 T +(char *def = \322class stdio{verbs{get,set,monitorOn,monitorOff}}\323;) 203.75 545.88 T +(// ***********************************************************) 203.75 523.88 T +(// * Insert the class definition.) 203.75 512.88 T +(// ***********************************************************) 203.75 501.88 T +(input.insert\050\322value\323, def\051;) 203.75 490.88 T +(// ***********************************************************) 203.75 468.88 T +(// * Submit the request to the cdevDirectory object.) 203.75 457.88 T +(// ***********************************************************) 203.75 446.88 T +(dir->send\050\322update\323, input, output\051) 203.75 435.88 T +(}) 203.75 424.88 T +180 382.02 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 10 Q +0 X +0 0 0 1 0 0 0 K +(T) 180.4 148.36 T +(ag Name) 185.31 148.36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Data T) 264.32 148.36 T +(ype) 293.13 148.36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Content) 427.42 148.36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Message Input) 77.43 128.36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(de) 168.57 128.36 T +(vice) 180.09 128.36 T +0 F +(or) 202.33 128.36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(char) 245.71 128.36 T +(acter str) 265.07 128.36 T +(ing) 301.33 128.36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the CDEV de) 335.86 128.36 T +(vice) 434.49 128.36 T +(.) 452.12 128.36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(c) 168.57 110.36 T +(lass) 173.93 110.36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 245.71 110.36 T +(acter str) 265.07 110.36 T +(ing) 301.33 110.36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the DDL class) 335.86 110.36 T +(.) 438.52 110.36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(attrib) 168.57 92.36 T +(ute) 193.37 92.36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 245.71 92.36 T +(acter str) 265.07 92.36 T +(ing) 301.33 92.36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the attr) 335.86 92.36 T +(ib) 407.71 92.36 T +(ute to v) 415.29 92.36 T +(alidate \050optional\051) 447.84 92.36 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +73.43 160.02 73.43 85.27 2 L +V +2 H +0 Z +N +164.57 162.02 164.57 84.77 2 L +V +0.5 H +N +241.71 162.02 241.71 84.77 2 L +V +N +331.86 162.02 331.86 84.77 2 L +V +N +558 160.02 558 85.27 2 L +V +2 H +N +72.43 161.02 559 161.02 2 L +V +N +74.43 140.27 557 140.27 2 L +V +0.5 H +N +74.43 137.77 557 137.77 2 L +V +N +72.43 121.02 559 121.02 2 L +V +N +72.43 103.02 559 103.02 2 L +V +N +72.43 85.02 559 85.02 2 L +V +N +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "65" 73 +%%Page: "66" 74 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. Using the cde) 54 739 T +(vDirector) 118.76 739 T +(y De) 155.03 739 T +(vice) 173.27 739 T +0 10 Q +(66) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +2.76 (The f) 162 647.33 P +2.76 (ollo) 187.25 647.33 P +2.76 (wing \336gure sho) 202.66 647.33 P +2.76 (ws the source code necessar) 275.29 647.33 P +2.76 (y to deter) 416.14 647.33 P +2.76 (mine if the) 463.6 647.33 P +4 F +2.76 (v) 520.8 647.33 P +2.76 (erb) 525.55 647.33 P +0 F +(\322monitorOn\323 is a member of the) 162 635.33 T +4 F +(class) 303.71 635.33 T +0 F +( \322stdio\323.) 326.49 635.33 T +4 9 Q +(Figure 53: Using the \322update\323 message with a cde) 162 602 T +(vDirector) 363.32 602 T +(y de) 399.59 602 T +(vice) 416.33 602 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 10 Q +(messa) 150.57 709.33 T +(g) 181.6 709.33 T +(e) 187.81 709.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 227.71 709.33 T +(acter str) 247.07 709.33 T +(ing) 283.33 709.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the message to v) 317.86 709.33 T +(alidate \050optional\051) 434.33 709.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(verb) 150.57 691.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(char) 227.71 691.33 T +(acter str) 247.07 691.33 T +(ing) 283.33 691.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Name of the v) 317.86 691.33 T +(erb to v) 379.86 691.33 T +(alidate \050optional\051) 412.96 691.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Message Output) 59.43 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(v) 150.57 673.33 T +(alue) 155.93 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(integer) 227.71 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Boolean completion status of the oper) 317.86 673.33 T +(ation.) 485.63 673.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +55.43 719.75 55.43 667 2 L +V +2 H +0 Z +N +146.57 720.25 146.57 665 2 L +V +0.5 H +N +223.71 720.25 223.71 665 2 L +V +N +313.86 720.25 313.86 665 2 L +V +N +540 719.75 540 667 2 L +V +2 H +N +54.43 720 541 720 2 L +V +0.5 H +N +54.43 702 541 702 2 L +V +N +56.43 685.25 539 685.25 2 L +V +N +56.43 682.75 539 682.75 2 L +V +N +54.43 666 541 666 2 L +V +2 H +N +162 81 540 654 C +162 362.5 540 599 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.88 364.95 542.45 591.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.92 370.57 536.87 596.57 R +7 X +V +0 X +N +168.17 374.46 529.45 593.41 R +7 X +V +5 9 Q +0 X +(#include ) 168.17 587.41 T +(#include ) 168.17 576.41 T +(#include ) 168.17 565.41 T +(void main\050\051) 168.17 543.41 T +({) 186.17 532.41 T +(cdevDevice *dir = cdevDevice::attachPtr\050\322cdevDirectory\323\051;) 186.17 521.41 T +(cdevData input, output;) 186.17 510.41 T +(int result;) 186.17 499.41 T +(input.insert\050\322class\323, \322stdio\323\051;) 186.17 477.41 T +(input.insert\050\322verb\323, \322monitorOn\323\051;) 186.17 466.41 T +(// ***********************************************************) 186.17 444.41 T +(// * Submit the request to the cdevDirectory object.) 186.17 433.41 T +(// ***********************************************************) 186.17 422.41 T +(dir->send\050\322validate\323, input, output\051) 186.17 411.41 T +(result = \050int\051output;) 186.17 400.41 T +(fprintf\050stdout, \322monitorOn %s in stdio\323, result?\323IS\323:\323IS NOT\323\051;) 186.17 389.41 T +(}) 186.17 378.41 T +162 81 540 654 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "66" 74 +%%Page: "67" 75 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 353.86 739 T +(ault Ser) 377.6 739 T +(vice Beha) 408.89 739 T +(vior f) 448.23 739 T +(or Standard Messages) 467.46 739 T +0 10 Q +(67) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(8.) 159.32 710.67 T +(Default Ser) 180 710.67 T +(vice Beha) 254.05 710.67 T +(vior f) 319.2 710.67 T +(or Standar) 353.15 710.67 T +(d Messa) 422.89 710.67 T +(g) 477.99 710.67 T +(es) 486.68 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w) 108.64 673.33 T +0 F +1.88 (The CDEV libr) 180 673.33 P +1.88 (ar) 247.56 673.33 P +1.88 (y is designed to pro) 256.75 673.33 P +1.88 (vide a standard calling interf) 350.83 673.33 P +1.88 (ace to dissimilar) 482.56 673.33 P +0.89 (de) 180 661.33 P +0.89 (vices within a control system. This interf) 190.82 661.33 P +0.89 (ace is accommodated through the use of) 372.02 661.33 P +0.02 (the cde) 180 649.33 P +0.02 (vDe) 212.52 649.33 P +0.02 (vice methods) 230 649.33 P +3 F +0.02 (send, sendNoBloc) 291.73 649.33 P +0.02 (k) 378.79 649.33 P +0 F +0.02 ( and) 384.35 649.33 P +3 F +0.02 (sendCallbac) 406.62 649.33 P +0.02 (k) 465.33 649.33 P +4 F +0.02 (.) 470.89 649.33 P +0 F +0.02 ( Ho) 473.67 649.33 P +0.02 (w) 489.1 649.33 P +0.02 (e) 496.22 649.33 P +0.02 (v) 501.48 649.33 P +0.02 (er) 506.23 649.33 P +0.02 (, because) 514.62 649.33 P +0.79 (each ser) 180 637.33 P +0.79 (vice can de\336ne the names and beha) 219.44 637.33 P +0.79 (viors of the messages that it suppor) 384.61 637.33 P +0.79 (ts) 547.59 637.33 P +0.79 (,) 555.22 637.33 P +(the user m) 180 625.33 T +(ust be increasingly a) 227.14 625.33 T +(w) 318.09 625.33 T +(are of which ser) 325.16 625.33 T +(vice ma) 396.04 625.33 T +(y process its messages) 430.19 625.33 T +(.) 533.96 625.33 T +0 (In order to reduce the required kno) 180 608.33 P +0 (wledge of the user) 333.81 608.33 P +0 (, and to impro) 415.01 608.33 P +0 (v) 475.99 608.33 P +0 (e the consistency) 480.74 608.33 P +0.46 (of all ser) 180 596.33 P +0.46 (vices) 219 596.33 P +0.46 (, all CDEV ser) 241.63 596.33 P +0.46 (vices should pro) 306.09 596.33 P +0.46 (vide w) 379.1 596.33 P +0.46 (ell-de\336ned suppor) 407.8 596.33 P +0.46 (t f) 488.13 596.33 P +0.46 (or a minim) 496.63 596.33 P +0.46 (um) 544.11 596.33 P +(list of) 180 584.33 T +4 F +(v) 206.12 584.33 T +(erbs) 210.87 584.33 T +0 F +(.) 230.17 584.33 T +2.13 (The f) 180 567.33 P +2.13 (ollo) 204.62 567.33 P +2.13 (wing v) 220.03 567.33 P +2.13 (erbs should be implemented to pro) 250.25 567.33 P +2.13 (vide a standard beha) 414.71 567.33 P +2.13 (vior in all) 514.29 567.33 P +(CDEV ser) 180 555.33 T +(vices:) 224.75 555.33 T +3 F +(g) 253.09 555.33 T +(et, set, monitorOn,) 259.3 555.33 T +0 F +( and) 347.65 555.33 T +3 F +(monitorOff) 369.89 555.33 T +(.) 421.45 555.33 T +2 F +(\322g) 72 526.33 T +(et\323 Messa) 83.21 526.33 T +(g) 130.35 526.33 T +(e) 136.56 526.33 T +0 F +0.79 (The) 180 526.33 P +4 F +0.79 (\322get\323) 200.8 526.33 P +0 F +0.79 ( v) 221.36 526.33 P +0.79 (erb can be joined with an) 229.68 526.33 P +0.79 (y) 344.66 526.33 P +4 F +0.79 (attr) 353.23 526.33 P +0.79 (ib) 367.83 526.33 P +0.79 (ute) 375.42 526.33 P +0 F +0.79 ( of a de) 389.32 526.33 P +0.79 (vice to f) 424.75 526.33 P +0.79 (or) 460.49 526.33 P +0.79 (m a \322get\323 message) 469.63 526.33 P +0.79 (.) 555.22 526.33 P +1.89 (This message is then sent to the de) 180 514.33 P +1.89 (vice in order to obtain the v) 350.8 514.33 P +1.89 (alue of speci\336ed) 481.96 514.33 P +4 F +0.19 (proper) 180 502.33 P +0.19 (ties) 209.3 502.33 P +0 F +0.19 (of the) 227.83 502.33 P +4 F +0.19 (attr) 256.02 502.33 P +0.19 (ib) 270.62 502.33 P +0.19 (ute) 278.2 502.33 P +0.19 (.) 291.95 502.33 P +0 F +0.19 (The f) 297.7 502.33 P +0.19 (ollo) 320.38 502.33 P +0.19 (wing steps should be e) 335.79 502.33 P +0.19 (x) 437.98 502.33 P +0.19 (ecuted in order to utiliz) 442.68 502.33 P +0.19 (e a) 543.91 502.33 P +4 F +(\322get\323) 180 490.33 T +0 F +( message) 200.56 490.33 T +(.) 243.76 490.33 T +(1.) 180 473.33 T +(Obtain a pointer to the) 198 473.33 T +4 F +(cde) 299.73 473.33 T +(vDe) 315.55 473.33 T +(vice) 333.03 473.33 T +0 F +( object f) 350.81 473.33 T +(or the de) 385.53 473.33 T +(vice that y) 424.7 473.33 T +(ou wish to address) 469.52 473.33 T +(.) 552.74 473.33 T +(2.) 180 449.33 T +(Create a message str) 198 449.33 T +(ing b) 293.74 449.33 T +(y concatenating the) 315.22 449.33 T +4 F +(attr) 404.72 449.33 T +(ib) 419.32 449.33 T +(ute) 426.9 449.33 T +0 F +(that y) 443.58 449.33 T +(ou wish to address) 467.84 449.33 T +(to the) 198 437.33 T +4 F +(\322get\323) 225.8 437.33 T +0 F +( v) 246.36 437.33 T +(erb) 253.89 437.33 T +(. F) 267.94 437.33 T +(or instance) 279.31 437.33 T +(, to get the) 328.07 437.33 T +4 F +(V) 378.11 437.33 T +(AL) 383.98 437.33 T +0 F +( attr) 396.21 437.33 T +(ib) 413.59 437.33 T +(ute of a de) 421.17 437.33 T +(vice) 468.13 437.33 T +(, the message) 485.76 437.33 T +(str) 198 425.33 T +(ings should be:) 209.26 425.33 T +3 F +(\322g) 279.3 425.33 T +(et V) 290.51 425.33 T +(AL) 308.05 425.33 T +(\323) 319.98 425.33 T +0 F +(.) 324.98 425.33 T +(3.) 180 401.33 T +(Optionally) 198 401.33 T +(, use the cde) 241.46 401.33 T +(vDe) 298.42 401.33 T +(vice object created in step 1 and the message str) 315.9 401.33 T +(ing) 533.38 401.33 T +(created in step 2 to obtain a pointer to a) 198 389.33 T +4 F +(cde) 377 389.33 T +(vRequestObject) 392.82 389.33 T +0 F +(object.) 466.74 389.33 T +(4.) 180 365.33 T +(Set the) 198 365.33 T +4 F +(conte) 232.47 365.33 T +(xt) 256.63 365.33 T +0 F +( of the) 264.41 365.33 T +4 F +(cde) 294.99 365.33 T +(vDe) 310.81 365.33 T +(vice) 328.29 365.33 T +0 F +( or) 346.07 365.33 T +4 F +(cde) 360.52 365.33 T +(vRequestObject) 376.34 365.33 T +0 F +( to indicate which) 447.48 365.33 T +(proper) 198 353.33 T +(ties y) 227.3 353.33 T +(ou wish to obtain. A non-z) 250.44 353.33 T +(ero v) 365.35 353.33 T +(alue in an) 387.33 353.33 T +(y proper) 430.54 353.33 T +(ty indicates that its) 467.62 353.33 T +(v) 198 341.33 T +(alue should be retur) 202.75 341.33 T +(ned. If no conte) 291.38 341.33 T +(xt has been speci\336ed, the ser) 360.02 341.33 T +(vice should) 490.39 341.33 T +(retur) 198 329.33 T +(n the) 218.81 329.33 T +4 F +(v) 243.83 329.33 T +(alue) 248.58 329.33 T +0 F +( proper) 267.48 329.33 T +(ty b) 299.56 329.33 T +(y def) 315.48 329.33 T +(ault. A complete descr) 336.86 329.33 T +(iption of the conte) 438.72 329.33 T +(xt data) 517.36 329.33 T +(object is pro) 198 317.33 T +(vided in the cde) 251.76 317.33 T +(vDe) 321.5 317.33 T +(vice documentation.) 338.98 317.33 T +(5.) 180 293.33 T +-0.08 (Use the) 198 293.33 P +3 F +-0.08 (send, sendNoBloc) 235.09 293.33 P +-0.08 (k,) 322.05 293.33 P +0 F +-0.08 (or) 333.09 293.33 P +3 F +-0.08 (sendCallbac) 344.68 293.33 P +-0.08 (k) 403.39 293.33 P +0 F +-0.08 ( message to submit the message) 408.95 293.33 P +(to the de) 198 281.33 T +(vice) 236.62 281.33 T +(.) 254.25 281.33 T +(6.) 180 257.33 T +(Ev) 198 257.33 T +(aluate the retur) 209.42 257.33 T +(n v) 276.93 257.33 T +(alue from the) 290.02 257.33 T +3 F +(send) 351.16 257.33 T +0 F +(command to deter) 377.28 257.33 T +(mine if the oper) 458.12 257.33 T +(ation) 526.94 257.33 T +(completed successful. An) 198 245.33 T +(y v) 311.23 245.33 T +(alue other than) 323.76 245.33 T +3 F +(CDEV_SUCCESS) 393.25 245.33 T +0 F +(indicates that an) 477.71 245.33 T +(error occurred in handling the message) 198 233.33 T +(.) 371.81 233.33 T +(7.) 180 209.33 T +(If the call w) 198 209.33 T +(as completed successfully) 247.87 209.33 T +(, e) 363.02 209.33 T +(xtr) 373.84 209.33 T +(act the desired proper) 384.85 209.33 T +(ties from the) 482.52 209.33 T +(resultant cde) 198 197.33 T +(vData object.) 254.95 197.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "67" 75 +%%Page: "68" 76 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 54 739 T +(ault Ser) 77.74 739 T +(vice Beha) 109.03 739 T +(vior f) 148.37 739 T +(or Standard Messages) 167.6 739 T +0 10 Q +(68) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(\322set\323 Messa) 54 713.33 T +(g) 111.7 713.33 T +(e) 117.91 713.33 T +0 F +0.86 (The) 162 713.33 P +4 F +0.86 (\322set\323) 182.87 713.33 P +0 F +0.86 ( v) 202.87 713.33 P +0.86 (erb can be joined with an) 211.26 713.33 P +0.86 (y) 326.59 713.33 P +4 F +0.86 (attr) 335.23 713.33 P +0.86 (ib) 349.83 713.33 P +0.86 (ute) 357.42 713.33 P +0 F +0.86 ( of a de) 371.32 713.33 P +0.86 (vice to f) 406.96 713.33 P +0.86 (or) 442.84 713.33 P +0.86 (m a \322set\323 message) 451.98 713.33 P +0.86 (.) 537.22 713.33 P +1.75 (This message is then sent to the de) 162 701.33 P +1.75 (vice in order to set the v) 331.8 701.33 P +1.75 (alue) 448.2 701.33 P +4 F +1.75 (proper) 471.62 701.33 P +1.75 (ty) 500.92 701.33 P +0 F +1.75 (of the) 513.23 701.33 P +4 F +(attr) 162 689.33 T +(ib) 176.6 689.33 T +(ute) 184.18 689.33 T +(.) 197.93 689.33 T +0 F +(The f) 203.49 689.33 T +(ollo) 225.98 689.33 T +(wing steps should be e) 241.39 689.33 T +(x) 342.81 689.33 T +(ecuted in order to utiliz) 347.51 689.33 T +(e a) 447.96 689.33 T +4 F +(\322set\323) 464.64 689.33 T +0 F +( message) 484.64 689.33 T +(.) 527.84 689.33 T +(1.) 162 672.33 T +(Obtain a pointer to the) 180 672.33 T +4 F +(cde) 281.73 672.33 T +(vDe) 297.55 672.33 T +(vice) 315.03 672.33 T +0 F +( object f) 332.81 672.33 T +(or the de) 367.53 672.33 T +(vice that y) 406.7 672.33 T +(ou wish to address) 451.52 672.33 T +(.) 534.74 672.33 T +(2.) 162 648.33 T +(Create a message str) 180 648.33 T +(ing b) 275.74 648.33 T +(y concatenating the) 297.22 648.33 T +4 F +(attr) 386.72 648.33 T +(ib) 401.32 648.33 T +(ute) 408.9 648.33 T +0 F +(that y) 425.58 648.33 T +(ou wish to address) 449.84 648.33 T +(to the) 180 636.33 T +4 F +(\322set\323) 207.8 636.33 T +0 F +( v) 227.8 636.33 T +(erb) 235.33 636.33 T +(. F) 249.38 636.33 T +(or instance) 260.75 636.33 T +(, to set the) 309.51 636.33 T +4 F +(bdl) 358.99 636.33 T +0 F +( attr) 372.33 636.33 T +(ib) 389.71 636.33 T +(ute of a de) 397.29 636.33 T +(vice) 444.25 636.33 T +(, the message) 461.88 636.33 T +(str) 180 624.33 T +(ing should be:) 191.26 624.33 T +3 F +(\322set bdl\323) 256.3 624.33 T +0 F +(.) 298.53 624.33 T +(3.) 162 600.33 T +(Optionally) 180 600.33 T +(, use the cde) 223.46 600.33 T +(vDe) 280.42 600.33 T +(vice object created in step 1 and the message str) 297.9 600.33 T +(ing) 515.38 600.33 T +(created in step 2 to obtain a pointer to a) 180 588.33 T +4 F +(cde) 359 588.33 T +(vRequestObject) 374.82 588.33 T +0 F +(object.) 448.74 588.33 T +(4.) 162 564.33 T +(Set the) 180 564.33 T +4 F +(v) 214.47 564.33 T +(alue) 219.22 564.33 T +0 F +( proper) 238.12 564.33 T +(ty of the outbound cde) 270.2 564.33 T +(vData object to the ne) 368.86 564.33 T +(w v) 465.94 564.33 T +(alue) 480.69 564.33 T +(.) 499.44 564.33 T +(5.) 162 540.33 T +-0.08 (Use the) 180 540.33 P +3 F +-0.08 (send, sendNoBloc) 217.09 540.33 P +-0.08 (k,) 304.05 540.33 P +0 F +-0.08 (or) 315.09 540.33 P +3 F +-0.08 (sendCallbac) 326.68 540.33 P +-0.08 (k) 385.39 540.33 P +0 F +-0.08 ( message to submit the message) 390.95 540.33 P +(to the de) 180 528.33 T +(vice) 218.62 528.33 T +(.) 236.25 528.33 T +(6.) 162 504.33 T +(Ev) 180 504.33 T +(aluate the retur) 191.42 504.33 T +(n v) 258.93 504.33 T +(alue from the speci\336c) 272.02 504.33 T +3 F +(send) 369.28 504.33 T +0 F +(command to deter) 395.4 504.33 T +(mine if the) 476.24 504.33 T +(message w) 180 492.33 T +(as tr) 230.42 492.33 T +(ansmitted successful. An) 249.77 492.33 T +(y v) 360.22 492.33 T +(alue other than) 372.75 492.33 T +3 F +(CDEV_SUCCESS) 442.24 492.33 T +0 F +(indicates that the message w) 180 480.33 T +(as not tr) 308.8 480.33 T +(ansmitted successfully) 344.83 480.33 T +(.) 443.86 480.33 T +1.92 (In the f) 162 456.33 P +1.92 (ollo) 196.13 456.33 P +1.92 (wing e) 211.54 456.33 P +1.92 (xample) 242.06 456.33 P +1.92 (, the) 274.14 456.33 P +4 F +1.92 (\322get\323) 300.23 456.33 P +0 F +1.92 ( message will be used to obtain the proper) 320.79 456.33 P +1.92 (ties) 524.44 456.33 P +4 F +3.16 (v) 162 444.33 P +3.16 (alue) 166.75 444.33 P +3.16 (, status and se) 185.5 444.33 P +3.16 (v) 259.71 444.33 P +3.16 (er) 264.46 444.33 P +3.16 (ity) 273.5 444.33 P +0 F +3.16 (from the) 289.44 444.33 P +4 F +3.16 (bdl) 335.21 444.33 P +0 F +3.16 ( attr) 348.55 444.33 P +3.16 (ib) 369.09 444.33 P +3.16 (ute of de) 376.67 444.33 P +3.16 (vice) 421.6 444.33 P +4 F +3.16 (MQB1S01) 445.32 444.33 P +0 F +3.16 (, the) 491.45 444.33 P +4 F +3.16 (\322set\323) 520 444.33 P +0 F +1.15 (message will then be used to cop) 162 432.33 P +1.15 (y the) 316.43 432.33 P +4 F +1.15 (v) 343.18 432.33 P +1.15 (alue) 347.93 432.33 P +0 F +1.15 ( proper) 366.83 432.33 P +1.15 (ty to the) 400.06 432.33 P +4 F +1.15 (bdl) 441.86 432.33 P +0 F +1.15 (attr) 459.13 432.33 P +1.15 (ib) 473.73 432.33 P +1.15 (ute of de) 481.31 432.33 P +1.15 (vice) 522.22 432.33 P +4 F +(MQB1S02) 162 420.33 T +0 F +(.) 208.13 420.33 T +4 9 Q +(Figure 54: Def) 162 387 T +(ault beha) 221.26 387 T +(vior of the \322get\323 and \322set\323 messages) 258.1 387 T +162 81 540 720 C +162 82.62 540 384 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.88 84.23 542.45 372.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.92 87.48 536.87 381.57 R +7 X +V +0 X +N +168.17 91.84 530.28 377.9 R +7 X +V +5 9 Q +0 X +(#include ) 168.17 371.9 T +(#include ) 168.17 360.9 T +(#include ) 168.17 349.9 T +(#include ) 168.17 338.9 T +(// ****************************************************************) 168.17 316.9 T +(// * The printError function will be used to output any error that) 168.17 305.9 T +(// * that occurs during the processing of the \322get\323 or \322set\323) 168.17 294.9 T +(// * messages.) 168.17 283.9 T +(// ****************************************************************) 168.17 272.9 T +(int printError \050 int errCode \051) 168.17 261.9 T +({) 186.17 250.9 T +(switch\050errCode\051) 186.17 239.9 T +({) 204.17 228.9 T +(// ******* Unknown device or device/message mismatch ******) 204.17 217.9 T +(case CDEV_INVALIDOBJ:) 204.17 206.9 T +(printf\050\322Unknown device or device/message mismatch\134n\323\051;) 222.17 195.9 T +(break;) 222.17 184.9 T +(// * Communications error between application and service *) 204.17 162.9 T +(case CDEV_NOTCONNECTED:) 204.17 151.9 T +(case CDEV_IOFAILED:) 204.17 140.9 T +(case CDEV_TIMEOUT:) 204.17 129.9 T +(printf\050\322Communications error while sending\134n\323\051;) 222.17 118.9 T +(break;) 222.17 107.9 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "68" 76 +%%Page: "69" 77 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 353.86 739 T +(ault Ser) 377.6 739 T +(vice Beha) 408.89 739 T +(vior f) 448.23 739 T +(or Standard Messages) 467.46 739 T +0 10 Q +(69) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +(Figure 54: Def) 180 714 T +(ault beha) 239.26 714 T +(vior of the \322get\323 and \322set\323 messages \050contin) 276.1 714 T +(ued\051) 450.08 714 T +180 81 558 720 C +180 94.38 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +187.3 96 560.87 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +181.33 100.78 555.28 705 R +7 X +V +0 X +N +186.58 103.84 548.7 701.33 R +7 X +V +5 9 Q +0 X +(// ******* No data or bad data passed with message ********) 222.58 695.33 T +(case CDEV_INVALIDARG:) 222.58 684.33 T +(case CDEV_OUTOFRANGE:) 222.58 673.33 T +(case CDEV_NOTFOUND:) 222.58 662.33 T +(case CDEV_CONVERT:) 222.58 651.33 T +(printf\050\322Bad or missing value passed in message\134n\323\051;) 240.58 640.33 T +(break;) 240.58 629.33 T +(// ******************** Generic Error *********************) 222.58 607.33 T +(case CDEV_ERROR:) 222.58 596.33 T +(case default:) 222.58 585.33 T +(printf\050\322Unable to send message\134n\323\051;) 240.58 574.33 T +(break;) 240.58 563.33 T +(}) 222.58 552.33 T +(}) 204.58 541.33 T +(void main\050\051) 186.58 519.33 T +({) 204.58 508.33 T +(cdevRequestObject * req1, *req2;) 204.58 497.33 T +(cdevData ctx;) 204.58 486.33 T +(cdevData output, input;) 204.58 475.33 T +(double val;) 204.58 464.33 T +(int errorCode = CDEV_SUCCESS;) 204.58 453.33 T +(// ***********************************************************) 204.58 431.33 T +(// * Obtain a pointer to the cdevRequestObject for the) 204.58 420.33 T +(// * \322get bdl\323 message on device \322MQB1S01\323.) 204.58 409.33 T +(// ***********************************************************) 204.58 398.33 T +(req1 = cdevRequestObject::attachPtr\050\322MQB1S01\323, \322get bdl\323\051;) 204.58 387.33 T +(// ***********************************************************) 204.58 365.33 T +(// * Place a non-zero value in the properties value, status,) 204.58 354.33 T +(// * severity.) 204.58 343.33 T +(// ***********************************************************) 204.58 332.33 T +(ctx.set\050\322value\323, 1\051;) 204.58 321.33 T +(ctx.set\050\322status\323, 1\051;) 204.58 310.33 T +(ctx.set\050\322severity\323, 1\051;) 204.58 299.33 T +(// ***********************************************************) 204.58 277.33 T +(// * Set the context of the cdevRequestObject.) 204.58 266.33 T +(// ***********************************************************) 204.58 255.33 T +(req1->setContext\050ctx\051;) 204.58 244.33 T +(// ***********************************************************) 204.58 222.33 T +(// * Submit the message to the device and test the return) 204.58 211.33 T +(// * value to ensure that the message was processed correctly) 204.58 200.33 T +(// ***********************************************************) 204.58 189.33 T +(if\050\050errorCode=req1->send\050NULL, &output\051\051==CDEV_SUCCESS\051) 204.58 178.33 T +({) 222.58 167.33 T +(// ********************************************************) 222.58 156.33 T +(// * Message was transmitted and processed successfuly.) 222.58 145.33 T +(// ********************************************************) 222.58 134.33 T +(char stat[50], sev[255];) 222.58 123.33 T +(output.get\050\322value\323, &val\051;) 222.58 112.33 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "69" 77 +%%Page: "70" 78 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 54 739 T +(ault Ser) 77.74 739 T +(vice Beha) 109.03 739 T +(vior f) 148.37 739 T +(or Standard Messages) 167.6 739 T +0 10 Q +(70) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Figure 54: Def) 162 714 T +(ault beha) 221.26 714 T +(vior of the \322get\323 and \322set\323 messages) 258.1 714 T +2 10 Q +(\322monitorOn\323) 54 308.48 T +(Messa) 54 296.48 T +(g) 84.47 296.48 T +(e) 90.68 296.48 T +0 F +3.52 (The) 162 308.48 P +4 F +3.52 (\322monitorOn\323) 185.52 308.48 P +0 F +3.52 ( v) 238.87 308.48 P +3.52 (erb can be joined with an) 249.91 308.48 P +3.52 (y) 378.51 308.48 P +4 F +3.52 (attr) 389.8 308.48 P +3.52 (ib) 404.4 308.48 P +3.52 (ute) 411.98 308.48 P +0 F +3.52 ( of a de) 425.88 308.48 P +3.52 (vice to f) 469.48 308.48 P +3.52 (or) 510.67 308.48 P +3.52 (m a) 519.82 308.48 P +-0.02 (\322) 162 296.48 P +4 F +-0.02 (monitorOn) 165.33 296.48 P +0 F +-0.02 (\323 message) 212.01 296.48 P +-0.02 (. This message is tells the cde) 258.52 296.48 P +-0.02 (vDe) 392.02 296.48 P +-0.02 (vice that each time one of the) 409.5 296.48 P +0.61 (monitored) 162 284.48 P +4 F +0.61 (proper) 209.85 284.48 P +0.61 (ties) 239.15 284.48 P +0 F +0.61 ( changes) 254.71 284.48 P +0.61 (, it should call the user speci\336ed callbac) 295.74 284.48 P +0.61 (k function with) 475.42 284.48 P +6.26 (the updated v) 162 272.47 P +6.26 (alue) 234.87 272.47 P +6.26 (. This message should alw) 253.62 272.47 P +6.26 (a) 396.32 272.47 P +6.26 (ys be submitted using the) 401.58 272.47 P +2 F +1.13 (sendCallbac) 162 260.47 P +1.13 (k) 220.71 260.47 P +0 F +1.13 (method of the cde) 230.18 260.47 P +1.13 (vDe) 313.32 260.47 P +1.13 (vice or cde) 330.8 260.47 P +1.13 (vRequestObject in order to pro) 381.12 260.47 P +1.13 (vide) 521.66 260.47 P +(the address of the callbac) 162 248.47 T +(k function.) 275.75 248.47 T +(The f) 162 231.47 T +(ollo) 184.49 231.47 T +(wing steps should be e) 199.9 231.47 T +(x) 301.32 231.47 T +(ecuted in order to submit a) 306.02 231.47 T +4 F +(\322monitorOn\323) 427.19 231.47 T +0 F +( message) 480.53 231.47 T +(.) 523.73 231.47 T +(1.) 162 214.47 T +(Obtain a pointer to the) 180 214.47 T +4 F +(cde) 281.73 214.47 T +(vDe) 297.55 214.47 T +(vice) 315.03 214.47 T +0 F +( object f) 332.81 214.47 T +(or the de) 367.53 214.47 T +(vice that y) 406.7 214.47 T +(ou wish to address) 451.52 214.47 T +(.) 534.74 214.47 T +(2.) 162 190.47 T +(Create a message str) 180 190.47 T +(ing b) 275.74 190.47 T +(y concatenating the) 297.22 190.47 T +4 F +(attr) 386.72 190.47 T +(ib) 401.32 190.47 T +(ute) 408.9 190.47 T +0 F +(that y) 425.58 190.47 T +(ou wish to address) 449.84 190.47 T +-0.38 (to the) 180 178.47 P +4 F +-0.38 (\322monitorOn\323) 207.04 178.47 P +0 F +-0.38 ( v) 260.38 178.47 P +-0.38 (erb) 267.53 178.47 P +-0.38 (. F) 281.58 178.47 P +-0.38 (or instance) 292.57 178.47 P +-0.38 (, to monitor a proper) 340.95 178.47 P +-0.38 (ty of the) 429.86 178.47 P +4 F +-0.38 (bdl) 467.08 178.47 P +0 F +-0.38 ( attr) 480.42 178.47 P +-0.38 (ib) 497.42 178.47 P +-0.38 (ute of a) 505 178.47 P +(de) 180 166.47 T +(vice) 190.82 166.47 T +(, the message str) 208.45 166.47 T +(ing should be:) 285.3 166.47 T +3 F +(\322monitorOn bdl\323) 350.34 166.47 T +0 F +(.) 429.23 166.47 T +(3.) 162 142.47 T +(Optionally) 180 142.47 T +(, use the cde) 223.46 142.47 T +(vDe) 280.42 142.47 T +(vice object created in step 1 and the message str) 297.9 142.47 T +(ing) 515.38 142.47 T +(created in step 2 to obtain a pointer to a) 180 130.47 T +4 F +(cde) 359 130.47 T +(vRequestObject) 374.82 130.47 T +0 F +(object.) 448.74 130.47 T +(4.) 162 106.47 T +-0.41 (Set the) 180 106.47 P +4 F +-0.41 (conte) 213.65 106.47 P +-0.41 (xt) 237.81 106.47 P +0 F +-0.41 (of the cde) 247.96 106.47 P +-0.41 (vDe) 290.75 106.47 P +-0.41 (vice or cde) 308.23 106.47 P +-0.41 (vRequestObject to indicate the) 355.46 106.47 P +4 F +-0.41 (proper) 492.77 106.47 P +-0.41 (ties) 522.07 106.47 P +0 F +(that y) 180 94.47 T +(ou wish to monitor) 204.26 94.47 T +(, and the) 284.9 94.47 T +4 F +(proper) 326.6 94.47 T +(ties) 355.9 94.47 T +0 F +( y) 371.46 94.47 T +(ou wish to receiv) 379.04 94.47 T +(e when a change) 453.26 94.47 T +162 334.14 540 720 C +162 334.14 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.05 339.93 537.45 699.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.08 344.83 536.04 705 R +7 X +V +0 X +N +167.33 346.93 529.45 701.33 R +7 X +V +5 9 Q +0 X +(output.get\050\322status\323, stat, 50\051;) 203.33 695.33 T +(output.get\050\322severity\323, sev, 50\051;) 203.33 684.33 T +(printf\050\322Val:%f, status:%s, severity:%s\323, val, stat, sev\051;) 203.33 673.33 T +(}) 203.33 662.33 T +(else printError\050errorCode\051;) 185.33 651.33 T +(// ***********************************************************) 185.33 629.33 T +(// * Obtain a pointer to the cdevRequestObject for the) 185.33 618.33 T +(// * \322set bdl\323 message on device \322MQB1S02\323.) 185.33 607.33 T +(// ***********************************************************) 185.33 596.33 T +(req2 = cdevRequestObject::attachPtr\050\322MQB1S02\323, \322set bdl\323\051;) 185.33 585.33 T +(// ***********************************************************) 185.33 563.33 T +(// * Insert the new value into the input cdevData object.) 185.33 552.33 T +(// ***********************************************************) 185.33 541.33 T +(input.insert\050\322value\323, value\051;) 185.33 530.33 T +(// ***********************************************************) 185.33 508.33 T +(// * Submit the message) 185.33 497.33 T +6 F +(\322set bdl\323) 314.93 497.33 T +5 F +(to the device and test) 368.93 497.33 T +(// * the return value to ensure that the message was) 185.33 486.33 T +(// * processed successfully. Note that, by default, the set) 185.33 475.33 T +(// * message does not generate any output.) 185.33 464.33 T +(// ***********************************************************) 185.33 453.33 T +(if\050\050errorCode==req2->send\050&input, NULL\051\051==CDEV_SUCCESS\051) 185.33 442.33 T +({) 203.33 431.33 T +(// ********************************************************) 203.33 420.33 T +(// * Message was transmitted and processed successfuly.) 203.33 409.33 T +(// ********************************************************) 203.33 398.33 T +(printf\050\322Message was transmitted successfully\134n\323\051;) 203.33 387.33 T +(}) 203.33 376.33 T +(else printError\050errorCode\051;) 185.33 365.33 T +(}) 185.33 354.33 T +162 334.14 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "70" 78 +%%Page: "71" 79 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 353.86 739 T +(ault Ser) 377.6 739 T +(vice Beha) 408.89 739 T +(vior f) 448.23 739 T +(or Standard Messages) 467.46 739 T +0 10 Q +(71) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(occurs) 198 713.33 T +(. The conte) 227.3 713.33 T +(xt used b) 277.03 713.33 T +(y the \322) 317.41 713.33 T +4 F +(monitorOn) 345.2 713.33 T +0 F +(\323 message diff) 391.88 713.33 T +(ers from that of the) 454.38 713.33 T +4 F +(\322get\323) 198 701.33 T +0 F +( message in that diff) 218.56 701.33 T +(erent non-z) 307.75 701.33 T +(ero v) 358.18 701.33 T +(alues ha) 380.16 701.33 T +(v) 417.76 701.33 T +(e special meanings) 422.51 701.33 T +(. The) 507.95 701.33 T +(f) 198 689.33 T +(ollo) 200.48 689.33 T +(wing is a list of integer v) 215.89 689.33 T +(alues that should be suppor) 321.79 689.33 T +(ted b) 445.04 689.33 T +(y the conte) 467.08 689.33 T +(xt of a) 515.7 689.33 T +(\322) 198 677.33 T +4 F +(monitorOn) 201.33 677.33 T +0 F +(\323 message) 248.01 677.33 T +(.) 294.54 677.33 T +2 F +(0) 198 653.33 T +0 F +(The v) 332.62 653.33 T +(alue of this proper) 357.38 653.33 T +(ty should ne) 437.82 653.33 T +(v) 491.44 653.33 T +(er be) 496.19 653.33 T +(retur) 333.12 641.33 T +(ned.) 353.93 641.33 T +2 F +(1) 198 617.33 T +0 F +(This proper) 332.62 617.33 T +(ty should not be monitored, b) 383.59 617.33 T +(ut it) 512.35 617.33 T +(should be retur) 333.12 605.33 T +(ned as conte) 400.07 605.33 T +(xt when a monitored) 457.03 605.33 T +(v) 333.12 593.33 T +(alue changes; e) 337.87 593.33 T +(.g. a time stamp) 408.32 593.33 T +(.) 479.11 593.33 T +2 F +(2) 198 569.33 T +0 F +(Monitor this proper) 332.62 569.33 T +(ty and call the callbac) 416.38 569.33 T +(k function) 511.78 569.33 T +-0.41 (when it changes) 333.12 557.33 P +-0.41 (, ho) 404.4 557.33 P +-0.41 (w) 420.52 557.33 P +-0.41 (e) 427.64 557.33 P +-0.41 (v) 432.9 557.33 P +-0.41 (er) 437.65 557.33 P +-0.41 (, retur) 446.04 557.33 P +-0.41 (n only this proper) 471.99 557.33 P +-0.41 (ty) 547.85 557.33 P +(in the resultant cde) 333.12 545.33 T +(vData object.) 417.31 545.33 T +2 F +(3) 198 521.33 T +0 F +(Monitor this proper) 332.62 521.33 T +(ty and call the) 416.38 521.33 T +( callbac) 478.08 521.33 T +(k function) 511.78 521.33 T +(when it changes and include the v) 333.12 509.33 T +(alue of all) 483.51 509.33 T +(proper) 333.12 497.33 T +(ties whose conte) 362.42 497.33 T +(xt is 1 in the resultant) 436.6 497.33 T +(cde) 333.12 485.33 T +(vData object.) 348.94 485.33 T +(5.) 180 461.33 T +(Create a) 198 461.33 T +4 F +(cde) 239.13 461.33 T +(vCallbac) 254.95 461.33 T +(k) 293.09 461.33 T +0 F +( object that contains the address of the cde) 298.09 461.33 T +(vCallbac) 488.46 461.33 T +(k) 526.6 461.33 T +(function and a v) 198 449.33 T +(oid pointer to an) 268.35 449.33 T +(y user argument that should be pro) 339.91 449.33 T +(vided to the) 494.84 449.33 T +(callbac) 198 437.33 T +(k function.) 228.92 437.33 T +(6.) 180 413.33 T +(Use the) 198 413.33 T +3 F +(sendCallbac) 235.24 413.33 T +(k) 293.95 413.33 T +0 F +( message to submit the message to the de) 299.51 413.33 T +(vice) 487.64 413.33 T +(.) 505.27 413.33 T +(7.) 180 389.33 T +-0.15 (Ev) 198 389.33 P +-0.15 (aluate the retur) 209.42 389.33 P +-0.15 (n v) 276.64 389.33 P +-0.15 (alue from the speci\336c) 289.58 389.33 P +3 F +-0.15 (sendCallbac) 386.25 389.33 P +-0.15 (k) 444.96 389.33 P +0 F +-0.15 (command to deter) 453.15 389.33 P +-0.15 (mine) 533.7 389.33 P +(if the message w) 198 377.33 T +(as tr) 272.88 377.33 T +(ansmitted successful. An) 292.23 377.33 T +(y v) 402.68 377.33 T +(alue other than) 415.21 377.33 T +3 F +(CDEV_SUCCESS) 198 365.33 T +0 F +(indicates that the message w) 282.46 365.33 T +(as not tr) 411.26 365.33 T +(ansmitted successfully) 447.29 365.33 T +(.) 546.32 365.33 T +(8.) 180 341.33 T +(Monitor the status retur) 198 341.33 T +(ned to the) 301.07 341.33 T +4 F +(cde) 348.33 341.33 T +(vCallbac) 364.15 341.33 T +(kFunction) 402.29 341.33 T +0 F +(to deter) 448.42 341.33 T +(mine if the) 482.58 341.33 T +(callbac) 198 329.33 T +(k is oper) 228.92 329.33 T +(ating correctly) 266.61 329.33 T +(. An) 327.85 329.33 T +(y of the f) 345.49 329.33 T +(ollo) 383.55 329.33 T +(wing v) 398.96 329.33 T +(alues ma) 427.05 329.33 T +(y be retur) 467.32 329.33 T +(ned in the) 509.81 329.33 T +4 F +(status) 198 317.33 T +0 F +( par) 224.68 317.33 T +(ameter) 241.81 317.33 T +(.) 272.43 317.33 T +2 F +(CDEV_SUCCESS:) 198 293.33 T +0 F +2.07 (The v) 344.29 293.33 P +2.07 (alue has changed and the ne) 371.11 293.33 P +2.07 (w v) 510.22 293.33 P +2.07 (alue is) 527.03 293.33 P +0.31 (stored in the cde) 344.43 281.33 P +0.31 (vData par) 418.99 281.33 P +0.31 (ameter) 462.55 281.33 P +0.31 (. This status is) 493.17 281.33 P +1.6 (also gener) 344.43 269.33 P +1.6 (ated when the monitorOn command) 392.63 269.33 P +(is initially issued.) 344.43 257.33 T +2 F +(CDEV_DISCONNECTED:) 198 240.33 T +0 F +4.32 (The connection has been lost betw) 344.29 240.33 P +4.32 (een the) 520.32 240.33 P +(application and the ser) 344.43 228.33 T +(v) 445.34 228.33 T +(er) 450.09 228.33 T +(.) 458.48 228.33 T +2 F +(CDEV_RECONNECTED:) 198 211.33 T +0 F +0.24 (The connection betw) 344.29 211.33 P +0.24 (een the application and the) 436.95 211.33 P +0.23 (ser) 344.43 199.33 P +0.23 (v) 358.62 199.33 P +0.23 (er has been re-estab) 363.37 199.33 P +0.23 (lished and the updated) 456.13 199.33 P +(v) 344.43 187.33 T +(alue is a) 349.18 187.33 T +(v) 386.22 187.33 T +(ailab) 390.97 187.33 T +(le in the cde) 411.89 187.33 T +(vData par) 465.51 187.33 T +(ameter) 508.76 187.33 T +(.) 539.38 187.33 T +2 F +(CDEV_ERR) 198 170.33 T +(OR:) 252.25 170.33 T +0 F +(The message w) 344.29 170.33 T +(as not processed successfully) 414.72 170.33 T +(.) 546.55 170.33 T +2 F +(CDEV_INV) 198 153.33 T +(ALIDOBJ:) 247.21 153.33 T +0 F +(In) 344.29 153.33 T +(v) 352.43 153.33 T +(alid cde) 357.18 153.33 T +(v request object used.) 391.34 153.33 T +2 F +(CDEV_INV) 198 136.33 T +(ALID) 247.21 136.33 T +(ARG:) 270.14 136.33 T +0 F +(In) 344.29 136.33 T +(v) 352.43 136.33 T +(alid argument passed to cde) 357.18 136.33 T +(v call.) 482.5 136.33 T +2 F +(CDEV_INV) 198 119.33 T +(ALIDSVC:) 247.21 119.33 T +0 F +(Wrong ser) 344.29 119.33 T +(vice dur) 390.71 119.33 T +(ing dynamic loading.) 425.87 119.33 T +2 F +(CDEV_NO) 198 102.33 T +(TCONNECTED:) 245.94 102.33 T +0 F +(Not connected to lo) 344.29 102.33 T +(w le) 430.3 102.33 T +(v) 447.78 102.33 T +(el netw) 452.53 102.33 T +(or) 484.11 102.33 T +(k ser) 493.15 102.33 T +(vice) 515.12 102.33 T +(.) 532.75 102.33 T +2 F +(CDEV_IOF) 198 85.33 T +(AILED:) 247.21 85.33 T +0 F +(Lo) 344.29 85.33 T +(w le) 355.26 85.33 T +(v) 372.74 85.33 T +(el netw) 377.49 85.33 T +(or) 409.07 85.33 T +(k ser) 418.11 85.33 T +(vice IO f) 440.08 85.33 T +(ailed.) 476.46 85.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "71" 79 +%%Page: "72" 80 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 54 739 T +(ault Ser) 77.74 739 T +(vice Beha) 109.03 739 T +(vior f) 148.37 739 T +(or Standard Messages) 167.6 739 T +0 10 Q +(72) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(CDEV_CONFLICT) 180 713.33 T +(:) 263.49 713.33 T +0 F +(Con\337icts of data types or tags) 326.29 713.33 T +(.) 457.87 713.33 T +2 F +(CDEV_NO) 180 696.33 T +(TFOUND:) 227.94 696.33 T +0 F +(Cannot \336nd speci\336ed data in cde) 326.29 696.33 T +(vData.) 471.07 696.33 T +2 F +(CDEV_TIMEOUT) 180 679.33 T +(:) 257.94 679.33 T +0 F +(Time out.) 326.29 679.33 T +2 F +(CDEV_CONVER) 180 662.33 T +(T) 255.92 662.33 T +(:) 261.63 662.33 T +0 F +(cde) 326.29 662.33 T +(vData con) 342.11 662.33 T +(v) 386.93 662.33 T +(ersion error) 391.68 662.33 T +(.) 442.3 662.33 T +2 F +(CDEV_OUT) 180 645.33 T +(OFRANGE:) 234.05 645.33 T +0 F +(V) 326.29 645.33 T +(alue out of r) 332.26 645.33 T +(ange f) 384.97 645.33 T +(or de) 412.47 645.33 T +(vice attr) 434.96 645.33 T +(ib) 470.12 645.33 T +(ute) 477.7 645.33 T +(.) 491.45 645.33 T +2 F +(CDEV_NO) 180 628.33 T +(A) 227.84 628.33 T +(CCESS:) 234.66 628.33 T +0 F +(Insuf\336cient access to perf) 326.29 628.33 T +(or) 438.82 628.33 T +(m request.) 447.96 628.33 T +2 F +(CDEV_A) 180 611.33 T +(CCESSCHANGED:) 220.16 611.33 T +0 F +(Change in access per) 326.29 611.33 T +(mission of de) 423.25 611.33 T +(vice) 481.86 611.33 T +(.) 499.49 611.33 T +(9.) 162 594.33 T +(Because the monitorOn command is a single message that ma) 180 594.33 T +(y gener) 458.15 594.33 T +(ate man) 491.4 594.33 T +(y) 527.38 594.33 T +(responses) 180 582.33 T +(, the de) 225.98 582.33 T +(v) 259.04 582.33 T +(eloper ma) 263.79 582.33 T +(y ha) 307.95 582.33 T +(v) 326.65 582.33 T +(e dif\336culty in deter) 331.4 582.33 T +(mining when the last reply) 412.24 582.33 T +(has been receiv) 180 570.33 T +(ed. In order to accomodate this) 250.34 570.33 T +(, the de) 390.82 570.33 T +(v) 423.88 570.33 T +(eloper ma) 428.63 570.33 T +(y call the) 472.79 570.33 T +(cde) 180 558.33 T +(vCallbac) 195.82 558.33 T +(k::isT) 233.96 558.33 T +(r) 256.65 558.33 T +(ansactionDone\050\051 method to deter) 259.88 558.33 T +(mine if the callbac) 406.31 558.33 T +(k that is) 486.14 558.33 T +(being processed is the last one that is associated with that request. The ser) 180 546.33 T +(vice) 516.58 546.33 T +-0.48 (de) 180 534.33 P +-0.48 (v) 190.82 534.33 P +-0.48 (eloper is e) 195.57 534.33 P +-0.48 (xpected to use the cde) 240.44 534.33 P +-0.48 (vCallbac) 338.83 534.33 P +-0.48 (k::\336reCallbac) 376.97 534.33 P +-0.48 (k method to ensure that) 434.56 534.33 P +(this par) 180 522.33 T +(ameter is set to the proper v) 212.69 522.33 T +(alue) 336.94 522.33 T +(.) 355.69 522.33 T +2 F +(\322monitorOff) 54 493.33 T +(\323) 110.96 493.33 T +(Messa) 54 481.33 T +(g) 84.47 481.33 T +(e) 90.68 481.33 T +0 F +3.47 (The) 162 493.33 P +4 F +3.47 (\322monitorOff) 185.48 493.33 P +3.47 (\323) 236.09 493.33 P +0 F +3.47 ( v) 239.42 493.33 P +3.47 (erb can be joined with an) 250.42 493.33 P +3.47 (y) 378.8 493.33 P +4 F +3.47 (attr) 390.06 493.33 P +3.47 (ib) 404.66 493.33 P +3.47 (ute) 412.24 493.33 P +0 F +3.47 ( of a de) 426.14 493.33 P +3.47 (vice to f) 469.61 493.33 P +3.47 (or) 510.72 493.33 P +3.47 (m a) 519.86 493.33 P +4.44 (\322) 162 481.33 P +4 F +4.44 (monitorOff) 165.33 481.33 P +0 F +4.44 (\323 message) 212.61 481.33 P +4.44 (. This message is tells the cde) 263.58 481.33 P +4.44 (vDe) 423.85 481.33 P +4.44 (vice to deactiv) 441.33 481.33 P +4.44 (ate a) 513.32 481.33 P +(monitorOn command that w) 162 469.33 T +(as pre) 284.67 469.33 T +(viously set on one or more of its attr) 312.16 469.33 T +(ib) 470.71 469.33 T +(utes) 478.29 469.33 T +(.) 497.04 469.33 T +1.5 (This message should alw) 162 452.33 P +1.5 (a) 278.6 452.33 P +1.5 (ys be called using the) 283.86 452.33 P +4 F +1.5 (sendCallbac) 390.27 452.33 P +1.5 (k) 445.09 452.33 P +0 F +1.5 ( method in order to) 450.09 452.33 P +(specify the address of the callbac) 162 440.33 T +(k function that w) 309.65 440.33 T +(as used in creating the monitor) 381.76 440.33 T +(.) 517.99 440.33 T +(The ser) 162 423.33 T +(vice chec) 196.2 423.33 T +(ks the f) 237.68 423.33 T +(ollo) 269.62 423.33 T +(wing things to deter) 285.03 423.33 T +(mine which monitor is to be remo) 371.99 423.33 T +(v) 518.55 423.33 T +(ed.) 523.3 423.33 T +2 F +(de) 180 406.33 T +(vice) 191.52 406.33 T +0 F +1.94 (The ser) 326.29 406.33 P +1.94 (vice will locate all activ) 362.43 406.33 P +1.94 (e monitors that) 469.97 406.33 P +(ha) 326.43 394.33 T +(v) 337.35 394.33 T +(e been placed on the speci\336ed de) 342.1 394.33 T +(vice) 491.34 394.33 T +(.) 508.97 394.33 T +2 F +(attrib) 180 377.33 T +(ute) 204.8 377.33 T +0 F +0.82 (F) 326.29 377.33 P +0.82 (rom the list of obtained abo) 331.95 377.33 P +0.82 (v) 456.51 377.33 P +0.82 (e) 461.26 377.33 P +0.82 (, the ser) 466.67 377.33 P +0.82 (vice will) 504.74 377.33 P +5.25 (locate all activ) 326.43 365.33 P +5.25 (e monitors on the speci\336ed) 399.49 365.33 P +(attr) 326.43 353.33 T +(ib) 341.03 353.33 T +(ute) 348.61 353.33 T +(.) 362.36 353.33 T +2 F +(function) 180 336.33 T +0 F +2.53 (F) 326.29 336.33 P +2.53 (rom the list obtained abo) 331.95 336.33 P +2.53 (v) 451.4 336.33 P +2.53 (e) 456.15 336.33 P +2.53 (, the ser) 461.56 336.33 P +2.53 (vice will) 503.04 336.33 P +0.28 (locate all activ) 326.43 324.33 P +0.28 (e monitors that ha) 389.54 324.33 P +0.28 (v) 470.21 324.33 P +0.28 (e the speci\336ed) 474.96 324.33 P +0.98 (callbac) 326.43 312.33 P +0.98 (k function. If this v) 357.35 312.33 P +0.98 (alue is NULL, then all) 441.05 312.33 P +(elements from the pre) 326.43 300.33 T +(vious list will be remo) 423.39 300.33 T +(v) 517.7 300.33 T +(ed.) 522.45 300.33 T +2 F +(userar) 180 283.33 T +(g) 210.42 283.33 T +0 F +2.53 (F) 326.29 283.33 P +2.53 (rom the list obtained abo) 331.95 283.33 P +2.53 (v) 451.4 283.33 P +2.53 (e) 456.15 283.33 P +2.53 (, the ser) 461.56 283.33 P +2.53 (vice will) 503.04 283.33 P +2.52 (locate and remo) 326.43 271.33 P +2.52 (v) 403.03 271.33 P +2.52 (e all monitors that ha) 407.78 271.33 P +2.52 (v) 510.49 271.33 P +2.52 (e the) 515.24 271.33 P +0.33 (same user argument. If this v) 326.43 259.33 P +0.33 (alue is NULL, then) 456.76 259.33 P +4.99 (all elements from the pre) 326.43 247.33 P +4.99 (vious list will be) 456.13 247.33 P +(remo) 326.43 235.33 T +(v) 349.06 235.33 T +(ed.) 353.81 235.33 T +(The f) 162 218.33 T +(ollo) 184.49 218.33 T +(wing steps should be e) 199.9 218.33 T +(x) 301.32 218.33 T +(ecuted in order to submit a) 306.02 218.33 T +4 F +(\322monitorOff) 427.19 218.33 T +(\323) 477.8 218.33 T +0 F +( message) 481.13 218.33 T +(.) 524.33 218.33 T +(1.) 162 201.33 T +(Obtain a pointer to the) 180 201.33 T +4 F +(cde) 281.73 201.33 T +(vDe) 297.55 201.33 T +(vice) 315.03 201.33 T +0 F +( object f) 332.81 201.33 T +(or the de) 367.53 201.33 T +(vice that y) 406.7 201.33 T +(ou wish to address) 451.52 201.33 T +(.) 534.74 201.33 T +(2.) 162 177.33 T +(Create a message str) 180 177.33 T +(ing b) 275.74 177.33 T +(y concatenating the) 297.22 177.33 T +4 F +(attr) 386.72 177.33 T +(ib) 401.32 177.33 T +(ute) 408.9 177.33 T +0 F +(that y) 425.58 177.33 T +(ou wish to address) 449.84 177.33 T +-0.42 (to the) 180 165.33 P +4 F +-0.42 (\322monitorOff) 206.96 165.33 P +-0.42 (\323) 257.57 165.33 P +0 F +-0.42 ( v) 260.9 165.33 P +-0.42 (erb) 268.02 165.33 P +-0.42 (. F) 282.07 165.33 P +-0.42 (or instance) 293.02 165.33 P +-0.42 (, to monitor a proper) 341.36 165.33 P +-0.42 (ty of the) 430.13 165.33 P +4 F +-0.42 (bdl) 467.23 165.33 P +0 F +-0.42 ( attr) 480.57 165.33 P +-0.42 (ib) 497.53 165.33 P +-0.42 (ute of a) 505.11 165.33 P +(de) 180 153.33 T +(vice) 190.82 153.33 T +(, the message str) 208.45 153.33 T +(ing should be:) 285.3 153.33 T +3 F +(\322monitorOn bdl\323) 350.34 153.33 T +0 F +(.) 429.23 153.33 T +(3.) 162 129.33 T +(Optionally) 180 129.33 T +(, use the cde) 223.46 129.33 T +(vDe) 280.42 129.33 T +(vice object created in step 1 and the message str) 297.9 129.33 T +(ing) 515.38 129.33 T +(created in step 2 to obtain a pointer to a) 180 117.33 T +4 F +(cde) 359 117.33 T +(vRequestObject) 374.82 117.33 T +0 F +(object.) 448.74 117.33 T +(4.) 162 93.33 T +(Create a) 180 93.33 T +4 F +(cde) 221.13 93.33 T +(vCallbac) 236.95 93.33 T +(k) 275.09 93.33 T +0 F +( object that contains the address of the cde) 280.09 93.33 T +(vCallbac) 470.46 93.33 T +(k) 508.6 93.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "72" 80 +%%Page: "73" 81 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 353.86 739 T +(ault Ser) 377.6 739 T +(vice Beha) 408.89 739 T +(vior f) 448.23 739 T +(or Standard Messages) 467.46 739 T +0 10 Q +(73) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.39 (function and a v) 198 713.33 P +-0.39 (oid pointer to the user argument that w) 267.17 713.33 P +-0.39 (as or) 435.47 713.33 P +-0.39 (iginally pro) 457.45 713.33 P +-0.39 (vided to the) 504.7 713.33 P +(monitorOn message) 198 701.33 T +(.) 287.88 701.33 T +(5.) 180 677.33 T +(Use the) 198 677.33 T +3 F +(sendCallbac) 235.24 677.33 T +(k) 293.95 677.33 T +0 F +( message to submit the message to the de) 299.51 677.33 T +(vice) 487.64 677.33 T +(.) 505.27 677.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "73" 81 +%%Page: "74" 82 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 54 739 T +(ault Ser) 77.74 739 T +(vice Beha) 109.03 739 T +(vior f) 148.37 739 T +(or Standard Messages) 167.6 739 T +0 10 Q +(74) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +2.12 (The f) 162 713.33 P +2.12 (ollo) 186.6 713.33 P +2.12 (wing e) 202.01 713.33 P +2.12 (xample illustr) 232.73 713.33 P +2.12 (ates ho) 293.09 713.33 P +2.12 (w to use the) 327.85 713.33 P +4 F +2.12 (\322monitorOn\323) 393.01 713.33 P +0 F +2.12 ( and) 446.35 713.33 P +4 F +2.12 (\322monitorOff) 472.82 713.33 P +2.12 (\323) 523.43 713.33 P +0 F +2.12 ( to) 526.76 713.33 P +0.93 (install and remo) 162 701.33 P +0.93 (v) 234.28 701.33 P +0.93 (e monitors) 239.03 701.33 P +0.93 (. This e) 286.49 701.33 P +0.93 (xample also demonstr) 324.54 701.33 P +0.93 (ates the to correct w) 424.1 701.33 P +0.93 (a) 517.69 701.33 P +0.93 (y to) 522.95 701.33 P +(utiliz) 162 689.33 T +(e the cde) 181.85 689.33 T +(vCallbac) 222.69 689.33 T +(k function.) 260.83 689.33 T +4 9 Q +(Figure 55: Def) 162 656 T +(ault beha) 221.26 656 T +(vior of the \322monitorOn\323 and \322monitorOff) 258.1 656 T +(\323 messages) 413.69 656 T +162 81 540 720 C +162 82.38 540 653 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.46 84.66 542.04 641.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.5 90.29 536.45 647 R +7 X +V +0 X +N +167.75 94.17 529.86 643.33 R +7 X +V +5 9 Q +0 X +(#include ) 167.75 637.33 T +(#include ) 167.75 626.33 T +(#include ) 167.75 615.33 T +(#include ) 167.75 604.33 T +(#include ) 167.75 593.33 T +(// ****************************************************************) 167.75 571.33 T +(// * This is the callback function that will be executed each time) 167.75 560.33 T +(// * one of my monitored values changes.) 167.75 549.33 T +(// ****************************************************************) 167.75 538.33 T +(void callback \050int status, void * userarg,) 167.75 527.33 T +( cdevRequestObject & req, cdevData & data\051) 239.75 516.33 T +({) 185.75 505.33 T +(switch\050status\051) 185.75 494.33 T +({) 203.75 483.33 T +(// *********************************************************) 203.75 472.33 T +(// * If I receive one of these message then I know that) 203.75 461.33 T +(// * updated data is available in the cdevData object.) 203.75 450.33 T +(// *********************************************************) 203.75 439.33 T +(case CDEV_SUCCESS:) 203.75 428.33 T +(case CDEV_RECONNECTED:) 203.75 417.33 T +(// ******************************************************) 221.75 406.33 T +(// * I will call the getType method to determine if the) 221.75 395.33 T +(// * value attribuite is present in the cdevData object.) 221.75 384.33 T +(// * If it is, then I will known that it is responsible) 221.75 373.33 T +(// * for triggering this callback.) 221.75 362.33 T +(// ******************************************************) 221.75 351.33 T +(if\050data.getType\050\322value\323\051!=CDEV_INVALID\051) 221.75 340.33 T +({) 239.75 329.33 T +(// **************************************************) 239.75 318.33 T +(// * I have specified that I wanted status and) 239.75 307.33 T +(// * severity to be returned as context whenever the) 239.75 296.33 T +(// * value property has changed. Therefore, I will) 239.75 285.33 T +(// * output all of these properties.) 239.75 274.33 T +(// **************************************************) 239.75 263.33 T +(double * valPtr;) 239.75 252.33 T +(char * statPtr;) 239.75 241.33 T +(char * sevPtr;) 239.75 230.33 T +(data.find\050\322value\323, \050void *&\051valPtr\051;) 239.75 219.33 T +(data.find\050\322status\323, \050void *&\051statPtr\051;) 239.75 208.33 T +(data.find\050\322severity\323, \050void *&\051sevPtr\051;) 239.75 197.33 T +(printf\050\322Val:%f, status:%s, severity:%s\323,) 239.75 186.33 T +(*valPtr, statPtr, sevPtr\051;) 275.75 175.33 T +(}) 239.75 164.33 T +(// ******************************************************) 221.75 153.33 T +(// * I will call the getType method of the cdevData) 221.75 142.33 T +(// * object to determine if the controlHigh property is) 221.75 131.33 T +(// * present. If it is, I will know that it triggered) 221.75 120.33 T +(// * this callback.) 221.75 109.33 T +(// ******************************************************) 221.75 98.33 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "74" 82 +%%Page: "75" 83 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 353.86 739 T +(ault Ser) 377.6 739 T +(vice Beha) 408.89 739 T +(vior f) 448.23 739 T +(or Standard Messages) 467.46 739 T +0 10 Q +(75) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 9 Q +(Figure 55: Def) 180 714 T +(ault beha) 239.26 714 T +(vior of the \322monitorOn\323 and \322monitorOff) 276.1 714 T +(\323 messages \050contin) 431.69 714 T +(ued\051) 507.63 714 T +180 81 558 720 C +180 85.21 558 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +186.46 90.16 560.04 704.57 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +183.83 93.28 552.79 709.17 R +7 X +V +0 X +N +184.08 93.84 546.2 701.33 R +7 X +V +5 9 Q +0 X +(else if\050getType\050\322controlHigh\323\051!=CDEV_INVALID\051) 238.08 695.33 T +({) 256.08 684.33 T +(double * controlPtr;) 256.08 673.33 T +(data.find\050\322controlHigh\323, \050void *&\051 controlPtr\051;) 256.08 662.33 T +(printf\050\322Control High is now %f\134n\323, *controlPtr\051;) 256.08 651.33 T +(}) 256.08 640.33 T +(break;) 220.08 629.33 T +(// *********************************************************) 220.08 607.33 T +(// * This status indicates that the connection has been lost) 220.08 596.33 T +(// * between the application and the server.) 220.08 585.33 T +(// *********************************************************) 220.08 574.33 T +(case CDEV_DISCONNECTED:) 220.08 563.33 T +(fprintf\050stderr, \322Connection lost to server\134n\323\051;) 238.08 552.33 T +(break;) 238.08 541.33 T +(// *********************************************************) 220.08 519.33 T +(// * This status indicates that an error occurred while) 220.08 508.33 T +(// * installing or operating the monitor.) 220.08 497.33 T +(// *********************************************************) 220.08 486.33 T +(case CDEV_ERROR:) 220.08 475.33 T +(fprintf\050stderr, \322Error while monitoring\323\051;) 238.08 464.33 T +(break;) 238.08 453.33 T +(}) 220.08 442.33 T +(}) 202.08 431.33 T +(void main\050\051) 184.08 409.33 T +({) 202.08 398.33 T +(cdevSystem * system;) 202.08 387.33 T +(cdevDevice * dev;) 202.08 376.33 T +(cdevRequestObject * req;) 202.08 365.33 T +(cdevData ctx;) 202.08 354.33 T +(// ***********************************************************) 202.08 332.33 T +(// * Construct a cdevCallback object that has a pointer to the) 202.08 321.33 T +(// * cdevCallback function and a NULL user argument.) 202.08 310.33 T +(// ***********************************************************) 202.08 299.33 T +(cdevCallback cb\050callback, NULL\051;) 202.08 288.33 T +(// ***********************************************************) 202.08 266.33 T +(// * Obtain a pointer to the default cdevSystem in order to) 202.08 255.33 T +(// * accomodate polling.) 202.08 244.33 T +(// ***********************************************************) 202.08 233.33 T +(system = &cdevSystem::defaultSystem\050\051;) 202.08 222.33 T +(// ***********************************************************) 202.08 200.33 T +(// * Obtain a pointer to the cdevDevice MQB1S01) 202.08 189.33 T +(// ***********************************************************) 202.08 178.33 T +(dev = cdevDevice::attachPtr\050\322MQB1S01\323\051;) 202.08 167.33 T +(// ***********************************************************) 202.08 145.33 T +(// * Obtain a pointer to the cdevRequestObject for the) 202.08 134.33 T +(// * \322monitorOff bdl\323 message on device \322MQB1S01\323.) 202.08 123.33 T +(// ***********************************************************) 202.08 112.33 T +(req = dev->getRequestObject\050\322MQB1S01\323, \322monitorOn bdl\323\051;) 202.08 101.33 T +180 81 558 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "75" 83 +%%Page: "76" 84 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 54 739 T +(ault Ser) 77.74 739 T +(vice Beha) 109.03 739 T +(vior f) 148.37 739 T +(or Standard Messages) 167.6 739 T +0 10 Q +(76) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 F +(Figure 55: Def) 162 714 T +(ault beha) 221.26 714 T +(vior of the \322monitorOn\323 and \322monitorOff) 258.1 714 T +(\323 messages \050contin) 413.69 714 T +(ued\051) 489.63 714 T +162 81 540 720 C +162 191.05 540 711 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +168.46 197.66 542.04 702.07 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +0 Z +N +162.5 202.45 536.45 707.5 R +7 X +V +0 X +N +167.75 207.17 529.86 703.83 R +7 X +V +5 9 Q +0 X +(// ###########################################################) 185.75 686.83 T +(// # Setup the context to indicate the data that should be) 185.75 675.83 T +(// # returned whenever one of the values is changed.) 185.75 664.83 T +(// ###########################################################) 185.75 653.83 T +(// ***********************************************************) 185.75 631.83 T +(// * Any time the \322value\323 property changes, I want to receive) 185.75 620.83 T +(// * the \322status\323 and \322severity\323 properties.) 185.75 609.83 T +(// ***********************************************************) 185.75 598.83 T +(ctx.insert\050\322value\323, 3\051;) 185.75 587.83 T +(ctx.insert\050\322status\323, 1\051;) 185.75 576.83 T +(ctx.insert\050\322severity\323, 1\051;) 185.75 565.83 T +(// ***********************************************************) 185.75 543.83 T +(// * Any time the \322controlhigh\323 property changes, I only want) 185.75 532.83 T +(// * to receive its new value.) 185.75 521.83 T +(// ***********************************************************) 185.75 510.83 T +(ctx.insert\050\322controlHigh\323, 2\051;) 185.75 499.83 T +(// ***********************************************************) 185.75 477.83 T +(// * Set the context of the cdevRequestObject to the new) 185.75 466.83 T +(// * context.) 185.75 455.83 T +(// ***********************************************************) 185.75 444.83 T +(req->setContext\050ctx\051;) 185.75 433.83 T +(// ************************************************************) 185.75 411.83 T +(// * Submit the \322monitorOn\323 message using the sendCallback) 185.75 400.83 T +(// * method of the cdevRequestObject.) 185.75 389.83 T +(// ************************************************************) 185.75 378.83 T +(if\050req->sendCallback\050NULL, cb\051==CDEV_SUCCESS\051) 185.75 367.83 T +({) 203.75 356.83 T +(// ********************************************************) 203.75 345.83 T +(// * Pend for 60 second.) 203.75 334.83 T +(// ********************************************************) 203.75 323.83 T +(system->pend\05060.0\051;) 203.75 312.83 T +(// ********************************************************) 203.75 290.83 T +(// * Send a \322monitorOff bdl\323 message to disable the monitor) 203.75 279.83 T +(// * that was just installed.) 203.75 268.83 T +(// ********************************************************) 203.75 257.83 T +(dev->sendCallback\050\322monitorOff bdl\323, NULL, cb\051;) 203.75 246.83 T +(}) 203.75 235.83 T +(else fprintf\050stderr, \322Failed to install monitor\134n\323\051;) 185.75 224.83 T +(}) 185.75 213.83 T +162 81 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "76" 84 +%%Page: "77" 85 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 353.86 739 T +(ault Ser) 377.6 739 T +(vice Beha) 408.89 739 T +(vior f) 448.23 739 T +(or Standard Messages) 467.46 739 T +0 10 Q +(77) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "77" 85 +%%Page: "78" 86 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 54 739 T +(ault Ser) 77.74 739 T +(vice Beha) 109.03 739 T +(vior f) 148.37 739 T +(or Standard Messages) 167.6 739 T +0 10 Q +(78) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "78" 86 +%%Page: "79" 87 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Def) 353.86 739 T +(ault Ser) 377.6 739 T +(vice Beha) 408.89 739 T +(vior f) 448.23 739 T +(or Standard Messages) 467.46 739 T +0 10 Q +(79) 546.88 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "79" 87 +%%Trailer +%%BoundingBox: 0 0 612 792 +%%PageOrder: Ascend +%%Pages: 87 +%%DocumentFonts: Helvetica +%%+ Times-BoldItalic +%%+ Helvetica-Bold +%%+ Helvetica-BoldOblique +%%+ Helvetica-Oblique +%%+ Courier-Bold +%%+ Courier-BoldOblique +%%EOF diff --git a/doc/ps/cdevUtilities.ps b/doc/ps/cdevUtilities.ps new file mode 100755 index 0000000..3dc208f --- /dev/null +++ b/doc/ps/cdevUtilities.ps @@ -0,0 +1,3644 @@ +%!PS-Adobe-3.0 +%%BoundingBox: (atend) +%%Pages: (atend) +%%PageOrder: (atend) +%%DocumentFonts: (atend) +%%Creator: Frame 5.0 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +% +% Frame ps_prolog 5.0, for use with Frame 5.0 products +% This ps_prolog file is Copyright (c) 1986-1995 Frame Technology +% Corporation. All rights reserved. This ps_prolog file may be +% freely copied and distributed in conjunction with documents created +% using FrameMaker, FrameMaker/SGML and FrameViewer as long as this +% copyright notice is preserved. +% +% FrameMaker users specify the proper paper size for each print job in the +% "Print" dialog's "Printer Paper Size" "Width" and "Height~ fields. If the +% printer that the PS file is sent to does not support the requested paper +% size, or if there is no paper tray of the proper size currently installed, +% then the job will not be printed. The following flag, if set to true, will +% cause the job to print on the default paper in such cases. +/FMAllowPaperSizeMismatch false def +% +% Frame products normally print colors as their true color on a color printer +% or as shades of gray, based on luminance, on a black-and white printer. The +% following flag, if set to true, forces all non-white colors to print as pure +% black. This has no effect on bitmap images. +/FMPrintAllColorsAsBlack false def +% +% Frame products can either set their own line screens or use a printer's +% default settings. Three flags below control this separately for no +% separations, spot separations and process separations. If a flag +% is true, then the default printer settings will not be changed. If it is +% false, Frame products will use their own settings from a table based on +% the printer's resolution. +/FMUseDefaultNoSeparationScreen true def +/FMUseDefaultSpotSeparationScreen true def +/FMUseDefaultProcessSeparationScreen false def +% +% For any given PostScript printer resolution, Frame products have two sets of +% screen angles and frequencies for printing process separations, which are +% recomended by Adobe. The following variable chooses the higher frequencies +% when set to true or the lower frequencies when set to false. This is only +% effective if the appropriate FMUseDefault...SeparationScreen flag is false. +/FMUseHighFrequencyScreens true def +% +% The following is a set of predefined optimal frequencies and angles for various +% common dpi settings. This is taken from "Advances in Color Separation Using +% PostScript Software Technology," from Adobe Systems (3/13/89 P.N. LPS 0043) +% and corrolated with information which is in various PPD (4.0) files. +% +% The "dpiranges" figure is the minimum dots per inch device resolution which +% can support this setting. The "low" and "high" values are controlled by the +% setting of the FMUseHighFrequencyScreens flag above. The "TDot" flags control +% the use of the "Yellow Triple Dot" feature whereby the frequency id divided by +% three, but the dot function is "trippled" giving a block of 3x3 dots per cell. +% +% PatFreq is a compromise pattern frequency for ps Level 2 printers which is close +% to the ideal WYSIWYG pattern frequency of 9 repetitions/inch but does not beat +% (too badly) against the screen frequencies of any separations for that DPI. +/dpiranges [ 2540 2400 1693 1270 1200 635 600 0 ] def +/CMLowFreqs [ 100.402 94.8683 89.2289 100.402 94.8683 66.9349 63.2456 47.4342 ] def +/YLowFreqs [ 95.25 90.0 84.65 95.25 90.0 70.5556 66.6667 50.0 ] def +/KLowFreqs [ 89.8026 84.8528 79.8088 89.8026 84.8528 74.8355 70.7107 53.033 ] def +/CLowAngles [ 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 ] def +/MLowAngles [ 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 ] def +/YLowTDot [ true true false true true false false false ] def +/CMHighFreqs [ 133.87 126.491 133.843 108.503 102.523 100.402 94.8683 63.2456 ] def +/YHighFreqs [ 127.0 120.0 126.975 115.455 109.091 95.25 90.0 60.0 ] def +/KHighFreqs [ 119.737 113.137 119.713 128.289 121.218 89.8026 84.8528 63.6395 ] def +/CHighAngles [ 71.5651 71.5651 71.5651 70.0169 70.0169 71.5651 71.5651 71.5651 ] def +/MHighAngles [ 18.4349 18.4349 18.4349 19.9831 19.9831 18.4349 18.4349 18.4349 ] def +/YHighTDot [ false false true false false true true false ] def +/PatFreq [ 10.5833 10.0 9.4055 10.5833 10.0 10.5833 10.0 9.375 ] def +% +% PostScript Level 2 printers contain an "Accurate Screens" feature which can +% improve process separation rendering at the expense of compute time. This +% flag is ignored by PostScript Level 1 printers. +/FMUseAcccurateScreens true def +% +% The following PostScript procedure defines the spot function that Frame +% products will use for process separations. You may un-comment-out one of +% the alternative functions below, or use your own. +% +% Dot function +/FMSpotFunction {abs exch abs 2 copy add 1 gt + {1 sub dup mul exch 1 sub dup mul add 1 sub } + {dup mul exch dup mul add 1 exch sub }ifelse } def +% +% Line function +% /FMSpotFunction { pop } def +% +% Elipse function +% /FMSpotFunction { dup 5 mul 8 div mul exch dup mul exch add +% sqrt 1 exch sub } def +% +% +/FMversion (5.0) def +/fMLevel1 /languagelevel where {pop languagelevel} {1} ifelse 2 lt def +/FMPColor + fMLevel1 { + false + /colorimage where {pop pop true} if + } { + true + } ifelse +def +/FrameDict 400 dict def +systemdict /errordict known not {/errordict 10 dict def + errordict /rangecheck {stop} put} if +% The readline in PS 23.0 doesn't recognize cr's as nl's on AppleTalk +FrameDict /tmprangecheck errordict /rangecheck get put +errordict /rangecheck {FrameDict /bug true put} put +FrameDict /bug false put +mark +% Some PS machines read past the CR, so keep the following 3 lines together! +currentfile 5 string readline +00 +0000000000 +cleartomark +errordict /rangecheck FrameDict /tmprangecheck get put +FrameDict /bug get { + /readline { + /gstring exch def + /gfile exch def + /gindex 0 def + { + gfile read pop + dup 10 eq {exit} if + dup 13 eq {exit} if + gstring exch gindex exch put + /gindex gindex 1 add def + } loop + pop + gstring 0 gindex getinterval true + } bind def + } if +/FMshowpage /showpage load def +/FMquit /quit load def +/FMFAILURE { + dup = flush + FMshowpage + /Helvetica findfont 12 scalefont setfont + 72 200 moveto show + 72 220 moveto show + FMshowpage + FMquit + } def +/FMVERSION { + FMversion ne { + (Frame product version does not match ps_prolog! Check installation;) + (also check ~/fminit and ./fminit for old versions) FMFAILURE + } if + } def +/FMBADEPSF { + (Adobe's PostScript Language Reference Manual, 2nd Edition, section H.2.4) + (says your EPS file is not valid, as it calls X ) + dup dup (X) search pop exch pop exch pop length + 5 -1 roll + putinterval + FMFAILURE + } def +/fmConcatProcs + { + /proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def + newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx +}def +FrameDict begin [ + /ALDsave + /FMdicttop + /FMoptop + /FMpointsize + /FMsaveobject + /b + /bitmapsave + /blut + /bpside + /bs + /bstring + /bwidth + /c + /cf + /cs + /cynu + /depth + /edown + /fh + /fillvals + /fw + /fx + /fy + /g + /gfile + /gindex + /grnt + /gryt + /gstring + /height + /hh + /i + /im + /indx + /is + /k + /kk + /landscape + /lb + /len + /llx + /lly + /m + /magu + /manualfeed + /n + /offbits + /onbits + /organgle + /orgbangle + /orgbfreq + /orgbproc + /orgbxfer + /orgfreq + /orggangle + /orggfreq + /orggproc + /orggxfer + /orgmatrix + /orgproc + /orgrangle + /orgrfreq + /orgrproc + /orgrxfer + /orgxfer + /pagesave + /paperheight + /papersizedict + /paperwidth + /pos + /pwid + /r + /rad + /redt + /sl + /str + /tran + /u + /urx + /ury + /val + /width + /width + /ws + /ww + /x + /x1 + /x2 + /xindex + /xpoint + /xscale + /xx + /y + /y1 + /y2 + /yelu + /yindex + /ypoint + /yscale + /yy +] { 0 def } forall +/FmBD {bind def} bind def +systemdict /pdfmark known { + /fMAcrobat true def + + /FmPD /pdfmark load def + + + /FmPT /show load def + + + currentdistillerparams /CoreDistVersion get 2000 ge { + + + /FmPD2 /pdfmark load def + + + + + + /FmPA { mark exch /Dest exch 5 3 roll + /View [ /XYZ null 6 -2 roll FmDC exch pop null] /DEST FmPD + }FmBD + } { + + /FmPD2 /cleartomark load def + /FmPA {pop pop pop}FmBD + } ifelse +} { + + /fMAcrobat false def + /FmPD /cleartomark load def + /FmPD2 /cleartomark load def + /FmPT /pop load def + /FmPA {pop pop pop}FmBD +} ifelse +/FmDC { + transform fMDefaultMatrix itransform cvi exch cvi exch +}FmBD +/FmBx { + dup 3 index lt {3 1 roll exch} if + 1 index 4 index lt {4 -1 roll 3 1 roll exch 4 1 roll} if +}FmBD +/FMnone 0 def +/FMcyan 1 def +/FMmagenta 2 def +/FMyellow 3 def +/FMblack 4 def +/FMcustom 5 def +/fMNegative false def +/FrameSepIs FMnone def +/FrameSepBlack 0 def +/FrameSepYellow 0 def +/FrameSepMagenta 0 def +/FrameSepCyan 0 def +/FrameSepRed 1 def +/FrameSepGreen 1 def +/FrameSepBlue 1 def +/FrameCurGray 1 def +/FrameCurPat null def +/FrameCurColors [ 0 0 0 1 0 0 0 ] def +/FrameColorEpsilon .001 def +/eqepsilon { + sub dup 0 lt {neg} if + FrameColorEpsilon le +} bind def +/FrameCmpColorsCMYK { + 2 copy 0 get exch 0 get eqepsilon { + 2 copy 1 get exch 1 get eqepsilon { + 2 copy 2 get exch 2 get eqepsilon { + 3 get exch 3 get eqepsilon + } {pop pop false} ifelse + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/FrameCmpColorsRGB { + 2 copy 4 get exch 0 get eqepsilon { + 2 copy 5 get exch 1 get eqepsilon { + 6 get exch 2 get eqepsilon + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/RGBtoCMYK { + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 3 copy + 2 copy + le { pop } { exch pop } ifelse + 2 copy + le { pop } { exch pop } ifelse + dup dup dup + 6 1 roll + 4 1 roll + 7 1 roll + sub + 6 1 roll + sub + 5 1 roll + sub + 4 1 roll +} bind def +/CMYKtoRGB { + dup dup 4 -1 roll add + 5 1 roll 3 -1 roll add + 4 1 roll add + 1 exch sub dup 0 lt {pop 0} if 3 1 roll + 1 exch sub dup 0 lt {pop 0} if exch + 1 exch sub dup 0 lt {pop 0} if exch +} bind def +/FrameSepInit { + 1.0 RealSetgray +} bind def +/FrameSetSepColor { + /FrameSepBlue exch def + /FrameSepGreen exch def + /FrameSepRed exch def + /FrameSepBlack exch def + /FrameSepYellow exch def + /FrameSepMagenta exch def + /FrameSepCyan exch def + /FrameSepIs FMcustom def + setCurrentScreen +} bind def +/FrameSetCyan { + /FrameSepBlue 1.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 1.0 def + /FrameSepIs FMcyan def + setCurrentScreen +} bind def + +/FrameSetMagenta { + /FrameSepBlue 1.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 1.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMmagenta def + setCurrentScreen +} bind def + +/FrameSetYellow { + /FrameSepBlue 0.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 1.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMyellow def + setCurrentScreen +} bind def + +/FrameSetBlack { + /FrameSepBlue 0.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 1.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMblack def + setCurrentScreen +} bind def + +/FrameNoSep { + /FrameSepIs FMnone def + setCurrentScreen +} bind def +/FrameSetSepColors { + FrameDict begin + [ exch 1 add 1 roll ] + /FrameSepColors + exch def end + } bind def +/FrameColorInSepListCMYK { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsCMYK + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/FrameColorInSepListRGB { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsRGB + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/RealSetgray /setgray load def +/RealSetrgbcolor /setrgbcolor load def +/RealSethsbcolor /sethsbcolor load def +end +/setgray { + FrameDict begin + FrameSepIs FMnone eq + { RealSetgray } + { + FrameSepIs FMblack eq + { RealSetgray } + { FrameSepIs FMcustom eq + FrameSepRed 0 eq and + FrameSepGreen 0 eq and + FrameSepBlue 0 eq and { + RealSetgray + } { + 1 RealSetgray pop + } ifelse + } ifelse + } ifelse + end +} bind def +/setrgbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetrgbcolor } + { + 3 copy [ 4 1 roll ] + FrameColorInSepListRGB + { + FrameSepBlue eq exch + FrameSepGreen eq and exch + FrameSepRed eq and + { 0 } { 1 } ifelse + } + { + FMPColor { + RealSetrgbcolor + currentcmykcolor + } { + RGBtoCMYK + } ifelse + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end +} bind def +/sethsbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSethsbcolor } + { + RealSethsbcolor + currentrgbcolor + setrgbcolor + } + ifelse + end +} bind def +FrameDict begin +/setcmykcolor where { + pop /RealSetcmykcolor /setcmykcolor load def +} { + /RealSetcmykcolor { + 4 1 roll + 3 { 3 index add 0 max 1 min 1 exch sub 3 1 roll} repeat + RealSetrgbcolor pop + } bind def +} ifelse +userdict /setcmykcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetcmykcolor } + { + 4 copy [ 5 1 roll ] + FrameColorInSepListCMYK + { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + { 0 } { 1 } ifelse + } + { + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end + } bind put +fMLevel1 { + + + + /patScreenDict 7 dict dup begin + <0f1e3c78f0e1c387> [ 45 { pop } {exch pop} .5 2 sqrt] FmBD + <0f87c3e1f0783c1e> [ 135 { pop } {exch pop} .5 2 sqrt] FmBD + [ 0 { pop } dup .5 2 ] FmBD + [ 90 { pop } dup .5 2 ] FmBD + <8142241818244281> [ 45 { 2 copy lt {exch} if pop} dup .75 2 sqrt] FmBD + <03060c183060c081> [ 45 { pop } {exch pop} .875 2 sqrt] FmBD + <8040201008040201> [ 135 { pop } {exch pop} .875 2 sqrt] FmBD + end def +} { + + /patProcDict 5 dict dup begin + <0f1e3c78f0e1c387> { 3 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <0f87c3e1f0783c1e> { 3 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + <8142241818244281> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -1 -1 moveto 9 9 lineto stroke } bind def + <03060c183060c081> { 1 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <8040201008040201> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + end def + /patDict 15 dict dup begin + /PatternType 1 def + /PaintType 2 def + /TilingType 3 def + /BBox [ 0 0 8 8 ] def + /XStep 8 def + /YStep 8 def + /PaintProc { + begin + patProcDict bstring known { + patProcDict bstring get exec + } { + 8 8 true [1 0 0 -1 0 8] bstring imagemask + } ifelse + end + } bind def + end def +} ifelse +/combineColor { + FrameSepIs FMnone eq + { + graymode fMLevel1 or not { + + [/Pattern [/DeviceCMYK]] setcolorspace + FrameCurColors 0 4 getinterval aload pop FrameCurPat setcolor + } { + FrameCurColors 3 get 1.0 ge { + FrameCurGray RealSetgray + } { + fMAcrobat not FMPColor graymode and and { + 0 1 3 { + FrameCurColors exch get + 1 FrameCurGray sub mul + } for + RealSetcmykcolor + } { + 4 1 6 { + FrameCurColors exch get + graymode { + 1 exch sub 1 FrameCurGray sub mul 1 exch sub + } { + 1.0 lt {FrameCurGray} {1} ifelse + } ifelse + } for + RealSetrgbcolor + } ifelse + } ifelse + } ifelse + } { + FrameCurColors 0 4 getinterval aload + FrameColorInSepListCMYK { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + FrameSepIs FMcustom eq and + { FrameCurGray } { 1 } ifelse + } { + FrameSepIs FMblack eq + {FrameCurGray 1.0 exch sub mul 1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop FrameCurGray 1.0 exch sub mul 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + graymode fMLevel1 or not { + + [/Pattern [/DeviceGray]] setcolorspace + FrameCurPat setcolor + } { + graymode not fMLevel1 and { + + dup 1 lt {pop FrameCurGray} if + } if + RealSetgray + } ifelse + } ifelse +} bind def +/savematrix { + orgmatrix currentmatrix pop + } bind def +/restorematrix { + orgmatrix setmatrix + } bind def +/fMDefaultMatrix matrix defaultmatrix def +/fMatrix2 matrix def +/dpi 72 0 fMDefaultMatrix dtransform + dup mul exch dup mul add sqrt def + +/freq dpi dup 72 div round dup 0 eq {pop 1} if 8 mul div def +/sangle 1 0 fMDefaultMatrix dtransform exch atan def + sangle fMatrix2 rotate + fMDefaultMatrix fMatrix2 concatmatrix + dup 0 get /sflipx exch def + 3 get /sflipy exch def +/screenIndex { + 0 1 dpiranges length 1 sub { dup dpiranges exch get 1 sub dpi le {exit} {pop} ifelse } for +} bind def +/getCyanScreen { + FMUseHighFrequencyScreens { CHighAngles CMHighFreqs} {CLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getMagentaScreen { + FMUseHighFrequencyScreens { MHighAngles CMHighFreqs } {MLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getYellowScreen { + FMUseHighFrequencyScreens { YHighTDot YHighFreqs} { YLowTDot YLowFreqs } ifelse + screenIndex dup 3 1 roll get 3 1 roll get { 3 div + {2 { 1 add 2 div 3 mul dup floor sub 2 mul 1 sub exch} repeat + FMSpotFunction } } {/FMSpotFunction load } ifelse + 0.0 exch +} bind def +/getBlackScreen { + FMUseHighFrequencyScreens { KHighFreqs } { KLowFreqs } ifelse + screenIndex get 45.0 /FMSpotFunction load +} bind def +/getSpotScreen { + getBlackScreen +} bind def +/getCompositeScreen { + getBlackScreen +} bind def +/FMSetScreen + fMLevel1 { /setscreen load + }{ { + 8 dict begin + /HalftoneType 1 def + /SpotFunction exch def + /Angle exch def + /Frequency exch def + /AccurateScreens FMUseAcccurateScreens def + currentdict end sethalftone + } bind } ifelse +def +/setDefaultScreen { + FMPColor { + orgrxfer cvx orggxfer cvx orgbxfer cvx orgxfer cvx setcolortransfer + } + { + orgxfer cvx settransfer + } ifelse + orgfreq organgle orgproc cvx setscreen +} bind def +/setCurrentScreen { + FrameSepIs FMnone eq { + FMUseDefaultNoSeparationScreen { + setDefaultScreen + } { + getCompositeScreen FMSetScreen + } ifelse + } { + FrameSepIs FMcustom eq { + FMUseDefaultSpotSeparationScreen { + setDefaultScreen + } { + getSpotScreen FMSetScreen + } ifelse + } { + FMUseDefaultProcessSeparationScreen { + setDefaultScreen + } { + FrameSepIs FMcyan eq { + getCyanScreen FMSetScreen + } { + FrameSepIs FMmagenta eq { + getMagentaScreen FMSetScreen + } { + FrameSepIs FMyellow eq { + getYellowScreen FMSetScreen + } { + getBlackScreen FMSetScreen + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse +} bind def +end + +/FMDOCUMENT { + array /FMfonts exch def + /#copies exch def + FrameDict begin + 0 ne /manualfeed exch def + /paperheight exch def + /paperwidth exch def + 0 ne /fMNegative exch def + 0 ne /edown exch def + /yscale exch def + /xscale exch def + fMLevel1 { + manualfeed {setmanualfeed} if + /FMdicttop countdictstack 1 add def + /FMoptop count def + setpapername + manualfeed {true} {papersize} ifelse + {manualpapersize} {false} ifelse + {desperatepapersize} {false} ifelse + {papersizefailure} if + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + } + {2 dict + dup /PageSize [paperwidth paperheight] put + manualfeed {dup /ManualFeed manualfeed put} if + {setpagedevice} stopped {papersizefailure} if + } + ifelse + + FMPColor { + currentcolorscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + cvlit /orgbproc exch def + /orgbangle exch def + /orgbfreq exch def + cvlit /orggproc exch def + /orggangle exch def + /orggfreq exch def + cvlit /orgrproc exch def + /orgrangle exch def + /orgrfreq exch def + currentcolortransfer + fMNegative { + 1 1 4 { + pop { 1 exch sub } fmConcatProcs 4 1 roll + } for + 4 copy + setcolortransfer + } if + cvlit /orgxfer exch def + cvlit /orgbxfer exch def + cvlit /orggxfer exch def + cvlit /orgrxfer exch def + } { + currentscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + + currenttransfer + fMNegative { + { 1 exch sub } fmConcatProcs + dup settransfer + } if + cvlit /orgxfer exch def + } ifelse + end +} def +/FMBEGINPAGE { + FrameDict begin + /pagesave save def + 3.86 setmiterlimit + /landscape exch 0 ne def + landscape { + 90 rotate 0 exch dup /pwid exch def neg translate pop + }{ + pop /pwid exch def + } ifelse + edown { [-1 0 0 1 pwid 0] concat } if + 0 0 moveto paperwidth 0 lineto paperwidth paperheight lineto + 0 paperheight lineto 0 0 lineto 1 setgray fill + xscale yscale scale + /orgmatrix matrix def + gsave +} def +/FMENDPAGE { + grestore + pagesave restore + end + showpage + } def +/FMFONTDEFINE { + FrameDict begin + findfont + ReEncode + 1 index exch + definefont + FMfonts 3 1 roll + put + end + } def +/FMFILLS { + FrameDict begin dup + array /fillvals exch def + dict /patCache exch def + end + } def +/FMFILL { + FrameDict begin + fillvals 3 1 roll put + end + } def +/FMNORMALIZEGRAPHICS { + newpath + 1 setlinewidth + 0 setlinecap + 0 0 0 sethsbcolor + 0 setgray + } bind def +/FMBEGINEPSF { + end + /FMEPSF save def + /showpage {} def +% See Adobe's "PostScript Language Reference Manual, 2nd Edition", page 714. +% "...the following operators MUST NOT be used in an EPS file:" (emphasis ours) + /banddevice {(banddevice) FMBADEPSF} def + /clear {(clear) FMBADEPSF} def + /cleardictstack {(cleardictstack) FMBADEPSF} def + /copypage {(copypage) FMBADEPSF} def + /erasepage {(erasepage) FMBADEPSF} def + /exitserver {(exitserver) FMBADEPSF} def + /framedevice {(framedevice) FMBADEPSF} def + /grestoreall {(grestoreall) FMBADEPSF} def + /initclip {(initclip) FMBADEPSF} def + /initgraphics {(initgraphics) FMBADEPSF} def + /quit {(quit) FMBADEPSF} def + /renderbands {(renderbands) FMBADEPSF} def + /setglobal {(setglobal) FMBADEPSF} def + /setpagedevice {(setpagedevice) FMBADEPSF} def + /setshared {(setshared) FMBADEPSF} def + /startjob {(startjob) FMBADEPSF} def + /lettertray {(lettertray) FMBADEPSF} def + /letter {(letter) FMBADEPSF} def + /lettersmall {(lettersmall) FMBADEPSF} def + /11x17tray {(11x17tray) FMBADEPSF} def + /11x17 {(11x17) FMBADEPSF} def + /ledgertray {(ledgertray) FMBADEPSF} def + /ledger {(ledger) FMBADEPSF} def + /legaltray {(legaltray) FMBADEPSF} def + /legal {(legal) FMBADEPSF} def + /statementtray {(statementtray) FMBADEPSF} def + /statement {(statement) FMBADEPSF} def + /executivetray {(executivetray) FMBADEPSF} def + /executive {(executive) FMBADEPSF} def + /a3tray {(a3tray) FMBADEPSF} def + /a3 {(a3) FMBADEPSF} def + /a4tray {(a4tray) FMBADEPSF} def + /a4 {(a4) FMBADEPSF} def + /a4small {(a4small) FMBADEPSF} def + /b4tray {(b4tray) FMBADEPSF} def + /b4 {(b4) FMBADEPSF} def + /b5tray {(b5tray) FMBADEPSF} def + /b5 {(b5) FMBADEPSF} def + FMNORMALIZEGRAPHICS + [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall + fx fw 2 div add fy fh 2 div add translate + rotate + fw 2 div neg fh 2 div neg translate + fw urx llx sub div fh ury lly sub div scale + llx neg lly neg translate + /FMdicttop countdictstack 1 add def + /FMoptop count def + } bind def +/FMENDEPSF { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMEPSF restore + FrameDict begin + } bind def +FrameDict begin +/setmanualfeed { +%%BeginFeature *ManualFeed True + statusdict /manualfeed true put +%%EndFeature + } bind def +/max {2 copy lt {exch} if pop} bind def +/min {2 copy gt {exch} if pop} bind def +/inch {72 mul} def +/pagedimen { + paperheight sub abs 16 lt exch + paperwidth sub abs 16 lt and + {/papername exch def} {pop} ifelse + } bind def +/setpapername { + /papersizedict 14 dict def + papersizedict begin + /papername /unknown def + /Letter 8.5 inch 11.0 inch pagedimen + /LetterSmall 7.68 inch 10.16 inch pagedimen + /Tabloid 11.0 inch 17.0 inch pagedimen + /Ledger 17.0 inch 11.0 inch pagedimen + /Legal 8.5 inch 14.0 inch pagedimen + /Statement 5.5 inch 8.5 inch pagedimen + /Executive 7.5 inch 10.0 inch pagedimen + /A3 11.69 inch 16.5 inch pagedimen + /A4 8.26 inch 11.69 inch pagedimen + /A4Small 7.47 inch 10.85 inch pagedimen + /B4 10.125 inch 14.33 inch pagedimen + /B5 7.16 inch 10.125 inch pagedimen + end + } bind def +/papersize { + papersizedict begin + /Letter {lettertray letter} def + /LetterSmall {lettertray lettersmall} def + /Tabloid {11x17tray 11x17} def + /Ledger {ledgertray ledger} def + /Legal {legaltray legal} def + /Statement {statementtray statement} def + /Executive {executivetray executive} def + /A3 {a3tray a3} def + /A4 {a4tray a4} def + /A4Small {a4tray a4small} def + /B4 {b4tray b4} def + /B5 {b5tray b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + statusdict begin stopped end + } bind def +/manualpapersize { + papersizedict begin + /Letter {letter} def + /LetterSmall {lettersmall} def + /Tabloid {11x17} def + /Ledger {ledger} def + /Legal {legal} def + /Statement {statement} def + /Executive {executive} def + /A3 {a3} def + /A4 {a4} def + /A4Small {a4small} def + /B4 {b4} def + /B5 {b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + stopped + } bind def +/desperatepapersize { + statusdict /setpageparams known + { + paperwidth paperheight 0 1 + statusdict begin + {setpageparams} stopped + end + } {true} ifelse + } bind def +/papersizefailure { + FMAllowPaperSizeMismatch not + { +(The requested paper size is not available in any currently-installed tray) +(Edit the PS file to "FMAllowPaperSizeMismatch true" to use default tray) + FMFAILURE } if + } def +/DiacriticEncoding [ +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl +/numbersign /dollar /percent /ampersand /quotesingle /parenleft +/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K +/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash +/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h +/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar +/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute +/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis +/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis +/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve +/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex +/udieresis /dagger /.notdef /cent /sterling /section /bullet +/paragraph /germandbls /registered /copyright /trademark /acute +/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef +/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown +/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef +/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde +/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright +/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis +/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl +/periodcentered /quotesinglbase /quotedblbase /perthousand +/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute +/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve +/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron +/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +] def +/ReEncode { + dup + length + dict begin + { + 1 index /FID ne + {def} + {pop pop} ifelse + } forall + 0 eq {/Encoding DiacriticEncoding def} if + currentdict + end + } bind def +FMPColor + + { + /BEGINBITMAPCOLOR { + BITMAPCOLOR} def + /BEGINBITMAPCOLORc { + BITMAPCOLORc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUECOLOR } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUECOLORc } def + /BEGINBITMAPCMYK { + BITMAPCMYK } def + /BEGINBITMAPCMYKc { + BITMAPCMYKc } def + } + + { + /BEGINBITMAPCOLOR { + BITMAPGRAY} def + /BEGINBITMAPCOLORc { + BITMAPGRAYc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUEGRAY } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUEGRAYc } def + /BEGINBITMAPCMYK { + BITMAPCMYKGRAY } def + /BEGINBITMAPCMYKc { + BITMAPCMYKGRAYc } def + } +ifelse +/K { + FMPrintAllColorsAsBlack { + dup 1 eq 2 index 1 eq and 3 index 1 eq and not + {7 {pop} repeat 0 0 0 1 0 0 0} if + } if + FrameCurColors astore + pop combineColor +} bind def +/graymode true def +fMLevel1 { + /fmGetFlip { + fMatrix2 exch get mul 0 lt { -1 } { 1 } ifelse + } FmBD +} if +/setPatternMode { + fMLevel1 { + 2 index patScreenDict exch known { + pop pop + patScreenDict exch get aload pop + freq + mul + 5 2 roll + fMatrix2 currentmatrix 1 get 0 ne { + 3 -1 roll 90 add 3 1 roll + sflipx 1 fmGetFlip sflipy 2 fmGetFlip neg mul + } { + sflipx 0 fmGetFlip sflipy 3 fmGetFlip mul + } ifelse + 0 lt {exch pop} {pop} ifelse + fMNegative { + {neg} fmConcatProcs + } if + bind + + + + systemdict /setscreen get exec + /FrameCurGray exch def + } { + /bwidth exch def + /bpside exch def + /bstring exch def + /onbits 0 def /offbits 0 def + freq sangle landscape {90 add} if + {/ypoint exch def + /xpoint exch def + /xindex xpoint 1 add 2 div bpside mul cvi def + /yindex ypoint 1 add 2 div bpside mul cvi def + bstring yindex bwidth mul xindex 8 idiv add get + 1 7 xindex 8 mod sub bitshift and 0 ne fMNegative {not} if + {/onbits onbits 1 add def 1} + {/offbits offbits 1 add def 0} + ifelse + } + setscreen + offbits offbits onbits add div fMNegative {1.0 exch sub} if + /FrameCurGray exch def + } ifelse + } { + pop pop + dup patCache exch known { + patCache exch get + } { + dup + patDict /bstring 3 -1 roll put + patDict + 9 PatFreq screenIndex get div dup matrix scale + makepattern + dup + patCache 4 -1 roll 3 -1 roll put + } ifelse + /FrameCurGray 0 def + /FrameCurPat exch def + } ifelse + /graymode false def + combineColor +} bind def +/setGrayScaleMode { + graymode not { + /graymode true def + fMLevel1 { + setCurrentScreen + } if + } if + /FrameCurGray exch def + combineColor +} bind def +/normalize { + transform round exch round exch itransform + } bind def +/dnormalize { + dtransform round exch round exch idtransform + } bind def +/lnormalize { + 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop + } bind def +/H { + lnormalize setlinewidth + } bind def +/Z { + setlinecap + } bind def + +/PFill { + graymode fMLevel1 or not { + gsave 1 setgray eofill grestore + } if +} bind def +/PStroke { + graymode fMLevel1 or not { + gsave 1 setgray stroke grestore + } if + stroke +} bind def +/X { + fillvals exch get + dup type /stringtype eq + {8 1 setPatternMode} + {setGrayScaleMode} + ifelse + } bind def +/V { + PFill gsave eofill grestore + } bind def +/Vclip { + clip + } bind def +/Vstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/N { + PStroke + } bind def +/Nclip { + strokepath clip newpath + } bind def +/Nstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/M {newpath moveto} bind def +/E {lineto} bind def +/D {curveto} bind def +/O {closepath} bind def +/L { + /n exch def + newpath + normalize + moveto + 2 1 n {pop normalize lineto} for + } bind def +/Y { + L + closepath + } bind def +/R { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + x1 y1 + x2 y1 + x2 y2 + x1 y2 + 4 Y + } bind def +/rarc + {rad + arcto + } bind def +/RR { + /rad exch def + normalize + /y2 exch def + /x2 exch def + normalize + /y1 exch def + /x1 exch def + mark + newpath + { + x1 y1 rad add moveto + x1 y2 x2 y2 rarc + x2 y2 x2 y1 rarc + x2 y1 x1 y1 rarc + x1 y1 x1 y2 rarc + closepath + } stopped {x1 y1 x2 y2 R} if + cleartomark + } bind def +/RRR { + /rad exch def + normalize /y4 exch def /x4 exch def + normalize /y3 exch def /x3 exch def + normalize /y2 exch def /x2 exch def + normalize /y1 exch def /x1 exch def + newpath + normalize moveto + mark + { + x2 y2 x3 y3 rarc + x3 y3 x4 y4 rarc + x4 y4 x1 y1 rarc + x1 y1 x2 y2 rarc + closepath + } stopped + {x1 y1 x2 y2 x3 y3 x4 y4 newpath moveto lineto lineto lineto closepath} if + cleartomark + } bind def +/C { + grestore + gsave + R + clip + setCurrentScreen +} bind def +/CP { + grestore + gsave + Y + clip + setCurrentScreen +} bind def +/F { + FMfonts exch get + FMpointsize scalefont + setfont + } bind def +/Q { + /FMpointsize exch def + F + } bind def +/T { + moveto show + } bind def +/RF { + rotate + 0 ne {-1 1 scale} if + } bind def +/TF { + gsave + moveto + RF + show + grestore + } bind def +/P { + moveto + 0 32 3 2 roll widthshow + } bind def +/PF { + gsave + moveto + RF + 0 32 3 2 roll widthshow + grestore + } bind def +/S { + moveto + 0 exch ashow + } bind def +/SF { + gsave + moveto + RF + 0 exch ashow + grestore + } bind def +/B { + moveto + 0 32 4 2 roll 0 exch awidthshow + } bind def +/BF { + gsave + moveto + RF + 0 32 4 2 roll 0 exch awidthshow + grestore + } bind def +/G { + gsave + newpath + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill fill + grestore + } bind def +/Gstrk { + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/Gclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GG { + gsave + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill + fill + grestore + } bind def +/GGclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GGstrk { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/A { + gsave + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/Aclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/Astrk { + Gstrk +} bind def +/AA { + gsave + savematrix + newpath + + 3 index 2 div add exch 4 index 2 div sub exch + + normalize 3 index 2 div sub exch 4 index 2 div add exch + translate + rotate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/AAclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/AAstrk { + GGstrk +} bind def +/BEGINPRINTCODE { + /FMdicttop countdictstack 1 add def + /FMoptop count 7 sub def + /FMsaveobject save def + userdict begin + /showpage {} def + FMNORMALIZEGRAPHICS + 3 index neg 3 index neg translate + } bind def +/ENDPRINTCODE { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMsaveobject restore + } bind def +/gn { + 0 + { 46 mul + cf read pop + 32 sub + dup 46 lt {exit} if + 46 sub add + } loop + add + } bind def +/cfs { + /str sl string def + 0 1 sl 1 sub {str exch val put} for + str def + } bind def +/ic [ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 + {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx} + {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx} + {19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} + {13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh} + {4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh} + {13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl} + {7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl} + {0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl} + {10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl} + ] def +/ms { + /sl exch def + /val 255 def + /ws cfs + /im cfs + /val 0 def + /bs cfs + /cs cfs + } bind def +400 ms +/ip { + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip { + + + bis ris copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + ris gis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + gis bis copy pop + dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip4 { + + + kis cis copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + cis mis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + mis yis copy pop + dup dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + yis kis copy pop + 3 mul is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/wh { + /len exch def + /pos exch def + ws 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/bl { + /len exch def + /pos exch def + bs 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/s1 1 string def +/fl { + /len exch def + /pos exch def + /val cf s1 readhexstring pop 0 get def + pos 1 pos len add 1 sub {im exch val put} for + pos len + } bind def +/hx { + 3 copy getinterval + cf exch readhexstring pop pop + } bind def +/wbytes { + dup dup + 8 gt { pop 8 idiv mul } + { 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse } ifelse + } bind def +/BEGINBITMAPBWc { + 1 {} COMMONBITMAPc + } bind def +/BEGINBITMAPGRAYc { + 8 {} COMMONBITMAPc + } bind def +/BEGINBITMAP2BITc { + 2 {} COMMONBITMAPc + } bind def +/COMMONBITMAPc { + + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + cvtProc + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} image + bitmapsave restore + grestore + } bind def +/BEGINBITMAPBW { + 1 {} COMMONBITMAP + } bind def +/BEGINBITMAPGRAY { + 8 {} COMMONBITMAP + } bind def +/BEGINBITMAP2BIT { + 2 {} COMMONBITMAP + } bind def +/COMMONBITMAP { + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + cvtProc + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} image + bitmapsave restore + grestore + } bind def +/ngrayt 256 array def +/nredt 256 array def +/nbluet 256 array def +/ngreent 256 array def +fMLevel1 { +/colorsetup { + currentcolortransfer + /gryt exch def + /blut exch def + /grnt exch def + /redt exch def + 0 1 255 { + /indx exch def + /cynu 1 red indx get 255 div sub def + /magu 1 green indx get 255 div sub def + /yelu 1 blue indx get 255 div sub def + /kk cynu magu min yelu min def + /u kk currentundercolorremoval exec def +% /u 0 def + nredt indx 1 0 cynu u sub max sub redt exec put + ngreent indx 1 0 magu u sub max sub grnt exec put + nbluet indx 1 0 yelu u sub max sub blut exec put + ngrayt indx 1 kk currentblackgeneration exec sub gryt exec put + } for + {255 mul cvi nredt exch get} + {255 mul cvi ngreent exch get} + {255 mul cvi nbluet exch get} + {255 mul cvi ngrayt exch get} + setcolortransfer + {pop 0} setundercolorremoval + {} setblackgeneration + } bind def +} +{ +/colorSetup2 { + [ /Indexed /DeviceRGB 255 + {dup red exch get 255 div + exch dup green exch get 255 div + exch blue exch get 255 div} + ] setcolorspace +} bind def +} ifelse +/fakecolorsetup { + /tran 256 string def + 0 1 255 {/indx exch def + tran indx + red indx get 77 mul + green indx get 151 mul + blue indx get 28 mul + add add 256 idiv put} for + currenttransfer + {255 mul cvi tran exch get 255.0 div} + exch fmConcatProcs settransfer +} bind def +/BITMAPCOLOR { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + fMLevel1 { + colorsetup + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} {is} {is} true 3 colorimage + } { + colorSetup2 + /is width depth wbytes string def + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {cf is readhexstring pop} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPCOLORc { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + fMLevel1 { + colorsetup + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} {is} {is} true 3 colorimage + } { + colorSetup2 + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {ip} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLORc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris} {gis} {bis} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYKc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip4 pop cis} {mis} {yis} {kis} true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLOR { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf gis readhexstring pop } + { cf bis readhexstring pop } + true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYK { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /mis width string def + /yis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf mis readhexstring pop } + { cf yis readhexstring pop } + { cf kis readhexstring pop } + true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUEGRAYc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris gis bis width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAYc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop cis mis yis kis width cgray} image + bitmapsave restore + grestore + } bind def +/cgray { + /ww exch def + /k exch def + /y exch def + /m exch def + /c exch def + 0 1 ww 1 sub { /i exch def c i get m i get y i get k i get CMYKtoRGB + .144 mul 3 1 roll .587 mul 3 1 roll .299 mul add add + c i 3 -1 roll floor cvi put } for + c + } bind def +/gray { + /ww exch def + /b exch def + /g exch def + /r exch def + 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul + b i get .114 mul add add r i 3 -1 roll floor cvi put } for + r + } bind def +/BITMAPTRUEGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf gis readhexstring pop + cf bis readhexstring pop width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /yis width string def + /mis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf mis readhexstring pop + cf yis readhexstring pop + cf kis readhexstring pop width cgray} image + bitmapsave restore + grestore + } bind def +/BITMAPGRAY { + 8 {fakecolorsetup} COMMONBITMAP + } bind def +/BITMAPGRAYc { + 8 {fakecolorsetup} COMMONBITMAPc + } bind def +/ENDBITMAP { + } bind def +end + /ALDmatrix matrix def ALDmatrix currentmatrix pop +/StartALD { + /ALDsave save def + savematrix + ALDmatrix setmatrix + } bind def +/InALD { + restorematrix + } bind def +/DoneALD { + ALDsave restore + } bind def +/I { setdash } bind def +/J { [] 0 setdash } bind def +%%EndProlog +%%BeginSetup +(5.0) FMVERSION +1 1 0 0 612 792 0 1 13 FMDOCUMENT +0 0 /Helvetica FMFONTDEFINE +1 0 /Times-BoldItalic FMFONTDEFINE +2 0 /Helvetica-Bold FMFONTDEFINE +3 0 /Helvetica-BoldOblique FMFONTDEFINE +4 0 /Helvetica-Oblique FMFONTDEFINE +5 0 /Courier-Bold FMFONTDEFINE +6 0 /Courier-BoldOblique FMFONTDEFINE +32 FMFILLS +0 0 FMFILL +1 0.1 FMFILL +2 0.3 FMFILL +3 0.5 FMFILL +4 0.7 FMFILL +5 0.9 FMFILL +6 0.97 FMFILL +7 1 FMFILL +8 <0f1e3c78f0e1c387> FMFILL +9 <0f87c3e1f0783c1e> FMFILL +10 FMFILL +11 FMFILL +12 <8142241818244281> FMFILL +13 <03060c183060c081> FMFILL +14 <8040201008040201> FMFILL +16 1 FMFILL +17 0.9 FMFILL +18 0.7 FMFILL +19 0.5 FMFILL +20 0.3 FMFILL +21 0.1 FMFILL +22 0.03 FMFILL +23 0 FMFILL +24 FMFILL +25 FMFILL +26 <3333333333333333> FMFILL +27 <0000ffff0000ffff> FMFILL +28 <7ebddbe7e7dbbd7e> FMFILL +29 FMFILL +30 <7fbfdfeff7fbfdfe> FMFILL +%%EndSetup +%%Page: "i" 1 +%%BeginPaperSize: Letter +%%EndPaperSize +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(i) 555.78 57 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 720 558 720 2 L +0.5 H +2 Z +N +72 72 558 72 2 L +N +72 504 558 504 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 32 Q +(CDEV Utilities) 180 662.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 12 Q +(Utility Applications of the Contr) 180 638 T +(ol De) 359.77 638 T +(vice Interface) 388.93 638 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(Chip W) 180 610 T +(atson, Jie Chen, Danjin W) 218.86 610 T +(u, W) 357.22 610 T +(alt Ak) 381.41 610 T +(ers) 411.18 610 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 180 582 T +(ersion 1.5 - December 9, 1996) 187.04 582 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(TJNAF - Thomas Jeff) 180 554 T +(erson National Acceler) 293.66 554 T +(ator F) 414.25 554 T +(acility) 445 554 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "i" 1 +%%Page: "ii" 2 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(ii) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 10 Q +(TRADEMARKS:) 54 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(UNIX is a registered tr) 180 569.33 T +(ademar) 278.26 569.33 T +(k of A) 312.31 569.33 T +(T&T in the USA and other countr) 336.68 569.33 T +(ies) 481.9 569.33 T +(.) 494.53 569.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(VxW) 180 545.33 T +(or) 200.81 545.33 T +(ks is a register tr) 209.85 545.33 T +(ademar) 283.1 545.33 T +(k of Wind Riv) 317.15 545.33 T +(er Systems) 375.8 545.33 T +(.) 425.66 545.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The X Windo) 180 521.33 T +(w System is a tr) 237.65 521.33 T +(ademar) 308.12 521.33 T +(k of Massachusetts Institute of T) 342.17 521.33 T +(echnology) 484.37 521.33 T +(.) 528.95 521.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(OSF/Motif and Motif are tr) 180 497.33 T +(ademar) 294.94 497.33 T +(ks of Open Softw) 328.99 497.33 T +(are F) 404.99 497.33 T +(oundation, Inc.) 428.03 497.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ultr) 180 473.33 T +(ix and DEC are registered tr) 195.7 473.33 T +(ademar) 319.53 473.33 T +(ks of Digital Equipment Cor) 353.58 473.33 T +(por) 475.03 473.33 T +(ation.) 489.38 473.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(HPUX is a registered tr) 180 449.33 T +(ademar) 282.15 449.33 T +(k of He) 316.2 449.33 T +(wlett P) 347.68 449.33 T +(ac) 377.29 449.33 T +(kard.) 387.65 449.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(SURA/CEB) 54 344.33 T +(AF:) 105.92 344.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +4.44 (The Southeaster) 180 344.33 P +4.44 (n Univ) 258.62 344.33 P +4.44 (ersities Research Association \050SURA\051 oper) 291.15 344.33 P +4.44 (ates the) 499.98 344.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.01 (Contin) 180 332.33 P +2.01 (uous Electron Beam Acceler) 208.8 332.33 P +2.01 (ator F) 340.89 332.33 P +2.01 (acility \050CEBAF\051 f) 368.52 332.33 P +2.01 (or the United States) 445.59 332.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Depar) 180 320.33 T +(tment of Energy under contr) 207.63 320.33 T +(act DE-A) 331.48 320.33 T +(C05-84ER40150.) 371.19 320.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DISCLAIMER:) 54 218.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +0.49 (This repor) 180 218.33 P +0.49 (t w) 225.9 218.33 P +0.49 (as prepared as an account of w) 239.02 218.33 P +0.49 (or) 381.4 218.33 P +0.49 (k sponsored b) 390.44 218.33 P +0.49 (y the United States) 454.03 218.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.18 (go) 180 206.33 P +2.18 (v) 190.97 206.33 P +2.18 (er) 195.72 206.33 P +2.18 (nment. Neither the United States nor the United States Depar) 204.86 206.33 P +2.18 (tment of) 501.68 206.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.04 (Energy) 180 194.33 P +1.04 (, nor an) 210.68 194.33 P +1.04 (y of their emplo) 246.52 194.33 P +1.04 (y) 317.69 194.33 P +1.04 (ees) 322.49 194.33 P +1.04 (, mak) 338.46 194.33 P +1.04 (es an) 363.75 194.33 P +1.04 (y w) 389.1 194.33 P +1.04 (arr) 404.99 194.33 P +1.04 (anty) 417.11 194.33 P +1.04 (, e) 435.01 194.33 P +1.04 (xpress or implied, or) 446.86 194.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.83 (assumes an) 180 182.33 P +1.83 (y legal liability or responsibility f) 235.59 182.33 P +1.83 (or the accur) 383.89 182.33 P +1.83 (acy) 440.24 182.33 P +1.83 (, completeness) 454.8 182.33 P +1.83 (, or) 523.72 182.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.68 (usefulness of an) 180 170.33 P +3.68 (y inf) 260.02 170.33 P +3.68 (or) 281.74 170.33 P +3.68 (mation, appar) 290.88 170.33 P +3.68 (atus) 355.59 170.33 P +3.68 (, product or process disclosed, or) 374.34 170.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.46 (represents that its use w) 180 158.33 P +2.46 (ould not infr) 298.11 158.33 P +2.46 (inge pr) 355.42 158.33 P +2.46 (iv) 388.59 158.33 P +2.46 (ately o) 395.56 158.33 P +2.46 (wned r) 427.33 158.33 P +2.46 (ights) 459.95 158.33 P +2.46 (. Ref) 480.92 158.33 P +2.46 (erence) 509.43 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.6 (herein to an) 180 146.33 P +1.6 (y speci\336c commercial product, process) 235.85 146.33 P +1.6 (, or ser) 413.79 146.33 P +1.6 (vice b) 448.4 146.33 P +1.6 (y tr) 475.92 146.33 P +1.6 (ade name) 491.3 146.33 P +1.6 (,) 537.22 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (mar) 180 134.33 P +2.12 (k, man) 197.37 134.33 P +2.12 (uf) 229.4 134.33 P +2.12 (acturer) 237.44 134.33 P +2.12 (, or otherwise) 268.06 134.33 P +2.12 (, does not necessar) 332.17 134.33 P +2.12 (ily constitute or imply its) 425.94 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (endorsement, recommendation, or f) 180 122.33 P +1.08 (a) 341.33 122.33 P +1.08 (v) 346.69 122.33 P +1.08 (or) 351.44 122.33 P +1.08 (ing b) 360.48 122.33 P +1.08 (y the United States go) 383.03 122.33 P +1.08 (v) 485.57 122.33 P +1.08 (er) 490.32 122.33 P +1.08 (nment or) 499.46 122.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (an) 180 110.33 P +0.83 (y agency thereof) 190.97 110.33 P +0.83 (. The vie) 266.26 110.33 P +0.83 (w and opinions of the authors e) 309.67 110.33 P +0.83 (xpressed herein do) 453.3 110.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.94 (not necessar) 180 98.33 P +1.94 (ily state or re\337ect those of the United States go) 239.34 98.33 P +1.94 (v) 464.01 98.33 P +1.94 (er) 468.76 98.33 P +1.94 (nment or an) 477.9 98.33 P +1.94 (y) 535 98.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(agency thereof) 180 86.33 T +(.) 245.85 86.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 F +(DOCUMENT D) 54 668.33 T +(A) 121.37 668.33 T +(TE:) 127.69 668.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 F +(T) 180 668.33 T +(ab) 184.91 668.33 T +(le of contents gener) 195.83 668.33 T +(ated: December 9, 1996 11:47 am) 283.56 668.33 T +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "ii" 2 +%%Page: "iii" 3 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iii) 551.34 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(T) 180 710.67 T +(ab) 187.43 710.67 T +(le of Contents) 203.63 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cde) 198 684.33 T +(vUtil Command Line Utility) 233.83 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 353.06 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 672.33 T +(er) 210.73 672.33 T +(vie) 219.92 672.33 T +(w) 232.5 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Location of Files) 198.2 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 660.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Star) 198.2 648.33 T +(ting cde) 216.94 648.33 T +(vUtil) 251.66 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 648.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Arguments to cde) 198.2 636.33 T +(vUtil) 276.27 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 297.46 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Syntax of cde) 198.2 624.33 T +(vUtil Commands) 258.49 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 333.6 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7) 552.44 624.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Exiting from cde) 198.2 612.33 T +(vUtil) 269.59 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 289.12 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 612.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 198.2 600.33 T +(vUtil Inter) 214.02 600.33 T +(nal Commands) 256.5 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 325.26 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 600.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 180 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The cddl De) 198 588.33 T +(vice De\336nition File Compiler) 251.61 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 378.08 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 588.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 198.2 576.33 T +(er) 210.73 576.33 T +(vie) 219.92 576.33 T +(w) 232.5 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 241.86 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Location of Files) 198.2 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 272.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 564.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Using the cddl Compiler) 198.2 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .) 305.8 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 552.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iii" 3 +%%Page: "iv" 4 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(iv) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "iv" 4 +%%Page: "v" 5 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(v) 553 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(List of Figures) 180 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(Figure 1.) 180 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Entering commands using cdevUtil) 234 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(..........................................................) 389.2 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8) 552.44 684.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Figure 2.) 180 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Typical output from the cddl compiler) 234 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(.......................................................) 397.54 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(9) 552.44 672.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "v" 5 +%%Page: "vi" 6 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +0 X +0 0 0 1 0 0 0 K +(vi) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "vi" 6 +%%Page: "7" 7 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. The cde) 410.23 739 T +(vUtil Command Line Utility) 452.48 739 T +0 10 Q +(7) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(1.) 159.32 710.67 T +(The) 180 710.67 T +3 F +(cde) 208.78 710.67 T +(vUtil) 232.7 710.67 T +2 F +(Command Line Utility) 266.93 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w) 108.64 673.33 T +0 F +1.31 (The cde) 180 673.33 P +1.31 (vUtil application pro) 217.14 673.33 P +1.31 (vides cde) 306.87 673.33 P +1.31 (v user\325) 350.13 673.33 P +1.31 (s with a simple application that can be) 380.39 673.33 P +0.59 (used to comm) 180 661.33 P +0.59 (unicate with cde) 243.88 661.33 P +0.59 (v ser) 316.47 661.33 P +0.59 (vices) 339.03 661.33 P +0.59 (. This prog) 361.66 661.33 P +0.59 (r) 409.98 661.33 P +0.59 (am pro) 413.21 661.33 P +0.59 (vides a direct interf) 444.77 661.33 P +0.59 (ace to) 530.17 661.33 P +0.13 (most of the capabilities of cde) 180 649.33 P +0.13 (v and is commonly used to test a ne) 312.07 649.33 P +0.13 (wly created ser) 472.42 649.33 P +0.13 (vice) 540.22 649.33 P +(or to ensure that changes made to a DDL \336le are beha) 180 637.33 T +(ving as e) 421.04 637.33 T +(xpected.) 460.76 637.33 T +2 F +(Location of Files) 72 608.33 T +0 F +2.22 (The source code f) 180 608.33 P +2.22 (or cde) 266.39 608.33 P +2.22 (vUtil is located in the) 296.1 608.33 P +3 F +2.22 ($\050CDEV\051/sr) 401.66 608.33 P +2.22 (c/utility) 453.69 608.33 P +0 F +2.22 (director) 493.69 608.33 P +2.22 (y) 527.33 608.33 P +2.22 (. This) 531.33 608.33 P +1.47 (application is automatically compiled whene) 180 596.33 P +1.47 (v) 379.55 596.33 P +1.47 (er the cde) 384.3 596.33 P +1.47 (v libr) 431.42 596.33 P +1.47 (ar) 453.9 596.33 P +1.47 (y is b) 463.09 596.33 P +1.47 (uilt. The binar) 489.17 596.33 P +1.47 (y) 553 596.33 P +-0.02 (e) 180 584.33 P +-0.02 (x) 185.26 584.33 P +-0.02 (ecutab) 189.96 584.33 P +-0.02 (le is placed in the director) 219.78 584.33 P +-0.02 (y) 333.38 584.33 P +3 F +-0.02 ($\050CDEV\051/bin/$\050T) 341.14 584.33 P +-0.02 (ARGET\051) 415.8 584.33 P +0 F +-0.02 ( when the application is) 454.13 584.33 P +0.05 (compiled) 180 572.33 P +3 F +0.05 (.) 220.01 572.33 P +0 F +0.05 (Once the cde) 225.62 572.33 P +0.05 (v libr) 284.91 572.33 P +0.05 (ar) 305.97 572.33 P +0.05 (ies and applications are compiled, this director) 315.01 572.33 P +0.05 (y should) 520.71 572.33 P +(be placed in y) 180 560.33 T +(our search path.) 241.5 560.33 T +2 F +(Star) 72 531.33 T +(ting cde) 91.65 531.33 T +(vUtil) 129.84 531.33 T +0 F +2.72 (The cde) 180 531.33 P +2.72 (vUtil utility is e) 218.55 531.33 P +2.72 (x) 289.74 531.33 P +2.72 (ecuted from the UNIX command line b) 294.44 531.33 P +2.72 (y typing) 480.06 531.33 P +4 F +2.72 (cde) 522.74 531.33 P +2.72 (vUtil) 538.56 531.33 P +0.03 () 210.54 519.33 P +0 F +0.03 (. If the cde) 221.94 519.33 P +0.03 (v binar) 268.43 519.33 P +0.03 (y director) 298.77 519.33 P +0.03 (y is not in y) 340.22 519.33 P +0.03 (our path, then y) 390.17 519.33 P +0.03 (ou will ha) 459.55 519.33 P +0.03 (v) 501.09 519.33 P +0.03 (e to pro) 505.84 519.33 P +0.03 (vide) 539.66 519.33 P +0.22 (the complete path on the command line) 180 507.33 P +0.22 (. The CDEVDDL en) 356.24 507.33 P +0.22 (vironment v) 443.94 507.33 P +0.22 (ar) 495.58 507.33 P +0.22 (iab) 504.62 507.33 P +0.22 (le should) 517.76 507.33 P +1.86 (be speci\336ed pr) 180 495.33 P +1.86 (ior to star) 248.89 495.33 P +1.86 (ting the utility because cde) 294.68 495.33 P +1.86 (vUtil will use this en) 419.64 495.33 P +1.86 (vironment) 514.1 495.33 P +(v) 180 483.33 T +(ar) 184.75 483.33 T +(iab) 193.79 483.33 T +(le to locate and load the de) 206.93 483.33 T +(vice de\336nition \336le) 326.71 483.33 T +(.) 402.7 483.33 T +2 F +(Ar) 72 454.33 T +(guments to) 82.96 454.33 T +(cde) 72 442.33 T +(vUtil) 89.08 442.33 T +0 F +0.38 (When star) 180 454.33 P +0.38 (ting the cde) 226.35 454.33 P +0.38 (vUtil utility) 278.51 454.33 P +0.38 (, the user ma) 322.89 454.33 P +0.38 (y pro) 382.09 454.33 P +0.38 (vide a list of str) 404.55 454.33 P +0.38 (ings as arguments) 472.91 454.33 P +0.38 (.) 555.22 454.33 P +1.7 (Each of these str) 180 442.33 P +1.7 (ings will be treated as a single command and will be processed) 260.29 442.33 P +1.69 (bef) 180 430.33 P +1.69 (ore the command line prompt is displa) 193.6 430.33 P +1.69 (y) 372.38 430.33 P +1.69 (ed. An) 377.18 430.33 P +1.69 (y command that is suppor) 407.63 430.33 P +1.69 (ted b) 529.27 430.33 P +1.69 (y) 553 430.33 P +1.15 (cde) 180 418.33 P +1.15 (vUtil ma) 195.82 418.33 P +1.15 (y be submitted as an argument, including, \322) 232.78 418.33 P +4 F +1.15 (deb) 432.02 418.33 P +1.15 (ug on) 448.5 418.33 P +0 F +1.15 (\323, \322) 474.67 418.33 P +4 F +1.15 (deb) 488.03 418.33 P +1.15 (ug off) 504.51 418.33 P +0 F +1.15 (\323, and) 531.28 418.33 P +4 F +0.29 (\322quit) 180 406.33 P +0 F +0.29 (\323. The syntax of individual commands is descr) 199.45 406.33 P +0.29 (ibed in the section titled) 403.95 406.33 P +3 F +0.29 (Syntax of) 512.7 406.33 P +(cde) 180 394.33 T +(vUtil Commands.) 197.08 394.33 T +0 F +0.76 (The f) 180 377.33 P +0.76 (ollo) 203.25 377.33 P +0.76 (wing \336gure sho) 218.66 377.33 P +0.76 (ws ho) 287.29 377.33 P +0.76 (w three command line arguments can be submitted to) 314.02 377.33 P +(cde) 180 365.33 T +(vUtil to be processed in batch mode) 195.82 365.33 T +(.) 354.63 365.33 T +4 9 Q +(Figure 1: Submitting batch commands to cde) 180 332 T +(vUtil) 360.81 332 T +2 10 Q +(Syntax of cde) 72 121.24 T +(vUtil) 136.87 121.24 T +(Commands) 72 109.24 T +0 F +(The cde) 180 121.24 T +(vUtil utility uses a simple syntax with the f) 215.83 121.24 T +(ollo) 398.92 121.24 T +(wing f) 414.33 121.24 T +(or) 440.15 121.24 T +(mat:) 449.29 121.24 T +3 F +(de) 198 104.24 T +(viceName verb attrib) 209.52 104.24 T +(uteName ta) 307.69 104.24 T +(g1=xxx ta) 361.49 104.24 T +(g2=xxx ...) 407.25 104.24 T +180 146.91 558 461 C +180 146.91 558 329 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +190.56 150.07 554.85 321.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +183.88 155.69 549.27 326.57 R +7 X +V +0 X +N +188.42 158.32 544.7 321.62 R +7 X +V +5 9 Q +0 X +(host1:> cdevUtil \322debug on\323 \322IPM1S01 set VAL value=25.0\323 \322quit\323) 188.42 315.62 T +(Submitting batch cdev commands...) 188.42 293.62 T +(-------------------- DEBUG OUTPUT -------------------) 188.42 282.62 T +(Attempting to transmit using the following parameters) 188.42 271.62 T +(Device: IPM1S01) 188.42 260.62 T +(Verb: set) 188.42 249.62 T +(Attrib: VAL) 188.42 238.62 T +(Tag: value = 25) 188.42 227.62 T +(SUCCESS: Device: IPM1S01 - Message: set VAL - Value: None) 188.42 205.62 T +(------------------ END DEBUG OUTPUT -----------------) 188.42 194.62 T +(host1:>) 188.42 172.62 T +180 146.91 558 461 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "7" 7 +%%Page: "8" 8 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. The cde) 54 739 T +(vUtil Command Line Utility) 96.25 739 T +0 10 Q +(8) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 10 Q +(de) 180 713.33 T +(viceName) 191.52 713.33 T +0 F +0.33 (The name of the cde) 261.29 713.33 P +0.33 (v de) 354.02 713.33 P +0.33 (vice that the message should be sent) 372.95 713.33 P +(to) 261.43 701.33 T +(.) 269.37 701.33 T +3 F +(verb) 180 677.33 T +0 F +2.48 (The v) 261.29 677.33 P +2.48 (erb component of the message str) 288.53 677.33 P +2.48 (ing. F) 452.82 677.33 P +2.48 (or a channel) 480.01 677.33 P +(access de) 261.43 665.33 T +(vice this will be get, set, monitorOn or monitorOff) 306.15 665.33 T +(.) 521.48 665.33 T +3 F +(attrib) 180 641.33 T +(uteName) 204.8 641.33 T +0 F +2.12 (The name of the cde) 261.29 641.33 P +2.12 (v de) 361.21 641.33 P +2.12 (vice attr) 381.93 641.33 P +2.12 (ib) 419.22 641.33 P +2.12 (ute that the v) 426.8 641.33 P +2.12 (erb will be) 490.74 641.33 P +(e) 261.43 629.33 T +(x) 266.69 629.33 T +(ecuted on.) 271.39 629.33 T +3 F +(ta) 180 605.33 T +(g=xxxx) 188.79 605.33 T +0 F +1.62 (These entr) 261.29 605.33 P +1.62 (ies are used to place inf) 310.86 605.33 P +1.62 (or) 424.27 605.33 P +1.62 (mation in the outbound) 433.41 605.33 P +1.47 (cde) 261.43 593.33 P +1.47 (vData object. tag is the te) 277.25 593.33 P +1.47 (xt str) 397.16 593.33 P +1.47 (ing name of the cde) 420.45 593.33 P +1.47 (vData) 513.88 593.33 P +0.84 (tag. xxxx is the v) 261.43 581.33 P +0.84 (alue that should be placed in the tag. At this) 338.45 581.33 P +1.16 (time cde) 261.43 569.33 P +1.16 (vUtil only suppor) 300.08 569.33 P +1.16 (ts the inser) 376.71 569.33 P +1.16 (tion of scalar v) 428.34 569.33 P +1.16 (alues into) 496.04 569.33 P +(the cde) 261.43 557.33 T +(vData object.) 293.93 557.33 T +-0.08 (The f) 162 540.33 P +-0.08 (ollo) 184.41 540.33 P +-0.08 (wing e) 199.82 540.33 P +-0.08 (xample sho) 228.35 540.33 P +-0.08 (ws the commands necessar) 279.25 540.33 P +-0.08 (y to submit a request to get the) 403.24 540.33 P +(v) 162 528.33 T +(alue of a de) 166.75 528.33 T +(vice) 218.71 528.33 T +(, and then set it to a ne) 236.34 528.33 T +(w v) 337.88 528.33 T +(alue) 352.63 528.33 T +(.) 371.38 528.33 T +4 9 Q +(Figure 2: Enter) 162 500 T +(ing commands using cde) 224.16 500 T +(vUtil) 323.43 500 T +2 10 Q +(Exiting fr) 54 368.52 T +(om) 97.14 368.52 T +(cde) 54 356.52 T +(vUtil) 71.08 356.52 T +0 F +0.17 (In order to e) 162 368.52 P +0.17 (xit from cde) 216.11 368.52 P +0.17 (vUtil, the user m) 267.82 368.52 P +0.17 (ust type) 340.46 368.52 P +3 F +0.17 (quit ) 378.59 368.52 P +0 F +0.17 (. This will remo) 443.76 368.52 P +0.17 (v) 510.77 368.52 P +0.17 (e an) 515.53 368.52 P +0.17 (y) 535 368.52 P +(monitors that might ha) 162 356.52 T +(v) 260.73 356.52 T +(e been created and will ter) 265.48 356.52 T +(minate the session.) 383.01 356.52 T +2 F +(cde) 54 327.52 T +(vUtil Internal) 71.08 327.52 T +(Commands) 54 315.52 T +0 F +2.72 (The f) 162 327.52 P +2.72 (ollo) 187.21 327.52 P +2.72 (wing commands are processed b) 202.62 327.52 P +2.72 (y the cde) 360.02 327.52 P +2.72 (vUtil application and are not) 405.73 327.52 P +(passed through to cde) 162 315.52 T +(v) 260.65 315.52 T +(.) 264.85 315.52 T +3 F +(deb) 180 291.52 T +(ug on) 197.58 291.52 T +0 F +3.32 (This message tells cde) 261.29 291.52 P +3.32 (vutil that the user w) 372.66 291.52 P +3.32 (ants e) 471.96 291.52 P +3.32 (xtremely) 502.22 291.52 P +0.42 (v) 261.43 279.53 P +0.42 (erbose output. When this is \337ag is set, the complete contents) 266.18 279.53 P +5.05 (of the incoming and outgoing cde) 261.43 267.53 P +5.05 (vData objects will be) 433.7 267.53 P +4.7 (displa) 261.43 255.53 P +4.7 (y) 287.25 255.53 P +4.7 (ed. T) 292.05 255.53 P +4.7 (ypically only the v) 318.35 255.53 P +4.7 (alue \336eld of the incoming) 410.57 255.53 P +(cde) 261.43 243.53 T +(vData object is displa) 277.25 243.53 T +(y) 371.43 243.53 T +(ed.) 376.23 243.53 T +3 F +(deb) 180 219.53 T +(ug off) 197.58 219.53 T +0 F +(This message tells cde) 261.29 219.53 T +(vUtil to stop displa) 362.69 219.53 T +(ying v) 443.53 219.53 T +(erbose output.) 469.4 219.53 T +3 F +(help) 180 195.53 T +0 F +3.58 (This command causes cde) 261.29 195.53 P +3.58 (vUtil to displa) 390.67 195.53 P +3.58 (y an simple help) 457 195.53 P +(screen that descr) 261.43 183.53 T +(ibes its usage and inter) 338.28 183.53 T +(nal commands) 441.36 183.53 T +(.) 506.23 183.53 T +3 F +(quit) 180 159.53 T +0 F +(This command ter) 261.29 159.53 T +(minates the cde) 341.56 159.53 T +(vUtil utility) 411.85 159.53 T +(.) 455.85 159.53 T +162 394.19 540 720 C +162 394.19 540 497 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +172.56 396.64 536.85 489.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +165.88 403 531.27 494.57 R +7 X +V +0 X +N +170.42 407 526.7 489.62 R +7 X +V +5 9 Q +0 X +(host1:> cdevUtil) 170.42 483.62 T +(>) 170.42 472.62 T +6 F +(IPM1S01 get VAL) 181.22 472.62 T +5 F +(> SUCCESS: Device: IPM1S01 - Message: get VAL - Value: 0) 170.42 461.62 T +(>) 170.42 450.62 T +6 F +(IPM1S01 set VAL value=1.0) 181.22 450.62 T +5 F +(> SUCCESS: Device: IPM1S01 - Message: set VAL - Value: None) 170.42 439.62 T +(>) 170.42 428.62 T +6 F +(quit) 181.22 428.62 T +5 F +(host1:>) 170.42 417.62 T +162 394.19 540 720 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "8" 8 +%%Page: "9" 9 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. The cddl De) 388.22 739 T +(vice De\336nition File Compiler) 446.48 739 T +0 10 Q +(9) 552.44 56.33 T +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 699 558 706 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 705.29 170.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 705.29 558 705.29 2 L +N +0 0 612 792 C +2 14 Q +0 X +0 0 0 1 0 0 0 K +(2.) 159.32 710.67 T +(The) 180 710.67 T +3 F +(cd) 208.78 710.67 T +(dl) 224.98 710.67 T +2 F +(De) 241.32 710.67 T +(vice De\336nition File Compiler) 259 710.67 T +2 10 Q +(Over) 72 673.33 T +(vie) 94.89 673.33 T +(w) 108.64 673.33 T +0 F +0.39 (The cddl compiler is used to con) 180 673.33 P +0.39 (v) 325.53 673.33 P +0.39 (er) 330.28 673.33 P +0.39 (t the ascii te) 339.57 673.33 P +0.39 (xt de) 393.81 673.33 P +0.39 (vice de\336nition \336les into a binar) 415.58 673.33 P +0.39 (y) 551.22 673.33 P +0.39 (,) 555.22 673.33 P +1.75 (pre-processed de) 180 661.33 P +1.75 (vice de\336nition \336le) 259.26 661.33 P +1.75 (. The binar) 338.75 661.33 P +1.75 (y DDL \336les load as m) 390.35 661.33 P +1.75 (uch as tw) 493.46 661.33 P +1.75 (enty) 539.1 661.33 P +1.37 (times f) 180 649.33 P +1.37 (aster than their ascii te) 210.51 649.33 P +1.37 (xt based counter) 316.27 649.33 P +1.37 (par) 393.23 649.33 P +1.37 (ts) 408.08 649.33 P +1.37 (. Additionally) 415.71 649.33 P +1.37 (, the cddl compiler) 472.77 649.33 P +1.37 (con\336r) 180 637.33 P +1.37 (ms that no syntax errors e) 204.7 637.33 P +1.37 (xist in the ascii data \336les when the) 326.86 637.33 P +1.37 (y are compiled.) 487.45 637.33 P +-0.12 (Theref) 180 625.33 P +-0.12 (ore) 208.6 625.33 P +-0.12 (, this tool is also eff) 222.9 625.33 P +-0.12 (ect in v) 307.06 625.33 P +-0.12 (alidating the syntax and str) 338.26 625.33 P +-0.12 (ucture of the DDL \336les) 456.9 625.33 P +-0.12 (.) 555.22 625.33 P +2 F +(Location of Files) 72 596.33 T +0 F +3.76 (The source code f) 180 596.33 P +3.76 (or cddl is located in the) 271 596.33 P +3 F +3.76 ($\050CDEV\051/sr) 398.58 596.33 P +3.76 (c/utility) 450.61 596.33 P +0 F +3.76 (director) 492.15 596.33 P +3.76 (y) 525.79 596.33 P +3.76 (. This) 529.79 596.33 P +1.47 (application is automatically compiled whene) 180 584.33 P +1.47 (v) 379.55 584.33 P +1.47 (er the cde) 384.3 584.33 P +1.47 (v libr) 431.42 584.33 P +1.47 (ar) 453.9 584.33 P +1.47 (y is b) 463.09 584.33 P +1.47 (uilt. The binar) 489.17 584.33 P +1.47 (y) 553 584.33 P +-0.02 (e) 180 572.33 P +-0.02 (x) 185.26 572.33 P +-0.02 (ecutab) 189.96 572.33 P +-0.02 (le is placed in the director) 219.78 572.33 P +-0.02 (y) 333.38 572.33 P +3 F +-0.02 ($\050CDEV\051/bin/$\050T) 341.14 572.33 P +-0.02 (ARGET\051) 415.8 572.33 P +0 F +-0.02 ( when the application is) 454.13 572.33 P +0.05 (compiled) 180 560.33 P +3 F +0.05 (.) 220.01 560.33 P +0 F +0.05 (Once the cde) 225.62 560.33 P +0.05 (v libr) 284.91 560.33 P +0.05 (ar) 305.97 560.33 P +0.05 (ies and applications are compiled, this director) 315.01 560.33 P +0.05 (y should) 520.71 560.33 P +(be placed in y) 180 548.33 T +(our search path.) 241.5 548.33 T +2 F +(Using the cd) 72 519.33 T +(dl) 131.91 519.33 T +(Compiler) 72 507.33 T +0 F +1.38 (The syntax of cddl is v) 180 519.33 P +1.38 (er) 285.59 519.33 P +1.38 (y similar to that of the C preprocessor) 294.78 519.33 P +1.38 (. The f) 470.11 519.33 P +1.38 (ollo) 500.93 519.33 P +1.38 (wing is a) 516.34 519.33 P +(sample command line f) 180 507.33 T +(or compiling the de) 282.51 507.33 T +(vice de\336nition \336le) 366.69 507.33 T +(.) 442.68 507.33 T +3 F +(cd) 198 490.33 T +(dl input\336le -o output\336le) 209.57 490.33 T +0 F +1.91 (It is impor) 180 473.33 P +1.91 (tant to note that the) 227.57 473.33 P +3 F +1.91 (input\336le) 326.09 473.33 P +0 F +1.91 (par) 369.67 473.33 P +1.91 (ameter m) 384.02 473.33 P +1.91 (ust contain a complete path) 428.06 473.33 P +-0.02 (speci\336cation to the de) 180 461.33 P +-0.02 (vice de\336nition \336le) 276.36 461.33 P +-0.02 (. An) 352.3 461.33 P +-0.02 (y errors will be repor) 369.92 461.33 P +-0.02 (ted to the screen. The) 460.8 461.33 P +(f) 180 449.33 T +(ollo) 182.48 449.33 T +(wing is the typical output from e) 197.89 449.33 T +(x) 337.65 449.33 T +(ecuting the cddl compiler) 342.35 449.33 T +(.) 452.45 449.33 T +4 9 Q +(Figure 3: T) 180 416 T +(ypical output from the cddl compiler) 224.94 416 T +180 81 558 526 C +180 359.48 558 413 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +190.56 362.64 554.85 405.14 R +0 X +0 0 0 1 0 0 0 K +V +0.5 H +2 Z +N +183.88 367.57 549.27 410.57 R +7 X +V +0 X +N +188.42 372.29 544.7 405.62 R +7 X +V +5 9 Q +0 X +(host1:> cddl ~mccops/ddl/master.ddl -o master.bdd) 188.42 399.62 T +(converted from ascii to binary ddl file!) 188.42 388.62 T +(host1:>) 188.42 377.62 T +180 81 558 526 C +0 0 612 792 C +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "9" 9 +%%Page: "10" 10 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] + 7 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(2. The cddl De) 54 739 T +(vice De\336nition File Compiler) 112.26 739 T +0 10 Q +(10) 54 56.33 T +0 9 Q +(Document Re) 452.24 56.33 T +(vision: 1) 506.99 56.33 T +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "10" 10 +%%Trailer +%%BoundingBox: 0 0 612 792 +%%PageOrder: Ascend +%%Pages: 10 +%%DocumentFonts: Helvetica +%%+ Times-BoldItalic +%%+ Helvetica-Bold +%%+ Helvetica-BoldOblique +%%+ Helvetica-Oblique +%%+ Courier-Bold +%%+ Courier-BoldOblique +%%EOF diff --git a/doc/ps/releaseNotes1_3.ps b/doc/ps/releaseNotes1_3.ps new file mode 100755 index 0000000..1351bb6 --- /dev/null +++ b/doc/ps/releaseNotes1_3.ps @@ -0,0 +1,3671 @@ +%!PS-Adobe-3.0 +%%BoundingBox: (atend) +%%Pages: (atend) +%%PageOrder: (atend) +%%DocumentFonts: (atend) +%%Creator: Frame 5.0 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +% +% Frame ps_prolog 5.0, for use with Frame 5.0 products +% This ps_prolog file is Copyright (c) 1986-1995 Frame Technology +% Corporation. All rights reserved. This ps_prolog file may be +% freely copied and distributed in conjunction with documents created +% using FrameMaker, FrameMaker/SGML and FrameViewer as long as this +% copyright notice is preserved. +% +% FrameMaker users specify the proper paper size for each print job in the +% "Print" dialog's "Printer Paper Size" "Width" and "Height~ fields. If the +% printer that the PS file is sent to does not support the requested paper +% size, or if there is no paper tray of the proper size currently installed, +% then the job will not be printed. The following flag, if set to true, will +% cause the job to print on the default paper in such cases. +/FMAllowPaperSizeMismatch false def +% +% Frame products normally print colors as their true color on a color printer +% or as shades of gray, based on luminance, on a black-and white printer. The +% following flag, if set to true, forces all non-white colors to print as pure +% black. This has no effect on bitmap images. +/FMPrintAllColorsAsBlack false def +% +% Frame products can either set their own line screens or use a printer's +% default settings. Three flags below control this separately for no +% separations, spot separations and process separations. If a flag +% is true, then the default printer settings will not be changed. If it is +% false, Frame products will use their own settings from a table based on +% the printer's resolution. +/FMUseDefaultNoSeparationScreen true def +/FMUseDefaultSpotSeparationScreen true def +/FMUseDefaultProcessSeparationScreen false def +% +% For any given PostScript printer resolution, Frame products have two sets of +% screen angles and frequencies for printing process separations, which are +% recomended by Adobe. The following variable chooses the higher frequencies +% when set to true or the lower frequencies when set to false. This is only +% effective if the appropriate FMUseDefault...SeparationScreen flag is false. +/FMUseHighFrequencyScreens true def +% +% The following is a set of predefined optimal frequencies and angles for various +% common dpi settings. This is taken from "Advances in Color Separation Using +% PostScript Software Technology," from Adobe Systems (3/13/89 P.N. LPS 0043) +% and corrolated with information which is in various PPD (4.0) files. +% +% The "dpiranges" figure is the minimum dots per inch device resolution which +% can support this setting. The "low" and "high" values are controlled by the +% setting of the FMUseHighFrequencyScreens flag above. The "TDot" flags control +% the use of the "Yellow Triple Dot" feature whereby the frequency id divided by +% three, but the dot function is "trippled" giving a block of 3x3 dots per cell. +% +% PatFreq is a compromise pattern frequency for ps Level 2 printers which is close +% to the ideal WYSIWYG pattern frequency of 9 repetitions/inch but does not beat +% (too badly) against the screen frequencies of any separations for that DPI. +/dpiranges [ 2540 2400 1693 1270 1200 635 600 0 ] def +/CMLowFreqs [ 100.402 94.8683 89.2289 100.402 94.8683 66.9349 63.2456 47.4342 ] def +/YLowFreqs [ 95.25 90.0 84.65 95.25 90.0 70.5556 66.6667 50.0 ] def +/KLowFreqs [ 89.8026 84.8528 79.8088 89.8026 84.8528 74.8355 70.7107 53.033 ] def +/CLowAngles [ 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 ] def +/MLowAngles [ 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 ] def +/YLowTDot [ true true false true true false false false ] def +/CMHighFreqs [ 133.87 126.491 133.843 108.503 102.523 100.402 94.8683 63.2456 ] def +/YHighFreqs [ 127.0 120.0 126.975 115.455 109.091 95.25 90.0 60.0 ] def +/KHighFreqs [ 119.737 113.137 119.713 128.289 121.218 89.8026 84.8528 63.6395 ] def +/CHighAngles [ 71.5651 71.5651 71.5651 70.0169 70.0169 71.5651 71.5651 71.5651 ] def +/MHighAngles [ 18.4349 18.4349 18.4349 19.9831 19.9831 18.4349 18.4349 18.4349 ] def +/YHighTDot [ false false true false false true true false ] def +/PatFreq [ 10.5833 10.0 9.4055 10.5833 10.0 10.5833 10.0 9.375 ] def +% +% PostScript Level 2 printers contain an "Accurate Screens" feature which can +% improve process separation rendering at the expense of compute time. This +% flag is ignored by PostScript Level 1 printers. +/FMUseAcccurateScreens true def +% +% The following PostScript procedure defines the spot function that Frame +% products will use for process separations. You may un-comment-out one of +% the alternative functions below, or use your own. +% +% Dot function +/FMSpotFunction {abs exch abs 2 copy add 1 gt + {1 sub dup mul exch 1 sub dup mul add 1 sub } + {dup mul exch dup mul add 1 exch sub }ifelse } def +% +% Line function +% /FMSpotFunction { pop } def +% +% Elipse function +% /FMSpotFunction { dup 5 mul 8 div mul exch dup mul exch add +% sqrt 1 exch sub } def +% +% +/FMversion (5.0) def +/fMLevel1 /languagelevel where {pop languagelevel} {1} ifelse 2 lt def +/FMPColor + fMLevel1 { + false + /colorimage where {pop pop true} if + } { + true + } ifelse +def +/FrameDict 400 dict def +systemdict /errordict known not {/errordict 10 dict def + errordict /rangecheck {stop} put} if +% The readline in PS 23.0 doesn't recognize cr's as nl's on AppleTalk +FrameDict /tmprangecheck errordict /rangecheck get put +errordict /rangecheck {FrameDict /bug true put} put +FrameDict /bug false put +mark +% Some PS machines read past the CR, so keep the following 3 lines together! +currentfile 5 string readline +00 +0000000000 +cleartomark +errordict /rangecheck FrameDict /tmprangecheck get put +FrameDict /bug get { + /readline { + /gstring exch def + /gfile exch def + /gindex 0 def + { + gfile read pop + dup 10 eq {exit} if + dup 13 eq {exit} if + gstring exch gindex exch put + /gindex gindex 1 add def + } loop + pop + gstring 0 gindex getinterval true + } bind def + } if +/FMshowpage /showpage load def +/FMquit /quit load def +/FMFAILURE { + dup = flush + FMshowpage + /Helvetica findfont 12 scalefont setfont + 72 200 moveto show + 72 220 moveto show + FMshowpage + FMquit + } def +/FMVERSION { + FMversion ne { + (Frame product version does not match ps_prolog! Check installation;) + (also check ~/fminit and ./fminit for old versions) FMFAILURE + } if + } def +/FMBADEPSF { + (Adobe's PostScript Language Reference Manual, 2nd Edition, section H.2.4) + (says your EPS file is not valid, as it calls X ) + dup dup (X) search pop exch pop exch pop length + 5 -1 roll + putinterval + FMFAILURE + } def +/fmConcatProcs + { + /proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def + newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx +}def +FrameDict begin [ + /ALDsave + /FMdicttop + /FMoptop + /FMpointsize + /FMsaveobject + /b + /bitmapsave + /blut + /bpside + /bs + /bstring + /bwidth + /c + /cf + /cs + /cynu + /depth + /edown + /fh + /fillvals + /fw + /fx + /fy + /g + /gfile + /gindex + /grnt + /gryt + /gstring + /height + /hh + /i + /im + /indx + /is + /k + /kk + /landscape + /lb + /len + /llx + /lly + /m + /magu + /manualfeed + /n + /offbits + /onbits + /organgle + /orgbangle + /orgbfreq + /orgbproc + /orgbxfer + /orgfreq + /orggangle + /orggfreq + /orggproc + /orggxfer + /orgmatrix + /orgproc + /orgrangle + /orgrfreq + /orgrproc + /orgrxfer + /orgxfer + /pagesave + /paperheight + /papersizedict + /paperwidth + /pos + /pwid + /r + /rad + /redt + /sl + /str + /tran + /u + /urx + /ury + /val + /width + /width + /ws + /ww + /x + /x1 + /x2 + /xindex + /xpoint + /xscale + /xx + /y + /y1 + /y2 + /yelu + /yindex + /ypoint + /yscale + /yy +] { 0 def } forall +/FmBD {bind def} bind def +systemdict /pdfmark known { + /fMAcrobat true def + + /FmPD /pdfmark load def + + + /FmPT /show load def + + + currentdistillerparams /CoreDistVersion get 2000 ge { + + + /FmPD2 /pdfmark load def + + + + + + /FmPA { mark exch /Dest exch 5 3 roll + /View [ /XYZ null 6 -2 roll FmDC exch pop null] /DEST FmPD + }FmBD + } { + + /FmPD2 /cleartomark load def + /FmPA {pop pop pop}FmBD + } ifelse +} { + + /fMAcrobat false def + /FmPD /cleartomark load def + /FmPD2 /cleartomark load def + /FmPT /pop load def + /FmPA {pop pop pop}FmBD +} ifelse +/FmDC { + transform fMDefaultMatrix itransform cvi exch cvi exch +}FmBD +/FmBx { + dup 3 index lt {3 1 roll exch} if + 1 index 4 index lt {4 -1 roll 3 1 roll exch 4 1 roll} if +}FmBD +/FMnone 0 def +/FMcyan 1 def +/FMmagenta 2 def +/FMyellow 3 def +/FMblack 4 def +/FMcustom 5 def +/fMNegative false def +/FrameSepIs FMnone def +/FrameSepBlack 0 def +/FrameSepYellow 0 def +/FrameSepMagenta 0 def +/FrameSepCyan 0 def +/FrameSepRed 1 def +/FrameSepGreen 1 def +/FrameSepBlue 1 def +/FrameCurGray 1 def +/FrameCurPat null def +/FrameCurColors [ 0 0 0 1 0 0 0 ] def +/FrameColorEpsilon .001 def +/eqepsilon { + sub dup 0 lt {neg} if + FrameColorEpsilon le +} bind def +/FrameCmpColorsCMYK { + 2 copy 0 get exch 0 get eqepsilon { + 2 copy 1 get exch 1 get eqepsilon { + 2 copy 2 get exch 2 get eqepsilon { + 3 get exch 3 get eqepsilon + } {pop pop false} ifelse + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/FrameCmpColorsRGB { + 2 copy 4 get exch 0 get eqepsilon { + 2 copy 5 get exch 1 get eqepsilon { + 6 get exch 2 get eqepsilon + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/RGBtoCMYK { + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 3 copy + 2 copy + le { pop } { exch pop } ifelse + 2 copy + le { pop } { exch pop } ifelse + dup dup dup + 6 1 roll + 4 1 roll + 7 1 roll + sub + 6 1 roll + sub + 5 1 roll + sub + 4 1 roll +} bind def +/CMYKtoRGB { + dup dup 4 -1 roll add + 5 1 roll 3 -1 roll add + 4 1 roll add + 1 exch sub dup 0 lt {pop 0} if 3 1 roll + 1 exch sub dup 0 lt {pop 0} if exch + 1 exch sub dup 0 lt {pop 0} if exch +} bind def +/FrameSepInit { + 1.0 RealSetgray +} bind def +/FrameSetSepColor { + /FrameSepBlue exch def + /FrameSepGreen exch def + /FrameSepRed exch def + /FrameSepBlack exch def + /FrameSepYellow exch def + /FrameSepMagenta exch def + /FrameSepCyan exch def + /FrameSepIs FMcustom def + setCurrentScreen +} bind def +/FrameSetCyan { + /FrameSepBlue 1.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 1.0 def + /FrameSepIs FMcyan def + setCurrentScreen +} bind def + +/FrameSetMagenta { + /FrameSepBlue 1.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 1.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMmagenta def + setCurrentScreen +} bind def + +/FrameSetYellow { + /FrameSepBlue 0.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 1.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMyellow def + setCurrentScreen +} bind def + +/FrameSetBlack { + /FrameSepBlue 0.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 1.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMblack def + setCurrentScreen +} bind def + +/FrameNoSep { + /FrameSepIs FMnone def + setCurrentScreen +} bind def +/FrameSetSepColors { + FrameDict begin + [ exch 1 add 1 roll ] + /FrameSepColors + exch def end + } bind def +/FrameColorInSepListCMYK { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsCMYK + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/FrameColorInSepListRGB { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsRGB + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/RealSetgray /setgray load def +/RealSetrgbcolor /setrgbcolor load def +/RealSethsbcolor /sethsbcolor load def +end +/setgray { + FrameDict begin + FrameSepIs FMnone eq + { RealSetgray } + { + FrameSepIs FMblack eq + { RealSetgray } + { FrameSepIs FMcustom eq + FrameSepRed 0 eq and + FrameSepGreen 0 eq and + FrameSepBlue 0 eq and { + RealSetgray + } { + 1 RealSetgray pop + } ifelse + } ifelse + } ifelse + end +} bind def +/setrgbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetrgbcolor } + { + 3 copy [ 4 1 roll ] + FrameColorInSepListRGB + { + FrameSepBlue eq exch + FrameSepGreen eq and exch + FrameSepRed eq and + { 0 } { 1 } ifelse + } + { + FMPColor { + RealSetrgbcolor + currentcmykcolor + } { + RGBtoCMYK + } ifelse + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end +} bind def +/sethsbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSethsbcolor } + { + RealSethsbcolor + currentrgbcolor + setrgbcolor + } + ifelse + end +} bind def +FrameDict begin +/setcmykcolor where { + pop /RealSetcmykcolor /setcmykcolor load def +} { + /RealSetcmykcolor { + 4 1 roll + 3 { 3 index add 0 max 1 min 1 exch sub 3 1 roll} repeat + RealSetrgbcolor pop + } bind def +} ifelse +userdict /setcmykcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetcmykcolor } + { + 4 copy [ 5 1 roll ] + FrameColorInSepListCMYK + { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + { 0 } { 1 } ifelse + } + { + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end + } bind put +fMLevel1 { + + + + /patScreenDict 7 dict dup begin + <0f1e3c78f0e1c387> [ 45 { pop } {exch pop} .5 2 sqrt] FmBD + <0f87c3e1f0783c1e> [ 135 { pop } {exch pop} .5 2 sqrt] FmBD + [ 0 { pop } dup .5 2 ] FmBD + [ 90 { pop } dup .5 2 ] FmBD + <8142241818244281> [ 45 { 2 copy lt {exch} if pop} dup .75 2 sqrt] FmBD + <03060c183060c081> [ 45 { pop } {exch pop} .875 2 sqrt] FmBD + <8040201008040201> [ 135 { pop } {exch pop} .875 2 sqrt] FmBD + end def +} { + + /patProcDict 5 dict dup begin + <0f1e3c78f0e1c387> { 3 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <0f87c3e1f0783c1e> { 3 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + <8142241818244281> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -1 -1 moveto 9 9 lineto stroke } bind def + <03060c183060c081> { 1 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <8040201008040201> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + end def + /patDict 15 dict dup begin + /PatternType 1 def + /PaintType 2 def + /TilingType 3 def + /BBox [ 0 0 8 8 ] def + /XStep 8 def + /YStep 8 def + /PaintProc { + begin + patProcDict bstring known { + patProcDict bstring get exec + } { + 8 8 true [1 0 0 -1 0 8] bstring imagemask + } ifelse + end + } bind def + end def +} ifelse +/combineColor { + FrameSepIs FMnone eq + { + graymode fMLevel1 or not { + + [/Pattern [/DeviceCMYK]] setcolorspace + FrameCurColors 0 4 getinterval aload pop FrameCurPat setcolor + } { + FrameCurColors 3 get 1.0 ge { + FrameCurGray RealSetgray + } { + fMAcrobat not FMPColor graymode and and { + 0 1 3 { + FrameCurColors exch get + 1 FrameCurGray sub mul + } for + RealSetcmykcolor + } { + 4 1 6 { + FrameCurColors exch get + graymode { + 1 exch sub 1 FrameCurGray sub mul 1 exch sub + } { + 1.0 lt {FrameCurGray} {1} ifelse + } ifelse + } for + RealSetrgbcolor + } ifelse + } ifelse + } ifelse + } { + FrameCurColors 0 4 getinterval aload + FrameColorInSepListCMYK { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + FrameSepIs FMcustom eq and + { FrameCurGray } { 1 } ifelse + } { + FrameSepIs FMblack eq + {FrameCurGray 1.0 exch sub mul 1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop FrameCurGray 1.0 exch sub mul 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + graymode fMLevel1 or not { + + [/Pattern [/DeviceGray]] setcolorspace + FrameCurPat setcolor + } { + graymode not fMLevel1 and { + + dup 1 lt {pop FrameCurGray} if + } if + RealSetgray + } ifelse + } ifelse +} bind def +/savematrix { + orgmatrix currentmatrix pop + } bind def +/restorematrix { + orgmatrix setmatrix + } bind def +/fMDefaultMatrix matrix defaultmatrix def +/fMatrix2 matrix def +/dpi 72 0 fMDefaultMatrix dtransform + dup mul exch dup mul add sqrt def + +/freq dpi dup 72 div round dup 0 eq {pop 1} if 8 mul div def +/sangle 1 0 fMDefaultMatrix dtransform exch atan def + sangle fMatrix2 rotate + fMDefaultMatrix fMatrix2 concatmatrix + dup 0 get /sflipx exch def + 3 get /sflipy exch def +/screenIndex { + 0 1 dpiranges length 1 sub { dup dpiranges exch get 1 sub dpi le {exit} {pop} ifelse } for +} bind def +/getCyanScreen { + FMUseHighFrequencyScreens { CHighAngles CMHighFreqs} {CLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getMagentaScreen { + FMUseHighFrequencyScreens { MHighAngles CMHighFreqs } {MLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getYellowScreen { + FMUseHighFrequencyScreens { YHighTDot YHighFreqs} { YLowTDot YLowFreqs } ifelse + screenIndex dup 3 1 roll get 3 1 roll get { 3 div + {2 { 1 add 2 div 3 mul dup floor sub 2 mul 1 sub exch} repeat + FMSpotFunction } } {/FMSpotFunction load } ifelse + 0.0 exch +} bind def +/getBlackScreen { + FMUseHighFrequencyScreens { KHighFreqs } { KLowFreqs } ifelse + screenIndex get 45.0 /FMSpotFunction load +} bind def +/getSpotScreen { + getBlackScreen +} bind def +/getCompositeScreen { + getBlackScreen +} bind def +/FMSetScreen + fMLevel1 { /setscreen load + }{ { + 8 dict begin + /HalftoneType 1 def + /SpotFunction exch def + /Angle exch def + /Frequency exch def + /AccurateScreens FMUseAcccurateScreens def + currentdict end sethalftone + } bind } ifelse +def +/setDefaultScreen { + FMPColor { + orgrxfer cvx orggxfer cvx orgbxfer cvx orgxfer cvx setcolortransfer + } + { + orgxfer cvx settransfer + } ifelse + orgfreq organgle orgproc cvx setscreen +} bind def +/setCurrentScreen { + FrameSepIs FMnone eq { + FMUseDefaultNoSeparationScreen { + setDefaultScreen + } { + getCompositeScreen FMSetScreen + } ifelse + } { + FrameSepIs FMcustom eq { + FMUseDefaultSpotSeparationScreen { + setDefaultScreen + } { + getSpotScreen FMSetScreen + } ifelse + } { + FMUseDefaultProcessSeparationScreen { + setDefaultScreen + } { + FrameSepIs FMcyan eq { + getCyanScreen FMSetScreen + } { + FrameSepIs FMmagenta eq { + getMagentaScreen FMSetScreen + } { + FrameSepIs FMyellow eq { + getYellowScreen FMSetScreen + } { + getBlackScreen FMSetScreen + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse +} bind def +end + +/FMDOCUMENT { + array /FMfonts exch def + /#copies exch def + FrameDict begin + 0 ne /manualfeed exch def + /paperheight exch def + /paperwidth exch def + 0 ne /fMNegative exch def + 0 ne /edown exch def + /yscale exch def + /xscale exch def + fMLevel1 { + manualfeed {setmanualfeed} if + /FMdicttop countdictstack 1 add def + /FMoptop count def + setpapername + manualfeed {true} {papersize} ifelse + {manualpapersize} {false} ifelse + {desperatepapersize} {false} ifelse + {papersizefailure} if + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + } + {2 dict + dup /PageSize [paperwidth paperheight] put + manualfeed {dup /ManualFeed manualfeed put} if + {setpagedevice} stopped {papersizefailure} if + } + ifelse + + FMPColor { + currentcolorscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + cvlit /orgbproc exch def + /orgbangle exch def + /orgbfreq exch def + cvlit /orggproc exch def + /orggangle exch def + /orggfreq exch def + cvlit /orgrproc exch def + /orgrangle exch def + /orgrfreq exch def + currentcolortransfer + fMNegative { + 1 1 4 { + pop { 1 exch sub } fmConcatProcs 4 1 roll + } for + 4 copy + setcolortransfer + } if + cvlit /orgxfer exch def + cvlit /orgbxfer exch def + cvlit /orggxfer exch def + cvlit /orgrxfer exch def + } { + currentscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + + currenttransfer + fMNegative { + { 1 exch sub } fmConcatProcs + dup settransfer + } if + cvlit /orgxfer exch def + } ifelse + end +} def +/FMBEGINPAGE { + FrameDict begin + /pagesave save def + 3.86 setmiterlimit + /landscape exch 0 ne def + landscape { + 90 rotate 0 exch dup /pwid exch def neg translate pop + }{ + pop /pwid exch def + } ifelse + edown { [-1 0 0 1 pwid 0] concat } if + 0 0 moveto paperwidth 0 lineto paperwidth paperheight lineto + 0 paperheight lineto 0 0 lineto 1 setgray fill + xscale yscale scale + /orgmatrix matrix def + gsave +} def +/FMENDPAGE { + grestore + pagesave restore + end + showpage + } def +/FMFONTDEFINE { + FrameDict begin + findfont + ReEncode + 1 index exch + definefont + FMfonts 3 1 roll + put + end + } def +/FMFILLS { + FrameDict begin dup + array /fillvals exch def + dict /patCache exch def + end + } def +/FMFILL { + FrameDict begin + fillvals 3 1 roll put + end + } def +/FMNORMALIZEGRAPHICS { + newpath + 1 setlinewidth + 0 setlinecap + 0 0 0 sethsbcolor + 0 setgray + } bind def +/FMBEGINEPSF { + end + /FMEPSF save def + /showpage {} def +% See Adobe's "PostScript Language Reference Manual, 2nd Edition", page 714. +% "...the following operators MUST NOT be used in an EPS file:" (emphasis ours) + /banddevice {(banddevice) FMBADEPSF} def + /clear {(clear) FMBADEPSF} def + /cleardictstack {(cleardictstack) FMBADEPSF} def + /copypage {(copypage) FMBADEPSF} def + /erasepage {(erasepage) FMBADEPSF} def + /exitserver {(exitserver) FMBADEPSF} def + /framedevice {(framedevice) FMBADEPSF} def + /grestoreall {(grestoreall) FMBADEPSF} def + /initclip {(initclip) FMBADEPSF} def + /initgraphics {(initgraphics) FMBADEPSF} def + /quit {(quit) FMBADEPSF} def + /renderbands {(renderbands) FMBADEPSF} def + /setglobal {(setglobal) FMBADEPSF} def + /setpagedevice {(setpagedevice) FMBADEPSF} def + /setshared {(setshared) FMBADEPSF} def + /startjob {(startjob) FMBADEPSF} def + /lettertray {(lettertray) FMBADEPSF} def + /letter {(letter) FMBADEPSF} def + /lettersmall {(lettersmall) FMBADEPSF} def + /11x17tray {(11x17tray) FMBADEPSF} def + /11x17 {(11x17) FMBADEPSF} def + /ledgertray {(ledgertray) FMBADEPSF} def + /ledger {(ledger) FMBADEPSF} def + /legaltray {(legaltray) FMBADEPSF} def + /legal {(legal) FMBADEPSF} def + /statementtray {(statementtray) FMBADEPSF} def + /statement {(statement) FMBADEPSF} def + /executivetray {(executivetray) FMBADEPSF} def + /executive {(executive) FMBADEPSF} def + /a3tray {(a3tray) FMBADEPSF} def + /a3 {(a3) FMBADEPSF} def + /a4tray {(a4tray) FMBADEPSF} def + /a4 {(a4) FMBADEPSF} def + /a4small {(a4small) FMBADEPSF} def + /b4tray {(b4tray) FMBADEPSF} def + /b4 {(b4) FMBADEPSF} def + /b5tray {(b5tray) FMBADEPSF} def + /b5 {(b5) FMBADEPSF} def + FMNORMALIZEGRAPHICS + [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall + fx fw 2 div add fy fh 2 div add translate + rotate + fw 2 div neg fh 2 div neg translate + fw urx llx sub div fh ury lly sub div scale + llx neg lly neg translate + /FMdicttop countdictstack 1 add def + /FMoptop count def + } bind def +/FMENDEPSF { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMEPSF restore + FrameDict begin + } bind def +FrameDict begin +/setmanualfeed { +%%BeginFeature *ManualFeed True + statusdict /manualfeed true put +%%EndFeature + } bind def +/max {2 copy lt {exch} if pop} bind def +/min {2 copy gt {exch} if pop} bind def +/inch {72 mul} def +/pagedimen { + paperheight sub abs 16 lt exch + paperwidth sub abs 16 lt and + {/papername exch def} {pop} ifelse + } bind def +/setpapername { + /papersizedict 14 dict def + papersizedict begin + /papername /unknown def + /Letter 8.5 inch 11.0 inch pagedimen + /LetterSmall 7.68 inch 10.16 inch pagedimen + /Tabloid 11.0 inch 17.0 inch pagedimen + /Ledger 17.0 inch 11.0 inch pagedimen + /Legal 8.5 inch 14.0 inch pagedimen + /Statement 5.5 inch 8.5 inch pagedimen + /Executive 7.5 inch 10.0 inch pagedimen + /A3 11.69 inch 16.5 inch pagedimen + /A4 8.26 inch 11.69 inch pagedimen + /A4Small 7.47 inch 10.85 inch pagedimen + /B4 10.125 inch 14.33 inch pagedimen + /B5 7.16 inch 10.125 inch pagedimen + end + } bind def +/papersize { + papersizedict begin + /Letter {lettertray letter} def + /LetterSmall {lettertray lettersmall} def + /Tabloid {11x17tray 11x17} def + /Ledger {ledgertray ledger} def + /Legal {legaltray legal} def + /Statement {statementtray statement} def + /Executive {executivetray executive} def + /A3 {a3tray a3} def + /A4 {a4tray a4} def + /A4Small {a4tray a4small} def + /B4 {b4tray b4} def + /B5 {b5tray b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + statusdict begin stopped end + } bind def +/manualpapersize { + papersizedict begin + /Letter {letter} def + /LetterSmall {lettersmall} def + /Tabloid {11x17} def + /Ledger {ledger} def + /Legal {legal} def + /Statement {statement} def + /Executive {executive} def + /A3 {a3} def + /A4 {a4} def + /A4Small {a4small} def + /B4 {b4} def + /B5 {b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + stopped + } bind def +/desperatepapersize { + statusdict /setpageparams known + { + paperwidth paperheight 0 1 + statusdict begin + {setpageparams} stopped + end + } {true} ifelse + } bind def +/papersizefailure { + FMAllowPaperSizeMismatch not + { +(The requested paper size is not available in any currently-installed tray) +(Edit the PS file to "FMAllowPaperSizeMismatch true" to use default tray) + FMFAILURE } if + } def +/DiacriticEncoding [ +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl +/numbersign /dollar /percent /ampersand /quotesingle /parenleft +/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K +/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash +/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h +/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar +/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute +/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis +/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis +/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve +/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex +/udieresis /dagger /.notdef /cent /sterling /section /bullet +/paragraph /germandbls /registered /copyright /trademark /acute +/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef +/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown +/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef +/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde +/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright +/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis +/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl +/periodcentered /quotesinglbase /quotedblbase /perthousand +/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute +/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve +/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron +/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +] def +/ReEncode { + dup + length + dict begin + { + 1 index /FID ne + {def} + {pop pop} ifelse + } forall + 0 eq {/Encoding DiacriticEncoding def} if + currentdict + end + } bind def +FMPColor + + { + /BEGINBITMAPCOLOR { + BITMAPCOLOR} def + /BEGINBITMAPCOLORc { + BITMAPCOLORc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUECOLOR } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUECOLORc } def + /BEGINBITMAPCMYK { + BITMAPCMYK } def + /BEGINBITMAPCMYKc { + BITMAPCMYKc } def + } + + { + /BEGINBITMAPCOLOR { + BITMAPGRAY} def + /BEGINBITMAPCOLORc { + BITMAPGRAYc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUEGRAY } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUEGRAYc } def + /BEGINBITMAPCMYK { + BITMAPCMYKGRAY } def + /BEGINBITMAPCMYKc { + BITMAPCMYKGRAYc } def + } +ifelse +/K { + FMPrintAllColorsAsBlack { + dup 1 eq 2 index 1 eq and 3 index 1 eq and not + {7 {pop} repeat 0 0 0 1 0 0 0} if + } if + FrameCurColors astore + pop combineColor +} bind def +/graymode true def +fMLevel1 { + /fmGetFlip { + fMatrix2 exch get mul 0 lt { -1 } { 1 } ifelse + } FmBD +} if +/setPatternMode { + fMLevel1 { + 2 index patScreenDict exch known { + pop pop + patScreenDict exch get aload pop + freq + mul + 5 2 roll + fMatrix2 currentmatrix 1 get 0 ne { + 3 -1 roll 90 add 3 1 roll + sflipx 1 fmGetFlip sflipy 2 fmGetFlip neg mul + } { + sflipx 0 fmGetFlip sflipy 3 fmGetFlip mul + } ifelse + 0 lt {exch pop} {pop} ifelse + fMNegative { + {neg} fmConcatProcs + } if + bind + + + + systemdict /setscreen get exec + /FrameCurGray exch def + } { + /bwidth exch def + /bpside exch def + /bstring exch def + /onbits 0 def /offbits 0 def + freq sangle landscape {90 add} if + {/ypoint exch def + /xpoint exch def + /xindex xpoint 1 add 2 div bpside mul cvi def + /yindex ypoint 1 add 2 div bpside mul cvi def + bstring yindex bwidth mul xindex 8 idiv add get + 1 7 xindex 8 mod sub bitshift and 0 ne fMNegative {not} if + {/onbits onbits 1 add def 1} + {/offbits offbits 1 add def 0} + ifelse + } + setscreen + offbits offbits onbits add div fMNegative {1.0 exch sub} if + /FrameCurGray exch def + } ifelse + } { + pop pop + dup patCache exch known { + patCache exch get + } { + dup + patDict /bstring 3 -1 roll put + patDict + 9 PatFreq screenIndex get div dup matrix scale + makepattern + dup + patCache 4 -1 roll 3 -1 roll put + } ifelse + /FrameCurGray 0 def + /FrameCurPat exch def + } ifelse + /graymode false def + combineColor +} bind def +/setGrayScaleMode { + graymode not { + /graymode true def + fMLevel1 { + setCurrentScreen + } if + } if + /FrameCurGray exch def + combineColor +} bind def +/normalize { + transform round exch round exch itransform + } bind def +/dnormalize { + dtransform round exch round exch idtransform + } bind def +/lnormalize { + 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop + } bind def +/H { + lnormalize setlinewidth + } bind def +/Z { + setlinecap + } bind def + +/PFill { + graymode fMLevel1 or not { + gsave 1 setgray eofill grestore + } if +} bind def +/PStroke { + graymode fMLevel1 or not { + gsave 1 setgray stroke grestore + } if + stroke +} bind def +/X { + fillvals exch get + dup type /stringtype eq + {8 1 setPatternMode} + {setGrayScaleMode} + ifelse + } bind def +/V { + PFill gsave eofill grestore + } bind def +/Vclip { + clip + } bind def +/Vstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/N { + PStroke + } bind def +/Nclip { + strokepath clip newpath + } bind def +/Nstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/M {newpath moveto} bind def +/E {lineto} bind def +/D {curveto} bind def +/O {closepath} bind def +/L { + /n exch def + newpath + normalize + moveto + 2 1 n {pop normalize lineto} for + } bind def +/Y { + L + closepath + } bind def +/R { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + x1 y1 + x2 y1 + x2 y2 + x1 y2 + 4 Y + } bind def +/rarc + {rad + arcto + } bind def +/RR { + /rad exch def + normalize + /y2 exch def + /x2 exch def + normalize + /y1 exch def + /x1 exch def + mark + newpath + { + x1 y1 rad add moveto + x1 y2 x2 y2 rarc + x2 y2 x2 y1 rarc + x2 y1 x1 y1 rarc + x1 y1 x1 y2 rarc + closepath + } stopped {x1 y1 x2 y2 R} if + cleartomark + } bind def +/RRR { + /rad exch def + normalize /y4 exch def /x4 exch def + normalize /y3 exch def /x3 exch def + normalize /y2 exch def /x2 exch def + normalize /y1 exch def /x1 exch def + newpath + normalize moveto + mark + { + x2 y2 x3 y3 rarc + x3 y3 x4 y4 rarc + x4 y4 x1 y1 rarc + x1 y1 x2 y2 rarc + closepath + } stopped + {x1 y1 x2 y2 x3 y3 x4 y4 newpath moveto lineto lineto lineto closepath} if + cleartomark + } bind def +/C { + grestore + gsave + R + clip + setCurrentScreen +} bind def +/CP { + grestore + gsave + Y + clip + setCurrentScreen +} bind def +/F { + FMfonts exch get + FMpointsize scalefont + setfont + } bind def +/Q { + /FMpointsize exch def + F + } bind def +/T { + moveto show + } bind def +/RF { + rotate + 0 ne {-1 1 scale} if + } bind def +/TF { + gsave + moveto + RF + show + grestore + } bind def +/P { + moveto + 0 32 3 2 roll widthshow + } bind def +/PF { + gsave + moveto + RF + 0 32 3 2 roll widthshow + grestore + } bind def +/S { + moveto + 0 exch ashow + } bind def +/SF { + gsave + moveto + RF + 0 exch ashow + grestore + } bind def +/B { + moveto + 0 32 4 2 roll 0 exch awidthshow + } bind def +/BF { + gsave + moveto + RF + 0 32 4 2 roll 0 exch awidthshow + grestore + } bind def +/G { + gsave + newpath + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill fill + grestore + } bind def +/Gstrk { + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/Gclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GG { + gsave + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill + fill + grestore + } bind def +/GGclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GGstrk { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/A { + gsave + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/Aclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/Astrk { + Gstrk +} bind def +/AA { + gsave + savematrix + newpath + + 3 index 2 div add exch 4 index 2 div sub exch + + normalize 3 index 2 div sub exch 4 index 2 div add exch + translate + rotate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/AAclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/AAstrk { + GGstrk +} bind def +/BEGINPRINTCODE { + /FMdicttop countdictstack 1 add def + /FMoptop count 7 sub def + /FMsaveobject save def + userdict begin + /showpage {} def + FMNORMALIZEGRAPHICS + 3 index neg 3 index neg translate + } bind def +/ENDPRINTCODE { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMsaveobject restore + } bind def +/gn { + 0 + { 46 mul + cf read pop + 32 sub + dup 46 lt {exit} if + 46 sub add + } loop + add + } bind def +/cfs { + /str sl string def + 0 1 sl 1 sub {str exch val put} for + str def + } bind def +/ic [ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 + {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx} + {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx} + {19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} + {13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh} + {4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh} + {13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl} + {7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl} + {0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl} + {10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl} + ] def +/ms { + /sl exch def + /val 255 def + /ws cfs + /im cfs + /val 0 def + /bs cfs + /cs cfs + } bind def +400 ms +/ip { + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip { + + + bis ris copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + ris gis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + gis bis copy pop + dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip4 { + + + kis cis copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + cis mis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + mis yis copy pop + dup dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + yis kis copy pop + 3 mul is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/wh { + /len exch def + /pos exch def + ws 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/bl { + /len exch def + /pos exch def + bs 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/s1 1 string def +/fl { + /len exch def + /pos exch def + /val cf s1 readhexstring pop 0 get def + pos 1 pos len add 1 sub {im exch val put} for + pos len + } bind def +/hx { + 3 copy getinterval + cf exch readhexstring pop pop + } bind def +/wbytes { + dup dup + 8 gt { pop 8 idiv mul } + { 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse } ifelse + } bind def +/BEGINBITMAPBWc { + 1 {} COMMONBITMAPc + } bind def +/BEGINBITMAPGRAYc { + 8 {} COMMONBITMAPc + } bind def +/BEGINBITMAP2BITc { + 2 {} COMMONBITMAPc + } bind def +/COMMONBITMAPc { + + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + cvtProc + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} image + bitmapsave restore + grestore + } bind def +/BEGINBITMAPBW { + 1 {} COMMONBITMAP + } bind def +/BEGINBITMAPGRAY { + 8 {} COMMONBITMAP + } bind def +/BEGINBITMAP2BIT { + 2 {} COMMONBITMAP + } bind def +/COMMONBITMAP { + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + cvtProc + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} image + bitmapsave restore + grestore + } bind def +/ngrayt 256 array def +/nredt 256 array def +/nbluet 256 array def +/ngreent 256 array def +fMLevel1 { +/colorsetup { + currentcolortransfer + /gryt exch def + /blut exch def + /grnt exch def + /redt exch def + 0 1 255 { + /indx exch def + /cynu 1 red indx get 255 div sub def + /magu 1 green indx get 255 div sub def + /yelu 1 blue indx get 255 div sub def + /kk cynu magu min yelu min def + /u kk currentundercolorremoval exec def +% /u 0 def + nredt indx 1 0 cynu u sub max sub redt exec put + ngreent indx 1 0 magu u sub max sub grnt exec put + nbluet indx 1 0 yelu u sub max sub blut exec put + ngrayt indx 1 kk currentblackgeneration exec sub gryt exec put + } for + {255 mul cvi nredt exch get} + {255 mul cvi ngreent exch get} + {255 mul cvi nbluet exch get} + {255 mul cvi ngrayt exch get} + setcolortransfer + {pop 0} setundercolorremoval + {} setblackgeneration + } bind def +} +{ +/colorSetup2 { + [ /Indexed /DeviceRGB 255 + {dup red exch get 255 div + exch dup green exch get 255 div + exch blue exch get 255 div} + ] setcolorspace +} bind def +} ifelse +/fakecolorsetup { + /tran 256 string def + 0 1 255 {/indx exch def + tran indx + red indx get 77 mul + green indx get 151 mul + blue indx get 28 mul + add add 256 idiv put} for + currenttransfer + {255 mul cvi tran exch get 255.0 div} + exch fmConcatProcs settransfer +} bind def +/BITMAPCOLOR { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + fMLevel1 { + colorsetup + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} {is} {is} true 3 colorimage + } { + colorSetup2 + /is width depth wbytes string def + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {cf is readhexstring pop} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPCOLORc { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + fMLevel1 { + colorsetup + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} {is} {is} true 3 colorimage + } { + colorSetup2 + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {ip} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLORc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris} {gis} {bis} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYKc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip4 pop cis} {mis} {yis} {kis} true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLOR { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf gis readhexstring pop } + { cf bis readhexstring pop } + true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYK { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /mis width string def + /yis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf mis readhexstring pop } + { cf yis readhexstring pop } + { cf kis readhexstring pop } + true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUEGRAYc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris gis bis width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAYc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop cis mis yis kis width cgray} image + bitmapsave restore + grestore + } bind def +/cgray { + /ww exch def + /k exch def + /y exch def + /m exch def + /c exch def + 0 1 ww 1 sub { /i exch def c i get m i get y i get k i get CMYKtoRGB + .144 mul 3 1 roll .587 mul 3 1 roll .299 mul add add + c i 3 -1 roll floor cvi put } for + c + } bind def +/gray { + /ww exch def + /b exch def + /g exch def + /r exch def + 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul + b i get .114 mul add add r i 3 -1 roll floor cvi put } for + r + } bind def +/BITMAPTRUEGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf gis readhexstring pop + cf bis readhexstring pop width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /yis width string def + /mis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf mis readhexstring pop + cf yis readhexstring pop + cf kis readhexstring pop width cgray} image + bitmapsave restore + grestore + } bind def +/BITMAPGRAY { + 8 {fakecolorsetup} COMMONBITMAP + } bind def +/BITMAPGRAYc { + 8 {fakecolorsetup} COMMONBITMAPc + } bind def +/ENDBITMAP { + } bind def +end + /ALDmatrix matrix def ALDmatrix currentmatrix pop +/StartALD { + /ALDsave save def + savematrix + ALDmatrix setmatrix + } bind def +/InALD { + restorematrix + } bind def +/DoneALD { + ALDsave restore + } bind def +/I { setdash } bind def +/J { [] 0 setdash } bind def +%%EndProlog +%%BeginSetup +(5.0) FMVERSION +1 1 0 0 612 792 0 1 6 FMDOCUMENT +0 0 /Helvetica FMFONTDEFINE +1 0 /Times-Roman FMFONTDEFINE +2 0 /Times-Bold FMFONTDEFINE +3 0 /Times-Italic FMFONTDEFINE +4 0 /Times-BoldItalic FMFONTDEFINE +32 FMFILLS +0 0 FMFILL +1 0.1 FMFILL +2 0.3 FMFILL +3 0.5 FMFILL +4 0.7 FMFILL +5 0.9 FMFILL +6 0.97 FMFILL +7 1 FMFILL +8 <0f1e3c78f0e1c387> FMFILL +9 <0f87c3e1f0783c1e> FMFILL +10 FMFILL +11 FMFILL +12 <8142241818244281> FMFILL +13 <03060c183060c081> FMFILL +14 <8040201008040201> FMFILL +16 1 FMFILL +17 0.9 FMFILL +18 0.7 FMFILL +19 0.5 FMFILL +20 0.3 FMFILL +21 0.1 FMFILL +22 0.03 FMFILL +23 0 FMFILL +24 FMFILL +25 FMFILL +26 <3333333333333333> FMFILL +27 <0000ffff0000ffff> FMFILL +28 <7ebddbe7e7dbbd7e> FMFILL +29 FMFILL +30 <7fbfdfeff7fbfdfe> FMFILL +%%EndSetup +%%Page: "5" 1 +%%BeginPaperSize: Letter +%%EndPaperSize +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. cdev Applications) 477.96 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdev 1.3 Release Notes) 267.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(5) 552.44 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +3.42 (Other applications will soon become a) 180 713.33 P +3.42 (v) 350.47 713.33 P +3.42 (ailable from other sites, and the most current) 355.22 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(information will be a) 180 701.33 T +(v) 263.96 701.33 T +(ailable from the cde) 268.71 701.33 T +(v web site, http://www) 348.16 701.33 T +(.cebaf.go) 438.62 701.33 T +(v/cde) 475.12 701.33 T +(v) 496.53 701.33 T +(.) 500.88 701.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "5" 1 +%%Page: "4" 2 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Planned Enhancements) 54 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(4) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(cdev 1.3 Release Notes) 249.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Document Revision: 1) 451.97 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Still Planned:) 162 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 695.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.26 (a simple service for which you need only pro) 189 695.33 P +0.26 (vide synchronous read and write routines.) 371.49 695.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.86 (This will speed up inte) 189 683.33 P +1.86 (grating a simple synchronous RPC or memory image based) 287.39 683.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(system.) 189 671.33 T +0 0 0 1 0 0 0 K +54 613 540 620 C +0 0 0 1 0 0 0 K +54 619.29 152.57 619.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 619.29 540 619.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(8.) 142.5 624.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Planned Enhancements) 162 624.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +0.46 (There are man) 162 598.33 P +0.46 (y enhancements planned for cde) 220.53 598.33 P +0.46 (v) 350.98 598.33 P +0.46 (, and releases will probably come out e) 355.33 598.33 P +0.46 (v) 514.41 598.33 P +0.46 (ery 3) 519.27 598.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.26 (months for a while. The follo) 162 586.33 P +0.26 (wing is a list of topics planned for summer of 1996. W) 280.25 586.33 P +0.26 (ork on all) 501.15 586.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(of these topics is underw) 162 574.33 T +(ay) 261.33 574.33 T +(.) 270.12 574.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 177.5 556.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.69 (Collection de) 189 556.33 P +0.69 (vices. Created dynamically or statically) 243.05 556.33 P +0.69 (, each de) 403.18 556.33 P +0.69 (vice w) 439.57 556.33 P +0.69 (ould contain a list) 466.54 556.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.28 (of other de) 189 544.33 P +0.28 (vices. Messages w) 232.63 544.33 P +0.28 (ould be repeated to all contained de) 307.24 544.33 P +0.28 (vices, and read results) 450.85 544.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.53 (w) 189 532.33 P +0.53 (ould be collected together and returned to the caller as a v) 196.12 532.33 P +0.53 (ector) 433.11 532.33 P +0.53 (. Implementation will) 452.55 532.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.23 (support passing the list do) 189 520.33 P +0.23 (wn to the service instead of iterating in the cde) 294.14 520.33 P +0.23 (v layer so that) 482.92 520.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(list based services \050such as SLA) 189 508.33 T +(C\325) 317.19 508.33 T +(s\051 can optimize performance.) 326.64 508.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 177.5 493.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.57 (Service + Serv) 189 493.33 P +0.57 (er based upon passing cde) 248.95 493.33 P +0.57 (vData objects between client and serv) 355.39 493.33 P +0.57 (er) 509.43 493.33 P +0.57 (. This) 516.65 493.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.95 (allo) 189 481.33 P +1.95 (ws comple) 203.75 481.33 P +1.95 (x query/reply type operations. A prototype is already in operation at) 248.6 481.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CEB) 189 469.33 T +(AF) 208.1 469.33 T +(, although the protocol is lik) 220.08 469.33 T +(ely to change some) 332.76 469.33 T +(what.) 409.44 469.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 177.5 454.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 189 454.33 T +(irtual de) 195.62 454.33 T +(vice wrapper around the correlation measurement engine \050see belo) 228.42 454.33 T +(w\051.) 494.2 454.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The follo) 162 436.33 T +(wing list has been put on the back b) 198.69 436.33 T +(urner) 341.81 436.33 T +(, b) 362.51 436.33 T +(ut still of interest:) 372.31 436.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 177.5 418.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.38 (\322Multiknob\323 de) 189 418.33 P +1.38 (vices. Write operations w) 253.18 418.33 P +1.38 (ould be applied to a v) 359.41 418.33 P +1.38 (ector of de) 452.53 418.33 P +1.38 (vices with) 497.79 418.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.55 (weighting f) 189 406.33 P +0.55 (actors which may be constant, or a simple functional form, or deri) 235.28 406.33 P +0.55 (v) 505.17 406.33 P +0.55 (ed by a) 510.02 406.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(call to another process. Intended for tuning machines.) 189 394.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 177.5 379.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.8 (Indirect de) 189 379.33 P +1.8 (vices. The name of the actual de) 233.59 379.33 P +1.8 (vice can be changed on the \337y) 373.25 379.33 P +1.8 (, and all) 504.46 379.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.39 (connections to the old de) 189 367.33 P +2.39 (vice will be automatically dropped and ne) 298.29 367.33 P +2.39 (w connections) 480.12 367.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(established. Useful for changing generic displays from one de) 189 355.33 T +(vice to another) 436.2 355.33 T +(.) 495.08 355.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 177.5 340.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.65 (tcl de) 189 340.33 P +0.65 (vices. De) 211.34 340.33 P +0.65 (vices implemented as tcl scripts, which may call other cde) 248.95 340.33 P +0.65 (v de) 487.3 340.33 P +0.65 (vices \050or) 504.64 340.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(an) 189 328.33 T +(ything else\051.) 198.29 328.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 177.5 313.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Connection to an object oriented database.) 189 313.33 T +0 0 0 1 0 0 0 K +54 255 540 262 C +0 0 0 1 0 0 0 K +54 261.29 152.57 261.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 261.29 540 261.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(9.) 142.5 266.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 162 266.67 T +(v A) 182.01 266.67 T +(pplications) 202.26 266.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(The follo) 162 240.33 T +(wing applications are a) 198.69 240.33 T +(v) 290.97 240.33 T +(ailable as cde) 295.72 240.33 T +(v e) 349.34 240.33 T +(xtensions from CEB) 361.13 240.33 T +(AF:) 442.45 240.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 177.5 222.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.93 (Correlation package, modeled after SLA) 189 222.33 P +2.93 (C\325) 362.78 222.33 P +2.93 (s correlation plot utility) 372.23 222.33 P +2.93 (. Consists of a) 474.54 222.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(correlation engine class library plus an application \050XA) 189 210.33 T +(CT\051 which uses it.) 410.5 210.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 177.5 195.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.35 (Multiknob utility \050lik) 189 195.33 P +0.35 (e #4 abo) 274.62 195.33 P +0.35 (v) 309.04 195.33 P +0.35 (e, with a GUI interf) 313.89 195.33 P +0.35 (ace\051. This is based upon a prototype) 393.77 195.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(of multiknob de) 189 183.33 T +(vices, and is con\336gured by ascii \336les.) 252.64 183.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.51 (Finally) 162 165.33 P +0.51 (, the follo) 189.69 165.33 P +0.51 (wing EPICS tools will be ported to cde) 229.07 165.33 P +0.51 (v or re-written using cde) 388.79 165.33 P +0.51 (v in the ne) 488.9 165.33 P +0.51 (xt) 532.22 165.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12 months \050ports to be distrib) 162 153.33 T +(uted with EPICS, not cde) 279.86 153.33 T +(v) 381 153.33 T +(, due to licensing constraints\051:) 385.35 153.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 177.5 135.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Alarm Handler \050specialized GUI tool\051. Porting no) 189 135.33 T +(w underw) 387.88 135.33 T +(ay at APS.) 427.49 135.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 177.5 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(General operator interf) 189 120.33 T +(ace \050GUI\051, either dm or medm or both.) 280.53 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 177.5 105.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Archi) 189 105.33 T +(v) 211.52 105.33 T +(er \050ne) 216.37 105.33 T +(w) 239.16 105.33 T +(, to be distrib) 245.73 105.33 T +(uted with cde) 298.31 105.33 T +(v\051.) 351.94 105.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 177.5 90.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sa) 189 90.33 T +(v) 198.8 90.33 T +(e / Restore tool \050ditto\051.) 203.65 90.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "4" 2 +%%Page: "3" 3 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Problems and Restrictions \050general\051) 404.45 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdev 1.3 Release Notes) 267.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(3) 552.44 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(9.) 195.5 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4.4 (The cde) 207 713.33 P +4.4 (v/e) 243.08 713.33 P +4.4 (xamples directory no) 255.15 713.33 P +4.4 (w contains 2 additional e) 348.14 713.33 P +4.4 (xample services, one) 465.6 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.52 (implementing compound cde) 207 701.33 P +0.52 (v de) 324.45 701.33 P +0.52 (vices, and the other \050demoService\051 is a tri) 341.65 701.33 P +0.52 (vial service) 511.66 701.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(useful as a starting point for read/write services.) 207 689.33 T +0 0 0 1 0 0 0 K +72 631 558 638 C +0 0 0 1 0 0 0 K +72 637.29 170.57 637.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 637.29 558 637.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(5.) 160.5 642.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pr) 180 642.67 T +(oblems and Restrictions \050general\051) 194.52 642.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Restrictions:) 180 616.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 598.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.46 (cde) 207 598.33 P +1.46 (v is not yet thread safe, and may not be safe ag) 220.63 598.33 P +1.46 (ainst instantiating more that one) 423.83 598.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 207 586.33 T +(vSystem object.) 220.63 586.33 T +0 0 0 1 0 0 0 K +72 528 558 535 C +0 0 0 1 0 0 0 K +72 534.29 170.57 534.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 534.29 558 534.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(6.) 160.5 539.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Channel Access Ser) 180 539.67 T +(vice F) 297.29 539.67 T +(eatur) 332.32 539.67 T +(es and Restrictions) 363.95 539.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +0.14 (EPICS / Channel Access v) 180 513.33 P +0.14 (ersion 3.12 is recommended. The follo) 287.05 513.33 P +0.14 (wing comments from the 1.1) 442.18 513.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(release still apply:) 180 501.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Major features:) 180 483.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 465.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Supports synchronous and asynchronous send\325) 207 465.33 T +(s.) 393.65 465.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 451.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Fetches data in nati) 207 451.33 T +(v) 284.24 451.33 T +(e type \050type con) 289.09 451.33 T +(v) 352.84 451.33 T +(ersion done on client and not serv) 357.69 451.33 T +(er\051.) 492.52 451.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 437.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.16 (Pro) 207 437.33 P +-0.16 (vides a def) 220.74 437.33 P +-0.16 (ault name service so that if a de) 263.63 437.33 P +-0.16 (vice is not de\336ned, then an EPICS channel) 388.6 437.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.43 (access connection is attempted with the record name set equal to the de) 207 425.33 P +0.43 (vice name, and) 496.88 425.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the \336eld name set equal to the attrib) 207 413.33 T +(ute name.) 349.84 413.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Restrictions:) 180 395.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 377.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.13 (Only supports set/get/monitorOn/monitorOf) 207 377.33 P +-0.13 (f v) 383.15 377.33 P +-0.13 (erbs and the pv and readonly service data) 393.7 377.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(tags. Support for arbitrary messages with def) 207 365.33 T +(ault data has ag) 386.59 365.33 T +(ain been postponed.) 448.47 365.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 351.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Discards all e) 207 351.33 T +(xception callbacks from channel access in this v) 261.28 351.33 T +(ersion.) 453.59 351.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 337.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Channel access security is not supported in this release.) 207 337.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 323.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendCallback does not support the same timeout feature as send.) 207 323.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 309.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4.17 (channel access f) 207 309.33 P +4.17 (ails if send is called from within a callback function \050either) 280.21 309.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(asynchronous methods are OK: sendNoBlock and sendCallback\051) 207 297.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Compilation options:) 180 279.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 261.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(_CA_SYNC_CONN = perform connections synchronously) 207 261.33 T +(, w) 444.19 261.33 T +(aiting up to 4 seconds.) 456.31 261.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 247.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(_CDEV_DEB) 207 247.33 T +(UG = print v) 264.12 247.33 T +(erbose messages) 315.44 247.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 233.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(_EPICS_3_12 = if not de\336ned, use 3.11 calls instead.) 207 233.33 T +0 0 0 1 0 0 0 K +72 175 558 182 C +0 0 0 1 0 0 0 K +72 181.29 170.57 181.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 181.29 558 181.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(7.) 160.5 186.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Customizing f) 180 186.67 T +(or a New System) 263.26 186.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +0.01 (T) 180 160.33 P +0.01 (o customize cde) 185.31 160.33 P +0.01 (v for a ne) 249.52 160.33 P +0.01 (w control system, a ne) 287.35 160.33 P +0.01 (w cde) 376.87 160.33 P +0.01 (v service must be written. T) 400.23 160.33 P +0.01 (w) 511.15 160.33 P +0.01 (o services) 518.28 160.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.54 (are pro) 180 148.33 P +0.54 (vided with the release: caService for EPICS channel access, and skService, a sk) 208.43 148.33 P +0.54 (eleton) 533.56 148.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.1 (service. The ca \050channel access\051 service is a comple) 180 136.33 P +-0.1 (x e) 386.46 136.33 P +-0.1 (xample of ho) 398.15 136.33 P +-0.1 (w to interact with a control) 450.47 136.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.17 (system which supports asychronous I/O. The sk) 180 124.33 P +2.17 (eleton service simply sho) 384.32 124.33 P +2.17 (ws the minimal) 491.98 124.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.02 (interf) 180 112.33 P +-0.02 (ace a service must pro) 201.56 112.33 P +-0.02 (vide, and can be used as a starting point for b) 290.18 112.33 P +-0.02 (uilding a ne) 470.56 112.33 P +-0.02 (w service.) 517.48 112.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.8 (A third e) 180 100.33 P +2.8 (xample is contained in the Service De) 221 100.33 P +2.8 (v) 389.18 100.33 P +2.8 (eloper\325) 394.03 100.33 P +2.8 (s Guide, and is intermediate in) 421.8 100.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(comple) 180 88.33 T +(xity) 209.29 88.33 T +(.) 224.2 88.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "3" 3 +%%Page: "2" 4 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Installation) 54 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(2) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(cdev 1.3 Release Notes) 249.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Document Revision: 1) 451.97 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(3.) 142.5 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Installation) 162 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +-0.06 (Sources are a) 162 684.33 P +-0.06 (v) 214.98 684.33 P +-0.06 (ailable in compressed tar format, and contain mak) 219.73 684.33 P +-0.06 (e\336les to b) 419.14 684.33 P +-0.06 (uild the libraries and) 457.7 684.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.17 (utilities. These ha) 162 672.33 P +-0.17 (v) 232.29 672.33 P +-0.17 (e been tested on the HP) 237.13 672.33 P +-0.17 (, SunOS, and SGI platforms to e) 329.31 672.33 P +-0.17 (x) 457.57 672.33 P +-0.17 (ecute correctly) 462.42 672.33 P +-0.17 (, and) 520.73 672.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.01 (SLA) 162 660.33 P +0.01 (C has ported this v) 180.49 660.33 P +0.01 (ersion to V) 255.39 660.33 P +0.01 (AX/VMS. Fix) 298.51 660.33 P +0.01 (es ha) 355.6 660.33 P +0.01 (v) 375.68 660.33 P +0.01 (e also been incorporated from an earlier) 380.53 660.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.96 (port to IBM/AIX \050at CERN\051. As con\336gured, cde) 162 648.33 P +0.96 (v will b) 362.63 648.33 P +0.96 (uild support for the EPICS channel) 394.92 648.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(access service.) 162 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.03 (The Mak) 162 618.33 P +3.03 (e\336les ha) 201.31 618.33 P +3.03 (v) 237.2 618.33 P +3.03 (e been e) 242.04 618.33 P +3.03 (xtensi) 280.72 618.33 P +3.03 (v) 304.36 618.33 P +3.03 (ely re) 309.21 618.33 P +3.03 (w) 334.48 618.33 P +3.03 (ork) 341.6 618.33 P +3.03 (ed since the 1.1 release, and should b) 354.83 618.33 P +3.03 (uild) 524.44 618.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(successfully on more platforms.) 162 606.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.06 (F) 162 588.33 P +3.06 (or further information, see the README \336le in the topmost directory) 167.41 588.33 P +3.06 (, and the) 475.98 588.33 P +3 F +3.06 (cde) 521.83 588.33 P +3.06 (v) 535.56 588.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Administr) 162 576.33 T +(ator\325) 201.3 576.33 T +(s Guide) 220.9 576.33 T +1 F +( in the /doc sub-directory) 251.73 576.33 T +(.) 351.62 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (Support for site speci\336c control systems must be added by the implementer) 162 558.33 P +0.83 (. See the) 471.41 558.33 P +3 F +0.83 (Service) 510.57 558.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.55 (De) 162 546.33 P +1.55 (veloper\325) 173.51 546.33 P +1.55 (s Guide) 206.43 546.33 P +1 F +1.55 ( for help in getting started interf) 238.81 546.33 P +1.55 (acing cde) 375.78 546.33 P +1.55 (v to a ne) 415.12 546.33 P +1.55 (w control system. In) 453.69 546.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(addition, there are a number of e) 162 534.33 T +(xample services included with this release.) 292.09 534.33 T +0 0 0 1 0 0 0 K +54 476 540 483 C +0 0 0 1 0 0 0 K +54 482.29 152.57 482.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 482.29 540 482.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(4.) 142.5 487.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Changes fr) 162 487.67 T +(om 1.1 V) 227.46 487.67 T +(ersion) 279.33 487.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +0.55 (A number of changes ha) 162 461.33 P +0.55 (v) 261.73 461.33 P +0.55 (e been made to mak) 266.58 461.33 P +0.55 (e the source code compile correctly on a lar) 348.65 461.33 P +0.55 (ger) 527.23 461.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.05 (v) 162 449.33 P +0.05 (ariety of compilers, including V) 166.75 449.33 P +0.05 (AX C++ and g++. In addition, cde) 293.63 449.33 P +0.05 (v no) 431.76 449.33 P +0.05 (w produces more error) 449.06 449.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.78 (and w) 162 437.33 P +0.78 (arning messages through its error logging routines. The follo) 186.84 437.33 P +0.78 (wing is a list of the more) 435.87 437.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(visible feature changes:) 162 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 177.5 407.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The C binding is included in the release \050pre) 189 407.33 T +(viously released as an add-on to 1.1\051.) 366.5 407.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 177.5 392.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.19 (The de) 189 392.33 P +-0.19 (vice de\336nitions \050ddl \336le\051 may no) 216.05 392.33 P +-0.19 (w be stored and loaded in a binary format, which) 345.66 392.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 (is about 20 times f) 189 380.33 P +1 (aster to load compared to the ascii format. A ne) 266.79 380.33 P +1 (w utility program,) 465.5 380.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.2 (cddl, compiles the ddl from ascii to binary) 189 368.33 P +0.2 (. At run-time, the \336le format of the ddl \336le is) 359.15 368.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(detected automatically so that either ascii or binary may be used.) 189 356.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 177.5 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.17 (Shared objects are no) 189 341.33 P +2.17 (w loaded from a subdirectory of the directory pointed to by) 281.08 341.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.33 (CDEVSHOBJ, where the subdirectory name is the name of the v) 189 329.33 P +0.33 (ersion of cde) 451.83 329.33 P +0.33 (v ag) 503.89 329.33 P +0.33 (ainst) 521.11 329.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.2 (which the application is running. This mak) 189 317.33 P +1.2 (es it possible to run dif) 367.49 317.33 P +1.2 (ferent applications) 464.65 317.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.22 (ag) 189 305.33 P +-0.22 (ainst dif) 198.39 305.33 P +-0.22 (ferent v) 230.42 305.33 P +-0.22 (ersions of cde) 260.87 305.33 P +-0.22 (v) 315.72 305.33 P +-0.22 (. If the subdirectory does not contain the needed object,) 320.07 305.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(it is loaded from CDEVSHOBJ as before.) 189 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 177.5 278.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.06 (cde) 189 278.33 P +1.06 (vFdChangedCallback added to cde) 202.63 278.33 P +1.06 (vSystem, allo) 345.27 278.33 P +1.06 (wing an application to be noti\336ed) 400.53 278.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(when \336le descriptors are opened or closed by cde) 189 266.33 T +(v services.) 385.92 266.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 177.5 251.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 189 251.33 T +(vData no) 202.63 251.33 T +(w supports a cast to char* as well as operator= o) 238.76 251.33 T +(v) 432.54 251.33 T +(erloading.) 437.39 251.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 177.5 236.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.31 (cde) 189 236.33 P +0.31 (vGroup no) 202.63 236.33 P +0.31 (w supports a deferred e) 245.74 236.33 P +0.31 (x) 340.15 236.33 P +0.31 (ecution / re-e) 345 236.33 P +0.31 (x) 398.23 236.33 P +0.31 (ecution mode: if a group is in this) 403.08 236.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.97 (mode, operations are remembered b) 189 224.33 P +1.97 (ut not e) 340.24 224.33 P +1.97 (x) 374.03 224.33 P +1.97 (ecuted. Sa) 378.88 224.33 P +1.97 (v) 421.75 224.33 P +1.97 (ed operations may later be) 426.6 224.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.22 (e) 189 212.33 P +-0.22 (x) 193.29 212.33 P +-0.22 (ecuted as a group, and re-e) 198.14 212.33 P +-0.22 (x) 304.07 212.33 P +-0.22 (ecuted without re-learning. Only asynchronous operations) 308.92 212.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(are remembered.) 189 200.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 177.5 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.24 (A fe) 189 185.33 P +0.24 (w b) 206.48 185.33 P +0.24 (ugs in the channel access service ha) 221.25 185.33 P +0.24 (v) 365.79 185.33 P +0.24 (e been \336x) 370.64 185.33 P +0.24 (ed. Monitoring of status without) 409.86 185.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(monitoring v) 189 173.33 T +(alue no) 240.7 173.33 T +(w w) 269.61 173.33 T +(orks correctly) 286.45 173.33 T +(.) 341.06 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8.) 177.5 158.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.12 (The cde) 189 158.33 P +-0.12 (v/src directory no) 220.55 158.33 P +-0.12 (w contains an e) 290.6 158.33 P +-0.12 (xtensions sub-directory) 352 158.33 P +-0.12 (. Extensions include the) 444.83 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.4 (tcl interf) 189 146.33 P +0.4 (ace, and the A) 223.46 146.33 P +0.4 (CE \050Adapti) 281.47 146.33 P +0.4 (v) 327.45 146.33 P +0.4 (e Communication En) 332.3 146.33 P +0.4 (vironment\051 based client/serv) 417.71 146.33 P +0.4 (er) 532.23 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.97 (package used for b) 189 134.33 P +1.97 (uilding ne) 269.95 134.33 P +1.97 (w cde) 311.95 134.33 P +1.97 (v serv) 337.27 134.33 P +1.97 (ers and services capable of passing entire) 363.24 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 189 122.33 T +(vData objects o) 202.63 122.33 T +(v) 264.69 122.33 T +(er the netw) 269.54 122.33 T +(ork.) 313.87 122.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "2" 4 +%%Page: "1" 5 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. Overview) 510.49 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdev 1.3 Release Notes) 267.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1) 552.44 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 24 Q +(cdev 1.3 Release Notes) 180 704 T +0 0 0 1 0 0 0 K +72 635 558 642 C +0 0 0 1 0 0 0 K +72 641.29 170.57 641.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 641.29 558 641.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(1.) 160.5 646.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180 646.67 T +(er) 197.75 646.67 T +(view) 210.04 646.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +3.77 (The cde) 180 620.33 P +3.77 (v \050control de) 215.45 620.33 P +3.77 (vice\051 C++ library is designed to pro) 273.83 620.33 P +3.77 (vide a standard application) 439.22 620.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.25 (programming interf) 180 608.33 P +1.25 (ace \050API\051 to one or more underlying packages, typically control system) 259.75 608.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.99 (interf) 180 596.33 P +1.99 (aces. The implementation is in 2 layers: the uppermost layer is used directly by an) 201.56 596.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.12 (application, and pro) 180 584.33 P +1.12 (vides an abstraction of the underlying package as well as man) 261.79 584.33 P +1.12 (y general) 519.96 584.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.22 (purpose features. The second layer \050service layer\051 pro) 180 572.33 P +2.22 (vides the interf) 410.34 572.33 P +2.22 (ace to one or more) 474.68 572.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(underlying packages, and is implemented as loadable libraries.) 180 560.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.53 (cde) 180 542.33 P +0.53 (v w) 193.63 542.33 P +0.53 (as initially de) 208.78 542.33 P +0.53 (v) 263.48 542.33 P +0.53 (eloped at CEB) 268.33 542.33 P +0.53 (AF with input from the EPICS collaboration, and is no) 327.37 542.33 P +0.53 (w) 550.78 542.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.3 (a) 180 530.33 P +0.3 (v) 184.24 530.33 P +0.3 (ailable for an) 188.99 530.33 P +0.3 (yone to tak) 242.2 530.33 P +0.3 (e and use or impro) 287.15 530.33 P +0.3 (v) 362.64 530.33 P +0.3 (e. W) 367.49 530.33 P +0.3 (e welcome all comments, suggestions, b) 385.87 530.33 P +0.3 (ug) 548 530.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.26 (reports, and \050especially\051 b) 180 518.33 P +0.26 (ug \336x) 284.45 518.33 P +0.26 (es, including \336x) 307.62 518.33 P +0.26 (es for ne) 372.17 518.33 P +0.26 (w platforms. There are man) 406.88 518.33 P +0.26 (y planned) 518.58 518.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (enhancements, and w) 180 506.33 P +1.08 (ould welcome v) 267.88 506.33 P +1.08 (olunteers to contrib) 333.73 506.33 P +1.08 (ute to this project. See belo) 413.46 506.33 P +1.08 (w for a) 527.51 506.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(summary of ne) 180 494.33 T +(w and planned features.) 239.74 494.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Y) 180 476.33 T +(ou may join a cde) 186.12 476.33 T +(v discussion list by sending the message) 256.97 476.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( subscribe cde) 180 458.33 T +(v) 253.9 458.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.07 (to the address mailserv@cebaf.go) 180 440.33 P +3.07 (v) 324.36 440.33 P +3.07 (. \050Send the message HELP to the same address for) 328.71 440.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(information on ho) 180 428.33 T +(w to use the mail serv) 251.97 428.33 T +(er) 339.31 428.33 T +(.\051 The cde) 346.53 428.33 T +(v web page is) 386.54 428.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(http://www) 200 410.33 T +(.cebaf.go) 244.91 410.33 T +(v/cde) 281.41 410.33 T +(v/) 302.82 410.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180 392.33 T +(v 1.3 is the third publically released v) 193.63 392.33 T +(ersion of cde) 344.02 392.33 T +(v) 395.42 392.33 T +(.) 399.77 392.33 T +0 0 0 1 0 0 0 K +72 334 558 341 C +0 0 0 1 0 0 0 K +72 340.29 170.57 340.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 340.29 558 340.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(2.) 160.5 345.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Documentation) 180 345.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(The documentation for cde) 180 319.33 T +(v includes the follo) 287.78 319.33 T +(wing:) 364.47 319.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 301.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +0.29 (Intr) 207 301.33 P +0.29 (oduction to cde) 221.55 301.33 P +0.29 (v) 283.65 301.33 P +1 F +0.29 ( -- this is an update of) 288.09 301.33 P +3 F +0.29 (The cde) 379.87 301.33 P +0.29 (v User\325) 411.39 301.33 P +0.29 (s Guide) 441 301.33 P +1 F +0.29 (, complete with more) 472.12 301.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(e) 207 289.33 T +(xamples. It co) 211.29 289.33 T +(v) 267.52 289.33 T +(ers all the basics, and is the best place to start.) 272.37 289.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 275.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +0.72 (A cde) 207 275.33 P +0.72 (v T) 230.06 275.33 P +0.72 (utorial) 242.73 275.33 P +1 F +0.72 ( -- this document goes through ho) 269.96 275.33 P +0.72 (w to use each of the classes in cde) 409.02 275.33 P +0.72 (v) 551.15 275.33 P +0.72 (,) 555.5 275.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(including all public methods; e) 207 263.33 T +(xtensi) 330.74 263.33 T +(v) 354.38 263.33 T +(e e) 359.23 263.33 T +(xamples are gi) 370.46 263.33 T +(v) 428.53 263.33 T +(en.) 433.38 263.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 249.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 207 249.33 T +(v Refer) 220.73 249.33 T +(ence Manual) 248.96 249.33 T +1 F +( -- documents each class in cde) 300.89 249.33 T +(v in alphabetical order) 425.05 249.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 235.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +0.63 (cde) 207 235.33 P +0.63 (v Administr) 220.73 235.33 P +0.63 (ator\325) 267.6 235.33 P +0.63 (s Guide) 287.2 235.33 P +1 F +0.63 ( -- this is for system administrators, and those intending to) 318.66 235.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(port cde) 207 223.33 T +(v to ne) 239.24 223.33 T +(w platforms) 266.21 223.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +0.92 (Service De) 207 209.33 P +0.92 (veloper\325) 251.36 209.33 P +0.92 (s Guide) 284.28 209.33 P +1 F +0.92 (-- this documents a couple of additional classes needed to) 319.46 209.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(create a custom service, and goes through a lengthly e) 207 197.33 T +(xample demoService.) 422.91 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 183.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 207 183.33 T +(v C Binding) 220.73 183.33 T +1 F +( -- documents the C wrapper routines for cde) 268.51 183.33 T +(v) 447.66 183.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(This documentation is also a) 180 165.33 T +(v) 294.24 165.33 T +(ailable on the web site.) 298.99 165.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "1" 5 +%%Trailer +%%BoundingBox: 0 0 612 792 +%%PageOrder: Descend +%%Pages: 5 +%%DocumentFonts: Helvetica +%%+ Times-Roman +%%+ Times-Bold +%%+ Times-Italic +%%+ Times-BoldItalic +%%EOF diff --git a/doc/ps/releaseNotes1_4.ps b/doc/ps/releaseNotes1_4.ps new file mode 100755 index 0000000..1221715 --- /dev/null +++ b/doc/ps/releaseNotes1_4.ps @@ -0,0 +1,3940 @@ +%!PS-Adobe-3.0 +%%BoundingBox: (atend) +%%Pages: (atend) +%%PageOrder: (atend) +%%DocumentFonts: (atend) +%%Creator: Frame 5.0 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +% +% Frame ps_prolog 5.0, for use with Frame 5.0 products +% This ps_prolog file is Copyright (c) 1986-1995 Frame Technology +% Corporation. All rights reserved. This ps_prolog file may be +% freely copied and distributed in conjunction with documents created +% using FrameMaker, FrameMaker/SGML and FrameViewer as long as this +% copyright notice is preserved. +% +% FrameMaker users specify the proper paper size for each print job in the +% "Print" dialog's "Printer Paper Size" "Width" and "Height~ fields. If the +% printer that the PS file is sent to does not support the requested paper +% size, or if there is no paper tray of the proper size currently installed, +% then the job will not be printed. The following flag, if set to true, will +% cause the job to print on the default paper in such cases. +/FMAllowPaperSizeMismatch false def +% +% Frame products normally print colors as their true color on a color printer +% or as shades of gray, based on luminance, on a black-and white printer. The +% following flag, if set to true, forces all non-white colors to print as pure +% black. This has no effect on bitmap images. +/FMPrintAllColorsAsBlack false def +% +% Frame products can either set their own line screens or use a printer's +% default settings. Three flags below control this separately for no +% separations, spot separations and process separations. If a flag +% is true, then the default printer settings will not be changed. If it is +% false, Frame products will use their own settings from a table based on +% the printer's resolution. +/FMUseDefaultNoSeparationScreen true def +/FMUseDefaultSpotSeparationScreen true def +/FMUseDefaultProcessSeparationScreen false def +% +% For any given PostScript printer resolution, Frame products have two sets of +% screen angles and frequencies for printing process separations, which are +% recomended by Adobe. The following variable chooses the higher frequencies +% when set to true or the lower frequencies when set to false. This is only +% effective if the appropriate FMUseDefault...SeparationScreen flag is false. +/FMUseHighFrequencyScreens true def +% +% The following is a set of predefined optimal frequencies and angles for various +% common dpi settings. This is taken from "Advances in Color Separation Using +% PostScript Software Technology," from Adobe Systems (3/13/89 P.N. LPS 0043) +% and corrolated with information which is in various PPD (4.0) files. +% +% The "dpiranges" figure is the minimum dots per inch device resolution which +% can support this setting. The "low" and "high" values are controlled by the +% setting of the FMUseHighFrequencyScreens flag above. The "TDot" flags control +% the use of the "Yellow Triple Dot" feature whereby the frequency id divided by +% three, but the dot function is "trippled" giving a block of 3x3 dots per cell. +% +% PatFreq is a compromise pattern frequency for ps Level 2 printers which is close +% to the ideal WYSIWYG pattern frequency of 9 repetitions/inch but does not beat +% (too badly) against the screen frequencies of any separations for that DPI. +/dpiranges [ 2540 2400 1693 1270 1200 635 600 0 ] def +/CMLowFreqs [ 100.402 94.8683 89.2289 100.402 94.8683 66.9349 63.2456 47.4342 ] def +/YLowFreqs [ 95.25 90.0 84.65 95.25 90.0 70.5556 66.6667 50.0 ] def +/KLowFreqs [ 89.8026 84.8528 79.8088 89.8026 84.8528 74.8355 70.7107 53.033 ] def +/CLowAngles [ 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 ] def +/MLowAngles [ 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 ] def +/YLowTDot [ true true false true true false false false ] def +/CMHighFreqs [ 133.87 126.491 133.843 108.503 102.523 100.402 94.8683 63.2456 ] def +/YHighFreqs [ 127.0 120.0 126.975 115.455 109.091 95.25 90.0 60.0 ] def +/KHighFreqs [ 119.737 113.137 119.713 128.289 121.218 89.8026 84.8528 63.6395 ] def +/CHighAngles [ 71.5651 71.5651 71.5651 70.0169 70.0169 71.5651 71.5651 71.5651 ] def +/MHighAngles [ 18.4349 18.4349 18.4349 19.9831 19.9831 18.4349 18.4349 18.4349 ] def +/YHighTDot [ false false true false false true true false ] def +/PatFreq [ 10.5833 10.0 9.4055 10.5833 10.0 10.5833 10.0 9.375 ] def +% +% PostScript Level 2 printers contain an "Accurate Screens" feature which can +% improve process separation rendering at the expense of compute time. This +% flag is ignored by PostScript Level 1 printers. +/FMUseAcccurateScreens true def +% +% The following PostScript procedure defines the spot function that Frame +% products will use for process separations. You may un-comment-out one of +% the alternative functions below, or use your own. +% +% Dot function +/FMSpotFunction {abs exch abs 2 copy add 1 gt + {1 sub dup mul exch 1 sub dup mul add 1 sub } + {dup mul exch dup mul add 1 exch sub }ifelse } def +% +% Line function +% /FMSpotFunction { pop } def +% +% Elipse function +% /FMSpotFunction { dup 5 mul 8 div mul exch dup mul exch add +% sqrt 1 exch sub } def +% +% +/FMversion (5.0) def +/fMLevel1 /languagelevel where {pop languagelevel} {1} ifelse 2 lt def +/FMPColor + fMLevel1 { + false + /colorimage where {pop pop true} if + } { + true + } ifelse +def +/FrameDict 400 dict def +systemdict /errordict known not {/errordict 10 dict def + errordict /rangecheck {stop} put} if +% The readline in PS 23.0 doesn't recognize cr's as nl's on AppleTalk +FrameDict /tmprangecheck errordict /rangecheck get put +errordict /rangecheck {FrameDict /bug true put} put +FrameDict /bug false put +mark +% Some PS machines read past the CR, so keep the following 3 lines together! +currentfile 5 string readline +00 +0000000000 +cleartomark +errordict /rangecheck FrameDict /tmprangecheck get put +FrameDict /bug get { + /readline { + /gstring exch def + /gfile exch def + /gindex 0 def + { + gfile read pop + dup 10 eq {exit} if + dup 13 eq {exit} if + gstring exch gindex exch put + /gindex gindex 1 add def + } loop + pop + gstring 0 gindex getinterval true + } bind def + } if +/FMshowpage /showpage load def +/FMquit /quit load def +/FMFAILURE { + dup = flush + FMshowpage + /Helvetica findfont 12 scalefont setfont + 72 200 moveto show + 72 220 moveto show + FMshowpage + FMquit + } def +/FMVERSION { + FMversion ne { + (Frame product version does not match ps_prolog! Check installation;) + (also check ~/fminit and ./fminit for old versions) FMFAILURE + } if + } def +/FMBADEPSF { + (Adobe's PostScript Language Reference Manual, 2nd Edition, section H.2.4) + (says your EPS file is not valid, as it calls X ) + dup dup (X) search pop exch pop exch pop length + 5 -1 roll + putinterval + FMFAILURE + } def +/fmConcatProcs + { + /proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def + newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx +}def +FrameDict begin [ + /ALDsave + /FMdicttop + /FMoptop + /FMpointsize + /FMsaveobject + /b + /bitmapsave + /blut + /bpside + /bs + /bstring + /bwidth + /c + /cf + /cs + /cynu + /depth + /edown + /fh + /fillvals + /fw + /fx + /fy + /g + /gfile + /gindex + /grnt + /gryt + /gstring + /height + /hh + /i + /im + /indx + /is + /k + /kk + /landscape + /lb + /len + /llx + /lly + /m + /magu + /manualfeed + /n + /offbits + /onbits + /organgle + /orgbangle + /orgbfreq + /orgbproc + /orgbxfer + /orgfreq + /orggangle + /orggfreq + /orggproc + /orggxfer + /orgmatrix + /orgproc + /orgrangle + /orgrfreq + /orgrproc + /orgrxfer + /orgxfer + /pagesave + /paperheight + /papersizedict + /paperwidth + /pos + /pwid + /r + /rad + /redt + /sl + /str + /tran + /u + /urx + /ury + /val + /width + /width + /ws + /ww + /x + /x1 + /x2 + /xindex + /xpoint + /xscale + /xx + /y + /y1 + /y2 + /yelu + /yindex + /ypoint + /yscale + /yy +] { 0 def } forall +/FmBD {bind def} bind def +systemdict /pdfmark known { + /fMAcrobat true def + + /FmPD /pdfmark load def + + + /FmPT /show load def + + + currentdistillerparams /CoreDistVersion get 2000 ge { + + + /FmPD2 /pdfmark load def + + + + + + /FmPA { mark exch /Dest exch 5 3 roll + /View [ /XYZ null 6 -2 roll FmDC exch pop null] /DEST FmPD + }FmBD + } { + + /FmPD2 /cleartomark load def + /FmPA {pop pop pop}FmBD + } ifelse +} { + + /fMAcrobat false def + /FmPD /cleartomark load def + /FmPD2 /cleartomark load def + /FmPT /pop load def + /FmPA {pop pop pop}FmBD +} ifelse +/FmDC { + transform fMDefaultMatrix itransform cvi exch cvi exch +}FmBD +/FmBx { + dup 3 index lt {3 1 roll exch} if + 1 index 4 index lt {4 -1 roll 3 1 roll exch 4 1 roll} if +}FmBD +/FMnone 0 def +/FMcyan 1 def +/FMmagenta 2 def +/FMyellow 3 def +/FMblack 4 def +/FMcustom 5 def +/fMNegative false def +/FrameSepIs FMnone def +/FrameSepBlack 0 def +/FrameSepYellow 0 def +/FrameSepMagenta 0 def +/FrameSepCyan 0 def +/FrameSepRed 1 def +/FrameSepGreen 1 def +/FrameSepBlue 1 def +/FrameCurGray 1 def +/FrameCurPat null def +/FrameCurColors [ 0 0 0 1 0 0 0 ] def +/FrameColorEpsilon .001 def +/eqepsilon { + sub dup 0 lt {neg} if + FrameColorEpsilon le +} bind def +/FrameCmpColorsCMYK { + 2 copy 0 get exch 0 get eqepsilon { + 2 copy 1 get exch 1 get eqepsilon { + 2 copy 2 get exch 2 get eqepsilon { + 3 get exch 3 get eqepsilon + } {pop pop false} ifelse + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/FrameCmpColorsRGB { + 2 copy 4 get exch 0 get eqepsilon { + 2 copy 5 get exch 1 get eqepsilon { + 6 get exch 2 get eqepsilon + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/RGBtoCMYK { + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 3 copy + 2 copy + le { pop } { exch pop } ifelse + 2 copy + le { pop } { exch pop } ifelse + dup dup dup + 6 1 roll + 4 1 roll + 7 1 roll + sub + 6 1 roll + sub + 5 1 roll + sub + 4 1 roll +} bind def +/CMYKtoRGB { + dup dup 4 -1 roll add + 5 1 roll 3 -1 roll add + 4 1 roll add + 1 exch sub dup 0 lt {pop 0} if 3 1 roll + 1 exch sub dup 0 lt {pop 0} if exch + 1 exch sub dup 0 lt {pop 0} if exch +} bind def +/FrameSepInit { + 1.0 RealSetgray +} bind def +/FrameSetSepColor { + /FrameSepBlue exch def + /FrameSepGreen exch def + /FrameSepRed exch def + /FrameSepBlack exch def + /FrameSepYellow exch def + /FrameSepMagenta exch def + /FrameSepCyan exch def + /FrameSepIs FMcustom def + setCurrentScreen +} bind def +/FrameSetCyan { + /FrameSepBlue 1.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 1.0 def + /FrameSepIs FMcyan def + setCurrentScreen +} bind def + +/FrameSetMagenta { + /FrameSepBlue 1.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 1.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMmagenta def + setCurrentScreen +} bind def + +/FrameSetYellow { + /FrameSepBlue 0.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 1.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMyellow def + setCurrentScreen +} bind def + +/FrameSetBlack { + /FrameSepBlue 0.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 1.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMblack def + setCurrentScreen +} bind def + +/FrameNoSep { + /FrameSepIs FMnone def + setCurrentScreen +} bind def +/FrameSetSepColors { + FrameDict begin + [ exch 1 add 1 roll ] + /FrameSepColors + exch def end + } bind def +/FrameColorInSepListCMYK { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsCMYK + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/FrameColorInSepListRGB { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsRGB + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/RealSetgray /setgray load def +/RealSetrgbcolor /setrgbcolor load def +/RealSethsbcolor /sethsbcolor load def +end +/setgray { + FrameDict begin + FrameSepIs FMnone eq + { RealSetgray } + { + FrameSepIs FMblack eq + { RealSetgray } + { FrameSepIs FMcustom eq + FrameSepRed 0 eq and + FrameSepGreen 0 eq and + FrameSepBlue 0 eq and { + RealSetgray + } { + 1 RealSetgray pop + } ifelse + } ifelse + } ifelse + end +} bind def +/setrgbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetrgbcolor } + { + 3 copy [ 4 1 roll ] + FrameColorInSepListRGB + { + FrameSepBlue eq exch + FrameSepGreen eq and exch + FrameSepRed eq and + { 0 } { 1 } ifelse + } + { + FMPColor { + RealSetrgbcolor + currentcmykcolor + } { + RGBtoCMYK + } ifelse + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end +} bind def +/sethsbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSethsbcolor } + { + RealSethsbcolor + currentrgbcolor + setrgbcolor + } + ifelse + end +} bind def +FrameDict begin +/setcmykcolor where { + pop /RealSetcmykcolor /setcmykcolor load def +} { + /RealSetcmykcolor { + 4 1 roll + 3 { 3 index add 0 max 1 min 1 exch sub 3 1 roll} repeat + RealSetrgbcolor pop + } bind def +} ifelse +userdict /setcmykcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetcmykcolor } + { + 4 copy [ 5 1 roll ] + FrameColorInSepListCMYK + { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + { 0 } { 1 } ifelse + } + { + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end + } bind put +fMLevel1 { + + + + /patScreenDict 7 dict dup begin + <0f1e3c78f0e1c387> [ 45 { pop } {exch pop} .5 2 sqrt] FmBD + <0f87c3e1f0783c1e> [ 135 { pop } {exch pop} .5 2 sqrt] FmBD + [ 0 { pop } dup .5 2 ] FmBD + [ 90 { pop } dup .5 2 ] FmBD + <8142241818244281> [ 45 { 2 copy lt {exch} if pop} dup .75 2 sqrt] FmBD + <03060c183060c081> [ 45 { pop } {exch pop} .875 2 sqrt] FmBD + <8040201008040201> [ 135 { pop } {exch pop} .875 2 sqrt] FmBD + end def +} { + + /patProcDict 5 dict dup begin + <0f1e3c78f0e1c387> { 3 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <0f87c3e1f0783c1e> { 3 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + <8142241818244281> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -1 -1 moveto 9 9 lineto stroke } bind def + <03060c183060c081> { 1 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <8040201008040201> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + end def + /patDict 15 dict dup begin + /PatternType 1 def + /PaintType 2 def + /TilingType 3 def + /BBox [ 0 0 8 8 ] def + /XStep 8 def + /YStep 8 def + /PaintProc { + begin + patProcDict bstring known { + patProcDict bstring get exec + } { + 8 8 true [1 0 0 -1 0 8] bstring imagemask + } ifelse + end + } bind def + end def +} ifelse +/combineColor { + FrameSepIs FMnone eq + { + graymode fMLevel1 or not { + + [/Pattern [/DeviceCMYK]] setcolorspace + FrameCurColors 0 4 getinterval aload pop FrameCurPat setcolor + } { + FrameCurColors 3 get 1.0 ge { + FrameCurGray RealSetgray + } { + fMAcrobat not FMPColor graymode and and { + 0 1 3 { + FrameCurColors exch get + 1 FrameCurGray sub mul + } for + RealSetcmykcolor + } { + 4 1 6 { + FrameCurColors exch get + graymode { + 1 exch sub 1 FrameCurGray sub mul 1 exch sub + } { + 1.0 lt {FrameCurGray} {1} ifelse + } ifelse + } for + RealSetrgbcolor + } ifelse + } ifelse + } ifelse + } { + FrameCurColors 0 4 getinterval aload + FrameColorInSepListCMYK { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + FrameSepIs FMcustom eq and + { FrameCurGray } { 1 } ifelse + } { + FrameSepIs FMblack eq + {FrameCurGray 1.0 exch sub mul 1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop FrameCurGray 1.0 exch sub mul 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + graymode fMLevel1 or not { + + [/Pattern [/DeviceGray]] setcolorspace + FrameCurPat setcolor + } { + graymode not fMLevel1 and { + + dup 1 lt {pop FrameCurGray} if + } if + RealSetgray + } ifelse + } ifelse +} bind def +/savematrix { + orgmatrix currentmatrix pop + } bind def +/restorematrix { + orgmatrix setmatrix + } bind def +/fMDefaultMatrix matrix defaultmatrix def +/fMatrix2 matrix def +/dpi 72 0 fMDefaultMatrix dtransform + dup mul exch dup mul add sqrt def + +/freq dpi dup 72 div round dup 0 eq {pop 1} if 8 mul div def +/sangle 1 0 fMDefaultMatrix dtransform exch atan def + sangle fMatrix2 rotate + fMDefaultMatrix fMatrix2 concatmatrix + dup 0 get /sflipx exch def + 3 get /sflipy exch def +/screenIndex { + 0 1 dpiranges length 1 sub { dup dpiranges exch get 1 sub dpi le {exit} {pop} ifelse } for +} bind def +/getCyanScreen { + FMUseHighFrequencyScreens { CHighAngles CMHighFreqs} {CLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getMagentaScreen { + FMUseHighFrequencyScreens { MHighAngles CMHighFreqs } {MLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getYellowScreen { + FMUseHighFrequencyScreens { YHighTDot YHighFreqs} { YLowTDot YLowFreqs } ifelse + screenIndex dup 3 1 roll get 3 1 roll get { 3 div + {2 { 1 add 2 div 3 mul dup floor sub 2 mul 1 sub exch} repeat + FMSpotFunction } } {/FMSpotFunction load } ifelse + 0.0 exch +} bind def +/getBlackScreen { + FMUseHighFrequencyScreens { KHighFreqs } { KLowFreqs } ifelse + screenIndex get 45.0 /FMSpotFunction load +} bind def +/getSpotScreen { + getBlackScreen +} bind def +/getCompositeScreen { + getBlackScreen +} bind def +/FMSetScreen + fMLevel1 { /setscreen load + }{ { + 8 dict begin + /HalftoneType 1 def + /SpotFunction exch def + /Angle exch def + /Frequency exch def + /AccurateScreens FMUseAcccurateScreens def + currentdict end sethalftone + } bind } ifelse +def +/setDefaultScreen { + FMPColor { + orgrxfer cvx orggxfer cvx orgbxfer cvx orgxfer cvx setcolortransfer + } + { + orgxfer cvx settransfer + } ifelse + orgfreq organgle orgproc cvx setscreen +} bind def +/setCurrentScreen { + FrameSepIs FMnone eq { + FMUseDefaultNoSeparationScreen { + setDefaultScreen + } { + getCompositeScreen FMSetScreen + } ifelse + } { + FrameSepIs FMcustom eq { + FMUseDefaultSpotSeparationScreen { + setDefaultScreen + } { + getSpotScreen FMSetScreen + } ifelse + } { + FMUseDefaultProcessSeparationScreen { + setDefaultScreen + } { + FrameSepIs FMcyan eq { + getCyanScreen FMSetScreen + } { + FrameSepIs FMmagenta eq { + getMagentaScreen FMSetScreen + } { + FrameSepIs FMyellow eq { + getYellowScreen FMSetScreen + } { + getBlackScreen FMSetScreen + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse +} bind def +end + +/FMDOCUMENT { + array /FMfonts exch def + /#copies exch def + FrameDict begin + 0 ne /manualfeed exch def + /paperheight exch def + /paperwidth exch def + 0 ne /fMNegative exch def + 0 ne /edown exch def + /yscale exch def + /xscale exch def + fMLevel1 { + manualfeed {setmanualfeed} if + /FMdicttop countdictstack 1 add def + /FMoptop count def + setpapername + manualfeed {true} {papersize} ifelse + {manualpapersize} {false} ifelse + {desperatepapersize} {false} ifelse + {papersizefailure} if + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + } + {2 dict + dup /PageSize [paperwidth paperheight] put + manualfeed {dup /ManualFeed manualfeed put} if + {setpagedevice} stopped {papersizefailure} if + } + ifelse + + FMPColor { + currentcolorscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + cvlit /orgbproc exch def + /orgbangle exch def + /orgbfreq exch def + cvlit /orggproc exch def + /orggangle exch def + /orggfreq exch def + cvlit /orgrproc exch def + /orgrangle exch def + /orgrfreq exch def + currentcolortransfer + fMNegative { + 1 1 4 { + pop { 1 exch sub } fmConcatProcs 4 1 roll + } for + 4 copy + setcolortransfer + } if + cvlit /orgxfer exch def + cvlit /orgbxfer exch def + cvlit /orggxfer exch def + cvlit /orgrxfer exch def + } { + currentscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + + currenttransfer + fMNegative { + { 1 exch sub } fmConcatProcs + dup settransfer + } if + cvlit /orgxfer exch def + } ifelse + end +} def +/FMBEGINPAGE { + FrameDict begin + /pagesave save def + 3.86 setmiterlimit + /landscape exch 0 ne def + landscape { + 90 rotate 0 exch dup /pwid exch def neg translate pop + }{ + pop /pwid exch def + } ifelse + edown { [-1 0 0 1 pwid 0] concat } if + 0 0 moveto paperwidth 0 lineto paperwidth paperheight lineto + 0 paperheight lineto 0 0 lineto 1 setgray fill + xscale yscale scale + /orgmatrix matrix def + gsave +} def +/FMENDPAGE { + grestore + pagesave restore + end + showpage + } def +/FMFONTDEFINE { + FrameDict begin + findfont + ReEncode + 1 index exch + definefont + FMfonts 3 1 roll + put + end + } def +/FMFILLS { + FrameDict begin dup + array /fillvals exch def + dict /patCache exch def + end + } def +/FMFILL { + FrameDict begin + fillvals 3 1 roll put + end + } def +/FMNORMALIZEGRAPHICS { + newpath + 1 setlinewidth + 0 setlinecap + 0 0 0 sethsbcolor + 0 setgray + } bind def +/FMBEGINEPSF { + end + /FMEPSF save def + /showpage {} def +% See Adobe's "PostScript Language Reference Manual, 2nd Edition", page 714. +% "...the following operators MUST NOT be used in an EPS file:" (emphasis ours) + /banddevice {(banddevice) FMBADEPSF} def + /clear {(clear) FMBADEPSF} def + /cleardictstack {(cleardictstack) FMBADEPSF} def + /copypage {(copypage) FMBADEPSF} def + /erasepage {(erasepage) FMBADEPSF} def + /exitserver {(exitserver) FMBADEPSF} def + /framedevice {(framedevice) FMBADEPSF} def + /grestoreall {(grestoreall) FMBADEPSF} def + /initclip {(initclip) FMBADEPSF} def + /initgraphics {(initgraphics) FMBADEPSF} def + /quit {(quit) FMBADEPSF} def + /renderbands {(renderbands) FMBADEPSF} def + /setglobal {(setglobal) FMBADEPSF} def + /setpagedevice {(setpagedevice) FMBADEPSF} def + /setshared {(setshared) FMBADEPSF} def + /startjob {(startjob) FMBADEPSF} def + /lettertray {(lettertray) FMBADEPSF} def + /letter {(letter) FMBADEPSF} def + /lettersmall {(lettersmall) FMBADEPSF} def + /11x17tray {(11x17tray) FMBADEPSF} def + /11x17 {(11x17) FMBADEPSF} def + /ledgertray {(ledgertray) FMBADEPSF} def + /ledger {(ledger) FMBADEPSF} def + /legaltray {(legaltray) FMBADEPSF} def + /legal {(legal) FMBADEPSF} def + /statementtray {(statementtray) FMBADEPSF} def + /statement {(statement) FMBADEPSF} def + /executivetray {(executivetray) FMBADEPSF} def + /executive {(executive) FMBADEPSF} def + /a3tray {(a3tray) FMBADEPSF} def + /a3 {(a3) FMBADEPSF} def + /a4tray {(a4tray) FMBADEPSF} def + /a4 {(a4) FMBADEPSF} def + /a4small {(a4small) FMBADEPSF} def + /b4tray {(b4tray) FMBADEPSF} def + /b4 {(b4) FMBADEPSF} def + /b5tray {(b5tray) FMBADEPSF} def + /b5 {(b5) FMBADEPSF} def + FMNORMALIZEGRAPHICS + [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall + fx fw 2 div add fy fh 2 div add translate + rotate + fw 2 div neg fh 2 div neg translate + fw urx llx sub div fh ury lly sub div scale + llx neg lly neg translate + /FMdicttop countdictstack 1 add def + /FMoptop count def + } bind def +/FMENDEPSF { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMEPSF restore + FrameDict begin + } bind def +FrameDict begin +/setmanualfeed { +%%BeginFeature *ManualFeed True + statusdict /manualfeed true put +%%EndFeature + } bind def +/max {2 copy lt {exch} if pop} bind def +/min {2 copy gt {exch} if pop} bind def +/inch {72 mul} def +/pagedimen { + paperheight sub abs 16 lt exch + paperwidth sub abs 16 lt and + {/papername exch def} {pop} ifelse + } bind def +/setpapername { + /papersizedict 14 dict def + papersizedict begin + /papername /unknown def + /Letter 8.5 inch 11.0 inch pagedimen + /LetterSmall 7.68 inch 10.16 inch pagedimen + /Tabloid 11.0 inch 17.0 inch pagedimen + /Ledger 17.0 inch 11.0 inch pagedimen + /Legal 8.5 inch 14.0 inch pagedimen + /Statement 5.5 inch 8.5 inch pagedimen + /Executive 7.5 inch 10.0 inch pagedimen + /A3 11.69 inch 16.5 inch pagedimen + /A4 8.26 inch 11.69 inch pagedimen + /A4Small 7.47 inch 10.85 inch pagedimen + /B4 10.125 inch 14.33 inch pagedimen + /B5 7.16 inch 10.125 inch pagedimen + end + } bind def +/papersize { + papersizedict begin + /Letter {lettertray letter} def + /LetterSmall {lettertray lettersmall} def + /Tabloid {11x17tray 11x17} def + /Ledger {ledgertray ledger} def + /Legal {legaltray legal} def + /Statement {statementtray statement} def + /Executive {executivetray executive} def + /A3 {a3tray a3} def + /A4 {a4tray a4} def + /A4Small {a4tray a4small} def + /B4 {b4tray b4} def + /B5 {b5tray b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + statusdict begin stopped end + } bind def +/manualpapersize { + papersizedict begin + /Letter {letter} def + /LetterSmall {lettersmall} def + /Tabloid {11x17} def + /Ledger {ledger} def + /Legal {legal} def + /Statement {statement} def + /Executive {executive} def + /A3 {a3} def + /A4 {a4} def + /A4Small {a4small} def + /B4 {b4} def + /B5 {b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + stopped + } bind def +/desperatepapersize { + statusdict /setpageparams known + { + paperwidth paperheight 0 1 + statusdict begin + {setpageparams} stopped + end + } {true} ifelse + } bind def +/papersizefailure { + FMAllowPaperSizeMismatch not + { +(The requested paper size is not available in any currently-installed tray) +(Edit the PS file to "FMAllowPaperSizeMismatch true" to use default tray) + FMFAILURE } if + } def +/DiacriticEncoding [ +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl +/numbersign /dollar /percent /ampersand /quotesingle /parenleft +/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K +/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash +/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h +/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar +/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute +/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis +/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis +/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve +/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex +/udieresis /dagger /.notdef /cent /sterling /section /bullet +/paragraph /germandbls /registered /copyright /trademark /acute +/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef +/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown +/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef +/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde +/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright +/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis +/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl +/periodcentered /quotesinglbase /quotedblbase /perthousand +/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute +/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve +/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron +/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +] def +/ReEncode { + dup + length + dict begin + { + 1 index /FID ne + {def} + {pop pop} ifelse + } forall + 0 eq {/Encoding DiacriticEncoding def} if + currentdict + end + } bind def +FMPColor + + { + /BEGINBITMAPCOLOR { + BITMAPCOLOR} def + /BEGINBITMAPCOLORc { + BITMAPCOLORc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUECOLOR } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUECOLORc } def + /BEGINBITMAPCMYK { + BITMAPCMYK } def + /BEGINBITMAPCMYKc { + BITMAPCMYKc } def + } + + { + /BEGINBITMAPCOLOR { + BITMAPGRAY} def + /BEGINBITMAPCOLORc { + BITMAPGRAYc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUEGRAY } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUEGRAYc } def + /BEGINBITMAPCMYK { + BITMAPCMYKGRAY } def + /BEGINBITMAPCMYKc { + BITMAPCMYKGRAYc } def + } +ifelse +/K { + FMPrintAllColorsAsBlack { + dup 1 eq 2 index 1 eq and 3 index 1 eq and not + {7 {pop} repeat 0 0 0 1 0 0 0} if + } if + FrameCurColors astore + pop combineColor +} bind def +/graymode true def +fMLevel1 { + /fmGetFlip { + fMatrix2 exch get mul 0 lt { -1 } { 1 } ifelse + } FmBD +} if +/setPatternMode { + fMLevel1 { + 2 index patScreenDict exch known { + pop pop + patScreenDict exch get aload pop + freq + mul + 5 2 roll + fMatrix2 currentmatrix 1 get 0 ne { + 3 -1 roll 90 add 3 1 roll + sflipx 1 fmGetFlip sflipy 2 fmGetFlip neg mul + } { + sflipx 0 fmGetFlip sflipy 3 fmGetFlip mul + } ifelse + 0 lt {exch pop} {pop} ifelse + fMNegative { + {neg} fmConcatProcs + } if + bind + + + + systemdict /setscreen get exec + /FrameCurGray exch def + } { + /bwidth exch def + /bpside exch def + /bstring exch def + /onbits 0 def /offbits 0 def + freq sangle landscape {90 add} if + {/ypoint exch def + /xpoint exch def + /xindex xpoint 1 add 2 div bpside mul cvi def + /yindex ypoint 1 add 2 div bpside mul cvi def + bstring yindex bwidth mul xindex 8 idiv add get + 1 7 xindex 8 mod sub bitshift and 0 ne fMNegative {not} if + {/onbits onbits 1 add def 1} + {/offbits offbits 1 add def 0} + ifelse + } + setscreen + offbits offbits onbits add div fMNegative {1.0 exch sub} if + /FrameCurGray exch def + } ifelse + } { + pop pop + dup patCache exch known { + patCache exch get + } { + dup + patDict /bstring 3 -1 roll put + patDict + 9 PatFreq screenIndex get div dup matrix scale + makepattern + dup + patCache 4 -1 roll 3 -1 roll put + } ifelse + /FrameCurGray 0 def + /FrameCurPat exch def + } ifelse + /graymode false def + combineColor +} bind def +/setGrayScaleMode { + graymode not { + /graymode true def + fMLevel1 { + setCurrentScreen + } if + } if + /FrameCurGray exch def + combineColor +} bind def +/normalize { + transform round exch round exch itransform + } bind def +/dnormalize { + dtransform round exch round exch idtransform + } bind def +/lnormalize { + 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop + } bind def +/H { + lnormalize setlinewidth + } bind def +/Z { + setlinecap + } bind def + +/PFill { + graymode fMLevel1 or not { + gsave 1 setgray eofill grestore + } if +} bind def +/PStroke { + graymode fMLevel1 or not { + gsave 1 setgray stroke grestore + } if + stroke +} bind def +/X { + fillvals exch get + dup type /stringtype eq + {8 1 setPatternMode} + {setGrayScaleMode} + ifelse + } bind def +/V { + PFill gsave eofill grestore + } bind def +/Vclip { + clip + } bind def +/Vstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/N { + PStroke + } bind def +/Nclip { + strokepath clip newpath + } bind def +/Nstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/M {newpath moveto} bind def +/E {lineto} bind def +/D {curveto} bind def +/O {closepath} bind def +/L { + /n exch def + newpath + normalize + moveto + 2 1 n {pop normalize lineto} for + } bind def +/Y { + L + closepath + } bind def +/R { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + x1 y1 + x2 y1 + x2 y2 + x1 y2 + 4 Y + } bind def +/rarc + {rad + arcto + } bind def +/RR { + /rad exch def + normalize + /y2 exch def + /x2 exch def + normalize + /y1 exch def + /x1 exch def + mark + newpath + { + x1 y1 rad add moveto + x1 y2 x2 y2 rarc + x2 y2 x2 y1 rarc + x2 y1 x1 y1 rarc + x1 y1 x1 y2 rarc + closepath + } stopped {x1 y1 x2 y2 R} if + cleartomark + } bind def +/RRR { + /rad exch def + normalize /y4 exch def /x4 exch def + normalize /y3 exch def /x3 exch def + normalize /y2 exch def /x2 exch def + normalize /y1 exch def /x1 exch def + newpath + normalize moveto + mark + { + x2 y2 x3 y3 rarc + x3 y3 x4 y4 rarc + x4 y4 x1 y1 rarc + x1 y1 x2 y2 rarc + closepath + } stopped + {x1 y1 x2 y2 x3 y3 x4 y4 newpath moveto lineto lineto lineto closepath} if + cleartomark + } bind def +/C { + grestore + gsave + R + clip + setCurrentScreen +} bind def +/CP { + grestore + gsave + Y + clip + setCurrentScreen +} bind def +/F { + FMfonts exch get + FMpointsize scalefont + setfont + } bind def +/Q { + /FMpointsize exch def + F + } bind def +/T { + moveto show + } bind def +/RF { + rotate + 0 ne {-1 1 scale} if + } bind def +/TF { + gsave + moveto + RF + show + grestore + } bind def +/P { + moveto + 0 32 3 2 roll widthshow + } bind def +/PF { + gsave + moveto + RF + 0 32 3 2 roll widthshow + grestore + } bind def +/S { + moveto + 0 exch ashow + } bind def +/SF { + gsave + moveto + RF + 0 exch ashow + grestore + } bind def +/B { + moveto + 0 32 4 2 roll 0 exch awidthshow + } bind def +/BF { + gsave + moveto + RF + 0 32 4 2 roll 0 exch awidthshow + grestore + } bind def +/G { + gsave + newpath + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill fill + grestore + } bind def +/Gstrk { + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/Gclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GG { + gsave + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill + fill + grestore + } bind def +/GGclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GGstrk { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/A { + gsave + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/Aclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/Astrk { + Gstrk +} bind def +/AA { + gsave + savematrix + newpath + + 3 index 2 div add exch 4 index 2 div sub exch + + normalize 3 index 2 div sub exch 4 index 2 div add exch + translate + rotate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/AAclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/AAstrk { + GGstrk +} bind def +/BEGINPRINTCODE { + /FMdicttop countdictstack 1 add def + /FMoptop count 7 sub def + /FMsaveobject save def + userdict begin + /showpage {} def + FMNORMALIZEGRAPHICS + 3 index neg 3 index neg translate + } bind def +/ENDPRINTCODE { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMsaveobject restore + } bind def +/gn { + 0 + { 46 mul + cf read pop + 32 sub + dup 46 lt {exit} if + 46 sub add + } loop + add + } bind def +/cfs { + /str sl string def + 0 1 sl 1 sub {str exch val put} for + str def + } bind def +/ic [ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 + {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx} + {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx} + {19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} + {13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh} + {4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh} + {13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl} + {7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl} + {0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl} + {10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl} + ] def +/ms { + /sl exch def + /val 255 def + /ws cfs + /im cfs + /val 0 def + /bs cfs + /cs cfs + } bind def +400 ms +/ip { + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip { + + + bis ris copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + ris gis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + gis bis copy pop + dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip4 { + + + kis cis copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + cis mis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + mis yis copy pop + dup dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + yis kis copy pop + 3 mul is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/wh { + /len exch def + /pos exch def + ws 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/bl { + /len exch def + /pos exch def + bs 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/s1 1 string def +/fl { + /len exch def + /pos exch def + /val cf s1 readhexstring pop 0 get def + pos 1 pos len add 1 sub {im exch val put} for + pos len + } bind def +/hx { + 3 copy getinterval + cf exch readhexstring pop pop + } bind def +/wbytes { + dup dup + 8 gt { pop 8 idiv mul } + { 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse } ifelse + } bind def +/BEGINBITMAPBWc { + 1 {} COMMONBITMAPc + } bind def +/BEGINBITMAPGRAYc { + 8 {} COMMONBITMAPc + } bind def +/BEGINBITMAP2BITc { + 2 {} COMMONBITMAPc + } bind def +/COMMONBITMAPc { + + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + cvtProc + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} image + bitmapsave restore + grestore + } bind def +/BEGINBITMAPBW { + 1 {} COMMONBITMAP + } bind def +/BEGINBITMAPGRAY { + 8 {} COMMONBITMAP + } bind def +/BEGINBITMAP2BIT { + 2 {} COMMONBITMAP + } bind def +/COMMONBITMAP { + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + cvtProc + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} image + bitmapsave restore + grestore + } bind def +/ngrayt 256 array def +/nredt 256 array def +/nbluet 256 array def +/ngreent 256 array def +fMLevel1 { +/colorsetup { + currentcolortransfer + /gryt exch def + /blut exch def + /grnt exch def + /redt exch def + 0 1 255 { + /indx exch def + /cynu 1 red indx get 255 div sub def + /magu 1 green indx get 255 div sub def + /yelu 1 blue indx get 255 div sub def + /kk cynu magu min yelu min def + /u kk currentundercolorremoval exec def +% /u 0 def + nredt indx 1 0 cynu u sub max sub redt exec put + ngreent indx 1 0 magu u sub max sub grnt exec put + nbluet indx 1 0 yelu u sub max sub blut exec put + ngrayt indx 1 kk currentblackgeneration exec sub gryt exec put + } for + {255 mul cvi nredt exch get} + {255 mul cvi ngreent exch get} + {255 mul cvi nbluet exch get} + {255 mul cvi ngrayt exch get} + setcolortransfer + {pop 0} setundercolorremoval + {} setblackgeneration + } bind def +} +{ +/colorSetup2 { + [ /Indexed /DeviceRGB 255 + {dup red exch get 255 div + exch dup green exch get 255 div + exch blue exch get 255 div} + ] setcolorspace +} bind def +} ifelse +/fakecolorsetup { + /tran 256 string def + 0 1 255 {/indx exch def + tran indx + red indx get 77 mul + green indx get 151 mul + blue indx get 28 mul + add add 256 idiv put} for + currenttransfer + {255 mul cvi tran exch get 255.0 div} + exch fmConcatProcs settransfer +} bind def +/BITMAPCOLOR { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + fMLevel1 { + colorsetup + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} {is} {is} true 3 colorimage + } { + colorSetup2 + /is width depth wbytes string def + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {cf is readhexstring pop} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPCOLORc { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + fMLevel1 { + colorsetup + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} {is} {is} true 3 colorimage + } { + colorSetup2 + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {ip} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLORc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris} {gis} {bis} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYKc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip4 pop cis} {mis} {yis} {kis} true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLOR { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf gis readhexstring pop } + { cf bis readhexstring pop } + true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYK { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /mis width string def + /yis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf mis readhexstring pop } + { cf yis readhexstring pop } + { cf kis readhexstring pop } + true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUEGRAYc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris gis bis width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAYc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop cis mis yis kis width cgray} image + bitmapsave restore + grestore + } bind def +/cgray { + /ww exch def + /k exch def + /y exch def + /m exch def + /c exch def + 0 1 ww 1 sub { /i exch def c i get m i get y i get k i get CMYKtoRGB + .144 mul 3 1 roll .587 mul 3 1 roll .299 mul add add + c i 3 -1 roll floor cvi put } for + c + } bind def +/gray { + /ww exch def + /b exch def + /g exch def + /r exch def + 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul + b i get .114 mul add add r i 3 -1 roll floor cvi put } for + r + } bind def +/BITMAPTRUEGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf gis readhexstring pop + cf bis readhexstring pop width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /yis width string def + /mis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf mis readhexstring pop + cf yis readhexstring pop + cf kis readhexstring pop width cgray} image + bitmapsave restore + grestore + } bind def +/BITMAPGRAY { + 8 {fakecolorsetup} COMMONBITMAP + } bind def +/BITMAPGRAYc { + 8 {fakecolorsetup} COMMONBITMAPc + } bind def +/ENDBITMAP { + } bind def +end + /ALDmatrix matrix def ALDmatrix currentmatrix pop +/StartALD { + /ALDsave save def + savematrix + ALDmatrix setmatrix + } bind def +/InALD { + restorematrix + } bind def +/DoneALD { + ALDsave restore + } bind def +/I { setdash } bind def +/J { [] 0 setdash } bind def +%%EndProlog +%%BeginSetup +(5.0) FMVERSION +1 1 0 0 612 792 0 1 6 FMDOCUMENT +0 0 /Helvetica FMFONTDEFINE +1 0 /Times-Roman FMFONTDEFINE +2 0 /Times-Bold FMFONTDEFINE +3 0 /Times-Italic FMFONTDEFINE +4 0 /Times-BoldItalic FMFONTDEFINE +32 FMFILLS +0 0 FMFILL +1 0.1 FMFILL +2 0.3 FMFILL +3 0.5 FMFILL +4 0.7 FMFILL +5 0.9 FMFILL +6 0.97 FMFILL +7 1 FMFILL +8 <0f1e3c78f0e1c387> FMFILL +9 <0f87c3e1f0783c1e> FMFILL +10 FMFILL +11 FMFILL +12 <8142241818244281> FMFILL +13 <03060c183060c081> FMFILL +14 <8040201008040201> FMFILL +16 1 FMFILL +17 0.9 FMFILL +18 0.7 FMFILL +19 0.5 FMFILL +20 0.3 FMFILL +21 0.1 FMFILL +22 0.03 FMFILL +23 0 FMFILL +24 FMFILL +25 FMFILL +26 <3333333333333333> FMFILL +27 <0000ffff0000ffff> FMFILL +28 <7ebddbe7e7dbbd7e> FMFILL +29 FMFILL +30 <7fbfdfeff7fbfdfe> FMFILL +%%EndSetup +%%Page: "5" 1 +%%BeginPaperSize: Letter +%%EndPaperSize +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(10. cdev Applications) 472.96 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdev 1.4 Release Notes) 267.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(5) 552.44 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(The follo) 180 713.33 T +(wing list has been put on the back b) 216.69 713.33 T +(urner) 359.81 713.33 T +(, b) 380.51 713.33 T +(ut still of interest:) 390.31 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 195.5 695.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.38 (\322Multiknob\323 de) 207 695.33 P +1.38 (vices. Write operations w) 271.18 695.33 P +1.38 (ould be applied to a v) 377.41 695.33 P +1.38 (ector of de) 470.53 695.33 P +1.38 (vices with) 515.79 695.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.55 (weighting f) 207 683.33 P +0.55 (actors which may be constant, or a simple functional form, or deri) 253.28 683.33 P +0.55 (v) 523.17 683.33 P +0.55 (ed by a) 528.02 683.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(call to another process. Intended for tuning machines.) 207 671.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 195.5 656.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.8 (Indirect de) 207 656.33 P +1.8 (vices. The name of the actual de) 251.59 656.33 P +1.8 (vice can be changed on the \337y) 391.25 656.33 P +1.8 (, and all) 522.47 656.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.39 (connections to the old de) 207 644.33 P +2.39 (vice will be automatically dropped and ne) 316.29 644.33 P +2.39 (w connections) 498.12 644.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(established. Useful for changing generic displays from one de) 207 632.33 T +(vice to another) 454.2 632.33 T +(.) 513.08 632.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 195.5 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.65 (tcl de) 207 617.33 P +0.65 (vices. De) 229.34 617.33 P +0.65 (vices implemented as tcl scripts, which may call other cde) 266.95 617.33 P +0.65 (v de) 505.3 617.33 P +0.65 (vices \050or) 522.64 617.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(an) 207 605.33 T +(ything else\051.) 216.29 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 195.5 590.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Connection to an object oriented database.) 207 590.33 T +0 0 0 1 0 0 0 K +72 532 558 539 C +0 0 0 1 0 0 0 K +72 538.29 170.57 538.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 538.29 558 538.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(10.) 153.5 543.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180 543.67 T +(v A) 200.01 543.67 T +(pplications) 220.26 543.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(The follo) 180 517.33 T +(wing applications are a) 216.69 517.33 T +(v) 308.97 517.33 T +(ailable as cde) 313.72 517.33 T +(v e) 367.34 517.33 T +(xtensions from CEB) 379.13 517.33 T +(AF:) 460.45 517.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 195.5 499.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.93 (Correlation package, modeled after SLA) 207 499.33 P +2.93 (C\325) 380.78 499.33 P +2.93 (s correlation plot utility) 390.23 499.33 P +2.93 (. Consists of a) 492.54 499.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(correlation engine class library plus an application \050XA) 207 487.33 T +(CT\051 which uses it.) 428.5 487.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 195.5 472.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.35 (Multiknob utility \050lik) 207 472.33 P +0.35 (e #4 abo) 292.62 472.33 P +0.35 (v) 327.04 472.33 P +0.35 (e, with a GUI interf) 331.89 472.33 P +0.35 (ace\051. This is based upon a prototype) 411.77 472.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(of multiknob de) 207 460.33 T +(vices, and is con\336gured by ascii \336les.) 270.64 460.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.51 (Finally) 180 442.33 P +0.51 (, the follo) 207.69 442.33 P +0.51 (wing EPICS tools will be ported to cde) 247.07 442.33 P +0.51 (v or re-written using cde) 406.79 442.33 P +0.51 (v in the ne) 506.9 442.33 P +0.51 (xt) 550.22 442.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12 months \050ports to be distrib) 180 430.33 T +(uted with EPICS, not cde) 297.86 430.33 T +(v) 399 430.33 T +(, due to licensing constraints\051:) 403.35 430.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 195.5 412.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Alarm Handler \050specialized GUI tool\051. Porting no) 207 412.33 T +(w underw) 405.88 412.33 T +(ay at APS.) 445.49 412.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 195.5 397.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(General operator interf) 207 397.33 T +(ace \050GUI\051, either dm or medm or both.) 298.53 397.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 195.5 382.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Archi) 207 382.33 T +(v) 229.52 382.33 T +(er \050ne) 234.37 382.33 T +(w) 257.16 382.33 T +(, to be distrib) 263.73 382.33 T +(uted with cde) 316.31 382.33 T +(v\051.) 369.94 382.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 195.5 367.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sa) 207 367.33 T +(v) 216.8 367.33 T +(e / Restore tool \050ditto\051.) 221.65 367.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.42 (Other applications will soon become a) 180 349.33 P +3.42 (v) 350.47 349.33 P +3.42 (ailable from other sites, and the most current) 355.22 349.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(information will be a) 180 337.33 T +(v) 263.96 337.33 T +(ailable from the cde) 268.71 337.33 T +(v web site, http://www) 348.16 337.33 T +(.cebaf.go) 438.62 337.33 T +(v/cde) 475.12 337.33 T +(v) 496.53 337.33 T +(.) 500.88 337.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "5" 1 +%%Page: "4" 2 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(8. Customizing for a New System) 54 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(4) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(cdev 1.4 Release Notes) 249.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Document Revision: 1) 451.97 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(\245) 180 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.16 (Pro) 189 713.33 P +-0.16 (vides a def) 202.74 713.33 P +-0.16 (ault name service so that if a de) 245.63 713.33 P +-0.16 (vice is not de\336ned, then an EPICS channel) 370.6 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.43 (access connection is attempted with the record name set equal to the de) 189 701.33 P +0.43 (vice name, and) 478.88 701.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the \336eld name set equal to the attrib) 189 689.33 T +(ute name.) 331.84 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Restrictions:) 162 671.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.13 (Only supports set/get/monitorOn/monitorOf) 189 653.33 P +-0.13 (f v) 365.15 653.33 P +-0.13 (erbs and the pv and readonly service data) 375.7 653.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(tags. Support for arbitrary messages with def) 189 641.33 T +(ault data has ag) 368.59 641.33 T +(ain been postponed.) 430.47 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 627.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Discards all e) 189 627.33 T +(xception callbacks from channel access in this v) 243.28 627.33 T +(ersion.) 435.59 627.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 613.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Channel access security is not supported in this release.) 189 613.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 599.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendCallback does not support the same timeout feature as send.) 189 599.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 585.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.07 (caService f) 189 585.33 P +1.07 (ails if send is called from within a callback function \050either asynchronous) 234.67 585.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(methods are OK: sendNoBlock and sendCallback\051) 189 573.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Compilation options:) 162 555.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 537.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(_CA_SYNC_CONN = perform connections synchronously) 189 537.33 T +(, w) 426.19 537.33 T +(aiting up to 4 seconds.) 438.31 537.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 523.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(_CDEV_DEB) 189 523.33 T +(UG = print v) 246.12 523.33 T +(erbose messages) 297.44 523.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(_EPICS_3_12 = if not de\336ned, use 3.11 calls instead.) 189 509.33 T +0 0 0 1 0 0 0 K +54 451 540 458 C +0 0 0 1 0 0 0 K +54 457.29 152.57 457.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 457.29 540 457.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(8.) 142.5 462.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Customizing f) 162 462.67 T +(or a New System) 245.26 462.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +0.01 (T) 162 436.33 P +0.01 (o customize cde) 167.31 436.33 P +0.01 (v for a ne) 231.52 436.33 P +0.01 (w control system, a ne) 269.35 436.33 P +0.01 (w cde) 358.87 436.33 P +0.01 (v service must be written. T) 382.23 436.33 P +0.01 (w) 493.15 436.33 P +0.01 (o services) 500.27 436.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.54 (are pro) 162 424.33 P +0.54 (vided with the release: caService for EPICS channel access, and skService, a sk) 190.43 424.33 P +0.54 (eleton) 515.56 424.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.1 (service. The ca \050channel access\051 service is a comple) 162 412.33 P +-0.1 (x e) 368.46 412.33 P +-0.1 (xample of ho) 380.15 412.33 P +-0.1 (w to interact with a control) 432.47 412.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.17 (system which supports asychronous I/O. The sk) 162 400.33 P +2.17 (eleton service simply sho) 366.32 400.33 P +2.17 (ws the minimal) 473.98 400.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.02 (interf) 162 388.33 P +-0.02 (ace a service must pro) 183.56 388.33 P +-0.02 (vide, and can be used as a starting point for b) 272.18 388.33 P +-0.02 (uilding a ne) 452.56 388.33 P +-0.02 (w service.) 499.48 388.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.8 (A third e) 162 376.33 P +2.8 (xample is contained in the Service De) 203 376.33 P +2.8 (v) 371.18 376.33 P +2.8 (eloper\325) 376.03 376.33 P +2.8 (s Guide, and is intermediate in) 403.8 376.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(comple) 162 364.33 T +(xity) 191.29 364.33 T +(.) 206.2 364.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Still Planned:) 162 346.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 328.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.26 (a simple service for which you need only pro) 189 328.33 P +0.26 (vide synchronous read and write routines.) 371.49 328.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.86 (This will speed up inte) 189 316.33 P +1.86 (grating a simple synchronous RPC or memory image based) 287.39 316.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(system.) 189 304.33 T +0 0 0 1 0 0 0 K +54 246 540 253 C +0 0 0 1 0 0 0 K +54 252.29 152.57 252.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 252.29 540 252.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(9.) 142.5 257.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Planned Enhancements) 162 257.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +0.46 (There are man) 162 231.33 P +0.46 (y enhancements planned for cde) 220.53 231.33 P +0.46 (v) 350.98 231.33 P +0.46 (, and releases will probably come out e) 355.33 231.33 P +0.46 (v) 514.41 231.33 P +0.46 (ery 3) 519.27 231.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.26 (months for a while. The follo) 162 219.33 P +0.26 (wing is a list of topics planned for summer of 1996. W) 280.25 219.33 P +0.26 (ork on all) 501.15 219.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(of these topics is underw) 162 207.33 T +(ay) 261.33 207.33 T +(.) 270.12 207.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 177.5 189.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.69 (Collection de) 189 189.33 P +0.69 (vices. Created dynamically or statically) 243.05 189.33 P +0.69 (, each de) 403.18 189.33 P +0.69 (vice w) 439.57 189.33 P +0.69 (ould contain a list) 466.54 189.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.28 (of other de) 189 177.33 P +0.28 (vices. Messages w) 232.63 177.33 P +0.28 (ould be repeated to all contained de) 307.24 177.33 P +0.28 (vices, and read results) 450.85 177.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.53 (w) 189 165.33 P +0.53 (ould be collected together and returned to the caller as a v) 196.12 165.33 P +0.53 (ector) 433.11 165.33 P +0.53 (. Implementation will) 452.55 165.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.23 (support passing the list do) 189 153.33 P +0.23 (wn to the service instead of iterating in the cde) 294.14 153.33 P +0.23 (v layer so that) 482.92 153.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(list based services \050such as SLA) 189 141.33 T +(C\325) 317.19 141.33 T +(s\051 can optimize performance.) 326.64 141.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 177.5 126.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.57 (Service + Serv) 189 126.33 P +0.57 (er based upon passing cde) 248.95 126.33 P +0.57 (vData objects between client and serv) 355.39 126.33 P +0.57 (er) 509.43 126.33 P +0.57 (. This) 516.65 126.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.95 (allo) 189 114.33 P +1.95 (ws comple) 203.75 114.33 P +1.95 (x query/reply type operations. A prototype is already in operation at) 248.6 114.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CEB) 189 102.33 T +(AF) 208.1 102.33 T +(, although the protocol is lik) 220.08 102.33 T +(ely to change some) 332.76 102.33 T +(what.) 409.44 102.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 177.5 87.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 189 87.33 T +(irtual de) 195.62 87.33 T +(vice wrapper around the correlation measurement engine \050see belo) 228.42 87.33 T +(w\051.) 494.2 87.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "4" 2 +%%Page: "3" 3 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Changes from 1.3 Version) 443.45 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdev 1.4 Release Notes) 267.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(3) 552.44 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(9.) 195.5 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4.4 (The cde) 207 713.33 P +4.4 (v/e) 243.08 713.33 P +4.4 (xamples directory no) 255.15 713.33 P +4.4 (w contains 2 additional e) 348.14 713.33 P +4.4 (xample services, one) 465.6 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.52 (implementing compound cde) 207 701.33 P +0.52 (v de) 324.45 701.33 P +0.52 (vices, and the other \050demoService\051 is a tri) 341.65 701.33 P +0.52 (vial service) 511.66 701.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(useful as a starting point for read/write services.) 207 689.33 T +0 0 0 1 0 0 0 K +72 631 558 638 C +0 0 0 1 0 0 0 K +72 637.29 170.57 637.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 637.29 558 637.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(5.) 160.5 642.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Changes fr) 180 642.67 T +(om 1.3 V) 245.46 642.67 T +(ersion) 297.33 642.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +-0.18 (Se) 180 616.33 P +-0.18 (v) 189.75 616.33 P +-0.18 (eral minor changes ha) 194.6 616.33 P +-0.18 (v) 281.89 616.33 P +-0.18 (e been introduced to the system in order to impro) 286.74 616.33 P +-0.18 (v) 481.88 616.33 P +-0.18 (e performance for) 486.73 616.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(e) 180 604.33 T +(xisting operations.) 184.29 604.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 195.5 586.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.03 (The) 207 586.33 P +3 F +1.03 (oper) 226.08 586.33 P +1.03 (ator ==) 244.26 586.33 P +1 F +1.03 ( and) 277.96 586.33 P +3 F +1.03 (oper) 299.46 586.33 P +1.03 (ator !=) 317.64 586.33 P +1 F +1.03 ( methods wha) 347.92 586.33 P +1.03 (v) 405.33 586.33 P +1.03 (e been added to the cde) 410.17 586.33 P +1.03 (vData class.) 508.65 586.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.05 (These methods allo) 207 574.33 P +1.05 (w the caller to perform a deep comparison of the contents of tw) 286.63 574.33 P +1.05 (o) 553 574.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 207 562.33 T +(vData objects.) 220.63 562.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 195.5 547.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.08 (A) 207 547.33 P +3 F +-0.08 (cde) 216.64 547.33 P +-0.08 (vT) 230.37 547.33 P +-0.08 (a) 239.45 547.33 P +-0.08 (gT) 244.35 547.33 P +-0.08 (ableCallbac) 253.99 547.33 P +-0.08 (k) 302.68 547.33 P +1 F +-0.08 ( class has been added to the cde) 307.12 547.33 P +-0.08 (vT) 433.25 547.33 P +-0.08 (agT) 443.56 547.33 P +-0.08 (able.h \336le. This class has) 458.31 547.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.97 (a pure virtual callback method that \050when re) 207 535.33 P +1.97 (gistered with the) 397.51 535.33 P +3 F +1.97 (cde) 472.57 535.33 P +1.97 (vData) 486.3 535.33 P +1 F +1.97 ( class\051 will) 510.74 535.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(recei) 207 523.33 T +(v) 226.18 523.33 T +(e a callback each time a ne) 231.03 523.33 T +(w tag is added to the cde) 337.96 523.33 T +(v global tag table.) 436.58 523.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 195.5 508.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.11 (The) 207 508.33 P +3 F +-0.11 (addT) 224.94 508.33 P +-0.11 (a) 244.58 508.33 P +-0.11 (gCallbac) 249.48 508.33 P +-0.11 (k) 285.95 508.33 P +1 F +-0.11 ( method has been added to the) 290.39 508.33 P +3 F +-0.11 (cde) 413.18 508.33 P +-0.11 (vData) 426.91 508.33 P +1 F +-0.11 ( class. This method is used) 451.35 508.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.3 (by the caller to install a) 207 496.33 P +3 F +0.3 (cde) 304.9 496.33 P +0.3 (vT) 318.63 496.33 P +0.3 (a) 327.71 496.33 P +0.3 (gT) 332.61 496.33 P +0.3 (ableCallbac) 342.25 496.33 P +0.3 (k) 390.94 496.33 P +1 F +0.3 ( object that will be e) 395.38 496.33 P +0.3 (x) 478.11 496.33 P +0.3 (ecuted each time a) 482.96 496.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ne) 207 484.33 T +(w tag is added to the global tag table.) 216.19 484.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 195.5 469.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.85 (The) 207 469.33 P +3 F +2.85 (delT) 227.9 469.33 P +2.85 (a) 244.76 469.33 P +2.85 (gCallbac) 249.65 469.33 P +2.85 (k) 286.12 469.33 P +1 F +2.85 (method has been added to the) 295.91 469.33 P +3 F +2.85 (cde) 434.07 469.33 P +2.85 (vData) 447.8 469.33 P +1 F +2.85 ( class. This method) 472.24 469.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.93 (remo) 207 457.33 P +3.93 (v) 227.4 457.33 P +3.93 (es a) 232.25 457.33 P +3 F +3.93 (cde) 257.88 457.33 P +3.93 (vT) 271.61 457.33 P +3.93 (a) 280.69 457.33 P +3.93 (gT) 285.59 457.33 P +3.93 (ableCallbac) 295.23 457.33 P +3.93 (k) 343.92 457.33 P +1 F +3.93 ( object that w) 348.36 457.33 P +3.93 (as pre) 414.2 457.33 P +3.93 (viously installed using the) 441.48 457.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 207 445.33 T +(vData::addT) 220.73 445.33 T +(a) 271.47 445.33 T +(gCallbac) 276.37 445.33 T +(k) 312.84 445.33 T +1 F +( method.) 317.28 445.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 195.5 430.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.94 (The) 207 430.33 P +3 F +0.94 (r) 225.99 430.33 P +0.94 (eadT) 229.51 430.33 P +0.94 (a) 248.59 430.33 P +0.94 (gT) 253.49 430.33 P +0.94 (able) 263.13 430.33 P +1 F +0.94 ( method has been added to the) 280.35 430.33 P +3 F +0.94 ( cde) 407.06 430.33 P +0.94 (vData) 424.23 430.33 P +1 F +0.94 (class. This method allo) 452.11 430.33 P +0.94 (ws) 546.89 430.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.47 (the caller to retrie) 207 418.33 P +0.47 (v) 278.98 418.33 P +0.47 (e a list of inte) 283.83 418.33 P +0.47 (ger tags and their corresponding character strings that) 340.02 418.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(are stored in the global tag table.) 207 406.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 195.5 391.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.32 (The) 207 391.33 P +3 F +1.32 (CDEVT) 226.37 391.33 P +1.32 (A) 257.54 391.33 P +1.32 (GT) 263.3 391.33 P +1.32 (ABLE) 275.58 391.33 P +1 F +1.32 (en) 303.29 391.33 P +1.32 (vironment v) 312.33 391.33 P +1.32 (ariable is used to indicate the location of a \336le) 362 391.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.09 (based list of tags that will be automatically loaded when a cde) 207 379.33 P +0.09 (v application is started. If) 455.72 379.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.33 (the v) 207 367.33 P +0.33 (ariable is not speci\336ed the application will attempt to load the list from) 226.8 367.33 P +3 F +0.33 (/usr/local/) 516.88 367.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(lib/cde) 207 355.33 T +(vT) 234.07 355.33 T +(a) 243.15 355.33 T +(gT) 248.05 355.33 T +(able) 257.69 355.33 T +1 F +(. If this \336le does not e) 274.91 355.33 T +(xist, then the def) 361.7 355.33 T +(ault list of tags will be used.) 428.26 355.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 195.5 340.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.22 (Channel Access Service \050caService\051 modi\336ed to call the callback function immediately) 207 340.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(when a second monitor is installed on an channel that is already monitored.) 207 328.33 T +0 0 0 1 0 0 0 K +72 270 558 277 C +0 0 0 1 0 0 0 K +72 276.29 170.57 276.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 276.29 558 276.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(6.) 160.5 281.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pr) 180 281.67 T +(oblems and Restrictions \050general\051) 194.52 281.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Restrictions:) 180 255.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 237.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.46 (cde) 207 237.33 P +1.46 (v is not yet thread safe, and may not be safe ag) 220.63 237.33 P +1.46 (ainst instantiating more that one) 423.83 237.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 207 225.33 T +(vSystem object.) 220.63 225.33 T +0 0 0 1 0 0 0 K +72 167 558 174 C +0 0 0 1 0 0 0 K +72 173.29 170.57 173.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 173.29 558 173.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(7.) 160.5 178.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Channel Access Ser) 180 178.67 T +(vice F) 297.29 178.67 T +(eatur) 332.32 178.67 T +(es and Restrictions) 363.95 178.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +0.14 (EPICS / Channel Access v) 180 152.33 P +0.14 (ersion 3.12 is recommended. The follo) 287.05 152.33 P +0.14 (wing comments from the 1.1) 442.18 152.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(release still apply:) 180 140.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Major features:) 180 122.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 104.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Supports synchronous and asynchronous send\325) 207 104.33 T +(s.) 393.65 104.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 90.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Fetches data in nati) 207 90.33 T +(v) 284.24 90.33 T +(e type \050type con) 289.09 90.33 T +(v) 352.84 90.33 T +(ersion done on client and not serv) 357.69 90.33 T +(er\051.) 492.52 90.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "3" 3 +%%Page: "2" 4 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Installation) 54 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(2) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(cdev 1.4 Release Notes) 249.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Document Revision: 1) 451.97 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(3.) 142.5 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Installation) 162 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +-0.06 (Sources are a) 162 684.33 P +-0.06 (v) 214.98 684.33 P +-0.06 (ailable in compressed tar format, and contain mak) 219.73 684.33 P +-0.06 (e\336les to b) 419.14 684.33 P +-0.06 (uild the libraries and) 457.7 684.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.17 (utilities. These ha) 162 672.33 P +-0.17 (v) 232.29 672.33 P +-0.17 (e been tested on the HP) 237.13 672.33 P +-0.17 (, SunOS, and SGI platforms to e) 329.31 672.33 P +-0.17 (x) 457.57 672.33 P +-0.17 (ecute correctly) 462.42 672.33 P +-0.17 (, and) 520.73 672.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.01 (SLA) 162 660.33 P +0.01 (C has ported this v) 180.49 660.33 P +0.01 (ersion to V) 255.39 660.33 P +0.01 (AX/VMS. Fix) 298.51 660.33 P +0.01 (es ha) 355.6 660.33 P +0.01 (v) 375.68 660.33 P +0.01 (e also been incorporated from an earlier) 380.53 660.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.96 (port to IBM/AIX \050at CERN\051. As con\336gured, cde) 162 648.33 P +0.96 (v will b) 362.63 648.33 P +0.96 (uild support for the EPICS channel) 394.92 648.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(access service.) 162 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.03 (The Mak) 162 618.33 P +3.03 (e\336les ha) 201.31 618.33 P +3.03 (v) 237.2 618.33 P +3.03 (e been e) 242.04 618.33 P +3.03 (xtensi) 280.72 618.33 P +3.03 (v) 304.36 618.33 P +3.03 (ely re) 309.21 618.33 P +3.03 (w) 334.48 618.33 P +3.03 (ork) 341.6 618.33 P +3.03 (ed since the 1.1 release, and should b) 354.83 618.33 P +3.03 (uild) 524.44 618.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(successfully on more platforms.) 162 606.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.06 (F) 162 588.33 P +3.06 (or further information, see the README \336le in the topmost directory) 167.41 588.33 P +3.06 (, and the) 475.98 588.33 P +3 F +3.06 (cde) 521.83 588.33 P +3.06 (v) 535.56 588.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Administr) 162 576.33 T +(ator\325) 201.3 576.33 T +(s Guide) 220.9 576.33 T +1 F +( in the /doc sub-directory) 251.73 576.33 T +(.) 351.62 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (Support for site speci\336c control systems must be added by the implementer) 162 558.33 P +0.83 (. See the) 471.41 558.33 P +3 F +0.83 (Service) 510.57 558.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.55 (De) 162 546.33 P +1.55 (veloper\325) 173.51 546.33 P +1.55 (s Guide) 206.43 546.33 P +1 F +1.55 ( for help in getting started interf) 238.81 546.33 P +1.55 (acing cde) 375.78 546.33 P +1.55 (v to a ne) 415.12 546.33 P +1.55 (w control system. In) 453.69 546.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(addition, there are a number of e) 162 534.33 T +(xample services included with this release.) 292.09 534.33 T +0 0 0 1 0 0 0 K +54 476 540 483 C +0 0 0 1 0 0 0 K +54 482.29 152.57 482.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 482.29 540 482.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(4.) 142.5 487.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Changes fr) 162 487.67 T +(om 1.1 V) 227.46 487.67 T +(ersion) 279.33 487.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +0.55 (A number of changes ha) 162 461.33 P +0.55 (v) 261.73 461.33 P +0.55 (e been made to mak) 266.58 461.33 P +0.55 (e the source code compile correctly on a lar) 348.65 461.33 P +0.55 (ger) 527.23 461.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.05 (v) 162 449.33 P +0.05 (ariety of compilers, including V) 166.75 449.33 P +0.05 (AX C++ and g++. In addition, cde) 293.63 449.33 P +0.05 (v no) 431.76 449.33 P +0.05 (w produces more error) 449.06 449.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.78 (and w) 162 437.33 P +0.78 (arning messages through its error logging routines. The follo) 186.84 437.33 P +0.78 (wing is a list of the more) 435.87 437.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(visible feature changes:) 162 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 177.5 407.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The C binding is included in the release \050pre) 189 407.33 T +(viously released as an add-on to 1.1\051.) 366.5 407.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 177.5 392.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.19 (The de) 189 392.33 P +-0.19 (vice de\336nitions \050ddl \336le\051 may no) 216.05 392.33 P +-0.19 (w be stored and loaded in a binary format, which) 345.66 392.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 (is about 20 times f) 189 380.33 P +1 (aster to load compared to the ascii format. A ne) 266.79 380.33 P +1 (w utility program,) 465.5 380.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.2 (cddl, compiles the ddl from ascii to binary) 189 368.33 P +0.2 (. At run-time, the \336le format of the ddl \336le is) 359.15 368.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(detected automatically so that either ascii or binary may be used.) 189 356.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 177.5 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.17 (Shared objects are no) 189 341.33 P +2.17 (w loaded from a subdirectory of the directory pointed to by) 281.08 341.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.33 (CDEVSHOBJ, where the subdirectory name is the name of the v) 189 329.33 P +0.33 (ersion of cde) 451.83 329.33 P +0.33 (v ag) 503.89 329.33 P +0.33 (ainst) 521.11 329.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.2 (which the application is running. This mak) 189 317.33 P +1.2 (es it possible to run dif) 367.49 317.33 P +1.2 (ferent applications) 464.65 317.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.22 (ag) 189 305.33 P +-0.22 (ainst dif) 198.39 305.33 P +-0.22 (ferent v) 230.42 305.33 P +-0.22 (ersions of cde) 260.87 305.33 P +-0.22 (v) 315.72 305.33 P +-0.22 (. If the subdirectory does not contain the needed object,) 320.07 305.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(it is loaded from CDEVSHOBJ as before.) 189 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 177.5 278.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.06 (cde) 189 278.33 P +1.06 (vFdChangedCallback added to cde) 202.63 278.33 P +1.06 (vSystem, allo) 345.27 278.33 P +1.06 (wing an application to be noti\336ed) 400.53 278.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(when \336le descriptors are opened or closed by cde) 189 266.33 T +(v services.) 385.92 266.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 177.5 251.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 189 251.33 T +(vData no) 202.63 251.33 T +(w supports a cast to char* as well as operator= o) 238.76 251.33 T +(v) 432.54 251.33 T +(erloading.) 437.39 251.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 177.5 236.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.31 (cde) 189 236.33 P +0.31 (vGroup no) 202.63 236.33 P +0.31 (w supports a deferred e) 245.74 236.33 P +0.31 (x) 340.15 236.33 P +0.31 (ecution / re-e) 345 236.33 P +0.31 (x) 398.23 236.33 P +0.31 (ecution mode: if a group is in this) 403.08 236.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.97 (mode, operations are remembered b) 189 224.33 P +1.97 (ut not e) 340.24 224.33 P +1.97 (x) 374.03 224.33 P +1.97 (ecuted. Sa) 378.88 224.33 P +1.97 (v) 421.75 224.33 P +1.97 (ed operations may later be) 426.6 224.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.22 (e) 189 212.33 P +-0.22 (x) 193.29 212.33 P +-0.22 (ecuted as a group, and re-e) 198.14 212.33 P +-0.22 (x) 304.07 212.33 P +-0.22 (ecuted without re-learning. Only asynchronous operations) 308.92 212.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(are remembered.) 189 200.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 177.5 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.24 (A fe) 189 185.33 P +0.24 (w b) 206.48 185.33 P +0.24 (ugs in the channel access service ha) 221.25 185.33 P +0.24 (v) 365.79 185.33 P +0.24 (e been \336x) 370.64 185.33 P +0.24 (ed. Monitoring of status without) 409.86 185.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(monitoring v) 189 173.33 T +(alue no) 240.7 173.33 T +(w w) 269.61 173.33 T +(orks correctly) 286.45 173.33 T +(.) 341.06 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8.) 177.5 158.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.12 (The cde) 189 158.33 P +-0.12 (v/src directory no) 220.55 158.33 P +-0.12 (w contains an e) 290.6 158.33 P +-0.12 (xtensions sub-directory) 352 158.33 P +-0.12 (. Extensions include the) 444.83 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.4 (tcl interf) 189 146.33 P +0.4 (ace, and the A) 223.46 146.33 P +0.4 (CE \050Adapti) 281.47 146.33 P +0.4 (v) 327.45 146.33 P +0.4 (e Communication En) 332.3 146.33 P +0.4 (vironment\051 based client/serv) 417.71 146.33 P +0.4 (er) 532.23 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.97 (package used for b) 189 134.33 P +1.97 (uilding ne) 269.95 134.33 P +1.97 (w cde) 311.95 134.33 P +1.97 (v serv) 337.27 134.33 P +1.97 (ers and services capable of passing entire) 363.24 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 189 122.33 T +(vData objects o) 202.63 122.33 T +(v) 264.69 122.33 T +(er the netw) 269.54 122.33 T +(ork.) 313.87 122.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "2" 4 +%%Page: "1" 5 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. Overview) 510.49 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdev 1.4 Release Notes) 267.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1) 552.44 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 24 Q +(cdev 1.4 Release Notes) 180 704 T +0 0 0 1 0 0 0 K +72 635 558 642 C +0 0 0 1 0 0 0 K +72 641.29 170.57 641.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 641.29 558 641.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(1.) 160.5 646.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180 646.67 T +(er) 197.75 646.67 T +(view) 210.04 646.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +3.77 (The cde) 180 620.33 P +3.77 (v \050control de) 215.45 620.33 P +3.77 (vice\051 C++ library is designed to pro) 273.83 620.33 P +3.77 (vide a standard application) 439.22 620.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.25 (programming interf) 180 608.33 P +1.25 (ace \050API\051 to one or more underlying packages, typically control system) 259.75 608.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.99 (interf) 180 596.33 P +1.99 (aces. The implementation is in 2 layers: the uppermost layer is used directly by an) 201.56 596.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.12 (application, and pro) 180 584.33 P +1.12 (vides an abstraction of the underlying package as well as man) 261.79 584.33 P +1.12 (y general) 519.96 584.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.22 (purpose features. The second layer \050service layer\051 pro) 180 572.33 P +2.22 (vides the interf) 410.34 572.33 P +2.22 (ace to one or more) 474.68 572.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(underlying packages, and is implemented as loadable libraries.) 180 560.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.53 (cde) 180 542.33 P +0.53 (v w) 193.63 542.33 P +0.53 (as initially de) 208.78 542.33 P +0.53 (v) 263.48 542.33 P +0.53 (eloped at CEB) 268.33 542.33 P +0.53 (AF with input from the EPICS collaboration, and is no) 327.37 542.33 P +0.53 (w) 550.78 542.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.3 (a) 180 530.33 P +0.3 (v) 184.24 530.33 P +0.3 (ailable for an) 188.99 530.33 P +0.3 (yone to tak) 242.2 530.33 P +0.3 (e and use or impro) 287.15 530.33 P +0.3 (v) 362.64 530.33 P +0.3 (e. W) 367.49 530.33 P +0.3 (e welcome all comments, suggestions, b) 385.87 530.33 P +0.3 (ug) 548 530.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.26 (reports, and \050especially\051 b) 180 518.33 P +0.26 (ug \336x) 284.45 518.33 P +0.26 (es, including \336x) 307.62 518.33 P +0.26 (es for ne) 372.17 518.33 P +0.26 (w platforms. There are man) 406.88 518.33 P +0.26 (y planned) 518.58 518.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (enhancements, and w) 180 506.33 P +1.08 (ould welcome v) 267.88 506.33 P +1.08 (olunteers to contrib) 333.73 506.33 P +1.08 (ute to this project. See belo) 413.46 506.33 P +1.08 (w for a) 527.51 506.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(summary of ne) 180 494.33 T +(w and planned features.) 239.74 494.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Y) 180 476.33 T +(ou may join a cde) 186.12 476.33 T +(v discussion list by sending the message) 256.97 476.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( subscribe cde) 180 458.33 T +(v) 253.9 458.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.07 (to the address mailserv@cebaf.go) 180 440.33 P +3.07 (v) 324.36 440.33 P +3.07 (. \050Send the message HELP to the same address for) 328.71 440.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(information on ho) 180 428.33 T +(w to use the mail serv) 251.97 428.33 T +(er) 339.31 428.33 T +(.\051 The cde) 346.53 428.33 T +(v web page is) 386.54 428.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(http://www) 200 410.33 T +(.cebaf.go) 244.91 410.33 T +(v/cde) 281.41 410.33 T +(v/) 302.82 410.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180 392.33 T +(v 1.4 is the third publically released v) 193.63 392.33 T +(ersion of cde) 344.02 392.33 T +(v) 395.42 392.33 T +(.) 399.77 392.33 T +0 0 0 1 0 0 0 K +72 334 558 341 C +0 0 0 1 0 0 0 K +72 340.29 170.57 340.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 340.29 558 340.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(2.) 160.5 345.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Documentation) 180 345.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(The documentation for cde) 180 319.33 T +(v includes the follo) 287.78 319.33 T +(wing:) 364.47 319.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 301.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +0.29 (Intr) 207 301.33 P +0.29 (oduction to cde) 221.55 301.33 P +0.29 (v) 283.65 301.33 P +1 F +0.29 ( -- this is an update of) 288.09 301.33 P +3 F +0.29 (The cde) 379.87 301.33 P +0.29 (v User\325) 411.39 301.33 P +0.29 (s Guide) 441 301.33 P +1 F +0.29 (, complete with more) 472.12 301.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(e) 207 289.33 T +(xamples. It co) 211.29 289.33 T +(v) 267.52 289.33 T +(ers all the basics, and is the best place to start.) 272.37 289.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 275.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +0.72 (A cde) 207 275.33 P +0.72 (v T) 230.06 275.33 P +0.72 (utorial) 242.73 275.33 P +1 F +0.72 ( -- this document goes through ho) 269.96 275.33 P +0.72 (w to use each of the classes in cde) 409.02 275.33 P +0.72 (v) 551.15 275.33 P +0.72 (,) 555.5 275.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(including all public methods; e) 207 263.33 T +(xtensi) 330.74 263.33 T +(v) 354.38 263.33 T +(e e) 359.23 263.33 T +(xamples are gi) 370.46 263.33 T +(v) 428.53 263.33 T +(en.) 433.38 263.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 249.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 207 249.33 T +(v Refer) 220.73 249.33 T +(ence Manual) 248.96 249.33 T +1 F +( -- documents each class in cde) 300.89 249.33 T +(v in alphabetical order) 425.05 249.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 235.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +0.63 (cde) 207 235.33 P +0.63 (v Administr) 220.73 235.33 P +0.63 (ator\325) 267.6 235.33 P +0.63 (s Guide) 287.2 235.33 P +1 F +0.63 ( -- this is for system administrators, and those intending to) 318.66 235.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(port cde) 207 223.33 T +(v to ne) 239.24 223.33 T +(w platforms) 266.21 223.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +0.92 (Service De) 207 209.33 P +0.92 (veloper\325) 251.36 209.33 P +0.92 (s Guide) 284.28 209.33 P +1 F +0.92 (-- this documents a couple of additional classes needed to) 319.46 209.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(create a custom service, and goes through a lengthly e) 207 197.33 T +(xample demoService.) 422.91 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 183.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 207 183.33 T +(v C Binding) 220.73 183.33 T +1 F +( -- documents the C wrapper routines for cde) 268.51 183.33 T +(v) 447.66 183.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(This documentation is also a) 180 165.33 T +(v) 294.24 165.33 T +(ailable on the web site.) 298.99 165.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "1" 5 +%%Trailer +%%BoundingBox: 0 0 612 792 +%%PageOrder: Descend +%%Pages: 5 +%%DocumentFonts: Helvetica +%%+ Times-Roman +%%+ Times-Bold +%%+ Times-Italic +%%+ Times-BoldItalic +%%EOF diff --git a/doc/ps/releaseNotes1_5.ps b/doc/ps/releaseNotes1_5.ps new file mode 100755 index 0000000..b3fa88b --- /dev/null +++ b/doc/ps/releaseNotes1_5.ps @@ -0,0 +1,4376 @@ +%!PS-Adobe-3.0 +%%BoundingBox: (atend) +%%Pages: (atend) +%%PageOrder: (atend) +%%DocumentFonts: (atend) +%%Creator: Frame 5.0 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +% +% Frame ps_prolog 5.0, for use with Frame 5.0 products +% This ps_prolog file is Copyright (c) 1986-1995 Frame Technology +% Corporation. All rights reserved. This ps_prolog file may be +% freely copied and distributed in conjunction with documents created +% using FrameMaker, FrameMaker/SGML and FrameViewer as long as this +% copyright notice is preserved. +% +% FrameMaker users specify the proper paper size for each print job in the +% "Print" dialog's "Printer Paper Size" "Width" and "Height~ fields. If the +% printer that the PS file is sent to does not support the requested paper +% size, or if there is no paper tray of the proper size currently installed, +% then the job will not be printed. The following flag, if set to true, will +% cause the job to print on the default paper in such cases. +/FMAllowPaperSizeMismatch false def +% +% Frame products normally print colors as their true color on a color printer +% or as shades of gray, based on luminance, on a black-and white printer. The +% following flag, if set to true, forces all non-white colors to print as pure +% black. This has no effect on bitmap images. +/FMPrintAllColorsAsBlack false def +% +% Frame products can either set their own line screens or use a printer's +% default settings. Three flags below control this separately for no +% separations, spot separations and process separations. If a flag +% is true, then the default printer settings will not be changed. If it is +% false, Frame products will use their own settings from a table based on +% the printer's resolution. +/FMUseDefaultNoSeparationScreen true def +/FMUseDefaultSpotSeparationScreen true def +/FMUseDefaultProcessSeparationScreen false def +% +% For any given PostScript printer resolution, Frame products have two sets of +% screen angles and frequencies for printing process separations, which are +% recomended by Adobe. The following variable chooses the higher frequencies +% when set to true or the lower frequencies when set to false. This is only +% effective if the appropriate FMUseDefault...SeparationScreen flag is false. +/FMUseHighFrequencyScreens true def +% +% The following is a set of predefined optimal frequencies and angles for various +% common dpi settings. This is taken from "Advances in Color Separation Using +% PostScript Software Technology," from Adobe Systems (3/13/89 P.N. LPS 0043) +% and corrolated with information which is in various PPD (4.0) files. +% +% The "dpiranges" figure is the minimum dots per inch device resolution which +% can support this setting. The "low" and "high" values are controlled by the +% setting of the FMUseHighFrequencyScreens flag above. The "TDot" flags control +% the use of the "Yellow Triple Dot" feature whereby the frequency id divided by +% three, but the dot function is "trippled" giving a block of 3x3 dots per cell. +% +% PatFreq is a compromise pattern frequency for ps Level 2 printers which is close +% to the ideal WYSIWYG pattern frequency of 9 repetitions/inch but does not beat +% (too badly) against the screen frequencies of any separations for that DPI. +/dpiranges [ 2540 2400 1693 1270 1200 635 600 0 ] def +/CMLowFreqs [ 100.402 94.8683 89.2289 100.402 94.8683 66.9349 63.2456 47.4342 ] def +/YLowFreqs [ 95.25 90.0 84.65 95.25 90.0 70.5556 66.6667 50.0 ] def +/KLowFreqs [ 89.8026 84.8528 79.8088 89.8026 84.8528 74.8355 70.7107 53.033 ] def +/CLowAngles [ 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 71.5651 ] def +/MLowAngles [ 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 18.4349 ] def +/YLowTDot [ true true false true true false false false ] def +/CMHighFreqs [ 133.87 126.491 133.843 108.503 102.523 100.402 94.8683 63.2456 ] def +/YHighFreqs [ 127.0 120.0 126.975 115.455 109.091 95.25 90.0 60.0 ] def +/KHighFreqs [ 119.737 113.137 119.713 128.289 121.218 89.8026 84.8528 63.6395 ] def +/CHighAngles [ 71.5651 71.5651 71.5651 70.0169 70.0169 71.5651 71.5651 71.5651 ] def +/MHighAngles [ 18.4349 18.4349 18.4349 19.9831 19.9831 18.4349 18.4349 18.4349 ] def +/YHighTDot [ false false true false false true true false ] def +/PatFreq [ 10.5833 10.0 9.4055 10.5833 10.0 10.5833 10.0 9.375 ] def +% +% PostScript Level 2 printers contain an "Accurate Screens" feature which can +% improve process separation rendering at the expense of compute time. This +% flag is ignored by PostScript Level 1 printers. +/FMUseAcccurateScreens true def +% +% The following PostScript procedure defines the spot function that Frame +% products will use for process separations. You may un-comment-out one of +% the alternative functions below, or use your own. +% +% Dot function +/FMSpotFunction {abs exch abs 2 copy add 1 gt + {1 sub dup mul exch 1 sub dup mul add 1 sub } + {dup mul exch dup mul add 1 exch sub }ifelse } def +% +% Line function +% /FMSpotFunction { pop } def +% +% Elipse function +% /FMSpotFunction { dup 5 mul 8 div mul exch dup mul exch add +% sqrt 1 exch sub } def +% +% +/FMversion (5.0) def +/fMLevel1 /languagelevel where {pop languagelevel} {1} ifelse 2 lt def +/FMPColor + fMLevel1 { + false + /colorimage where {pop pop true} if + } { + true + } ifelse +def +/FrameDict 400 dict def +systemdict /errordict known not {/errordict 10 dict def + errordict /rangecheck {stop} put} if +% The readline in PS 23.0 doesn't recognize cr's as nl's on AppleTalk +FrameDict /tmprangecheck errordict /rangecheck get put +errordict /rangecheck {FrameDict /bug true put} put +FrameDict /bug false put +mark +% Some PS machines read past the CR, so keep the following 3 lines together! +currentfile 5 string readline +00 +0000000000 +cleartomark +errordict /rangecheck FrameDict /tmprangecheck get put +FrameDict /bug get { + /readline { + /gstring exch def + /gfile exch def + /gindex 0 def + { + gfile read pop + dup 10 eq {exit} if + dup 13 eq {exit} if + gstring exch gindex exch put + /gindex gindex 1 add def + } loop + pop + gstring 0 gindex getinterval true + } bind def + } if +/FMshowpage /showpage load def +/FMquit /quit load def +/FMFAILURE { + dup = flush + FMshowpage + /Helvetica findfont 12 scalefont setfont + 72 200 moveto show + 72 220 moveto show + FMshowpage + FMquit + } def +/FMVERSION { + FMversion ne { + (Frame product version does not match ps_prolog! Check installation;) + (also check ~/fminit and ./fminit for old versions) FMFAILURE + } if + } def +/FMBADEPSF { + (Adobe's PostScript Language Reference Manual, 2nd Edition, section H.2.4) + (says your EPS file is not valid, as it calls X ) + dup dup (X) search pop exch pop exch pop length + 5 -1 roll + putinterval + FMFAILURE + } def +/fmConcatProcs + { + /proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def + newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx +}def +FrameDict begin [ + /ALDsave + /FMdicttop + /FMoptop + /FMpointsize + /FMsaveobject + /b + /bitmapsave + /blut + /bpside + /bs + /bstring + /bwidth + /c + /cf + /cs + /cynu + /depth + /edown + /fh + /fillvals + /fw + /fx + /fy + /g + /gfile + /gindex + /grnt + /gryt + /gstring + /height + /hh + /i + /im + /indx + /is + /k + /kk + /landscape + /lb + /len + /llx + /lly + /m + /magu + /manualfeed + /n + /offbits + /onbits + /organgle + /orgbangle + /orgbfreq + /orgbproc + /orgbxfer + /orgfreq + /orggangle + /orggfreq + /orggproc + /orggxfer + /orgmatrix + /orgproc + /orgrangle + /orgrfreq + /orgrproc + /orgrxfer + /orgxfer + /pagesave + /paperheight + /papersizedict + /paperwidth + /pos + /pwid + /r + /rad + /redt + /sl + /str + /tran + /u + /urx + /ury + /val + /width + /width + /ws + /ww + /x + /x1 + /x2 + /xindex + /xpoint + /xscale + /xx + /y + /y1 + /y2 + /yelu + /yindex + /ypoint + /yscale + /yy +] { 0 def } forall +/FmBD {bind def} bind def +systemdict /pdfmark known { + /fMAcrobat true def + + /FmPD /pdfmark load def + + + /FmPT /show load def + + + currentdistillerparams /CoreDistVersion get 2000 ge { + + + /FmPD2 /pdfmark load def + + + + + + /FmPA { mark exch /Dest exch 5 3 roll + /View [ /XYZ null 6 -2 roll FmDC exch pop null] /DEST FmPD + }FmBD + } { + + /FmPD2 /cleartomark load def + /FmPA {pop pop pop}FmBD + } ifelse +} { + + /fMAcrobat false def + /FmPD /cleartomark load def + /FmPD2 /cleartomark load def + /FmPT /pop load def + /FmPA {pop pop pop}FmBD +} ifelse +/FmDC { + transform fMDefaultMatrix itransform cvi exch cvi exch +}FmBD +/FmBx { + dup 3 index lt {3 1 roll exch} if + 1 index 4 index lt {4 -1 roll 3 1 roll exch 4 1 roll} if +}FmBD +/FMnone 0 def +/FMcyan 1 def +/FMmagenta 2 def +/FMyellow 3 def +/FMblack 4 def +/FMcustom 5 def +/fMNegative false def +/FrameSepIs FMnone def +/FrameSepBlack 0 def +/FrameSepYellow 0 def +/FrameSepMagenta 0 def +/FrameSepCyan 0 def +/FrameSepRed 1 def +/FrameSepGreen 1 def +/FrameSepBlue 1 def +/FrameCurGray 1 def +/FrameCurPat null def +/FrameCurColors [ 0 0 0 1 0 0 0 ] def +/FrameColorEpsilon .001 def +/eqepsilon { + sub dup 0 lt {neg} if + FrameColorEpsilon le +} bind def +/FrameCmpColorsCMYK { + 2 copy 0 get exch 0 get eqepsilon { + 2 copy 1 get exch 1 get eqepsilon { + 2 copy 2 get exch 2 get eqepsilon { + 3 get exch 3 get eqepsilon + } {pop pop false} ifelse + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/FrameCmpColorsRGB { + 2 copy 4 get exch 0 get eqepsilon { + 2 copy 5 get exch 1 get eqepsilon { + 6 get exch 2 get eqepsilon + }{pop pop false} ifelse + } {pop pop false} ifelse +} bind def +/RGBtoCMYK { + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 1 exch sub + 3 1 roll + 3 copy + 2 copy + le { pop } { exch pop } ifelse + 2 copy + le { pop } { exch pop } ifelse + dup dup dup + 6 1 roll + 4 1 roll + 7 1 roll + sub + 6 1 roll + sub + 5 1 roll + sub + 4 1 roll +} bind def +/CMYKtoRGB { + dup dup 4 -1 roll add + 5 1 roll 3 -1 roll add + 4 1 roll add + 1 exch sub dup 0 lt {pop 0} if 3 1 roll + 1 exch sub dup 0 lt {pop 0} if exch + 1 exch sub dup 0 lt {pop 0} if exch +} bind def +/FrameSepInit { + 1.0 RealSetgray +} bind def +/FrameSetSepColor { + /FrameSepBlue exch def + /FrameSepGreen exch def + /FrameSepRed exch def + /FrameSepBlack exch def + /FrameSepYellow exch def + /FrameSepMagenta exch def + /FrameSepCyan exch def + /FrameSepIs FMcustom def + setCurrentScreen +} bind def +/FrameSetCyan { + /FrameSepBlue 1.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 1.0 def + /FrameSepIs FMcyan def + setCurrentScreen +} bind def + +/FrameSetMagenta { + /FrameSepBlue 1.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 1.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMmagenta def + setCurrentScreen +} bind def + +/FrameSetYellow { + /FrameSepBlue 0.0 def + /FrameSepGreen 1.0 def + /FrameSepRed 1.0 def + /FrameSepBlack 0.0 def + /FrameSepYellow 1.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMyellow def + setCurrentScreen +} bind def + +/FrameSetBlack { + /FrameSepBlue 0.0 def + /FrameSepGreen 0.0 def + /FrameSepRed 0.0 def + /FrameSepBlack 1.0 def + /FrameSepYellow 0.0 def + /FrameSepMagenta 0.0 def + /FrameSepCyan 0.0 def + /FrameSepIs FMblack def + setCurrentScreen +} bind def + +/FrameNoSep { + /FrameSepIs FMnone def + setCurrentScreen +} bind def +/FrameSetSepColors { + FrameDict begin + [ exch 1 add 1 roll ] + /FrameSepColors + exch def end + } bind def +/FrameColorInSepListCMYK { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsCMYK + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/FrameColorInSepListRGB { + FrameSepColors { + exch dup 3 -1 roll + FrameCmpColorsRGB + { pop true exit } if + } forall + dup true ne {pop false} if + } bind def +/RealSetgray /setgray load def +/RealSetrgbcolor /setrgbcolor load def +/RealSethsbcolor /sethsbcolor load def +end +/setgray { + FrameDict begin + FrameSepIs FMnone eq + { RealSetgray } + { + FrameSepIs FMblack eq + { RealSetgray } + { FrameSepIs FMcustom eq + FrameSepRed 0 eq and + FrameSepGreen 0 eq and + FrameSepBlue 0 eq and { + RealSetgray + } { + 1 RealSetgray pop + } ifelse + } ifelse + } ifelse + end +} bind def +/setrgbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetrgbcolor } + { + 3 copy [ 4 1 roll ] + FrameColorInSepListRGB + { + FrameSepBlue eq exch + FrameSepGreen eq and exch + FrameSepRed eq and + { 0 } { 1 } ifelse + } + { + FMPColor { + RealSetrgbcolor + currentcmykcolor + } { + RGBtoCMYK + } ifelse + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end +} bind def +/sethsbcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSethsbcolor } + { + RealSethsbcolor + currentrgbcolor + setrgbcolor + } + ifelse + end +} bind def +FrameDict begin +/setcmykcolor where { + pop /RealSetcmykcolor /setcmykcolor load def +} { + /RealSetcmykcolor { + 4 1 roll + 3 { 3 index add 0 max 1 min 1 exch sub 3 1 roll} repeat + RealSetrgbcolor pop + } bind def +} ifelse +userdict /setcmykcolor { + FrameDict begin + FrameSepIs FMnone eq + { RealSetcmykcolor } + { + 4 copy [ 5 1 roll ] + FrameColorInSepListCMYK + { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + { 0 } { 1 } ifelse + } + { + FrameSepIs FMblack eq + {1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + RealSetgray + } + ifelse + end + } bind put +fMLevel1 { + + + + /patScreenDict 7 dict dup begin + <0f1e3c78f0e1c387> [ 45 { pop } {exch pop} .5 2 sqrt] FmBD + <0f87c3e1f0783c1e> [ 135 { pop } {exch pop} .5 2 sqrt] FmBD + [ 0 { pop } dup .5 2 ] FmBD + [ 90 { pop } dup .5 2 ] FmBD + <8142241818244281> [ 45 { 2 copy lt {exch} if pop} dup .75 2 sqrt] FmBD + <03060c183060c081> [ 45 { pop } {exch pop} .875 2 sqrt] FmBD + <8040201008040201> [ 135 { pop } {exch pop} .875 2 sqrt] FmBD + end def +} { + + /patProcDict 5 dict dup begin + <0f1e3c78f0e1c387> { 3 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <0f87c3e1f0783c1e> { 3 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + <8142241818244281> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -1 -1 moveto 9 9 lineto stroke } bind def + <03060c183060c081> { 1 setlinewidth -1 -1 moveto 9 9 lineto stroke + 4 -4 moveto 12 4 lineto stroke + -4 4 moveto 4 12 lineto stroke} bind def + <8040201008040201> { 1 setlinewidth -1 9 moveto 9 -1 lineto stroke + -4 4 moveto 4 -4 lineto stroke + 4 12 moveto 12 4 lineto stroke} bind def + end def + /patDict 15 dict dup begin + /PatternType 1 def + /PaintType 2 def + /TilingType 3 def + /BBox [ 0 0 8 8 ] def + /XStep 8 def + /YStep 8 def + /PaintProc { + begin + patProcDict bstring known { + patProcDict bstring get exec + } { + 8 8 true [1 0 0 -1 0 8] bstring imagemask + } ifelse + end + } bind def + end def +} ifelse +/combineColor { + FrameSepIs FMnone eq + { + graymode fMLevel1 or not { + + [/Pattern [/DeviceCMYK]] setcolorspace + FrameCurColors 0 4 getinterval aload pop FrameCurPat setcolor + } { + FrameCurColors 3 get 1.0 ge { + FrameCurGray RealSetgray + } { + fMAcrobat not FMPColor graymode and and { + 0 1 3 { + FrameCurColors exch get + 1 FrameCurGray sub mul + } for + RealSetcmykcolor + } { + 4 1 6 { + FrameCurColors exch get + graymode { + 1 exch sub 1 FrameCurGray sub mul 1 exch sub + } { + 1.0 lt {FrameCurGray} {1} ifelse + } ifelse + } for + RealSetrgbcolor + } ifelse + } ifelse + } ifelse + } { + FrameCurColors 0 4 getinterval aload + FrameColorInSepListCMYK { + FrameSepBlack eq exch + FrameSepYellow eq and exch + FrameSepMagenta eq and exch + FrameSepCyan eq and + FrameSepIs FMcustom eq and + { FrameCurGray } { 1 } ifelse + } { + FrameSepIs FMblack eq + {FrameCurGray 1.0 exch sub mul 1.0 exch sub 4 1 roll pop pop pop} { + FrameSepIs FMyellow eq + {pop FrameCurGray 1.0 exch sub mul 1.0 exch sub 3 1 roll pop pop} { + FrameSepIs FMmagenta eq + {pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub exch pop } { + FrameSepIs FMcyan eq + {pop pop pop FrameCurGray 1.0 exch sub mul 1.0 exch sub } + {pop pop pop pop 1} ifelse } ifelse } ifelse } ifelse + } ifelse + graymode fMLevel1 or not { + + [/Pattern [/DeviceGray]] setcolorspace + FrameCurPat setcolor + } { + graymode not fMLevel1 and { + + dup 1 lt {pop FrameCurGray} if + } if + RealSetgray + } ifelse + } ifelse +} bind def +/savematrix { + orgmatrix currentmatrix pop + } bind def +/restorematrix { + orgmatrix setmatrix + } bind def +/fMDefaultMatrix matrix defaultmatrix def +/fMatrix2 matrix def +/dpi 72 0 fMDefaultMatrix dtransform + dup mul exch dup mul add sqrt def + +/freq dpi dup 72 div round dup 0 eq {pop 1} if 8 mul div def +/sangle 1 0 fMDefaultMatrix dtransform exch atan def + sangle fMatrix2 rotate + fMDefaultMatrix fMatrix2 concatmatrix + dup 0 get /sflipx exch def + 3 get /sflipy exch def +/screenIndex { + 0 1 dpiranges length 1 sub { dup dpiranges exch get 1 sub dpi le {exit} {pop} ifelse } for +} bind def +/getCyanScreen { + FMUseHighFrequencyScreens { CHighAngles CMHighFreqs} {CLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getMagentaScreen { + FMUseHighFrequencyScreens { MHighAngles CMHighFreqs } {MLowAngles CMLowFreqs} ifelse + screenIndex dup 3 1 roll get 3 1 roll get /FMSpotFunction load +} bind def +/getYellowScreen { + FMUseHighFrequencyScreens { YHighTDot YHighFreqs} { YLowTDot YLowFreqs } ifelse + screenIndex dup 3 1 roll get 3 1 roll get { 3 div + {2 { 1 add 2 div 3 mul dup floor sub 2 mul 1 sub exch} repeat + FMSpotFunction } } {/FMSpotFunction load } ifelse + 0.0 exch +} bind def +/getBlackScreen { + FMUseHighFrequencyScreens { KHighFreqs } { KLowFreqs } ifelse + screenIndex get 45.0 /FMSpotFunction load +} bind def +/getSpotScreen { + getBlackScreen +} bind def +/getCompositeScreen { + getBlackScreen +} bind def +/FMSetScreen + fMLevel1 { /setscreen load + }{ { + 8 dict begin + /HalftoneType 1 def + /SpotFunction exch def + /Angle exch def + /Frequency exch def + /AccurateScreens FMUseAcccurateScreens def + currentdict end sethalftone + } bind } ifelse +def +/setDefaultScreen { + FMPColor { + orgrxfer cvx orggxfer cvx orgbxfer cvx orgxfer cvx setcolortransfer + } + { + orgxfer cvx settransfer + } ifelse + orgfreq organgle orgproc cvx setscreen +} bind def +/setCurrentScreen { + FrameSepIs FMnone eq { + FMUseDefaultNoSeparationScreen { + setDefaultScreen + } { + getCompositeScreen FMSetScreen + } ifelse + } { + FrameSepIs FMcustom eq { + FMUseDefaultSpotSeparationScreen { + setDefaultScreen + } { + getSpotScreen FMSetScreen + } ifelse + } { + FMUseDefaultProcessSeparationScreen { + setDefaultScreen + } { + FrameSepIs FMcyan eq { + getCyanScreen FMSetScreen + } { + FrameSepIs FMmagenta eq { + getMagentaScreen FMSetScreen + } { + FrameSepIs FMyellow eq { + getYellowScreen FMSetScreen + } { + getBlackScreen FMSetScreen + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse + } ifelse +} bind def +end + +/FMDOCUMENT { + array /FMfonts exch def + /#copies exch def + FrameDict begin + 0 ne /manualfeed exch def + /paperheight exch def + /paperwidth exch def + 0 ne /fMNegative exch def + 0 ne /edown exch def + /yscale exch def + /xscale exch def + fMLevel1 { + manualfeed {setmanualfeed} if + /FMdicttop countdictstack 1 add def + /FMoptop count def + setpapername + manualfeed {true} {papersize} ifelse + {manualpapersize} {false} ifelse + {desperatepapersize} {false} ifelse + {papersizefailure} if + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + } + {2 dict + dup /PageSize [paperwidth paperheight] put + manualfeed {dup /ManualFeed manualfeed put} if + {setpagedevice} stopped {papersizefailure} if + } + ifelse + + FMPColor { + currentcolorscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + cvlit /orgbproc exch def + /orgbangle exch def + /orgbfreq exch def + cvlit /orggproc exch def + /orggangle exch def + /orggfreq exch def + cvlit /orgrproc exch def + /orgrangle exch def + /orgrfreq exch def + currentcolortransfer + fMNegative { + 1 1 4 { + pop { 1 exch sub } fmConcatProcs 4 1 roll + } for + 4 copy + setcolortransfer + } if + cvlit /orgxfer exch def + cvlit /orgbxfer exch def + cvlit /orggxfer exch def + cvlit /orgrxfer exch def + } { + currentscreen + cvlit /orgproc exch def + /organgle exch def + /orgfreq exch def + + currenttransfer + fMNegative { + { 1 exch sub } fmConcatProcs + dup settransfer + } if + cvlit /orgxfer exch def + } ifelse + end +} def +/FMBEGINPAGE { + FrameDict begin + /pagesave save def + 3.86 setmiterlimit + /landscape exch 0 ne def + landscape { + 90 rotate 0 exch dup /pwid exch def neg translate pop + }{ + pop /pwid exch def + } ifelse + edown { [-1 0 0 1 pwid 0] concat } if + 0 0 moveto paperwidth 0 lineto paperwidth paperheight lineto + 0 paperheight lineto 0 0 lineto 1 setgray fill + xscale yscale scale + /orgmatrix matrix def + gsave +} def +/FMENDPAGE { + grestore + pagesave restore + end + showpage + } def +/FMFONTDEFINE { + FrameDict begin + findfont + ReEncode + 1 index exch + definefont + FMfonts 3 1 roll + put + end + } def +/FMFILLS { + FrameDict begin dup + array /fillvals exch def + dict /patCache exch def + end + } def +/FMFILL { + FrameDict begin + fillvals 3 1 roll put + end + } def +/FMNORMALIZEGRAPHICS { + newpath + 1 setlinewidth + 0 setlinecap + 0 0 0 sethsbcolor + 0 setgray + } bind def +/FMBEGINEPSF { + end + /FMEPSF save def + /showpage {} def +% See Adobe's "PostScript Language Reference Manual, 2nd Edition", page 714. +% "...the following operators MUST NOT be used in an EPS file:" (emphasis ours) + /banddevice {(banddevice) FMBADEPSF} def + /clear {(clear) FMBADEPSF} def + /cleardictstack {(cleardictstack) FMBADEPSF} def + /copypage {(copypage) FMBADEPSF} def + /erasepage {(erasepage) FMBADEPSF} def + /exitserver {(exitserver) FMBADEPSF} def + /framedevice {(framedevice) FMBADEPSF} def + /grestoreall {(grestoreall) FMBADEPSF} def + /initclip {(initclip) FMBADEPSF} def + /initgraphics {(initgraphics) FMBADEPSF} def + /quit {(quit) FMBADEPSF} def + /renderbands {(renderbands) FMBADEPSF} def + /setglobal {(setglobal) FMBADEPSF} def + /setpagedevice {(setpagedevice) FMBADEPSF} def + /setshared {(setshared) FMBADEPSF} def + /startjob {(startjob) FMBADEPSF} def + /lettertray {(lettertray) FMBADEPSF} def + /letter {(letter) FMBADEPSF} def + /lettersmall {(lettersmall) FMBADEPSF} def + /11x17tray {(11x17tray) FMBADEPSF} def + /11x17 {(11x17) FMBADEPSF} def + /ledgertray {(ledgertray) FMBADEPSF} def + /ledger {(ledger) FMBADEPSF} def + /legaltray {(legaltray) FMBADEPSF} def + /legal {(legal) FMBADEPSF} def + /statementtray {(statementtray) FMBADEPSF} def + /statement {(statement) FMBADEPSF} def + /executivetray {(executivetray) FMBADEPSF} def + /executive {(executive) FMBADEPSF} def + /a3tray {(a3tray) FMBADEPSF} def + /a3 {(a3) FMBADEPSF} def + /a4tray {(a4tray) FMBADEPSF} def + /a4 {(a4) FMBADEPSF} def + /a4small {(a4small) FMBADEPSF} def + /b4tray {(b4tray) FMBADEPSF} def + /b4 {(b4) FMBADEPSF} def + /b5tray {(b5tray) FMBADEPSF} def + /b5 {(b5) FMBADEPSF} def + FMNORMALIZEGRAPHICS + [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall + fx fw 2 div add fy fh 2 div add translate + rotate + fw 2 div neg fh 2 div neg translate + fw urx llx sub div fh ury lly sub div scale + llx neg lly neg translate + /FMdicttop countdictstack 1 add def + /FMoptop count def + } bind def +/FMENDEPSF { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMEPSF restore + FrameDict begin + } bind def +FrameDict begin +/setmanualfeed { +%%BeginFeature *ManualFeed True + statusdict /manualfeed true put +%%EndFeature + } bind def +/max {2 copy lt {exch} if pop} bind def +/min {2 copy gt {exch} if pop} bind def +/inch {72 mul} def +/pagedimen { + paperheight sub abs 16 lt exch + paperwidth sub abs 16 lt and + {/papername exch def} {pop} ifelse + } bind def +/setpapername { + /papersizedict 14 dict def + papersizedict begin + /papername /unknown def + /Letter 8.5 inch 11.0 inch pagedimen + /LetterSmall 7.68 inch 10.16 inch pagedimen + /Tabloid 11.0 inch 17.0 inch pagedimen + /Ledger 17.0 inch 11.0 inch pagedimen + /Legal 8.5 inch 14.0 inch pagedimen + /Statement 5.5 inch 8.5 inch pagedimen + /Executive 7.5 inch 10.0 inch pagedimen + /A3 11.69 inch 16.5 inch pagedimen + /A4 8.26 inch 11.69 inch pagedimen + /A4Small 7.47 inch 10.85 inch pagedimen + /B4 10.125 inch 14.33 inch pagedimen + /B5 7.16 inch 10.125 inch pagedimen + end + } bind def +/papersize { + papersizedict begin + /Letter {lettertray letter} def + /LetterSmall {lettertray lettersmall} def + /Tabloid {11x17tray 11x17} def + /Ledger {ledgertray ledger} def + /Legal {legaltray legal} def + /Statement {statementtray statement} def + /Executive {executivetray executive} def + /A3 {a3tray a3} def + /A4 {a4tray a4} def + /A4Small {a4tray a4small} def + /B4 {b4tray b4} def + /B5 {b5tray b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + statusdict begin stopped end + } bind def +/manualpapersize { + papersizedict begin + /Letter {letter} def + /LetterSmall {lettersmall} def + /Tabloid {11x17} def + /Ledger {ledger} def + /Legal {legal} def + /Statement {statement} def + /Executive {executive} def + /A3 {a3} def + /A4 {a4} def + /A4Small {a4small} def + /B4 {b4} def + /B5 {b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + stopped + } bind def +/desperatepapersize { + statusdict /setpageparams known + { + paperwidth paperheight 0 1 + statusdict begin + {setpageparams} stopped + end + } {true} ifelse + } bind def +/papersizefailure { + FMAllowPaperSizeMismatch not + { +(The requested paper size is not available in any currently-installed tray) +(Edit the PS file to "FMAllowPaperSizeMismatch true" to use default tray) + FMFAILURE } if + } def +/DiacriticEncoding [ +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl +/numbersign /dollar /percent /ampersand /quotesingle /parenleft +/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K +/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash +/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h +/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar +/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute +/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis +/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis +/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve +/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex +/udieresis /dagger /.notdef /cent /sterling /section /bullet +/paragraph /germandbls /registered /copyright /trademark /acute +/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef +/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown +/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef +/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde +/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright +/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis +/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl +/periodcentered /quotesinglbase /quotedblbase /perthousand +/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute +/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve +/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron +/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +] def +/ReEncode { + dup + length + dict begin + { + 1 index /FID ne + {def} + {pop pop} ifelse + } forall + 0 eq {/Encoding DiacriticEncoding def} if + currentdict + end + } bind def +FMPColor + + { + /BEGINBITMAPCOLOR { + BITMAPCOLOR} def + /BEGINBITMAPCOLORc { + BITMAPCOLORc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUECOLOR } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUECOLORc } def + /BEGINBITMAPCMYK { + BITMAPCMYK } def + /BEGINBITMAPCMYKc { + BITMAPCMYKc } def + } + + { + /BEGINBITMAPCOLOR { + BITMAPGRAY} def + /BEGINBITMAPCOLORc { + BITMAPGRAYc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUEGRAY } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUEGRAYc } def + /BEGINBITMAPCMYK { + BITMAPCMYKGRAY } def + /BEGINBITMAPCMYKc { + BITMAPCMYKGRAYc } def + } +ifelse +/K { + FMPrintAllColorsAsBlack { + dup 1 eq 2 index 1 eq and 3 index 1 eq and not + {7 {pop} repeat 0 0 0 1 0 0 0} if + } if + FrameCurColors astore + pop combineColor +} bind def +/graymode true def +fMLevel1 { + /fmGetFlip { + fMatrix2 exch get mul 0 lt { -1 } { 1 } ifelse + } FmBD +} if +/setPatternMode { + fMLevel1 { + 2 index patScreenDict exch known { + pop pop + patScreenDict exch get aload pop + freq + mul + 5 2 roll + fMatrix2 currentmatrix 1 get 0 ne { + 3 -1 roll 90 add 3 1 roll + sflipx 1 fmGetFlip sflipy 2 fmGetFlip neg mul + } { + sflipx 0 fmGetFlip sflipy 3 fmGetFlip mul + } ifelse + 0 lt {exch pop} {pop} ifelse + fMNegative { + {neg} fmConcatProcs + } if + bind + + + + systemdict /setscreen get exec + /FrameCurGray exch def + } { + /bwidth exch def + /bpside exch def + /bstring exch def + /onbits 0 def /offbits 0 def + freq sangle landscape {90 add} if + {/ypoint exch def + /xpoint exch def + /xindex xpoint 1 add 2 div bpside mul cvi def + /yindex ypoint 1 add 2 div bpside mul cvi def + bstring yindex bwidth mul xindex 8 idiv add get + 1 7 xindex 8 mod sub bitshift and 0 ne fMNegative {not} if + {/onbits onbits 1 add def 1} + {/offbits offbits 1 add def 0} + ifelse + } + setscreen + offbits offbits onbits add div fMNegative {1.0 exch sub} if + /FrameCurGray exch def + } ifelse + } { + pop pop + dup patCache exch known { + patCache exch get + } { + dup + patDict /bstring 3 -1 roll put + patDict + 9 PatFreq screenIndex get div dup matrix scale + makepattern + dup + patCache 4 -1 roll 3 -1 roll put + } ifelse + /FrameCurGray 0 def + /FrameCurPat exch def + } ifelse + /graymode false def + combineColor +} bind def +/setGrayScaleMode { + graymode not { + /graymode true def + fMLevel1 { + setCurrentScreen + } if + } if + /FrameCurGray exch def + combineColor +} bind def +/normalize { + transform round exch round exch itransform + } bind def +/dnormalize { + dtransform round exch round exch idtransform + } bind def +/lnormalize { + 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop + } bind def +/H { + lnormalize setlinewidth + } bind def +/Z { + setlinecap + } bind def + +/PFill { + graymode fMLevel1 or not { + gsave 1 setgray eofill grestore + } if +} bind def +/PStroke { + graymode fMLevel1 or not { + gsave 1 setgray stroke grestore + } if + stroke +} bind def +/X { + fillvals exch get + dup type /stringtype eq + {8 1 setPatternMode} + {setGrayScaleMode} + ifelse + } bind def +/V { + PFill gsave eofill grestore + } bind def +/Vclip { + clip + } bind def +/Vstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/N { + PStroke + } bind def +/Nclip { + strokepath clip newpath + } bind def +/Nstrk { + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/M {newpath moveto} bind def +/E {lineto} bind def +/D {curveto} bind def +/O {closepath} bind def +/L { + /n exch def + newpath + normalize + moveto + 2 1 n {pop normalize lineto} for + } bind def +/Y { + L + closepath + } bind def +/R { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + x1 y1 + x2 y1 + x2 y2 + x1 y2 + 4 Y + } bind def +/rarc + {rad + arcto + } bind def +/RR { + /rad exch def + normalize + /y2 exch def + /x2 exch def + normalize + /y1 exch def + /x1 exch def + mark + newpath + { + x1 y1 rad add moveto + x1 y2 x2 y2 rarc + x2 y2 x2 y1 rarc + x2 y1 x1 y1 rarc + x1 y1 x1 y2 rarc + closepath + } stopped {x1 y1 x2 y2 R} if + cleartomark + } bind def +/RRR { + /rad exch def + normalize /y4 exch def /x4 exch def + normalize /y3 exch def /x3 exch def + normalize /y2 exch def /x2 exch def + normalize /y1 exch def /x1 exch def + newpath + normalize moveto + mark + { + x2 y2 x3 y3 rarc + x3 y3 x4 y4 rarc + x4 y4 x1 y1 rarc + x1 y1 x2 y2 rarc + closepath + } stopped + {x1 y1 x2 y2 x3 y3 x4 y4 newpath moveto lineto lineto lineto closepath} if + cleartomark + } bind def +/C { + grestore + gsave + R + clip + setCurrentScreen +} bind def +/CP { + grestore + gsave + Y + clip + setCurrentScreen +} bind def +/F { + FMfonts exch get + FMpointsize scalefont + setfont + } bind def +/Q { + /FMpointsize exch def + F + } bind def +/T { + moveto show + } bind def +/RF { + rotate + 0 ne {-1 1 scale} if + } bind def +/TF { + gsave + moveto + RF + show + grestore + } bind def +/P { + moveto + 0 32 3 2 roll widthshow + } bind def +/PF { + gsave + moveto + RF + 0 32 3 2 roll widthshow + grestore + } bind def +/S { + moveto + 0 exch ashow + } bind def +/SF { + gsave + moveto + RF + 0 exch ashow + grestore + } bind def +/B { + moveto + 0 32 4 2 roll 0 exch awidthshow + } bind def +/BF { + gsave + moveto + RF + 0 32 4 2 roll 0 exch awidthshow + grestore + } bind def +/G { + gsave + newpath + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill fill + grestore + } bind def +/Gstrk { + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/Gclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GG { + gsave + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + PFill + fill + grestore + } bind def +/GGclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + clip newpath + restorematrix + } bind def +/GGstrk { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + restorematrix + currentlinewidth exch setlinewidth PStroke setlinewidth + } bind def +/A { + gsave + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/Aclip { + newpath + savematrix + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/Astrk { + Gstrk +} bind def +/AA { + gsave + savematrix + newpath + + 3 index 2 div add exch 4 index 2 div sub exch + + normalize 3 index 2 div sub exch 4 index 2 div add exch + translate + rotate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + PStroke + grestore + } bind def +/AAclip { + savematrix + newpath + normalize translate 0.0 0.0 moveto + rotate + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath + strokepath clip newpath + restorematrix +} bind def +/AAstrk { + GGstrk +} bind def +/BEGINPRINTCODE { + /FMdicttop countdictstack 1 add def + /FMoptop count 7 sub def + /FMsaveobject save def + userdict begin + /showpage {} def + FMNORMALIZEGRAPHICS + 3 index neg 3 index neg translate + } bind def +/ENDPRINTCODE { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMsaveobject restore + } bind def +/gn { + 0 + { 46 mul + cf read pop + 32 sub + dup 46 lt {exit} if + 46 sub add + } loop + add + } bind def +/cfs { + /str sl string def + 0 1 sl 1 sub {str exch val put} for + str def + } bind def +/ic [ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 + {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx} + {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx} + {19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} + {13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh} + {4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh} + {13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl} + {7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl} + {0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl} + {10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl} + ] def +/ms { + /sl exch def + /val 255 def + /ws cfs + /im cfs + /val 0 def + /bs cfs + /cs cfs + } bind def +400 ms +/ip { + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip { + + + bis ris copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + ris gis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + gis bis copy pop + dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/rip4 { + + + kis cis copy pop + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + cis mis copy pop + dup is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + mis yis copy pop + dup dup add is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop pop + yis kis copy pop + 3 mul is exch + + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/wh { + /len exch def + /pos exch def + ws 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/bl { + /len exch def + /pos exch def + bs 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/s1 1 string def +/fl { + /len exch def + /pos exch def + /val cf s1 readhexstring pop 0 get def + pos 1 pos len add 1 sub {im exch val put} for + pos len + } bind def +/hx { + 3 copy getinterval + cf exch readhexstring pop pop + } bind def +/wbytes { + dup dup + 8 gt { pop 8 idiv mul } + { 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse } ifelse + } bind def +/BEGINBITMAPBWc { + 1 {} COMMONBITMAPc + } bind def +/BEGINBITMAPGRAYc { + 8 {} COMMONBITMAPc + } bind def +/BEGINBITMAP2BITc { + 2 {} COMMONBITMAPc + } bind def +/COMMONBITMAPc { + + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + cvtProc + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} image + bitmapsave restore + grestore + } bind def +/BEGINBITMAPBW { + 1 {} COMMONBITMAP + } bind def +/BEGINBITMAPGRAY { + 8 {} COMMONBITMAP + } bind def +/BEGINBITMAP2BIT { + 2 {} COMMONBITMAP + } bind def +/COMMONBITMAP { + /cvtProc exch def + /depth exch def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + cvtProc + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} image + bitmapsave restore + grestore + } bind def +/ngrayt 256 array def +/nredt 256 array def +/nbluet 256 array def +/ngreent 256 array def +fMLevel1 { +/colorsetup { + currentcolortransfer + /gryt exch def + /blut exch def + /grnt exch def + /redt exch def + 0 1 255 { + /indx exch def + /cynu 1 red indx get 255 div sub def + /magu 1 green indx get 255 div sub def + /yelu 1 blue indx get 255 div sub def + /kk cynu magu min yelu min def + /u kk currentundercolorremoval exec def +% /u 0 def + nredt indx 1 0 cynu u sub max sub redt exec put + ngreent indx 1 0 magu u sub max sub grnt exec put + nbluet indx 1 0 yelu u sub max sub blut exec put + ngrayt indx 1 kk currentblackgeneration exec sub gryt exec put + } for + {255 mul cvi nredt exch get} + {255 mul cvi ngreent exch get} + {255 mul cvi nbluet exch get} + {255 mul cvi ngrayt exch get} + setcolortransfer + {pop 0} setundercolorremoval + {} setblackgeneration + } bind def +} +{ +/colorSetup2 { + [ /Indexed /DeviceRGB 255 + {dup red exch get 255 div + exch dup green exch get 255 div + exch blue exch get 255 div} + ] setcolorspace +} bind def +} ifelse +/fakecolorsetup { + /tran 256 string def + 0 1 255 {/indx exch def + tran indx + red indx get 77 mul + green indx get 151 mul + blue indx get 28 mul + add add 256 idiv put} for + currenttransfer + {255 mul cvi tran exch get 255.0 div} + exch fmConcatProcs settransfer +} bind def +/BITMAPCOLOR { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + fMLevel1 { + colorsetup + /is width depth wbytes string def + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {cf is readhexstring pop} {is} {is} true 3 colorimage + } { + colorSetup2 + /is width depth wbytes string def + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {cf is readhexstring pop} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPCOLORc { + /depth 8 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + fMLevel1 { + colorsetup + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height depth [width 0 0 height neg 0 height] + {ip} {is} {is} true 3 colorimage + } { + colorSetup2 + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + 7 dict dup begin + /ImageType 1 def + /Width width def + /Height height def + /ImageMatrix [width 0 0 height neg 0 height] def + /DataSource {ip} bind def + /BitsPerComponent depth def + /Decode [0 255] def + end image + } ifelse + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLORc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris} {gis} {bis} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYKc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip4 pop cis} {mis} {yis} {kis} true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLOR { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf gis readhexstring pop } + { cf bis readhexstring pop } + true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCMYK { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /mis width string def + /yis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop } + { cf mis readhexstring pop } + { cf yis readhexstring pop } + { cf kis readhexstring pop } + true 4 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUEGRAYc { + /depth 24 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /ris im 0 width getinterval def + /gis im width width getinterval def + /bis im width 2 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop ris gis bis width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAYc { + /depth 32 def + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /lb width depth wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + + /is im 0 lb getinterval def + /cis im 0 width getinterval def + /mis im width width getinterval def + /yis im width 2 mul width getinterval def + /kis im width 3 mul width getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + {width rip pop cis mis yis kis width cgray} image + bitmapsave restore + grestore + } bind def +/cgray { + /ww exch def + /k exch def + /y exch def + /m exch def + /c exch def + 0 1 ww 1 sub { /i exch def c i get m i get y i get k i get CMYKtoRGB + .144 mul 3 1 roll .587 mul 3 1 roll .299 mul add add + c i 3 -1 roll floor cvi put } for + c + } bind def +/gray { + /ww exch def + /b exch def + /g exch def + /r exch def + 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul + b i get .114 mul add add r i 3 -1 roll floor cvi put } for + r + } bind def +/BITMAPTRUEGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /gis width string def + /bis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf gis readhexstring pop + cf bis readhexstring pop width gray} image + bitmapsave restore + grestore + } bind def +/BITMAPCMYKGRAY { + gsave + + 3 index 2 div add exch + 4 index 2 div add exch + translate + rotate + 1 index 2 div neg + 1 index 2 div neg + translate + scale + /height exch def /width exch def + /bitmapsave save def + /is width string def + /yis width string def + /mis width string def + /kis width string def + /cf currentfile def + width height 8 [width 0 0 height neg 0 height] + { cf is readhexstring pop + cf mis readhexstring pop + cf yis readhexstring pop + cf kis readhexstring pop width cgray} image + bitmapsave restore + grestore + } bind def +/BITMAPGRAY { + 8 {fakecolorsetup} COMMONBITMAP + } bind def +/BITMAPGRAYc { + 8 {fakecolorsetup} COMMONBITMAPc + } bind def +/ENDBITMAP { + } bind def +end + /ALDmatrix matrix def ALDmatrix currentmatrix pop +/StartALD { + /ALDsave save def + savematrix + ALDmatrix setmatrix + } bind def +/InALD { + restorematrix + } bind def +/DoneALD { + ALDsave restore + } bind def +/I { setdash } bind def +/J { [] 0 setdash } bind def +%%EndProlog +%%BeginSetup +(5.0) FMVERSION +1 1 0 0 612 792 0 1 7 FMDOCUMENT +0 0 /Helvetica FMFONTDEFINE +1 0 /Times-Roman FMFONTDEFINE +2 0 /Times-Bold FMFONTDEFINE +3 0 /Times-Italic FMFONTDEFINE +4 0 /Times-BoldItalic FMFONTDEFINE +32 FMFILLS +0 0 FMFILL +1 0.1 FMFILL +2 0.3 FMFILL +3 0.5 FMFILL +4 0.7 FMFILL +5 0.9 FMFILL +6 0.97 FMFILL +7 1 FMFILL +8 <0f1e3c78f0e1c387> FMFILL +9 <0f87c3e1f0783c1e> FMFILL +10 FMFILL +11 FMFILL +12 <8142241818244281> FMFILL +13 <03060c183060c081> FMFILL +14 <8040201008040201> FMFILL +16 1 FMFILL +17 0.9 FMFILL +18 0.7 FMFILL +19 0.5 FMFILL +20 0.3 FMFILL +21 0.1 FMFILL +22 0.03 FMFILL +23 0 FMFILL +24 FMFILL +25 FMFILL +26 <3333333333333333> FMFILL +27 <0000ffff0000ffff> FMFILL +28 <7ebddbe7e7dbbd7e> FMFILL +29 FMFILL +30 <7fbfdfeff7fbfdfe> FMFILL +%%EndSetup +%%Page: "6" 1 +%%BeginPaperSize: Letter +%%EndPaperSize +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +J +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(11. cdev Applications) 54 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(6) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(cdev 1.5 Release Notes) 249.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Document Revision: 1) 451.97 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(The follo) 162 713.33 T +(wing list has been put on the back b) 198.69 713.33 T +(urner) 341.81 713.33 T +(, b) 362.51 713.33 T +(ut still of interest:) 372.31 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 177.5 695.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.38 (\322Multiknob\323 de) 189 695.33 P +1.38 (vices. Write operations w) 253.18 695.33 P +1.38 (ould be applied to a v) 359.41 695.33 P +1.38 (ector of de) 452.53 695.33 P +1.38 (vices with) 497.79 695.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.55 (weighting f) 189 683.33 P +0.55 (actors which may be constant, or a simple functional form, or deri) 235.28 683.33 P +0.55 (v) 505.17 683.33 P +0.55 (ed by a) 510.02 683.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(call to another process. Intended for tuning machines.) 189 671.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 177.5 656.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.8 (Indirect de) 189 656.33 P +1.8 (vices. The name of the actual de) 233.59 656.33 P +1.8 (vice can be changed on the \337y) 373.25 656.33 P +1.8 (, and all) 504.46 656.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.39 (connections to the old de) 189 644.33 P +2.39 (vice will be automatically dropped and ne) 298.29 644.33 P +2.39 (w connections) 480.12 644.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(established. Useful for changing generic displays from one de) 189 632.33 T +(vice to another) 436.2 632.33 T +(.) 495.08 632.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 177.5 617.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.65 (tcl de) 189 617.33 P +0.65 (vices. De) 211.34 617.33 P +0.65 (vices implemented as tcl scripts, which may call other cde) 248.95 617.33 P +0.65 (v de) 487.3 617.33 P +0.65 (vices \050or) 504.64 617.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(an) 189 605.33 T +(ything else\051.) 198.29 605.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 177.5 590.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Connection to an object oriented database.) 189 590.33 T +0 0 0 1 0 0 0 K +54 532 540 539 C +0 0 0 1 0 0 0 K +54 538.29 152.57 538.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 538.29 540 538.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(11.) 135.5 543.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 162 543.67 T +(v A) 182.01 543.67 T +(pplications) 202.26 543.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(The follo) 162 517.33 T +(wing applications are a) 198.69 517.33 T +(v) 290.97 517.33 T +(ailable as cde) 295.72 517.33 T +(v e) 349.34 517.33 T +(xtensions from CEB) 361.13 517.33 T +(AF:) 442.45 517.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 177.5 499.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.93 (Correlation package, modeled after SLA) 189 499.33 P +2.93 (C\325) 362.78 499.33 P +2.93 (s correlation plot utility) 372.23 499.33 P +2.93 (. Consists of a) 474.54 499.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(correlation engine class library plus an application \050XA) 189 487.33 T +(CT\051 which uses it.) 410.5 487.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 177.5 472.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.35 (Multiknob utility \050lik) 189 472.33 P +0.35 (e #4 abo) 274.62 472.33 P +0.35 (v) 309.04 472.33 P +0.35 (e, with a GUI interf) 313.89 472.33 P +0.35 (ace\051. This is based upon a prototype) 393.77 472.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(of multiknob de) 189 460.33 T +(vices, and is con\336gured by ascii \336les.) 252.64 460.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 177.5 445.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(AR) 189 445.33 T +(TEMIS Model Serv) 202.29 445.33 T +(er) 281.58 445.33 T +(.) 288.8 445.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 177.5 430.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CEB) 189 430.33 T +(AF Lock Serv) 208.1 430.33 T +(er) 264.61 430.33 T +(.) 271.83 430.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.51 (Finally) 162 412.33 P +0.51 (, the follo) 189.69 412.33 P +0.51 (wing EPICS tools will be ported to cde) 229.07 412.33 P +0.51 (v or re-written using cde) 388.79 412.33 P +0.51 (v in the ne) 488.9 412.33 P +0.51 (xt) 532.22 412.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(12 months \050ports to be distrib) 162 400.33 T +(uted with EPICS, not cde) 279.86 400.33 T +(v) 381 400.33 T +(, due to licensing constraints\051:) 385.35 400.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 177.5 382.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Alarm Handler \050specialized GUI tool\051. Porting no) 189 382.33 T +(w underw) 387.88 382.33 T +(ay at APS.) 427.49 382.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 177.5 367.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(General operator interf) 189 367.33 T +(ace \050GUI\051, either dm or medm or both.) 280.53 367.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 177.5 352.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Archi) 189 352.33 T +(v) 211.52 352.33 T +(er \050ne) 216.37 352.33 T +(w) 239.16 352.33 T +(, to be distrib) 245.73 352.33 T +(uted with cde) 298.31 352.33 T +(v\051.) 351.94 352.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 177.5 337.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Sa) 189 337.33 T +(v) 198.8 337.33 T +(e / Restore tool \050ditto\051.) 203.65 337.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.42 (Other applications will soon become a) 162 319.33 P +3.42 (v) 332.47 319.33 P +3.42 (ailable from other sites, and the most current) 337.22 319.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(information will be a) 162 307.33 T +(v) 245.96 307.33 T +(ailable from the cde) 250.71 307.33 T +(v web site, http://www) 330.16 307.33 T +(.cebaf.go) 420.62 307.33 T +(v/cde) 457.12 307.33 T +(v) 478.53 307.33 T +(.) 482.88 307.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "6" 1 +%%Page: "5" 2 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(9. Customizing for a New System) 424.96 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdev 1.5 Release Notes) 267.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(5) 552.44 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(\245) 198 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.16 (Pro) 207 713.33 P +-0.16 (vides a def) 220.74 713.33 P +-0.16 (ault name service so that if a de) 263.63 713.33 P +-0.16 (vice is not de\336ned, then an EPICS channel) 388.6 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.43 (access connection is attempted with the record name set equal to the de) 207 701.33 P +0.43 (vice name, and) 496.88 701.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(the \336eld name set equal to the attrib) 207 689.33 T +(ute name.) 349.84 689.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Restrictions:) 180 671.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 653.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.13 (Only supports set/get/monitorOn/monitorOf) 207 653.33 P +-0.13 (f v) 383.15 653.33 P +-0.13 (erbs and the pv and readonly service data) 393.7 653.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(tags. Support for arbitrary messages with def) 207 641.33 T +(ault data has ag) 386.59 641.33 T +(ain been postponed.) 448.47 641.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 627.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Discards all e) 207 627.33 T +(xception callbacks from channel access in this v) 261.28 627.33 T +(ersion.) 453.59 627.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 613.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Channel access security is not supported in this release.) 207 613.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 599.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sendCallback does not support the same timeout feature as send.) 207 599.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 585.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.07 (caService f) 207 585.33 P +1.07 (ails if send is called from within a callback function \050either asynchronous) 252.67 585.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(methods are OK: sendNoBlock and sendCallback\051) 207 573.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Compilation options:) 180 555.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 537.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(_CA_SYNC_CONN = perform connections synchronously) 207 537.33 T +(, w) 444.19 537.33 T +(aiting up to 4 seconds.) 456.31 537.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 523.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(_CDEV_DEB) 207 523.33 T +(UG = print v) 264.12 523.33 T +(erbose messages) 315.44 523.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 509.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(_EPICS_3_12 = if not de\336ned, use 3.11 calls instead.) 207 509.33 T +0 0 0 1 0 0 0 K +72 451 558 458 C +0 0 0 1 0 0 0 K +72 457.29 170.57 457.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 457.29 558 457.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(9.) 160.5 462.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Customizing f) 180 462.67 T +(or a New System) 263.26 462.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +0.01 (T) 180 436.33 P +0.01 (o customize cde) 185.31 436.33 P +0.01 (v for a ne) 249.52 436.33 P +0.01 (w control system, a ne) 287.35 436.33 P +0.01 (w cde) 376.87 436.33 P +0.01 (v service must be written. T) 400.23 436.33 P +0.01 (w) 511.15 436.33 P +0.01 (o services) 518.28 436.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.54 (are pro) 180 424.33 P +0.54 (vided with the release: caService for EPICS channel access, and skService, a sk) 208.43 424.33 P +0.54 (eleton) 533.56 424.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.1 (service. The ca \050channel access\051 service is a comple) 180 412.33 P +-0.1 (x e) 386.46 412.33 P +-0.1 (xample of ho) 398.15 412.33 P +-0.1 (w to interact with a control) 450.47 412.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.17 (system which supports asychronous I/O. The sk) 180 400.33 P +2.17 (eleton service simply sho) 384.32 400.33 P +2.17 (ws the minimal) 491.98 400.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.02 (interf) 180 388.33 P +-0.02 (ace a service must pro) 201.56 388.33 P +-0.02 (vide, and can be used as a starting point for b) 290.18 388.33 P +-0.02 (uilding a ne) 470.56 388.33 P +-0.02 (w service.) 517.48 388.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.8 (A third e) 180 376.33 P +2.8 (xample is contained in the Service De) 221 376.33 P +2.8 (v) 389.18 376.33 P +2.8 (eloper\325) 394.03 376.33 P +2.8 (s Guide, and is intermediate in) 421.8 376.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(comple) 180 364.33 T +(xity) 209.29 364.33 T +(.) 224.2 364.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Still Planned:) 180 346.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 328.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.26 (a simple service for which you need only pro) 207 328.33 P +0.26 (vide synchronous read and write routines.) 389.49 328.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.86 (This will speed up inte) 207 316.33 P +1.86 (grating a simple synchronous RPC or memory image based) 305.39 316.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(system.) 207 304.33 T +0 0 0 1 0 0 0 K +72 246 558 253 C +0 0 0 1 0 0 0 K +72 252.29 170.57 252.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 252.29 558 252.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(10.) 153.5 257.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Planned Enhancements) 180 257.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +0.46 (There are man) 180 231.33 P +0.46 (y enhancements planned for cde) 238.53 231.33 P +0.46 (v) 368.98 231.33 P +0.46 (, and releases will probably come out e) 373.33 231.33 P +0.46 (v) 532.41 231.33 P +0.46 (ery 3) 537.27 231.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.26 (months for a while. The follo) 180 219.33 P +0.26 (wing is a list of topics planned for summer of 1996. W) 298.25 219.33 P +0.26 (ork on all) 519.15 219.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(of these topics is underw) 180 207.33 T +(ay) 279.33 207.33 T +(.) 288.12 207.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 195.5 189.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.69 (Collection de) 207 189.33 P +0.69 (vices. Created dynamically or statically) 261.05 189.33 P +0.69 (, each de) 421.18 189.33 P +0.69 (vice w) 457.57 189.33 P +0.69 (ould contain a list) 484.54 189.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.28 (of other de) 207 177.33 P +0.28 (vices. Messages w) 250.63 177.33 P +0.28 (ould be repeated to all contained de) 325.24 177.33 P +0.28 (vices, and read results) 468.85 177.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.53 (w) 207 165.33 P +0.53 (ould be collected together and returned to the caller as a v) 214.12 165.33 P +0.53 (ector) 451.11 165.33 P +0.53 (. Implementation will) 470.55 165.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.23 (support passing the list do) 207 153.33 P +0.23 (wn to the service instead of iterating in the cde) 312.14 153.33 P +0.23 (v layer so that) 500.92 153.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(list based services \050such as SLA) 207 141.33 T +(C\325) 335.19 141.33 T +(s\051 can optimize performance.) 344.64 141.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 195.5 126.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.57 (Service + Serv) 207 126.33 P +0.57 (er based upon passing cde) 266.95 126.33 P +0.57 (vData objects between client and serv) 373.39 126.33 P +0.57 (er) 527.43 126.33 P +0.57 (. This) 534.65 126.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.95 (allo) 207 114.33 P +1.95 (ws comple) 221.75 114.33 P +1.95 (x query/reply type operations. A prototype is already in operation at) 266.6 114.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(CEB) 207 102.33 T +(AF) 226.1 102.33 T +(, although the protocol is lik) 238.08 102.33 T +(ely to change some) 350.76 102.33 T +(what.) 427.44 102.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 195.5 87.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(V) 207 87.33 T +(irtual de) 213.62 87.33 T +(vice wrapper around the correlation measurement engine \050see belo) 246.42 87.33 T +(w\051.) 512.2 87.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "5" 2 +%%Page: "4" 3 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(7. Problems and Restrictions \050general\051) 54 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(4) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(cdev 1.5 Release Notes) 249.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Document Revision: 1) 451.97 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(6.) 177.5 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (The) 189 713.33 P +3 F +2.12 (cde) 209.17 713.33 P +2.12 (vRequestObject::attac) 222.9 713.33 P +2.12 (hRef\050cde) 312.17 713.33 P +2.12 (vDe) 347.56 713.33 P +2.12 (vice &, c) 363.51 713.33 P +2.12 (har *messa) 403.42 713.33 P +2.12 (g) 451.26 713.33 P +2.12 (e\051) 456.16 713.33 P +1 F +2.12 ( method has been) 463.93 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.8 (made protected and is no longer part of the public interf) 189 701.33 P +0.8 (ace. This method w) 420.18 701.33 P +0.8 (as al) 500.8 701.33 P +0.8 (w) 519.55 701.33 P +0.8 (ays) 526.67 701.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +11.62 (intended to be used internally by cde) 189 689.33 P +11.62 (v) 405.66 689.33 P +11.62 (. De) 410.01 689.33 P +11.62 (v) 438.03 689.33 P +11.62 (elopers should use) 442.88 689.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +7.24 (cde) 189 677.33 P +7.24 (vRequestObject::attac) 202.73 677.33 P +7.24 (hRef\050c) 292 677.33 P +7.24 (har * de) 317.95 677.33 P +7.24 (vice) 365.62 677.33 P +7.24 (, c) 381.62 677.33 P +7.24 (har * messa) 398.15 677.33 P +7.24 (g) 460.88 677.33 P +7.24 (e\051) 465.77 677.33 P +1 F +7.24 ( to obtain a) 473.55 677.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 189 665.33 T +(vRequestObject reference.) 202.63 665.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 177.5 650.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.03 (The cde) 189 650.33 P +-0.03 (vCallback class has been e) 220.65 650.33 P +-0.03 (xpanded to pro) 327.05 650.33 P +-0.03 (vide a \336reCallback method that has an) 386.84 650.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (additional parameter; partialT) 189 638.33 P +1.08 (ransaction. If the service is deli) 310.22 638.33 P +1.08 (v) 440.31 638.33 P +1.08 (ering a message that is) 445.16 638.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.38 (one of man) 189 626.33 P +3.38 (y that might be generated by the request \050such as monitorOn\051, the) 240.61 626.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.46 (partialT) 189 614.33 P +2.46 (ransaction \337ag should be set to non-zero. If the reply is in response to a) 220.31 614.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.45 (monotonic operation \050such as \322get\323 or \322set\323\051 or if it is the last response of a multi-part) 189 602.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(reply) 189 590.33 T +(, the partialT) 208.9 590.33 T +(ransaction \337ag should be set to zero.) 259.93 590.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8.) 177.5 575.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.71 (The isT) 189 575.33 P +0.71 (ransactionDone method has been added to the cde) 220.2 575.33 P +0.71 (vCallback class to allo) 425.18 575.33 P +0.71 (w the) 517.34 575.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(callback function to identify if the message is a monotonic response or one of man) 189 563.33 T +(y) 518.8 563.33 T +(.) 523.15 563.33 T +0 0 0 1 0 0 0 K +54 505 540 512 C +0 0 0 1 0 0 0 K +54 511.29 152.57 511.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 511.29 540 511.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(7.) 142.5 516.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Pr) 162 516.67 T +(oblems and Restrictions \050general\051) 176.52 516.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Restrictions:) 162 490.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 472.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.46 (cde) 189 472.33 P +1.46 (v is not yet thread safe, and may not be safe ag) 202.63 472.33 P +1.46 (ainst instantiating more that one) 405.83 472.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 189 460.33 T +(vSystem object.) 202.63 460.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 446.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.35 (De) 189 446.33 P +0.35 (vice names can only be added to or remo) 200.41 446.33 P +0.35 (v) 366.9 446.33 P +0.35 (ed from the cde) 371.75 446.33 P +0.35 (vCollection de) 435.03 446.33 P +0.35 (vice until it) 493.74 446.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.92 (has been used) 189 434.33 P +4 F +0.92 (once) 249.8 434.33 P +1 F +0.92 (. After a cde) 269.24 434.33 P +0.92 (vCollectionRequest object has been generated from a) 321.18 434.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(speci\336c cde) 189 422.33 T +(vCollection de) 235.68 422.33 T +(vice, the de) 294.04 422.33 T +(vice list cannot be modi\336ed.) 339.61 422.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 408.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.31 (cde) 189 408.33 P +1.31 (vCollection de) 202.63 408.33 P +1.31 (vices do not support the messages \322monitorOn\323 and \322monitorOf) 262.3 408.33 P +1.31 (f\323.) 529.73 408.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Only monotonic operations are currently supported by the cde) 189 396.33 T +(vCollection de) 437.04 396.33 T +(vice.) 495.4 396.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 382.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.21 (cde) 189 382.33 P +-0.21 (vCollection de\336nitions must be the last things de\336ned in the CDEV DDL \336le. This is) 202.63 382.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +5.89 (because the constituent de) 189 370.33 P +5.89 (vices must ha) 311.12 370.33 P +5.89 (v) 377.14 370.33 P +5.89 (e already been de\336ned when the) 381.98 370.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 189 358.33 T +(vCollection is de\336ned.) 202.63 358.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 344.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.97 (When the data from a cde) 189 344.33 P +0.97 (vDe) 296.64 344.33 P +0.97 (vice operation is used to construct the output cde) 313.05 344.33 P +0.97 (vData) 516.12 344.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.05 (object for a cde) 189 332.33 P +0.05 (vCollection operation, only data that is scalar in nature will be used. If a) 250.81 332.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.29 (cde) 189 320.33 P +0.29 (vDe) 202.63 320.33 P +0.29 (vice returns tagged data items that are arrays in its results, those data items will) 219.04 320.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(not be included in the result.) 189 308.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 294.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.23 (cde) 189 294.33 P +0.23 (vCollection objects must be comprised of re) 202.63 294.33 P +0.23 (gular cde) 380.53 294.33 P +0.23 (vDe) 417.45 294.33 P +0.23 (vice objects only) 433.86 294.33 P +0.23 (. Because) 501.45 294.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.86 (the cde) 189 282.33 P +1.86 (vCollection does not support cde) 219.21 282.33 P +1.86 (vDe) 358.08 282.33 P +1.86 (vices that return arrays of data in their) 374.49 282.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(result, a cde) 189 270.33 T +(vCollection can not contain another cde) 236.79 270.33 T +(vCollection.) 395.68 270.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 256.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.8 (If a cde) 189 256.33 P +0.8 (vCollection consists of de) 220.33 256.33 P +0.8 (vices from multiple services, the collection does not) 326.09 256.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.42 (guarantee the order in which the cde) 189 244.33 P +2.42 (vDe) 348.76 244.33 P +2.42 (vice\325) 365.17 244.33 P +2.42 (s requests will be serviced. Because) 384.61 244.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.32 (services perform at v) 189 232.33 P +1.32 (arying speeds, a f) 276.86 232.33 P +1.32 (aster service may process its de) 350.7 232.33 P +1.32 (vices requests) 482.86 232.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(sooner than another service.) 189 220.33 T +0 0 0 1 0 0 0 K +54 162 540 169 C +0 0 0 1 0 0 0 K +54 168.29 152.57 168.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 168.29 540 168.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(8.) 142.5 173.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Channel Access Ser) 162 173.67 T +(vice F) 279.29 173.67 T +(eatur) 314.32 173.67 T +(es and Restrictions) 345.95 173.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +0.14 (EPICS / Channel Access v) 162 147.33 P +0.14 (ersion 3.12 is recommended. The follo) 269.05 147.33 P +0.14 (wing comments from the 1.1) 424.18 147.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(release still apply:) 162 135.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Major features:) 162 117.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 99.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Supports synchronous and asynchronous send\325) 189 99.33 T +(s.) 375.65 99.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 180 85.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Fetches data in nati) 189 85.33 T +(v) 266.24 85.33 T +(e type \050type con) 271.09 85.33 T +(v) 334.84 85.33 T +(ersion done on client and not serv) 339.69 85.33 T +(er\051.) 474.52 85.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "4" 3 +%%Page: "3" 4 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(5. Changes from 1.3 Version) 443.45 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdev 1.5 Release Notes) 267.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(3) 552.44 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 F +(9.) 195.5 713.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4.4 (The cde) 207 713.33 P +4.4 (v/e) 243.08 713.33 P +4.4 (xamples directory no) 255.15 713.33 P +4.4 (w contains 2 additional e) 348.14 713.33 P +4.4 (xample services, one) 465.6 713.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.52 (implementing compound cde) 207 701.33 P +0.52 (v de) 324.45 701.33 P +0.52 (vices, and the other \050demoService\051 is a tri) 341.65 701.33 P +0.52 (vial service) 511.66 701.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(useful as a starting point for read/write services.) 207 689.33 T +0 0 0 1 0 0 0 K +72 631 558 638 C +0 0 0 1 0 0 0 K +72 637.29 170.57 637.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 637.29 558 637.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(5.) 160.5 642.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Changes fr) 180 642.67 T +(om 1.3 V) 245.46 642.67 T +(ersion) 297.33 642.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +-0.18 (Se) 180 616.33 P +-0.18 (v) 189.75 616.33 P +-0.18 (eral minor changes ha) 194.6 616.33 P +-0.18 (v) 281.89 616.33 P +-0.18 (e been introduced to the system in order to impro) 286.74 616.33 P +-0.18 (v) 481.88 616.33 P +-0.18 (e performance for) 486.73 616.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(e) 180 604.33 T +(xisting operations.) 184.29 604.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 195.5 586.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.59 (The) 207 586.33 P +3 F +1.59 (oper) 226.63 586.33 P +1.59 (ator ==) 244.82 586.33 P +1 F +1.59 ( and) 279.07 586.33 P +3 F +1.59 (oper) 301.68 586.33 P +1.59 (ator !=) 319.86 586.33 P +1 F +1.59 ( methods ha) 350.69 586.33 P +1.59 (v) 401.99 586.33 P +1.59 (e been added to the cde) 406.84 586.33 P +1.59 (vData class.) 508.1 586.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.05 (These methods allo) 207 574.33 P +1.05 (w the caller to perform a deep comparison of the contents of tw) 286.63 574.33 P +1.05 (o) 553 574.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 207 562.33 T +(vData objects.) 220.63 562.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 195.5 547.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.08 (A) 207 547.33 P +3 F +-0.08 (cde) 216.64 547.33 P +-0.08 (vT) 230.37 547.33 P +-0.08 (a) 239.45 547.33 P +-0.08 (gT) 244.35 547.33 P +-0.08 (ableCallbac) 253.99 547.33 P +-0.08 (k) 302.68 547.33 P +1 F +-0.08 ( class has been added to the cde) 307.12 547.33 P +-0.08 (vT) 433.25 547.33 P +-0.08 (agT) 443.56 547.33 P +-0.08 (able.h \336le. This class has) 458.31 547.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.97 (a pure virtual callback method that \050when re) 207 535.33 P +1.97 (gistered with the) 397.51 535.33 P +3 F +1.97 (cde) 472.57 535.33 P +1.97 (vData) 486.3 535.33 P +1 F +1.97 ( class\051 will) 510.74 535.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(recei) 207 523.33 T +(v) 226.18 523.33 T +(e a callback each time a ne) 231.03 523.33 T +(w tag is added to the cde) 337.96 523.33 T +(v global tag table.) 436.58 523.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 195.5 508.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.11 (The) 207 508.33 P +3 F +-0.11 (addT) 224.94 508.33 P +-0.11 (a) 244.58 508.33 P +-0.11 (gCallbac) 249.48 508.33 P +-0.11 (k) 285.95 508.33 P +1 F +-0.11 ( method has been added to the) 290.39 508.33 P +3 F +-0.11 (cde) 413.18 508.33 P +-0.11 (vData) 426.91 508.33 P +1 F +-0.11 ( class. This method is used) 451.35 508.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.3 (by the caller to install a) 207 496.33 P +3 F +0.3 (cde) 304.9 496.33 P +0.3 (vT) 318.63 496.33 P +0.3 (a) 327.71 496.33 P +0.3 (gT) 332.61 496.33 P +0.3 (ableCallbac) 342.25 496.33 P +0.3 (k) 390.94 496.33 P +1 F +0.3 ( object that will be e) 395.38 496.33 P +0.3 (x) 478.11 496.33 P +0.3 (ecuted each time a) 482.96 496.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(ne) 207 484.33 T +(w tag is added to the global tag table.) 216.19 484.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 195.5 469.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.85 (The) 207 469.33 P +3 F +2.85 (delT) 227.9 469.33 P +2.85 (a) 244.76 469.33 P +2.85 (gCallbac) 249.65 469.33 P +2.85 (k) 286.12 469.33 P +1 F +2.85 (method has been added to the) 295.91 469.33 P +3 F +2.85 (cde) 434.07 469.33 P +2.85 (vData) 447.8 469.33 P +1 F +2.85 ( class. This method) 472.24 469.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.93 (remo) 207 457.33 P +3.93 (v) 227.4 457.33 P +3.93 (es a) 232.25 457.33 P +3 F +3.93 (cde) 257.88 457.33 P +3.93 (vT) 271.61 457.33 P +3.93 (a) 280.69 457.33 P +3.93 (gT) 285.59 457.33 P +3.93 (ableCallbac) 295.23 457.33 P +3.93 (k) 343.92 457.33 P +1 F +3.93 ( object that w) 348.36 457.33 P +3.93 (as pre) 414.2 457.33 P +3.93 (viously installed using the) 441.48 457.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 207 445.33 T +(vData::addT) 220.73 445.33 T +(a) 271.47 445.33 T +(gCallbac) 276.37 445.33 T +(k) 312.84 445.33 T +1 F +( method.) 317.28 445.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 195.5 430.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.94 (The) 207 430.33 P +3 F +0.94 (r) 225.99 430.33 P +0.94 (eadT) 229.51 430.33 P +0.94 (a) 248.59 430.33 P +0.94 (gT) 253.49 430.33 P +0.94 (able) 263.13 430.33 P +1 F +0.94 ( method has been added to the) 280.35 430.33 P +3 F +0.94 ( cde) 407.06 430.33 P +0.94 (vData) 424.23 430.33 P +1 F +0.94 (class. This method allo) 452.11 430.33 P +0.94 (ws) 546.89 430.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.47 (the caller to retrie) 207 418.33 P +0.47 (v) 278.98 418.33 P +0.47 (e a list of inte) 283.83 418.33 P +0.47 (ger tags and their corresponding character strings that) 340.02 418.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(are stored in the global tag table.) 207 406.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 195.5 391.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.32 (The) 207 391.33 P +3 F +1.32 (CDEVT) 226.37 391.33 P +1.32 (A) 257.54 391.33 P +1.32 (GT) 263.3 391.33 P +1.32 (ABLE) 275.58 391.33 P +1 F +1.32 (en) 303.29 391.33 P +1.32 (vironment v) 312.33 391.33 P +1.32 (ariable is used to indicate the location of a \336le) 362 391.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.09 (based list of tags that will be automatically loaded when a cde) 207 379.33 P +0.09 (v application is started. If) 455.72 379.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.33 (the v) 207 367.33 P +0.33 (ariable is not speci\336ed the application will attempt to load the list from) 226.8 367.33 P +3 F +0.33 (/usr/local/) 516.88 367.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(lib/cde) 207 355.33 T +(vT) 234.07 355.33 T +(a) 243.15 355.33 T +(gT) 248.05 355.33 T +(able) 257.69 355.33 T +1 F +(. If this \336le does not e) 274.91 355.33 T +(xist, then the def) 361.7 355.33 T +(ault list of tags will be used.) 428.26 355.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 195.5 340.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.22 (Channel Access Service \050caService\051 modi\336ed to call the callback function immediately) 207 340.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(when a second monitor is installed on an channel that is already monitored.) 207 328.33 T +0 0 0 1 0 0 0 K +72 270 558 277 C +0 0 0 1 0 0 0 K +72 276.29 170.57 276.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 276.29 558 276.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(6.) 160.5 281.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Changes fr) 180 281.67 T +(om 1.4 V) 245.46 281.67 T +(ersion) 297.33 281.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(Major additions ha) 180 255.33 T +(v) 255.35 255.33 T +(e been made to the system to support ne) 260.2 255.33 T +(w functionality) 419.93 255.33 T +(.) 480.11 255.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 195.5 237.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.16 (The cde) 207 237.33 P +1.16 (vCollection de) 239.84 237.33 P +1.16 (vice and cde) 299.36 237.33 P +1.16 (vCollectionRequest object ha) 351.41 237.33 P +1.16 (v) 471.31 237.33 P +1.16 (e been added to the) 476.16 237.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.18 (CDEV class library) 207 225.33 P +0.18 (. These mechanisms pro) 285.02 225.33 P +0.18 (vide the capability to send a single message) 382.06 225.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(to a group of de) 207 213.33 T +(vices that may span multiple services.) 270.07 213.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 195.5 198.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.18 (Modi\336cations ha) 207 198.33 P +0.18 (v) 274.48 198.33 P +0.18 (e been made to the cde) 279.33 198.33 P +0.18 (vDe) 371.33 198.33 P +0.18 (vice, cde) 387.74 198.33 P +0.18 (vRequestObject, and cde) 423.2 198.33 P +0.18 (vService) 523.01 198.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(class to support the ne) 207 186.33 T +(w cde) 295.63 186.33 T +(vCollection hierarch) 318.98 186.33 T +(y) 400.86 186.33 T +(.) 405.21 186.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 195.5 171.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.71 (Because of binary incompatibilities between the dif) 207 171.33 P +0.71 (ferent v) 417.11 171.33 P +0.71 (ersions of the CDEV DDL) 448.49 171.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.51 (\336le. The cde) 207 159.33 P +1.51 (vSystem will no) 259.48 159.33 P +1.51 (w append the v) 327.26 159.33 P +1.51 (ersion number of the current v) 392.46 159.33 P +1.51 (ersion of) 521.22 159.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.33 (CDEV \050-1.5\051 to the name speci\336ed in th CDEVDDL en) 207 147.33 P +2.33 (vironment v) 449.73 147.33 P +2.33 (ariable before) 500.42 147.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(attempting to load the \336le.) 207 135.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 195.5 120.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.12 (Modi\336cations ha) 207 120.33 P +2.12 (v) 276.42 120.33 P +2.12 (e been made to the CDEV Generic Serv) 281.27 120.33 P +2.12 (er Engine to allo) 455.68 120.33 P +2.12 (w it to) 528.19 120.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(manage user de\336ned pack) 207 108.33 T +(et types using the same protocol de\336nition.) 310.48 108.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 195.5 93.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(A) 207 93.33 T +(CE V) 213.82 93.33 T +(ersion 4.0.32 is no) 235.21 93.33 T +(w being distrib) 308.57 93.33 T +(uted with CDEV) 368.37 93.33 T +(.) 434.3 93.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "3" 4 +%%Page: "2" 5 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(3. Installation) 54 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(2) 54 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +(cdev 1.5 Release Notes) 249.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Document Revision: 1) 451.97 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +540 72 54 72 2 L +0.5 H +2 Z +N +540 729 54 729 2 L +N +0 0 0 1 0 0 0 K +54 699 540 706 C +0 0 0 1 0 0 0 K +54 705.29 152.57 705.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 705.29 540 705.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(3.) 142.5 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Installation) 162 710.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +-0.06 (Sources are a) 162 684.33 P +-0.06 (v) 214.98 684.33 P +-0.06 (ailable in compressed tar format, and contain mak) 219.73 684.33 P +-0.06 (e\336les to b) 419.14 684.33 P +-0.06 (uild the libraries and) 457.7 684.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.17 (utilities. These ha) 162 672.33 P +-0.17 (v) 232.29 672.33 P +-0.17 (e been tested on the HP) 237.13 672.33 P +-0.17 (, SunOS, and SGI platforms to e) 329.31 672.33 P +-0.17 (x) 457.57 672.33 P +-0.17 (ecute correctly) 462.42 672.33 P +-0.17 (, and) 520.73 672.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.01 (SLA) 162 660.33 P +0.01 (C has ported this v) 180.49 660.33 P +0.01 (ersion to V) 255.39 660.33 P +0.01 (AX/VMS. Fix) 298.51 660.33 P +0.01 (es ha) 355.6 660.33 P +0.01 (v) 375.68 660.33 P +0.01 (e also been incorporated from an earlier) 380.53 660.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.96 (port to IBM/AIX \050at CERN\051. As con\336gured, cde) 162 648.33 P +0.96 (v will b) 362.63 648.33 P +0.96 (uild support for the EPICS channel) 394.92 648.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(access service.) 162 636.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.03 (The Mak) 162 618.33 P +3.03 (e\336les ha) 201.31 618.33 P +3.03 (v) 237.2 618.33 P +3.03 (e been e) 242.04 618.33 P +3.03 (xtensi) 280.72 618.33 P +3.03 (v) 304.36 618.33 P +3.03 (ely re) 309.21 618.33 P +3.03 (w) 334.48 618.33 P +3.03 (ork) 341.6 618.33 P +3.03 (ed since the 1.1 release, and should b) 354.83 618.33 P +3.03 (uild) 524.44 618.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(successfully on more platforms.) 162 606.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.06 (F) 162 588.33 P +3.06 (or further information, see the README \336le in the topmost directory) 167.41 588.33 P +3.06 (, and the) 475.98 588.33 P +3 F +3.06 (cde) 521.83 588.33 P +3.06 (v) 535.56 588.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Administr) 162 576.33 T +(ator\325) 201.3 576.33 T +(s Guide) 220.9 576.33 T +1 F +( in the /doc sub-directory) 251.73 576.33 T +(.) 351.62 576.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.83 (Support for site speci\336c control systems must be added by the implementer) 162 558.33 P +0.83 (. See the) 471.41 558.33 P +3 F +0.83 (Service) 510.57 558.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.55 (De) 162 546.33 P +1.55 (veloper\325) 173.51 546.33 P +1.55 (s Guide) 206.43 546.33 P +1 F +1.55 ( for help in getting started interf) 238.81 546.33 P +1.55 (acing cde) 375.78 546.33 P +1.55 (v to a ne) 415.12 546.33 P +1.55 (w control system. In) 453.69 546.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(addition, there are a number of e) 162 534.33 T +(xample services included with this release.) 292.09 534.33 T +0 0 0 1 0 0 0 K +54 476 540 483 C +0 0 0 1 0 0 0 K +54 482.29 152.57 482.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +163.43 482.29 540 482.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(4.) 142.5 487.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Changes fr) 162 487.67 T +(om 1.1 V) 227.46 487.67 T +(ersion) 279.33 487.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +0.55 (A number of changes ha) 162 461.33 P +0.55 (v) 261.73 461.33 P +0.55 (e been made to mak) 266.58 461.33 P +0.55 (e the source code compile correctly on a lar) 348.65 461.33 P +0.55 (ger) 527.23 461.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.05 (v) 162 449.33 P +0.05 (ariety of compilers, including V) 166.75 449.33 P +0.05 (AX C++ and g++. In addition, cde) 293.63 449.33 P +0.05 (v no) 431.76 449.33 P +0.05 (w produces more error) 449.06 449.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.78 (and w) 162 437.33 P +0.78 (arning messages through its error logging routines. The follo) 186.84 437.33 P +0.78 (wing is a list of the more) 435.87 437.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(visible feature changes:) 162 425.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(1.) 177.5 407.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(The C binding is included in the release \050pre) 189 407.33 T +(viously released as an add-on to 1.1\051.) 366.5 407.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(2.) 177.5 392.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.19 (The de) 189 392.33 P +-0.19 (vice de\336nitions \050ddl \336le\051 may no) 216.05 392.33 P +-0.19 (w be stored and loaded in a binary format, which) 345.66 392.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 (is about 20 times f) 189 380.33 P +1 (aster to load compared to the ascii format. A ne) 266.79 380.33 P +1 (w utility program,) 465.5 380.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.2 (cddl, compiles the ddl from ascii to binary) 189 368.33 P +0.2 (. At run-time, the \336le format of the ddl \336le is) 359.15 368.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(detected automatically so that either ascii or binary may be used.) 189 356.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(3.) 177.5 341.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.17 (Shared objects are no) 189 341.33 P +2.17 (w loaded from a subdirectory of the directory pointed to by) 281.08 341.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.33 (CDEVSHOBJ, where the subdirectory name is the name of the v) 189 329.33 P +0.33 (ersion of cde) 451.83 329.33 P +0.33 (v ag) 503.89 329.33 P +0.33 (ainst) 521.11 329.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.2 (which the application is running. This mak) 189 317.33 P +1.2 (es it possible to run dif) 367.49 317.33 P +1.2 (ferent applications) 464.65 317.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.22 (ag) 189 305.33 P +-0.22 (ainst dif) 198.39 305.33 P +-0.22 (ferent v) 230.42 305.33 P +-0.22 (ersions of cde) 260.87 305.33 P +-0.22 (v) 315.72 305.33 P +-0.22 (. If the subdirectory does not contain the needed object,) 320.07 305.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(it is loaded from CDEVSHOBJ as before.) 189 293.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(4.) 177.5 278.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.06 (cde) 189 278.33 P +1.06 (vFdChangedCallback added to cde) 202.63 278.33 P +1.06 (vSystem, allo) 345.27 278.33 P +1.06 (wing an application to be noti\336ed) 400.53 278.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(when \336le descriptors are opened or closed by cde) 189 266.33 T +(v services.) 385.92 266.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(5.) 177.5 251.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 189 251.33 T +(vData no) 202.63 251.33 T +(w supports a cast to char* as well as operator= o) 238.76 251.33 T +(v) 432.54 251.33 T +(erloading.) 437.39 251.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(6.) 177.5 236.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.31 (cde) 189 236.33 P +0.31 (vGroup no) 202.63 236.33 P +0.31 (w supports a deferred e) 245.74 236.33 P +0.31 (x) 340.15 236.33 P +0.31 (ecution / re-e) 345 236.33 P +0.31 (x) 398.23 236.33 P +0.31 (ecution mode: if a group is in this) 403.08 236.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.97 (mode, operations are remembered b) 189 224.33 P +1.97 (ut not e) 340.24 224.33 P +1.97 (x) 374.03 224.33 P +1.97 (ecuted. Sa) 378.88 224.33 P +1.97 (v) 421.75 224.33 P +1.97 (ed operations may later be) 426.6 224.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.22 (e) 189 212.33 P +-0.22 (x) 193.29 212.33 P +-0.22 (ecuted as a group, and re-e) 198.14 212.33 P +-0.22 (x) 304.07 212.33 P +-0.22 (ecuted without re-learning. Only asynchronous operations) 308.92 212.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(are remembered.) 189 200.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(7.) 177.5 185.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.24 (A fe) 189 185.33 P +0.24 (w b) 206.48 185.33 P +0.24 (ugs in the channel access service ha) 221.25 185.33 P +0.24 (v) 365.79 185.33 P +0.24 (e been \336x) 370.64 185.33 P +0.24 (ed. Monitoring of status without) 409.86 185.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(monitoring v) 189 173.33 T +(alue no) 240.7 173.33 T +(w w) 269.61 173.33 T +(orks correctly) 286.45 173.33 T +(.) 341.06 173.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(8.) 177.5 158.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +-0.12 (The cde) 189 158.33 P +-0.12 (v/src directory no) 220.55 158.33 P +-0.12 (w contains an e) 290.6 158.33 P +-0.12 (xtensions sub-directory) 352 158.33 P +-0.12 (. Extensions include the) 444.83 158.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.4 (tcl interf) 189 146.33 P +0.4 (ace, and the A) 223.46 146.33 P +0.4 (CE \050Adapti) 281.47 146.33 P +0.4 (v) 327.45 146.33 P +0.4 (e Communication En) 332.3 146.33 P +0.4 (vironment\051 based client/serv) 417.71 146.33 P +0.4 (er) 532.23 146.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.97 (package used for b) 189 134.33 P +1.97 (uilding ne) 269.95 134.33 P +1.97 (w cde) 311.95 134.33 P +1.97 (v serv) 337.27 134.33 P +1.97 (ers and services capable of passing entire) 363.24 134.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 189 122.33 T +(vData objects o) 202.63 122.33 T +(v) 264.69 122.33 T +(er the netw) 269.54 122.33 T +(ork.) 313.87 122.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "2" 5 +%%Page: "1" 6 +612 792 0 FMBEGINPAGE +[0 0 0 1 0 0 0] +[ 0 0 0 0 1 1 1] +[ 0 1 1 0 1 0 0] +[ 1 0 1 0 0 1 0] +[ 1 1 0 0 0 0 1] +[ 1 0 0 0 0 1 1] +[ 0 1 0 0 1 0 1] +[ 0 0 1 0 1 1 0] +[ 0 1 1 0 1 0 0] + 9 FrameSetSepColors +FrameNoSep +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 9 Q +0 X +0 0 0 1 0 0 0 K +(1. Overview) 510.49 739 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cdev 1.5 Release Notes) 267.23 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 10 Q +(1) 552.44 56.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +72 72 558 72 2 L +0.5 H +2 Z +N +72 729 558 729 2 L +N +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +4 24 Q +(cdev 1.5 Release Notes) 180 704 T +0 0 0 1 0 0 0 K +72 635 558 642 C +0 0 0 1 0 0 0 K +72 641.29 170.57 641.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 641.29 558 641.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(1.) 160.5 646.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Ov) 180 646.67 T +(er) 197.75 646.67 T +(view) 210.04 646.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +3.77 (The cde) 180 620.33 P +3.77 (v \050control de) 215.45 620.33 P +3.77 (vice\051 C++ library is designed to pro) 273.83 620.33 P +3.77 (vide a standard application) 439.22 620.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.25 (programming interf) 180 608.33 P +1.25 (ace \050API\051 to one or more underlying packages, typically control system) 259.75 608.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.99 (interf) 180 596.33 P +1.99 (aces. The implementation is in 2 layers: the uppermost layer is used directly by an) 201.56 596.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.12 (application, and pro) 180 584.33 P +1.12 (vides an abstraction of the underlying package as well as man) 261.79 584.33 P +1.12 (y general) 519.96 584.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2.22 (purpose features. The second layer \050service layer\051 pro) 180 572.33 P +2.22 (vides the interf) 410.34 572.33 P +2.22 (ace to one or more) 474.68 572.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(underlying packages, and is implemented as loadable libraries.) 180 560.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.53 (cde) 180 542.33 P +0.53 (v w) 193.63 542.33 P +0.53 (as initially de) 208.78 542.33 P +0.53 (v) 263.48 542.33 P +0.53 (eloped at CEB) 268.33 542.33 P +0.53 (AF with input from the EPICS collaboration, and is no) 327.37 542.33 P +0.53 (w) 550.78 542.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.3 (a) 180 530.33 P +0.3 (v) 184.24 530.33 P +0.3 (ailable for an) 188.99 530.33 P +0.3 (yone to tak) 242.2 530.33 P +0.3 (e and use or impro) 287.15 530.33 P +0.3 (v) 362.64 530.33 P +0.3 (e. W) 367.49 530.33 P +0.3 (e welcome all comments, suggestions, b) 385.87 530.33 P +0.3 (ug) 548 530.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0.26 (reports, and \050especially\051 b) 180 518.33 P +0.26 (ug \336x) 284.45 518.33 P +0.26 (es, including \336x) 307.62 518.33 P +0.26 (es for ne) 372.17 518.33 P +0.26 (w platforms. There are man) 406.88 518.33 P +0.26 (y planned) 518.58 518.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1.08 (enhancements, and w) 180 506.33 P +1.08 (ould welcome v) 267.88 506.33 P +1.08 (olunteers to contrib) 333.73 506.33 P +1.08 (ute to this project. See belo) 413.46 506.33 P +1.08 (w for a) 527.51 506.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(summary of ne) 180 494.33 T +(w and planned features.) 239.74 494.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Y) 180 476.33 T +(ou may join a cde) 186.12 476.33 T +(v discussion list by sending the message) 256.97 476.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +( subscribe cde) 180 458.33 T +(v) 253.9 458.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.07 (to the address mailserv@cebaf.go) 180 440.33 P +3.07 (v) 324.36 440.33 P +3.07 (. \050Send the message HELP to the same address for) 328.71 440.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(information on ho) 180 428.33 T +(w to use the mail serv) 251.97 428.33 T +(er) 339.31 428.33 T +(.\051 The cde) 346.53 428.33 T +(v web page is) 386.54 428.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(http://www) 200 410.33 T +(.cebaf.go) 244.91 410.33 T +(v/cde) 281.41 410.33 T +(v/) 302.82 410.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(cde) 180 392.33 T +(v 1.4 is the third publically released v) 193.63 392.33 T +(ersion of cde) 344.02 392.33 T +(v) 395.42 392.33 T +(.) 399.77 392.33 T +0 0 0 1 0 0 0 K +72 334 558 341 C +0 0 0 1 0 0 0 K +72 340.29 170.57 340.29 2 L +0.5 H +2 Z +0 X +0 0 0 1 0 0 0 K +N +181.43 340.29 558 340.29 2 L +N +0 0 0 1 0 0 0 K +0 0 612 792 C +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +2 14 Q +0 X +0 0 0 1 0 0 0 K +(2.) 160.5 345.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(Documentation) 180 345.67 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +1 10 Q +(The documentation for cde) 180 319.33 T +(v includes the follo) 287.78 319.33 T +(wing:) 364.47 319.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 301.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +0.29 (Intr) 207 301.33 P +0.29 (oduction to cde) 221.55 301.33 P +0.29 (v) 283.65 301.33 P +1 F +0.29 ( -- this is an update of) 288.09 301.33 P +3 F +0.29 (The cde) 379.87 301.33 P +0.29 (v User\325) 411.39 301.33 P +0.29 (s Guide) 441 301.33 P +1 F +0.29 (, complete with more) 472.12 301.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(e) 207 289.33 T +(xamples. It co) 211.29 289.33 T +(v) 267.52 289.33 T +(ers all the basics, and is the best place to start.) 272.37 289.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 275.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +0.72 (A cde) 207 275.33 P +0.72 (v T) 230.06 275.33 P +0.72 (utorial) 242.73 275.33 P +1 F +0.72 ( -- this document goes through ho) 269.96 275.33 P +0.72 (w to use each of the classes in cde) 409.02 275.33 P +0.72 (v) 551.15 275.33 P +0.72 (,) 555.5 275.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(including all public methods; e) 207 263.33 T +(xtensi) 330.74 263.33 T +(v) 354.38 263.33 T +(e e) 359.23 263.33 T +(xamples are gi) 370.46 263.33 T +(v) 428.53 263.33 T +(en.) 433.38 263.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 249.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 207 249.33 T +(v Refer) 220.73 249.33 T +(ence Manual) 248.96 249.33 T +1 F +( -- documents each class in cde) 300.89 249.33 T +(v in alphabetical order) 425.05 249.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 235.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +0.63 (cde) 207 235.33 P +0.63 (v Administr) 220.73 235.33 P +0.63 (ator\325) 267.6 235.33 P +0.63 (s Guide) 287.2 235.33 P +1 F +0.63 ( -- this is for system administrators, and those intending to) 318.66 235.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(port cde) 207 223.33 T +(v to ne) 239.24 223.33 T +(w platforms) 266.21 223.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 209.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +0.92 (Service De) 207 209.33 P +0.92 (veloper\325) 251.36 209.33 P +0.92 (s Guide) 284.28 209.33 P +1 F +0.92 (-- this documents a couple of additional classes needed to) 319.46 209.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(create a custom service, and goes through a lengthly e) 207 197.33 T +(xample demoService.) 422.91 197.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(\245) 198 183.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3.12 (cde) 207 183.33 P +3.12 (vCollection De) 220.73 183.33 P +3.12 (vice Requir) 283.97 183.33 P +3.12 (ements and Design --) 332.55 183.33 P +1 F +3.12 (This document illustrates the) 432.8 183.33 P +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(structure and usage of the cde) 207 171.33 T +(vCollection de) 325.88 171.33 T +(vice.) 384.24 171.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(\245) 198 157.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +3 F +(cde) 207 157.33 T +(v C Binding) 220.73 157.33 T +1 F +( -- documents the C wrapper routines for cde) 268.51 157.33 T +(v) 447.66 157.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +(This documentation is also a) 180 139.33 T +(v) 294.24 139.33 T +(ailable on the web site.) 298.99 139.33 T +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +0 0 0 1 0 0 0 K +FMENDPAGE +%%EndPage: "1" 6 +%%Trailer +%%BoundingBox: 0 0 612 792 +%%PageOrder: Descend +%%Pages: 6 +%%DocumentFonts: Helvetica +%%+ Times-Roman +%%+ Times-Bold +%%+ Times-Italic +%%+ Times-BoldItalic +%%EOF diff --git a/doc/releaseNotes1_3.doc b/doc/releaseNotes1_3.doc new file mode 100755 index 0000000..bf84d0c Binary files /dev/null and b/doc/releaseNotes1_3.doc differ diff --git a/doc/releaseNotes1_4.doc b/doc/releaseNotes1_4.doc new file mode 100755 index 0000000..4353ea4 Binary files /dev/null and b/doc/releaseNotes1_4.doc differ diff --git a/doc/releaseNotes1_5.doc b/doc/releaseNotes1_5.doc new file mode 100755 index 0000000..2fa0d37 Binary files /dev/null and b/doc/releaseNotes1_5.doc differ diff --git a/doc/releaseNotes1_6.doc b/doc/releaseNotes1_6.doc new file mode 100755 index 0000000..6017337 Binary files /dev/null and b/doc/releaseNotes1_6.doc differ diff --git a/etc/rc.d/init.d/cdevGateway b/etc/rc.d/init.d/cdevGateway new file mode 100755 index 0000000..34d44a7 --- /dev/null +++ b/etc/rc.d/init.d/cdevGateway @@ -0,0 +1,78 @@ +#!/bin/sh +# +# cdevGateway This shell script takes care of starting and stopping +# cdevGateway. +# +# chkconfig: 2345 60 60 +# description: cdevGateway is the daemon required for JAVA/CDEV to work properly. + +# Source function library. +. /etc/rc.d/init.d/functions + +# Source networking configuration. +. /etc/sysconfig/network + +# Check that networking is up. +[ ${NETWORKING} = "no" ] && exit 0 + +[ -f /usr/local/i386-glibc22-linux/cdev-1.7.2/lib/cdev-setup.sh ] || exit 0 +. /usr/local/i386-glibc22-linux/cdev-1.7.2/lib/cdev-setup.sh + +[ -f $CDEV/sbin/cdevGateway.sh ] || exit 0 + +PATH=$CDEV/bin/$SYSNAME:$CDEV/sbin:/usr/bin:/usr/sbin:/bin:/sbin + +# See how we were called. +case "$1" in + start) + + # make sure log file exists and has the right ownership + touch /var/log/cdevGateway.log + chown nobody.nobody /var/log/cdevGateway.log + # Start daemons. + + echo -n "Starting cdevGateway: " + if [ ! -f /var/run/rsvcServer.pid ] ;then + echo -n "rsvcServer " + Pidgen="`su nobody -l -c $CDEV/sbin/rsvcServer.sh`" + echo -n $Pidgen >/var/run/rsvcServer.pid + logger -p local5.info -t "rsvcServer[$Pidgen]" "CDEV generic server started." + sleep 2 + else + echo; status rsvcServer + fi + if [ ! -f /var/run/cdevGateway.pid ] ;then + echo -n "cdevGateway" + Pidgat="`su nobody -l -c $CDEV/sbin/cdevGateway.sh`" + echo -n $Pidgat >/var/run/cdevGateway.pid + logger -p local5.info -t "cdevGateway[$Pidgat]" "CDEV gateway server started." + else + echo; status cdevGateway + fi + touch /var/lock/subsys/cdevGateway + sleep 1 + pidof cdevGateway >/dev/null 2>&1 && success "cdevGateway startup" || failure "cdevGateway startup" + echo + ;; + stop) + # Stop daemons. + echo -n "Shutting down cdevGateway: " + killproc cdevGateway + killproc rsvcServer + echo + rm -f /var/lock/subsys/cdevGateway + ;; + status) + status rsvcServer + status cdevGateway + ;; + restart) + $0 stop + $0 start + ;; + *) + echo "Usage: cdevGateway {start|stop|restart|status}" + exit 1 +esac + +exit 0 diff --git a/extensions/CLIPService/.shobj/Linux/CLIPRequestObject.o b/extensions/CLIPService/.shobj/Linux/CLIPRequestObject.o new file mode 100644 index 0000000..7f0d4a8 Binary files /dev/null and b/extensions/CLIPService/.shobj/Linux/CLIPRequestObject.o differ diff --git a/extensions/CLIPService/.shobj/Linux/CLIPService.o b/extensions/CLIPService/.shobj/Linux/CLIPService.o new file mode 100644 index 0000000..e7521c5 Binary files /dev/null and b/extensions/CLIPService/.shobj/Linux/CLIPService.o differ diff --git a/extensions/CLIPService/CLIP.ddl b/extensions/CLIPService/CLIP.ddl new file mode 100644 index 0000000..b1faeaa --- /dev/null +++ b/extensions/CLIPService/CLIP.ddl @@ -0,0 +1,373 @@ +service CLIP { + tags {server, host, port} + } + + +class ca { + verbs {get, set, monitorOn, monitorOff} + attributes { + VAL CLIP {server=Gateway1, host=devsrv.cebaf.gov, port=9199}; + XPOS CLIP {server=Gateway1, host=devsrv.cebaf.gov, port=9199}; + YPOS CLIP {server=Gateway1, host=devsrv.cebaf.gov, port=9199}; + ServerInfo CLIP {server=Gateway1, host=devsrv.cebaf.gov, port=9199}; + ClientInfo CLIP {server=Gateway1, host=devsrv.cebaf.gov, port=9199}; + } + } + +class ModelClass + { + verbs {get, set, monitorOn, monitorOff} + attributes { + elements CLIP {server=GOLD, host=mdlsrv.cebaf.gov, port=9000}; + sections CLIP {server=GOLD, host=mdlsrv.cebaf.gov, port=9000}; + ServerInfo CLIP {server=GOLD, host=mdlsrv.cebaf.gov, port=9000}; + ClientInfo CLIP {server=GOLD, host=mdlsrv.cebaf.gov, port=9000}; + } + } + +ModelClass : model ; + +ca : IPM1R01 +IPM1R02 +IPM1R03 +IPM1R04 +IPM1R06 +IPM1R08 +IPM1R09 +IPM1R10 +IPM1S01 +IPM1S02 +IPM1S03 +IPM1S05 +IPM1S07 +IPM1S08 +IPM1S09 +IPM1S10 +IPM2R01 +IPM2R02 +IPM2R03 +IPM2R04 +IPM2R06 +IPM2R08 +IPM2R09 +IPM2R10 +IPM2S01 +IPM2S02 +IPM2S03 +IPM2S07 +IPM2S08 +IPM2S09 +IPM2T00A +IPM2T00B +IPM2T01 +IPM2T03 +IPM2T06 +IPM2T07 +IPM2T08 +IPM2T09 +IPM3A02 +IPM3A03 +IPM3A05 +IPM3A07 +IPM3A08 +IPM3A09 +IPM3A10 +IPM3A11 +IPM3A13 +IPM3A15 +IPM3A16 +IPM3A17 +IPM3A18 +IPM3A19 +IPM3A21 +IPM3A23 +IPM3A24 +IPM3A25 +IPM3A26 +IPM3A27 +IPM3A29 +IPM3A31 +IPM3A32 +IPM3E01 +IPM3E03 +IPM3R01 +IPM3R02 +IPM3R03 +IPM3R04 +IPM3R06 +IPM3R08 +IPM3R09 +IPM3R10 +IPM3S01 +IPM3S02 +IPM3S03 +IPM3S05 +IPM3S07 +IPM3S08 +IPM3S09 +IPM3S10 +IPM4A02 +IPM4A03 +IPM4A05 +IPM4A07 +IPM4A08 +IPM4A09 +IPM4A10 +IPM4A11 +IPM4A13 +IPM4A15 +IPM4A16 +IPM4A17 +IPM4A18 +IPM4A19 +IPM4A21 +IPM4A23 +IPM4A24 +IPM4A25 +IPM4A26 +IPM4A27 +IPM4A29 +IPM4A31 +IPM4A32 +IPM4E03 +IPM4R01 +IPM4R02 +IPM4R03 +IPM4R04 +IPM4R06 +IPM4R08 +IPM4R09 +IPM4R10 +IPM4S01 +IPM4S02 +IPM4S03 +IPM4S07 +IPM4S09 +IPM4T00A +IPM4T00B +IPM4T01 +IPM4T03 +IPM4T06 +IPM4T07 +IPM4T08 +IPM4T09 +IPM5A02 +IPM5A03 +IPM5A05 +IPM5A07 +IPM5A08 +IPM5A09 +IPM5A10 +IPM5A11 +IPM5A13 +IPM5A15 +IPM5A16 +IPM5A17 +IPM5A18 +IPM5A19 +IPM5A21 +IPM5A23 +IPM5A24 +IPM5A25 +IPM5A26 +IPM5A27 +IPM5A29 +IPM5A31 +IPM5A32 +IPM5E01 +IPM5E03 +IPM5R01 +IPM5R02 +IPM5R03 +IPM5R04 +IPM5R06 +IPM5R08 +IPM5R09 +IPM5R10 +IPM5S01 +IPM5S02 +IPM5S03 +IPM5S05 +IPM5S07 +IPM5S08 +IPM5S09 +IPM5S10 +IPM6A02 +IPM6A03 +IPM6A05 +IPM6A07 +IPM6A08 +IPM6A09 +IPM6A10 +IPM6A11 +IPM6A13 +IPM6A15 +IPM6A16 +IPM6A17 +IPM6A18 +IPM6A19 +IPM6A21 +IPM6A23 +IPM6A24 +IPM6A25 +IPM6A26 +IPM6A27 +IPM6A29 +IPM6A31 +IPM6A32 +IPM6E03 +IPM6R01 +IPM6R02 +IPM6R03 +IPM6R04 +IPM6R06 +IPM6R08 +IPM6R09 +IPM6R10 +IPM6S01 +IPM6S02 +IPM6S03 +IPM6S07 +IPM6S09 +IPM6T00A +IPM6T00B +IPM6T01 +IPM6T03 +IPM6T06 +IPM6T07 +IPM6T08 +IPM6T09 +IPM7A02 +IPM7A03 +IPM7A05 +IPM7A07 +IPM7A08 +IPM7A09 +IPM7A10 +IPM7A11 +IPM7A13 +IPM7A15 +IPM7A16 +IPM7A17 +IPM7A18 +IPM7A19 +IPM7A21 +IPM7A23 +IPM7A24 +IPM7A25 +IPM7A26 +IPM7A27 +IPM7A29 +IPM7A31 +IPM7A32 +IPM7E01 +IPM7E03 +IPM7R01 +IPM7R02 +IPM7R03 +IPM7R04 +IPM7R06 +IPM7R08 +IPM7R09 +IPM7R10 +IPM7S01 +IPM7S02 +IPM7S03 +IPM7S05 +IPM7S07 +IPM7S08 +IPM7S09 +IPM7S10 +IPM8A02 +IPM8A03 +IPM8A05 +IPM8A07 +IPM8A08 +IPM8A09 +IPM8A10 +IPM8A11 +IPM8A13 +IPM8A15 +IPM8A16 +IPM8A17 +IPM8A18 +IPM8A19 +IPM8A21 +IPM8A23 +IPM8A24 +IPM8A25 +IPM8A26 +IPM8A27 +IPM8A29 +IPM8A31 +IPM8A32 +IPM8E03 +IPM8R01 +IPM8R02 +IPM8R03 +IPM8R04 +IPM8R06 +IPM8R08 +IPM8R09 +IPM8R10 +IPM8S01 +IPM8S02 +IPM8S03 +IPM8S07 +IPM8S08 +IPM8T00A +IPM8T00B +IPM8T01 +IPM8T03 +IPM8T06 +IPM8T07 +IPM8T08 +IPM8T09 +IPM9A02 +IPM9A03 +IPM9A05 +IPM9A07 +IPM9A08 +IPM9A09 +IPM9A10 +IPM9A11 +IPM9A13 +IPM9A15 +IPM9A16 +IPM9A17 +IPM9A18 +IPM9A19 +IPM9A21 +IPM9A23 +IPM9A24 +IPM9A25 +IPM9A26 +IPM9A27 +IPM9A29 +IPM9A31 +IPM9A32 +IPM9E01 +IPM9E03 +IPM9R01 +IPM9R02 +IPM9R03 +IPM9R04 +IPM9R05 +IPM9R07 +IPM9R08 +IPM9S01 +IPM9S02 +IPM9S04 +IPM9S05 +IPM9S06 +IPM9S07 +IPM9S08 +IPMAS00 +IPMAT02 +IPMAT07 +IPMAT09 +IPMNS01 +IPMNS04 +IPMNS05 +IPMNS06 +; diff --git a/extensions/CLIPService/CLIPRequestObject.cc b/extensions/CLIPService/CLIPRequestObject.cc new file mode 100644 index 0000000..1b351bc --- /dev/null +++ b/extensions/CLIPService/CLIPRequestObject.cc @@ -0,0 +1,47 @@ +#include +#include +#include +#include + +CLIPRequestObject::CLIPRequestObject ( char * device, char * message, cdevSystem & system) + : cdevClientRequestObject(device, message, system) + { + cdevData output; + + *host = 0; + port = 0; + + sprintf (host, "resolveServiceData %s %s", device, message); + if((system.nameServer()).send(host, NULL, &output)==CDEV_SUCCESS) + { + *host = 0; + output.get ("host", host, 256); + output.get ("port", &port); + } + else *host = 0; + } + +int CLIPRequestObject::getServerHandler ( ServerHandler ** Handler ) + { + CLIPService * svc = (CLIPService *)service_; + int result = CDEV_SUCCESS; + + *Handler = NULL; + + if (*server==0 && *DDL_server!=0) strcpy(server, DDL_server); + if (*server!=0 && handler==NULL) + { + if((*Handler = svc->connect(server, + (*host)?host:(char *)NULL, + (*host)?port:0))==NULL) result = CDEV_ERROR; + else + { + handler = *Handler; + handler->registerServerCallback(this); + } + } + else *Handler = handler; + + return result; + } + diff --git a/extensions/CLIPService/CLIPRequestObject.h b/extensions/CLIPService/CLIPRequestObject.h new file mode 100644 index 0000000..b93fa9d --- /dev/null +++ b/extensions/CLIPService/CLIPRequestObject.h @@ -0,0 +1,14 @@ +#include + +class CLIPRequestObject : public cdevClientRequestObject +{ +protected: + char host [256]; + unsigned short port; + +public: + CLIPRequestObject ( char *device, char * message, + cdevSystem & system = cdevSystem::defaultSystem()); + + virtual int getServerHandler ( ServerHandler ** Handler ); +}; diff --git a/extensions/CLIPService/CLIPService.cc b/extensions/CLIPService/CLIPService.cc new file mode 100644 index 0000000..75ddce7 --- /dev/null +++ b/extensions/CLIPService/CLIPService.cc @@ -0,0 +1,247 @@ +#include +#include +#include + +// ***************************************************************************** +// * newCLIPService: +// * This function will be called by the cdevSystem object to create an +// * initial instance of the CLIPService. +// ***************************************************************************** +extern "C" cdevService * newCLIPService (char * name, cdevSystem * system) + { + return new CLIPService(name, *system); + } + +void NULLError (int, char *, cdevRequestObject *) + { + } + +// ***************************************************************************** +// * CLIPService::CLIPService : +// * This is the constructor for the CLIPService. It initializes the +// * underlying CLIPService by specifying that it is in the domain of +// * VIRTUAL. +// ***************************************************************************** +CLIPService::CLIPService ( char * name, cdevSystem & system) + : cdevClientService("CLIP", name, system) + { + system.reportError(CDEV_SEVERITY_INFO, "CLIPService", NULL, + "Constructing a new CLIPService"); + + } + +// ***************************************************************************** +// * CLIPService::getRequestObject : +// * This is the interface that cdev objects will use to obtain a +// * CLIPRequestObject object. The CLIPRequestObject +// * represents a combined device and message pair that is associated +// * with the CLIPService. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int CLIPService::getRequestObject ( char * device, char * message, cdevRequestObject * &req) + { + req = new CLIPRequestObject (device, message, system_); + return (req ? CDEV_SUCCESS : CDEV_ERROR); + } + + +// ***************************************************************************** +// * CLIPService::connect : +// * This mechanism will establish a new connection with a server and will +// * will return a pointer to the ServerHandler. If the host and port are +// * specified in the arguments, then the method will attempt to connect +// * using those values without going through the CDEV Name Server. +// * +// * Note: This method will insert the ServerHandler into the connections +// * object and will install it in the Reactor. +// ***************************************************************************** +ServerHandler * CLIPService::connect ( char * server, char * host, short port ) + { + ServerHandler * handler = NULL; + + // ********************************************************************* + // * First attempt to locate the handler from the existing connections. + // ********************************************************************* + if(server && *server && (handler = connections.find(server))==NULL) + { + int errCode = CDEV_SUCCESS; + char serverHost[255]; + short serverPort; + int serverStatus; + int hostMatchesNS; + + // ************************************************************* + // * Initialize these values to reflect a server that is not + // * defined within the name server. + // ************************************************************* + *serverHost = 0; + serverPort = 0; + serverStatus = 2; + hostMatchesNS = 0; + + // ************************************************************* + // * Raise the error threshold to reduce noise while the service + // * tries to resolve the location of the server. + // ************************************************************* + system_.setThreshold(100); + + // ************************************************************* + // * In this implementation we will always attempt to resolve + // * the location of the server using the name server first, to + // * determine if monitoring can be installed later... + // ************************************************************* + cdevData input; + cdevData output; + cdevRequestObject & rnsReq = + cdevRequestObject::attachRef("NameServer", "get"); + + // ***************************************************** + // * Insert domain and name in the input request object + // * to be sent to the CDEV Name Server. + // ***************************************************** + input.insert("name", server); + input.insert("domain", domain); + + // ***************************************************** + // * Query the Name Server to obtain the hostname and + // * port of the specified domain and server. + // ***************************************************** + if(rnsReq.send(input, output)==CDEV_SUCCESS) + { + output.get("host", serverHost, 255); + output.get("port", &serverPort); + output.get("status", &serverStatus); + } + + // ************************************************************* + // * Restore the error threshold to a reasonable level. + // ************************************************************* + system_.setThreshold(CDEV_SEVERITY_ERROR); + + // ************************************************************* + // * If the host and port have been specified, then use them + // * rather than going through the CDEV Name Server. + // ************************************************************* + if(host!=NULL && *host && port>0) + { + if(strcmp(serverHost, host) && serverPort==port) + hostMatchesNS = 1; + + strcpy(serverHost, host); + serverPort = port; + } + else { + if(*serverHost == 0 || serverPort<=0 || serverStatus!=0) + { + errCode = CDEV_ERROR; + + // ********************************************* + // * If the hostname could not be found, report + // * the error and set the return value to + // * CDEV_ERROR. + // ********************************************* + outputError(CDEV_SEVERITY_ERROR, + "CLIPService::connect", + "Cannot find host for server \"%s\" in domain \"%s\"", + server, domain); + } + else hostMatchesNS = 1; + } + + // ************************************************************* + // * If the hostname was discovered, then the errCode should be + // * CDEV_SUCCESS. Attempt to connect to the server using the + // * cdevReactor mechanisms. + // ************************************************************* + if(errCode==CDEV_SUCCESS) + { + cdevInetAddr addr; + + addr.set (serverPort, serverHost); + + handler = new ServerHandler(server, this); + + if(handler->open(addr)!=0) + { + outputError(CDEV_SEVERITY_ERROR, + "CLIPService::connect", + "Failed to connect to %s on port %i", + serverHost, + serverPort); + delete handler; + handler = NULL; + } + else { + outputError(CDEV_SEVERITY_INFO, + "CLIPService::connect", + "Connected to %s on port %i", + serverHost, + serverPort); + connections.insert(handler); + + // ********************************************* + // * This calls the registerFd method of the + // * service which will cause the FD Changed + // * callbacks to be triggered. + // ********************************************* + registerFd(handler->getHandle(), 1); + + // ********************************************* + // * Install a Name Server monitor to maintain + // * the status of the connection. + // * Note: If a monitor has already been + // * installed using this informations, then the + // * CDEV Name Server service should not create + // * a second monitor. + // * + // * Note: I am using the FifoQueue associated + // * with the specific server in order to + // * differentiate between the various servers. + // ********************************************* + if(hostMatchesNS) + { + cdevData monData; + cdevCallback monCb(nameServerCallback, (void *)getCallbackArg(server)); + cdevRequestObject & monReq = cdevRequestObject::attachRef("NameServer", "monitorOn"); + + monData.insert("name", server); + monData.insert("domain", domain); + monReq.sendCallback(monData, monCb); + } + + // ********************************************* + // * Here is where a "set ClientInfo" message + // * will be sent to the server to provide + // * descriptive information about the client. + // ********************************************* + cdevData tagMap; + int * tags; + char ** ctags; + int ntags; + char * binary = NULL; + size_t binaryLen = 0; + + cdevData::readTagTable(tags, ctags, ntags); + tagMap.insert(1, tags, ntags); + tagMap.insert(2, ctags, ntags); + + delete tags; + delete ctags; + handler->setTagChangeFlag(0); + + cdevMessageBinary packet(handler->getClientID(), + 0, 0, 0, 0, CDEV_SERVER_OP, 0, 0, + NULL, "set ClientInfo", + &clientInfo.getClientData(), + NULL, &tagMap); + + packet.streamOut(&binary, &binaryLen); + packet.detachData(); + + ServerInterface::enqueue(handler, binary, binaryLen); + } + } + } + return handler; + } diff --git a/extensions/CLIPService/CLIPService.h b/extensions/CLIPService/CLIPService.h new file mode 100644 index 0000000..7ad109c --- /dev/null +++ b/extensions/CLIPService/CLIPService.h @@ -0,0 +1,24 @@ +#include + +// ***************************************************************************** +// * newCLIPService : +// * This function will be called by the cdevSystem object to create an +// * initial instance of the CLIPService. +// ***************************************************************************** +extern "C" cdevService * newCLIPService ( char * name, cdevSystem * system ); + +// ***************************************************************************** +// * class CLIPService : +// * This class simply inherits from the cdevClientService and must define +// * only a constructor and destructor. +// ***************************************************************************** +class CLIPService : public cdevClientService +{ +public: + CLIPService ( char * name, cdevSystem & system = cdevSystem::defaultSystem()); + virtual ServerHandler * connect ( char * server, char * host = NULL, short port = 0 ); + virtual int getRequestObject ( char * device, char * message, cdevRequestObject * &req); + +protected: + virtual ~CLIPService ( void ) {}; +}; diff --git a/extensions/CLIPService/JAVA.ddl b/extensions/CLIPService/JAVA.ddl new file mode 100644 index 0000000..b7c44de --- /dev/null +++ b/extensions/CLIPService/JAVA.ddl @@ -0,0 +1,16 @@ +service CLIP { + tags {server, host, port} + } + + +class JAVAServer { + verbs {get, set, monitorOn, monitorOff} + attributes { + Thing1 CLIP {server=JServer1, host=localhost, port=9900}; + Thing2 CLIP {server=JServer1, host=localhost, port=9900}; + } + } + +JAVAServer : + JServer1 + ; diff --git a/extensions/CLIPService/Makefile b/extensions/CLIPService/Makefile new file mode 100644 index 0000000..f39dd5a --- /dev/null +++ b/extensions/CLIPService/Makefile @@ -0,0 +1,30 @@ +ARCH = OS +SHOBJ = YES + +include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.$(ARCH) + +APPNAME = "CDEV CLIP Client/Service" +CXXINCLUDES = -I./ + +# ****************************************************************************** +# * The BINARIES definition names all of the binary files that should be deleted +# * whenever "make clean" is executed. +# ****************************************************************************** +BINARIES = $(BASELIB)/libCLIPService.a \ + $(BASELIB)/CLIPService.so + +ifeq ($(SHOBJ), YES) + LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + TARGETS = $(BASELIB)/CLIPService.so +else + LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + TARGETS = $(BASELIB)/libCLIPService.a +endif + +targets : $(TARGETS) + +$(BASELIB)/CLIPService.so : $(OBJDIR)/CLIPService.o $(OBJDIR)/CLIPRequestObject.o + $(LINK.so) -o $@ $^ -L$(CDEVLIB) -lcdevGenericServer $(NETLIBS) + @mkdir -p $(CDEVSHOBJ)/$(CDEVVERSION) + @cp $@ $(CDEVSHOBJ)/$(CDEVVERSION)/$(@F) + diff --git a/extensions/CLIPService/errors.txt b/extensions/CLIPService/errors.txt new file mode 100644 index 0000000..9a4d8c3 --- /dev/null +++ b/extensions/CLIPService/errors.txt @@ -0,0 +1,74 @@ + => Building [Linux] in CDEV CLIP Client/Service + => g++ -c CLIPService.cc -o CLIPService.o +target is .shobj/Linux/CLIPService.o and CLIPService.cc +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/fifo.h: In function `static class QueueBase::node * QueueBase::newNode()': +In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerHandler.h:17, + from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h:5, + from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:7, + from CLIPService.h:1, + from CLIPService.cc:1: +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/fifo.h:76: warning: ANSI C++ forbids implicit conversion from `void *' in assignment +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/StringHash.h: In method `char * StringHashIterator::key()': +In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h:7, + from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:7, + from CLIPService.h:1, + from CLIPService.cc:1: +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/StringHash.h:227: warning: ANSI C++ forbids implicit conversion from `void *' in return +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h: In method `class ServerHandler * ServerConnectionList::operator [](int)': +In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:7, + from CLIPService.h:1, + from CLIPService.cc:1: +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h:30: warning: ANSI C++ forbids implicit conversion from `void *' in return +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevContextMap.h: In method `class cdevData * cdevContextMap::find(int)': +In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:9, + from CLIPService.h:1, + from CLIPService.cc:1: +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevContextMap.h:28: warning: ANSI C++ forbids implicit conversion from `void *' in return +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h: In method `class ServerHandler * CLIPService::connect(char *, char * = 0, short int = 0)': +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:99: method `class NSCallbackArg * cdevClientService::getCallbackArg(char *)' is private +CLIPService.cc:205: within this context +CLIPService.cc:205: in base initialization for class `cdevCallback' +compile done\n + => g++ -c CLIPRequestObject.cc -o CLIPRequestObject.o +target is .shobj/Linux/CLIPRequestObject.o and CLIPRequestObject.cc +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/fifo.h: In function `static class QueueBase::node * QueueBase::newNode()': +In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerHandler.h:17, + from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h:5, + from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:7, + from CLIPService.h:1, + from CLIPRequestObject.cc:2: +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/fifo.h:76: warning: ANSI C++ forbids implicit conversion from `void *' in assignment +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/StringHash.h: In method `char * StringHashIterator::key()': +In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h:7, + from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:7, + from CLIPService.h:1, + from CLIPRequestObject.cc:2: +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/StringHash.h:227: warning: ANSI C++ forbids implicit conversion from `void *' in return +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h: In method `class ServerHandler * ServerConnectionList::operator [](int)': +In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:7, + from CLIPService.h:1, + from CLIPRequestObject.cc:2: +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/ServerInterface.h:30: warning: ANSI C++ forbids implicit conversion from `void *' in return +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevContextMap.h: In method `class cdevData * cdevContextMap::find(int)': +In file included from /home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevClientService.h:9, + from CLIPService.h:1, + from CLIPRequestObject.cc:2: +/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/include/cdevContextMap.h:28: warning: ANSI C++ forbids implicit conversion from `void *' in return +CLIPRequestObject.cc: In method `int CLIPRequestObject::getServerHandler(class ServerHandler **)': +CLIPRequestObject.cc:30: member `server' is private +CLIPRequestObject.cc:30: member `DDL_server' is private +CLIPRequestObject.cc:30: member `server' is private +CLIPRequestObject.cc:30: member `DDL_server' is private +CLIPRequestObject.cc:31: member `server' is private +CLIPRequestObject.cc:31: member `handler' is private +CLIPRequestObject.cc:33: member `server' is private +CLIPRequestObject.cc:38: member `handler' is private +CLIPRequestObject.cc:39: member `handler' is private +CLIPRequestObject.cc:42: member `handler' is private +compile done\n +start so build... +=> Building shared object CLIPService.so +/bin/sh: @@echo: command not found +gcc: .shobj/Linux/CLIPService.o: No such file or directory +gcc: .shobj/Linux/CLIPRequestObject.o: No such file or directory +make: *** [/home/pss060/sls/watson/1.7/extensions/cdevGenericServer/lib/Linux/CLIPService.so] Error 1 diff --git a/extensions/ScriptService/doc/cdevScriptService.book b/extensions/ScriptService/doc/cdevScriptService.book new file mode 100755 index 0000000..a3c1344 Binary files /dev/null and b/extensions/ScriptService/doc/cdevScriptService.book differ diff --git a/extensions/ScriptService/doc/cdevScriptService.doc b/extensions/ScriptService/doc/cdevScriptService.doc new file mode 100755 index 0000000..91a0174 Binary files /dev/null and b/extensions/ScriptService/doc/cdevScriptService.doc differ diff --git a/extensions/ScriptService/doc/cdevScriptServiceLOF.doc b/extensions/ScriptService/doc/cdevScriptServiceLOF.doc new file mode 100755 index 0000000..f03ac58 Binary files /dev/null and b/extensions/ScriptService/doc/cdevScriptServiceLOF.doc differ diff --git a/extensions/ScriptService/doc/cdevScriptServiceTITLE.doc b/extensions/ScriptService/doc/cdevScriptServiceTITLE.doc new file mode 100755 index 0000000..d250a42 Binary files /dev/null and b/extensions/ScriptService/doc/cdevScriptServiceTITLE.doc differ diff --git a/extensions/ScriptService/doc/cdevScriptServiceTOC.doc b/extensions/ScriptService/doc/cdevScriptServiceTOC.doc new file mode 100755 index 0000000..22db7c0 Binary files /dev/null and b/extensions/ScriptService/doc/cdevScriptServiceTOC.doc differ diff --git a/extensions/ScriptService/doc/html/bullet.jpg b/extensions/ScriptService/doc/html/bullet.jpg new file mode 100755 index 0000000..a79a191 Binary files /dev/null and b/extensions/ScriptService/doc/html/bullet.jpg differ diff --git a/extensions/ScriptService/doc/html/cdevScriptService.html b/extensions/ScriptService/doc/html/cdevScriptService.html new file mode 100755 index 0000000..2666c82 --- /dev/null +++ b/extensions/ScriptService/doc/html/cdevScriptService.html @@ -0,0 +1,948 @@ + + +CDEV Script Service + + + + + + +


        + + + +
        + + + + CDEV Script Service +

        + +

        + A Tool for Using Interactive Scripts from CDEV +

        + +

        + Walt Akers +

        + +

        + Version 1.0 February 11, 1997 +

        + +

        + TJNAF - Thomas Jefferson National Accelerator Facility +

        + +

        +
        + +


        + + + + + +
        + + + + Table of Contents +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +
        +
        + + Script Service Fundamentals +
        +
        + + +
        +
        + + Overview of the Script Service +
        +
        + + +
        +
        + + Features of the Script Service +
        +
        + + 2. +
        +
        + + Building the Script Service +
        +
        + + +
        +
        + + Location of Files +
        +
        + + +
        +
        + + Steps to Building Service +
        +
        + + 3. +
        +
        + + Structure of Data Provided to the Script +
        +
        + + +
        +
        + + General Form of Data String +
        +
        + + +
        +
        + + Representation of Scalar Data +
        +
        + + +
        +
        + + Representation of Array Data +
        +
        + + 4. +
        +
        + + Structure of Data Returned from the Script +
        +
        + + +
        +
        + + Returning Data to the Calling CDEV Application +
        +
        + + +
        +
        + + General Form of String Data +
        +
        + + +
        +
        + + Returning a Single Result Packet +
        +
        + + +
        +
        + + Returning Multiple Result Packets +
        +
        + + +
        +
        + + Special Considerations +
        +
        + + 5. +
        +
        + + DDL Entries for the Script Service +
        +
        + + +
        +
        + + Setting Up the DDL +
        +
        +
        + +


        + + + + + +
        + + + + List of Figures +

        +
        + + + + Figure 7: + General form of string representation of cdevData +
        + + Figure 8: + String representation of scalar data in a cdevData object +
        + + Figure 9: + String representation of array data +
        + + Figure 10: + Returning a single result packet to the CDEV application +
        + + Figure 11: + Returning a multiple result packets to the CDEV application +
        + + Figure 12: + Simple DDL file for the Script Service +
        +
        + +


        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + + Script Service Fundamentals +

        +
        + + + Overview of the + Script Service +

        +
        + + The CDEV Script Service is designed to allow a a CDEV application to execute an + external script to process a message. The output that is produced by the executable + will be returned to the caller in the form of a cdevData. The CDEV Script Service + meets the following requirements. +

        +
        + + + Features of the + Script Service +

        +
        + + + + + + + + + + + + + + + + + + + + + +
        + + +

        +
        + + The filename of the script is associated with a CDEV device/message + combination by using the "filename" field of the class-data in the CDEV DDL file. + Syntax is described later in this document. +

        +
        + + +

        +
        + + A new process will be spawned for the script each time it is executed. Its standard + output (stdout) file descriptor will be redirected to return data to the main CDEV + application, allowing the script to return results to the parent process. +

        +
        + + +

        +
        + + The external executable file can be any form of user shell, batch file or binary + application that is supported on the host platform. +

        +
        + + +

        +
        + + The Script Service supports all of CDEV's send mechanisms; "send", + "sendNoBlock" and "sendCallback". Because of limits imposed on the number of + active processes, the user is advised to use the synchronous "send" method + whenever practical. +

        +
        + + +

        +
        + + When called by CDEV, the script will receive three arguments; the name of the + CDEV device associated with the request, the message string that was submitted + to the device, and a string that describes the contents of the outbound cdevData + object. +

        +
        + + +

        +
        + + The reply that is written to the standard output by the script must have a specific + format as described later in this document. A script may return more than one + reply packet to the caller. +

        +
        + + +

        +
        + + The script notifies CDEV that it has written its last reply packet by writing "done" + alone on a line to the standard output. +

        +
        + + +

        +
        + + If the script is to return multiple results, it should write "end" alone on a line to the + standard output between each packet, and write "done" alone on a line following + the last packet. +

        +
        + + +

        +
        + + If the script returns a value in the "status" tag of its reply packet, this will be + provided to the caller as the completion code of the message. Traditionally a + status of 0 indicates success, and all other values indicated an error occurred. +

        +
        + + +

        +
        + + Because the callback mechanism of the Script Service is triggered by output from + the script, the script developer should at least write "done" to the standard output + even if the application returns no output. +

        +
        +
        + + 2. +

        +
        + + + Building the Script Service +

        +
        + + + Location of Files +

        +
        + + The source code for the Script Service is provided with the CDEV distribution starting + with version 1.5. The source code is located in the directory $CDEV/extensions/ + ScriptService. The following steps should be taken to build the ScriptService. +

        +
        + + + Steps to Building + Service +

        +
        + + + + + + + + + + + +
        + + 1. +

        +
        + + Obtain and install the CDEV distribution - Version 1.5 or higher. +

        +
        + + 2. +

        +
        + + Follow the installation steps to build CDEV on your system. This includes setting + all of the environment variables required by CDEV. +

        +
        + + 3. +

        +
        + + Change directories to $CDEV/extensions/ScriptService/src. +

        +
        + + 4. +

        +
        + + There is a collection of platform specific makefiles in the directory $CDEV/ + extensions/cdevGenericServer/include/makeinclude. Link the makefile that is + appropriate to your architecture to the file Makefile.OS. +

        + + For example, to link to the makefile for HP-UX, you would type the following + command. +

        + +

        + ln -s Makefile.hpux Makefile.OS +

        + +

        +
        + + 5. +

        +
        + + Type make to compile and link the Script Service shared object. Note that you + must be using GNU make in order to build this distribution. +

        +
        + + Upon completion the Makefile will generate the shared object for the Script Service + and will install it into your CDEVSHOBJ directory. At this point you are ready to use + the Script Service. +

        +
        + + 3. +

        +
        + + + Structure of Data Provided to the Script +

        +
        + + + General Form of + Data String +

        +
        + + When a developer makes a CDEV send call, he may provide outbound data in the + form of a cdevData object. Before calling the script, this data is converted into a string + and provided as the third argument to the application (the first argument is the device + name and the second is the message). The structure of the outbound data string is of + the following form. +

        + +

        + + Figure 7: + + General form of string representation of cdevData +
        + + + +
        + + +
        
        +tag1="string value"
        +tag2=1.00
        +			
        +
        +
        + +

        + + +

        +
        + + + Representation of + Scalar Data +

        +
        + + The above example shows two data entries of the form tag=value. Each entry is + separated by a carriage return. The first entry has a tag name of 'tag1' and a value of + 'string value'. You will note that 'string value' is enclosed in double quotes in the + example. This is used to notify the script that the value is a non-numeric character + string. In the second data entry the value '1.0' is not enclosed in quotes, indicating that + the value is a number. +

        + The following example illustrates how scalar values stored in a cdevData object would + look when they are passed to the script. +

        + +

        + + Figure 8: + + String representation of scalar data in a cdevData object +
        + + + +
        + + +
        
        +Data stored in cdevData object:
        +      Tag:   value
        +      Data Type:   character string
        +      Value:   Test
        + 
        +      Tag:   status
        +      Data Type:   integer
        +      Value:   0
        + 
        +      Tag:   controlHigh
        +      Data Type:   double
        +      Value:   1.001
        + 
        +String representation provided to script:
        +      value="Test"\\n
        +      status=0\\n
        +      controlHigh=1.001\\n
        +			
        +
        +
        + +

        + + +

        +
        + + + Representation of + Array Data +

        +
        + + If array data is stored in the outbound cdevData object, it too can be provided to the + script. The data is structured in the standard C format where opening and closing + braces mark the beginning and end (respectively) of each array bound. The following + example illustrates how various arrays would be represented as strings. +

        + + Figure 9: + + String representation of array data +
        + + + +
        + + +
        
        +Data stored in cdevData object:
        +      Tag:   value
        +      Data Type:   character string [3]
        +      Value:   "value1" "value2" "value3"
        + 
        +String representation provided to script:
        +      value={"value1","value2","value3"}\\n
        + 
        +
        + 
        +Data stored in cdevData object:
        +      Tag:   value
        +      Data Type:   double [3]
        +      Value:   1.0, 2.0, 3.01
        + 
        +String representation provided to script:
        +      value={1,2,3.01}\\n
        + 
        +
        + 
        +Data stored in cdevData object:
        +      Tag:   value
        +      Data Type:   double [3][2]
        +      Value:   1.0, 2.0,   3.0, 4.0,    5.0, 6.0
        + 
        +String representation provided to script:
        +      value={{1,2},{3,4},{5,6}}\\n
        +			
        +
        +
        + +

        +
        + + 4. +

        +
        + + + Structure of Data Returned from the Script +

        +
        + + + Returning Data to + the Calling CDEV + Application +

        +
        + + Before CDEV starts the script, it creates a pipe that is used to pass data between the + script and the CDEV application. One end of this pipe is maintained by the application + and the other end of the pipe is provided to the script as its standard output. This + means that anytime the script uses the "echo" command or the "printf" command, the + data that it output's will be transmitted through the pipe to the parent application. +

        + The script is responsible for formatting the data into a collection of character strings + that can be recognized by the CDEV application. +

        +
        + + + General Form of + String Data +

        +
        + + In general, the data that is returned from a script is of the same form as described in + the preceding section, "Structure of Data Provided to the Script". The most notable + difference is that the script must terminate the list by providing a character string that + indicates that the group of data items is complete; the string "end" or "done" alone on + a line. +

        +
        + + + Returning a + Single Result + Packet +

        +
        + + If the script is going to return exactly one result packet (a group of tags and values that + will be used to populate the result cdevData), then it should write the string "done" on + a line by itself immediately following the output data. This will notify the Script Service + that no more data will be returned from the script. +

        + The following example shows how a single result will be returned from a script. Note + that the "status" tag contains the completion code that will be returned to the CDEV + application. +

        + + Figure 10: + + Returning a single result packet to the CDEV application +
        + + + +
        + + +
        
        +#\\! /bin/csh -f
        + 
        +echo value=\\"Test\\"
        +echo status=0
        +echo controlLow=1.5
        +echo controlHigh=25.1
        +echo done
        +			
        +
        +
        + +

        +
        + + + Returning + Multiple Result + Packets +

        +
        + + Returning multiple results from a single script execution is not generally advised. + However, If the script is going to return more than one result packet, then each interim + packet should be terminated by the "end" keyword on a line by itself. The "done" + keyword should follow the last entry. +

        + The following example shows how two results will be returned from a script. +

        + + Figure 11: + + Returning a multiple result packets to the CDEV application +
        + + + +
        + + +
        
        +#\\! /bin/csh -f
        + 
        +echo value=\\"Start Result 1\\"
        +echo status=0
        +echo end
        +echo value=\\"Start Result 2\\"
        +echo status=-1
        +echo done
        +			
        +
        +
        + +

        +
        + + + Special + Considerations +

        +
        + + If the script that is being executed will not return a result, then the developer should + still write "done" to the standard output in order to notify the CDEV application that it + should no longer wait for output. If the script is not returning a result, it may write the + terminating "done" at the beginning of the script or at the end. Because synchronous + calls will block until a reply is received, the developer should return a result to the + CDEV application as quickly as possible. +

        + If the developer never writes anything to the standard output, then the user specified + CDEV callback will never be executed... therefore, it is crucial to notify the CDEV + application when the script has completed. +

        +
        + + 5. +

        +
        + + + DDL Entries for the Script Service +

        +
        + + + Setting Up the + DDL +

        +
        + + The following example illustrates how to add a service entry to identify the Script + Service and how to use the class-data to specify the filename that the Script Service + will execute to service a message. +

        + + Figure 12: + + Simple DDL file for the Script Service +
        + + + +
        + + +
        
        +/*
        + * This is the service definition, it tells CDEV that there is
        + * a service named Script and that it will use the cdevData
        + * tag 'filename' to read configuration information from the
        + * DDL file entries.
        + */
        +service Script 
        +   {
        +   tags {filename}
        +   }
        + 
        +/*
        + * This class definition identifies the class scriptClass which
        + * supports the "get and "set" commands on attributes "attrib0"
        + * and "attrib1".  Note that attrib0 will call script /bin/ouch
        + * and attrib1 will call script /bin/wammo.
        + */ 
        +class scriptClass 
        +   {
        +       verbs {get, set}
        +   attributes 
        +      { 
        +      attrib0 Script {filename = /bin/ouch};
        +            attrib1 Script {filename = /bin/wammo};
        +      }
        +}
        + 
        +/*
        + * Finally, the CDEV DDL identifies two devices that are of type
        + * scriptClass.  Any time one of the supported messages is passed
        + * to one of these devices it will activate the corresponding
        + * script.
        + */
        +scriptClass : device0, device1;
        + 
        +			
        +
        +
        + +

        + + +

        +
        + diff --git a/extensions/ScriptService/doc/makehtml b/extensions/ScriptService/doc/makehtml new file mode 100755 index 0000000..044095c --- /dev/null +++ b/extensions/ScriptService/doc/makehtml @@ -0,0 +1,21 @@ +#! /bin/csh + +if( -f fmbatch.dat) rm fmbatch.dat +if( -d html) rm -rf html +mkdir -p html +cp $CDEV/doc/bullet.jpg html + +foreach x (`find . -name \*.doc -a ! -name \*TOC.doc -a ! -name \*LOF.doc`) + echo "Open $x" >> fmbatch.dat + echo "SaveAs ma $x html/`basename $x .doc`.mif" >> fmbatch.dat + end + +fmbatch fmbatch.dat + +cd html + +foreach x (`find . -name \*.mif -a ! -name \*TITLE.mif`) + mif2html -t 'CDEV Script Service' -o `basename $x .mif`.html `basename $x .mif`TITLE.mif \-TOC \-LOF $x + end + +rm *.mif diff --git a/extensions/ScriptService/src/.shobj/Linux/ScriptRequestObject.o b/extensions/ScriptService/src/.shobj/Linux/ScriptRequestObject.o new file mode 100644 index 0000000..4a606fa Binary files /dev/null and b/extensions/ScriptService/src/.shobj/Linux/ScriptRequestObject.o differ diff --git a/extensions/ScriptService/src/.shobj/Linux/ScriptService.o b/extensions/ScriptService/src/.shobj/Linux/ScriptService.o new file mode 100644 index 0000000..af82844 Binary files /dev/null and b/extensions/ScriptService/src/.shobj/Linux/ScriptService.o differ diff --git a/extensions/ScriptService/src/Makefile b/extensions/ScriptService/src/Makefile new file mode 100755 index 0000000..dbed95c --- /dev/null +++ b/extensions/ScriptService/src/Makefile @@ -0,0 +1,46 @@ +ARCH = OS +SHOBJ = YES + +include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.$(ARCH) + +APPNAME = "CDEV/ACE Script Service" +CXXINCLUDES = -I./ +BASEBIN = ./ +SO_LIBS = $(OSLIBS) +SO_SRCS = ScriptService.cc \ + ScriptRequestObject.cc \ + ScriptList.cc +OBJS = $(OBJDIR)/ScriptService.o \ + $(OBJDIR)/ScriptRequestObject.o \ + $(OBJDIR)/ScriptList.o + +# ****************************************************************************** +# * The BINARIES definition names all of the binary files that should be deleted +# * whenever "make clean" is executed. +# ****************************************************************************** +BINARIES = $(CDEVLIB)/libScriptService.a \ + $(CDEVSHOBJ)/$(CDEVVERSION)/ScriptService.so + +ifeq ($(SHOBJ), YES) + LIBS = $(CDEVLIBS) $(OSLIBS) + TARGETS = $(CDEVSHOBJ)/$(CDEVVERSION)/ScriptService.so +else + LIBS = $(CDEVLIBS) -lScriptService $(OSLIBS) + TARGETS = $(CDEVLIB)/libScriptService.a +endif + +targets : $(TARGETS) + +$(CDEVSHOBJ)/$(CDEVVERSION)/ScriptService.so : $(OBJS) + @rm -f $@ + @$(SOBUILD) + @mkdir -p $(CDEVSHOBJ)/$(CDEVVERSION) + @echo "<= Done...\n" + +$(CDEVLIB)/libScriptService.a : $(OBJS) + @rm -f $@ + @echo "=> Building archive library $(@F)" + @echo " => Linking $(@F) from objects" + @$(LINK.a) $@ $^ + @$(RANLIB) $@ > /dev/null + @echo "<= Done...\n" diff --git a/extensions/ScriptService/src/ScriptList.cc b/extensions/ScriptService/src/ScriptList.cc new file mode 100755 index 0000000..b3f31b8 --- /dev/null +++ b/extensions/ScriptService/src/ScriptList.cc @@ -0,0 +1,958 @@ +// ----------------------------------------------------------------------------- +// Copyright (c) 1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// ----------------------------------------------------------------------------- +// +// Description: +// This header file contains the class definitions for the classes +// associated with the construction of a script service. +// +// Author: Walt Akers +// +// Revision History: +// ScriptList.cc,v +// Revision 1.3 1997/02/14 20:43:40 akers +// Ongoing improvement +// +// Revision 1.2 1997/02/14 20:06:32 akers +// Ongoing improvement +// +// Revision 1.1 1997/02/11 17:37:22 akers +// Directory restructure +// +// Revision 1.7 1997/02/10 20:31:23 akers +// Ongoing improvement +// +// Revision 1.6 1997/02/07 16:19:43 akers +// Ongoing development +// +// Revision 1.5 1997/02/06 20:27:48 akers +// Ongoing development +// +// Revision 1.4 1997/01/31 21:09:58 akers +// Ongoing Development +// +// Revision 1.3 1997/01/31 18:51:26 akers +// Ongoing development +// +// Revision 1.2 1997/01/31 16:21:22 akers +// Ongoing development +// +// Revision 1.1 1997/01/30 20:35:33 akers +// Initial installation of Script Service +// +// ----------------------------------------------------------------------------- +#include + +// ***************************************************************************** +// * ScriptData::ScriptData : +// * Constructor for the class... +// ***************************************************************************** +ScriptData::ScriptData ( cdevTranObj & Xobj ) + : next(NULL), data(new cdevData), + xobj(&Xobj), inputBuf(NULL), + inputBufLen(0), amntRead(0), + process(0), finished(0), callbackCount(0) + { + // ********************************************************************* + // * Attempt to create the pipe that will be used to return + // * the result to the class. + // ********************************************************************* + if(pipe((int *)&sp)!=0) + { + sp.readFD = -1; + sp.writeFD = -1; + } + } + +// ***************************************************************************** +// * ScriptData::data2Buffer : +// * This method is used to convert a cdevData object into a +// * series of strings that can be used by the script. +// ***************************************************************************** +int ScriptData::data2Buffer ( cdevData & data, char *& buf, int &bufLen) + { + cdevDataIterator iter(&data); + int i; + int idx = 0; + struct DataPack + { + char * tag; + char ** ptr; + double * dPtr; + size_t ptrCnt; + int quoted; + cdevBounds * bounds; + size_t boundsCnt; + } dataPack[256]; + + memset(dataPack, 0, sizeof(dataPack)); + + // ********************************************************************* + // * Iterate through the cdevData object and collect the data + // * that is stored into an array of character strings. + // ********************************************************************* + for(bufLen=0, iter.init(); !iter && idx<256; idx++) + { + // ************************************************************* + // * Get the tag string and add the length of that plus + // * the length of a seperating equals sign (=) to the + // * buffer length. + // ************************************************************* + data.tagI2C(iter.tag(), dataPack[idx].tag); + bufLen+=strlen(dataPack[idx].tag)+2; + + // ************************************************************* + // * Get the number of elements in the array. + // ************************************************************* + data.getElems(dataPack[idx].tag, &dataPack[idx].ptrCnt); + + // ************************************************************* + // * If the data object is a string, add two times the + // * number of elements to the buffer length (to account + // * for double quotes around each entry.) + // ************************************************************* + if(data.getType(dataPack[idx].tag)==CDEV_STRING || + data.getType(dataPack[idx].tag)==CDEV_TIMESTAMP) + { + dataPack[idx].quoted = 1; + bufLen+=(2*dataPack[idx].ptrCnt); + + // ***************************************************** + // * Allocate an array of character strings to + // * be used to extract the array as a + // * collection of strings and increase the + // * buffer length to accomodate all of the + // * items. + // ***************************************************** + dataPack[idx].ptr = new char * [dataPack[idx].ptrCnt]; + data.get(dataPack[idx].tag, dataPack[idx].ptr); + for(i=0; i=0 && *tPtr; tPtr++) + { + if(*tPtr=='"') + { + tPtr = strchr(tPtr+1, '"'); + dataType = CDEV_STRING; + } + else if(*tPtr=='}') + { + if(dimIdx==nDim-1) bounds[dimIdx].length++; + dimIdx--; + } + else if(*tPtr=='{') + { + bounds[dimIdx++].length++; + } + else if(*tPtr==',' && dimIdx==nDim-1) + { + bounds[dimIdx].length++; + } + } + + // ***************************************************** + // * At this point, the last element of the bounds + // * array will contain the total count of items. + // ***************************************************** + itmCnt = bounds[nDim-1].length; + + // ***************************************************** + // * To set each bounds element to its actual array + // * dimension, it will be necessary to divide it by + // * the size of its predecessor - working backwards. + // ***************************************************** + for(dimIdx = nDim-2; dimIdx>=0; dimIdx--) + { + bounds[dimIdx+1].length /= bounds[dimIdx].length; + } + for(dimIdx = 0; dimIdx0) + { + // ***************************************************** + // * Allocate a buffer of the correct type to hold the + // * data. + // ***************************************************** + if(dataType == CDEV_STRING) strData = new char *[itmCnt]; + else dblData = new double [itmCnt]; + + // ***************************************************** + // * Walk through the data and accumulate the items + // * into the array. + // ***************************************************** + tPtr = ptr; + dimIdx = -1; + + do { + if(*tPtr=='{') + { + int jumpTheComma = 0; + + dimIdx++; + tPtr++; + + if(*tPtr && dimIdx==nDim-1) do + { + if(*tPtr==',' && jumpTheComma) tPtr++; + + while(isspace(*tPtr)) tPtr++; + if(dataType==CDEV_DOUBLE) + { + dblData[itmIdx++] = atof(tPtr); + while(*tPtr && *tPtr!=',' && *tPtr!='}') tPtr++; + } + else { + char oldEndVal; + char * ePtr; + if(*tPtr=='"') + { + tPtr++; + ePtr = strchr(tPtr, '"'); + } + else for(ePtr=tPtr; *ePtr && *ePtr!=',' && *ePtr!='}'; ePtr++); + + if(ePtr) + { + oldEndVal = *ePtr; + *ePtr = 0; + } + + strData[itmIdx++] = strdup(tPtr); + + if(ePtr) + { + *ePtr = oldEndVal; + tPtr = (*ePtr=='"')?ePtr+1:ePtr; + } + else tPtr = tPtr+strlen(tPtr); + } + jumpTheComma = (*tPtr==',')?1:0; + } while(*tPtr!='}' && *tPtr); + } + else if(*tPtr=='}') + { + dimIdx--; + tPtr++; + } + else tPtr++; + } while (*tPtr && itmIdx=0); + + if(dataType==CDEV_STRING) + { + data.insert(tag, strData, itmCnt, nDim); + for(int x=0; xuserCallback_->fireCallback ( result, arg, req, data, partial ); + callbackCount++; + } + +// ***************************************************************************** +// * ScriptData::dispatch : +// * This method is responsible for collecting data from the +// * read file descriptor, and executing the callback associated +// * with it. +// * +// * This method will return the number of messages that it handled. +// ***************************************************************************** +int ScriptData::dispatch ( void ) + { + int nHandled = 0; + if(!finished) + { + int count = 0; + int stat_val; + // ************************************************************* + // * Find out how many bytes are ready to read. + // ************************************************************* + while(ioctl(sp.readFD, FIONREAD, &count)==0 && count>0) + { + // ***************************************************** + // * If the input buffer has not already been + // * allocated, then allocate a new one that + // * is of sufficient size in increments of + // * 1024 bytes. + // ***************************************************** + if(inputBufLen==0) + { + inputBufLen = (count/1024+1)*1024; + inputBuf = (char *)malloc(inputBufLen); + } + // ***************************************************** + // * If the existing buffer is not sufficiently + // * large, then allocate a new one that is + // * of sufficient size in increments of + // * 1024 bytes. + // ********************************************* + else if(amntRead + count > inputBufLen) + { + inputBufLen = ((amntRead+count)/1024+1)*1024; + inputBuf = (char *)realloc(inputBuf, inputBufLen); + } + + // ***************************************************** + // * Read the data that is ready into the buffer + // ***************************************************** + amntRead += read(sp.readFD, inputBuf+amntRead, count); + + // ***************************************************** + // * NULL terminate the buffer to prevent memory + // * overruns while performing string operations + // ***************************************************** + inputBuf[amntRead] = 0; + + int done = 0; + + // ***************************************************** + // * Search the data for the "done" or "end" keywords + // * on a line by themselves... Either of these + // * keywords indicate the end of a data transmission. + // ***************************************************** + do { + char * ePtr = NULL; + + if (strncmp(inputBuf, "end\n", 4)==0 || + strncmp(inputBuf, "done\n", 5)==0) + { + ePtr = inputBuf; + } + else if((ePtr = strstr(inputBuf, "\nend\n"))!=NULL || + (ePtr = strstr(inputBuf, "\ndone\n"))!=NULL) + { + ePtr++; + } + else done = 1; + + if(ePtr && *ePtr) + { + if(*ePtr=='d') + { + *ePtr = 0; + ePtr += 5; + finished = 1; + } + else { + *ePtr = 0; + ePtr += 4; + } + + buffer2Data (inputBuf, *data); + strcpy(inputBuf, ePtr); + amntRead = strlen(inputBuf); + + // ************************************* + // * If no more data is ready, + // * determine if the process + // * is still alive. + // ************************************* + stat_val = 0; + if(waitpid(process, &stat_val, WNOHANG)==process && + (errno==ECHILD || WIFEXITED(stat_val))) + { + finished = 1; + } + + // ************************************* + // * Transfer the data from the + // * temporary data object into + // * the user-defined result + // * data object. + // ************************************* + if(xobj->resultData_==NULL) + xobj->resultData_ = data; + else *(xobj->resultData_) = *data; + + // ************************************* + // * Fire the user provided + // * callback and increment the + // * callback counter. The status as + // * returned in the cdevData object + // * is the status for the request. + // ************************************* + int status = CDEV_SUCCESS; + xobj->resultData_->get("status", &status); + fireCallback + ( + status, + xobj->userCallback_->userarg(), + *xobj->reqObj_, + *xobj->resultData_, + !finished); + nHandled++; + } + } while(!done && !finished); + } + + // ************************************************************* + // * When no more data is ready, determine if the process is + // * still alive. + // ************************************************************* + if(!finished && waitpid(process, &stat_val, WNOHANG)==process && + (errno==ECHILD || WIFEXITED(stat_val))) + { + finished = 1; + } + } + return nHandled; + } + +// ***************************************************************************** +// * ScriptData::~ScriptData : +// * The destructor is protected to prevent it from being deleted by +// * anyone except the ScriptList class. +// ***************************************************************************** +ScriptData::~ScriptData ( void ) + { + static int killCount = 0; + if(callbackCount==0) + { + data->remove(); + fireCallback ( + CDEV_SUCCESS, + xobj->userCallback_->userarg(), + *xobj->reqObj_, + *data); + } + + if(inputBuf) delete inputBuf; + if(sp.readFD != -1) close(sp.readFD); + if(sp.writeFD != -1) close(sp.writeFD); + if(data) delete data; + if(xobj) + { + xobj->removeFromGrps(); + delete xobj; + } + } + + +// ***************************************************************************** +// * ScriptList::ScriptList : +// * This is the constructor for the ScriptList class. It +// * initializes the internals of the class to 0. +// ***************************************************************************** +ScriptList::ScriptList ( void ) : scripts(NULL), fdList(NULL), fdCount(0), fdMax(0) + { + }; + +// ***************************************************************************** +// * ScriptList::ScriptList : +// * This method will walk through the list of ScriptData objects and +// * will delete each of them in sequence. +// * +// * Note that is no callbacks have been delivered for the specified +// * ScriptData object, it will deliver a single callback with +// * CDEV_ERROR as the status prior to terminating. +// ***************************************************************************** +ScriptList::~ScriptList ( void ) + { + ScriptData * curr; + while(scripts!=NULL) + { + curr = scripts; + scripts = scripts->next; + delete curr; + } + } + +// ***************************************************************************** +// * ScriptList::find : +// * This method allows the caller to locate the ScriptData object +// * that is associated with a specified file descriptor. +// ***************************************************************************** +ScriptData * ScriptList::find ( int fd ) + { + ScriptData * curr = scripts; + while(curr->sp.readFD != fd && curr!=NULL) + { + curr = curr->next; + } + return curr; + } + +// ***************************************************************************** +// * ScriptList::insert : +// * This method allows the caller to insert a new ScriptData object +// * into the list of scripts that is managed by this list. Once +// * added to the list the file descriptor associated with the +// * ScriptData object will be placed on the list of file +// * descriptors that will be polled by the cdevSystem object. +// ***************************************************************************** +void ScriptList::insert ( ScriptData & script ) + { + script.next = scripts; + scripts = &script; + + if(fdCount >= fdMax) + { + fdMax = (fdMax>1)?(fdMax*2):16; + fdList = (int *)realloc(fdList, fdMax*sizeof(int)); + } + if(fdCount==0) fdList[fdCount++] = selector.readfd(); + fdList[fdCount++] = script.sp.readFD; + } + +// ***************************************************************************** +// * ScriptList::remove : +// * This method calls the remove(fd) method to remove the ScriptData +// * object that is specified by the caller. +// ***************************************************************************** +void ScriptList::remove ( ScriptData & script ) + { + remove(script.sp.readFD); + } + +// ***************************************************************************** +// * ScriptList::remove : +// * This method will walk through all scripts in the list until it +// * locates the file descriptor specified by fd. The method will +// * then remove the ScriptData object that is associated with that +// * file descriptor. +// * +// * The fdList and fdCount variables will be updated once the dead +// * file descriptor has been removed. +// ***************************************************************************** +void ScriptList::remove ( int fd ) + { + ScriptData * prev = NULL; + ScriptData * curr = scripts; + + while(curr!=NULL && curr->sp.readFD!=fd) + { + prev = curr; + curr = prev->next; + } + if(curr!=NULL) + { + if(prev!=NULL) prev->next = curr->next; + else scripts = curr->next; + delete curr; + + for(fdCount=0, curr = scripts; curr!=NULL; curr=curr->next) + { + fdList[fdCount++] = curr->sp.readFD; + } + } + } + +// ***************************************************************************** +// * ScriptList::getFd : +// * This method allows the caller to obtain the list of file +// * descriptors that are in use in all scripts. These descriptors +// * will be used to perform ending at the cdevSystem level. +// * +// * Note that this list is updated and maintained each time the +// * user calls "insert" to add a new file descriptor of "remove" to +// * extract an old one. +// ***************************************************************************** +int ScriptList::getFd ( int * &fd, int & numFd ) + { + fd = fdList; + numFd = fdCount; + + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * ScriptList::poll : +// * This method is called to poll for events on a list of scripts +// * that are currently executing. This method will return the +// * count of callbacks that were dispatched during this pass through +// * poll. +// ***************************************************************************** +int ScriptList::poll ( void ) + { + int nHandled = 0; + ScriptData * prev = NULL; + ScriptData * curr = scripts; + + // ********************************************************************* + // * Clear any events that might be stored in the selector object. + // ********************************************************************* + selector.purge(); + + // ********************************************************************* + // * Walk through each script and call the dispatch method to + // * fire callbacks for all file descriptors that have data + // * ready. + // ********************************************************************* + for(curr=scripts; curr!=NULL; curr = curr->next) + { + nHandled+=curr->dispatch(); + } + + // ********************************************************************* + // * Walk through the list of scripts again. This time, check + // * the finished flag to determine if each script has run to + // * completion. If so, remove the script from the list of + // * scripts and delete it. + // ********************************************************************* + for(prev=NULL, curr=scripts; curr!=NULL; ) + { + if(curr->finished) + { + int deadFd = curr->sp.readFD; + curr = curr->next; + remove(deadFd); + } + else { + prev = curr; + curr = prev->next; + } + } + + // ********************************************************************* + // * Return the total number of callbacks that were fired. This + // * value will be used to allow for polling until at least one + // * event has been processed. + // ********************************************************************* + return nHandled; + } + + + diff --git a/extensions/ScriptService/src/ScriptList.h b/extensions/ScriptService/src/ScriptList.h new file mode 100755 index 0000000..79ed341 --- /dev/null +++ b/extensions/ScriptService/src/ScriptList.h @@ -0,0 +1,113 @@ +/* + * ----------------------------------------------------------------------------- + * Copyright (c) 1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * Description: + * This header file contains the class definitions for the classes + * associated with the construction of a script service. + * + * Author: Walt Akers + * + * ----------------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include +#include +#include +#include +// ***************************************************************************** +// * class ScriptData : +// * This contains the information associated with a single script. A list +// * of ScriptData objects is maintained and accessed through the ScriptList +// * object. +// * +// * Note: because this object is only accessed through the ScriptList +// * object, all data items have been made public to improve performance. +// ***************************************************************************** +class ScriptData +{ +public: + typedef struct { + int readFD; + int writeFD; + } SocketPair; + + + ScriptData * next; + SocketPair sp; + cdevTranObj * xobj; + cdevData * data; + char * inputBuf; + int inputBufLen; + int amntRead; + pid_t process; + int finished; + int callbackCount; + + ScriptData ( cdevTranObj & Xobj ); + ~ScriptData (void); + static int data2Buffer (cdevData & data, char *& buf, int &bufLen); + static void dataArray2Buffer (char * output, + char ** ptr, + size_t & ptrIdx, + cdevBounds * bounds, + size_t nBounds, + size_t boundsIdx); + static void dataArray2Buffer (char * output, + double * ptr, + size_t & ptrIdx, + cdevBounds * bounds, + size_t nBounds, + size_t boundsIdx); + static int buffer2Data (char * &buf, cdevData & data ); + void fireCallback (int result, + void * arg, + cdevRequestObject &req, + cdevData & data, + int partial=0); + int dispatch (void); +}; + + +// ***************************************************************************** +// * class ScriptList: +// * This class maintains a list of ScriptData objects that represent all +// * of the scripts that are currently being run by the ScriptService. The +// * ScriptService object will use the methods of this object to perform +// * operations on the items in the list. +// * +// * Because this class is only accessible through the ScriptService, its +// * internals have been made public to improve performance. +// ***************************************************************************** +class ScriptList +{ +public: + static cdevSelector selector; + + ScriptData * scripts; + int * fdList; + int fdCount; + int fdMax; + + ScriptList (void); + ~ScriptList (void); + ScriptData * find ( int fd ); + void insert ( ScriptData & script ); + void remove ( ScriptData & script ); + void remove ( int fd ); + int getFd ( int * &fd, int & numFd ); + int poll ( void ); +}; + + + diff --git a/extensions/ScriptService/src/ScriptRequestObject.cc b/extensions/ScriptService/src/ScriptRequestObject.cc new file mode 100755 index 0000000..86987b5 --- /dev/null +++ b/extensions/ScriptService/src/ScriptRequestObject.cc @@ -0,0 +1,134 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// This header file contains the class definitions for the classes +// associated with the construction of a model request object. +// +// Author: Walt Akers +// +// Revision History: +// ScriptRequestObject.cc,v +// Revision 1.1 1997/02/11 17:37:24 akers +// Directory restructure +// +// Revision 1.1 1997/01/30 20:35:34 akers +// Initial installation of Script Service +// +//----------------------------------------------------------------------------- +// + +#include +#include +#include + +int ScriptRequestObject::syncCode = 0; + +// ********************************************************************* +// * ScriptRequestObject::ScriptRequestObject : +// * This constructor initializes the internals of a device/message +// * pair associated with the model server. +// * +// * Returns nothing. +// ********************************************************************* +ScriptRequestObject::ScriptRequestObject ( char * device, char * message, cdevSystem & system) + : cdevRequestObject(device, message, system), syncFinished(0) + { + } + + +// ***************************************************************************** +// * ScriptRequestObject::sendNoBlock : +// * This function allows the caller to submit an asynchronous message to the +// * server for processing. +// ***************************************************************************** +int ScriptRequestObject::sendNoBlock (cdevData * in, cdevData * out) + { + ScriptService * svc = (ScriptService *)service_; + cdevTranObj * xobj = new cdevTranObj(&system_, this, out, &svc->asyncCallback); + cdevData * Data = ((in==NULL)?new cdevData:new cdevData(*in)); + + return svc->submit(*xobj, *Data); + } + + +// ***************************************************************************** +// * ScriptRequestObject::sendCallback : +// * This function allows the caller to submit an asynchronous message to the +// * server for processing. +// ***************************************************************************** +int ScriptRequestObject::sendCallback (cdevData * in, cdevCallback & callback) + { + ScriptService * svc = (ScriptService *)service_; + cdevTranObj * xobj = new cdevTranObj(&system_, this, NULL, new cdevCallback(callback)); + cdevData * Data = ((in==NULL)?new cdevData:new cdevData(*in)); + + xobj->enableDeleteCbk(); + return svc->submit(*xobj, *Data); + } + + +// ***************************************************************************** +// * ScriptRequestObject::send : +// * The send interface is used to provide synchronous I/O with the service. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int ScriptRequestObject::send ( cdevData * in, cdevData * out ) + { + int status = CDEV_SUCCESS; + ScriptService * svc = (ScriptService *)service_; + cdevCallback * cb = new cdevCallback(ScriptService::syncCallbackFunc, (void *)++syncCode); + cdevTranObj * xobj = new cdevTranObj(&system_, this, out, cb); + cdevData * Data = ((in==NULL)?new cdevData:new cdevData(*in)); + + xobj->enableDeleteCbk(); + if((status = svc->submit(*xobj, *Data))==CDEV_SUCCESS) + { + // ************************************************************* + // * I used to wait for a response here only if the outbound + // * cdevData object was non-null. However, that provided + // * unexpected behavior to the client. Now I wait whether + // * output data is expected or not. + // ************************************************************* + cdevTimeValue t((double)SEND_WAIT_PERIOD); + cdevClock timer; + timer.schedule(NULL,t); + + // ************************************************************* + // * WAITING WITH system_.pend(): + // * Previously I was using system_.pend() to process events + // * while waiting for the service to respond. This resulted + // * in a lock-up when the connection could not be + // * established or if the connection collapsed while in use. + // * + // * WAITING WITH system_.poll(): + // * When in a heavy inbound traffic situation, the calls from other + // * services will trample all over the inbound data coming from the + // * model service. This results in unreliable delivery and + // * processing of messages from the model server. + // * + // * WAITING WITH service_.poll(): + // * So far so good. + // ************************************************************* + for(syncFinished=0; !syncFinished && !timer.expired(); svc->poll()); + if (!syncFinished) + { + status = CDEV_ERROR; + system_.reportError( + CDEV_SEVERITY_ERROR, + "cdevRequestObject", + this, + "Transaction wasn't processed after %i seconds", + SEND_WAIT_PERIOD); + } + else status = syncStatus; + } + return status; + } diff --git a/extensions/ScriptService/src/ScriptRequestObject.h b/extensions/ScriptService/src/ScriptRequestObject.h new file mode 100755 index 0000000..6fc892f --- /dev/null +++ b/extensions/ScriptService/src/ScriptRequestObject.h @@ -0,0 +1,121 @@ +/* + *----------------------------------------------------------------------------- + * Copyright (c) 1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + *----------------------------------------------------------------------------- + * + * Description: + * This header file contains the class definitions for the classes + * associated with the construction of a request object. + * + * Author: Walt Akers + * + *----------------------------------------------------------------------------- + */ + +#if !defined (_SCRIPT_REQUEST_OBJECT_H_) +#define _SCRIPT_REQUEST_OBJECT_H_ + +#include +#include +#include +#include + +// ***************************************************************************** +// * ScriptRequestObject: +// * The ScriptRequestObject class provides the interface for sending +// * messages to a server. All device/message commands are routed +// * through a ScriptRequestObject either directly or indirectly. +// ***************************************************************************** +class ScriptRequestObject : public cdevRequestObject +{ +friend class ScriptService; + +public: + // ********************************************************************* + // * This is how long the system will wait for a reply to be returned + // * from a send. + // ********************************************************************* + enum { SEND_WAIT_PERIOD=30 }; + + // ********************************************************************* + // * ScriptRequestObject::ScriptRequestObject : + // * This constructor initializes the internals of a device/message + // * pair associated with the server. + // * + // * Returns nothing. + // ********************************************************************* + ScriptRequestObject ( char * device, char * message, + cdevSystem & system = cdevSystem::defaultSystem() ); + + // ********************************************************************* + // * ScriptRequestObject::~ScriptRequestObject : + // * This destructor performs any deallocation or shutdown operations + // * necessary, prior to the destruction of the object. + // * + // * Returns nothing. + // ********************************************************************* + virtual ~ScriptRequestObject ( void ) {} + + // ********************************************************************* + // * ScriptRequestObject::send : + // * The send interface is used to provide synchronous I/O with the + // * service. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int send ( cdevData & in, cdevData & out ) + { return send(&in, &out); } + int send ( cdevData * in, cdevData & out ) + { return send(in, &out); } + int send ( cdevData & in, cdevData * out ) + { return send(&in, out); } + int send ( cdevData * in, cdevData * out ); + + // ********************************************************************* + // * ScriptRequestObject::sendNoBlock : + // * The sendNoBlock interface is used in conjunction with cdevGroup + // * or cdevSystem to execute a series of operations. During the + // * early implementation of this product, these functions will be + // * linked directly to the send call. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int sendNoBlock (cdevData & in, cdevData & out) + { return sendNoBlock(&in, &out); } + int sendNoBlock (cdevData * in, cdevData & out) + { return sendNoBlock(in, &out); } + int sendNoBlock (cdevData & in, cdevData * out) + { return sendNoBlock(&in, out); } + int sendNoBlock (cdevData * in, cdevData * out); + + // ********************************************************************* + // * ScriptRequestObject::sendCallback : + // * The sendCallback interface provides asynchronous communications + // * with the server. During the early implementation of this + // * product, these functions will be linked directly to the send + // * call. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int sendCallback (cdevData & in, cdevCallback & callback) + { return sendCallback(&in, callback); } + int sendCallback (cdevData * in, cdevCallback & callback); + + // ********************************************************************* + // * ScriptRequestObject::className : + // * This function returns the name of the class as a constant string + // ********************************************************************* + const char * className ( void ) const { return "ScriptRequestObject"; } + +private: + int syncFinished; + int syncStatus; + static int syncCode; + }; + +#endif /* _SCRIPT_REQUEST_OBJECT_H_ */ diff --git a/extensions/ScriptService/src/ScriptService.cc b/extensions/ScriptService/src/ScriptService.cc new file mode 100755 index 0000000..8609eb6 --- /dev/null +++ b/extensions/ScriptService/src/ScriptService.cc @@ -0,0 +1,381 @@ +// ----------------------------------------------------------------------------- +// Copyright (c) 1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// ----------------------------------------------------------------------------- +// +// Description: +// This header file contains the class definitions for the classes +// associated with the construction of a script service. +// +// Author: Walt Akers +// +// Revision History: +// ScriptService.cc,v +// Revision 1.3 1997/02/14 20:43:41 akers +// Ongoing improvement +// +// Revision 1.2 1997/02/14 20:06:32 akers +// Ongoing improvement +// +// Revision 1.1 1997/02/11 17:37:27 akers +// Directory restructure +// +// Revision 1.3 1997/01/31 18:51:27 akers +// Ongoing development +// +// Revision 1.2 1997/01/31 16:21:24 akers +// Ongoing development +// +// Revision 1.1 1997/01/30 20:35:35 akers +// Initial installation of Script Service +// +// ----------------------------------------------------------------------------- + +#include + +#include "ScriptService.h" +#include "cdevDirectory.h" +#include "cdevClock.h" +#include "ScriptList.h" + +cdevSelector ScriptList::selector; + +// **************************************************************************** +// * This function is an interrupt handler that will be executed whenever the +// * program receives a SIGCHLD signal. When called it will execute the poll +// * method of the default server, in order to remove any dead Script Service +// * processes. +// **************************************************************************** +static void SIGCHLD_handler (int) + { + ScriptList::selector.insertEvent(); + } + + +// ********************************************************************* +// * newScriptService : +// * This method is called by the cdevSystem object to load the +// * initial instance of the ScriptService. +// ********************************************************************* +cdevService * newScriptService ( char * name, cdevSystem * system ) + { + signal(SIGCHLD, SIGCHLD_handler); + return new ScriptService(name, *system); + } + + +// ********************************************************************* +// * ScriptService::ScriptService : +// * This is the constructor for the script service. It determines +// * the tag number for the "filename" tag if it does not already +// * exist and allocates the ScriptList object that will be used +// * to hold the individual script instances. +// ********************************************************************* +ScriptService::ScriptService ( char * name, cdevSystem & system ) + : cdevService(name, system), + FILENAME_TAG(1000), + asyncCallback(asyncCallbackFunc, NULL) + { + scripts = new ScriptList; + + while(cdevData::tagC2I("filename", &FILENAME_TAG)!=CDEV_SUCCESS) + { + cdevData::insertTag(++FILENAME_TAG, "filename"); + } + } + +// ********************************************************************* +// * ScriptService::~ScriptService : +// * This is the destructor for the script service,it does nothing +// * but act as a placeholder for the virtual destructor. +// ********************************************************************* +ScriptService::~ScriptService ( void ) + { + } + +// ********************************************************************* +// * ScriptService::getRequestObject : +// * This is the interface that cdev objects will use to obtain a +// * ScriptRequestObject object. The ScriptRequestObject +// * represents a combined device and message pair that is associated +// * with the ScriptService. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ********************************************************************* +int ScriptService::getRequestObject ( char * device, char * message, cdevRequestObject * &req) + { + req = new ScriptRequestObject (device, message, system_); + return (req ? CDEV_SUCCESS : CDEV_ERROR); + } + +// ***************************************************************************** +// * ScriptService::getFd +// * This function will return the list of file descriptors that the +// * ScriptService is using. This will allow the file descriptors to be +// * used in global select and poll calls performed at the cdevSystem class +// * level. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int ScriptService::getFd ( int * &fd, int & numFd ) + { + fd = scripts->fdList; + numFd = scripts->fdCount; + + return CDEV_SUCCESS; + } + + +// ********************************************************************* +// * ScriptService::flush : +// * This function flushes all communications buffers that the +// * service may have open. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ********************************************************************* +int ScriptService::flush ( void ) + { + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * ScriptService::poll : +// * This function polls the file descriptors used by the service +// * until one of them becomes active or a discrete amount of time +// * has expired. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int ScriptService::poll ( void ) + { + if(scripts->fdCount>0) scripts->poll(); + + return CDEV_SUCCESS; + } + + + +// ***************************************************************************** +// * ScriptService::pend : +// * Pends until the named file descriptor (or any file descriptor +// * if fd = -1) is ready. Will pend forever if the descriptor does +// * not become active. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int ScriptService::pend ( int ) + { + while(scripts->fdCount>0 && scripts->poll()==0); + + return CDEV_SUCCESS; + } + + + +// ***************************************************************************** +// * ScriptService::pend : +// * Pends until the named file descriptor (or any file descriptor +// * if fd = -1) is ready. Will pend for no longer than the user +// * specified number of seconds. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int ScriptService::pend ( double seconds, int ) + { + if(scripts->fdCount > 0) + { + int nHandled = 0; + cdevTimeValue sec = seconds; + cdevClock timer; + + timer.schedule(NULL, sec); + + do { + nHandled = scripts->poll(); + } while(!nHandled && + !timer.expired() && + scripts->fdCount>0); + } + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * ScriptService::submit : +// * This is the mechanism that the request object will use to submit a +// * message to the service. It is important to note that all of the +// * data provided to this object becomes the property of the service and +// * must not be accessed afterwords. +// ***************************************************************************** +int ScriptService::submit ( cdevTranObj &xobj, cdevData &data ) + { + int status = CDEV_SUCCESS; + + // ********************************************************************* + // * Attempt to read the script filename from the DDL file. + // ********************************************************************* + ScriptData *script = new ScriptData(xobj); + cdevData temp; + char DDL_request[256]; + + sprintf (DDL_request, + "resolveServiceData %s %s", + xobj.reqObj_->device().name(), + xobj.reqObj_->message()); + + if((system_.nameServer()).send(DDL_request, NULL, &temp)==CDEV_SUCCESS) + { + *DDL_request = 0; + temp.get (FILENAME_TAG, DDL_request, 256); + } + else *DDL_request = 0; + + // ********************************************************************* + // * If the script file was loaded, then begin the process of creating + // * a pipe to retrieve the output of the script, and forking off an + // * additional process to handle execution. + // ********************************************************************* + if(*DDL_request) + { + char * parms = NULL; + int bufLen = 0; + + // ************************************************************* + // * Extract the data from the user provided output cdevData + // * object into a string that can be passed to the script. + // ************************************************************* + ScriptData::data2Buffer(data, parms, bufLen); + + // ************************************************************* + // * Make a copy standard output for later use to restore the + // * standard output file descriptor in the main thread... + // * This is because the behaviour of vfork on some systems + // * will leave the file descriptor in the main thread modified. + // ************************************************************* + int fd = dup(1); + + // ************************************************************* + // * Set the standard output file descriptor to the write file + // * descriptor of the socket pair. + // ************************************************************* + dup2(script->sp.writeFD, 1); + + // ************************************************************* + // * Fork the process to allow the user application to continue + // * running in the original branch, and the script to be + // * executed in the new (child) process. + // ************************************************************* + switch((script->process = vfork())) + { + // ***************************************************** + // * 0 Indicates that we are in the new child process. + // ***************************************************** + case 0: + { + if(bufLen) + { + execl(DDL_request, + DDL_request, + xobj.reqObj_->device().name(), + xobj.reqObj_->message(), + parms, NULL); + } + else { + execl(DDL_request, + DDL_request, + xobj.reqObj_->device().name(), + xobj.reqObj_->message(), + NULL); + } + exit(-1); + } + break; + + // ***************************************************** + // * -1 Indicates that a new process could not be + // * forked. + // ***************************************************** + case -1: + { + // ********************************************* + // * Restore the standard output file descriptor + // ********************************************* + dup2(fd, 1); + close(fd); + + system_.reportError( + CDEV_SEVERITY_ERROR, + "ScriptService", + xobj.reqObj_, + "Failed to fork a new process"); + + script->fireCallback(CDEV_ERROR, + xobj.userCallback_->userarg(), + *xobj.reqObj_, + *script->data); + + status = CDEV_ERROR; + delete script; + } + break; + + // ***************************************************** + // * Any other value indicates that we are in the parent + // * and the value is the process ID of the new child. + // ***************************************************** + default: + { + // ********************************************* + // * Restore the standard output file descriptor + // ********************************************* + dup2(fd, 1); + close(fd); + + // ********************************************* + // * Insert the script into the list. + // ********************************************* + scripts->insert(*script); + } + break; + } + + // ************************************************************* + // * Delete parameters (if any). + // ************************************************************* + if(bufLen) delete parms; + } + else { + system_.reportError( + CDEV_SEVERITY_ERROR, + "ScriptService", + xobj.reqObj_, + "No filename specified for request %s %s", + xobj.reqObj_->device().name(), + xobj.reqObj_->message()); + + script->fireCallback(CDEV_ERROR, + xobj.userCallback_->userarg(), + *xobj.reqObj_, + *script->data); + status = CDEV_ERROR; + delete script; + } + + return status; + } + +// ***************************************************************************** +// * ScriptService::getNameServer : +// * This function should obtain the default name server for this object. +// * It does nothing for now. +// ***************************************************************************** +int ScriptService::getNameServer(cdevDevice * &ns) + { + ns = 0; + return CDEV_SUCCESS; + } diff --git a/extensions/ScriptService/src/ScriptService.h b/extensions/ScriptService/src/ScriptService.h new file mode 100755 index 0000000..a4cffc1 --- /dev/null +++ b/extensions/ScriptService/src/ScriptService.h @@ -0,0 +1,166 @@ +/* + *----------------------------------------------------------------------------- + * Copyright (c) 1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + *----------------------------------------------------------------------------- + * + * Description: + * This header file contains the class definitions for the classes + * associated with the construction of a script service. + * + * Author: Walt Akers + * + *----------------------------------------------------------------------------- + */ + +#if !defined (_SCRIPT_SERVICE_H_) +#define _SCRIPT_SERVICE_H_ + +#include +#include "ScriptRequestObject.h" + +extern "C" cdevService *newScriptService ( char * name, cdevSystem * system ); + +class ScriptService : public cdevService +{ +friend class ScriptRequestObject; + +public: + // ********************************************************************* + // * ScriptService::ScriptService : + // * This constructor is responsible for performing all service + // * initialization. + // ********************************************************************* + ScriptService ( char * name, cdevSystem & system ); + + // ********************************************************************* + // * ScriptService::~ScriptService : + // * The destructor is protected to prevent it from being called + // * directly. The destructor performs any clean-up or shutdown + // * operations. + // * + // * Returns nothing. + // ********************************************************************* + ~ScriptService ( void ); + + // ********************************************************************* + // * ScriptService::installTags : + // * Installs the tags that the service and service applications + // * will use. This function is static to allow servers to setup + // * the necessary tags without having to instanciate a + // * ScriptService object. + // ********************************************************************* + void installTags ( void ); + + // ********************************************************************* + // * ScriptService::getRequestObject : + // * This is the interface that cdev objects will use to obtain a + // * cdevSimpleRequestObject object. The cdevSimpleRequestObject + // * represents a combined device and message pair that is associated + // * with the ScriptService. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int getRequestObject (char *, char *, cdevRequestObject * &); + + // ********************************************************************* + // * ScriptService::getFd + // * This function will return the list of file descriptors that the + // * ScriptService is using. This will allow the file + // * descriptors to be used in global select and poll calls performed + // * at the cdevSystem class level. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int getFd ( int * &fd, int & numFd ); + + // ********************************************************************* + // * ScriptService::flush : + // * This function flushes all communications buffers that the + // * service may have open. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int flush ( void ); + + // ********************************************************************* + // * ScriptService::poll : + // * This function polls the file descriptors used by the service + // * until one of them becomes active or a discrete amount of time + // * has expired. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int poll ( void ); + + // ********************************************************************* + // * ScriptService::pend : + // * Pends until the named file descriptor (or any file descriptor + // * if fd = -1) is ready. Will pend for no longer than the user + // * specified number of seconds. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int pend ( double seconds, int = -1); + + // ********************************************************************* + // * ScriptService::pend : + // * Pends until the named file descriptor (or any file descriptor + // * if fd = -1) is ready. Will pend forever if the descriptor does + // * not become active. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int pend ( int = -1); + + // ********************************************************************* + // * ScriptService::submit : + // * This is the mechanism that the request object will use to submit + // * a message to the service. It is important to note that all of + // * the data provided to this object becomes the property of the + // * service and must not be accessed afterwords. + // ********************************************************************* + int submit (cdevTranObj &, cdevData &); + + // ********************************************************************* + // * ScriptService::getNameServer : + // * This function should obtain the default name server for this + // * object. It does nothing for now. + // ********************************************************************* + int getNameServer(cdevDevice * &ns); + + // ********************************************************************* + // * ScriptService::asyncCallback : + // * This method is called in response to a sendNoBlock reply. + // ********************************************************************* + static void asyncCallbackFunc (int, void *, cdevRequestObject &, cdevData &) + { + } + + // ********************************************************************* + // * ScriptService::syncCallback : + // * This method is called whenever a send is requested from a + // * ScriptRequestObject. + // ********************************************************************* + static void syncCallbackFunc ( int status, void *arg, cdevRequestObject &req, cdevData &) + { + ScriptRequestObject * sReq = (ScriptRequestObject *)&req; + int syncCode = (int)arg; + + if(syncCode == sReq->syncCode) + { + sReq->syncFinished = 1; + sReq->syncStatus = status; + } + } +protected: + int FILENAME_TAG; + class ScriptList * scripts; + cdevCallback asyncCallback; +}; + +#endif /* _SCRIPT_SERVICE_H_ */ diff --git a/extensions/ScriptService/test/.shobj/Linux/TestProgram.o b/extensions/ScriptService/test/.shobj/Linux/TestProgram.o new file mode 100644 index 0000000..c3153e1 Binary files /dev/null and b/extensions/ScriptService/test/.shobj/Linux/TestProgram.o differ diff --git a/extensions/ScriptService/test/.shobj/Linux/TestProgram2.o b/extensions/ScriptService/test/.shobj/Linux/TestProgram2.o new file mode 100644 index 0000000..d48d2e8 Binary files /dev/null and b/extensions/ScriptService/test/.shobj/Linux/TestProgram2.o differ diff --git a/extensions/ScriptService/test/Makefile b/extensions/ScriptService/test/Makefile new file mode 100755 index 0000000..deff011 --- /dev/null +++ b/extensions/ScriptService/test/Makefile @@ -0,0 +1,39 @@ +ARCH = OS +SHOBJ = YES + +include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.$(ARCH) + +APPNAME = "CDEV/ACE Script Service Tests" +CXXINCLUDES = -I./ +BASEBIN = ./ +SO_LIBS = $(OSLIBS) + +# ****************************************************************************** +# * The BINARIES definition names all of the binary files that should be deleted +# * whenever "make clean" is executed. +# ****************************************************************************** +BINARIES = $(BASEBIN)/TestProgram $(BASEBIN)/TestProgram2 + +ifeq ($(SHOBJ), YES) + LIBS = $(CDEVLIBS) $(OSLIBS) + TARGETS = $(BASEBIN)/TestProgram \ + $(BASEBIN)/TestProgram2 +else + LIBS = $(CDEVLIBS) -lScriptService $(OSLIBS) + TARGETS = $(BASEBIN)/TestProgram \ + $(BASEBIN)/TestProgram2 +endif + +targets : $(TARGETS) + +$(BASEBIN)/TestProgram : $(OBJDIR)/TestProgram.o + @rm -f $@ + @echo "=> $(CXX) -o $(@F) $(^F)" + @$(LINK.cc) $^ -o $@ $(LIBS) + @echo "<= Done...\n" + +$(BASEBIN)/TestProgram2 : $(OBJDIR)/TestProgram2.o + @rm -f $@ + @echo "=> $(CXX) -o $(@F) $(^F)" + @$(LINK.cc) $^ -o $@ $(LIBS) + @echo "<= Done...\n" diff --git a/extensions/ScriptService/test/Script.ddl b/extensions/ScriptService/test/Script.ddl new file mode 100755 index 0000000..80ca0ed --- /dev/null +++ b/extensions/ScriptService/test/Script.ddl @@ -0,0 +1,27 @@ +service Script + { + tags {filename} + } + +class scriptClass + { + verbs {get, set, monitorOn, monitorOff} + attributes + { + attrib0 Script {filename = <>.attrib0}; + attrib1 Script {filename = <>.attrib1}; + attrib2 Script {filename = <>.attrib2}; + attrib3 Script {filename = <>.attrib3}; + attrib4 Script {filename = <>.attrib4}; + attrib5 Script {filename = <>.attrib5}; + attrib6 Script {filename = <>.attrib6}; + attrib7 Script {filename = <>.attrib7}; + attrib8 Script {filename = <>.attrib8}; + attrib9 Script; + } +} + +scriptClass : + device0, device1, device2, device3, device4, + device5, device6, device7, device8, device9 +; diff --git a/extensions/ScriptService/test/TestProgram b/extensions/ScriptService/test/TestProgram new file mode 100755 index 0000000..871ee61 Binary files /dev/null and b/extensions/ScriptService/test/TestProgram differ diff --git a/extensions/ScriptService/test/TestProgram.cc b/extensions/ScriptService/test/TestProgram.cc new file mode 100755 index 0000000..8d6394d --- /dev/null +++ b/extensions/ScriptService/test/TestProgram.cc @@ -0,0 +1,76 @@ +#include +#include +#include +#include + +void callback (int, void *arg, cdevRequestObject &, cdevData &) + { + static int totalCount = 0; + int * resultCount = (int *)arg; + (*resultCount)++; + + fprintf(stdout, "Total count = %i\n", ++totalCount); + } + +char * data[2][2][3] = + { + {{"1", "2", "3"}, {"4", "5", "6"}}, + {{"1", "2", "3"}, {"4", "5", "6"}}, + }; + +double dData[2][2][3] = + { + {{1.1, 2.2, 3.3}, {4.4, 5.5, 6.6}}, + {{1.7, 2.8, 3.9}, {4.11, 5.12, 6.13}} + }; + +cdevBounds bounds[3] = + {{0, 2}, + {0, 2}, + {0, 3}}; + +int main ( void ) + { + int resultCount = 0; + cdevData in; + cdevRequestObject & req = cdevRequestObject::attachRef("device0", "get attrib0"); + cdevCallback cb (callback, &resultCount); + + in.insert("value", (char **)data, 12, 3); + in.setBounds("value", bounds, 3); + in.insert("severity", (double*)dData, 12, 3); + in.setBounds("severity", bounds, 3); + in.insert("status", "Testing"); + + for(int i=0; i<10; i++) + { + resultCount = 0; + + for(int j=0; j<20; j++) + { + req.sendCallback(in, cb); + } + while(resultCount<26) cdevSystem::defaultSystem().poll(); + } + } +/* +#include "ScriptList.cc" + +int main() + { + cdevData in, out; + char * buf; + int bufLen; + + in.insert("value", (char **)data, 12, 3); + in.setBounds("value", bounds, 3); + in.insert("severity", (double*)dData, 12, 3); + in.setBounds("severity", bounds, 3); + in.insert("status", "Testing"); + + ScriptData::data2Buffer(in, buf, bufLen); + ScriptData::buffer2Data(buf, out); + out.asciiDump(); + delete buf; + } +*/ diff --git a/extensions/ScriptService/test/TestProgram2 b/extensions/ScriptService/test/TestProgram2 new file mode 100755 index 0000000..41816ba Binary files /dev/null and b/extensions/ScriptService/test/TestProgram2 differ diff --git a/extensions/ScriptService/test/TestProgram2.cc b/extensions/ScriptService/test/TestProgram2.cc new file mode 100755 index 0000000..4f69679 --- /dev/null +++ b/extensions/ScriptService/test/TestProgram2.cc @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +int done = 0; + +void callback (int, void *, cdevRequestObject &, cdevData &data) + { + static int resultCount = 0; + done = cdevCallback::isTransactionDone(); + fprintf(stdout, "Result count %i - %s done...\n", ++resultCount, done?" ":"NOT"); + if(done) data.asciiDump(); + } + +int main ( void ) + { + cdevData in; + cdevRequestObject & req = cdevRequestObject::attachRef("device0", "get attrib0"); + cdevCallback cb (callback, NULL); + + req.sendCallback(in, cb); + while(!done) + { + cdevSystem::defaultSystem().pend(); + } + } diff --git a/extensions/ScriptService/test/device0.attrib0 b/extensions/ScriptService/test/device0.attrib0 new file mode 100755 index 0000000..b176281 --- /dev/null +++ b/extensions/ScriptService/test/device0.attrib0 @@ -0,0 +1,386 @@ +#! /bin/csh -f +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value=1\nseverity="GOOD"\nstatus=0\nend\n' +printf 'value={{1,2,3},{4,5,6}}\nseverity="NOT so GOOD"\nstatus=0\ncontrolLow={1, 2, 3}\ndone\n' diff --git a/extensions/ScriptService/test/device0.attrib1 b/extensions/ScriptService/test/device0.attrib1 new file mode 100755 index 0000000..e6aa966 --- /dev/null +++ b/extensions/ScriptService/test/device0.attrib1 @@ -0,0 +1 @@ +#! /bin/csh diff --git a/extensions/ScriptService/test/odebug.txt b/extensions/ScriptService/test/odebug.txt new file mode 100755 index 0000000..b0cb00f --- /dev/null +++ b/extensions/ScriptService/test/odebug.txt @@ -0,0 +1,15 @@ +load /lib/milli.a +load /lib/libc.sl +load /usr/csite4/CenterLine/pa-hpux8/lib/libC.a +load -G /usr/csite/cdev/1.5/lib/hpux-09.XX/libcdev.a +load -D_OS_MAJOR_=9 \ + -D_OS_MINOR_=7 \ + -I/usr/csite/cdev/1.5/include \ + -g -D_HAS_CA -pta \ + -I./ -I../src\ + ../src/ScriptList.cc \ + ../src/ScriptService.cc \ + ../src/ScriptRequestObject.cc \ + TestProgram2.cc \ + -ly -ll -L/lib -lm +link diff --git a/extensions/SimpleService/.obj/Linux/cdevSimpleRequestObject.o b/extensions/SimpleService/.obj/Linux/cdevSimpleRequestObject.o new file mode 100644 index 0000000..c29a080 Binary files /dev/null and b/extensions/SimpleService/.obj/Linux/cdevSimpleRequestObject.o differ diff --git a/extensions/SimpleService/.obj/Linux/cdevSimpleService.o b/extensions/SimpleService/.obj/Linux/cdevSimpleService.o new file mode 100644 index 0000000..ee61e40 Binary files /dev/null and b/extensions/SimpleService/.obj/Linux/cdevSimpleService.o differ diff --git a/extensions/SimpleService/.obj/Linux/cdevTranNode.o b/extensions/SimpleService/.obj/Linux/cdevTranNode.o new file mode 100644 index 0000000..2d0303d Binary files /dev/null and b/extensions/SimpleService/.obj/Linux/cdevTranNode.o differ diff --git a/extensions/SimpleService/.shobj/Linux/cdevSimpleRequestObject.o b/extensions/SimpleService/.shobj/Linux/cdevSimpleRequestObject.o new file mode 100644 index 0000000..c16c4d4 Binary files /dev/null and b/extensions/SimpleService/.shobj/Linux/cdevSimpleRequestObject.o differ diff --git a/extensions/SimpleService/.shobj/Linux/cdevSimpleService.o b/extensions/SimpleService/.shobj/Linux/cdevSimpleService.o new file mode 100644 index 0000000..799012b Binary files /dev/null and b/extensions/SimpleService/.shobj/Linux/cdevSimpleService.o differ diff --git a/extensions/SimpleService/.shobj/Linux/cdevTranNode.o b/extensions/SimpleService/.shobj/Linux/cdevTranNode.o new file mode 100644 index 0000000..1ea4ce4 Binary files /dev/null and b/extensions/SimpleService/.shobj/Linux/cdevTranNode.o differ diff --git a/extensions/SimpleService/Makefile b/extensions/SimpleService/Makefile new file mode 100755 index 0000000..986e32f --- /dev/null +++ b/extensions/SimpleService/Makefile @@ -0,0 +1,43 @@ +ARCH=OS +include ../cdevGenericServer/include/makeinclude/Makefile.$(ARCH) + +APPNAME = "CDEV Simple Generic Service" +BASEDIR = $(shell pwd) +INCDIR = $(CDEV)/extensions/cdevGenericServer/include +BINDIR = ./ +LIBDIR = $(CDEV)/lib/$(TARGETDIR) + +CDEV_INCLUDES = -I$(CDEV)/include +CDEV_LIBS = -lcdev +CDEV_LIBDIR = $(CDEV)/lib/$(TARGETDIR) + +CLASS_INCLUDES = -I./ -I$(INCDIR) + +CXXEXTRA = -g $(CDEV_INCLUDES) $(CLASS_INCLUDES) + +ARLIB_OBJ = .obj/$(TARGETDIR)/cdevSimpleRequestObject.o \ + .obj/$(TARGETDIR)/cdevSimpleService.o \ + .obj/$(TARGETDIR)/cdevTranNode.o + +SHLIB_OBJ = .shobj/$(TARGETDIR)/cdevSimpleRequestObject.o \ + .shobj/$(TARGETDIR)/cdevSimpleService.o \ + .shobj/$(TARGETDIR)/cdevTranNode.o + +TARGETS = $(LIBDIR)/libSimpleService.a $(LIBDIR)/libSimpleService.sl + +targets : $(TARGETS) + +$(LIBDIR)/libSimpleService.a : $(ARLIB_OBJ) + @rm -f $@ + @echo "=> ar ruv $@" + @mkdir -p $(LIBDIR) + @$(LINK.a) $@ $(ARLIB_OBJ) + @ranlib $@ > /dev/null + @echo "\n -------- Completed ----------\n" + +$(LIBDIR)/libSimpleService.sl : $(SHLIB_OBJ) + @rm -f $@ + @echo "=> $(LINK.so) $(@F)" + @mkdir -p $(LIBDIR) + @$(LINK.so) -o $@ $(SHLIB_OBJ) + @echo "\n -------- Completed ----------\n" diff --git a/extensions/SimpleService/cdevSimpleRequestObject.cc b/extensions/SimpleService/cdevSimpleRequestObject.cc new file mode 100755 index 0000000..1eabfab --- /dev/null +++ b/extensions/SimpleService/cdevSimpleRequestObject.cc @@ -0,0 +1,145 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// This header file contains the class definitions for the classes +// associated with the construction of a model request object. +// +// Author: Walt Akers +// +// Revision History: +// cdevSimpleRequestObject.cc,v +// Revision 1.1 1996/11/21 18:22:19 akers +// Non-Server Oriented Service +// +// Revision 1.1 1996/04/30 15:37:30 akers +// Simple CDEV Service +// +// Revision 1.1.1.1 1996/02/28 16:36:21 akers +// Initial release of support for ACE Services +// +//----------------------------------------------------------------------------- +// + +#include +#include +#include +#include + +// ********************************************************************* +// * cdevSimpleRequestObject::cdevSimpleRequestObject : +// * This constructor initializes the internals of a device/message +// * pair associated with the model server. +// * +// * Returns nothing. +// ********************************************************************* +cdevSimpleRequestObject::cdevSimpleRequestObject ( char * device, char * message, cdevSystem & system) + : cdevRequestObject(device, message, system) + { + cdevData::tagC2I("transaction", &TRANSACT_TAG); + cdevData::tagC2I("transobject", &TRANSOBJ_TAG); + } + + +// ***************************************************************************** +// * cdevSimpleRequestObject::sendNoBlock : +// * This function allows the caller to submit an asynchronous message to the +// * server for processing. +// ***************************************************************************** +int cdevSimpleRequestObject::sendNoBlock (cdevData * in, cdevData * out) + { + cdevSimpleService * svc = (cdevSimpleService *)service_; + cdevTranNode * xobj = new cdevTranNode(&system_, this, out, &svc->callback); + char * Device = strdup(deviceName_); + char * Message = strdup(message_); + cdevData * Data = ((in==NULL)?new cdevData:new cdevData(*in)); + + svc->submit(xobj, Device, Message, Data); + + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * cdevSimpleRequestObject::sendCallback : +// * This function allows the caller to submit an asynchronous message to the +// * server for processing. +// ***************************************************************************** +int cdevSimpleRequestObject::sendCallback (cdevData * in, cdevCallback & callback) + { + cdevSimpleService * svc = (cdevSimpleService *)service_; + cdevTranNode * xobj = new cdevTranNode(&system_, this, NULL, new cdevCallback(callback)); + char * Device = strdup(deviceName_); + char * Message = strdup(message_); + cdevData * Data = ((in==NULL)?new cdevData:new cdevData(*in)); + + xobj->enableDeleteCbk(); + svc->submit(xobj, Device, Message, Data); + + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * cdevSimpleRequestObject::send : +// * The send interface is used to provide synchronous I/O with the service. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int cdevSimpleRequestObject::send ( cdevData * in, cdevData * out ) + { + int status = CDEV_SUCCESS; + cdevSimpleService * svc = (cdevSimpleService *)service_; + cdevTranNode * xobj = new cdevTranNode(&system_, this, out, &svc->callback); + char * Device = strdup(deviceName_); + char * Message = strdup(message_); + cdevData * Data = ((in==NULL)?new cdevData:new cdevData(*in)); + + xobj->permanent(1); + svc->submit(xobj, Device, Message, Data); + + // ********************************************************************* + // * I used to wait for a response here only if the outbound cdevData + // * object was non-null. However, that provided unexpected behavior + // * to the client. Now I wait whether output data is expected or not. + // ********************************************************************* + cdevTimeValue t(30.0); + cdevClock timer; + timer.schedule(NULL,t); + + // ********************************************************************* + // * WAITING WITH system_.pend(): + // * Previously I was using system_.pend() to process events while + // * waiting for the service to respond. This resulted in a lock-up + // * when the connection could not be established or if the + // * connection collapsed while in use. + // * + // * WAITING WITH system_.poll(): + // * When in a heavy inbound traffic situation, the calls from other + // * services will trample all over the inbound data coming from the + // * model service. This results in unreliable delivery and + // * processing of messages from the model server. + // * + // * WAITING WITH service_.poll(): + // * So far so good. + // ********************************************************************* + while(!xobj->finished() && !timer.expired()) service_->poll(); + if (!xobj->finished()) + { + status = CDEV_ERROR; + system_.reportError( + CDEV_SEVERITY_ERROR, + "cdevRequestObject", + this, + "Transaction wasn't processed after 30 seconds"); + } + + delete xobj; + return status; + } diff --git a/extensions/SimpleService/cdevSimpleRequestObject.h b/extensions/SimpleService/cdevSimpleRequestObject.h new file mode 100755 index 0000000..2a4f4f5 --- /dev/null +++ b/extensions/SimpleService/cdevSimpleRequestObject.h @@ -0,0 +1,110 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// This header file contains the class definitions for the classes +// associated with the construction of a request object. +// +// Author: Walt Akers +// +//----------------------------------------------------------------------------- + +#if !defined (_CDEV_SIMPLE_REQUEST_OBJECT_H_) +#define _CDEV_SIMPLE_REQUEST_OBJECT_H_ + +#include +#include +#include +#include + +// ***************************************************************************** +// * cdevSimpleRequestObject: +// * The cdevSimpleRequestObject class provides the interface for sending +// * messages to a server. All device/message commands are routed +// * through a cdevSimpleRequestObject either directly or indirectly. +// ***************************************************************************** +class cdevSimpleRequestObject : public cdevRequestObject +{ +public: + // ********************************************************************* + // * cdevSimpleRequestObject::cdevSimpleRequestObject : + // * This constructor initializes the internals of a device/message + // * pair associated with the server. + // * + // * Returns nothing. + // ********************************************************************* + cdevSimpleRequestObject ( char * device, char * message, + cdevSystem & system = cdevSystem::defaultSystem() ); + + // ********************************************************************* + // * cdevSimpleRequestObject::~cdevSimpleRequestObject : + // * This destructor performs any deallocation or shutdown operations + // * necessary, prior to the destruction of the object. + // * + // * Returns nothing. + // ********************************************************************* + ~cdevSimpleRequestObject ( void ) {} + + // ********************************************************************* + // * cdevSimpleRequestObject::send : + // * The send interface is used to provide synchronous I/O with the + // * service. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int send ( cdevData & in, cdevData & out ) + { return send(&in, &out); } + int send ( cdevData * in, cdevData & out ) + { return send(in, &out); } + int send ( cdevData & in, cdevData * out ) + { return send(&in, out); } + int send ( cdevData * in, cdevData * out ); + + // ********************************************************************* + // * cdevSimpleRequestObject::sendNoBlock : + // * The sendNoBlock interface is used in conjunction with cdevGroup + // * or cdevSystem to execute a series of operations. During the + // * early implementation of this product, these functions will be + // * linked directly to the send call. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int sendNoBlock (cdevData & in, cdevData & out) + { return sendNoBlock(&in, &out); } + int sendNoBlock (cdevData * in, cdevData & out) + { return sendNoBlock(in, &out); } + int sendNoBlock (cdevData & in, cdevData * out) + { return sendNoBlock(&in, out); } + int sendNoBlock (cdevData * in, cdevData * out); + + // ********************************************************************* + // * cdevSimpleRequestObject::sendCallback : + // * The sendCallback interface provides asynchronous communications + // * with the server. During the early implementation of this + // * product, these functions will be linked directly to the send + // * call. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int sendCallback (cdevData & in, cdevCallback & callback) + { return sendCallback(&in, callback); } + int sendCallback (cdevData * in, cdevCallback & callback); + + // ********************************************************************* + // * cdevSimpleRequestObject::className : + // * This function returns the name of the class as a constant string + // ********************************************************************* + const char * className ( void ) const { return "cdevSimpleRequestObject"; } + +private: + int TRANSACT_TAG; + int TRANSOBJ_TAG; + }; + +#endif /* _CDEV_SIMPLE_REQUEST_OBJECT_H_ */ diff --git a/extensions/SimpleService/cdevSimpleService.cc b/extensions/SimpleService/cdevSimpleService.cc new file mode 100755 index 0000000..e3ed3ff --- /dev/null +++ b/extensions/SimpleService/cdevSimpleService.cc @@ -0,0 +1,419 @@ + +// ----------------------------------------------------------------------------- +// Copyright (c) 1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// ----------------------------------------------------------------------------- +// +// Description: +// This header file contains the class definitions for the classes +// associated with the construction of a service. +// +// Author: Walt Akers +// +// Revision History: +// cdevSimpleService.cc,v +// Revision 1.1 1996/11/21 18:22:24 akers +// Non-Server Oriented Service +// +// Revision 1.1 1996/04/30 15:37:38 akers +// Simple CDEV Service +// +// Revision 1.2 1996/03/21 13:57:55 akers +// Major Modifications +// +// Revision 1.1.1.1 1996/02/28 16:36:21 akers +// Initial release of support for ACE Services +// +// ----------------------------------------------------------------------------- + +#include +#include +#include +#include + +// ***************************************************************************** +// * defaultCallback: +// * This static function is the default callback function that will be +// * utilized for send and sendNoBlock. +// ***************************************************************************** +static void defaultCallback(int, void *, cdevRequestObject &, cdevData &) + { + } + + +// ***************************************************************************** +// * trim : +// * This method is used to remove any extraneous spaces from a message. +// ***************************************************************************** +static char * trim ( char * ptr ) + { + char * s1 = ptr; + char * s2; + + if(ptr!=NULL) + { + // ************************************************************* + // * Remove leading space from the string. + // ************************************************************* + for(s1=ptr; isspace(*s1) && s1!=0; s1++); + if(s1!=ptr) memmove(ptr, s1, strlen(s1)+1); + + // ************************************************************* + // * Remove any multi-space entries from the string. + // ************************************************************* + for(s1=ptr; *s1; s1++) if(isspace(*s1)) + { + for(s2=s1; *s2 && isspace(*s2); s2++); + if(s2>s1+1) memmove(s1+1, s2, strlen(s2)+1); + } + + // ************************************************************* + // * Remove trailing space from the string. + // ************************************************************* + for(s1=&ptr[strlen(ptr)-1]; s1>=ptr && isspace(*s1); s1--) *s1=0; + } + + return ptr; + } + +// ***************************************************************************** +// * cdevSimpleService::cdevSimpleService : +// * This constructor is responsible for performing all service +// * initialization. +// ***************************************************************************** +cdevSimpleService::cdevSimpleService ( char * name, cdevSystem & system ) + : serviceFD(-1), + queue(), + selector(), + callback(defaultCallback, NULL), + cdevService(name, system) + { + // ********************************************************************* + // * Install the ACE_service specific flags + // ********************************************************************* + installTags(); + + // ********************************************************************* + // * Clear local variables + // ********************************************************************* + memset(&serviceFD, 0, sizeof(serviceFD)); + + // ********************************************************************* + // * Assign the value of the read file descriptor for the selector to + // * the serviceFD variable. + // ********************************************************************* + serviceFD = selector.readfd(); + } + + +// ***************************************************************************** +// * cdevSimpleService::~cdevSimpleService : +// * The destructor is protected to prevent it from being called directly. +// * The destructor performs any clean-up or shutdown operations. +// * +// * Returns nothing. +// ***************************************************************************** +cdevSimpleService::~cdevSimpleService ( void ) + { + // ********************************************************************* + // * Call flush to process all outbound messages. + // ********************************************************************* + flush(); + + // ********************************************************************* + // * Clear the file descriptors used by cdev for polling. + // ********************************************************************* + memset(&serviceFD, 0, sizeof(serviceFD)); + } + + +// ***************************************************************************** +// * cdevSimpleService::installTags : +// * Installs the tags that the service and service applications +// * will use. This function is static to allow servers to setup +// * the necessary tags without having to instanciate a cdevSimpleService object. +// ***************************************************************************** +void cdevSimpleService::installTags ( void ) + { + } + + +// ********************************************************************* +// * cdevSimpleService::getRequestObject : +// * This is the interface that cdev objects will use to obtain a +// * cdevSimpleRequestObject object. The cdevSimpleRequestObject +// * represents a combined device and message pair that is associated +// * with the cdevSimpleService. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ********************************************************************* +int cdevSimpleService::getRequestObject ( char * device, char * message, cdevRequestObject * &req) + { + req = new cdevSimpleRequestObject (device, message, system_); + return (req ? CDEV_SUCCESS : CDEV_ERROR); + } + +// ***************************************************************************** +// * cdevSimpleService::getFd +// * This function will return the list of file descriptors that the +// * cdevSimpleService is using. This will allow the file descriptors to be +// * used in global select and poll calls performed at the cdevSystem class +// * level. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int cdevSimpleService::getFd ( int * &fd, int & numFd ) + { + fd = &serviceFD; + numFd = 1; + + return CDEV_SUCCESS; + } + + +// ********************************************************************* +// * cdevSimpleService::flush : +// * This function flushes all communications buffers that the +// * service may have open. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ********************************************************************* +int cdevSimpleService::flush ( void ) + { + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * cdevSimpleService::poll : +// * This function polls the file descriptors used by the service +// * until one of them becomes active or a discrete amount of time +// * has expired. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int cdevSimpleService::poll ( void ) + { + return pend(0.0001); + } + + + +// ***************************************************************************** +// * cdevSimpleService::pend : +// * Pends until the named file descriptor (or any file descriptor +// * if fd = -1) is ready. Will pend forever if the descriptor does +// * not become active. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int cdevSimpleService::pend ( int ) + { + while(!queue.empty()) handleOneEvent(); + + // ********************************************************************* + // * Empty the contents of the cdevSelector object. + // ********************************************************************* + selector.purge(); + + return CDEV_SUCCESS; + } + + + +// ***************************************************************************** +// * cdevSimpleService::pend : +// * Pends until the named file descriptor (or any file descriptor +// * if fd = -1) is ready. Will pend for no longer than the user +// * specified number of seconds. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int cdevSimpleService::pend ( double seconds, int ) + { + cdevTimeValue sec = seconds; + cdevClock timer; + + timer.schedule(NULL, sec); + + do { + handleOneEvent(); + } while(!timer.expired() && !queue.empty()); + + // ********************************************************************* + // * Empty the contents of the cdevSelector object. + // ********************************************************************* + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * cdevSimpleService::submit : +// * This is the mechanism that the request object will use to submit a +// * message to the service. It is important to note that all of the +// * data provided to this object becomes the property of the service and +// * must not be accessed afterwords. +// ***************************************************************************** +int cdevSimpleService::submit (cdevTranNode *node, + char *device, + char *message, + cdevData *data) + { + cdevTransaction * transaction = new cdevTransaction; + cdevServiceMessage * packet; + + // ********************************************************************* + // * Populate the cdevTransaction structure with data. + // ********************************************************************* + transaction->transnum = node->transaction(); + transaction->transobj = node; + + // ********************************************************************* + // * Call trim on the device and message to remove any extra spaces. + // ********************************************************************* + trim(device); + trim(message); + + // ********************************************************************* + // * Populate the packet variable with the data. + // ********************************************************************* + + packet = new cdevServiceMessage(transaction, device, message, data); + + // ********************************************************************* + // * Place the cdevServiceMessage into the queue. + // ********************************************************************* + queue.enqueue(packet); + + // ********************************************************************* + // * Add an event to the cdevSelector object in order to trigger polling + // ********************************************************************* + selector.insertEvent(); + + return CDEV_SUCCESS; + } + + + +// ***************************************************************************** +// * cdevSimpleService::dequeue : +// * The handleOneEvent method uses this function to extract a single +// * message from the service and process it. All data objects obtained +// * through this function become the property of the caller and must +// * be deleted. +// ***************************************************************************** +int cdevSimpleService::dequeue (cdevTransaction * &transaction, + char * &device, + char * &message, + cdevData * &data) + { + int result = CDEV_ERROR; + cdevServiceMessage * packet = (cdevServiceMessage *)queue.dequeue(); + + if(packet!=NULL) + { + transaction = packet->transaction; + device = packet->device; + message = packet->message; + data = packet->data; + result = CDEV_SUCCESS; + delete packet; + } + + return result; + } + +// ***************************************************************************** +// * cdevSimpleService::enqueue : +// * The handleOneEvent method uses this function to dispatch callbacks +// * after the function has been processed. +// ***************************************************************************** +int cdevSimpleService::enqueue (int status, + cdevTransaction * trans, + char * device, + char * message, + cdevData * data) + { + cdevTranNode * node = trans?trans->transobj:NULL; + + if(node!=NULL && node->validate(trans->transnum)==CDEV_SUCCESS) + { + cdevData localData; + + // ************************************************************* + // * cdevData must be returned to the caller. + // ************************************************************* + if(node->resultData_==NULL) node->resultData_ = (data?data:&localData); + else *(node->resultData_) = (data?*data:localData); + + // ************************************************************* + // * Call the user provided callback function. + // ************************************************************* + (node->userCallback_->callbackFunction()) + (status, + node->userCallback_->userarg(), + *node->reqObj_, + *node->resultData_); + + // ************************************************************* + // * Tag the transaction as finished + // ************************************************************* + node->finished(1); + + // ************************************************************* + // * Delete the cdevTranNode if it is not permanent. + // ************************************************************* + if(!node->permanent()) delete node; + + // ************************************************************* + // * Remove the event from the selector object. + // ************************************************************* + selector.removeEvent(); + } + + // ********************************************************************* + // * Delete the components of the message. + // ********************************************************************* + if(trans != NULL) delete trans; + if(device != NULL) delete device; + if(message != NULL) delete message; + if(data != NULL) delete data; + + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * cdevSimpleService::handleOneEvent : +// * This method allows the caller to handle individual events. This handler +// * only processes one event and then returns to the caller. +// ***************************************************************************** +void cdevSimpleService::handleOneEvent ( void ) + { + cdevTransaction * transaction; + char * device; + char * message; + cdevData * data; + + if(dequeue(transaction, device, message, data)==CDEV_SUCCESS) + { + enqueue(CDEV_SUCCESS, transaction, device, message, data); + } + } + + +// ***************************************************************************** +// * cdevSimpleService::getNameServer : +// * This function should obtain the default name server for this object. +// * It does nothing for now. +// ***************************************************************************** +int cdevSimpleService::getNameServer(cdevDevice * &ns) + { + ns = 0; + return CDEV_SUCCESS; + } + diff --git a/extensions/SimpleService/cdevSimpleService.h b/extensions/SimpleService/cdevSimpleService.h new file mode 100755 index 0000000..e63a2da --- /dev/null +++ b/extensions/SimpleService/cdevSimpleService.h @@ -0,0 +1,229 @@ + +// ----------------------------------------------------------------------------- +// Copyright (c) 1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// ----------------------------------------------------------------------------- +// +// Description: +// This header file contains the class definitions for the classes +// associated with the construction of a model service. +// +// Author: Walt Akers +// +// ----------------------------------------------------------------------------- + +#if !defined (_CDEV_SIMPLE_SERVICE_H_) +#define _CDEV_SIMPLE_SERVICE_H_ + +#include +#include +#include +#include + +// **************************************************************************** +// * Service Loader: +// * The first step in building a new service is to construct a service +// * loader function. This function will allow cdev to dynamically +// * initialize a service by name. +// * +// * The function should adhere to the following naming convention... +// * cdevService * newXXX (char * name, cdevSystem * system); +// * +// * The 'XXX' should be replaced with the name of the service +// * class. +// * +// * The function should also be declared as 'extern "C"' to allow it +// * to be called and loaded from within an external shared library module. +// * +// * This function serves only to construct a new instance of the +// * specified service, and return it to the instanciating mechanism. +// ***************************************************************************** +// extern "C" cdevService *newcdevSimpleService ( char * name, cdevSystem * system ); + +// ***************************************************************************** +// * This structure is used to maintain a cdevTranNode class and its matching +// * transaction number. The transaction number will be used to validate +// * the cdevTranNode later. +// ***************************************************************************** +typedef struct + { + int transnum; + cdevTranNode * transobj; + } cdevTransaction; + + +// ****************************************************************************** +// * This is a structure that is used to store the components that are placed in +// * the queues. +// ****************************************************************************** +class cdevServiceMessage +{ +public: + cdevTransaction * transaction; + char * device; + char * message; + cdevData * data; + + cdevServiceMessage(cdevTransaction *Transaction=NULL, + char *Device=NULL, + char *Message=NULL, + cdevData *Data=NULL) + : transaction(Transaction), + device(Device), + message(Message), + data(Data) + { + } + }; + + + +// ***************************************************************************** +// * cdevSimpleService: +// * This is class provides the mechanisms that the cdev system will use +// * to communicate with the model service. +// ***************************************************************************** +class cdevSimpleService : public cdevService +{ +friend class cdevSimpleRequestObject; + +public: + // ********************************************************************* + // * cdevSimpleService::cdevSimpleService : + // * This constructor is responsible for performing all service + // * initialization. + // ********************************************************************* + cdevSimpleService ( char * name, cdevSystem & system ); + + // ********************************************************************* + // * cdevSimpleService::~cdevSimpleService : + // * The destructor is protected to prevent it from being called + // * directly. The destructor performs any clean-up or shutdown + // * operations. + // * + // * Returns nothing. + // ********************************************************************* + ~cdevSimpleService ( void ); + + // ********************************************************************* + // * cdevSimpleService::installTags : + // * Installs the tags that the service and service applications + // * will use. This function is static to allow servers to setup + // * the necessary tags without having to instanciate a + // * cdevSimpleService object. + // ********************************************************************* + void installTags ( void ); + + // ********************************************************************* + // * cdevSimpleService::getRequestObject : + // * This is the interface that cdev objects will use to obtain a + // * cdevSimpleRequestObject object. The cdevSimpleRequestObject + // * represents a combined device and message pair that is associated + // * with the cdevSimpleService. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int getRequestObject (char *, char *, cdevRequestObject * &); + + // ********************************************************************* + // * cdevSimpleService::getFd + // * This function will return the list of file descriptors that the + // * cdevSimpleService is using. This will allow the file + // * descriptors to be used in global select and poll calls performed + // * at the cdevSystem class level. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int getFd ( int * &fd, int & numFd ); + + // ********************************************************************* + // * cdevSimpleService::flush : + // * This function flushes all communications buffers that the + // * service may have open. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int flush ( void ); + + // ********************************************************************* + // * cdevSimpleService::poll : + // * This function polls the file descriptors used by the service + // * until one of them becomes active or a discrete amount of time + // * has expired. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int poll ( void ); + + // ********************************************************************* + // * cdevSimpleService::pend : + // * Pends until the named file descriptor (or any file descriptor + // * if fd = -1) is ready. Will pend for no longer than the user + // * specified number of seconds. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int pend ( double seconds, int = -1); + + // ********************************************************************* + // * cdevSimpleService::pend : + // * Pends until the named file descriptor (or any file descriptor + // * if fd = -1) is ready. Will pend forever if the descriptor does + // * not become active. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + int pend ( int = -1); + + // ********************************************************************* + // * cdevSimpleService::submit : + // * This is the mechanism that the request object will use to submit + // * a message to the service. It is important to note that all of + // * the data provided to this object becomes the property of the + // * service and must not be accessed afterwords. + // ********************************************************************* + virtual int submit (cdevTranNode *, char *, char *, cdevData *); + + // ********************************************************************* + // * cdevSimpleService::dequeue : + // * The handleOneEvent method uses this function to extract a single + // * message from the service and process it. All data objects + // * obtained through this function become the property of the caller + // * and must be deleted. + // ********************************************************************* + virtual int dequeue (cdevTransaction * &, char * &, char * &, cdevData * &); + + // ********************************************************************* + // * cdevSimpleService::enqueue : + // * The handleOneEvent method uses this function to dispatch + // * callbacks after the function has been processed. + // ********************************************************************* + virtual int enqueue (int, cdevTransaction *, char *, char *, cdevData *); + + // ********************************************************************* + // * cdevSimpleService::handleOneEvent : + // * This method allows the caller to handle individual events. This + // * handler only processes one event and then returns to the caller. + // ********************************************************************* + virtual void handleOneEvent ( void ); + + // ********************************************************************* + // * cdevSimpleService::getNameServer : + // * This function should obtain the default name server for this + // * object. It does nothing for now. + // ********************************************************************* + int getNameServer(cdevDevice * &ns); + + +private: + FifoQueue queue; + int serviceFD; + cdevSelector selector; + cdevCallback callback; +}; + +#endif /* _CDEV_SIMPLE_SERVICE_H_ */ diff --git a/extensions/SimpleService/cdevTranNode.cc b/extensions/SimpleService/cdevTranNode.cc new file mode 100755 index 0000000..cd6affd --- /dev/null +++ b/extensions/SimpleService/cdevTranNode.cc @@ -0,0 +1,145 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// This header file contains the class definitions for the classes +// associated with a cdevTranNode. The cdevTranNode is an extension +// of the cdevTranObj. It provides a mechanism for tracking allocated +// and unallocated cdevTranObj objects and prevents inadvertent writes +// to unallocated memory. +// +// Author: Walt Akers +// +// Revision History: +// cdevTranNode.cc,v +// Revision 1.1 1996/11/21 18:22:27 akers +// Non-Server Oriented Service +// +// Revision 1.1 1996/04/30 15:37:41 akers +// Simple CDEV Service +// +// Revision 1.1.1.1 1996/02/28 16:36:20 akers +// Initial release of support for ACE Services +// +// Revision 2.0 1995/10/04 19:21:37 withers +// New CVS repository +// +// Revision 1.1.1.1 1995/10/04 18:45:08 bickley +// CVS start of high-level apps +// +// Revision 1.1.1.1 1995/09/15 17:15:30 withers +// MODEL SERVICE SOURCE +// +// +#include + +// ***************************************************************************** +// * Static class members requiring initialization. +// ***************************************************************************** +int cdevTranNode::count = 0; +cdevTranNode * cdevTranNode::freeList = NULL; +cdevTranNode * cdevTranNode::activeList = NULL; +int cdevTranNode::initialized = 1; + +// ***************************************************************************** +// * cdevTranNode::new : +// * This is the internal mechanism that is used to allocate new cdevTranNode +// * objects. If an object is already available on the freelist, this +// * function will allocate from that list to the activeList. Otherwise, a +// * block of cdevTranNode objects will be allocated to repopulate the +// * freeList first. +// ***************************************************************************** +void * cdevTranNode::operator new ( size_t ) + { + cdevTranNode * node; + int i; + + if(freeList==NULL) + { + freeList = ::new cdevTranNode[16]; + for(i=0; i<16; i++) + { + freeList[i].next = (i<15) ? &freeList[i+1] : NULL; + freeList[i].allocated = FALSE; + freeList[i].finished_ = FALSE; + freeList[i].transaction_ = 0; + } + cdevTranNode::count-=16; + } + node = freeList; + freeList = node->next; + + node->allocated = TRUE; + node->next = activeList; + activeList = node; + + return node; + } + +// ***************************************************************************** +// * cdevTranNode::delete : +// * This function is used to return an allocated cdevTranNode to the +// * freeList for later allocation to another caller. This function will +// * clear the transaction flag and will clear the allocated flag. +// ***************************************************************************** +void cdevTranNode::operator delete ( void * ptr ) + { + cdevTranNode * node = activeList; + cdevTranNode * prev = NULL; + + if(ptr != NULL) + { + while(node!=NULL && node!=(cdevTranNode *)ptr) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + if(prev) prev->next = node->next; + else activeList = node->next; + } + + node = (cdevTranNode *)ptr; + node->allocated = FALSE; + node->finished_ = FALSE; + node->transaction_ = 0; + node->next = freeList; + freeList = node; + } + } + +// ***************************************************************************** +// * cdevTranNode::find: +// * Allows the caller to locate a cdevTranNode using the transaction number. +// ***************************************************************************** +cdevTranNode * cdevTranNode::find ( int Transaction ) + { + cdevTranNode * node = activeList; + while(node!=NULL && node->transaction_ != Transaction) + { + node = node->next; + } + return node; + } + +// ***************************************************************************** +// * cdevTranNode::init: +// * Allows the caller to initialize static members of the cdevTranNode class +// ***************************************************************************** +void cdevTranNode::init ( void ) + { + if(!initialized) + { + count = 0; + freeList = NULL; + activeList = NULL; + initialized = 1; + } + } diff --git a/extensions/SimpleService/cdevTranNode.h b/extensions/SimpleService/cdevTranNode.h new file mode 100755 index 0000000..cc4c0cb --- /dev/null +++ b/extensions/SimpleService/cdevTranNode.h @@ -0,0 +1,165 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// This header file contains the class definitions for the classes +// associated with a cdevTranNode. The cdevTranNode is an extension +// of the cdevTranObj. It provides a mechanism for tracking allocated +// and unallocated cdevTranObj objects and prevents inadvertent writes +// to unallocated memory. +// +// Author: Walt Akers +// +// +// +#ifndef _CDEV_TRAN_NODE_H_ +#define _CDEV_TRAN_NODE_H_ + +#include + +#ifndef TRUE + #define TRUE 1 + #define FALSE 0 +#endif + +class cdevTranNode : public cdevTranObj +{ +private: + static int count; + static cdevTranNode * freeList; + static cdevTranNode * activeList; + static int initialized; + + cdevTranNode * next; + int allocated; + +protected: + int finished_; + int permanent_; + int transaction_; + +public: + cdevTranNode ( void ); + cdevTranNode ( cdevSystem*, cdevRequestObject*, cdevData*, cdevCallback*); + ~cdevTranNode( void ); + + void * operator new ( size_t size ); + void operator delete ( void * ptr ); + + int validate ( int Transaction ); + void transaction ( int Transaction ); + int transaction ( void ); + void finished ( int Finished ); + int finished ( void ); + void permanent ( int Permanent ); + int permanent ( void ); + + static cdevTranNode * find ( int Transaction ); + static void init ( void ); +}; + +// ***************************************************************************** +// * cdevTranNode : +// * Allocates a cdevTranNode with no contents. +// ***************************************************************************** +inline cdevTranNode::cdevTranNode ( void ) + : cdevTranObj(), finished_(FALSE), permanent_(FALSE) + { + if(!initialized) init(); + transaction_ = count++; + disableDeleteCbk(); + } + +// ***************************************************************************** +// * cdevTranNode : +// * Allocates a cdevTranNode populated with the required data values. +// ***************************************************************************** +inline cdevTranNode::cdevTranNode ( cdevSystem * sys, cdevRequestObject *req, + cdevData * data, cdevCallback * callback ) + : cdevTranObj(sys, req, data, callback), finished_(FALSE), permanent_(FALSE) + { + if(!initialized) init(); + transaction_ = count++; + disableDeleteCbk(); + } + +// ***************************************************************************** +// * ~cdevTranNode: +// * Deletes the cdevTranNode object. +// ***************************************************************************** +inline cdevTranNode::~cdevTranNode ( void ) + { + } + +// ***************************************************************************** +// * cdevTranNode::validate: +// * Allows the user to verify that the cdevTranNode that he has a pointer +// * to, corresponds to the specified Transaction number. +// ***************************************************************************** +inline int cdevTranNode::validate ( int Transaction ) + { + return (allocated==TRUE && transaction_==Transaction)?CDEV_SUCCESS:CDEV_NOTFOUND; + } + +// ***************************************************************************** +// * cdevTranNode::transaction: +// * Allows the caller to specify a new transaction number. +// ***************************************************************************** +inline void cdevTranNode::transaction ( int Transaction ) + { + transaction_ = Transaction; + } + + +// ***************************************************************************** +// * cdevTranNode::transaction: +// * Allows the caller to obtain the transaction number. +// ***************************************************************************** +inline int cdevTranNode::transaction ( void ) + { + return transaction_; + } + +// ***************************************************************************** +// * cdevTranNode::finished: +// * Allows the caller to set the finished flag. +// ***************************************************************************** +inline void cdevTranNode::finished ( int Finished ) + { + finished_ = Finished?TRUE:FALSE; + } + +// ***************************************************************************** +// * cdevTranNode::finished: +// * Allows the caller to read the contents of the finished flag. +// ***************************************************************************** +inline int cdevTranNode::finished ( void ) + { + return finished_; + } + +// ***************************************************************************** +// * cdevTranNode::permanent: +// * Allows the caller to set the permanent flag. +// ***************************************************************************** +inline void cdevTranNode::permanent ( int Permanent ) + { + permanent_ = Permanent?TRUE:FALSE; + } + +// ***************************************************************************** +// * cdevTranNode::permanent: +// * Allows the caller to read the contents of the permanent flag. +// ***************************************************************************** +inline int cdevTranNode::permanent ( void ) + { + return permanent_; + } + +#endif /* _CDEV_TRAN_NODE_H_ */ diff --git a/extensions/SimpleService/example/Makefile b/extensions/SimpleService/example/Makefile new file mode 100755 index 0000000..a615042 --- /dev/null +++ b/extensions/SimpleService/example/Makefile @@ -0,0 +1,76 @@ +ARCH = hpux-sl +include $(CDEV)/examples/Makefile.common + +SRCROOT = $(CDEV)/extensions/cdevGenericServer +CDEVSHOBJ = /usr/user4/mccops/lib/$(TARGETDIR) +APPNAME = "CDEV Sample Service" + +LIBDIR = $(CDEVLIB) +INCDIR = $(SRCROOT)/include +LIBS = -L$(LIBDIR) -lSimpleService \ + -L$(CDEVLIB) -lcdev \ + -ly -ll -L/lib -lm + +LINKLIBS = -L$(LIBDIR) -lSimpleService\ + -ly -ll -L/lib -lm + +CLASS_INCLUDES = -I./ -I$(INCDIR) -I$(CDEV)/extensions/SimpleService +CXXEXTRA = -pta $(EPICSINCLUDES) $(ACE_INCLUDES) $(CLASS_INCLUDES) + +SRCS = SampleService.cc + +OBJS = SampleService.o + +% : %.cc + @rm -f $@ + @echo "=> $(CXX) $< -o $@" + @$(CXX) $(CXXFLAGS) $(CXXEXTRA) $< -o $@ -L$(ACE_LIBDIR) $(ACE_LIBS) + +ifeq ($(SHOBJ), YES) +OUTPUTLIB = SampleService.so +targets: buildingService $(CDEVSHOBJ)/$(CDEVVERSION)/SampleService.so + +else +OUTPUTLIB = libSampleService.a +targets: buildingService $(CDEV)/lib/$(TARGETDIR)/libSampleService.a + +endif + +buildingService: + @echo "BUILDING LIBRARY \"$(OUTPUTLIB)\"..." + +objClean : + @echo "" + @echo "=> Removing old object files prior to building library" + @rm -rf $(OBJS) + +$(CDEVSHOBJ)/$(CDEVVERSION)/SampleService.so : $(OBJS) $(SRCS) + @rm -f $@ + @echo "=> Building shared object $@" + @echo " => Pleasuring templates for $@" + @echo "int main() {return 0; }" >dummy.cc + @$(CXX) $(CXXFLAGS) $(CXXEXTRA) dummy.cc $(SRCS) -Wl,+s -ptr./ptSampleService -ptr./ptrepository $(LIBS) + @rm -rf a.out dummy.* + @if test -f ./ptSampleService/*.o; \ + then \ + echo " => Linking $@ from objects and template objects"; \ + $(CXX) -b -o $@ $(OBJS) ptSampleService/*.o $(LINKLIBS); \ + else \ + echo " => Linking $@ from objects"; \ + $(CXX) -b -o $@ $(OBJS) $(LINKLIBS); \ + fi + @echo " => $@ finished" + +$(CDEV)/lib/$(TARGETDIR)/libSampleService.a : hail buildingService objClean $(OBJS) + @rm -f $@ + @echo "=> Building archive library $@" + @echo " => Linking $@ from objects" + @ar ruv libSampleService.a $(OBJS) + @chmod a+r libSampleService.a + @echo " => $@ finished" + +clean: + @echo "=> Sample Service" + @echo " => Removing old objects and binaries" + @rm -rf $(OBJS) $(CDEVSHOBJ)/$(TARGETDIR)/SampleService.so a.out *.o *~ core ptrepository ptSampleService + @echo " => Done" diff --git a/extensions/SimpleService/example/Sample.ddl b/extensions/SimpleService/example/Sample.ddl new file mode 100755 index 0000000..e899cef --- /dev/null +++ b/extensions/SimpleService/example/Sample.ddl @@ -0,0 +1,62 @@ +service ca + { + tags {PV, READONLY} + } + +service Sample + { + tags {server} + } + +class BPM + { + verbs {get, set, monitorOn, monitorOff} + attributes + { + attrib0 ca {PV = <>.VAL}; + attrib1 ca {PV = <>.VAL}; + attrib2 ca {PV = <>.VAL}; + attrib3 ca {PV = <>.VAL}; + attrib4 ca {PV = <>.VAL}; + attrib5 ca {PV = <>.VAL}; + attrib6 ca {PV = <>.VAL}; + attrib7 ca {PV = <>.VAL}; + attrib8 ca {PV = <>.VAL}; + attrib9 ca {PV = <>.VAL}; + } +} + +class Samples + { + verbs {get, set, monitorOn, monitorOff} + attributes + { + default Sample; + servers Sample; + attrib0 Sample; + attrib1 Sample; + attrib2 Sample; + attrib3 Sample; + attrib4 Sample; + attrib5 Sample; + attrib6 Sample; + attrib7 Sample; + attrib8 Sample; + attrib9 Sample; + } + messages + { + disconnect Sample; + } + } + + +BPM : + IPM1S01, IPM1S02, IPM1S03, IPM1S05, IPM1S07, + IPM1S08, IPM1S09 +; + +Samples : + device0, device1, device2, device3, device4, + device5, device6, device7, device8, device9 +; diff --git a/extensions/SimpleService/example/SampleService.cc b/extensions/SimpleService/example/SampleService.cc new file mode 100755 index 0000000..c5660cc --- /dev/null +++ b/extensions/SimpleService/example/SampleService.cc @@ -0,0 +1,32 @@ +#include "SampleService.h" + +cdevService * newSampleService ( char * name, cdevSystem * system ) + { + return new SampleService(name, *system); + } + + +SampleService::SampleService ( char * name, cdevSystem & system ) + : cdevSimpleService(name, system), var(0) + { + } + +SampleService::~SampleService ( void ) + { + } + +void SampleService::handleOneEvent ( void ) + { + cdevTransaction * transaction; + char * device; + char * message; + cdevData * data; + + if(dequeue(transaction, device, message, data)==CDEV_SUCCESS) + { + data->insert("device", device); + data->insert("message", message); + data->insert("value", var++); + enqueue(CDEV_SUCCESS, transaction, device, message, data); + } + } diff --git a/extensions/SimpleService/example/SampleService.h b/extensions/SimpleService/example/SampleService.h new file mode 100755 index 0000000..f891522 --- /dev/null +++ b/extensions/SimpleService/example/SampleService.h @@ -0,0 +1,13 @@ +#include + +extern "C" cdevService *newSampleService ( char * name, cdevSystem * system ); + +class SampleService : public cdevSimpleService +{ +int var; + +public: + SampleService ( char * name, cdevSystem & system ); + virtual ~SampleService ( void ); + virtual void handleOneEvent( void ); +}; diff --git a/extensions/SimpleService/g++ b/extensions/SimpleService/g++ new file mode 100644 index 0000000..4fd476b --- /dev/null +++ b/extensions/SimpleService/g++ @@ -0,0 +1 @@ +=> @@echo = -o libSimpleService.sl;rm -rf /usr/local/i386-glibc22-linux/cdev-1.7.2/lib/Linux/libSimpleService.sl; mkdir -p /usr/local/i386-glibc22-linux/cdev-1.7.2/lib/Linux; g++ -shared libSimpleService.sl diff --git a/extensions/cdevGenericServer/Makefile b/extensions/cdevGenericServer/Makefile new file mode 100755 index 0000000..fafd21a --- /dev/null +++ b/extensions/cdevGenericServer/Makefile @@ -0,0 +1,143 @@ +ifneq ("$(VERBOSE)", "YES") + MAKE := $(MAKE) -s VERBOSE=NO +endif + +BASEDIR = $(shell pwd) +BASEINCLUDES = $(BASEDIR)/include +BASEBIN = $(BASEDIR)/bin +BASELIB = $(BASEDIR)/lib +HEADERS = *.h *.i + +SRCONLY_DIRS = $(BASEDIR)/cdevClient\ + $(BASEDIR)/cdevContextMap\ + $(BASEDIR)/cdevMonitorTable\ + $(BASEDIR)/cdevPacket\ + $(BASEDIR)/cdevServer\ + $(BASEDIR)/cdevTagMap\ + $(BASEDIR)/common\ + +LIB_DIRS = $(BASEDIR)/cdevReactor\ + $(BASEDIR)/NameServer/src\ + $(BASEDIR)/NameServer/cdev\ + $(BASEDIR)/lib + +UTIL_DIRS = $(BASEDIR)/NameServer/dumpServer + +EXAMPLE_DIRS = $(BASEDIR)/NameServer/examples\ + $(BASEDIR)/example + +TEST_DIRS = $(BASEDIR)/tests\ + $(BASEDIR)/cdevReactor/TimerTest\ + $(BASEDIR)/cdevReactor/ServerTest + +DOC_DIRS = $(BASEDIR)/doc\ + +HEADER_DIRS = $(BASEDIR)/cdevReactor\ + $(BASEDIR)/cdevTagMap\ + $(BASEDIR)/cdevContextMap\ + $(BASEDIR)/cdevMonitorTable\ + $(BASEDIR)/cdevPacket\ + $(BASEDIR)/common\ + $(BASEDIR)/cdevClient\ + $(BASEDIR)/cdevServer\ + $(BASEDIR)/NameServer/src\ + $(BASEDIR)/NameServer/cdev + +CLEAN_DIRS = $(SRCONLY_DIRS)\ + $(LIB_DIRS)\ + $(UTIL_DIRS)\ + $(EXAMPLE_DIRS)\ + $(TEST_DIRS)\ + $(DOC_DIRS) + +PURGE_DIRS = $(SRCONLY_DIRS)\ + $(BASEDIR)/cdevReactor\ + $(BASEDIR)/NameServer/src\ + $(BASEDIR)/NameServer/cdev\ + $(BASEDIR)/liteClient\ + $(UTIL_DIRS)\ + $(EXAMPLE_DIRS)\ + $(TEST_DIRS)\ + $(DOC_DIRS) + +all: directories headers archive shared utils + +directories: + @echo "=> Creating directories for binary files" + @mkdir -p $(BASEBIN) + @mkdir -p $(BASELIB) + @echo "<= Done...\n" + +headers: + @echo "=> Linking header files to include directory" + @for dir in $(HEADER_DIRS); \ + do \ + cd $$dir; \ + for file in $(HEADERS); \ + do \ + if test -f $$file; then cp $$dir/$$file $(BASEINCLUDES)/$$file; fi; \ + done \ + done + @cp $(BASEDIR)/include/makeinclude/Makefile.lib $(BASEDIR)/lib/Makefile + @echo "<= Done...\n" + +archive: + @echo "=> Building archive version of libraries" + @for dir in $(LIB_DIRS); \ + do \ + $(MAKE) -C $$dir SHOBJ=NO; \ + done + @echo "<= Done...\n" + +shared: + @echo "=> Building shared version of libraries" + @for dir in $(LIB_DIRS); \ + do \ + $(MAKE) -C $$dir SHOBJ=YES; \ + done + @echo "<= Done...\n" + +utils: + @echo "=> Building utility programs" + @for dir in $(UTIL_DIRS); \ + do \ + $(MAKE) -C $$dir SHOBJ=YES; \ + done + @echo "<= Done...\n" + +examples: + @echo "=> Building example programs" + @for dir in $(EXAMPLE_DIRS); \ + do \ + $(MAKE) -C $$dir SHOBJ=YES; \ + done + @echo "<= Done...\n" + +apps: + @echo "=> Building test programs" + @for dir in $(TEST_DIRS); \ + do \ + $(MAKE) -C $$dir SHOBJ=YES; \ + done + @echo "<= Done...\n" + +clean: + @echo "=> Cleaning CDEV Generic Server Directories" + @for dir in $(CLEAN_DIRS); \ + do \ + $(MAKE) -C $$dir clean; \ + done + @echo "<= Done...\n" + +purge: + @echo "=> Purging CDEV Generic Server Directories" + @echo " => Removing links to header files" + @rm -rf $(BASEINCLUDES)/*.h $(BASEINCLUDES)/*.i + @echo " Done..." + @for dir in $(PURGE_DIRS); \ + do \ + $(MAKE) -C $$dir purge; \ + done + @rm -rf $(BASEDIR)/lib + @rm -rf $(BASEDIR)/bin + @echo "<= Done...\n" diff --git a/extensions/cdevGenericServer/NMakefile.mak b/extensions/cdevGenericServer/NMakefile.mak new file mode 100644 index 0000000..aafc97d --- /dev/null +++ b/extensions/cdevGenericServer/NMakefile.mak @@ -0,0 +1,135 @@ +!IF "$(VERBOSE)" != "YES" +MAKE = $(MAKE) -s VERBOSE=NO +!ENDIF + +BASEDIR = $(MAKEDIR) +BASEINCLUDES = $(BASEDIR)\include +BASEBIN = $(BASEDIR)\bin +BASELIB = $(BASEDIR)\lib +HEADERS = dir\*.h dir\*.i + +SRCONLY_DIRS = $(BASEDIR)\cdevClient\ + $(BASEDIR)\cdevContextMap\ + $(BASEDIR)\cdevMonitorTable\ + $(BASEDIR)\cdevPacket\ + $(BASEDIR)\cdevServer\ + $(BASEDIR)\cdevTagMap\ + $(BASEDIR)\common\ + +LIB_DIRS = $(BASEDIR)\cdevReactor\ + $(BASEDIR)\NameServer\src\ + $(BASEDIR)\NameServer\cdev\ + $(BASEDIR)\lib\ + $(BASEDIR)\liteClient + +UTIL_DIRS = $(BASEDIR)\NameServer\dumpServer + +EXAMPLE_DIRS = $(BASEDIR)\NameServer\examples\ + $(BASEDIR)\example + +TEST_DIRS = $(BASEDIR)\tests\ + $(BASEDIR)\cdevReactor\TimerTest\ + $(BASEDIR)\cdevReactor\ServerTest + +DOC_DIRS = $(BASEDIR)\doc\ + +HEADER_DIRS = $(BASEDIR)\cdevReactor\ + $(BASEDIR)\cdevTagMap\ + $(BASEDIR)\cdevContextMap\ + $(BASEDIR)\cdevMonitorTable\ + $(BASEDIR)\cdevPacket\ + $(BASEDIR)\common\ + $(BASEDIR)\cdevClient\ + $(BASEDIR)\cdevServer\ + $(BASEDIR)\NameServer\src\ + $(BASEDIR)\NameServer\cdev + +CLEAN_DIRS = $(SRCONLY_DIRS)\ + $(LIB_DIRS)\ + $(UTIL_DIRS)\ + $(EXAMPLE_DIRS)\ + $(TEST_DIRS)\ + $(DOC_DIRS) + +all: hail directories headers shared utils fairwell + +everything: hail directories headers shared utils examples apps other fairwell + +hail: + @echo --------------------------------------------------------------- + @echo Building CDEV Generic Server for Target : $(ARCH) + @echo --------------------------------------------------------------- + +fairwell: + @echo --------------------------------------------------------------- + @echo CDEV Generic Server has been built for Target : $(ARCH) + @echo --------------------------------------------------------------- + +directories: + @echo =^> Creating directories for binary files + -@if not exist $(BASEBIN) mkdir $(BASEBIN) + -@if not exist $(BASELIB) mkdir $(BASELIB) + -@copy $(BASEINCLUDES)\makeinclude\NMakefile.lib $(BASELIB)\NMakefile.mak + @echo ^<= Done... + +headers: + @echo =^> Copying header files to include directory + -@for %d in ($(HEADER_DIRS)) do @for %f in ($(HEADERS:dir=%d)) do @copy %f $(BASEINCLUDES) > nul + @echo ^<= Done... + +archives: + @echo =^> Building archive version of libraries + @for %d in ($(LIB_DIRS)) do @cd %d & $(MAKE) /NOLOGO SHOBJ=NO /f NMakefile.mak + @echo <^= Done... + +shared: + @echo =^> Building shared version of libraries + @for %d in ($(LIB_DIRS)) do @cd %d & $(MAKE) /NOLOGO SHOBJ=YES /f NMakefile.mak + @echo ^<= Done... + +utils: + @echo =^> Building utility programs + @for %d in ($(UTIL_DIRS)) do @cd %d & $(MAKE) /NOLOGO SHOBJ=YES /f NMakefile.mak + @echo ^<= Done... + +examples: + @echo =^> Building example programs + @for %d in ($(EXAMPLE_DIRS)) do @cd %d & $(MAKE) /NOLOGO SHOBJ=YES /f NMakefile.mak + @echo ^<= Done... + +apps: + @echo =^> Building test programs + @for %d in ($(TEST_DIRS)) do @cd %d & $(MAKE) /NOLOGO SHOBJ=YES /f NMakefile.mak + @echo ^<= Done... + +other: + @echo =^> Building miscellaneous applications and libraries + @for %d in ($(SRCONLY_DIRS)) do @cd %d & $(MAKE) /NOLOGO SHOBJ=YES /f NMakefile.mak + @echo ^<= Done... + +clean: + @echo =^> Cleaning CDEV Generic Server Directories + @for %d in ($(CLEAN_DIRS)) do @if exist %d\NMakefile.mak cd %d & $(MAKE) /NOLOGO /f NMakefile.mak clean + @echo ^<= Done... + +purge: + @echo =^> Purging CDEV Generic Server Directories + @echo ^ ^ ^ =^> Removing header files + -@for %f in ($(BASEINCLUDES)\*.h $(BASEINCLUDES)\*.i) do @erase %f + @echo ^ ^ ^ ^ ^ ^ Done... + @for %d in ($(CLEAN_DIRS)) do @if exist %d\NMakefile.mak cd %d & $(MAKE) /NOLOGO /f NMakefile.mak purge + -@if exist $(BASEDIR)\lib rmdir /s /q $(BASEDIR)\lib + -@if exist $(BASEDIR)\bin rmdir /s /q $(BASEDIR)\bin + @echo ^<= Done... + +!IF "$(SUBTARGETDIR)" == "" +subtarget : + -@echo SUBTARGETDIR variable must be defined to build subtargets +!ELSE +!IF "$(SUBTARGET)" == "" +SUBTARGET = all +!ENDIF +subtarget : + @cd $(SUBTARGETDIR) + @$(MAKE) /NOLOGO /f NMakefile.mak $(SUBTARGET) +!ENDIF diff --git a/extensions/cdevGenericServer/NameServer/Makefile b/extensions/cdevGenericServer/NameServer/Makefile new file mode 100755 index 0000000..f2ab9ce --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/Makefile @@ -0,0 +1,21 @@ +BASEDIR = $(shell pwd) +BUILDDIRS = $(BASEDIR)/src $(BASEDIR)/cdev $(BASEDIR)/dumpServer $(BASEDIR)/examples +CLEANDIRS = $(BASEDIR)/src $(BASEDIR)/cdev $(BASEDIR)/dumpServer $(BASEDIR)/examples + +all: + @for dir in $(BUILDDIRS); \ + do \ + $(MAKE) -C $$dir; \ + done + +clean: + @for dir in $(CLEANDIRS); \ + do \ + $(MAKE) -C $$dir clean; \ + done + +purge: + @for dir in $(CLEANDIRS); \ + do \ + $(MAKE) -C $$dir purge; \ + done diff --git a/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rnsRequestObject.o b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rnsRequestObject.o new file mode 100644 index 0000000..3f8bd9b Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rnsRequestObject.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rnsService.o b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rnsService.o new file mode 100644 index 0000000..75f9522 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rnsService.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcCallback.o b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcCallback.o new file mode 100644 index 0000000..09dc0ba Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcCallback.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcCbk.o b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcCbk.o new file mode 100644 index 0000000..f3846fd Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcCbk.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcClient.o b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcClient.o new file mode 100644 index 0000000..099ba28 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcClient.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcData.o b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcData.o new file mode 100644 index 0000000..0ae5959 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcData.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcDataEntry.o b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcDataEntry.o new file mode 100644 index 0000000..56cc369 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcDataEntry.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcDataStreamer.o b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcDataStreamer.o new file mode 100644 index 0000000..e755104 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcDataStreamer.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcHSlist.o b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcHSlist.o new file mode 100644 index 0000000..15884f9 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcHSlist.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcHash.o b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcHash.o new file mode 100644 index 0000000..2b27f15 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcHash.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcHashable.o b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcHashable.o new file mode 100644 index 0000000..bb43093 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcHashable.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcNetData.o b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcNetData.o new file mode 100644 index 0000000..7bcf541 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcNetData.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcSlist.o b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcSlist.o new file mode 100644 index 0000000..cef9632 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcSlist.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcStreamable.o b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcStreamable.o new file mode 100644 index 0000000..04bf964 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcStreamable.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcUdpClient.o b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcUdpClient.o new file mode 100644 index 0000000..29fe082 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.obj/Linux/rsvcUdpClient.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/cdev_test.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/cdev_test.o new file mode 100644 index 0000000..d415011 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/cdev_test.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rnsRequestObject.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rnsRequestObject.o new file mode 100644 index 0000000..f80182f Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rnsRequestObject.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rnsService.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rnsService.o new file mode 100644 index 0000000..410b162 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rnsService.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcCallback.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcCallback.o new file mode 100644 index 0000000..65bd721 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcCallback.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcCbk.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcCbk.o new file mode 100644 index 0000000..0defab1 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcCbk.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcClient.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcClient.o new file mode 100644 index 0000000..0b6275a Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcClient.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcData.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcData.o new file mode 100644 index 0000000..e6353a3 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcData.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcDataEntry.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcDataEntry.o new file mode 100644 index 0000000..507cd3d Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcDataEntry.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcDataStreamer.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcDataStreamer.o new file mode 100644 index 0000000..a04fc6b Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcDataStreamer.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcHSlist.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcHSlist.o new file mode 100644 index 0000000..6a79aca Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcHSlist.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcHash.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcHash.o new file mode 100644 index 0000000..9182008 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcHash.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcHashable.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcHashable.o new file mode 100644 index 0000000..0307f76 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcHashable.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcNetData.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcNetData.o new file mode 100644 index 0000000..3f747a9 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcNetData.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcSlist.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcSlist.o new file mode 100644 index 0000000..ec1e9be Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcSlist.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcStreamable.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcStreamable.o new file mode 100644 index 0000000..5b462cb Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcStreamable.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcUdpClient.o b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcUdpClient.o new file mode 100644 index 0000000..86bdb28 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/cdev/.shobj/Linux/rsvcUdpClient.o differ diff --git a/extensions/cdevGenericServer/NameServer/cdev/Makefile b/extensions/cdevGenericServer/NameServer/cdev/Makefile new file mode 100755 index 0000000..e904f54 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/Makefile @@ -0,0 +1,83 @@ +ARCH = OS +SHOBJ = YES +APPNAME = "Name Server Interface for CDEV" + +include ../../include/makeinclude/Makefile.$(ARCH) + +TEMPLINKS = rsvcSlist.cc \ + rsvcHSlist.cc \ + rsvcHash.cc \ + rsvcDataStreamer.cc \ + rsvcDataEntry.cc \ + rsvcData.cc \ + rsvcNetData.cc \ + rsvcCbk.cc \ + rsvcHashable.cc \ + rsvcStreamable.cc \ + rsvcCallback.cc \ + rsvcClient.cc \ + rsvcUdpClient.cc +OBJS = $(OBJDIR)/rsvcSlist.o \ + $(OBJDIR)/rsvcHSlist.o \ + $(OBJDIR)/rsvcHash.o \ + $(OBJDIR)/rsvcDataStreamer.o \ + $(OBJDIR)/rsvcDataEntry.o \ + $(OBJDIR)/rsvcData.o \ + $(OBJDIR)/rsvcNetData.o \ + $(OBJDIR)/rsvcCbk.o \ + $(OBJDIR)/rsvcHashable.o \ + $(OBJDIR)/rsvcStreamable.o \ + $(OBJDIR)/rsvcCallback.o \ + $(OBJDIR)/rsvcClient.o \ + $(OBJDIR)/rsvcUdpClient.o \ + $(OBJDIR)/rnsService.o \ + $(OBJDIR)/rnsRequestObject.o + +ifeq ($(SHOBJ),YES) + TARGETS = $(CDEVSHOBJ)/$(CDEVVERSION)/rnsService.so $(BASEBIN)/cdev_test +else + TARGETS = $(BASELIB)/librnsService.a +endif + +CXXINCLUDES = -I./ +LIBS = -L$(CDEVLIB) -lcdevReactor $(CDEVLIBS) $(OSLIBS) +BINARIES = $(BASEBIN)/cdev_test $(BASELIB)/rnsService.so $(BASELIB)/librnsService.a $(TEMPLINKS) + +targets: $(TEMPLINKS) $(TARGETS) + +$(TEMPLINKS) : + @cp $^ $@ + +$(BASEBIN)/cdev_test: $(OBJDIR)/cdev_test.o + $(LINK.cc) $^ $(LIBS) -o $@ + +$(BASELIB)/librnsService.a: $(OBJS) + $(LINK.a) $@ $^ + @$(RANLIB) $@ > /dev/null + @cp $@ $(CDEVLIB) + +$(BASELIB)/rnsService.so: $(OBJS) + @mkdir -p $(CDEVSHOBJ)/$(CDEVVERSION) + $(LINK.so) -o $@ $^ $(NETLIBS) + @cp $@ $(CDEVSHOBJ)/$(CDEVVERSION) + + +$(CDEVSHOBJ)/$(CDEVVERSION)/rnsService.so : $(BASELIB)/rnsService.so + @mkdir -p $(@D) + @echo " => Copying $(@^) to $@" + @rm -f $@ + @cp $^ $@ + +rsvcSlist.cc : ../src/rsvcSlist.cc +rsvcHSlist.cc : ../src/rsvcHSlist.cc +rsvcHash.cc : ../src/rsvcHash.cc +rsvcDataStreamer.cc : ../src/rsvcDataStreamer.cc +rsvcDataEntry.cc : ../src/rsvcDataEntry.cc +rsvcData.cc : ../src/rsvcData.cc +rsvcNetData.cc : ../src/rsvcNetData.cc +rsvcCbk.cc : ../src/rsvcCbk.cc +rsvcHashable.cc : ../src/rsvcHashable.cc +rsvcStreamable.cc : ../src/rsvcStreamable.cc +rsvcCallback.cc : ../src/rsvcCallback.cc +rsvcClient.cc : ../src/rsvcClient.cc +rsvcUdpClient.cc : ../src/rsvcUdpClient.cc diff --git a/extensions/cdevGenericServer/NameServer/cdev/NMakefile.mak b/extensions/cdevGenericServer/NameServer/cdev/NMakefile.mak new file mode 100644 index 0000000..3cef6d4 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/NMakefile.mak @@ -0,0 +1,118 @@ +.SUFFIXES: .cc .obj + +APPNAME = Name Server Interface for CDEV +ARCH = WINNT-4.0 + +BINARIES = $(TEMPLINKS) $(BASEBIN)\cdev_test + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +TEMPLINKS = rsvcSlist.cc\ + rsvcHSlist.cc\ + rsvcHash.cc\ + rsvcDataStreamer.cc\ + rsvcDataEntry.cc\ + rsvcData.cc\ + rsvcNetData.cc\ + rsvcCbk.cc\ + rsvcHashable.cc\ + rsvcStreamable.cc\ + rsvcCallback.cc\ + rsvcClient.cc\ + rsvcUdpClient.cc +OBJS = $(OBJDIR)\rsvcSlist.obj\ + $(OBJDIR)\rsvcHSlist.obj\ + $(OBJDIR)\rsvcHash.obj\ + $(OBJDIR)\rsvcDataStreamer.obj\ + $(OBJDIR)\rsvcDataEntry.obj\ + $(OBJDIR)\rsvcData.obj\ + $(OBJDIR)\rsvcNetData.obj\ + $(OBJDIR)\rsvcCbk.obj\ + $(OBJDIR)\rsvcHashable.obj\ + $(OBJDIR)\rsvcStreamable.obj\ + $(OBJDIR)\rsvcCallback.obj\ + $(OBJDIR)\rsvcClient.obj\ + $(OBJDIR)\rsvcUdpClient.obj\ + $(OBJDIR)\rnsService.obj\ + $(OBJDIR)\rnsRequestObject.obj + +!IF "$(SHOBJ)" == "YES" +TARGETS = $(TEMPLINKS) $(CDEVSHOBJ)\$(CDEVVERSION)\rnsService.dll $(BASEBIN)\cdev_test.exe +!ELSE +TARGETS = $(TEMPLINKS) $(CDEVLIB)\rnsService.lib +!ENDIF + +CXXINCLUDES = -I.\\ +CXXEXTRA_DLL = /D "_RSVC_CORE_EXPORTS_=1" + +targets : $(TARGETS) + @erase $(TEMPLINKS) + +$(BASEBIN)\cdev_test.exe: $(OBJDIR)\cdev_test.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib\ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +$(CDEVLIB)\rnsService.lib: $(OBJS) + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib\ + $(LINK_LIB_FLAGS) /out:$@ $(OBJS) + @echo ^ ^ ^ ^ ^ ^ Done... + +$(CDEVLIB)\rnsService.dll: $(OBJS) + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib\ + $(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $(OBJS) + -@if not exist $(CDEVSHOBJ)\$(CDEVVERSION) mkdir $(CDEVSHOBJ)\$(CDEVVERSION) + @copy $@ $(CDEVSHOBJ)\$(CDEVVERSION)\$(@F) > nul + @echo ^ ^ ^ ^ ^ ^ Done... + +$(CDEVSHOBJ)\$(CDEVVERSION)\rnsService.dll : $(CDEVLIB)\rnsService.dll + @echo ^ ^ ^ =^> Transfer $(@F) to CDEVSHOBJ directory + -@copy $(CDEVLIB)\rnsService.dll $@ + +rsvcSlist.cc : ..\src\rsvcSlist.cc + -@$(CREATE_LINK) + +rsvcHSlist.cc : ..\src\rsvcHSlist.cc + -@$(CREATE_LINK) + +rsvcHash.cc : ..\src\rsvcHash.cc + -@$(CREATE_LINK) + +rsvcDataStreamer.cc : ..\src\rsvcDataStreamer.cc + -@$(CREATE_LINK) + +rsvcDataEntry.cc : ..\src\rsvcDataEntry.cc + -@$(CREATE_LINK) + +rsvcData.cc : ..\src\rsvcData.cc + -@$(CREATE_LINK) + +rsvcNetData.cc : ..\src\rsvcNetData.cc + -@$(CREATE_LINK) + +rsvcCbk.cc : ..\src\rsvcCbk.cc + -@$(CREATE_LINK) + +rsvcHashable.cc : ..\src\rsvcHashable.cc + -@$(CREATE_LINK) + +rsvcStreamable.cc : ..\src\rsvcStreamable.cc + -@$(CREATE_LINK) + +rsvcCallback.cc : ..\src\rsvcCallback.cc + -@$(CREATE_LINK) + +rsvcClient.cc : ..\src\rsvcClient.cc + -@$(CREATE_LINK) + +rsvcUdpClient.cc : ..\src\rsvcUdpClient.cc + -@$(CREATE_LINK) + diff --git a/extensions/cdevGenericServer/NameServer/cdev/cdev_test.cc b/extensions/cdevGenericServer/NameServer/cdev/cdev_test.cc new file mode 100755 index 0000000..1361983 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/cdev_test.cc @@ -0,0 +1,132 @@ +// simple test for name server cdev interface +#include +#include +#include +#include +#include + +#ifdef _WIN32 +inline int strcasecmp ( const char * string1, const char * string2 ) + { + return _stricmp(string1, string2); + } +#endif + +static void entryCallback (int status, void *, + cdevRequestObject&, cdevData& data) +{ + if (status == CDEV_SUCCESS || status == CDEV_INCOMPLETE) { + printf ("New server is here \n"); + data.asciiDump (); + } + else if (status == CDEV_CBK_FINISHED) { + printf ("entry monitor finished\n"); + } + else if (status == CDEV_DISCONNECTED) + printf ("Server is gone\n"); + else + printf ("monitor callback failed\n"); +} + +static void monCallback (int status, void* /* arg */, + cdevRequestObject& /* obj */, cdevData& data) +{ + if (status == CDEV_SUCCESS) + data.asciiDump (); + else if (status == CDEV_CBK_FINISHED) { + printf ("monitor finished\n"); + data.asciiDump (); + } + else if (status == CDEV_DISCONNECTED) + printf ("server is dead\n"); + else + printf ("monitor callback failed\n"); +} + +int main (int /* argc */, char** /* argv */) +{ + cdevSystem& system = cdevSystem::defaultSystem (); + char temp[100]; + char comd[100]; + + printf ("Enter cdev test command\n"); + scanf ("%s", comd); + + if (strcasecmp (comd, "get") == 0) { + cdevRequestObject* obj = cdevRequestObject::attachPtr ("serverNs", "get"); + + if (obj) { + cdevData result; + cdevData out; + printf ("enter namd and domain \n"); + char name[100], domain[100]; + scanf ("%s %s", name, domain); + out.insert ("name", name); + out.insert ("domain", domain); + + if (obj->send (out, result) == CDEV_SUCCESS) { + result.asciiDump (); + } + else + printf ("get data failed\n"); + } + } + else if (strcasecmp (comd, "monitorOn") == 0) { + cdevRequestObject* obj = cdevRequestObject::attachPtr ("serverNs", + "monitorOn"); + if (obj) { + cdevData result; + cdevData out; + printf ("enter namd and domain \n"); + char name[100], domain[100]; + scanf ("%s %s", name, domain); + + out.insert ("name", name); + out.insert ("domain", domain); + + cdevCallback cbk (monCallback, 0); + + if (obj->sendCallback (out, cbk) != CDEV_SUCCESS) + printf ("monitor data failed\n"); + else { + while (1) + system.pend (); + } + + // now remove monitor + cdevRequestObject* obj0 = cdevRequestObject::attachPtr ("serverNs", + "monitorOff"); + if (obj0) { + if (obj0->sendCallback (out, cbk) != CDEV_SUCCESS) + printf ("monitor off data failed\n"); + else + system.pend (20.0); + } + } + } + else if (strcasecmp (comd, "monitorEntry") == 0) { + cdevRequestObject* obj = cdevRequestObject::attachPtr ("serverNs", + "monitorEntry"); + if (obj) { + cdevCallback cbk (entryCallback, 0); + + if (obj->sendCallback (0, cbk) != CDEV_SUCCESS) + printf ("monitor entry failed\n"); + else { + while (1) + system.pend (); + } + + // now remove monitor + cdevRequestObject* obj0 = cdevRequestObject::attachPtr ("serverNs", + "monitorEntryOff"); + if (obj0) { + if (obj0->sendCallback (0, cbk) != CDEV_SUCCESS) + printf ("monitor off data failed\n"); + else + system.pend (20.0); + } + } + } +return 0; +} diff --git a/extensions/cdevGenericServer/NameServer/cdev/rns.ddl b/extensions/cdevGenericServer/NameServer/cdev/rns.ddl new file mode 100755 index 0000000..dc402be --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rns.ddl @@ -0,0 +1,17 @@ +service rns { + tags {PV} +} + +class RNS { + messages { + get rns; + monitorOn rns; + monitorOff rns; + monitorEntry rns; + monitorEntryOff rns; + } +} + +RNS : +serverNs +; diff --git a/extensions/cdevGenericServer/NameServer/cdev/rnsMonitorObj.h b/extensions/cdevGenericServer/NameServer/cdev/rnsMonitorObj.h new file mode 100755 index 0000000..197a1ce --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rnsMonitorObj.h @@ -0,0 +1,54 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Name Server Monitor Object +// +// Author: Jie Chen +// +// +// +#ifndef _RNS_MONITOR_OBJ_H +#define _RNS_MONITOR_OBJ_H + +#include + +class rnsRequestObject; + +class rnsMonitorObj : public cdevMonitorObj +{ +public: + // constructor and destructor + rnsMonitorObj (cdevTranObj& tranObj) + :cdevMonitorObj (tranObj), out_ (0), started_ (1) + { +#ifdef _TRACE_OBJECTS + printf (" Create rnsMonitorObj Class Object\n"); +#endif + } + + ~rnsMonitorObj (void) + { +#ifdef _TRACE_OBJECTS + printf (" Delete rnsMonitorObj Class Object\n"); +#endif + if (out_) + delete out_; + } + + const char* className (void) const {return "rnsMonitorObj";} + + // out bound cdevdata + cdevData* out_; + + // whether this monitor callback is restarted or not + int started_; +}; +#endif + diff --git a/extensions/cdevGenericServer/NameServer/cdev/rnsQueryCollector.h b/extensions/cdevGenericServer/NameServer/cdev/rnsQueryCollector.h new file mode 100755 index 0000000..3a7a1a7 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rnsQueryCollector.h @@ -0,0 +1,439 @@ +#include +#include +#include +#include + +class rnsQueryCollector +{ +private: + cdevData * data; + int deleteFlag; + unsigned char * byteData; + short * shortData; + unsigned short * ushortData; + long * longData; + unsigned long * ulongData; + float * floatData; + double * doubleData; + cdev_TS_STAMP * tsData; + size_t byteCnt; + size_t shortCnt; + size_t ushortCnt; + size_t longCnt; + size_t ulongCnt; + size_t floatCnt; + size_t doubleCnt; + size_t tsCnt; + +public: + rnsQueryCollector ( cdevData & userData, int deleteData = 0 ) + : data(&userData), deleteFlag(deleteData), + byteData(NULL), shortData(NULL), ushortData(NULL), + longData(NULL), ulongData(NULL), floatData(NULL), + doubleData(NULL), tsData(NULL), byteCnt(0), + shortCnt(0), ushortCnt(0), longCnt(0), ulongCnt(0), + floatCnt(0), doubleCnt(0), tsCnt(0) + { + data->remove(); + } + + ~rnsQueryCollector ( void ) + { + if(deleteFlag) delete data; + if(byteData) delete byteData; + if(shortData) delete shortData; + if(ushortData) delete ushortData; + if(longData) delete longData; + if(ulongData) delete ulongData; + if(floatData) delete floatData; + if(doubleData) delete doubleData; + if(tsData) delete tsData; + } + + cdevData * getData ( void ) { return data; } + void clearData ( void ) { data->remove(); } + inline int collect ( cdevData & userData ); + +private: + inline int collectAttribute ( cdevData & userData, int tag, int position ); + inline void collectByteAttribute ( cdevData & userData, int tag, int position ); + inline void collectShortAttribute ( cdevData & userData, int tag, int position ); + inline void collectUShortAttribute ( cdevData & userData, int tag, int position ); + inline void collectLongAttribute ( cdevData & userData, int tag, int position ); + inline void collectULongAttribute ( cdevData & userData, int tag, int position ); + inline void collectFloatAttribute ( cdevData & userData, int tag, int position ); + inline void collectDoubleAttribute ( cdevData & userData, int tag, int position ); + inline void collectStringAttribute ( cdevData & userData, int tag, int position ); + inline void collectTimestampAttribute ( cdevData & userData, int tag, int position ); +}; + + +// ***************************************************************************** +// * class rnsQueryCallback : +// * This class provides the methods to allow a rnsQueryCollector to be +// * incorporated into a cdevCallback. The localCallback function will +// * be called with results until the data has been completely collected, +// * and only then will the user callback be executed - providing full +// * data. +// ***************************************************************************** +class rnsQueryCallback : public cdevCallback +{ +private: + rnsQueryCollector collector; + cdevCallback callback; + +public: + rnsQueryCallback ( cdevCallback & Callback ) + : cdevCallback(), callback(Callback), collector(*(new cdevData), 1) + { + userarg_ = this; + function_ = rnsQueryCallback::localCallback; + } + + virtual ~rnsQueryCallback ( void ) + { + } + + static void localCallback ( int status, void * arg, cdevRequestObject & req, cdevData & data) + { + rnsQueryCallback * qCallback; + + if((qCallback = (rnsQueryCallback *)arg)!=NULL) + { + if(status==CDEV_SUCCESS || + status==CDEV_INCOMPLETE) + { + qCallback->collector.collect(data); + } + + if(status==CDEV_SUCCESS || + status==CDEV_ERROR || + status==CDEV_NOTFOUND || + status==CDEV_MSG_ERR) + { + qCallback->callback.fireCallback(status, qCallback->callback.userarg(), + req, *qCallback->collector.getData(), 0); + } + } + } +}; + + +// ***************************************************************************** +// * rnsQueryCollector::collect : +// * This method is called when a cdevData object needs to be appended to +// * the cdevData object that is serving as a collection. This method will +// * transfer each of the data items in the userData object to the proper +// * position in the local data object. +// ***************************************************************************** +int rnsQueryCollector::collect ( cdevData & userData ) + { + int cnt = 0; + size_t size = 0; + cdevDataIterator iter(&userData); + cdevDataIterator dIter(data); + + // ********************************************************************* + // * Look through the existing data and determine the largest number + // * of items that exist in a single tagged item. This value will be + // * used to specify the position of the data that is being added to the + // * array. + // ********************************************************************* + dIter.init(); + while(dIter.tag()!=0) + { + size_t elems = 0; + data->getElems(dIter.tag(), &elems); + if(elems>size) size = elems; + ++dIter; + } + + // ********************************************************************* + // * Walk through the list of tagged data items that are stored in the + // * inbound data object. Call the collectAttribute method for each + // * data item. This method will copy the contents of the inbound + // * data object to the correct position in the local data object. + // ********************************************************************* + iter.init(); + while(iter.tag()!=0) + { + cnt+=(collectAttribute(userData, iter.tag(), size)==0)?1:0; + ++iter; + } + + // ********************************************************************* + // * Return the count of data items that were assimilated into the + // * local data object. + // ********************************************************************* + return cnt; + } + + +// ***************************************************************************** +// * rnsQueryCollector::collectAttribute : +// * This method will assimilate a single attribute from the specified +// * userData object into the local cdevData object at the specified +// * position. +// ***************************************************************************** +int rnsQueryCollector::collectAttribute ( cdevData & userData, int tag, int position ) + { + cdevSystem & sys = cdevSystem::defaultSystem(); + int result = 0; + size_t dim = 0; + size_t userDim = 0; + cdevDataTypes type = data->getType(tag); + cdevDataTypes userType = userData.getType(tag); + + if(userData.getDim(tag, &dim)==CDEV_NOTFOUND || dim > 0) + { + sys.reportError(CDEV_SEVERITY_ERROR, "Name Server", NULL, + "Cannot add array data to query reply"); + result = -1; + } + else if(data->getDim(tag, &dim)!=CDEV_NOTFOUND && dim > 1) + { + sys.reportError(CDEV_SEVERITY_ERROR, "Name Server", NULL, + "Cannot assemble a query with multi-dimensional data"); + result = -1; + } + else if (userType == CDEV_INVALID) + { + sys.reportError(CDEV_SEVERITY_ERROR, "Name Server", NULL, + "Inbound query data object has invalid data type"); + result = -1; + } + else { + if(type!=CDEV_INVALID) + { + if(typeuserType)?type:userType; + } + else if(type==CDEV_TIMESTAMP) type = userType; + } + else type = userType; + + switch(type) + { + case CDEV_BYTE: + collectByteAttribute(userData, tag, position); + break; + case CDEV_INT16: + collectShortAttribute(userData, tag, position); + break; + case CDEV_UINT16: + collectUShortAttribute(userData, tag, position); + break; + case CDEV_INT32: + collectLongAttribute(userData, tag, position); + break; + case CDEV_UINT32: + collectULongAttribute(userData, tag, position); + break; + case CDEV_FLOAT: + collectFloatAttribute(userData, tag, position); + break; + case CDEV_DOUBLE: + collectDoubleAttribute(userData, tag, position); + break; + case CDEV_STRING: + collectStringAttribute(userData, tag, position); + break; + case CDEV_TIMESTAMP: + collectTimestampAttribute(userData, tag, position); + break; + default: + result = -1; + break; + } + } + return result; + } + + +// ***************************************************************************** +// * rnsQueryCollector::collectByteAttribute : +// * This method will transfer the byte attribute stored in the userData +// * object into the local cdevData object at the specified position. +// ***************************************************************************** +void rnsQueryCollector::collectByteAttribute (cdevData & userData, int tag, int position ) + { + if((position+1)>byteCnt) + { + if(byteData!=NULL) delete byteData; + byteCnt = ((position+1)>100)?(position+100):100; + byteData = new unsigned char [byteCnt]; + } + memset(byteData, 0, byteCnt*sizeof(unsigned char)); + data->get(tag, byteData); + userData.get(tag, &byteData[position]); + data->insert(tag, byteData, position+1); + } + +// ***************************************************************************** +// * rnsQueryCollector::collectShortAttribute : +// * This method will transfer the short attribute stored in the userData +// * object into the local cdevData object at the specified position. +// ***************************************************************************** +void rnsQueryCollector::collectShortAttribute (cdevData & userData, int tag, int position ) + { + if((position+1)>shortCnt) + { + if(shortData!=NULL) delete shortData; + shortCnt = ((position+1)>100)?(position+100):100; + shortData = new short [shortCnt]; + } + memset(shortData, 0, shortCnt*sizeof(short)); + data->get(tag, shortData); + userData.get(tag, &shortData[position]); + data->insert(tag, shortData, position+1); + } + +// ***************************************************************************** +// * rnsQueryCollector::collectUShortAttribute : +// * This method will transfer the unsigned short attribute stored in the +// * userData object into the local cdevData object at the specified +// * position. +// ***************************************************************************** +void rnsQueryCollector::collectUShortAttribute (cdevData & userData, int tag, int position ) + { + if((position+1)>ushortCnt) + { + if(ushortData!=NULL) delete ushortData; + ushortCnt = ((position+1)>100)?(position+100):100; + ushortData = new unsigned short [ushortCnt]; + } + memset(ushortData, 0, ushortCnt*sizeof(unsigned short)); + data->get(tag, ushortData); + userData.get(tag, &ushortData[position]); + data->insert(tag, ushortData, position+1); + } + +// ***************************************************************************** +// * rnsQueryCollector::collectLongAttribute : +// * This method will transfer the long attribute stored in the +// * userData object into the local cdevData object at the specified +// * position. +// ***************************************************************************** +void rnsQueryCollector::collectLongAttribute (cdevData & userData, int tag, int position ) + { + if((position+1)>longCnt) + { + if(longData!=NULL) delete longData; + longCnt = ((position+1)>100)?(position+100):100; + longData = new long [longCnt]; + } + memset(longData, 0, longCnt*sizeof(long)); + data->get(tag, longData); + userData.get(tag, &longData[position]); + data->insert(tag, longData, position+1); + } + +// ***************************************************************************** +// * rnsQueryCollector::collectULongAttribute : +// * This method will transfer the unsigned long attribute stored in the +// * userData object into the local cdevData object at the specified +// * position. +// ***************************************************************************** +void rnsQueryCollector::collectULongAttribute (cdevData & userData, int tag, int position ) + { + if((position+1)>ulongCnt) + { + if(ulongData!=NULL) delete ulongData; + ulongCnt = ((position+1)>100)?(position+100):100; + ulongData = new unsigned long [ulongCnt]; + } + memset(ulongData, 0, ulongCnt*sizeof(unsigned long)); + data->get(tag, ulongData); + userData.get(tag, &ulongData[position]); + data->insert(tag, ulongData, position+1); + } + +// ***************************************************************************** +// * rnsQueryCollector::collectFloatAttribute : +// * This method will transfer the float attribute stored in the +// * userData object into the local cdevData object at the specified +// * position. +// ***************************************************************************** +void rnsQueryCollector::collectFloatAttribute (cdevData & userData, int tag, int position ) + { + if((position+1)>floatCnt) + { + if(floatData!=NULL) delete floatData; + floatCnt = ((position+1)>100)?(position+100):100; + floatData = new float [floatCnt]; + } + memset(floatData, 0, floatCnt*sizeof(float)); + data->get(tag, floatData); + userData.get(tag, &floatData[position]); + data->insert(tag, floatData, position+1); + } + +// ***************************************************************************** +// * rnsQueryCollector::collectDoubleAttribute : +// * This method will transfer the double attribute stored in the +// * userData object into the local cdevData object at the specified +// * position. +// ***************************************************************************** +void rnsQueryCollector::collectDoubleAttribute (cdevData & userData, int tag, int position ) + { + if((position+1)>doubleCnt) + { + if(doubleData!=NULL) delete doubleData; + doubleCnt = ((position+1)>100)?(position+100):100; + doubleData = new double [doubleCnt]; + } + memset(doubleData, 0, doubleCnt*sizeof(double)); + data->get(tag, doubleData); + userData.get(tag, &doubleData[position]); + data->insert(tag, doubleData, position+1); + } + +// ***************************************************************************** +// * rnsQueryCollector::collectStringAttribute : +// * This method will transfer the string attribute stored in the +// * userData object into the local cdevData object at the specified +// * position. +// ***************************************************************************** +void rnsQueryCollector::collectStringAttribute (cdevData & userData, int tag, int position ) + { + int i; + char blank = 0; + + char ** stringData = new char * [ position+1 ]; + memset(stringData, 0, (position+1)*sizeof(char *)); + data->get(tag, stringData); + userData.get(tag, &stringData[position]); + + for(i=0; iinsert(tag, stringData, position+1); + + for(i=0; itsCnt) + { + if(tsData!=NULL) delete tsData; + tsCnt = ((position+1)>100)?(position+100):100; + tsData = new cdev_TS_STAMP [tsCnt]; + } + memset(tsData, 0, tsCnt); + data->get(tag, tsData); + userData.get(tag, &tsData[position]); + data->insert(tag, tsData, position+1); + } diff --git a/extensions/cdevGenericServer/NameServer/cdev/rnsRequestObject.cc b/extensions/cdevGenericServer/NameServer/cdev/rnsRequestObject.cc new file mode 100755 index 0000000..979e7cc --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rnsRequestObject.cc @@ -0,0 +1,752 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rnsRequesObject Class +// +// Author: Jie Chen +// +// Revision History: +// rnsRequestObject.cc,v +// Revision 1.7 1998/04/01 15:32:12 chen +// fix transaction done flag +// +// Revision 1.6 1998/03/19 18:31:43 chen +// add monitorEntry capability +// +// Revision 1.5 1998/02/09 13:35:47 chen +// duplicate cdev data in the monitor object +// +// Revision 1.4 1998/02/06 15:11:25 chen +// add connection management for name server +// +// Revision 1.3 1998/02/05 15:59:19 akers +// Ongoing development +// +// Revision 1.2 1998/01/30 18:31:37 akers +// Ongoing development +// +// Revision 1.1 1998/01/22 17:07:51 akers +// Addition of new NameServer +// +// +// +#include +#include +#include +#include + +#include "rnsService.h" +#include "rnsRequestObject.h" +#include "rnsQueryCollector.h" +#include + +char* rnsRequestObject::stags_[] = {"name", "domain"}; +int rnsRequestObject::numstags_ = 2; + +#ifdef _WIN32 +inline int strcasecmp ( const char * string1, const char * string2 ) + { + return stricmp(string1, string2); + } +#endif + +// ***************************************************************************** +// * The localQuerySynchronizer class has been added to allow me to make +// * synchronous requests to query the NameServer. +// ***************************************************************************** +class localQuerySynchronizer +{ +public: + static int cbDone; + static long cbIdent; + static cdevData cbData; + static cdevCallback getCallbackObj ( void ) + { + cbData.remove(); + cbDone = 0; + cbIdent++; + cdevCallback cbObj(callback, (void *)cbIdent); + return cbObj; + } + static void callback ( int /*status*/, void * userarg, cdevRequestObject &/*reqObj*/, cdevData &data) + { + if(((long)userarg)==cbIdent) + { + cbDone = 1; + cbData = data; + } + } +}; + +int localQuerySynchronizer::cbDone = 0; +long localQuerySynchronizer::cbIdent = 0; +cdevData localQuerySynchronizer::cbData; + +rnsRequestObject::rnsRequestObject (char* device, char* msg, + rnsService* svc, + cdevSystem& system) +:cdevRequestObject (device, msg, system), client_ (0) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rnsRequestObject Class Object\n"); +#endif + client_ = &(svc->client_); + + // convert msg to integer action + rnsRequestObject::findAction (msg, action_); +} + +rnsRequestObject::~rnsRequestObject (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete rnsRequestObject Class Object\n"); +#endif +} + +int +rnsRequestObject::getState (void) +{ + if (client_->connected ()) + return CDEV_STATE_CONNECTED; + return CDEV_STATE_NOTCONNECTED; +} + +int +rnsRequestObject::sendCallback (cdevData& out, cdevCallback& cbk) +{ + return sendCallback (&out, cbk); +} + + +int +rnsRequestObject::sendCallback (cdevData* out, cdevCallback& userCallback) +{ + if (deferExecution (out, &userCallback)) + return CDEV_SUCCESS; + + int status = CDEV_SUCCESS; + cdevTranObj* xobj = 0; + rnsMonitorObj* mobj = 0; + rnsService* nservice = (rnsService *)service_; + + // copy userCallback into the following callback, which will free + // the user from worrying about cdevCallback object + // note: cdevCallback's new operator is an overloaded operator + cdevCallback* callback = 0; + + if (client_->connected ()) { + switch (action_) { + case rnsRequestObject::GET: + { + if (out == 0) + return CDEV_INVALIDARG; + + callback = new cdevCallback (userCallback); + xobj = new cdevTranObj (&system_, this, 0, callback); + + rsvcData outdata; + if (rnsRequestObject::dataCdevToRsvc (*out, outdata) != CDEV_SUCCESS) + status = CDEV_INVALIDARG; + else { + if (client_->getValue (_RSVC_CDEV_SERVERS, outdata, + &(rnsRequestObject::getCallback), + (void *)xobj) != CDEV_SUCCESS) + status = CDEV_IOFAILED; + } + if (status != CDEV_SUCCESS) + delete xobj; + } + break; + case rnsRequestObject::QUERY: + { + if (out == 0) + return CDEV_INVALIDARG; + + callback = (cdevCallback *)new rnsQueryCallback(userCallback); + xobj = new cdevTranObj (&system_, this, 0, callback); + mobj = new rnsMonitorObj (*xobj); + + char qmsg[1024]; + if (out->get ("queryMsg", qmsg, sizeof (qmsg)) != CDEV_SUCCESS) + status = CDEV_INVALIDARG; + else { + mobj->out_ = new cdevData (*out); + if (client_->query (_RSVC_CDEV_SERVERS, qmsg, + &(rnsRequestObject::queryCallback), + (void *)mobj) != CDEV_SUCCESS) + status = CDEV_IOFAILED; + else + nservice->addMonitorObject (mobj); + } + if (status != CDEV_SUCCESS) { + delete xobj; + delete mobj; + } + } + break; + case rnsRequestObject::MONITORON: + { + if (out == 0) + return CDEV_INVALIDARG; + + if (nservice->hasCallback (userCallback)) + return CDEV_INVALIDARG; + + callback = new cdevCallback (userCallback); + xobj = new cdevTranObj (&system_, this, 0, callback); + mobj = new rnsMonitorObj (*xobj); + + + rsvcData outdata; + if (rnsRequestObject::dataCdevToRsvc (*out, outdata) != CDEV_SUCCESS) + status = CDEV_INVALIDARG; + else { + mobj->out_ = new cdevData (*out); + if (client_->monitorValue (_RSVC_CDEV_SERVERS, outdata, + &(rnsRequestObject::monitorCallback), + (void *)mobj) != CDEV_SUCCESS) + status = CDEV_IOFAILED; + else + nservice->addMonitorObject (mobj); + } + if (status != CDEV_SUCCESS) { + delete xobj; + delete mobj; + } + } + break; + case rnsRequestObject::MONITOROFF: + { + if (out == 0) + return CDEV_INVALIDARG; + + rnsMonitorObj* mobj = 0; + rsvcData outdata; + if (rnsRequestObject::dataCdevToRsvc (*out, outdata) != CDEV_SUCCESS) + status = CDEV_INVALIDARG; + else { + if ((mobj = nservice->hasCallback (userCallback)) == 0) { + printf ("this callback function is not registered\n"); + status = CDEV_INVALIDARG; + } + else + status = monitorOff (outdata, mobj); + } + } + break; + case rnsRequestObject::MONITORENTRY: + { + if (nservice->hasCallback (userCallback)) + return CDEV_INVALIDARG; + + callback = new cdevCallback (userCallback); + xobj = new cdevTranObj (&system_, this, 0, callback); + mobj = new rnsMonitorObj (*xobj); + + rsvcData empty; + if (client_->monitorIncomingEntries (_RSVC_CDEV_SERVERS, empty, + &(rnsRequestObject::entryCallback), + (void *)mobj) != CDEV_SUCCESS) + status = CDEV_IOFAILED; + else + nservice->addMonitorObject (mobj); + + if (status != CDEV_SUCCESS) { + delete xobj; + delete mobj; + } + } + break; + case rnsRequestObject::MONITORENTRYOFF: + { + rnsMonitorObj* mobj = 0; + if ((mobj = nservice->hasCallback (userCallback)) == 0) { +#ifdef _CDEV_DEBUG + printf ("this callback function is not registered\n"); +#endif + status = CDEV_INVALIDARG; + } + else + status = monitorEntryOff (mobj); + } + break; + default: + status = CDEV_INVALIDARG; + break; + } + } + else + status = CDEV_NOTCONNECTED; + + return status; +} + +int +rnsRequestObject::sendMonitor (rnsMonitorObj* mobj) +{ + rsvcData outdata; + int status = CDEV_SUCCESS; + + if (rnsRequestObject::dataCdevToRsvc (*mobj->out_, outdata)!= CDEV_SUCCESS) { + mobj->started_ = 1; + status = CDEV_INVALIDARG; + } + else { + if ((status = client_->monitorValue (_RSVC_CDEV_SERVERS, outdata, + &(rnsRequestObject::monitorCallback), + (void *)mobj)) != CDEV_SUCCESS) + mobj->started_ = 1; + } + return status; +} + +int +rnsRequestObject::sendEntryMonitor (rnsMonitorObj* mobj) +{ + int status = CDEV_SUCCESS; + rsvcData empty; + + if ((status = client_->monitorIncomingEntries (_RSVC_CDEV_SERVERS, empty, + &(rnsRequestObject::entryCallback), + (void *)mobj)) != CDEV_SUCCESS) + mobj->started_ = 1; + return status; +} + +void +rnsRequestObject::getCallback (int status, void* arg, rsvcData* data) +{ + cdevTranObj* xobj = (cdevTranObj *)arg; + + + // if a callback has been discarded, do not do anything + if (xobj->isTrash ()) { + delete xobj; + return; + } + + cdevCallback* cbk = xobj->userCallback_; + cdevRequestObject* obj = xobj->reqObj_; + cdevData* rda = xobj->resultData_; + cdevData result; + + if (rda) // send no block + rda->remove (); + else + rda = &result; + + if (status == RSVC_SUCCESS) + rnsRequestObject::dataRsvcToCdev (*data, *rda); + + if (cbk) + cbk->fireCallback (status, cbk->userarg (), *obj, result, 0); + + delete xobj; +} + +void +rnsRequestObject::queryCallback (int status, void* arg, rsvcData* data) +{ + rnsMonitorObj* mobj = (rnsMonitorObj *)arg; + + cdevCallback* cbk = mobj->userCallback_; + cdevRequestObject* obj = mobj->reqObj_; + cdevData result; + int cbk_finished = 1; + + // first time this callback is called + if (mobj->tobj_) { + delete mobj->tobj_; + mobj->tobj_ = 0; + } + + if (status == RSVC_ERROR || status == RSVC_NOTFOUND) + cbk->fireCallback (status, cbk->userarg (), *obj, result, 0); + else if (status == RSVC_INCOMPLETE) { + rnsRequestObject::dataRsvcToCdev (*data, result); + cbk->fireCallback (status, cbk->userarg (), *obj, result, 1); + cbk_finished = 0; + } + else if (status == RSVC_QUERYMSG_ERR) + cbk->fireCallback (CDEV_MSG_ERR, cbk->userarg (), *obj, result, 0); + else { + rnsRequestObject::dataRsvcToCdev (*data, result); + cbk->fireCallback (status, cbk->userarg (), *obj, result, 0); + } + if (cbk_finished) { + rnsRequestObject* nsreq = (rnsRequestObject *)obj; + nsreq->removeMonitorObject (mobj); + } +} + +void +rnsRequestObject::monitorCallback (int status, void* arg, rsvcData* data) +{ + rnsMonitorObj* mobj = (rnsMonitorObj *)arg; + + cdevCallback* cbk = mobj->userCallback_; + cdevRequestObject* obj = mobj->reqObj_; + cdevData result; + int cbk_finished = 1; + + // first time this callback is called + if (mobj->tobj_) { + delete mobj->tobj_; + mobj->tobj_ = 0; + } + + if (status == RSVC_SUCCESS) { + rnsRequestObject::dataRsvcToCdev (*data, result); + cbk->fireCallback (status, cbk->userarg (), *obj, result, 1); + cbk_finished = 0; + if (!mobj->started_) + mobj->started_ = 1; + } + else if (status == RSVC_CBK_FINISHED) { + rnsRequestObject::dataRsvcToCdev (*data, result); + if (mobj->started_) + cbk->fireCallback (status, cbk->userarg (), *obj, result, 0); + } + else { + if (mobj->started_) + cbk->fireCallback (status, cbk->userarg (), *obj, result, 0); + } + + if (cbk_finished && mobj->started_) { + rnsRequestObject* nsreq = (rnsRequestObject *)obj; + nsreq->removeMonitorObject (mobj); + } +} + +void +rnsRequestObject::entryCallback (int status, void* arg, rsvcData* data) +{ + rnsMonitorObj* mobj = (rnsMonitorObj *)arg; + + cdevCallback* cbk = mobj->userCallback_; + cdevRequestObject* obj = mobj->reqObj_; + cdevData result; + int cbk_finished = 1; + + // first time this callback is called + if (mobj->tobj_) { + delete mobj->tobj_; + mobj->tobj_ = 0; + } + + if (status == RSVC_SUCCESS || status == RSVC_INCOMPLETE) { + rnsRequestObject::dataRsvcToCdev (*data, result); + cbk->fireCallback (RSVC_SUCCESS, cbk->userarg (), *obj, result, 1); + cbk_finished = 0; + if (!mobj->started_) + mobj->started_ = 1; + } + else if (status == RSVC_CBK_FINISHED) { + rnsRequestObject::dataRsvcToCdev (*data, result); + if (mobj->started_) + cbk->fireCallback (status, cbk->userarg (), *obj, result, 0); + } + else { + if (mobj->started_) + cbk->fireCallback (status, cbk->userarg (), *obj, result, 1); + } + + if (cbk_finished && mobj->started_) { + rnsRequestObject* nsreq = (rnsRequestObject *)obj; + nsreq->removeMonitorObject (mobj); + } +} + +int +rnsRequestObject::monitorOff (rsvcData& data, rnsMonitorObj* mobj) +{ + int status; + status = client_->monitorOffValue (_RSVC_CDEV_SERVERS, data, + &(rnsRequestObject::monitorCallback), + (void *)mobj); + return status; +} + +int +rnsRequestObject::monitorEntryOff (rnsMonitorObj* mobj) +{ + int status; + rsvcData empty; + status = client_->monitorOffIncomingEntries (_RSVC_CDEV_SERVERS, empty, + &(rnsRequestObject::entryCallback), + (void *)mobj); + return status; +} + +int +rnsRequestObject::sendNoBlock (cdevData& out, cdevData& result) +{ + return sendNoBlock (&out, &result); +} + +int +rnsRequestObject::sendNoBlock (cdevData* out, cdevData& result) +{ + return sendNoBlock (out, &result); +} + +int +rnsRequestObject::sendNoBlock (cdevData& out, cdevData* result) +{ + return sendNoBlock (&out, result); +} + +int +rnsRequestObject::sendNoBlock (cdevData* out, cdevData* result) +{ + if (deferExecution (out, result)) + return CDEV_SUCCESS; + + int status = CDEV_SUCCESS; + cdevTranObj* xobj = 0; + rnsService* nservice = (rnsService *)service_; + + if (client_->connected ()) { + switch (action_) { + case rnsRequestObject::GET: + { + if (out == 0 || result == 0) + return CDEV_INVALIDARG; + + xobj = new cdevTranObj (&system_, this, result, 0); + + rsvcData outdata; + if (rnsRequestObject::dataCdevToRsvc (*out, outdata) != CDEV_SUCCESS) + status = CDEV_INVALIDARG; + else { + if (client_->getValue (_RSVC_CDEV_SERVERS, outdata, + &(rnsRequestObject::getCallback), + (void *)xobj) != CDEV_SUCCESS) + status = CDEV_IOFAILED; + } + if (status != CDEV_SUCCESS) + delete xobj; + } + break; + default: + status = CDEV_INVALIDARG; + break; + } + } + else + status = CDEV_NOTCONNECTED; + + return status; +} + +int +rnsRequestObject::send (cdevData& out, cdevData& result) +{ + return send (&out, &result); +} + +int +rnsRequestObject::send (cdevData* out, cdevData& result) +{ + return send (out, &result); +} + +int +rnsRequestObject::send (cdevData& out, cdevData* result) +{ + return send (&out, result); +} + +int +rnsRequestObject::send (cdevData* out, cdevData* result) +{ + int status = CDEV_SUCCESS; + rnsService* nservice = (rnsService *)service_; + + if (client_->connected ()) { + switch (action_) { + case rnsRequestObject::GET: + if (out == 0 || result == 0) + status = CDEV_INVALIDARG; + else { + cdevGroup grp (2, system_); + grp.start (); + sendNoBlock (out, result); + grp.end (); + grp.pend (4.0); + if (!grp.allFinished ()) + status = CDEV_TIMEOUT; + } + break; + case rnsRequestObject::QUERY: + if(out==0 || result==0) + status = CDEV_INVALIDARG; + else { + cdevCallback cb = localQuerySynchronizer::getCallbackObj(); + if((status=sendCallback(out, cb))==CDEV_SUCCESS) + { + cdevTimeValue t(5.0); + cdevClock timer; + timer.schedule(NULL, t); + + while(!localQuerySynchronizer::cbDone && !timer.expired()) nservice->poll(); + + if(!localQuerySynchronizer::cbDone) status = CDEV_TIMEOUT; + else *result = localQuerySynchronizer::cbData; + } + } + break; + default: + status = CDEV_INVALIDARG; + break; + } + } + else + status = CDEV_NOTCONNECTED; + + return status; +} + +int +rnsRequestObject::dataCdevToRsvc (cdevData& data, rsvcData& res) +{ + char val[1024]; + for (int i = 0; i < rnsRequestObject::numstags_; i++) { + if (data.get (rnsRequestObject::stags_[i], val, sizeof (val)) + != CDEV_SUCCESS) + return CDEV_ERROR; + + res.insert (rnsRequestObject::stags_[i], val); + } + return CDEV_SUCCESS; +} + + +int +rnsRequestObject::dataRsvcToCdev (rsvcData& data, cdevData& res) +{ + rsvcDataIterator ite (&data); + int type; + int tag; + size_t numelems; + size_t dim; + char* ctag; + + for (ite.init (); !ite ; ++ite) { + ctag = (char *)ite.tag (); + type = data.getType (ctag); + data.getElems (ctag, &numelems); + data.getDim (ctag, &dim); + + if (cdevData::tagC2I (ctag, &tag) != CDEV_SUCCESS || dim > 1) + continue; + + switch (type) { + case RSVC_BYTE: + case RSVC_INT16: + case RSVC_UINT16: + case RSVC_INT32: + case RSVC_UINT32: + { + if (dim == 0) { + int val; + data.get (ctag, &val); + res.insert (tag, val); + } + else { + int* val = new int[numelems]; + data.get (ctag, val); + res.insert (tag, val, numelems); + delete []val; + } + } + break; + case RSVC_FLOAT: + { + if (dim == 0) { + float val; + data.get (ctag, &val); + res.insert (tag, val); + } + else { + float* val = new float[numelems]; + data.get (ctag, val); + res.insert (tag, val, numelems); + delete []val; + } + } + break; + case RSVC_DOUBLE: + { + if (dim == 0) { + double val; + data.get (ctag, &val); + res.insert (tag, val); + } + else { + double* val = new double[numelems]; + data.get (ctag, val); + res.insert (tag, val, numelems); + delete []val; + } + } + break; + case RSVC_STRING: + { + if (dim == 0) { + char val[1024]; + data.get (ctag, val, sizeof (val)); + res.insert (tag, val); + } + else { + char** val = new char*[numelems]; + data.get (ctag, val); + res.insert (tag, val, numelems); + } + } + break; + default: + break; + } + } + return CDEV_SUCCESS; +} + +int +rnsRequestObject::removeMonitorObject (rnsMonitorObj* mobj) +{ + rnsService *nservice = (rnsService *)service_; + + nservice->removeMonitorObject (mobj); + delete mobj; + + return CDEV_SUCCESS; +} + +int +rnsRequestObject::findAction (char* msg, int& action) +{ + if (strcasecmp (msg, "query") == 0) + action = rnsRequestObject::QUERY; + else if (strcasecmp (msg, "get") == 0) + action = rnsRequestObject::GET; + else if (strcasecmp (msg, "monitorOn") == 0) + action = rnsRequestObject::MONITORON; + else if (strcasecmp (msg, "monitorOff") == 0) + action = rnsRequestObject::MONITOROFF; + else if (strcasecmp (msg, "monitorEntry") == 0) + action = rnsRequestObject::MONITORENTRY; + else if (strcasecmp (msg, "monitorEntryOff") == 0) + action = rnsRequestObject::MONITORENTRYOFF; + else + action = rnsRequestObject::UNKNOWN; + + return CDEV_SUCCESS; +} diff --git a/extensions/cdevGenericServer/NameServer/cdev/rnsRequestObject.h b/extensions/cdevGenericServer/NameServer/cdev/rnsRequestObject.h new file mode 100755 index 0000000..8d3b0e5 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rnsRequestObject.h @@ -0,0 +1,130 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// CDEV Resource Name Service Request Object +// +// Author: Jie Chen +// +// +// +#ifndef _RNS_REQUEST_OBJECT_H +#define _RNS_REQUEST_OBJECT_H + +#include +#include + +class rsvcClient; +class rnsService; +class rnsMonitorObj; + +class rnsRequestObject: public cdevRequestObject +{ +public: + // constructor and destructor + rnsRequestObject (char* device, + char* msg, + rnsService* svc, + cdevSystem& system = cdevSystem::defaultSystem()); + ~rnsRequestObject (void); + + int send (cdevData& out, cdevData& result); + int send (cdevData *out, cdevData& result); + int send (cdevData& out, cdevData* result); + int send (cdevData *out, cdevData* result); + // PURPOSE: Synchronous IO operations + // REQUIRE: When do query and get, result must be provided + // PROMISE: return CDEV_SUCCESS: success. + + int sendNoBlock (cdevData& out, cdevData& result); + int sendNoBlock (cdevData* out, cdevData& result); + int sendNoBlock (cdevData& out, cdevData* result); + int sendNoBlock (cdevData* out, cdevData* result); + // PURPOSE: Asynchronous IO operations used in conjunction with + // cdevGroup or system + // REQUIRE: + // PROMISE: return CDEV_SUCCESS: requests have been sent out. + + int sendCallback (cdevData& out, cdevCallback& callback); + int sendCallback (cdevData* out, cdevCallback& callback); + // PURPOSE: Asynchromous IO operations with a user supplied callback function + // REQUIRE: + // PROMISE: User callback function will be called with status information + // status = CDEV_DISCONNECTED: channel discconected + // status = CDEV_SUCCESS : everything is OK + // status = CDEV_ERROR : something fishy. + // status = CDEV_INCOMPLETE : data flow will coming (88) + // status = CDEV_CBK_FINISHED: query callback finished (89) + // status = CDEV_QUERYMSG_ERR: query message syntax erro (91) + + int getState (void); + // PURPOSE: get connection state + // REQUIRE: none + // PROMISE: CDEV_CONNECTED or CDEV_NOTCONNECTED + + const char *className (void) const {return "rnsRequestObject";} + +protected: + // find out action from message + static int findAction (char* msg, int& action); + + // action value + typedef enum {GET = 0x2000,QUERY,MONITORON,MONITOROFF, + MONITORENTRY, MONITORENTRYOFF, UNKNOWN} RNSENUMVERB; + + // get value callback + static void getCallback (int status, void* arg, rsvcData* data); + + // query value callback + static void queryCallback (int status, void* arg, rsvcData* data); + + // monitor value callback + static void monitorCallback (int status, void* arg, rsvcData* data); + + // monitor entry callback + static void entryCallback (int status, void* arg, rsvcData* data); + + // data conversion from rsvc to cdev + static int dataRsvcToCdev (rsvcData& data, cdevData& result); + + // data conversion from cdev to rsvc + static int dataCdevToRsvc (cdevData& data, rsvcData& result); + + // remove a monitor object + int removeMonitorObject (rnsMonitorObj* mobj); + + // monitor off a callback + int monitorOff (rsvcData& data, rnsMonitorObj* obj); + + // monitor off entry callback + int monitorEntryOff (rnsMonitorObj* obj); + + // resend a monitor callback + int sendMonitor (rnsMonitorObj* mobj); + + // resend a monitor entry callback + int sendEntryMonitor (rnsMonitorObj* mobj); + +private: + + // two tags are needed for all serachs + static char* stags_[]; + static int numstags_; + + // action type + int action_; + + // pointer of underlying client connection + rsvcClient* client_; + + // friend class + friend class rnsService; + +}; +#endif diff --git a/extensions/cdevGenericServer/NameServer/cdev/rnsService.cc b/extensions/cdevGenericServer/NameServer/cdev/rnsService.cc new file mode 100755 index 0000000..3b51bbc --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rnsService.cc @@ -0,0 +1,383 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of nsService Class +// +// Author: Jie Chen +// +// Revision History: +// rnsService.cc,v +// Revision 1.8 1998/03/19 18:31:43 chen +// add monitorEntry capability +// +// Revision 1.7 1998/02/23 16:29:35 chen +// change back to use alarm to handle reconnecton to the name server +// +// Revision 1.6 1998/02/19 18:39:52 akers +// Bug Fixes +// +// Revision 1.5 1998/02/18 14:42:52 chen +// add registerFd to the service +// +// Revision 1.4 1998/02/10 18:06:44 chen +// use system timer instead of alarm +// +// Revision 1.3 1998/02/06 15:11:26 chen +// add connection management for name server +// +// Revision 1.2 1998/01/30 18:31:37 akers +// Ongoing development +// +// Revision 1.1 1998/01/22 17:07:52 akers +// Addition of new NameServer +// +// +// +#include +#include +#include +#include + +#ifndef _WIN32 + #include +#endif + +#include "rnsService.h" +#include "rnsRequestObject.h" +#include + +#define _RNS_CLIENT_RECONN_TIMEOUT 5 + +char * rnsService::tags_[] = { + "table", + "key", + "keyExp", + "keyType", + "name", + "domain", + "host", + "owner", + "time", + "port", + "pid", + "ping", + "client", + "queryMsg" +}; + +int rnsService::numtags_ = 14; + +static rnsService* _rnsNameService_ = 0; + +#ifdef _WIN32 +void CALLBACK _rnsAlarmHandler_ ( HWND hwnd, UINT umsg, UINT idEvent, DWORD dwTime ) + { + if (_rnsNameService_->reconnect () == CDEV_SUCCESS) + { + if (_rnsNameService_->monitorsRestarted ()) + { + KillTimer(NULL, idEvent); + } + } + } +#else +static struct sigaction _oldaction_; + +static void _rnsAlarmHandler_ (int /* signo */) +{ + int done = 0; + + if (_rnsNameService_->reconnect () == CDEV_SUCCESS) { + if (_rnsNameService_->monitorsRestarted ()) { + sigaction (SIGALRM, &_oldaction_, 0); + done = 1; + } + } + + if (!done) + alarm (_RNS_CLIENT_RECONN_TIMEOUT); +} +#endif + +rnsService::rnsService (char* name, cdevSystem& system) +:cdevService (name, system), client_ (), fds_ (0), numFds_ (0), + monobjs_ () +{ +#ifdef _TRACE_OBJECTS + printf (" Create rnsService Class Object\n"); +#endif + // register all tags + for (int i = 0; i < rnsService::numtags_; i++) + cdevData::addTag (rnsService::tags_[i]); + + // remember this service + _rnsNameService_ = this; +} + +rnsService::~rnsService (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete rnsService Class Object\n"); +#endif + if (client_.connected ()) + client_.disconnect (); + + if (numFds_ > 0) + delete []fds_; + + // delete all callbacks + cdevSlistIterator ite (monobjs_); + rnsMonitorObj* mobj = 0; + + for (ite.init (); !ite; ++ite) { + mobj = (rnsMonitorObj *) ite (); + delete mobj; + } +} + +int +rnsService::getFd (int* &fd, int& numFd) +{ + fd = fds_; + numFd = numFds_; + return CDEV_SUCCESS; +} + +int +rnsService::flush (void) +{ + return CDEV_SUCCESS; +} + + +int +rnsService::poll (void) +{ + return client_.pendIO (0.001); +} + +int +rnsService::pend (int /* fd */) +{ + return client_.pendIO (); +} + +int +rnsService::pend (double seconds, int) +{ + return client_.pendIO (seconds); +} + +int +rnsService::getRequestObject (char* deviceName, char* msg, + cdevRequestObject* &req) +{ + if (!client_.connected ()) { + char* nsHost = getenv ("CDEV_NAME_SERVER"); + if (!nsHost) { + reportError (CDEV_SEVERITY_SEVERE, serviceName_, 0, + "Cannot find environment variable CDEV_NAME_SERVER !!!"); + req = 0; + return CDEV_ERROR; + } + if (client_.connect (nsHost, RSVC_SERVER_PORT, 3.0) != RSVC_SUCCESS) { + reportError (CDEV_SEVERITY_SEVERE, serviceName_, 0, + "Cannot connect to name server at port %d on %s", + RSVC_SERVER_PORT, nsHost); + req = 0; + return CDEV_ERROR; + } + + if (numFds_ > 0) + delete []fds_; + + fds_ = new int[1]; + numFds_ = 1; + fds_[0] = client_.getFd (); + + // register fd to the system + registerFd (client_.getFd (), 1); + + // register a disconnection callback + if (client_.disconnectCallback (&(rnsService::discCallback), + (void *)this) != RSVC_SUCCESS) + reportError (CDEV_SEVERITY_WARN, serviceName_, 0, + "Cannot register disconnect callback"); + } + req = new rnsRequestObject (deviceName, msg, this, system_); + return CDEV_SUCCESS; +} + +int +rnsService::reconnect (void) +{ + char* nsHost = getenv ("CDEV_NAME_SERVER"); + if (!client_.connected ()) { + if (client_.connect (nsHost, RSVC_SERVER_PORT, 3.0) == RSVC_SUCCESS) { + reportError (CDEV_SEVERITY_INFO, serviceName_, 0, + "Reconnected to name server at port %d on %s", + RSVC_SERVER_PORT, nsHost); + + fds_ = new int[1]; + numFds_ = 1; + fds_[0] = client_.getFd (); + + // register this fd to the sysem + registerFd (client_.getFd(), 1); + + // register a disconnection callback + if (client_.disconnectCallback (&(rnsService::discCallback), + (void *)this) != RSVC_SUCCESS) + reportError (CDEV_SEVERITY_WARN, serviceName_, 0, + "Cannot register disconnect callback"); + + return CDEV_SUCCESS; + } + else + return CDEV_TIMEOUT; + } + return CDEV_SUCCESS; +} + +int +rnsService::getNameServer (cdevDevice* &ns) +{ + ns = 0; + return CDEV_SUCCESS; +} + +cdevService * +newRnsService (char* name, cdevSystem* system) +{ + return new rnsService (name, *system); +} + + +int +rnsService::addMonitorObject (rnsMonitorObj* obj) +{ + cdevSlistIterator ite (monobjs_); + rnsMonitorObj* mobj = 0; + + for (ite.init (); !ite; ++ite) { + mobj = (rnsMonitorObj *) ite (); + if (*(mobj->userCallback_) == *(obj->userCallback_)) + return CDEV_ERROR; + } + monobjs_.add ((void *)obj); + return CDEV_SUCCESS; +} + +int +rnsService::removeMonitorObject (rnsMonitorObj* obj) +{ + cdevSlistIterator ite (monobjs_); + rnsMonitorObj* mobj = 0; + int found = 0; + + for (ite.init (); !ite; ++ite) { + mobj = (rnsMonitorObj *) ite (); + if (mobj == obj) { + found = 1; + break; + } + } + if (found) { + monobjs_.remove ((void *)obj); + return CDEV_SUCCESS; + } + return CDEV_ERROR; +} + +rnsMonitorObj* +rnsService::hasCallback (cdevCallback& cbk) +{ + cdevSlistIterator ite (monobjs_); + rnsMonitorObj* mobj = 0; + + for (ite.init (); !ite; ++ite) { + mobj = (rnsMonitorObj *) ite (); + if (*(mobj->userCallback_) == cbk) + return mobj; + } + return 0; +} + +int +rnsService::monitorsRestarted (void) +{ + cdevSlistIterator ite (monobjs_); + rnsMonitorObj* mobj = 0; + rnsRequestObject* req = 0; + int notdone = 0; + + for (ite.init (); !ite; ++ite) { + mobj = (rnsMonitorObj *)ite (); + if (!mobj->started_) { + notdone = 1; + req = (rnsRequestObject *)mobj->reqObj_; + if (req->action_ == rnsRequestObject::MONITORON) + req->sendMonitor (mobj); + else if (req->action_ == rnsRequestObject::MONITORENTRY) + req->sendEntryMonitor (mobj); + } + } + return !notdone; +} + + +void +rnsService::discCallback (int /* status */, void* arg, rsvcData* /* data */) +{ + rnsService* nsvc = (rnsService *) arg; + + if (nsvc->numFds_ > 0) { + // remove this fd from the system + for (int i = 0; i < nsvc->numFds_; i++) + nsvc->registerFd (nsvc->fds_[i], 0); + + delete [](nsvc->fds_); + nsvc->numFds_ = 0; + } + + cdevSlistIterator ite (nsvc->monobjs_); + rnsMonitorObj* mobj = 0; + cdevCallback* cbk = 0; + cdevRequestObject *req = 0; + cdevData empty; + + for (ite.init (); !ite; ++ite) { + mobj = (rnsMonitorObj *) ite (); + + cbk = mobj->userCallback_; + req = mobj->reqObj_; + cbk->fireCallback (CDEV_DISCONNECTED, cbk->userarg (), + *req, empty, 0); + mobj->started_ = 0; + } + +#ifdef _WIN32 + SetTimer (NULL, 0, 1000*_RNS_CLIENT_RECONN_TIMEOUT, _rnsAlarmHandler_); +#else + // register a alarm handler to try to connect to the name server + struct sigaction act; + + act.sa_handler = _rnsAlarmHandler_; + sigemptyset (&act.sa_mask); + act.sa_flags = 0; + + if (sigaction (SIGALRM, &act, &_oldaction_) < 0) + cdevSystem::defaultSystem().reportError( + CDEV_SEVERITY_ERROR, "RNS Service", NULL, + "Cannot register alarm signal handler"); + else + alarm (_RNS_CLIENT_RECONN_TIMEOUT); +#endif +} diff --git a/extensions/cdevGenericServer/NameServer/cdev/rnsService.h b/extensions/cdevGenericServer/NameServer/cdev/rnsService.h new file mode 100755 index 0000000..a96580b --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rnsService.h @@ -0,0 +1,128 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of cdev interface to resouce service client +// +// This is only a subset of whole APIs of rsvc client +// +// Author: Jie Chen +// +// +// +#ifndef _NS_SERVICE_H +#define _NS_SERVICE_H + +#ifndef _CDEV_MANAGE_SERVERS +#define _CDEV_MANAGE_SERVERS +#endif + +#include +#include +#include +#include +#include +#include +#include + +extern "C" RSVCAPI cdevService * newRnsService (char* name, cdevSystem* system); + +class rnsMonitorObj; +class rnsRequestObject; + +class rnsService: public cdevService +{ +public: + // cornstructor + rnsService (char* name, cdevSystem& system = cdevSystem::defaultSystem ()); + + int getFd (int * &fd, int &numFd); + // PURPOSE: return channel access network file descriptors + // REQUIRE: callers provide pointer only and don't free memory + // PROMISE: numFd will be real number of file descriptors of the + // channel access client. return 0: always + + int flush (void); + // PURPOSE: flush network requests + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS: success + + int poll (void); + // PURPOSE: polling method + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS: success. Else error + + int pend (int fd = -1); + // PURPOSE: handle network pending + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS: success, else error + + int pend (double seconds, int fd = -1); + // PURPOSE: handle network pending for 'seconds' + // REQUIRE: nothing + // PROMISE: return 0: success. return CDEV_TIMEOUT for timeout + + int getRequestObject (char *deviceName, char *msg, + cdevRequestObject * &req); + // PURPOSE: return a rnsRequestObject (called from attachPtr function + // of cdevRequestObject class) + // REQUIRE: right pair of deviceName and msg. + // PROMISE: a rnsRequestObject + + int getNameServer (cdevDevice* &rns); + // PURPOSE: retrieve ca name server in case of missing DDL + // REQUIRE: nothing + // PROMISE: + + int monitorsRestarted (void); + // PURPOSE: check whether all monitors have been restarted or not + // REQUIRE: nothing + // PROMISE: 1: yes, 0: no + + int reconnect (void); + // PURPOSE: reconnect to name server + // REQUIRE: nothing + // PROMISE: CDEV_SUCCESS on sucessful connection + + const char* className (void) const {return "rnsService";} + +protected: + + // deny direct access to destructor + ~rnsService (void); + + // add a monitor object + int addMonitorObject (rnsMonitorObj* obj); + // remove a monitor object + int removeMonitorObject (rnsMonitorObj* obj); + // check whether this callback is in the list + rnsMonitorObj* hasCallback (cdevCallback& cbk); + + // server disconnection callback + static void discCallback (int status, void* arg, rsvcData* data); + +private: + rsvcClient client_; + int *fds_; + int numFds_; + + // list of monitor object + cdevSlist monobjs_; + + // all tags needed for this service + static char* tags_[]; + + // number of tags needed for this service + static int numtags_; + + // friend class + friend class rnsRequestObject; +}; +#endif + diff --git a/extensions/cdevGenericServer/NameServer/cdev/rsvcCallback.cc b/extensions/cdevGenericServer/NameServer/cdev/rsvcCallback.cc new file mode 100755 index 0000000..73c7cd4 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rsvcCallback.cc @@ -0,0 +1,94 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcCallback Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcCallback.cc,v +// Revision 1.1 1998/01/22 17:08:00 akers +// Addition of new NameServer +// +// +// +#include "rsvcCallback.h" + +rsvcCallback::rsvcCallback (void) +:cbk_ (0), arg_ (0) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcCallback Class Object\n"); +#endif +} + +rsvcCallback::rsvcCallback (rsvcCbkFunc func, void* arg) +:cbk_ (func), arg_ (arg) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcCallback Class Object\n"); +#endif +} + +rsvcCallback::rsvcCallback (const rsvcCallback& cbk) +:cbk_ (cbk.cbk_), arg_ (cbk.arg_) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcCallback Class Object\n"); +#endif +} + +rsvcCallback & +rsvcCallback::operator = (const rsvcCallback& cbk) +{ + if (this != &cbk) { + cbk_ = cbk.cbk_; + arg_ = cbk.arg_; + } + return *this; +} + +rsvcCallback::~rsvcCallback (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcCallback Class Object\n"); +#endif +} + +int +rsvcCallback::operator == (const rsvcCallback& cbk) +{ + return (cbk_ == cbk.cbk_ && arg_ == cbk.arg_); +} + +int +rsvcCallback::operator != (const rsvcCallback& cbk) +{ + return !(cbk_ == cbk.cbk_ && arg_ == cbk.arg_); +} + +rsvcCbkFunc +rsvcCallback::cbkFunc (void) const +{ + return cbk_; +} + +void * +rsvcCallback::userarg (void) const +{ + return arg_; +} + +int +rsvcCallback::empty (void) +{ + return !cbk_; +} + diff --git a/extensions/cdevGenericServer/NameServer/cdev/rsvcCbk.cc b/extensions/cdevGenericServer/NameServer/cdev/rsvcCbk.cc new file mode 100755 index 0000000..637d481 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rsvcCbk.cc @@ -0,0 +1,377 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcCbk class +// +// Author: Jie Chen +// +// Revision History: +// rsvcCbk.cc,v +// Revision 1.1 1998/01/22 17:08:01 akers +// Addition of new NameServer +// +// +// +#include +#include +#include + +#ifdef _WIN32 + #include +#else + #include +#endif + +#include +#include "rsvcCbk.h" + +rsvcCbk::rsvcCbk (void) +:rsvcStreamable (), rsvcHashable (), + opcode_ (RSVC_OP_UNKNOWN), cbkid_ (0), reqid_ (0), + clientid_ (0), socketid_ (0), status_ (RSVC_SUCCESS), private_ (0) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcCbk Class Object\n"); +#endif + + // empty +} + +rsvcCbk::rsvcCbk (int opcode, int cbkid, int reqid, + int clientid, int socketid, int status, void* ptr) +:rsvcStreamable (), rsvcHashable (), + opcode_ (opcode), cbkid_ (cbkid), reqid_ (reqid), + clientid_ (clientid), socketid_ (socketid), + status_ (status), private_ (ptr) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcCbk Class Object\n"); +#endif + // empty +} + +rsvcCbk::rsvcCbk (const rsvcCbk& cbk) +:rsvcStreamable (), rsvcHashable (), + opcode_ (cbk.opcode_), cbkid_ (cbk.cbkid_), reqid_ (cbk.reqid_), + clientid_ (cbk.clientid_), socketid_ (cbk.socketid_), + status_ (cbk.status_), private_ (cbk.private_) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcCbk Class Object\n"); +#endif + // empty +} + +rsvcCbk & +rsvcCbk::operator = (const rsvcCbk& cbk) +{ + if (this != &cbk) { + opcode_ = cbk.opcode_; + cbkid_ = cbk.cbkid_; + reqid_ = cbk.reqid_; + clientid_ = cbk.clientid_; + socketid_ = cbk.socketid_; + status_ = cbk.status_; + private_ = cbk.private_; + } + return *this; +} + +rsvcCbk::~rsvcCbk (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcCbk Class Object\n"); +#endif + // empty +} + + +void +rsvcCbk::cleanup (void) +{ + opcode_ = 0; + cbkid_ = 0; + reqid_ = 0; + clientid_ = 0; + socketid_ = 0; + status_ = 0; + private_ = 0; +} + +void +rsvcCbk::socketid (int socketid) +{ + socketid_ = socketid; +} + +int +rsvcCbk::socketid (void) const +{ + return socketid_; +} + +void +rsvcCbk::cbkstatus (int st) +{ + status_ = st; +} + +int +rsvcCbk::cbkstatus (void) const +{ + return status_; +} + +int +rsvcCbk::opcode (void) const +{ + return opcode_; +} + +void +rsvcCbk::opcode (int op) +{ + opcode_ = op; +} + +int +rsvcCbk::reqid (void) const +{ + return reqid_; +} + +void +rsvcCbk::reqid (int req) +{ + reqid_ = req; +} + +int +rsvcCbk::cbkid (void) const +{ + return cbkid_; +} + +void +rsvcCbk::cbkid (int id) +{ + cbkid_ = id; +} + +int +rsvcCbk::clientid (void) const +{ + return clientid_; +} + +void +rsvcCbk::clientid (int cid) +{ + clientid_ = cid; +} + +void * +rsvcCbk::userptr (void) const +{ + return private_; +} + +void +rsvcCbk::userptr (void* ptr) +{ + private_ = ptr; +} + +size_t +rsvcCbk::streamSize (void) +{ + return 6*sizeof (int); +} + +int +rsvcCbk::streamOut (char** buf, size_t* len) +{ + char* buffer = new char[6*sizeof (int)]; + + if (buffer == 0) { + fprintf (stderr, "Allocate buffer for rsvcCbk error, quit\n"); + exit (1); + } + + *len = 6*sizeof (int); + *buf = buffer; + + int tmp; + int i = 0; + + tmp = htonl (opcode_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (cbkid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (reqid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (clientid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (socketid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (status_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + return RSVC_SUCCESS; +} + +int +rsvcCbk::streamOut (char* buffer, size_t len) +{ + if (buffer == 0) { + fprintf (stderr, "Allocate buffer for rsvcCbk error, quit\n"); + exit (1); + } + + if (len < 6*sizeof (int)) { + fprintf (stderr, "Streaming out rsvcCbk has not enough buffer size\n"); + return RSVC_OVERFLOW; + } + + int tmp; + int i = 0; + + tmp = htonl (opcode_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (cbkid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (reqid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (clientid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (socketid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (status_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + return RSVC_SUCCESS; +} + +int +rsvcCbk::streamIn (char* buffer, size_t len) +{ + if (buffer == 0) { + fprintf (stderr, "Stream in buffer == 0 error, quit\n"); + exit (1); + } + + if (len < 6*sizeof (int)) { + fprintf (stderr, "Streaming in rsvcCbk has not enough buffer size\n"); + return RSVC_OVERFLOW; + } + + int tmp; + int i = 0; + + memcpy (&tmp, &(buffer[i]), sizeof (int)); + i += sizeof (int); + opcode_ = ntohl (tmp); + + memcpy (&tmp, &(buffer[i]), sizeof (int)); + i += sizeof (int); + cbkid_ = ntohl (tmp); + + memcpy (&tmp, &(buffer[i]), sizeof (int)); + i += sizeof (int); + reqid_ = ntohl (tmp); + + memcpy (&tmp, &(buffer[i]), sizeof (int)); + i += sizeof (int); + clientid_ = ntohl (tmp); + + memcpy (&tmp, &(buffer[i]), sizeof (int)); + i += sizeof (int); + socketid_ = ntohl (tmp); + + memcpy (&tmp, &(buffer[i]), sizeof (int)); + i += sizeof (int); + status_ = ntohl (tmp); + + return RSVC_SUCCESS; +} + +int +rsvcCbk::sameCallback (rsvcCbk* cbk1, rsvcCbk* cbk2, + int checkreq) +{ + if (checkreq) { + if (cbk1->reqid_ == cbk2->reqid_ && + cbk1->clientid_ == cbk2->clientid_ && + cbk1->socketid_ == cbk2->socketid_ && + cbk1->cbkid_ == cbk2->cbkid_) + return 1; + else + return 0; + } + else { + if (cbk1->clientid_ == cbk2->clientid_ && + cbk1->socketid_ == cbk2->socketid_ && + cbk1->cbkid_ == cbk2->cbkid_) + return 1; + else + return 0; + } +} + + +int +rsvcCbk::match (rsvcCbk* cbk) +{ + if (opcode_ == cbk->opcode_ && + reqid_ == cbk->reqid_ && + clientid_ == cbk->clientid_ && + cbkid_ == cbk->cbkid_) + return 1; + return 0; +} + +unsigned int +rsvcCbk::hash (void) +{ + // return hash value of callback id + unsigned int h = 0; + unsigned char *k, *e; + + k = (unsigned char *)&cbkid_; + e = k + sizeof (int); + for (h = 0; k < e; ++k) { + h *= 16777619; + h ^= *k; + } + return h; +} + diff --git a/extensions/cdevGenericServer/NameServer/cdev/rsvcClient.cc b/extensions/cdevGenericServer/NameServer/cdev/rsvcClient.cc new file mode 100755 index 0000000..3876310 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rsvcClient.cc @@ -0,0 +1,1119 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcClient Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcClient.cc,v +// Revision 1.8 1998/03/19 18:30:56 chen +// add monitorEntry capability to server table +// +// Revision 1.6 1998/02/25 19:52:55 chen +// keep alive option on +// +// Revision 1.5 1998/02/24 14:13:39 chen +// remove errno check on read_n +// +// Revision 1.4 1998/02/20 19:37:28 chen +// reset errno after using it (hpux) sometimes not resetting it +// +// Revision 1.3 1998/02/06 15:12:32 chen +// add connection management to the name server +// +// Revision 1.2 1998/01/22 20:04:06 chen +// to make it work with cdevReactor +// +// Revision 1.1 1998/01/22 17:08:02 akers +// Addition of new NameServer +// +// +// +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include + +#define RSVC_ERRNO WSAGetLastError() +#define EADDRINUSE WSAEADDRINUSE +#define EINPROGRESS WSAEINPROGRESS +#define SYSINTR WSAEINTR +#define EISCONN WSAEISCONN +#define ETIMEDOUT WSAETIMEDOUT +#define EWOULDBLOCK WSAEWOULDBLOCK + +#define RSVC_SET_ERRNO(e) WSASetLastError(e) + +#define SOCKOPT_VALUE_PTR (const char *) + +#else /* _WIN32 */ +#include +#include +#include +#include + +#define RSVC_ERRNO errno +#define SYSINTR EINTR +#define RSVC_SET_ERRNO(e) errno=e + +#ifndef solaris +#define SOCKOPT_VALUE_PTR (void *) +#else +#define SOCKOPT_VALUE_PTR (char *) +#endif + +#endif + +#if defined(AIX) || defined(__linux) + typedef unsigned int SOCKOPT_SIZE_PARM; +#else + typedef int SOCKOPT_SIZE_PARM; +#endif + +#include +#include "rsvcClient.h" + +rsvcClient::rsvcClient (void) +:connected_ (0), tcp_fd_ (-1), server_host_ (0), server_port_ (0), + lock_ (0), reqid_ (1234), cbkid_ (93), discCbkList_ (), cmdCbkList_ (), + monitorCbkTable_ (1000, 3) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcClient Class Object\n"); +#endif + +#ifdef _WIN32 + WORD wVersion; + WSADATA wsaData; + + wVersion = MAKEWORD (2, 0); /* WinSock 2.0 */ + if (WSAStartup (wVersion, &wsaData) != 0) { + WSACleanup (); + fprintf (stderr, "rsvcClient: Cannot initialize win socket\n"); + } +#endif + + cbuflen_ = 4096; + cbuffer_ = new char[cbuflen_]; + if (!cbuffer_) { + fprintf (stderr, "rsvcClient Fatal: malloc error\n"); + exit (1); + } +} + +rsvcClient::~rsvcClient (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcClient Class Object\n"); +#endif + + if (server_host_) + delete []server_host_; + + if (connected_) + disconnect (); + + delete []cbuffer_; + +#ifdef _WIN32 + WSACleanup (); +#endif +} + +int +rsvcClient::connect (char* host, unsigned short port, + double seconds) +{ + if (connected_) + return RSVC_SUCCESS; + + struct hostent* phe = 0; + struct sockaddr_in sin; + + memset (&sin, 0, sizeof (sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons (port); + + if (phe = gethostbyname (host)) + memcpy (&sin.sin_addr, phe->h_addr, phe->h_length); + else { + fprintf (stderr, "RSVC Client: gethostbyname %s error\n", host); + return RSVC_ERROR; + } + + tcp_fd_ = socket (AF_INET, SOCK_STREAM, 0); + + if (tcp_fd_ < 0) { + fprintf (stderr, "RSVC Client: cannot create tcp socket\n"); + return RSVC_ERROR; + } + + // if timeout is zero we do simple blocked connect + int status; + if (seconds < 0.00001) { + if ((status = ::connect (tcp_fd_, (struct sockaddr *)&sin, + sizeof (sin))) < 0) { + fprintf (stderr, "RSVC Client: cannot connect to server %s@%d\n", + host, port); + return RSVC_ERROR; + } + else { + connected_ = 1; + + // remember the server information + if (server_host_) + delete server_host_; + server_host_ = new char[strlen (host) + 1]; + strcpy (server_host_, host); + server_port_ = port; + + // set socket option keep alive + int alive = 1; + setsockopt (tcp_fd_, SOL_SOCKET, SO_KEEPALIVE, SOCKOPT_VALUE_PTR &alive, + (SOCKOPT_SIZE_PARM)sizeof (alive)); + return RSVC_SUCCESS; + } + } + else { + struct timeval timeout; + + timeout.tv_sec = (int)seconds; + timeout.tv_usec = (int) ((seconds - timeout.tv_sec)*1000000); + if (connect_nonblock (tcp_fd_, (struct sockaddr *)&sin, + sizeof (sin), &timeout) != RSVC_SUCCESS) { + close (tcp_fd_); + tcp_fd_ = -1; + return RSVC_ERROR; + } + connected_ = 1; + + // remember the server information + if (server_host_) + delete server_host_; + server_host_ = new char[strlen (host) + 1]; + strcpy (server_host_, host); + server_port_ = port; + + // set socket option keep alive + int alive = 1; + setsockopt (tcp_fd_, SOL_SOCKET, SO_KEEPALIVE, SOCKOPT_VALUE_PTR &alive, + (SOCKOPT_SIZE_PARM)sizeof (alive)); + return RSVC_SUCCESS; + } +} + +int +rsvcClient::connect_nonblock (int sockfd, struct sockaddr* addr, + size_t addrlen, struct timeval* timeout) +{ + int flags, n, error; + int len; + fd_set rset, wset; + +#ifndef _WIN32 + // set non block mode + flags = fcntl (sockfd, F_GETFL, 0); + fcntl (sockfd, F_SETFL, flags | O_NONBLOCK); +#endif + + error = 0; + + if ((n = ::connect (sockfd, addr, addrlen)) < 0) { + if (errno != EINPROGRESS && errno != EWOULDBLOCK) + return RSVC_ERROR; + } + + if (n == 0) + goto connect_done; // connection complete + + FD_ZERO (&rset); + FD_SET (sockfd, &rset); + memcpy (&wset, &rset, sizeof (rset)); + +#ifdef _SELECT_USES_INT_ + if ((n = select (sockfd + 1, (int *)&rset, (int *)&wset, (int *)0, timeout)) == 0) +#else + if ((n = select (sockfd + 1, &rset, &wset, 0, timeout)) == 0) +#endif + { + // timeout + RSVC_SET_ERRNO (ETIMEDOUT); + return RSVC_ERROR; + } + if (FD_ISSET (sockfd, &rset) || FD_ISSET (sockfd, &wset)) { + len = sizeof (error); + if (getsockopt (sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, (SOCKOPT_SIZE_PARM *)&len) < 0) + return RSVC_ERROR; // solaris pending error + } + else + return RSVC_ERROR; + +connect_done: +#ifndef _WIN32 + // restore old flag + fcntl (sockfd, F_SETFL, flags); +#endif + + if (error) { + RSVC_SET_ERRNO(error); + return RSVC_ERROR; + } + return RSVC_SUCCESS; +} + +int +rsvcClient::disconnect (void) +{ + if (connected_) { + shutdown (tcp_fd_, 0); + close (tcp_fd_); + tcp_fd_ = -1; + connected_ = 0; + + // remove all callbacks + cleanupCallbacks (); + } + return RSVC_SUCCESS; +} + +int +rsvcClient::connected (void) +{ + return connected_; +} + +int +rsvcClient::disconnectCallback (rsvcCbkFunc func, void* arg) +{ + rsvcCallback* cbk = new rsvcCallback (func, arg); + + rsvcSlistIterator ite (discCbkList_); + rsvcCallback* tcbk = 0; + int error = 0; + + for (ite.init (); !ite; ++ite) { + tcbk = (rsvcCallback *) ite (); + if (*tcbk == *cbk) { + error = 1; + break; + } + } + if (!error) { + discCbkList_.add ((void *)cbk); + return RSVC_SUCCESS; + } + delete cbk; + return RSVC_ERROR; +} + + +void +rsvcClient::cleanupCallbacks (void) +{ + // delete everything from disconnect callback list + rsvcSlistIterator ite (discCbkList_); + rsvcCallback* cbk = 0; + + for (ite.init (); !ite; ++ite) { + cbk = (rsvcCallback *) ite (); + delete cbk; + } + discCbkList_.deleteAllValues (); + + // delete all from command callback list + rsvcSlistIterator cite (cmdCbkList_); + rsvcCbk* scbk = 0; + + for (cite.init (); !cite; ++cite) { + scbk = (rsvcCbk *) cite (); + cbk = (rsvcCallback *)scbk->userptr (); + delete cbk; + delete scbk; + } + cmdCbkList_.deleteAllValues (); + + // delete all from monitor table + rsvcHashIterator hite (monitorCbkTable_); + + for (hite.init (); !hite; ++hite) { + scbk = (rsvcCbk *) hite (); + cbk = (rsvcCallback *)scbk->userptr (); + delete cbk; + delete scbk; + } + monitorCbkTable_.deleteAllValues (); +} + +void +rsvcClient::callAllDiscCbks (void) +{ + rsvcSlistIterator ite (discCbkList_); + rsvcCallback* cbk = 0; + rsvcCbkFunc func = 0; + void *arg = 0; + + for (ite.init (); !ite; ++ite) { + cbk = (rsvcCallback *)ite (); + func = cbk->cbkFunc (); + arg = cbk->userarg (); + (*func)(RSVC_DISCONNECTED, arg, (rsvcData *)0); + } +} + + +int +rsvcClient::getFd (void) const +{ + return tcp_fd_; +} + +int +rsvcClient::pendIO (double seconds) +{ + // first prevent recursice calling from a callback + if (lock_) + return RSVC_INVALID; + + if (tcp_fd_ == -1) + return RSVC_BADIO; + + int nfound = 0; + fd_set readfd; + struct timeval tv; + + if (seconds <= 0.000001) { + tv.tv_sec = 0; + tv.tv_usec = 0; + } + else { + tv.tv_sec = (int)seconds; + tv.tv_usec = (int)((seconds - tv.tv_sec)*1000000); + } + + FD_ZERO (&readfd); + FD_SET (tcp_fd_, &readfd); + + do { +#ifndef __hpux + nfound = select (tcp_fd_ + 1, &readfd, 0, 0, &tv); +#else + +#ifdef _SELECT_USES_INT_ + nfound = select (tcp_fd_ + 1, (int *)&readfd, (int *)0, (int *)0, + &tv); +#else + nfound = select (tcp_fd_ + 1, &readfd, 0, 0, &tv); +#endif + +#endif + }while (nfound == -1 && errno == SYSINTR); + + if (nfound == -1) { // something wrong with tcp_fd_ + fprintf (stderr, "rsvcClient: Bad tcp fd %d\n", tcp_fd_); + tcp_fd_ = -1; + return RSVC_BADIO; + } + else if (nfound == 0) // timeout + return RSVC_TIMEOUT; + else { + if (FD_ISSET (tcp_fd_, &readfd)) { + if (handle_input (tcp_fd_) < 0) { // bad io + handle_close (tcp_fd_); + return RSVC_IOERROR; + } + } + } + return RSVC_SUCCESS; +} + +int +rsvcClient::pendIO (void) +{ + if (lock_) + return RSVC_INVALID; + + if (tcp_fd_ == -1) + return RSVC_BADIO; + + int nfound = 0; + fd_set readfd; + + FD_ZERO (&readfd); + FD_SET (tcp_fd_, &readfd); + + do { +#ifndef __hpux + nfound = select (tcp_fd_ + 1, &readfd, 0, 0, 0); +#else + +#ifdef _SELECT_USES_INT_ + nfound = select (tcp_fd_ + 1, (int *)&readfd, (int *)0, (int *)0, + (struct timeval *)0); +#else + nfound = select (tcp_fd_ + 1, &readfd, 0, 0, 0); +#endif + +#endif + }while (nfound == -1 && errno == EINTR); + + if (nfound == -1) { // something wrong with tcp_fd_ + fprintf (stderr, "rsvcClient: bad tcp fd %d\n", tcp_fd_); + tcp_fd_ = -1; + return RSVC_BADIO; + } + else if (nfound == 0) // timeout + return RSVC_TIMEOUT; + else { + if (FD_ISSET (tcp_fd_, &readfd)) { + if (handle_input (tcp_fd_) < 0) { // bad io + handle_close (tcp_fd_); + return RSVC_IOERROR; + } + } + } + return RSVC_SUCCESS; +} + +int +rsvcClient::handle_input (int) +{ + int n; + rsvcNetData ndata; + + // lock thus event processing function to prevent a recursive call + rsvcClientLocker locker (this); + + // read header information + char header[32]; + n = rsvcClient::read_n (tcp_fd_, header, rsvcNetData::headerLen ()); + if (n != rsvcNetData::headerLen ()) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: Receiving netdata header error\n"); +#endif + printf ("rsvcClient: Server is dead\n"); + return -1; + } + + size_t datasize; + if (rsvcNetData::readHeader (header, n, &datasize) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: reading netdata header error\n"); +#endif + return -1; + } + + if (datasize > cbuflen_) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: incoming data size %d > %d, resize\n", + datasize, cbuflen_); +#endif + delete []cbuffer_; + cbuflen_ = 2*datasize; + cbuffer_ = new char[cbuflen_]; + if (!cbuffer_) { + fprintf (stderr, "rsvcClientIO: malloc error in hanlde_input\n"); + exit (1); + } + } + + // now really try to read data + n = rsvcClient::read_n (tcp_fd_, cbuffer_, datasize); + if (n != datasize) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: Received %d bytes != %d bytes\n", + n, datasize); +#endif + return -1; + } + + // convert data + if (ndata.streamIn (cbuffer_, datasize) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: stream in netdata error\n"); +#endif + return -1; + } + + return processData (ndata); +} + +int +rsvcClient::handle_close (int) +{ + shutdown (tcp_fd_, 0); + close (tcp_fd_); + tcp_fd_ = -1; + connected_ = 0; + + // call all disconnect callback + callAllDiscCbks (); + + // cleanup all callbacks + cleanupCallbacks (); + + return 0; +} + + +int +rsvcClient::processData (rsvcNetData& ndata) +{ + rsvcData& data = ndata.data (); + rsvcCbk& cbk = ndata.cbk (); + int op = cbk.opcode (); + int status = 0; + + if (op < RSVC_MONITOR_ON) { + // all simple transaction callback + status = cmdCbkFromServer ((int)cbk.cbkstatus (), data, cbk); + } + else if (op < RSVC_OP_UNKNOWN){ + // all monitor callbacks + status = monitorCbkFromServer ((int)cbk.cbkstatus (), data, cbk); + } + else { + fprintf (stderr, "rsvcClient: Invalid operation code\n"); + status = -1; + } + return status; +} + +int +rsvcClient::cmdCbkFromServer (int status, rsvcData& data, rsvcCbk& cbk) +{ + rsvcSlistIterator ite (cmdCbkList_); + rsvcCbk* tcbk = 0; + rsvcCallback* rcbk = 0; + int found = 0; + + for (ite.init (); !ite; ++ite) { + tcbk = (rsvcCbk *) ite (); + if (tcbk->match (&cbk)) { + found = 1; + rcbk = (rsvcCallback *)tcbk->userptr (); + (*rcbk->cbkFunc() )(status, rcbk->userarg (), &data); + } + } + if (found && status != RSVC_INCOMPLETE) { + cmdCbkList_.remove ((void *)tcbk); + delete rcbk; + delete tcbk; + } + else { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: Callback from server does not match any\n"); +#endif + } + + return 0; +} + +int +rsvcClient::monitorCbkFromServer (int status, rsvcData& data, + rsvcCbk& cbk) +{ + rsvcHSlist& list = monitorCbkTable_.bucketRef (&cbk); + rsvcHSlistIterator ite (list); + + rsvcCbk* tcbk = 0; + rsvcCallback* rcbk = 0; + int found = 0; + + for (ite.init (); !ite; ++ite) { + tcbk = (rsvcCbk *) ite (); + if (tcbk->match (&cbk)) { + found = 1; + rcbk = (rsvcCallback *)tcbk->userptr (); + (*rcbk->cbkFunc())(status, rcbk->userarg (), &data); + } + } + if (found && cbk.cbkstatus () != RSVC_SUCCESS + && cbk.cbkstatus () != RSVC_INCOMPLETE) { + // if callback is bad or finished remove it from the list + list.remove (tcbk); + delete rcbk; + delete tcbk; + } + else if (cbk.cbkstatus () != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: monitorCallback from server does not match any\n"); + printf ("rsvcClient: cbk has %d %d %d %d %d\n", + cbk.opcode (), cbk.reqid (), cbk.cbkid (), cbk.clientid (), + cbk.cbkstatus()); +#endif + } + + return 0; +} + + +int +rsvcClient::createMemDbase (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = commandCallback ((int)RSVC_CREATE_MEMTABLE, data, + func, arg); + return status; +} + + +int +rsvcClient::openDatabase (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = commandCallback ((int)RSVC_OPEN_DBASE, data, + func, arg); + return status; +} + +int +rsvcClient::insertValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg, int overwrite) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else { + if (!overwrite) + status = commandCallback ((int)RSVC_INSERT, data, + func, arg); + else + status = commandCallback ((int)RSVC_OVERWRITE, data, + func, arg); + } + return status; +} + +int +rsvcClient::getValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = commandCallback ((int)RSVC_GET, data, + func, arg); + return status; +} + + +int +rsvcClient::delValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = commandCallback ((int)RSVC_DEL, data, + func, arg); + return status; +} + +int +rsvcClient::setValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = commandCallback ((int)RSVC_SET, data, + func, arg); + return status; +} + + +int +rsvcClient::commandCallback (int opcode, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + size_t nbytes = 0; + size_t nw = 0; + + rsvcCallback* cbk = new rsvcCallback (func, arg); + rsvcCbk* cbkid = new rsvcCbk (opcode, cbkid_++, + reqid_++, tcp_fd_, 0, + RSVC_SUCCESS, (void *)cbk); + + // create netdata + rsvcNetData netdata (data, *cbkid); + + if ((nbytes = streamData (netdata)) <= 0) + status = RSVC_ERROR; + else { + // block write + if ((nw = rsvcClient::write_n (tcp_fd_, cbuffer_, nbytes)) != nbytes) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: wrote %d nbytes and expect to write %d bytes\n", + nw, nbytes); +#endif + status = RSVC_ERROR; + } + else + // register callback and so on + cmdCbkList_.add ((void *)cbkid); + } + if (status != RSVC_SUCCESS) { + delete cbkid; + delete cbk; + } + + return status; +} + + +int +rsvcClient::monitorValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = monitorCallback ((int)RSVC_MONITOR_ON, data, + func, arg); + return status; +} + +int +rsvcClient::monitorOffValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = monitorOffCallback ((int)RSVC_MONITOR_OFF, data, + func, arg); + return status; +} + +int +rsvcClient::monitorIncomingEntries (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = monitorCallback ((int)RSVC_MONITOR_ENTRIES, data, + func, arg); + + return status; +} + +int +rsvcClient::monitorOffIncomingEntries (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = monitorOffCallback ((int)RSVC_MONITOR_OFFENTRIES, data, + func, arg); + + return status; +} + + +int +rsvcClient::monitorCallback (int opcode, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + size_t nbytes = 0; + size_t nw = 0; + + // this callback is in the table already + if (monitorCbkInTable (func, arg) != 0) { + printf ("rsvcClient: monitor callback function already in use\n"); + return RSVC_INVALIDARG; + } + + rsvcCallback* cbk = new rsvcCallback (func, arg); + rsvcCbk* cbkid = new rsvcCbk (opcode, cbkid_++, + reqid_++, tcp_fd_, 0, + RSVC_SUCCESS, (void *)cbk); + + + // create netdata + rsvcNetData netdata (data, *cbkid); + + if ((nbytes = streamData (netdata)) <= 0) + status = RSVC_ERROR; + else { + // block write + if ((nw = rsvcClient::write_n (tcp_fd_, cbuffer_, nbytes)) != nbytes) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: wrote %d nbytes and expect to write %d bytes\n", + nw, nbytes); +#endif + status = RSVC_ERROR; + } + else + // register callback and so on + monitorCbkTable_.add (cbkid); + } + + if (status != RSVC_SUCCESS) { + delete cbkid; + delete cbk; + } + return status; +} + +int +rsvcClient::monitorOffCallback (int opcode, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + size_t nbytes = 0; + size_t nw = 0; + rsvcCbk* cbk = 0; + + + if ((cbk = monitorCbkInTable (func, arg)) == 0) + return RSVC_INVALIDARG; + + // create netdata + // change cbk opcode into monitor off + cbk->opcode (opcode); + rsvcNetData netdata (data, *cbk); + + if ((nbytes = streamData (netdata)) <= 0) + status = RSVC_ERROR; + else { + // block write + if ((nw = rsvcClient::write_n (tcp_fd_, cbuffer_, nbytes)) != nbytes) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: wrote %d nbytes and expect to write %d bytes\n", + nw, nbytes); +#endif + status = RSVC_ERROR; + } + } + + return status; +} + +rsvcCbk* +rsvcClient::monitorCbkInTable (rsvcCbkFunc func, void* arg) +{ + rsvcHashIterator ite (monitorCbkTable_); + rsvcCbk* tcbk = 0; + rsvcCallback* usrcbk0 = 0; + int found = 0; + rsvcCallback tmp (func, arg); + + for (ite.init (); !ite; ++ite) { + tcbk = (rsvcCbk *) ite (); + usrcbk0 = (rsvcCallback *)tcbk->userptr (); + if (*usrcbk0 == tmp) { + found = 1; + break; + } + } + if (found) + return tcbk; + return 0; +} + +int +rsvcClient::monitorAttr (char* name, char* attr, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + + + if (data.insert (RSVC_MONITOR_TAG, attr) != RSVC_SUCCESS) + status = RSVC_ERROR; + + if (status == RSVC_SUCCESS) + status = monitorCallback ((int)RSVC_MONITOR_ONATTR, data, + func, arg); + return status; +} + +int +rsvcClient::monitorOffAttr (char* name, char* attr, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + + if (data.insert (RSVC_MONITOR_TAG, attr) != RSVC_SUCCESS) + status = RSVC_ERROR; + + if (status == RSVC_SUCCESS) + status = monitorOffCallback ((int)RSVC_MONITOR_OFFATTR, data, + func, arg); + return status; +} + +int +rsvcClient::query (char* name, char* qmsg, + rsvcCbkFunc func, void *arg) +{ + int status = RSVC_SUCCESS; + rsvcData data; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + + if (data.insert (RSVC_QUERY_TAG, qmsg) != RSVC_SUCCESS) + status = RSVC_ERROR; + + if (status == RSVC_SUCCESS) + status = commandCallback ((int)RSVC_QUERY, data, + func, arg); + return status; +} + +void +rsvcClient::shutdownServer (void) +{ + rsvcData data; + + commandCallback ((int)RSVC_SERVER_EXIT, data, 0, 0); +} + +int +rsvcClient::streamData (rsvcNetData& data) +{ + size_t datasize = data.streamSize (); + + if (datasize > cbuflen_) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: Streamed data size %d is exceeding %d, resize\n", + datasize, cbuflen_); +#endif + delete []cbuffer_; + cbuflen_ = 2*datasize; + cbuffer_ = new char[cbuflen_]; + if (!cbuffer_) { + fprintf (stderr, "rsvcClient: malloc error on stream data\n"); + exit (1); + } + } + if (data.streamOut (cbuffer_, datasize) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: rsvcNetData stream out error\n"); +#endif + return -1; + } + return datasize; +} + +int +rsvcClient::write_n (int fd, const char* buffer, size_t len) +{ + size_t bytes_written; + int n; + + for (bytes_written = 0; bytes_written < len; bytes_written += n) + { +#ifdef _WIN32 + n = ::send (fd, buffer + bytes_written, len - bytes_written, 0); +#else + n = ::write (fd, buffer + bytes_written, len - bytes_written); +#endif + if (n == -1) { + return -1; + } + } + return bytes_written; +} + +int +rsvcClient::read_n (int fd, char* buffer, size_t len) +{ + size_t bytes_read; + int n = 0; + + for (bytes_read = 0; bytes_read < len; bytes_read += n) + { +#ifdef _WIN32 + n = ::recv (fd, buffer + bytes_read, len - bytes_read, 0); +#else + n = ::read (fd, buffer + bytes_read, len - bytes_read); +#endif + if (n == -1) + return -1; + else if (n == 0) + break; + } + return bytes_read; +} + +void +rsvcClient::lock (void) +{ + lock_ = 1; +} + +void +rsvcClient::unlock (void) +{ + lock_ = 0; +} + + +//============================================================ +// Implemenation of rsvcClientLocker Class +//============================================================ +rsvcClientLocker::rsvcClientLocker (rsvcClient* client) + :cl_ (client) +{ + cl_->lock (); +} + +rsvcClientLocker::~rsvcClientLocker (void) +{ + cl_->unlock (); +} + + + + + diff --git a/extensions/cdevGenericServer/NameServer/cdev/rsvcData.cc b/extensions/cdevGenericServer/NameServer/cdev/rsvcData.cc new file mode 100755 index 0000000..23d9ca5 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rsvcData.cc @@ -0,0 +1,3382 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: rsvc.h +// Generic tool designed to convert arrays of data types from one +// type to another +// +// Author: Walt Akers and Danjin Wu +// +// Revision History: +// rsvcData.cc,v +// Revision 1.3 1998/05/27 16:26:55 chen +// fix a iterator bug on ++ operation +// +// Revision 1.2 1998/01/29 19:10:58 akers +// Ongoing development +// +// Revision 1.1 1998/01/22 17:08:04 akers +// Addition of new NameServer +// +// +// +//-------------------------------------------------------------------------- + +#include +#include +#include +#include "rsvcData.h" +#include "rsvcDataStreamer.h" + +static char* rsvcStrncpy (char* dst, const char* src, size_t len) +{ + if (strlen (src) + 1 <= len) + return strncpy (dst, src, len); + strncpy (dst, src, len - 1); + dst[len - 1] = 0; + return dst; +} + +// ***************************************************************************** +// * rsvc_gcvt: +// * This overloaded function is being used in conjunction with the +// * standard library rsvc_gcvt to correct conversion errors when converting +// * float values. +// ***************************************************************************** +char * rsvcData::rsvc_gcvt(float value, size_t ndigit, char *buf) +{ + char tbuf[32]; + sprintf(tbuf, "%.7g", value); + rsvcStrncpy(buf, tbuf, ndigit); + return buf; +} + +char * rsvcData::rsvc_gcvt(double value, size_t ndigit, char * buf) +{ + char tbuf[32]; + sprintf(tbuf, "%.14g", value); + rsvcStrncpy(buf, tbuf, ndigit); + return buf; +} + +// ***************************************************************************** +// * RSVCConverter: +// * This is the type definition for all RSVC conversion functions. These +// * functions are used to perform data conversion from one RSVC datatype +// * to another. +// ***************************************************************************** +typedef void (*rsvcConverter)(void * input, void * output, size_t nElems); + +// ***************************************************************************** +// * RSVCConversionMatrix: +// * This matrix contains the cdev conversion functions necessary to convert +// * between all cdev data types. The user requests a conversion routime +// * by using the enumerated cdevDataType values that represent the from +// * type and the too type. +// * +// * For instance: +// * To convert from 16 bit integer to 32 bit integer, cdevData would +// * use the command... +// * cdevConversionMatrix[CDEV_INT16][CDEV_INT32](&in16, &out32, 1); +// * +// * To convert an array of 25 floats to an array of 25 doubles, +// * cdevData would use the command... +// * cdevConversionMatrix[CDEV_FLOAT][CDEV_DOUBLE](in, out, 25) +// ***************************************************************************** +extern const rsvcConverter rsvcConversionMatrix [RSVC_INVALID+1][RSVC_INVALID+1]; + +// ***************************************************************************** +// * copy: +// * This function copies the contents of the rsvcData object specified by +// * data into this rsvcData object. It is used by both the copy constructor +// * and by the assignment operator. +// ***************************************************************************** +rsvcData & +rsvcData::copy (const rsvcData & data) +{ + if(this != (rsvcData *)&data) { + remove(); + for(rsvcDataEntry *ptr = data.entries; ptr!=0; ptr = ptr->next_) { + switch(ptr->dataType_) { + case RSVC_BYTE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.cval); + else insert(ptr->tag_, ptr->data_.cptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_INT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.sval); + else insert(ptr->tag_, ptr->data_.sptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_UINT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.usval); + else insert(ptr->tag_, ptr->data_.usptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_INT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.lval); + else insert(ptr->tag_, ptr->data_.lptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_UINT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.ulval); + else insert(ptr->tag_, ptr->data_.ulptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_FLOAT: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.fval); + else insert(ptr->tag_, ptr->data_.fptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_DOUBLE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.dval); + else insert(ptr->tag_, ptr->data_.dptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_STRING: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.str); + else insert(ptr->tag_, ptr->data_.strarr, ptr->elems_, ptr->dim_); + break; + + case RSVC_TIMESTAMP: + if (ptr->dim_==0) insert(ptr->tag_, ptr->data_.ts); + else insert(ptr->tag_, ptr->data_.tsptr, ptr->elems_, ptr->dim_); + break; + + default: + break; + } + } + } + return *this; +} + +// **************************************************************************** +// * insert +// * This function insert entry into data directly +// **************************************************************************** +int +rsvcData::insert (rsvcDataEntry* entry) +{ + + rsvcDataEntry *result = 0, *prev = 0; + + // ********************************************************************* + // * Walk through the list of rsvcDataEntry objects until a matching + // * tag is found, or until no more items are available. + // ********************************************************************* + for(result=entries; result!=0; prev=result, result = result->next_); + + // ********************************************************************* + // * If result is 0, then a matching entry was not found. If the + // * user has specified create, then create a new entry. + // ********************************************************************* + + // ************************************************************* + // * The prev flag is used to indicate the last known + // * rsvcDataEntry object in the list. If prev contains 0, + // * then the list was empty and must be allocated directly. + // ************************************************************* + if( prev == 0 ) + entries = entry; + + // ************************************************************* + // * Otherwise, the new rsvcDataEntry object should be placed + // * at the bottom of the list. + // ************************************************************* + else + prev->next_ = entry; + return RSVC_SUCCESS; +} + + +// ***************************************************************************** +// * lookupTag: +// * This function attempts to locate the specified tag within the rsvcData +// * objects list of rsvcDataEntry objects. If the tag is found, then +// * its associated rsvcDataEntry object will be returned, otherwise, +// * if the caller has specified a non-zero value in the create flag, then +// * the new tag will be added to the list. +// ***************************************************************************** +rsvcDataEntry * +rsvcData::lookupTag(char* tag, int create) +{ + rsvcDataEntry *result = 0, *prev = 0; + + // ********************************************************************* + // * Walk through the list of rsvcDataEntry objects until a matching + // * tag is found, or until no more items are available. + // ********************************************************************* + for(result=entries; + result!=0 && (strcmp (result->tag_, tag)) != 0; + prev=result, result = result->next_); + + // ********************************************************************* + // * If result is 0, then a matching entry was not found. If the + // * user has specified create, then create a new entry. + // ********************************************************************* + if ( result==0 && create ) { + // ************************************************************* + // * The prev flag is used to indicate the last known + // * rsvcDataEntry object in the list. If prev contains 0, + // * then the list was empty and must be allocated directly. + // ************************************************************* + if( prev == 0 ) { + entries = new rsvcDataEntry; + result = entries; + } + // ************************************************************* + // * Otherwise, the new rsvcDataEntry object should be placed + // * at the bottom of the list. + // ************************************************************* + else { + prev->next_ = new rsvcDataEntry; + result = prev->next_; + } + } + + return result; +} + +// ***************************************************************************** +// * setupTag: +// * Convenience function to allow the rsvcData object to more efficiently +// * prepare new rsvcDataEntry objects for data insertion. +// * elemSize is the size of one element in bytes, numElems is the number of +// * elements to allocate, and numDims is the number of dimensions to create. +// ***************************************************************************** +rsvcDataEntry * +rsvcData::setupTag (char* tag, rsvcDataTypes type, size_t elemSize, + size_t numElems, size_t numDims ) +{ + rsvcDataEntry * entry; + if((entry = lookupTag(tag, 1))!=0) { + // ************************************************************* + // * If the entry is already populated and the new data is not + // * multidimensional, clear the old contents. + // ************************************************************* + if((strcmp (entry->tag_, tag) == 0) && numDims<=0) entry->clear(); + + // ************************************************************* + // * If the entry is multidimensional, allocate a new data + // * block for storing the data. + // ************************************************************* + if(numDims == 1) + entry->allocate(numDims, numElems, elemSize); + + // ************************************************************* + // * Populate the entry with the new data. + // ************************************************************* + rsvcStrncpy (entry->tag_, tag, RSVC_TAG_MAX_LEN); + entry->dataType_ = type; + } + return entry; +} + + +// ***************************************************************************** +// * rsvcData: +// * Default constructor for the rsvcData object. Initializes local data. +// ***************************************************************************** +rsvcData::rsvcData ( void ) +:entries (0) +{ + // empty +} + +// ***************************************************************************** +// * rsvcData: +// * Copy constructor. This constructor duplicates the rsvcData object that +// * it has been passed as a parameter. +// ***************************************************************************** +rsvcData::rsvcData ( const rsvcData & data ) +:entries (0) +{ + copy(data); +} + +// ***************************************************************************** +// * ~rsvcData: +// * Default destructor for the rsvcData object. Deallocates local data. +// ***************************************************************************** +rsvcData::~rsvcData( void ) +{ + remove(); +} + +// ***************************************************************************** +// * asciiDump: +// * This function will dump the contents of the rsvcData object to the +// * user specified file descriptor. +// ***************************************************************************** +#ifdef _WIN32 +void rsvcData::asciiDump (long osfHandle) +{ + int fd = _open_osfhandle(osfHandle, _O_WRONLY | _O_APPEND ); + FILE* fp = _fdopen (fd, "a"); +#else +void rsvcData::asciiDump ( FILE * fp ) +{ +#endif + rsvcDataEntry * entry; + char tagText[RSVC_INVALID+1][20]; + int i; + + // ************************************* + // * Load the names of the dataTypes * + // ************************************* + sprintf(tagText[RSVC_BYTE], "8 Bit Integer"); + sprintf(tagText[RSVC_INT16], "16 Bit Integer"); + sprintf(tagText[RSVC_UINT16], "Unsigned 16 Bit Int"); + sprintf(tagText[RSVC_INT32], "32 Bit Integer"); + sprintf(tagText[RSVC_UINT32], "Unsigned 32 Bit Int"); + sprintf(tagText[RSVC_FLOAT], "Float"); + sprintf(tagText[RSVC_DOUBLE], "Double"); + sprintf(tagText[RSVC_STRING], "Char String"); + sprintf(tagText[RSVC_TIMESTAMP], "Time Stamp"); + sprintf(tagText[RSVC_INVALID], "Invalid Data"); + + for(entry=entries; entry!=0; entry=entry->next_) + { + fprintf(fp, "Tag Name: %s\n", entry->tag_); + fprintf(fp, "Data Type: %s", tagText[entry->dataType_]); + fprintf(fp, "[%i]", entry->elems_); + + fprintf(fp, "\nValues: "); + + switch(entry->dataType_) + { + case RSVC_BYTE: + if(entry->dim_==0) fprintf(fp, "% 4i", entry->data_.cval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 4i%s", entry->data_.cptr[i], + (i%13==12)?"\n ":" "); + break; + + case RSVC_INT16: + if(entry->dim_==0) fprintf(fp, "% 6hi", entry->data_.sval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 6hi%s", entry->data_.sptr[i], + (i%9==8)?"\n ":" "); + break; + + case RSVC_UINT16: + if(entry->dim_==0) fprintf(fp, "% 6hu", entry->data_.usval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 6hu%s", entry->data_.usptr[i], + (i%9==8)?"\n ":" "); + break; + + case RSVC_INT32: + if(entry->dim_==0) fprintf(fp, "% 8li", entry->data_.lval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 8li%s", entry->data_.lptr[i], + (i%7==6)?"\n ":" "); + break; + + case RSVC_UINT32: + if(entry->dim_==0) fprintf(fp, "% 8lu", entry->data_.ulval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 8lu%s", entry->data_.ulptr[i], + (i%7==6)?"\n ":" "); + break; + + case RSVC_FLOAT: + if(entry->dim_==0) fprintf(fp, "% 12.5f", entry->data_.fval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 12.5f%s", entry->data_.fptr[i], + (i%5==4)?"\n ":" "); + break; + + case RSVC_DOUBLE: + if(entry->dim_==0) fprintf(fp, "% 14.7f", entry->data_.dval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 14.7f%s", entry->data_.dptr[i], + (i%4==3)?"\n ":" "); + break; + + case RSVC_STRING: + if(entry->dim_==0) fprintf(fp, "%s\n", entry->data_.str); + else for(i=0; ielems_; i++) + fprintf(fp, "%s\n ", entry->data_.strarr[i]); + break; + + case RSVC_TIMESTAMP: + if(entry->dim_==0) + fprintf(fp, "%u sec and %u nsec \n", + entry->data_.ts.secPastEpoch, entry->data_.ts.nsec); + else for(i=0; ielems_; i++) + fprintf(fp, "%u sec and %u nsec \n", + entry->data_.tsptr[i].secPastEpoch, entry->data_.tsptr[i].nsec); + break; + + case RSVC_INVALID: + break; + } + fprintf(fp, "\n\n"); + } + fflush (fp); +#ifdef _WIN32 + _commit (fd); +#endif +} + + +// ***************************************************************************** +// * streamSize: +// * Calculates the size of the Buffer necessary to store the rsvcData +// * object. This function may be used to determine the size of a +// * preallocated buffer for storing the xdr representation of a rsvcData +// * object. The bufLen parameter will receive the size of the buffer, and +// * the elementCount variable will receive the number of elements that will +// * be stored in the buffer. +// ***************************************************************************** +int +rsvcData::streamSize (size_t * bufLen, size_t * elementCount) +{ + rsvcDataEntry * ptr = entries; + int dataSize = 0; + int rsvcElementCnt = 0; + int i; + + // ************************************# + // * CALCULATE THE SIZE OF THE BUFFER # + // ************************************# + + // ************************************* + // * First is magic number * + // ************************************* + dataSize += rsvcStreamSize (_RSVC_MAGIC_NUM); + + // ************************************* + // * Add the size of the tag count int * + // ************************************* + dataSize += rsvcStreamSize (rsvcElementCnt); + + // ************************************* + // * Add the size of each valid item * + // ************************************* + for(ptr=entries; ptr!=0; ptr = ptr->next_) + { + // ***************************** + // * Do not process entries * + // * with RSVC_INVALID as the * + // * dataType or 0 as the tag. * + // ***************************** + if(ptr->dataType_==RSVC_INVALID || ptr->tag_[0] ==0) continue; + + // ***************************** + // * Calculate the number of * + // * elements in this tagged * + // * data item. * + // ***************************** + int numElements = ptr->dim_!=0?ptr->elems_:1; + + // ***************************** + // * Increment the counter * + // ***************************** + rsvcElementCnt++; + + // ***************************** + // * Add the size of the * + // * rsvcDataEntries tag_, * + // ***************************** + dataSize += rsvcStreamSize ((void *)ptr->tag_, RSVC_TAG_MAX_LEN); + + //****************************** + // * dataType_, dim_, elems_. * + // ***************************** + dataSize += 3 * rsvcStreamSize ((int)1); + + // ***************************** + // * Add the size of the data * + // ***************************** + if (ptr->dataType_==RSVC_BYTE) + dataSize += numElements * rsvcStreamSize ((char)1); + else if(ptr->dataType_==RSVC_INT16) + dataSize += numElements * rsvcStreamSize ((short)1); + else if(ptr->dataType_==RSVC_UINT16) + dataSize += numElements * rsvcStreamSize ((unsigned short)1); + else if(ptr->dataType_==RSVC_INT32) + dataSize += numElements * rsvcStreamSize ((int)1); + else if(ptr->dataType_==RSVC_UINT32) + dataSize += numElements * rsvcStreamSize ((unsigned int)1); + else if(ptr->dataType_==RSVC_FLOAT) + dataSize += numElements * rsvcStreamSize ((float) 1.0); + else if(ptr->dataType_==RSVC_DOUBLE) + dataSize += numElements * rsvcStreamSize ((double)1.0); + else if(ptr->dataType_==RSVC_STRING) + { + if(numElements==1) + dataSize += rsvcStreamSize (ptr->data_.str); + else + for(i=0; idata_.strarr[i]); + } + else if(ptr->dataType_==RSVC_TIMESTAMP) + dataSize += numElements * rsvcStreamSize (ptr->data_.ts); + } + + *elementCount = rsvcElementCnt; + *bufLen = dataSize; + + return *bufLen>0?RSVC_SUCCESS:RSVC_ERROR; +} + +// ***************************************************************************** +// * streamOut: +// * This function encapsulates the contents of the rsvcData class into a +// * binary stream. This function allocates the buffer and returns the new +// * buffer and the buffer size. +// ***************************************************************************** +int +rsvcData::streamOut ( char ** buf, size_t * bufLen ) +{ + size_t count = 0; + int st = RSVC_SUCCESS; + + // ************************************# + // * Calculate the size of the buffer # + // ************************************# + if ((st = streamSize(bufLen, &count)) != RSVC_SUCCESS) + return st; + + // ************************************# + // * Allocate the buffer and call the # + // * export function. # + // ************************************# + if((*buf = new char[*bufLen])!=0) streamOut (*buf, *bufLen, count); + + return buf==0?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * streamOut +// * This function encapsulates the contents of the rsvcData class into a +// * preallocated binary stream. The buf parameter contains the address of +// * the caller allocated buffer, the bufLen parameter specifies the size +// * of the buffer, and the count parameter specifies the number of tagged +// * data items that will be copied from the rsvcData object into the +// * binary stream. +// ***************************************************************************** +int +rsvcData::streamOut ( char * buf, size_t bufLen, size_t count) +{ + rsvcDataEntry * ptr; + int dataSize = bufLen; + int rsvcElementCnt = count; + int i; + int idx = 0; + // float ftmp; + // double dtmp; + int rsvcError = RSVC_SUCCESS; + + // create stream writer without deleting buffer + rsvcDataStreamWriter writer (buf, bufLen, 0); + + // ************************************# + // * Transfer the data to the buffer # + // ************************************# + + // ************************************* + // * Write magic number first * + // ************************************* + if ((rsvcError = writer.write (_RSVC_MAGIC_NUM)) != RSVC_SUCCESS) + return rsvcError; + + // ************************************* + // * Write the number of elements * + // ************************************* + if ((rsvcError = writer.write (rsvcElementCnt)) != RSVC_SUCCESS) + return rsvcError; + + // ************************************* + // * Write each valid item. * + // ************************************* + for(ptr = entries; ptr != 0 && rsvcError == RSVC_SUCCESS; ptr = ptr->next_) + { + // ***************************** + // * Do not process entries * + // * with RSVC_INVALID as the * + // * dataType or 0 as the tag. * + // ***************************** + if(ptr->dataType_==RSVC_INVALID || ptr->tag_==0) continue; + + // ***************************** + // * Calculate the number of * + // * elements in this tagged * + // * data item. * + // ***************************** + int numElements = ptr->dim_!=0?ptr->elems_:1; + + // ***************************** + // * Decrement the counter * + // ***************************** + rsvcElementCnt--; + + // ***************************** + // * Write the tag_, * + // * write dataType_ * + // * dim_, and elems_ of the * + // * rsvcDataEntry object. * + // ***************************** + + if (writer.write ((void *)ptr->tag_, RSVC_TAG_MAX_LEN) != RSVC_SUCCESS || + writer.write (ptr->dataType_) != RSVC_SUCCESS || + writer.write (ptr->dim_) != RSVC_SUCCESS || + writer.write (ptr->elems_) != RSVC_SUCCESS) { + rsvcError = RSVC_ERROR; + return rsvcError; + } + + // ***************************** + // * Write the data * + // ***************************** + if (ptr->dataType_==RSVC_BYTE) { + if(numElements==1) + rsvcError = writer.write (ptr->data_.cval); + else { + for(i=0; idata_.cptr[i]); + } + } + else if(ptr->dataType_==RSVC_INT16) + { + if(numElements==1) + rsvcError = writer.write (ptr->data_.sval); + else { + for(i=0; idata_.sptr[i]); + } + } + else if(ptr->dataType_==RSVC_UINT16) + { + if(numElements==1) + rsvcError = writer.write (ptr->data_.usval); + else { + for(i=0; idata_.usptr[i]); + } + } + else if(ptr->dataType_==RSVC_INT32) + { + if(numElements==1) + rsvcError = writer.write (ptr->data_.lval); + else { + for(i=0; idata_.lptr[i]); + } + } + else if(ptr->dataType_==RSVC_UINT32) + { + if(numElements==1) + rsvcError = writer.write (ptr->data_.ulval); + else { + for(i=0; idata_.ulptr[i]); + } + } + else if(ptr->dataType_==RSVC_FLOAT) + { + if(numElements==1) + rsvcError = writer.write (ptr->data_.fval); + else { + for(i=0; idata_.fptr[i]); + } + } + else if(ptr->dataType_==RSVC_DOUBLE) + { + if(numElements==1) + rsvcError = writer.write (ptr->data_.dval); + else { + for(i=0; idata_.dptr[i]); + } + } + else if(ptr->dataType_==RSVC_STRING) + { + if(numElements==1) + rsvcError = writer.write (ptr->data_.str); + else { + for(i=0; idata_.strarr[i]); + } + } + else if(ptr->dataType_==RSVC_TIMESTAMP) + { + // rsvc_TS_STAMP tmpts; + if(numElements==1) + rsvcError = writer.write (ptr->data_.ts); + else { + for(i=0; idata_.tsptr[i]); + } + } + } + + return rsvcError; +} + +// ***************************************************************************** +// * streamIn +// * This function populates the rsvcData class using the contents of a +// * binary buffer that has bee created by the xdrExport function. +// ***************************************************************************** +int +rsvcData::streamIn ( char * buf, size_t bufLen) +{ + int rsvcElementCnt; + int i, j; + int rsvcError = RSVC_SUCCESS; + + if(buf==0 || bufLen==0) return RSVC_INVALIDARG; + + rsvcDataStreamReader reader (buf, bufLen, 0); + // ************************************* + // * Deallocate any data previously * + // * assigned to the rsvcData class. * + // ************************************* + remove(); + + // ************************************* + // * Read the magic number from buffer * + // ************************************* + long magic; + + if (reader.read (magic) != RSVC_SUCCESS || magic != _RSVC_MAGIC_NUM) { + printf ("Magic number mismatch 0x%x != 0x%x\n", magic, _RSVC_MAGIC_NUM); + rsvcError = RSVC_ERROR; + return rsvcError; + } + + // ************************************* + // * Read the element count from the * + // * buffer. * + // ************************************* + rsvcError = reader.read (rsvcElementCnt); + + // ************************************* + // * Process each tagged element in * + // * the buffer. * + // ************************************* + for(i=0; idata_.cval); + else for(j=0; jdata_.cptr[j]); + } + break; + + case RSVC_INT16: + if((entry = setupTag(tag_, dataType_, sizeof(short), + numElements, dim_))!=0) { + if(numElements==1) + rsvcError = reader.read(entry->data_.sval); + else + for(j=0; jdata_.sptr[j]); + } + break; + + case RSVC_UINT16: + if((entry = setupTag(tag_, dataType_, sizeof(unsigned short), + numElements, dim_))!=0) { + if(numElements==1) + rsvcError = reader.read (entry->data_.usval); + else + for(j=0; jdata_.usptr[j]); + } + break; + + case RSVC_INT32: + if((entry = setupTag(tag_, dataType_, sizeof(long), + numElements, dim_))!=0) { + + if(numElements==1) + rsvcError = reader.read (entry->data_.lval); + else + for(j=0; jdata_.lptr[j]); + } + break; + + case RSVC_UINT32: + if((entry = setupTag(tag_, dataType_, sizeof(unsigned long), + numElements, dim_))!=0) { + if(numElements==1) + rsvcError = reader.read(entry->data_.ulval); + else + for(j=0; jdata_.ulptr[j]); + } + break; + + case RSVC_FLOAT: + if((entry = setupTag(tag_, dataType_, sizeof(float), + numElements, dim_))!=0) { + if(numElements==1) + rsvcError = reader.read (entry->data_.fval); + else + for(j=0; jdata_.fptr[j]); + } + break; + + case RSVC_DOUBLE: + if((entry = setupTag(tag_, dataType_, sizeof(double), + numElements, dim_))!=0) { + if(numElements==1) + rsvcError = reader.read (entry->data_.dval); + else for(j=0; jdata_.dptr[j]); + } + break; + + case RSVC_STRING: + { + char ** ptr = new char *[numElements]; + memset(ptr, 0, sizeof(char *)*numElements); + + for(j=0; jdata_.ts); + else + for(j=0; jdata_.tsptr[j]); + } + break; + + case RSVC_INVALID: + break; + } + } + + } + + return rsvcError; +} + +// ***************************************************************************** +// * remove: +// * Removes the all rsvcDataEntry objects from the rsvcData object. +// ***************************************************************************** +void rsvcData::remove( void ) +{ + while(entries!=0) + { + rsvcDataEntry * ptr = entries; + entries = ptr->next_; + delete ptr; + } +} + +// ***************************************************************************** +// * remove: +// * Removes a specified tagged data item from the rsvcData object. +// ***************************************************************************** +void rsvcData::remove(char* tag) +{ + rsvcDataEntry *result = 0, *prev = 0; + + // ********************************************************************* + // * Walk through the list of rsvcDataEntry objects until a matching + // * tag is found, or until no more items are available. + // ********************************************************************* + for(result=entries; + result!=0 && strcmp (result->tag_, tag) != 0; + prev=result, result = result->next_); + + if(result!=0) + { + if(prev!=0) prev->next_ = result->next_; + else entries = result->next_; + delete result; + } +} + +// ********************************************************************* +// * changeTag: +// * Replace a new tag with the old one within the +// * rsvcData object. If the old one can not be not found, +// * RSVC_NOTFOUND is returned. If the new tag has already +// * been found in that rsvcData object, RSVC_ERROR is returned. +// ********************************************************************* +int rsvcData::changeTag(char* oldTag, char* newTag) +{ + int result; + rsvcDataEntry *entry; + if((entry=lookupTag(oldTag)) == 0) result = RSVC_NOTFOUND; + else { + if( lookupTag(newTag) != 0) result = RSVC_ERROR; + else { + rsvcStrncpy (entry->tag_, newTag, RSVC_TAG_MAX_LEN); + result = RSVC_SUCCESS; + } + } + return result; +} + +// ********************************************************************* +// * dupWithTag: +// * copy data with tag 'old_tag' to tag 'new_tag'. +// * rsvcData object. If the old one can not be not found, +// * RSVC_NOTFOUND is returned. If the new tag has already +// * been found in that rsvcData object, RSVC_ERROR is returned. +// ********************************************************************* +int rsvcData::dupWithTag (char* old_tag, char* new_tag) +{ + int result; + rsvcDataEntry* entry; + rsvcDataEntry* newentry; + + if ((entry = lookupTag (old_tag)) == 0) + result = RSVC_NOTFOUND; + else { + if (lookupTag (new_tag) != 0) + result = RSVC_ERROR; + else { + newentry = new rsvcDataEntry (*entry); + rsvcStrncpy (newentry->tag_, new_tag, RSVC_TAG_MAX_LEN); + // now put this entry into the list + newentry->next_ = entries; + entries = newentry; + result = RSVC_SUCCESS; + } + } + return result; +} + +// ***************************************************************************** +// * getType: +// * Retrieves the rsvcDataTypes of the referenced tagged data item. +// * If no item with that tag is within the rsvcData object, then +// * RSVC_INVALID is returned. +// ***************************************************************************** +rsvcDataTypes rsvcData::getType(char* tag) +{ + rsvcDataEntry * entry = lookupTag(tag); + return entry==0?RSVC_INVALID:entry->dataType_; +} + +// ***************************************************************************** +// * getDim: +// * Obtains the number of dimensions in the specified tagged data +// * item. Returns RSVC_SUCCESS if the tagged item exists, otherwise, +// * RSVC_NOTFOUND is returned. +// ***************************************************************************** +int rsvcData::getDim(char* tag, size_t *dim) +{ + rsvcDataEntry * entry = lookupTag(tag); + *dim = entry==0?0:entry->dim_; + return entry==0?RSVC_NOTFOUND:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * getElems: +// * Obtains the number of elements in the specified tagged data +// * item. Returns RSVC_SUCCESS if the tagged item exists, otherwise, +// * RSVC_NOTFOUND is returned. +// ***************************************************************************** +int rsvcData::getElems(char* tag, size_t *elems) +{ + rsvcDataEntry * entry = lookupTag(tag); + *elems = entry==0?0:(entry->dim_>0?entry->elems_:1); + return entry==0?RSVC_NOTFOUND:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar character value into a rsvcDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, BYTE data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_BYTE, sizeof(char), 1, 0))!=0) + { + entry->data_.cval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar short int value into a rsvcDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, short data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_INT16, sizeof(short), 1, 0))!=0) + { + entry->data_.sval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar unsigned short int value into a +// * rsvcDataEntry object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, unsigned short data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_UINT16, sizeof(unsigned short), 1, 0))!=0) + { + entry->data_.usval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar long int value into a rsvcDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, int data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_INT32, sizeof(long), 1, 0))!=0) + { + entry->data_.lval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar unsigned long int value into a +// * rsvcDataEntry object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, unsigned int data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_UINT32, sizeof(long), 1, 0))!=0) + { + entry->data_.ulval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar long int value into a rsvcDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, long data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_INT32, sizeof(long), 1, 0))!=0) + { + entry->data_.lval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar unsigned long int value into a +// * rsvcDataEntry object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, unsigned long data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_UINT32, sizeof(long), 1, 0))!=0) + { + entry->data_.ulval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar float value into a rsvcDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, float data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_FLOAT, sizeof(float), 1, 0))!=0) + { + entry->data_.fval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar double value into a rsvcDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, double data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_DOUBLE, sizeof(double), 1, 0))!=0) + { + entry->data_.dval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a time stamp value into a rsvcDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert ( char* tag, rsvc_TS_STAMP data ) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_TIMESTAMP, sizeof(rsvc_TS_STAMP), 1, 0))!=0) + { + entry->data_.ts.secPastEpoch = data.secPastEpoch; + entry->data_.ts.nsec = data.nsec; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of characters arrays of data +// * into a rsvcData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, BYTE * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_BYTE, sizeof(char), len, ndim))!=0) + { + memcpy(entry->data_.cptr, data, len*sizeof(char)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of short int arrays of data +// * into a rsvcData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, short * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_INT16, sizeof(short), len, ndim))!=0) + { + memcpy(entry->data_.sptr, data, len*sizeof(short)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of unsigned short int arrays +// * of data into a rsvcData object. The len variable contains the total +// * number of elements to be inserted, the ndim variable indicates the +// * number of dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, unsigned short * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_UINT16, sizeof(unsigned short), len, ndim))!=0) + { + memcpy(entry->data_.usptr, data, len*sizeof(unsigned short)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of long int arrays of data +// * into a rsvcData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, int * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_INT32, sizeof(long), len, ndim))!=0) + { + memcpy(entry->data_.lptr, data, len*sizeof(long)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of unsigned long int arrays +// * of data into a rsvcData object. The len variable contains the total +// * number of elements to be inserted, the ndim variable indicates the +// * number of dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, unsigned int * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_UINT32, sizeof(unsigned long), len, ndim))!=0) + { + memcpy(entry->data_.ulptr, data, len*sizeof(unsigned long)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of long int arrays of data +// * into a rsvcData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, long * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_INT32, sizeof(long), len, ndim))!=0) + { + memcpy(entry->data_.lptr, data, len*sizeof(long)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of unsigned long int arrays +// * of data into a rsvcData object. The len variable contains the total +// * number of elements to be inserted, the ndim variable indicates the +// * number of dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, unsigned long * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_UINT32, sizeof(unsigned long), len, ndim))!=0) + { + memcpy(entry->data_.ulptr, data, len*sizeof(unsigned long)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of float arrays of data +// * into a rsvcData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, float * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_FLOAT, sizeof(float), len, ndim))!=0) + { + memcpy(entry->data_.fptr, data, len*sizeof(float)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of double arrays of data +// * into a rsvcData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, double * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_DOUBLE, sizeof(double), len, ndim))!=0) + { + memcpy(entry->data_.dptr, data, len*sizeof(double)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of a character string into +// * a rsvcData object. The length of the string is calculated using the +// * strlen function. It is important to note, that although this data item +// * uses the array_ block within the rsvcDataEntry object, it has no +// * rsvcBounds information associated with it. +// ***************************************************************************** +int rsvcData::insert (char* tag, char * data ) +{ + rsvcDataEntry * entry; + int result = RSVC_ERROR; + int len = data!=0?strlen(data)+1:0; + + if(len>0 && (entry = lookupTag(tag, 1))!=0) { + // ************************************************************* + // * Allocate a new data block for storing the character string. + // * Note that the number of dimensions will be zero, but the + // * array_ element within the rsvcDataEntry object will still + // * be used. + // ************************************************************* + entry->allocate(0, len, sizeof(char)); + + // ************************************************************* + // * Populate the entry with the new data. + // ************************************************************* + rsvcStrncpy (entry->tag_, tag, RSVC_TAG_MAX_LEN); + entry->dataType_ = RSVC_STRING; + memcpy(entry->data_.str, data, len); + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of an array of character +// * strings. Unlike the individual character string, this data may have +// * rsvcBounds data associated within it. +// ***************************************************************************** +int rsvcData::insert (char* tag, char ** data, size_t len, size_t ndim ) +{ + int result = RSVC_SUCCESS; + rsvcDataEntry * entry; + + // ********************************************************************* + // * If the user specified len is invalid (or 0 by default), walk + // * through the array of pointers until 0 is found. + // ********************************************************************* + if(len<=0) for(len=0; data && data[len]!=0; len++); + if(len==0) result = RSVC_INVALIDARG; + else if(len==1) result = insert(tag, *data); + else + { + int i; + size_t dataLen = 0; + + // ************************************************************* + // * To determine the data space needed to store an array of + // * character strings, the function must calculate the length + // * of each character string (plus one for the 0 terminator), + // * then add in the space necessary to store the pointers. + // ************************************************************* + for(i=0; ielems_ = len; + entry->bytes_ = 4; + + // ***************************************************** + // * Set the pointer within the string array to point + // * to the extra memory allocated at the end of the + // * entry->data_.strarr block. Then copy the new data + // * into the string array. + // ***************************************************** + char ** ptr = entry->data_.strarr; + ptr[0] = (char *)(&entry->data_.strarr[len+1]); + strcpy(ptr[0], data[0]); + for(i=1; idata_.tsptr, data, len*sizeof(rsvc_TS_STAMP)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + + +// ***************************************************************************** +// * get: +// * This function retrieves a character value specified by tag from the +// * rsvcData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, BYTE * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_BYTE] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_BYTE] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves an short integer value specified by tag from the +// * rsvcData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, short * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_INT16] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_INT16] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves an unsigned short integer value specified by tag +// * from the rsvcData object. This value may be either scalar or an array. +// * If the data is an array, the user must have preallocated sufficient +// * space to store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, unsigned short * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_UINT16] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_UINT16] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves an long integer value specified by tag from the +// * rsvcData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, int * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_INT32] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_INT32] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves an unsigned long integer value specified by tag +// * from the rsvcData object. This value may be either scalar or an array. +// * If the data is an array, the user must have preallocated sufficient +// * space to store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, unsigned int * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_UINT32] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_UINT32] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + + +// ***************************************************************************** +// * get: +// * This function retrieves an long integer value specified by tag from the +// * rsvcData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, long * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_INT32] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_INT32] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves an unsigned long integer value specified by tag +// * from the rsvcData object. This value may be either scalar or an array. +// * If the data is an array, the user must have preallocated sufficient +// * space to store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, unsigned long * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_UINT32] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_UINT32] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves a floating point value specified by tag from the +// * rsvcData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, float * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_FLOAT] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_FLOAT] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + + +// ***************************************************************************** +// * get: +// * This function retrieves a double float value specified by tag from the +// * rsvcData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, double * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_DOUBLE] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_DOUBLE] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves a time stamp value specified by tag from the +// * rsvcData object. +// ***************************************************************************** +int rsvcData::get(char* tag, rsvc_TS_STAMP * data) +{ + int result; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_TIMESTAMP] + (entry->data_.vptr, data, entry->elems_); + else + rsvcConversionMatrix[entry->dataType_][RSVC_TIMESTAMP] + (&entry->data_, data, 1); + result = RSVC_SUCCESS; + } + return result; +} + + +// ***************************************************************************** +// * get: +// * This function retrieves a char string value specified by tag from the +// * rsvcData object. For simplicity, this method operates differently +// * than the other get methods. +// ***************************************************************************** +int rsvcData::get(char* tag, char * data, size_t len) +{ + int nelem = 1, result = RSVC_NOTFOUND; + rsvcDataEntry * entry; + if(data!=0 && (entry=lookupTag(tag, 0))!=0) + { + if(entry->dim_ > 0)nelem = entry->elems_; + + switch(entry->dataType_) + { + case RSVC_BYTE: + if(nelem==1) sprintf(data, "%.*s", len, ltoa(entry->data_.cval)); + else sprintf(data, "%.*s", len, ltoa(*entry->data_.str)); + break; + case RSVC_INT16: + if(nelem==1) sprintf(data, "%.*s", len, ltoa(entry->data_.sval)); + else sprintf(data, "%.*s", len, ltoa(*entry->data_.sptr)); + break; + case RSVC_UINT16: + if(nelem==1) sprintf(data, "%.*s", len, ultoa(entry->data_.usval)); + else sprintf(data, "%.*s", len, ultoa(*entry->data_.usptr)); + break; + case RSVC_INT32: + if(nelem==1) sprintf(data, "%.*s", len, ltoa(entry->data_.lval)); + else sprintf(data, "%.*s", len, ltoa(*entry->data_.lptr)); + break; + case RSVC_UINT32: + if(nelem==1) sprintf(data, "%.*s", len, ultoa(entry->data_.ulval)); + else sprintf(data, "%.*s", len, ultoa(*entry->data_.ulptr)); + break; + case RSVC_FLOAT: + if(nelem==1) rsvc_gcvt(entry->data_.fval, len, data); + else rsvc_gcvt(*entry->data_.fptr, len, data); + break; + case RSVC_DOUBLE: + if(nelem==1) rsvc_gcvt(entry->data_.dval, len, data); + else rsvc_gcvt(*entry->data_.dptr, len, data); + break; + case RSVC_STRING: + if(nelem==1) rsvcStrncpy(data, entry->data_.str, len); + else rsvcStrncpy(data, entry->data_.strarr[0], len); + data[len-1] = 0; + break; + case RSVC_TIMESTAMP: + if(nelem==1) + rsvcStrncpy(data, ctime((time_t *)&(entry->data_.ts.secPastEpoch)), len); + data[len-1] = 0; + break; + + default: + break; + } + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves a char string array specified by tag from the +// * rsvcData object. For simplicity, this method operates differently +// * than the other get methods. +// ***************************************************************************** +int rsvcData::get(char* tag, char ** data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else + { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_STRING] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_STRING] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * find: +// * Allows the user to directly extract a pointer to the internal data +// * buffer that the rsvcDataEntry object uses to store data. +// ***************************************************************************** +int rsvcData::find(char* tag, void* &data) +{ + int result = RSVC_NOTFOUND; + rsvcDataEntry * entry; + if((entry=lookupTag(tag, 0))!=0) + { + if(entry->dim_>0 || entry->dataType_==RSVC_STRING) data = entry->data_.vptr; + else data = &entry->data_; + result = RSVC_SUCCESS; + } + else data = 0; + return result; +} + +// ********************************************************************* +// * replace: +// * This function allows part or all taged values being replaced +// * by other taged values represented by a rsvcData +// ********************************************************************* +int +rsvcData::replace (const rsvcData& data) +{ + void* dptr = 0; + int found = 0; + for(rsvcDataEntry *ptr = data.entries; ptr!=0; ptr = ptr->next_) { + if (find (ptr->tag_, dptr) == RSVC_SUCCESS) { + found = 1; + remove (ptr->tag_); + switch(ptr->dataType_) { + case RSVC_BYTE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.cval); + else insert(ptr->tag_, ptr->data_.cptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_INT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.sval); + else insert(ptr->tag_, ptr->data_.sptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_UINT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.usval); + else insert(ptr->tag_, ptr->data_.usptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_INT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.lval); + else insert(ptr->tag_, ptr->data_.lptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_UINT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.ulval); + else insert(ptr->tag_, ptr->data_.ulptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_FLOAT: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.fval); + else insert(ptr->tag_, ptr->data_.fptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_DOUBLE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.dval); + else insert(ptr->tag_, ptr->data_.dptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_STRING: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.str); + else insert(ptr->tag_, ptr->data_.strarr, ptr->elems_, ptr->dim_); + break; + + case RSVC_TIMESTAMP: + if (ptr->dim_==0) insert(ptr->tag_, ptr->data_.ts); + else insert(ptr->tag_, ptr->data_.tsptr, ptr->elems_, ptr->dim_); + break; + + default: + break; + } + } + } + if (found) + return RSVC_SUCCESS; + return RSVC_ERROR; +} + + +// ***************************************************************************** +// * operator == : +// * This method will allow the caller to rapidly determine if two rsvcData +// * objects contain identical fields and values... +// * +// * In the first step, the method will count the total number of fields in +// * both objects... if they are not equal an error will be returned... +// * +// * Next the method will begin getting pointers to the rsvcDataEntry objects +// * that are stored in each object and will use their embedded comparison +// * operators to compare the contents of each of them. +// ***************************************************************************** +int rsvcData::operator == ( rsvcData & data ) +{ + int result = 1; + rsvcDataEntry *entry1, *entry2; + int entry1Cnt=0, entry2Cnt=0; + + for(entry1=entries; entry1!=0; entry1=entry1->next_) entry1Cnt++; + for(entry2=data.entries; entry2!=0; entry2=entry2->next_) entry2Cnt++; + if(entry1Cnt==entry2Cnt) + { + result = 0; + for(entry1=entries; !result && entry1!=0; entry1=entry1->next_) + { + if((entry2 = data.lookupTag(entry1->tag_))!=0) + { + result = !(entry1->operator == (*entry2)); + } + else result = -1; + } + } + return !result; +} + +// ***************************************************************************** +// * Assignment operation: +// * This operation will reassign data object to another object +// ***************************************************************************** +rsvcData& +rsvcData::operator = (const rsvcData& data) +{ + return copy (data); +} + +// ***************************************************************************** +// * Append operation: +// * This operation will append a rsvcData onto an existing rsvcData +// * and return this object. If there is confilicts among tags, the +// * appended one wins +// ***************************************************************************** +rsvcData& +rsvcData::operator += (const rsvcData& data) +{ + for(rsvcDataEntry *ptr = data.entries; ptr!=0; ptr = ptr->next_) { + switch(ptr->dataType_) { + case RSVC_BYTE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.cval); + else insert(ptr->tag_, ptr->data_.cptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_INT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.sval); + else insert(ptr->tag_, ptr->data_.sptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_UINT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.usval); + else insert(ptr->tag_, ptr->data_.usptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_INT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.lval); + else insert(ptr->tag_, ptr->data_.lptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_UINT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.ulval); + else insert(ptr->tag_, ptr->data_.ulptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_FLOAT: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.fval); + else insert(ptr->tag_, ptr->data_.fptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_DOUBLE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.dval); + else insert(ptr->tag_, ptr->data_.dptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_STRING: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.str); + else insert(ptr->tag_, ptr->data_.strarr, ptr->elems_, ptr->dim_); + break; + + case RSVC_TIMESTAMP: + if (ptr->dim_==0) insert(ptr->tag_, ptr->data_.ts); + else insert(ptr->tag_, ptr->data_.tsptr, ptr->elems_, ptr->dim_); + break; + + default: + break; + } + } + return *this; +} + + +// ***************************************************************************** +// * rsvc Conversion Utilities +// * These functions are incorporated into the rsvcConversionMatrix and are +// * used to convert between rsvcDataTypes. Because these functions are +// * defined for use specifically within the rsvcData object, they are not +// * declared in the header file and should not be used by external modules +// * or applications. +// * +// * All rsvc function sthat use these utilities should access them through +// * the rsvcConversionMatrix array as described at the beginning of this +// * file. +// ***************************************************************************** + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_BYTE ( void * input, void * output, size_t nElems ) +{ + memcpy(output, input, nElems*sizeof(char)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((short *)output)[nElems] = (short)((BYTE *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((BYTE *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((long *)output)[nElems] = (long)((BYTE *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((BYTE *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((float *)output)[nElems] = (float)((BYTE *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((double *)output)[nElems] = (double)((BYTE *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_STRING ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = new char[strlen(ltoa(((BYTE *)input)[nElems]))+1]; + strcpy(((char **)output)[nElems], ltoa(((BYTE *)input)[nElems])); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch = (unsigned long)((BYTE *)input)[nElems]; + ((rsvc_TS_STAMP *)output)[nElems].nsec = 0; + } + fprintf(stderr, "warning: Byte converts to timestamp struct, data may be invalid\n"); +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to Invalid Conversion Facilities... Does nothing +// ***************************************************************************** +void rsvcConvert_BYTE_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((char *)output)[nElems] = (char)((short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_INT16 ( void * input, void * output, size_t nElems ) +{ + memcpy(output, input, nElems*sizeof(short)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((long *)output)[nElems] = (long)((short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((float *)output)[nElems] = (float)((short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((double *)output)[nElems] = (double)((short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_STRING ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = new char[strlen(ltoa(((short *)input)[nElems]))+1]; + strcpy(((char **)output)[nElems], ltoa(((short *)input)[nElems])); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch = (unsigned long)((short *)input)[nElems]; + ((rsvc_TS_STAMP *)output)[nElems].nsec = 0; + } + fprintf(stderr, "warning: INT16 converts to timestamp struct, data may be invalid\n"); +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_INT16_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((char *)output)[nElems] = (char)((unsigned short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((short *)output)[nElems] = (unsigned short)((unsigned short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + memcpy(output, input, nElems*sizeof(unsigned short)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((long *)output)[nElems] = (long)((unsigned short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((unsigned short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((float *)output)[nElems] = (float)((unsigned short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((double *)output)[nElems] = (double)((unsigned short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_STRING ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = new char[strlen(ultoa(((unsigned short *)input)[nElems]))+1]; + strcpy(((char **)output)[nElems], ultoa(((unsigned short *)input)[nElems])); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch=(unsigned long)((unsigned short *)input)[nElems]; + ((rsvc_TS_STAMP *)output)[nElems].nsec = 0; + } + fprintf(stderr, "warning: UINT16 converts to timestamp struct, data may be invalid\n"); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_UINT16_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((char *)output)[nElems] = (char)((long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((short *)output)[nElems] = (short)((long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_INT32 ( void * input, void * output, size_t nElems ) +{ + memcpy(output, input, nElems*sizeof(long)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((float *)output)[nElems] = (float)((long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((double *)output)[nElems] = (double)((long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_STRING ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = new char[strlen(ltoa(((long *)input)[nElems]))+1]; + strcpy(((char **)output)[nElems], ltoa(((long *)input)[nElems])); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch=(unsigned long)((long *)input)[nElems]; + ((rsvc_TS_STAMP *)output)[nElems].nsec = 0; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_INT32_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((char *)output)[nElems] = (char)((unsigned long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((short *)output)[nElems] = (short)((unsigned long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((unsigned long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((long *)output)[nElems] = (unsigned long)((unsigned long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + memcpy(output, input, nElems*sizeof(unsigned long)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((float *)output)[nElems] = (float)((unsigned long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((double *)output)[nElems] = (double)((unsigned long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_STRING ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = new char[strlen(ultoa(((unsigned long *)input)[nElems]))+1]; + strcpy(((char **)output)[nElems], ultoa(((unsigned long *)input)[nElems])); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch=((unsigned long *)input)[nElems]; + ((rsvc_TS_STAMP *)output)[nElems].nsec = 0; + } +} + + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_UINT32_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((char *)output)[nElems] = (char)((float *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((short *)output)[nElems] = (short)((float *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((float *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((long *)output)[nElems] = (long)((float *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((float *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + memcpy(output, input, nElems*sizeof(float)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((double *)output)[nElems] = (double)((float *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_STRING ( void * input, void * output, size_t nElems ) +{ + char buf[32]; + while(nElems>0) { + nElems--; + rsvcData::rsvc_gcvt(((float *)input)[nElems], (size_t)32, buf); + ((char **)output)[nElems] = new char[strlen(buf)+1]; + strcpy(((char **)output)[nElems], buf); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch=(unsigned long)((float *)input)[nElems]; + ((rsvc_TS_STAMP *)output)[nElems].nsec = + (unsigned long)(((float)((float *)input)[nElems]-(unsigned long)((float *)input)[nElems])*1000000000); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_FLOAT_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((char *)output)[nElems] = (char)((double *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((short *)output)[nElems] = (short)((double *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((double *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((long *)output)[nElems] = (long)((double *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((double *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((float *)output)[nElems] = (float)((double *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + memcpy(output, input, nElems*sizeof(double)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_STRING ( void * input, void * output, size_t nElems ) +{ + char buf[32]; + while(nElems>0) { + nElems--; + rsvcData::rsvc_gcvt(((double *)input)[nElems], 32, buf); + ((char **)output)[nElems] = new char[strlen(buf)+1]; + strcpy(((char **)output)[nElems], buf); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch= + (unsigned long)((double *)input)[nElems]; + ((rsvc_TS_STAMP *)output)[nElems].nsec = + (unsigned long)(((double)((double *)input)[nElems]-(unsigned long)((double *)input)[nElems])*1000000000); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((char *)output)[nElems] = (char)atof(((char **)input)[nElems]); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((short *)output)[nElems] = (short)atof(((char **)input)[nElems]); + } + +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)atof(((char **)input)[nElems]); + } + +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((long *)output)[nElems] = (long)atof(((char **)input)[nElems]); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)atof(((char **)input)[nElems]); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((float *)output)[nElems] = (float)atof(((char **)input)[nElems]); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((double *)output)[nElems] = (double)atof(((char **)input)[nElems]); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_STRING ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = new char[strlen(((char **)input)[nElems])+1]; + strcpy(((char **)output)[nElems], ((char **)input)[nElems]); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + double tmp = atof(((char **)input)[nElems]); + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch=(unsigned long)tmp; + ((rsvc_TS_STAMP *)output)[nElems].nsec =(unsigned long)((tmp-(unsigned long)tmp)*1000000000); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_STRING_to_INVALID ( void *, void *, size_t ) +{ +} + + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char *)output)[nElems] = (char)(((rsvc_TS_STAMP *)input)[nElems].secPastEpoch); + } + fprintf(stderr, "warning: Timestamp struct converts to Byte, data may be invalid\n"); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((short *)output)[nElems] = (short)(((rsvc_TS_STAMP *)input)[nElems].secPastEpoch); + } + fprintf(stderr, "warning: Timestamp struct converts to INT16, data may be invalid\n"); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((unsigned short *)output)[nElems]= + (unsigned short)(((rsvc_TS_STAMP *)input)[nElems].secPastEpoch); + } + fprintf(stderr, "warning: Timestamp struct converts to UINT16, data may be invalid\n"); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((long *)output)[nElems]= + (long)(((rsvc_TS_STAMP *)input)[nElems].secPastEpoch); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((unsigned long *)output)[nElems]= + ((rsvc_TS_STAMP *)input)[nElems].secPastEpoch; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to Floating Point Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((float *)output)[nElems]= + (float)(((rsvc_TS_STAMP *)input)[nElems].secPastEpoch+ + ((rsvc_TS_STAMP *)input)[nElems].nsec/1000000000.); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to Doouble Floating Point Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((double *)output)[nElems]= + (double)(((rsvc_TS_STAMP *)input)[nElems].secPastEpoch+ + ((rsvc_TS_STAMP *)input)[nElems].nsec/1000000000.); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to Char String Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_STRING ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = new char[30]; + strcpy( ((char **)output)[nElems], + ctime((time_t *)(&(((rsvc_TS_STAMP *)input)[nElems].secPastEpoch))) ); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to Time Stamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch = + ((rsvc_TS_STAMP *)input)[nElems].secPastEpoch; + ((rsvc_TS_STAMP *)output)[nElems].nsec = + ((rsvc_TS_STAMP *)input)[nElems].nsec; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to Invalid Conversion Facilities...Dose Nothing +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to 8 Bit Integer Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_BYTE ( void *, void * output, size_t nElems ) +{ + memset((char *)output, 0, nElems*sizeof(char)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to 16 Bit Integer Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_INT16 ( void *, void * output, size_t nElems ) +{ + memset((short *)output, 0, nElems*sizeof(short)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to Unsigned 16 Bit Integer Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_UINT16 ( void *, void * output, size_t nElems ) +{ + memset((short *)output, 0, nElems*sizeof(unsigned short)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to 32 Bit Integer Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_INT32 ( void *, void * output, size_t nElems ) +{ + memset((long *)output, 0, nElems*sizeof(long)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to Unsigned 32 Bit Integer Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_UINT32 ( void *, void * output, size_t nElems ) +{ + memset((long *)output, 0, nElems*sizeof(unsigned long)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to Float Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_FLOAT ( void *, void * output, size_t nElems ) +{ + memset((float *)output, 0, nElems*sizeof(float)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to Double Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_DOUBLE ( void *, void * output, size_t nElems ) +{ + memset((double *)output, 0, nElems*sizeof(double)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to String Array Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_STRING ( void *, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = 0; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to Timestamp Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_TIMESTAMP ( void *, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch=0; + ((rsvc_TS_STAMP *)output)[nElems].nsec =0; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_INVALID_to_INVALID ( void *, void *, size_t ) +{ +} + + +// ***************************************************************************** +// * rsvcConversionMatrix: +// * Instanciation of the conversion matrix defined at the beginning of this +// * file. +// ***************************************************************************** +const rsvcConverter rsvcConversionMatrix [RSVC_INVALID+1][RSVC_INVALID+1] = +{ + { + rsvcConvert_BYTE_to_BYTE, + rsvcConvert_BYTE_to_INT16, + rsvcConvert_BYTE_to_UINT16, + rsvcConvert_BYTE_to_INT32, + rsvcConvert_BYTE_to_UINT32, + rsvcConvert_BYTE_to_FLOAT, + rsvcConvert_BYTE_to_DOUBLE, + rsvcConvert_BYTE_to_STRING, + rsvcConvert_BYTE_to_TIMESTAMP, + rsvcConvert_BYTE_to_INVALID + }, + { + rsvcConvert_INT16_to_BYTE, + rsvcConvert_INT16_to_INT16, + rsvcConvert_INT16_to_UINT16, + rsvcConvert_INT16_to_INT32, + rsvcConvert_INT16_to_UINT32, + rsvcConvert_INT16_to_FLOAT, + rsvcConvert_INT16_to_DOUBLE, + rsvcConvert_INT16_to_STRING, + rsvcConvert_INT16_to_TIMESTAMP, + rsvcConvert_INT16_to_INVALID, + }, + { + rsvcConvert_UINT16_to_BYTE, + rsvcConvert_UINT16_to_INT16, + rsvcConvert_UINT16_to_UINT16, + rsvcConvert_UINT16_to_INT32, + rsvcConvert_UINT16_to_UINT32, + rsvcConvert_UINT16_to_FLOAT, + rsvcConvert_UINT16_to_DOUBLE, + rsvcConvert_UINT16_to_STRING, + rsvcConvert_UINT16_to_TIMESTAMP, + rsvcConvert_UINT16_to_INVALID, + }, + { + rsvcConvert_INT32_to_BYTE, + rsvcConvert_INT32_to_INT16, + rsvcConvert_INT32_to_UINT16, + rsvcConvert_INT32_to_INT32, + rsvcConvert_INT32_to_UINT32, + rsvcConvert_INT32_to_FLOAT, + rsvcConvert_INT32_to_DOUBLE, + rsvcConvert_INT32_to_STRING, + rsvcConvert_INT32_to_TIMESTAMP, + rsvcConvert_INT32_to_INVALID, + }, + { + rsvcConvert_UINT32_to_BYTE, + rsvcConvert_UINT32_to_INT16, + rsvcConvert_UINT32_to_UINT16, + rsvcConvert_UINT32_to_INT32, + rsvcConvert_UINT32_to_UINT32, + rsvcConvert_UINT32_to_FLOAT, + rsvcConvert_UINT32_to_DOUBLE, + rsvcConvert_UINT32_to_STRING, + rsvcConvert_UINT32_to_TIMESTAMP, + rsvcConvert_UINT32_to_INVALID, + }, + { + rsvcConvert_FLOAT_to_BYTE, + rsvcConvert_FLOAT_to_INT16, + rsvcConvert_FLOAT_to_UINT16, + rsvcConvert_FLOAT_to_INT32, + rsvcConvert_FLOAT_to_UINT32, + rsvcConvert_FLOAT_to_FLOAT, + rsvcConvert_FLOAT_to_DOUBLE, + rsvcConvert_FLOAT_to_STRING, + rsvcConvert_FLOAT_to_TIMESTAMP, + rsvcConvert_FLOAT_to_INVALID, + }, + { + rsvcConvert_DOUBLE_to_BYTE, + rsvcConvert_DOUBLE_to_INT16, + rsvcConvert_DOUBLE_to_UINT16, + rsvcConvert_DOUBLE_to_INT32, + rsvcConvert_DOUBLE_to_UINT32, + rsvcConvert_DOUBLE_to_FLOAT, + rsvcConvert_DOUBLE_to_DOUBLE, + rsvcConvert_DOUBLE_to_STRING, + rsvcConvert_DOUBLE_to_TIMESTAMP, + rsvcConvert_DOUBLE_to_INVALID, + }, + { + rsvcConvert_STRING_to_BYTE, + rsvcConvert_STRING_to_INT16, + rsvcConvert_STRING_to_UINT16, + rsvcConvert_STRING_to_INT32, + rsvcConvert_STRING_to_UINT32, + rsvcConvert_STRING_to_FLOAT, + rsvcConvert_STRING_to_DOUBLE, + rsvcConvert_STRING_to_STRING, + rsvcConvert_STRING_to_TIMESTAMP, + rsvcConvert_STRING_to_INVALID, + }, + { + rsvcConvert_TIMESTAMP_to_BYTE, + rsvcConvert_TIMESTAMP_to_INT16, + rsvcConvert_TIMESTAMP_to_UINT16, + rsvcConvert_TIMESTAMP_to_INT32, + rsvcConvert_TIMESTAMP_to_UINT32, + rsvcConvert_TIMESTAMP_to_FLOAT, + rsvcConvert_TIMESTAMP_to_DOUBLE, + rsvcConvert_TIMESTAMP_to_STRING, + rsvcConvert_TIMESTAMP_to_TIMESTAMP, + rsvcConvert_TIMESTAMP_to_INVALID, + }, + { + rsvcConvert_INVALID_to_BYTE, + rsvcConvert_INVALID_to_INT16, + rsvcConvert_INVALID_to_UINT16, + rsvcConvert_INVALID_to_INT32, + rsvcConvert_INVALID_to_UINT32, + rsvcConvert_INVALID_to_FLOAT, + rsvcConvert_INVALID_to_DOUBLE, + rsvcConvert_INVALID_to_STRING, + rsvcConvert_INVALID_to_TIMESTAMP, + rsvcConvert_INVALID_to_INVALID, + } +}; + + +// ***************************************************************************** +// *rsvcDataIterator: +// * +// ***************************************************************************** +rsvcDataIterator::rsvcDataIterator(rsvcData* data) { + dataobj_ = data; + cur_ = 0; +} + +int rsvcDataIterator::init() { + if (dataobj_) { + cur_ = dataobj_->entries; + return cur_ != 0; } + else { return 0; } +} + +int rsvcDataIterator::operator !() { + return cur_ != 0; +} + +int rsvcDataIterator::operator ++() { + if (cur_) + cur_ = cur_->next_; + return cur_ != 0; +} + +const char* rsvcDataIterator::tag(void) { + return (cur_!=0)?cur_->tag_:0; +} + +rsvcDataEntry * +rsvcDataIterator::operator () (void) +{ + return cur_; +} + + +// ***************************************************************************** +// * ltoa and ultoa +// * Supporing routines for non hpux platform +// * the return values point to static data whose content is overwritten by +// * each call +// ***************************************************************************** +#ifndef hpux +char *ltoa (long val) +{ + static char ltoabuf[80]; + + sprintf (ltoabuf,"%ld", val); + + return ltoabuf; +} + +char *ultoa (unsigned long val) +{ + static char ultoabuf[80]; + + sprintf (ultoabuf,"%lu", val); + + return ultoabuf; +} +#endif diff --git a/extensions/cdevGenericServer/NameServer/cdev/rsvcDataEntry.cc b/extensions/cdevGenericServer/NameServer/cdev/rsvcDataEntry.cc new file mode 100755 index 0000000..1316a2d --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rsvcDataEntry.cc @@ -0,0 +1,173 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//------------------------------------------------------------------------------ +// +// description: rcsDataEntry.cc +// This file contains the non-inlined functions associated with the +// rsvcDataEntry family of classes. +// +// Author: Walt Akers +// +// Revision History: +// rsvcDataEntry.cc,v +// Revision 1.1 1998/01/22 17:08:05 akers +// Addition of new NameServer +// +// +// +//------------------------------------------------------------------------------ +#include "rsvcDataEntry.h" + + +// ***************************************************************************** +// * rsvcDataEntryeStorage::operator ==: +// * This operator allows you to directly and rapidly compare two +// * rsvcDataEntryStorage objects... +// ***************************************************************************** +int rsvcDataEntryStorage::operator == (rsvcDataEntryStorage & entry) +{ + int result = 0; + int i = 0; + + // ********************************************************************* + // * First compare all of the pertinent scalar values... + // ********************************************************************* + if(strcmp (tag_, entry.tag_) == 0 && + dataType_ == entry.dataType_ && + dim_ == entry.dim_ && + elems_ == entry.elems_) + { + // ************************************************************* + // * Next compare the contents of the data items... + // ************************************************************* + if(dim_) + { + result = 0; + if(dataType_==RSVC_BYTE) + for(i=0; i 0) { + // allocate memory + allocate (entry.dim_, entry.elems_, entry.bytes_); + // copy memory + memcpy (buffer_, entry.buffer_, size_); + } + else + memcpy (&data_, &entry.data_, sizeof (data_)); +} + +rsvcDataEntry & +rsvcDataEntry::operator = (const rsvcDataEntry& entry) +{ + if (this != &entry) { + clear (); + + dataType_ = entry.dataType_; + dim_ = entry.dim_; + elems_ = entry.elems_; + bytes_ = entry.bytes_; + size_ = entry.size_; + strcpy (tag_, entry.tag_); + buffer_ = 0; + + if (dim_ > 0 || (dim_ == 0 && dataType_ == RSVC_STRING)) { + // allocate memory + allocate (entry.dim_, entry.elems_, entry.bytes_); + // copy memory + memcpy (buffer_, entry.buffer_, size_); + } + else + memcpy (&data_, &entry.data_, sizeof (data_)); + } + return *this; +} + + +// ***************************************************************************** +// * Global initialization of the static freeList_ member of the +// * rsvcDataEntry class. +// ***************************************************************************** +rsvcDataEntry * rsvcDataEntry::freeList_ = NULL; + +// ***************************************************************************** +// * new: +// * Allocation function for the object. It will get the next preallocated +// * rsvcDataEntry object from the freeList_, or, if none are available, +// * refill the freeList_ and then return a new rsvcDataEntry object. +// ***************************************************************************** +void * rsvcDataEntry::operator new ( size_t ) +{ + rsvcDataEntry * result = NULL; + + if(freeList_==NULL) + { + freeList_ = ::new rsvcDataEntry[ALLOCATION_COUNT]; + for(int i=0; inext_; + } + + return result; +} diff --git a/extensions/cdevGenericServer/NameServer/cdev/rsvcDataStreamer.cc b/extensions/cdevGenericServer/NameServer/cdev/rsvcDataStreamer.cc new file mode 100755 index 0000000..ebb9bb7 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rsvcDataStreamer.cc @@ -0,0 +1,630 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// rsvc data streamer class +// +// Author: Jie Chen +// +// Revision History: +// rsvcDataStreamer.cc,v +// Revision 1.1 1998/01/22 17:08:08 akers +// Addition of new NameServer +// +// +// +#include "rsvcErr.h" +#include "rsvcDataStreamer.h" + +// ****************************************************************** +// float and double conversion routines +// not portable yet especially for VAX machines +// ****************************************************************** +static float htonf (float f) +{ + float fret; + long *p = (long *)&f; + long nl = htonl (*p); + fret = *(float *)&nl; + return fret; +} + +static float ntohf (float f) +{ + float fret; + + long *p = (long *)&f; + long nl = ntohl (*p); + fret = *(float *)&nl; + return fret; +} + +static double htond (double d) +{ + long *lp, *lq; + long *dp, *dq; + double ret; + + // move high byte first + lp = lq = (long *)&d; + lp++; + + dp = dq = (long *)&ret; + *dp = htonl (*lp); + + lp--; dp++; + *dp = htonl (*lp); + + ret = *(double *)dq; + return ret; +} + +static double ntohd (double d) +{ + long *lp, *lq; + long *dp, *dq; + double ret; + + // low byte of incoming data should be high byte of host native data + lp = lq = (long *)&d; + dp = dq = (long *)&ret; + dp++; + + *dp = ntohl (*lp); + + lp++; dp--; + *dp = ntohl (*lp); + + ret = *(double *)dq; + return ret; +} + +static rsvc_TS_STAMP htonts (rsvc_TS_STAMP& ts) +{ + rsvc_TS_STAMP rts; + + rts.secPastEpoch = htonl (ts.secPastEpoch); + rts.nsec = htonl (ts.nsec); + return rts; +} + +static rsvc_TS_STAMP ntohts (rsvc_TS_STAMP& ts) +{ + rsvc_TS_STAMP rts; + + rts.secPastEpoch = ntohl (ts.secPastEpoch); + rts.nsec = ntohl (ts.nsec); + return rts; +} + + +rsvcDataStreamer::rsvcDataStreamer (char* buffer, size_t buflen, + int dealloc) +:buffer_ (buffer), buflen_ (buflen), dealloc_ (dealloc), pos_ (0), + err_ (RSVC_SUCCESS) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcDataStreamer Class Object\n"); +#endif +} + +rsvcDataStreamer::~rsvcDataStreamer (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcDataStreamer Class Object\n"); +#endif + if (dealloc_) + if (buffer_) { + delete []buffer_; + buffer_ = 0; + } +} + +char* +rsvcDataStreamer::buffer (void) const +{ + return buffer_; +} + +size_t +rsvcDataStreamer::bufferLength (void) const +{ + return buflen_; +} + +int +rsvcDataStreamer::streamStatus (void) const +{ + return err_; +} + + +//=============================================================== +// Implementation of rsvcDataStreamWriter +//=============================================================== +rsvcDataStreamWriter::rsvcDataStreamWriter (char* buffer, size_t size, + int dealloc) +:rsvcDataStreamer (buffer, size, dealloc) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcDataStreamWriter Class Object\n"); +#endif +} + +rsvcDataStreamWriter::~rsvcDataStreamWriter (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete rsvcDataStreamWriter Class Object\n"); +#endif +} + +int +rsvcDataStreamWriter::write (char c) +{ + long tmp = (long)c; + return write (tmp); +} + +int +rsvcDataStreamWriter::write (unsigned char c) +{ + long tmp = (long)c; + return write (tmp); +} + +int +rsvcDataStreamWriter::write (short c) +{ + long tmp = (long)c; + return write (tmp); +} + +int +rsvcDataStreamWriter::write (unsigned short c) +{ + long tmp = (long)c; + return write (tmp); +} + + +int +rsvcDataStreamWriter::write (int c) +{ + long tmp = (long)c; + return write (tmp); +} + +int +rsvcDataStreamWriter::write (unsigned int c) +{ + long tmp = (long)c; + return write (tmp); +} + +int +rsvcDataStreamWriter::write (long c) +{ + long tmp = htonl (c); + if (pos_ + rsvcStreamSize (c) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: write overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + memcpy (&(buffer_[pos_]), &tmp, rsvcStreamSize (c)); + pos_ += rsvcStreamSize (c); + + return RSVC_SUCCESS; +} + +int +rsvcDataStreamWriter::write (unsigned long c) +{ + long tmp = (long)c; + return write (tmp); +} + +int +rsvcDataStreamWriter::write (float c) +{ + float ftmp = htonf (c); + + if (pos_ + rsvcStreamSize (c) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: write float overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + memcpy (&(buffer_[pos_]), &ftmp, rsvcStreamSize (c)); + pos_ += rsvcStreamSize (c); + + return RSVC_SUCCESS; +} + +int +rsvcDataStreamWriter::write (double c) +{ + double dtmp = htond (c); + + if (pos_ + rsvcStreamSize (c) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: write double overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + memcpy (&(buffer_[pos_]), &dtmp, rsvcStreamSize (c)); + + pos_ += rsvcStreamSize (c); +#ifdef _RSVC_DEBUG + printf ("Write cursor is %d\n", pos_); +#endif + return RSVC_SUCCESS; +} + +int +rsvcDataStreamWriter::write (char* str) +{ + size_t slen = strlen (str) + 1; + size_t rlen = _RSVC_RNDUP (slen); + size_t len = sizeof (long) + _RSVC_RNDUP (slen); + + if (pos_ + len > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: write string %s overflow buffer at %d with bufsize %d\n", + str, pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + + // write size of string first + write ((long)rlen); + + memcpy (&(buffer_[pos_]), str, slen); + pos_ += slen; + + if (rlen > slen) + memset (&(buffer_[pos_]), 0, rlen - slen); + pos_ += (rlen - slen); + + return RSVC_SUCCESS; +} + +int +rsvcDataStreamWriter::write (void* data, size_t len) +{ + size_t rlen = _RSVC_RNDUP (len); + size_t wlen = sizeof (long) + rlen; + + if (pos_ + wlen > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: write void * overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + + // write out size of data first + write ((long)rlen); + + memcpy (&(buffer_[pos_]), data, len); + pos_ += len; + + if (rlen > len) + memset (&(buffer_[pos_]), 0, rlen - len); + + pos_ += (rlen - len); + + return RSVC_SUCCESS; +} + +int +rsvcDataStreamWriter::write (rsvc_TS_STAMP& ts) +{ + rsvc_TS_STAMP tts = htonts (ts); + + if (pos_ + rsvcStreamSize (ts) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: write TS overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + memcpy (&(buffer_[pos_]), &tts, rsvcStreamSize (ts)); + pos_ += rsvcStreamSize (ts); + + return RSVC_SUCCESS; +} + +//=============================================================== +// Implementation of rsvcDataStreamReader +//=============================================================== +rsvcDataStreamReader::rsvcDataStreamReader (char* buffer, size_t buflen, + int dealloc) +:rsvcDataStreamer (buffer, buflen, dealloc) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcDataStreamReader Class Object\n"); +#endif +} + +rsvcDataStreamReader::~rsvcDataStreamReader (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete rsvcDataStreamReader Class Object\n"); +#endif +} + + +int +rsvcDataStreamReader::read (char& c) +{ + long tmp; + int st; + + if ((st = read (tmp)) == RSVC_SUCCESS) + c = (char)tmp; + else + c = 0; + + return st; +} + +int +rsvcDataStreamReader::read (unsigned char& c) +{ + long tmp; + int st; + + if ((st = read (tmp)) == RSVC_SUCCESS) + c = (unsigned char)tmp; + else + c = 0; + + return st; +} + +int +rsvcDataStreamReader::read (short & c) +{ + long tmp; + int st; + + if ((st = read (tmp)) == RSVC_SUCCESS) + c = (short)tmp; + else + c = 0; + + return st; +} + +int +rsvcDataStreamReader::read (unsigned short& c) +{ + long tmp; + int st; + + if ((st = read (tmp)) == RSVC_SUCCESS) + c = (unsigned short)tmp; + else + c = 0; + + return st; +} + +int +rsvcDataStreamReader::read (int& c) +{ + long tmp; + int st; + + if ((st = read (tmp)) == RSVC_SUCCESS) + c = (int)tmp; + else + c = 0; + + return st; +} + +int +rsvcDataStreamReader::read (unsigned int& c) +{ + long tmp; + int st; + + if ((st = read (tmp)) == RSVC_SUCCESS) + c = (unsigned int)tmp; + else + c = 0; + + return st; +} + +int +rsvcDataStreamReader::read (long& c) +{ + long tmp; + + if (pos_ + sizeof (c) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read long overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + + memcpy (&tmp, &(buffer_[pos_]), sizeof (long)); + pos_ += sizeof (long); + + c = ntohl (tmp); + return RSVC_SUCCESS; +} + +int +rsvcDataStreamReader::read (unsigned long& c) +{ + long tmp; + int st; + + if ((st = read (tmp)) == RSVC_SUCCESS) + c = (unsigned long)tmp; + else + c = 0; + + return st; +} + +int +rsvcDataStreamReader::read (float& c) +{ + float ftmp; + + if (pos_ + rsvcStreamSize (c) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read float overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + memcpy (&ftmp, &(buffer_[pos_]), rsvcStreamSize (c)); + pos_ += rsvcStreamSize (c); + + c = ntohf (ftmp); + + return RSVC_SUCCESS; +} + +int +rsvcDataStreamReader::read (double& c) +{ + double dtmp; + + if (pos_ + rsvcStreamSize (c) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read double overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + memcpy (&dtmp, &(buffer_[pos_]), rsvcStreamSize (c)); + pos_ += rsvcStreamSize (c); + + c = ntohd (dtmp); + + return RSVC_SUCCESS; +} + +int +rsvcDataStreamReader::read (rsvc_TS_STAMP & ts) +{ + rsvc_TS_STAMP tts; + + if (pos_ + rsvcStreamSize (ts) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read TS overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + memcpy (&tts, &(buffer_[pos_]), rsvcStreamSize (ts)); + pos_ += rsvcStreamSize (ts); + + ts = ntohts (tts); + return RSVC_SUCCESS; +} + +int +rsvcDataStreamReader::read (char* & str) +{ + long str_size = 0; + int st = RSVC_SUCCESS; + + if (pos_ + sizeof (long) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read string header overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + st = err_ = RSVC_ERROR; + return err_; + } + + if ((st = read (str_size)) == RSVC_SUCCESS) { + if (pos_ + str_size > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read string overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + + if (str_size > 0) { + str = new char[str_size]; + memcpy (str, &(buffer_[pos_]), (unsigned int)str_size); + pos_ += (int)str_size; + } + else { + str = 0; + err_ = st = RSVC_ERROR; + } + } + else { + str = 0; + st = err_ = RSVC_ERROR; + } + return st; +} + +int +rsvcDataStreamReader::read (void* data, size_t size) +{ + long data_size = 0; + int st = RSVC_SUCCESS; + + if (pos_ + sizeof (long) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read void * header overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + st = err_ = RSVC_ERROR; + return err_; + } + + if ((st = read (data_size)) == RSVC_SUCCESS) { + if (pos_ + data_size > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read void * overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + st = err_ = RSVC_ERROR; + return err_; + } + if (data_size > 0) { + memcpy (data, &(buffer_[pos_]), size); + pos_ += (int)data_size; + } + else + st = err_ = RSVC_ERROR; + } + return st; +} + + diff --git a/extensions/cdevGenericServer/NameServer/cdev/rsvcHSlist.cc b/extensions/cdevGenericServer/NameServer/cdev/rsvcHSlist.cc new file mode 100755 index 0000000..d5856c1 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rsvcHSlist.cc @@ -0,0 +1,762 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Single Linked List for rsvcHashable* pointer +// +// Note: remove and clean operations on the list +// will only remove link nodes without removal of +// the content inside the nodes. It is callers' +// responsiblity to clean up those contents +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// Revision History: +// rsvcHSlist.cc,v +// Revision 1.1 1998/01/22 17:08:12 akers +// Addition of new NameServer +// +// +// +#include +#include "rsvcHSlist.h" + +//====================================================================== +// class rsvcHSlist implementation +//====================================================================== +rsvcHSlist::rsvcHSlist (void) +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +:ptrToFirstLink(0), count_ (0), lock_ () +#else +:ptrToFirstLink(0), count_ (0) +#endif +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcHSlist Class Object\n"); +#endif + // no further initialization +} + +rsvcHSlist::rsvcHSlist (const rsvcHSlist & source) +:count_ (source.count_) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcHSlist Class Object\n"); +#endif + + // duplicate elements from source list + if (source.isEmpty_i()) + ptrToFirstLink = 0; + else{ + rsvcHSlistLink * firstLink = source.ptrToFirstLink; + ptrToFirstLink = firstLink->duplicate(); + } +} + +rsvcHSlist::~rsvcHSlist (void) +{ + // empty all elements from the list +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcHSlist Class Object\n"); +#endif + deleteAllValues(); +} + +void +rsvcHSlist::add (rsvcHashable* val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // add a new value to the front of a linked list + ptrToFirstLink = new rsvcHSlistLink(val, ptrToFirstLink); + count_ ++; + assert(ptrToFirstLink != 0); +} + +void +rsvcHSlist::addToEnd (rsvcHashable* val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + count_ ++; + if (ptrToFirstLink == 0) { + ptrToFirstLink = new rsvcHSlistLink(val, ptrToFirstLink); + return; + } + + // loop through until last element + rsvcHSlistLink *p = 0; + for (p = ptrToFirstLink; p->ptrToNextLink; p = p->ptrToNextLink) + ; + + rsvcHSlistLink* q = new rsvcHSlistLink (val, 0); + p->ptrToNextLink = q; +} + +void +rsvcHSlist::add_i (rsvcHashable* val) +{ + // add a new value to the front of a linked list + count_ ++; + ptrToFirstLink = new rsvcHSlistLink(val, ptrToFirstLink); + assert(ptrToFirstLink != 0); +} + +int +rsvcHSlist::remove (rsvcHashable* val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // remove an element from the list + // loop to test each element + rsvcHSlistLink *q = ptrToFirstLink; + for (rsvcHSlistLink * p = ptrToFirstLink; p; p = p->ptrToNextLink){ + if (val == p->value){ + if (q == p){ + // remove first element + ptrToFirstLink = p->ptrToNextLink; + delete p; + } + else{ + q->ptrToNextLink = p->ptrToNextLink; + delete p; + } + count_ --; + return 1; + } + q = p; + } + // not found + return 0; +} + +void +rsvcHSlist::deleteAllValues (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // clear all items from the list + rsvcHSlistLink * next; + + for (rsvcHSlistLink * p = ptrToFirstLink; p != 0; p = next){ + // delete the element pointed to by p + next = p->ptrToNextLink; + p->ptrToNextLink = 0; + delete p; + } + + // set count to zero + count_ = 0; + // mark that the list contains no elements + ptrToFirstLink = 0; +} + +void +rsvcHSlist::deleteAllValues_i (void) +{ + // clear all items from the list + rsvcHSlistLink * next; + + for (rsvcHSlistLink * p = ptrToFirstLink; p != 0; p = next){ + // delete the element pointed to by p + next = p->ptrToNextLink; + p->ptrToNextLink = 0; + delete p; + } + + // set count to zero + count_ = 0; + + // mark that the list contains no elements + ptrToFirstLink = 0; +} + +int +rsvcHSlist::count (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + return count_; +} + +rsvcHSlist* +rsvcHSlist::duplicate (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + rsvcHSlist * newlist = new rsvcHSlist; + assert(newlist != 0); + + // copy list + if (ptrToFirstLink) + newlist->ptrToFirstLink = ptrToFirstLink->duplicate(); + + // set new list count + newlist->count_ = count_; + // return the new list + return newlist; +} + +rsvcHashable* +rsvcHSlist::firstElement (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // return first value in list + assert(ptrToFirstLink != 0); + return ptrToFirstLink->value; +} + +rsvcHashable* +rsvcHSlist::firstElement_i (void) +{ + // return first value in list + assert(ptrToFirstLink != 0); + return ptrToFirstLink->value; +} + +rsvcHashable* +rsvcHSlist::lastElement (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + assert(ptrToFirstLink != 0); + // loop through until last element + rsvcHSlistLink *p = 0; + for (p = ptrToFirstLink; p->ptrToNextLink; p = p->ptrToNextLink) + ; + return p->value; +} + +rsvcHashable* +rsvcHSlist::lastElement_i (void) +{ + assert(ptrToFirstLink != 0); + // loop through until last element + rsvcHSlistLink *p = 0; + for (p = ptrToFirstLink; p->ptrToNextLink; p = p->ptrToNextLink) + ; + return p->value; +} + +int +rsvcHSlist::includes(rsvcHashable* v) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // loop to test each element + for (rsvcHSlistLink * p = ptrToFirstLink; p; p = p->ptrToNextLink) + if (v == p->value) + return 1; + + // not found + return 0; +} + +int +rsvcHSlist::isEmpty (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // test to see if the list is empty + // list is empty if the pointer to the first link is null + return ptrToFirstLink == 0; +} + +int +rsvcHSlist::isEmpty_i (void) const +{ + // test to see if the list is empty + // list is empty if the pointer to the first link is null + return ptrToFirstLink == 0; +} + +void +rsvcHSlist::removeFirst (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // make sure there is a first element + assert(ptrToFirstLink != 0); + + // save pointer to the removed node + rsvcHSlistLink * p = ptrToFirstLink; + + // reassign the ptrToFirstLink node + ptrToFirstLink = p->ptrToNextLink; + + // decrease the count + count_ --; + // recover memory used by the first element + delete p; +} + +void +rsvcHSlist::removeFirst_i (void) +{ + // make sure there is a first element + assert(ptrToFirstLink != 0); + + // save pointer to the removed node + rsvcHSlistLink * p = ptrToFirstLink; + + // reassign the ptrToFirstLink node + ptrToFirstLink = p->ptrToNextLink; + + // decrease the count + count_ --; + + // recover memory used by the first element + delete p; +} + +//====================================================================== +// class slink implementation +// No need to add any mutex protection since all member +// functions are called with lock held +//====================================================================== +rsvcHSlistLink* +rsvcHSlistLink::insert(rsvcHashable* val) +{ + // insert a new link after current node + ptrToNextLink = new rsvcHSlistLink(val, ptrToNextLink); + + // check that allocation was successful + assert(ptrToNextLink != 0); + return ptrToNextLink; +} + +rsvcHSlistLink::rsvcHSlistLink (rsvcHashable* val, rsvcHSlistLink * nxt) +:value(val), ptrToNextLink(nxt) +{ + // create and initialize a new link field +} + +rsvcHSlistLink* +rsvcHSlistLink::duplicate (void) +{ + rsvcHSlistLink * newlink; + + // if there is a next field. copy remainder of list + if (ptrToNextLink != 0) + newlink = new rsvcHSlistLink(value, ptrToNextLink->duplicate()); + else + newlink = new rsvcHSlistLink (value, 0); + + // check that allocation was successful + assert(newlink != 0); + return newlink; +} + +rsvcHSlistLink* +rsvcHSlistLink::next (void) +{ + return ptrToNextLink; +} + +rsvcHashable* +rsvcHSlistLink::data (void) +{ + return value; +} + +//====================================================================== +// class listIterator implementation +//====================================================================== +rsvcHSlistIterator::rsvcHSlistIterator(rsvcHSlist & aList) +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +:theList(aList), lock_ () +#else +:theList(aList) +#endif +{ + // create and initialize a new list + init_i(); +} + +int +rsvcHSlistIterator::init_i() +{ + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +int +rsvcHSlistIterator::init() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +rsvcHashable* +rsvcHSlistIterator::operator () (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + // return value of current element + // check to see if there is a current element + assert(currentLink != 0); + + // return value associated with current element + return currentLink->value; +} + +int rsvcHSlistIterator::operator ! (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + // test for termination of the iterator + // if current link references a removed value, + // update current to point to next position + if (currentLink == 0) + if (previousLink != 0) + currentLink = previousLink->ptrToNextLink; + + // now see if currentLink is valid + return currentLink != 0; +} + +int rsvcHSlistIterator::forward_i (void) +{ + // move current pointer to nect element + // special processing if current link is deleted + if (currentLink == 0){ + if (previousLink == 0) + currentLink = theList.ptrToFirstLink; + else + currentLink = previousLink->ptrToNextLink; + } + else{ + // advance pointer + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + + +int rsvcHSlistIterator::operator ++() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // move current pointer to nect element + // special processing if current link is deleted + if (currentLink == 0){ + if (previousLink == 0) + currentLink = theList.ptrToFirstLink; + else + currentLink = previousLink->ptrToNextLink; + } + else{ + // advance pointer + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +void rsvcHSlistIterator::operator = (rsvcHashable* val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // modify value of current element + assert(currentLink != 0); + + // modify value of the current link + currentLink->value = val; +} + +void rsvcHSlistIterator::removeCurrent_i (void) +{ + // remove the current element from a list + // make sure there is a current element + assert(currentLink != 0); + + // case 1, removing first element + if (previousLink == 0) + theList.ptrToFirstLink = currentLink->ptrToNextLink; + + // case 2, not removing the first element + else + previousLink->ptrToNextLink = currentLink->ptrToNextLink; + + // delete current node + delete currentLink; + + // and set current pointer to null + currentLink = 0; + + // decrease list count element + theList.count_ --; +} + +void rsvcHSlistIterator::removeCurrent (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // remove the current element from a list + // make sure there is a current element + assert(currentLink != 0); + + // case 1, removing first element + if (previousLink == 0) + theList.ptrToFirstLink = currentLink->ptrToNextLink; + + // case 2, not removing the first element + else + previousLink->ptrToNextLink = currentLink->ptrToNextLink; + + // delete current node + delete currentLink; + + // and set current pointer to null + currentLink = 0; + + // decrease list count element + theList.count_ --; +} + +void rsvcHSlistIterator::addBefore(rsvcHashable* val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // add a new element to list before current value + // case 1, not at start + if (previousLink) + previousLink = previousLink->insert(val); + + // case 2, at start of list + else{ + theList.rsvcHSlist::add(val); + previousLink = theList.ptrToFirstLink; + currentLink = previousLink->ptrToNextLink; + } + + // increase the count + theList.count_ ++; +} + +void rsvcHSlistIterator::addAfter(rsvcHashable* val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // a a new element to list after current value + // case 1, not at start + if (currentLink != 0) + currentLink->insert(val); + + // case 2, at end of list + else if (previousLink != 0) + currentLink = previousLink->insert(val); + + // case 3, start of list + else + theList.rsvcHSlist::add(val); + + // increase the count + theList.count_ ++; +} + +int rsvcHSlistIterator::searchSame(rsvcHashable* &val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // search the list to find out whether we have this element + // if we do, move cursor to this element return 1 + // if we don't return 0 + init_i(); + + if (currentLink == 0){ + // empty link + return 0; + } + while (currentLink != 0){ + // advance pointer + if (currentLink->value == val) + break; + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +//======================================================================== +// Implementation of rsvcHSlistCursor +// Implements of cursor without changing list +//======================================================================== +rsvcHSlistCursor::rsvcHSlistCursor(const rsvcHSlist & aList) +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +:theList(aList), lock_ () +#else +:theList(aList) +#endif +{ + // create and initialize a new list + init_i(); +} + +int +rsvcHSlistCursor::init_i() +{ + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +int +rsvcHSlistCursor::init() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +rsvcHashable* +rsvcHSlistCursor::operator () (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // return value of current element + // check to see if there is a current element + assert(currentLink != 0); + + // return value associated with current element + return currentLink->value; +} + +int rsvcHSlistCursor::operator ! (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // test for termination of the iterator + // if current link references a removed value, + // update current to point to next position + if (currentLink == 0) + if (previousLink != 0) + currentLink = previousLink->ptrToNextLink; + + // now see if currentLink is valid + return currentLink != 0; +} + +int rsvcHSlistCursor::operator ++ (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // move current pointer to nect element + // special processing if current link is deleted + if (currentLink == 0){ + if (previousLink == 0) + currentLink = theList.ptrToFirstLink; + else + currentLink = previousLink->ptrToNextLink; + } + else{ + // advance pointer + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +int rsvcHSlistCursor::searchSame (rsvcHashable* &val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + // search the list to find out whether we have this element + // if we do, move cursor to this element return 1 + // if we don't return 0 + init_i(); + + if (currentLink == 0){ + // empty link + return 0; + } + while (currentLink != 0){ + // advance pointer + if (currentLink->value == val) + break; + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +void rsvcHSlistCursor::operator = (rsvcHashable* ) +{ + // empty +} diff --git a/extensions/cdevGenericServer/NameServer/cdev/rsvcHash.cc b/extensions/cdevGenericServer/NameServer/cdev/rsvcHash.cc new file mode 100755 index 0000000..a4bfcb5 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rsvcHash.cc @@ -0,0 +1,351 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606 +// Email: coda@cebaf.gov Tel: (804) 249-7101 Fax: (804) 249-7363 +//----------------------------------------------------------------------------- +// +// Description: +// rsvcHash: rsvc hash table keyed by a variable length string +// Open Hash with buckets implemented by single linked lists +// +// Note: void *s are stored inside the table. This class +// will not manage these pointers. Callers have to +// manage these pointers +// +// Note: this is unsafe C++ practice. Use at your own risk +// +// Reason: It is so difficult to use a template class inside +// a shared library. (Cfront based C++ compiler cannot +// instantiate a template class during compilation time +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// Revision History: +// rsvcHash.cc,v +// Revision 1.3 1998/02/26 19:10:24 chen +// provide direct access to array of linked list +// +// Revision 1.2 1998/02/20 19:29:54 chen +// Remove debug print +// +// Revision 1.1 1998/01/22 17:08:13 akers +// Addition of new NameServer +// +// +// +#include +#include +#include +#include +#include +#include "rsvcHash.h" + +// the following are 10 prime numbers. Each is twice of value of the +// one in front of it. + +static unsigned int rsvc_prime_table[] = +{11, 97, 199, 499, 997, 1999, 4999, 9973, 25013, 49999, 99991}; + +static unsigned int rsvc_prime_table_size = 11; + +static unsigned int +rsvc_pick_prime (unsigned max, int* index) +{ + unsigned int diff = 12345678; + unsigned int tmp; + + for (int i = 0; i < rsvc_prime_table_size; i++) { + tmp = abs ((int)((int)max - (int)rsvc_prime_table[i])); + if (tmp < diff) { + diff = tmp; + *index = i; + } + } + return rsvc_prime_table[*index]; +} + +// a simple string hash function +unsigned int rsvcHashFunc (const char *src) +{ + unsigned int hash = 0, g; + + for (int i = 0; src[i] != '\0'; i++){ + hash = (hash << 4) + src[i]; + // assume 32 bit integer + if (g = hash & 0xf0000000){ + hash ^= g >> 24; + hash ^= g; + } + } + return hash; +} + + +//====================================================================== +// class rsvcHash implementation +//====================================================================== + +// lock_ has default constructor, so compiler will do it for us + +rsvcHash::rsvcHash (unsigned int max, unsigned int loadfactor) +:lf (loadfactor) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcHash Class Objects\n"); +#endif + + // figure out nearest prime number for max + tablesize = rsvc_pick_prime (max, &primeindex); +#ifdef _RSVC_DEBUG + /*printf ("table size for str hash is %d, index is %d\n", tablesize, + primeindex);*/ +#endif + // rsvcSlist has a default constructor, so one can create an array of the list + buckets = new rsvcHSlist[tablesize]; + assert (buckets); +} + +rsvcHash::~rsvcHash (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcHash Class Objects\n"); +#endif + delete []buckets; + buckets = 0; +} + +void +rsvcHash::rehash (void) +{ + if (primeindex == rsvc_prime_table_size - 1) { + fprintf (stderr, "Cannot exapnd the hash table size %d anymore\n", + rsvc_prime_table[primeindex]); + return; + } + // remember old values + unsigned int oldtablesize = tablesize; + rsvcHSlist* oldbuckets = buckets; + + // create new values + tablesize = rsvc_prime_table[primeindex + 1]; + buckets = new rsvcHSlist[tablesize]; + assert (buckets); + +#ifdef _RSVC_DEBUG + /* fprintf (stderr, "Expand hash table from %d to %d (reaching lf %d) \n", + oldtablesize, tablesize, lf);*/ +#endif + primeindex ++; + + rsvcHashable* elem = 0; + for (int i = 0; i < oldtablesize; i++) { + rsvcHSlistIterator site (oldbuckets[i]); + for (site.init (); !site; ++site) { + elem = site (); + add (elem); + } + } + + // remove old memory + delete []oldbuckets; +} + + + +int +rsvcHash::isEmpty() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + // if any table is non-empty, return 0 + for (int i = 0; i < tablesize; i++) + if (!buckets[i].isEmpty_i()) + return 0; + + // all empty + return 1; +} + +void +rsvcHash::deleteAllValues() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + // delete all values from a hash table + // clear the elements from each of teh buckets + for (int i = 0; i < tablesize; i++) + buckets[i].deleteAllValues_i(); +} + +unsigned int +rsvcHash::hash(rsvcHashable* ele) const +{ + // return hashed value of key + return (ele->hash () % tablesize); +} + +void +rsvcHash::add (rsvcHashable* newele) +{ + buckets[hash (newele)].add (newele); + if (buckets[hash (newele)].count () > lf) { +#ifdef _RSVC_DEBUG +/* fprintf (stderr, "Hash buckets %d has %d elements > load factor %d, resize\n", + hash (newele), buckets[hash (newele)].count (), lf);*/ +#endif + rehash (); + } +} + +rsvcHSlist& +rsvcHash::bucketRef (rsvcHashable* ele) +{ + return (buckets[hash (ele)]); +} + +rsvcHSlist& +rsvcHash::bucketRef (unsigned int hashcode) +{ + return (buckets[hashcode % tablesize]); +} + +void +rsvcHash::bucketList (rsvcHSlist* &lists, unsigned int& size) +{ + lists = buckets; + size = tablesize; +} + + +void +rsvcHash::asciiDump (FILE* fd) +{ + fprintf (fd, "Hash table looks like the following\n"); + fprintf (fd, "====================================================\n"); + + for (int i = 0; i < tablesize; i++) + fprintf (fd, "Bucket[%d] contains %d elements\n", i, buckets[i].count ()); + fprintf (fd, "====================================================\n"); +} + + +//====================================================================== +// class rsvcHashIterator implementation +//====================================================================== +rsvcHashIterator::rsvcHashIterator (rsvcHash& v) +:base(v), currentIndex(0), itr(0) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcHashIterator Class Object \n"); +#endif + // no further initialization +} + +rsvcHashIterator::~rsvcHashIterator (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcHashIterator Class Object \n"); +#endif + currentIndex = 0; + if (itr) + delete itr; +} + +int +rsvcHashIterator::init (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // initialize iterator, + // start search with first bucket + currentIndex = 0; + itr = 0; + return getNextIterator(); +} + +rsvcHashable * +rsvcHashIterator::operator() (void) +{ + // return current element + return (*itr)(); +} + +int +rsvcHashIterator::operator ! (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // test if there is a current element + return itr != 0; +} + +int +rsvcHashIterator::operator ++ (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // see if current iterator can be advanced + if (itr && itr->forward_i ()) + return 1; + + // if not, get next iterator + currentIndex++; + return getNextIterator(); +} + +void +rsvcHashIterator::operator = (rsvcHashable* val) +{ + // change the current value + (*itr) = val; +} + +void +rsvcHashIterator::removeCurrent (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + if (itr) + itr->removeCurrent_i (); +} + +int +rsvcHashIterator::getNextIterator (void) +{ + // if there is an old iterator, delete it + if (itr != 0) + delete itr; + + // now search for a new one + for (; currentIndex < base.tablesize; currentIndex++){ + // generate a new iterator at the current point + itr = new rsvcHSlistIterator (base.buckets[currentIndex]); + assert(itr != 0); + + // if it has at least one element, we're done + if (itr->init_i()) + return 1; + + // otherwise delete it, try again + delete itr; + } + // all out of iterators, can quit + itr = 0; + return 0; +} diff --git a/extensions/cdevGenericServer/NameServer/cdev/rsvcHashable.cc b/extensions/cdevGenericServer/NameServer/cdev/rsvcHashable.cc new file mode 100755 index 0000000..ebb6e86 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rsvcHashable.cc @@ -0,0 +1,38 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Hashable Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcHashable.cc,v +// Revision 1.1 1998/01/22 17:08:13 akers +// Addition of new NameServer +// +// +// +#include +#include "rsvcHashable.h" + +rsvcHashable::rsvcHashable (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcHashable Class Object\n"); +#endif +} + +rsvcHashable::~rsvcHashable (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcHashable Class Object\n"); +#endif +} + diff --git a/extensions/cdevGenericServer/NameServer/cdev/rsvcNetData.cc b/extensions/cdevGenericServer/NameServer/cdev/rsvcNetData.cc new file mode 100755 index 0000000..629a9d9 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rsvcNetData.cc @@ -0,0 +1,354 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcNetData Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcNetData.cc,v +// Revision 1.1 1998/01/22 17:08:18 akers +// Addition of new NameServer +// +// +// +#include +#include "rsvcNetData.h" + +rsvcNetData::rsvcNetData (void) +:cbk_ (), data_ () +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcNetData Class Object\n"); +#endif + // empty +} + +rsvcNetData::rsvcNetData (rsvcData& data, long opcode, long cbkid, + long reqid, long clientid, long socketid, + long status) +:cbk_ (opcode, cbkid, reqid, clientid, socketid, status), data_ (data) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcNetData Class Object\n"); +#endif + // empty +} + +rsvcNetData::rsvcNetData (rsvcData& data, rsvcCbk& cbk) +:cbk_ (cbk), data_ (data) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcNetData Class Object\n"); +#endif + // empty +} + +rsvcNetData::rsvcNetData (rsvcData& data) +: cbk_ (), data_ (data) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcNetData Class Object\n"); +#endif + // empty +} + +rsvcNetData::rsvcNetData (rsvcCbk& cbk) +:cbk_ (cbk), data_ () +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcNetData Class Object\n"); +#endif + // empty +} + +rsvcNetData::rsvcNetData (const rsvcNetData& data) +:cbk_ (data.cbk_), data_ (data.data_) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcNetData Class Object\n"); +#endif + // empty +} + +rsvcNetData::~rsvcNetData (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete rsvcNetData Class Object\n"); +#endif + // empty +} + +void +rsvcNetData::set (rsvcData& data, rsvcCbk& cbk) +{ + data_ = data; + cbk_ = cbk; +} + +void +rsvcNetData::set (rsvcCbk& cbk) +{ + cbk_ = cbk; +} + + +void +rsvcNetData::cleanup (void) +{ + cbk_.cleanup (); + data_.remove (); +} + +long +rsvcNetData::opcode (void) const +{ + return cbk_.opcode (); +} + +void +rsvcNetData::opcode (long op) +{ + cbk_.opcode (op); +} + +long +rsvcNetData::cbkid (void) const +{ + return cbk_.cbkid (); +} + +void +rsvcNetData::cbkid (long cid) +{ + cbk_.cbkid (cid); +} + +long +rsvcNetData::reqid (void) const +{ + return cbk_.reqid (); +} + +void +rsvcNetData::reqid (long req) +{ + cbk_.reqid (req); +} + +long +rsvcNetData::clientid (void) const +{ + return cbk_.clientid (); +} + +void +rsvcNetData::clientid (long cid) +{ + cbk_.clientid (cid); +} + +long +rsvcNetData::socketid (void) const +{ + return cbk_.socketid (); +} + +void +rsvcNetData::socketid (long sid) +{ + cbk_.socketid (sid); +} + +void +rsvcNetData::cbkstatus (long status) +{ + cbk_.cbkstatus (status); +} + +long +rsvcNetData::cbkstatus (void) const +{ + return cbk_.cbkstatus (); +} + +rsvcData& +rsvcNetData::data (void) +{ + return data_; +} + +rsvcCbk& +rsvcNetData::cbk (void) +{ + return cbk_; +} + +size_t +rsvcNetData::streamSize (void) +{ + int st = RSVC_SUCCESS; + size_t dataSize = 0; + long size = 0; + + // First is magic number + dataSize += rsvcStreamSize (_RSVC_MAGIC_NUM); + + // Size of the data to follow after this + dataSize += rsvcStreamSize (size); + + // send all cbk information + dataSize += cbk_.streamSize (); + + // send data itself + size_t buflen, count; + data_.streamSize (&buflen, &count); + + dataSize += buflen; + + return dataSize; +} + +int +rsvcNetData::streamOut (char** buffer, size_t* len) +{ + size_t datasize = streamSize (); + char* buf = new char[datasize]; + int i = 0; + + if (!buf) { + fprintf (stderr, "Cannot allocate buffer to rsvcNetData streamout\n"); + exit (1); + } + + *buffer = buf; + *len = datasize; + return streamOut (buf, *len, datasize); +} + +int +rsvcNetData::streamOut (char* buffer, size_t buflen, size_t size) +{ + int st = RSVC_SUCCESS; + int i = 0; + + if (size > buflen) { + fprintf (stderr, "Fatal: rsvcNetData streamout buffer overflow %d > %d\n", + size , buflen); + return RSVC_ERROR; + } + + // write magic number first + long tmp = htonl ((long)_RSVC_MAGIC_NUM); + memcpy (&(buffer[i]), &tmp, rsvcStreamSize (_RSVC_MAGIC_NUM)); + i += rsvcStreamSize (_RSVC_MAGIC_NUM); + + // write data size without header information + size_t real_size = size - rsvcStreamSize (_RSVC_MAGIC_NUM) + - rsvcStreamSize (size); + + tmp = htonl (real_size); + memcpy (&(buffer[i]), &tmp, rsvcStreamSize (size)); + i += rsvcStreamSize (real_size); + + // write cbk data + long cbksize = cbk_.streamSize (); + if (cbk_.streamOut (&(buffer[i]), buflen - i) != RSVC_SUCCESS) + return RSVC_ERROR; + i += (int)cbksize; + + // write data itself + size_t databuflen, datacount; + data_.streamSize (&databuflen, &datacount); + + if (data_.streamOut (&(buffer[i]), buflen - i, datacount) != RSVC_SUCCESS) + return RSVC_ERROR; + + i += databuflen; + + if (i != size) { + fprintf (stderr, "Fatal: Overflow rsvcNetData the stream out buffer\n"); + return RSVC_ERROR; + } + return RSVC_SUCCESS; +} + +int +rsvcNetData::streamOut (char* buffer, size_t len) +{ + size_t datasize = streamSize (); + + if (datasize > len) { + fprintf (stderr, "Fatal: rsvcNetData streamout buffer overflow %d > %d\n", + datasize, len); + return RSVC_ERROR; + } + return streamOut (buffer, len, datasize); +} + +int +rsvcNetData::streamIn (char* buffer, size_t len) +{ + int st = RSVC_SUCCESS; + int i = 0; + + if ((st = cbk_.streamIn (&(buffer[i]), len)) != RSVC_SUCCESS) + return st; + + i += cbk_.streamSize (); + + if ((st = data_.streamIn (&(buffer[i]), len - i)) != RSVC_SUCCESS) + return st; + + return st; +} + +int +rsvcNetData::readHeader (char* buffer, size_t len, size_t* datasize) +{ + long magicnum; + size_t size = 0; + + if (len < rsvcStreamSize (_RSVC_MAGIC_NUM) + rsvcStreamSize (size)) { + fprintf (stderr, "Fatal: reading rsvcNetData Header error: overflow\n"); + return RSVC_ERROR; + } + + int i = 0; + long tmp; + + // get magic number + memcpy (&tmp, &(buffer[i]), rsvcStreamSize (_RSVC_MAGIC_NUM)); + magicnum = ntohl (tmp); + if (magicnum != _RSVC_MAGIC_NUM) { + fprintf (stderr, "Fatal: reading rsvcNetData header error: magic number mismatch\n"); + return RSVC_ERROR; + } + i += rsvcStreamSize (_RSVC_MAGIC_NUM); + + // get data size + memcpy (&tmp, &(buffer[i]), rsvcStreamSize (size)); + size = (unsigned int)ntohl (tmp); + i += rsvcStreamSize (size); + + *datasize = size; + + return RSVC_SUCCESS; +} + +size_t +rsvcNetData::headerLen (void) +{ + return rsvcStreamSize (_RSVC_MAGIC_NUM) + rsvcStreamSize ((size_t)1); +} + + + + diff --git a/extensions/cdevGenericServer/NameServer/cdev/rsvcSlist.cc b/extensions/cdevGenericServer/NameServer/cdev/rsvcSlist.cc new file mode 100755 index 0000000..e9c58c6 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rsvcSlist.cc @@ -0,0 +1,903 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Single Linked List for void * +// +// Note: remove and clean operations on the list +// will only remove link nodes without removal of +// the content inside the nodes. It is callers' +// responsiblity to clean up those contents +// +// This is unsafe C++ practice, use this list at you own risk +// +// Reason for this list: It is very difficult to instantiate +// a template class in a stand alone shared library +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// Revision History: +// rsvcSlist.cc,v +// Revision 1.1 1998/01/22 17:08:22 akers +// Addition of new NameServer +// +// +// +#include "rsvcSlist.h" + +//====================================================================== +// class rsvcSlist implementation +//====================================================================== +rsvcSlist::rsvcSlist (void) +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +:ptrToFirstLink(0), count_ (0), lock_ () +#else +:ptrToFirstLink(0), count_ (0) +#endif +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcSlist Class Object\n"); +#endif + // no further initialization +} + +rsvcSlist::rsvcSlist (const rsvcSlist & source) +:count_ (source.count_) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcSlist Class Object\n"); +#endif + + // duplicate elements from source list + if (source.isEmpty_i()) + ptrToFirstLink = 0; + else{ + rsvcSlistLink * firstLink = source.ptrToFirstLink; + ptrToFirstLink = firstLink->duplicate(); + } +} + +rsvcSlist::~rsvcSlist (void) +{ + // empty all elements from the list +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcSlist Class Object\n"); +#endif + deleteAllValues(); +} + +void +rsvcSlist::add (rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // add a new value to the front of a linked list + ptrToFirstLink = new rsvcSlistLink(val, ptrToFirstLink); + count_ ++; + assert(ptrToFirstLink != 0); +} + +void +rsvcSlist::addToEnd (rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + count_ ++; + if (ptrToFirstLink == 0) { + ptrToFirstLink = new rsvcSlistLink(val, ptrToFirstLink); + return; + } + + // loop through until last element + rsvcSlistLink *p = 0; + for (p = ptrToFirstLink; p->ptrToNextLink; p = p->ptrToNextLink) + ; + + rsvcSlistLink* q = new rsvcSlistLink (val, 0); + p->ptrToNextLink = q; +} + +void +rsvcSlist::add_i (rsvcSlistItem val) +{ + // add a new value to the front of a linked list + count_ ++; + ptrToFirstLink = new rsvcSlistLink(val, ptrToFirstLink); + assert(ptrToFirstLink != 0); +} + +int +rsvcSlist::remove (rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // remove an element from the list + // loop to test each element + rsvcSlistLink *q = ptrToFirstLink; + for (rsvcSlistLink * p = ptrToFirstLink; p; p = p->ptrToNextLink){ + if (val == p->value){ + if (q == p){ + // remove first element + ptrToFirstLink = p->ptrToNextLink; + delete p; + } + else{ + q->ptrToNextLink = p->ptrToNextLink; + delete p; + } + count_ --; + return 1; + } + q = p; + } + // not found + return 0; +} + +void +rsvcSlist::deleteAllValues (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // clear all items from the list + rsvcSlistLink * next; + + for (rsvcSlistLink * p = ptrToFirstLink; p != 0; p = next){ + // delete the element pointed to by p + next = p->ptrToNextLink; + p->ptrToNextLink = 0; + delete p; + } + + // set count to zero + count_ = 0; + // mark that the list contains no elements + ptrToFirstLink = 0; +} + +void +rsvcSlist::deleteAllValues_i (void) +{ + // clear all items from the list + rsvcSlistLink * next; + + for (rsvcSlistLink * p = ptrToFirstLink; p != 0; p = next){ + // delete the element pointed to by p + next = p->ptrToNextLink; + p->ptrToNextLink = 0; + delete p; + } + + // set count to zero + count_ = 0; + + // mark that the list contains no elements + ptrToFirstLink = 0; +} + +int +rsvcSlist::count (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + return count_; +} + +rsvcSlist* +rsvcSlist::duplicate (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + rsvcSlist * newlist = new rsvcSlist; + assert(newlist != 0); + + // copy list + if (ptrToFirstLink) + newlist->ptrToFirstLink = ptrToFirstLink->duplicate(); + + // set new list count + newlist->count_ = count_; + // return the new list + return newlist; +} + +rsvcSlistItem +rsvcSlist::firstElement (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // return first value in list + assert(ptrToFirstLink != 0); + return ptrToFirstLink->value; +} + +rsvcSlistItem +rsvcSlist::firstElement_i (void) +{ + // return first value in list + assert(ptrToFirstLink != 0); + return ptrToFirstLink->value; +} + +rsvcSlistItem +rsvcSlist::lastElement (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + assert(ptrToFirstLink != 0); + // loop through until last element + rsvcSlistLink *p = 0; + for (p = ptrToFirstLink; p->ptrToNextLink; p = p->ptrToNextLink) + ; + return p->value; +} + +rsvcSlistItem +rsvcSlist::lastElement_i (void) +{ + assert(ptrToFirstLink != 0); + // loop through until last element + rsvcSlistLink *p = 0; + for (p = ptrToFirstLink; p->ptrToNextLink; p = p->ptrToNextLink) + ; + return p->value; +} + +int +rsvcSlist::includes(rsvcSlistItem v) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // loop to test each element + for (rsvcSlistLink * p = ptrToFirstLink; p; p = p->ptrToNextLink) + if (v == p->value) + return 1; + + // not found + return 0; +} + +int +rsvcSlist::isEmpty (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // test to see if the list is empty + // list is empty if the pointer to the first link is null + return ptrToFirstLink == 0; +} + +int +rsvcSlist::isEmpty_i (void) const +{ + // test to see if the list is empty + // list is empty if the pointer to the first link is null + return ptrToFirstLink == 0; +} + +void +rsvcSlist::removeFirst (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // make sure there is a first element + assert(ptrToFirstLink != 0); + + // save pointer to the removed node + rsvcSlistLink * p = ptrToFirstLink; + + // reassign the ptrToFirstLink node + ptrToFirstLink = p->ptrToNextLink; + + // decrease the count + count_ --; + // recover memory used by the first element + delete p; +} + +void +rsvcSlist::removeFirst_i (void) +{ + // make sure there is a first element + assert(ptrToFirstLink != 0); + + // save pointer to the removed node + rsvcSlistLink * p = ptrToFirstLink; + + // reassign the ptrToFirstLink node + ptrToFirstLink = p->ptrToNextLink; + + // decrease the count + count_ --; + + // recover memory used by the first element + delete p; +} + +//====================================================================== +// class slink implementation +// No need to add any mutex protection since all member +// functions are called with lock held +//====================================================================== +rsvcSlistLink* +rsvcSlistLink::insert(rsvcSlistItem val) +{ + // insert a new link after current node + ptrToNextLink = new rsvcSlistLink(val, ptrToNextLink); + + // check that allocation was successful + assert(ptrToNextLink != 0); + return ptrToNextLink; +} + +rsvcSlistLink::rsvcSlistLink (rsvcSlistItem val, rsvcSlistLink * nxt) +:value(val), ptrToNextLink(nxt) +{ + // create and initialize a new link field +} + +rsvcSlistLink* +rsvcSlistLink::duplicate (void) +{ + rsvcSlistLink * newlink; + + // if there is a next field. copy remainder of list + if (ptrToNextLink != 0) + newlink = new rsvcSlistLink(value, ptrToNextLink->duplicate()); + else + newlink = new rsvcSlistLink (value, 0); + + // check that allocation was successful + assert(newlink != 0); + return newlink; +} + +rsvcSlistLink* +rsvcSlistLink::next (void) +{ + return ptrToNextLink; +} + +rsvcSlistItem +rsvcSlistLink::data (void) +{ + return value; +} + +//====================================================================== +// class listIterator implementation +//====================================================================== +rsvcSlistIterator::rsvcSlistIterator(rsvcSlist & aList) +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +:theList(aList), lock_ () +#else +:theList(aList) +#endif +{ + // create and initialize a new list + init_i(); +} + +int +rsvcSlistIterator::init_i() +{ + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +int +rsvcSlistIterator::init() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +rsvcSlistItem +rsvcSlistIterator::operator () (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + // return value of current element + // check to see if there is a current element + assert(currentLink != 0); + + // return value associated with current element + return currentLink->value; +} + +int rsvcSlistIterator::operator ! (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + // test for termination of the iterator + // if current link references a removed value, + // update current to point to next position + if (currentLink == 0) + if (previousLink != 0) + currentLink = previousLink->ptrToNextLink; + + // now see if currentLink is valid + return currentLink != 0; +} + +int rsvcSlistIterator::forward_i (void) +{ + // move current pointer to nect element + // special processing if current link is deleted + if (currentLink == 0){ + if (previousLink == 0) + currentLink = theList.ptrToFirstLink; + else + currentLink = previousLink->ptrToNextLink; + } + else{ + // advance pointer + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + + +int rsvcSlistIterator::operator ++() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // move current pointer to nect element + // special processing if current link is deleted + if (currentLink == 0){ + if (previousLink == 0) + currentLink = theList.ptrToFirstLink; + else + currentLink = previousLink->ptrToNextLink; + } + else{ + // advance pointer + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +void rsvcSlistIterator::operator = (rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // modify value of current element + assert(currentLink != 0); + + // modify value of the current link + currentLink->value = val; +} + +void rsvcSlistIterator::removeCurrent_i (void) +{ + // remove the current element from a list + // make sure there is a current element + assert(currentLink != 0); + + // case 1, removing first element + if (previousLink == 0) + theList.ptrToFirstLink = currentLink->ptrToNextLink; + + // case 2, not removing the first element + else + previousLink->ptrToNextLink = currentLink->ptrToNextLink; + + // delete current node + delete currentLink; + + // and set current pointer to null + currentLink = 0; + + // decrease list count element + theList.count_ --; +} + +void rsvcSlistIterator::removeCurrent (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // remove the current element from a list + // make sure there is a current element + assert(currentLink != 0); + + // case 1, removing first element + if (previousLink == 0) + theList.ptrToFirstLink = currentLink->ptrToNextLink; + + // case 2, not removing the first element + else + previousLink->ptrToNextLink = currentLink->ptrToNextLink; + + // delete current node + delete currentLink; + + // and set current pointer to null + currentLink = 0; + + // decrease list count element + theList.count_ --; +} + +void rsvcSlistIterator::addBefore(rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // add a new element to list before current value + // case 1, not at start + if (previousLink) + previousLink = previousLink->insert(val); + + // case 2, at start of list + else{ + theList.rsvcSlist::add(val); + previousLink = theList.ptrToFirstLink; + currentLink = previousLink->ptrToNextLink; + } + + // increase the count + theList.count_ ++; +} + +void rsvcSlistIterator::addAfter(rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // a a new element to list after current value + // case 1, not at start + if (currentLink != 0) + currentLink->insert(val); + + // case 2, at end of list + else if (previousLink != 0) + currentLink = previousLink->insert(val); + + // case 3, start of list + else + theList.rsvcSlist::add(val); + + // increase the count + theList.count_ ++; +} + +int rsvcSlistIterator::searchSame(rsvcSlistItem &val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // search the list to find out whether we have this element + // if we do, move cursor to this element return 1 + // if we don't return 0 + init_i(); + + if (currentLink == 0){ + // empty link + return 0; + } + while (currentLink != 0){ + // advance pointer + if (currentLink->value == val) + break; + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +//======================================================================== +// Implementation of rsvcSlistCursor +// Implements of cursor without changing list +//======================================================================== +rsvcSlistCursor::rsvcSlistCursor(const rsvcSlist & aList) +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +:theList(aList), lock_ () +#else +:theList(aList) +#endif +{ + // create and initialize a new list + init_i(); +} + +int +rsvcSlistCursor::init_i() +{ + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +int +rsvcSlistCursor::init() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +rsvcSlistItem +rsvcSlistCursor::operator () (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // return value of current element + // check to see if there is a current element + assert(currentLink != 0); + + // return value associated with current element + return currentLink->value; +} + +int rsvcSlistCursor::operator ! (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // test for termination of the iterator + // if current link references a removed value, + // update current to point to next position + if (currentLink == 0) + if (previousLink != 0) + currentLink = previousLink->ptrToNextLink; + + // now see if currentLink is valid + return currentLink != 0; +} + +int rsvcSlistCursor::operator ++ (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // move current pointer to nect element + // special processing if current link is deleted + if (currentLink == 0){ + if (previousLink == 0) + currentLink = theList.ptrToFirstLink; + else + currentLink = previousLink->ptrToNextLink; + } + else{ + // advance pointer + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +int rsvcSlistCursor::searchSame (rsvcSlistItem &val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + // search the list to find out whether we have this element + // if we do, move cursor to this element return 1 + // if we don't return 0 + init_i(); + + if (currentLink == 0){ + // empty link + return 0; + } + while (currentLink != 0){ + // advance pointer + if (currentLink->value == val) + break; + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +void rsvcSlistCursor::operator = (rsvcSlistItem ) +{ + // empty +} + + +//======================================================================== +// Implementation of doubleEndedList +//======================================================================== +rsvcDoubleEndedSlist::rsvcDoubleEndedSlist() +:rsvcSlist() +{ + ptrToLastLink = 0; +} + +rsvcDoubleEndedSlist::rsvcDoubleEndedSlist(const rsvcDoubleEndedSlist &v) +:rsvcSlist(v) +{ + ptrToLastLink = v.ptrToLastLink; +} + +void +rsvcDoubleEndedSlist::add(rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // add method needs to check one special case when the first element + // is added to the list + if (isEmpty_i()) { + // call parent method + rsvcSlist::add_i (val); + ptrToLastLink = ptrToFirstLink; + } + else{ + // always add to the head + rsvcSlist::add_i(val); + } +} + +void +rsvcDoubleEndedSlist::addToEnd (rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + //add new value T to the end of the list + // if there is an end, add to it + if(ptrToLastLink != 0) { + ptrToLastLink = ptrToLastLink->insert(val); + count_ ++; + } + else { + assert (isEmpty_i ()); + // call parent method + rsvcSlist::add_i (val); + ptrToLastLink = ptrToFirstLink; + } +} + +void +rsvcDoubleEndedSlist::deleteAllValues() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + //delete all values from the list + rsvcSlist::deleteAllValues_i(); + ptrToLastLink = 0; +} + +void +rsvcDoubleEndedSlist::removeFirst() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + //remove the first element from the list + // invoke the parent method + rsvcSlist::removeFirst_i(); + + // only do something if we removed last element + if(isEmpty_i()) + ptrToLastLink = 0; +} + + +//======================================================================== +// Implementation of queue +//======================================================================== +rsvcQueue::rsvcQueue (void) +:rsvcDoubleEndedSlist () +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcQueue Class Object\n"); +#endif +} + +rsvcSlistItem +rsvcQueue::front (void) +{ + return firstElement (); +} + +void +rsvcQueue::enqueue (rsvcSlistItem val) +{ + // add new value val to the end of the list + // if there is an end, add to it + if(ptrToLastLink != 0) { + ptrToLastLink = ptrToLastLink->insert(val); + count_ ++; + } + else { + assert (isEmpty_i ()); + // call parent method + rsvcSlist::add_i (val); + ptrToLastLink = ptrToFirstLink; + } +} + +rsvcSlistItem +rsvcQueue::dequeue (void) +{ + if (isEmpty_i ()) + return 0; + + // get first element + rsvcSlistItem result = firstElement_i (); + //remove the first element from the list + // invoke the parent method + rsvcSlist::removeFirst_i(); + + // only do something if we removed last element + if(isEmpty_i()) + ptrToLastLink = 0; + + return result; +} diff --git a/extensions/cdevGenericServer/NameServer/cdev/rsvcStreamable.cc b/extensions/cdevGenericServer/NameServer/cdev/rsvcStreamable.cc new file mode 100755 index 0000000..f8f0f51 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rsvcStreamable.cc @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Streamable class +// +// Author: Jie Chen +// +// Revision History: +// rsvcStreamable.cc,v +// Revision 1.1 1998/01/22 17:08:23 akers +// Addition of new NameServer +// +// +// +#include +#include +#include "rsvcStreamable.h" + +rsvcStreamable::rsvcStreamable (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcStreamable Class Object\n"); +#endif + // empty +} + +rsvcStreamable::~rsvcStreamable (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcStreamable Class Object\n"); +#endif + // empty +} + diff --git a/extensions/cdevGenericServer/NameServer/cdev/rsvcUdpClient.cc b/extensions/cdevGenericServer/NameServer/cdev/rsvcUdpClient.cc new file mode 100755 index 0000000..ac7a2f2 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/cdev/rsvcUdpClient.cc @@ -0,0 +1,167 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC UDP Client +// +// Author: Jie Chen +// +// Revision History: +// rsvcUdpClient.cc,v +// Revision 1.2 1998/02/20 19:37:28 chen +// reset errno after using it (hpux) sometimes not resetting it +// +// Revision 1.1 1998/01/22 17:08:25 akers +// Addition of new NameServer +// +// +// +#include "rsvcUdpClient.h" +#include + +rsvcUdpClient::rsvcUdpClient (void) +:fd_ (-1) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcUdpClient Class Object\n"); +#endif +} + + +rsvcUdpClient::~rsvcUdpClient (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcUdpClient Class Object\n"); +#endif + if (fd_ != -1) + close (fd_); +} + +int +rsvcUdpClient::connect (char* host, unsigned short port) +{ + if ((openUdpPort (host, port)) == -1) + return RSVC_ERROR; + + return RSVC_SUCCESS; +} + +int +rsvcUdpClient::disconnect (void) +{ + if (fd_ != -1) + close (fd_); + return RSVC_SUCCESS; +} + +int +rsvcUdpClient::update (rsvcData& data) +{ + if (fd_ == -1) + return RSVC_ERROR; + + int nbytes; + int nw; + int status = RSVC_SUCCESS; + + rsvcCbk cbkid (RSVC_SET, (long)0, + (long)5678, (long)fd_); + // create netdata + rsvcNetData netdata (data, cbkid); + + if ((nbytes = streamData (netdata)) <= 0) + status = RSVC_ERROR; + else { + // block write + if ((nw = ::sendto (fd_, obuffer_, nbytes, 0, (sockaddr *)&udp_addr_, + sizeof (udp_addr_))) != nbytes) { +#ifdef _RSVC_DEBUG + printf ("rsvcUdpClient: wrote %d nbytes and expect to write %d bytes\n", + nw, nbytes); + printf ("rsvcUdpClient: errno is %d\n", errno); + perror ("client sendto error "); + // reset errno + errno = 0; +#endif + status = RSVC_ERROR; + } + } + return status; +} + +int +rsvcUdpClient::streamData (rsvcNetData& data) +{ + size_t datasize = data.streamSize (); + + if (datasize > sizeof (obuffer_)) { +#ifdef _RSVC_DEBUG + printf ("rsvcUdpClient: Streamed data size %d is exceeding %d, resize\n", + datasize, sizeof(obuffer_)); +#endif + return -1; + } + + if (data.streamOut (obuffer_, datasize) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcUdpClient: rsvcNetData stream out error\n"); +#endif + return -1; + } + return datasize; +} + +int +rsvcUdpClient::openUdpPort (char* host, unsigned short port) +{ + struct sockaddr_in my_addr; + struct hostent* hp = 0; + + // initialize the server inet address structure + ::memset (&udp_addr_, 0, sizeof (udp_addr_)); + udp_addr_.sin_family = AF_INET; + udp_addr_.sin_port = htons (port); + + hp = gethostbyname (host); + + if (hp == 0) { + fprintf (stderr, "rsvcUdpClient: Cannot find ip address of host %s\n", + host); + return -1; + } + ::memcpy (&udp_addr_.sin_addr, hp->h_addr, hp->h_length); + + // open a socket + if ((fd_ = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { + fprintf (stderr, "udp_open: cannot create socket\n"); + fd_ = -1; + return -1; + } + // bind local address for us + ::memset (&my_addr, 0, sizeof (my_addr)); + my_addr.sin_family = AF_INET; + my_addr.sin_addr.s_addr = htonl (INADDR_ANY); + my_addr.sin_port = htons (0); + + if (bind (fd_, (struct sockaddr *)&my_addr, sizeof (my_addr)) < 0) { + fprintf (stderr, "rsvcUdpClient : bind error\n"); + close (fd_); + fd_ = -1; + return -1; + } + return 0; +} + + + + + + + + diff --git a/extensions/cdevGenericServer/NameServer/dumpServer/.shobj/Linux/dumpServer.o b/extensions/cdevGenericServer/NameServer/dumpServer/.shobj/Linux/dumpServer.o new file mode 100644 index 0000000..28df78a Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/dumpServer/.shobj/Linux/dumpServer.o differ diff --git a/extensions/cdevGenericServer/NameServer/dumpServer/DumpAllHandler.h b/extensions/cdevGenericServer/NameServer/dumpServer/DumpAllHandler.h new file mode 100755 index 0000000..f04d426 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/dumpServer/DumpAllHandler.h @@ -0,0 +1,274 @@ +#if !defined (_SIMPLE_SERVER_HANDLER_H_) +#define _SIMPLE_SERVER_HANDLER_H_ + +#include "cdevEventHandler.h" +#include "cdevAddr.h" +#include "cdevSocketConnector.h" +#include "cdevReactor.h" +#include "ErrorReporter.h" +#include "SocketUtil.h" +#include "fifo.h" +#include "clipMagicNumber.h" +#include "cdevMessageBinary.h" +#include "cdevMessage.h" +#include "ClientInfo.h" + + +const int _CDEV_CONNECTION_RETRIES = 5; +const int MAX_SERVERS = 1024; +extern FifoQueue results [MAX_SERVERS]; +extern int completionCodes[MAX_SERVERS]; + +class DumpAllHandler : public cdevEventHandler, + public SocketReader, + public SocketWriter +{ +protected: + char hostName [MAXHOSTNAMELEN + 1]; + FifoQueue queue; + cdevSocketConnector stream; + int serverQuitFlag; + cdevReactor & Reactor; + int index; + ClientInfo info; + +public: + DumpAllHandler (char * Host, unsigned short Port, cdevReactor & LocalReactor, int Index) + : info(), + SocketReader(CLIP_MAGIC_NUMBER), + SocketWriter(CLIP_MAGIC_NUMBER), + index(Index), + Reactor(LocalReactor), + serverQuitFlag(0) + { + cdevInetAddr addr; + hostName[0] = 0; + addr.set (Port, Host); + if(open(addr)!=0) + { + outputError(CDEV_SEVERITY_ERROR, + "DumpAllHandler::connect", + "Failed to connect to %s on port %i", + Host, + Port); + completionCodes[index]=-1; + } + + completionCodes[index] = 0; + + cdevData tagMap; + int * tags; + char ** ctags; + int ntags; + char * binary = NULL; + size_t binaryLen = 0; + + cdevData::readTagTable(tags, ctags, ntags); + tagMap.insert(1, tags, ntags); + tagMap.insert(2, ctags, ntags); + + delete tags; + delete ctags; + + cdevMessageBinary packet0(index, 0, 0, 0, 0, CDEV_SERVER_OP, 0, 0, + NULL, "set ClientInfo", &info.getClientData(), + NULL, &tagMap); + + packet0.streamOut(&binary, &binaryLen); + packet0.detachData(); + enqueue(binary, binaryLen); + + cdevMessageBinary packet1(index, 1, 0, 0, 0, CDEV_SERVER_OP, 0, 0, + NULL, "get ServerInfo", NULL, NULL, &tagMap); + + packet1.streamOut(&binary, &binaryLen); + packet1.detachData(); + enqueue(binary, binaryLen); + + cdevMessageBinary packet2(index, 2, 0, 0, 0, CDEV_SERVER_OP, 0, 0, + NULL, "get ClientInfo", NULL, NULL, &tagMap); + packet2.streamOut(&binary, &binaryLen); + packet2.detachData(); + enqueue(binary, binaryLen); + } + + ~DumpAllHandler (void) + { + if(completionCodes[index]!=1) completionCodes[index]=-1; + if(stream.getHandle()>0 && serverQuitFlag==0) + { + writeGoodbye(); + } + + if(reactor) reactor->extractHandler(this); + handleClose(); + } + + int open (const cdevAddr &addr) + { + int result = 0; + int count = 0; + + result = stream.connect (addr); + + if (result != -1) + { + if((result = Reactor.registerHandler(this, READ_MASK|WRITE_MASK|EXCEPT_MASK))==-1) + { + handleClose(); + } + } + return result; + } + + char * getHostName ( void ) + { + if(*hostName==0) + { + cdevInetAddr addr; + if(stream.getRemoteAddress (addr)==0) + { + const char * ptr=addr.getHostName(); + if(ptr) strncpy (hostName, ptr, MAXHOSTNAMELEN+1); + } + } + return hostName; + } + + char * getName (void) const + { + return "DumpAllHandler"; + } + + int getHandle (void) const + { + return stream.getHandle(); + } + + void enqueue (char * buf, size_t len) + { + queue.enqueue(buf, len); + setMask(WRITE_MASK|EXCEPT_MASK); + } + + void undequeue (char * buf, size_t len) + { + queue.undequeue(buf, len); + } + + int dequeue (char **buf, size_t *len) + { + return queue.dequeue(buf, len); + } + + int empty (void) + { + return queue.empty(); + } + + int handleClose (void) + { + stream.close(); + return 0; + } + + int handleInput (void) + { + int retval = 0; + char * buf = NULL; + size_t len = 0; + int result = 1; + + while(result>0) + { + result = read(&buf, (int *)&len); + + switch(result) + { + case SHUTDOWN_CODE: + outputError(CDEV_SEVERITY_INFO, (char *)getName(), + "Connection to %s terminated by client", getHostName()); + retval = -1; + break; + + case -1: + outputError(CDEV_SEVERITY_WARN, (char *)getName(), + "Error reading from connection to client %s", getHostName()); + retval = -1; + break; + + case 0: + break; + + default: + { + cdevMessage *message = new cdevMessage; + unsigned transIndex = 0; + unsigned clientID = 0; + + if(message->streamIn(buf, len)==0 && + (clientID=message->getClientID())==index && + (transIndex=message->getTransIndex())>0 && + transIndex<3) + { + results[index].enqueue((void *)message); + if(transIndex==2) completionCodes[index] = 1; + } + else delete message; + } + break; + } + } + + return retval; + } + + int handleOutput (void) + { + int retval = 0; + char * buf = NULL; + size_t len = 0; + + if(!writing() && dequeue(&buf, &len)==0) + { + int full = 0; + while(!full) + { + if(!(full = writeEnqueue(buf, len))) + { + delete buf; + full = dequeue(&buf, &len); + } + else undequeue(buf, len); + } + if(writeContinue()<0) retval = -1; + } + else if(writing()) + { + if(writeContinue()<0) retval = -1; + } + + if(retval!=0) + { + outputError(CDEV_SEVERITY_WARN, (char *)getName(), + "Error transmitting to %s", getHostName()); + } + + if(empty() && !writing()) + { + setMask(READ_MASK|EXCEPT_MASK); + } + + return retval; + } + + int handleExcept (void) + { + stream.close(); + serverQuitFlag=1; + return -1; + } +}; + + +#endif /* _SIMPLE_SERVER_HANDLER_H_ */ diff --git a/extensions/cdevGenericServer/NameServer/dumpServer/Makefile b/extensions/cdevGenericServer/NameServer/dumpServer/Makefile new file mode 100755 index 0000000..aec041e --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/dumpServer/Makefile @@ -0,0 +1,14 @@ +ARCH = OS +SHOBJ = YES + +include ../../include/makeinclude/Makefile.$(ARCH) + +APPNAME = Name Server Query Application +LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) +BINARIES = $(CDEVBIN)/dumpServer + +targets: $(BINARIES) + +$(CDEVBIN)/dumpServer: $(OBJDIR)/dumpServer.o + $(LINK.cc) $^ $(LIBS) -o $@ + diff --git a/extensions/cdevGenericServer/NameServer/dumpServer/NMakefile.mak b/extensions/cdevGenericServer/NameServer/dumpServer/NMakefile.mak new file mode 100644 index 0000000..c164514 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/dumpServer/NMakefile.mak @@ -0,0 +1,18 @@ +.SUFFIXES: .cc .obj + +APPNAME = Name Server Query Application +ARCH = WINNT-4.0 + +BINARIES = $(CDEVBIN)\dumpServer.exe + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +targets : $(BINARIES) + +$(CDEVBIN)\dumpServer.exe : .exec\$(TARGETDIR)\dumpServer.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + diff --git a/extensions/cdevGenericServer/NameServer/dumpServer/NameServer.ddl b/extensions/cdevGenericServer/NameServer/dumpServer/NameServer.ddl new file mode 100755 index 0000000..e55ee8a --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/dumpServer/NameServer.ddl @@ -0,0 +1,16 @@ +service rns { + tags {PV} +} + +class RNS { + messages { + query rns; + get rns; + monitorOn rns; + monitorOff rns; + } +} + +RNS : +NameServer +; diff --git a/extensions/cdevGenericServer/NameServer/dumpServer/dumpServer.cc b/extensions/cdevGenericServer/NameServer/dumpServer/dumpServer.cc new file mode 100755 index 0000000..ebb3a60 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/dumpServer/dumpServer.cc @@ -0,0 +1,705 @@ +#include +#include +#include +#include +#include "DumpAllHandler.h" +#include "cdevGenericServerTags.h" + +FifoQueue results [MAX_SERVERS]; +int completionCodes[MAX_SERVERS]; + +static char * NameServerDefinitionString = +"service rns { tags {PV} }\n\ +class RNS { messages { query rns; get rns; monitorOn rns; monitorOff rns; } }\n\ +RNS :\nNameServer\n;\n"; + +cdevReactor DumpAllReactor; + +void ReportStandard ( char * Domain, char * Name, char * Server, int Port, int index ); +void ReportBrief ( int index ); +void ReportServerBrief ( cdevData & data ); +void ReportClientBrief ( cdevData & data ); +void ReportComplete ( int index ); +void ReportServerComplete ( cdevData & data ); +void ReportClientComplete ( cdevData & data ); +void *getItem ( cdevData & data, char * tag, unsigned defaultItem); +void *getItem ( cdevData & data, char * tag, float defaultItem); +void *findItem ( cdevData & data, char * tag, cdevDataTypes type, size_t maxItems, void *defaultItem); + + +int main (int argc, char ** argv) + { + char * cdevNameServer = getenv("CDEV_NAME_SERVER"); + cdevGenericServerTagDef tags; + + typedef enum { STANDARD=0, BRIEF=1, COMPLETE=2, SIMPLE=4, BOGUS=8} ReportType; + ReportType reportType = STANDARD; + + if(cdevNameServer==NULL) + { + fprintf(stdout, "-----------------------------------------------------------------------\n"); + fprintf(stdout, "ERROR : CDEV_NAME_SERVER is not defined in the local environment.\n"); + fprintf(stdout, " Set the CDEV_NAME_SERVER variable to indicate the host where \n"); + fprintf(stdout, " the name server is running prior to executing this application.\n"); + fprintf(stdout, "-----------------------------------------------------------------------\n"); + fflush(stdout); + exit(1); + } + + for(int x=1; xsend(in, data)!=CDEV_SUCCESS) + { + cdevSystem::defaultSystem().reportError(CDEV_SEVERITY_ERROR, "DumpServer", NULL, "Failed to communicate with Name Server"); + return 0; + } + + size_t cnt = 0, cnt1 = 0; + char ** domainPtr = NULL; + char ** serverPtr = NULL; + char ** hostPtr = NULL; + int * portPtr = NULL; + int * status = NULL; + + if(data.getElems("domain", &cnt1)==CDEV_SUCCESS && cnt1>cnt) cnt = cnt1; + if(data.getElems("name", &cnt1)==CDEV_SUCCESS && cnt1>cnt) cnt = cnt1; + if(data.getElems("host", &cnt1)==CDEV_SUCCESS && cnt1>cnt) cnt = cnt1; + if(data.getElems("port", &cnt1)==CDEV_SUCCESS && cnt1>cnt) cnt = cnt1; + if(data.getElems("status", &cnt1)==CDEV_SUCCESS && cnt1>cnt) cnt = cnt1; + + if(cnt>0) + { + domainPtr = new char *[cnt]; + serverPtr = new char *[cnt]; + hostPtr = new char *[cnt]; + portPtr = new int [cnt]; + status = new int [cnt]; + + memset(domainPtr, 0, sizeof(char *)*cnt); + memset(serverPtr, 0, sizeof(char *)*cnt); + memset(hostPtr, 0, sizeof(char *)*cnt); + memset(portPtr, 0, sizeof(int)*cnt); + memset(status, 0, sizeof(int)*cnt); + + data.get("domain", domainPtr); + data.get("name", serverPtr); + data.get("host", hostPtr); + data.get("port", portPtr); + data.get("status", status); + + int i, retry=0; + if(reportType==SIMPLE) + { + fprintf(stdout, "\n================================================================================\n"); + fprintf(stdout, " THIS DATA OBTAINED FROM CDEV NAME SERVER AT : %s\n", cdevNameServer); + fprintf(stdout, "================================================================================\n\n"); + + fprintf(stdout, "\n-------------------------------------------------------------------------------\n"); + fprintf(stdout, " DOMAIN NAME HOST PORT \n"); + fprintf(stdout, "--------------------------------------------------------------------------------\n"); + fflush(stdout); + + for(i=0; igetTransIndex()==1) + { + if(ServerInfo!=NULL) delete ServerInfo; + ServerInfo = temp; + } + else if(temp->getTransIndex()==2) + { + if(ClientInfo!=NULL) delete ClientInfo; + ClientInfo = temp; + } + } + char domain[255]; + char name [255]; + char server[255]; + char startTimeStr[255]; + int port = 0; + float utilization = 0; + time_t startTime = 0; + int clientCnt = 0; + + if(ServerInfo) + { + cdevData * data = ServerInfo->getData(); + if(data->get("domain", domain, 255)!=CDEV_SUCCESS) strcpy(domain, Domain); + if(data->get("server", name, 255)!=CDEV_SUCCESS) strcpy(name, Name); + if(data->get("host", server, 255)!=CDEV_SUCCESS) strcpy(server, Server); + if(data->get("port", &port)!=CDEV_SUCCESS) port = Port; + if(data->get("pctcpu", &utilization)!=CDEV_SUCCESS) utilization = 0; + if(data->get("starttime", &startTime)!=CDEV_SUCCESS) startTime = time(NULL); + } + else { + strcpy(domain, Domain); + strcpy(name, Name); + strcpy(server, Server); + port = Port; + utilization = 0; + startTime = time(NULL); + } + + sprintf(startTimeStr, "%s", startTime?ctime(&startTime):"UNKNOWN"); + if(strchr(startTimeStr, '\n')!=NULL) *(strchr(startTimeStr, '\n'))=0; + + if(!headerDefined) + { + fprintf(stdout, "\n--------------------------------------------------------------------------------\n"); + fprintf(stdout, " DOMAIN NAME HOST PORT CPU%% START\n"); + fprintf(stdout, "--------------------------------------------------------------------------------\n"); + fflush(stdout); + headerDefined = 1; + } + fprintf(stdout, " %-17s%-17s%-17s% 5i %5.2f %s\n", domain, name, server, port, utilization*100.0, startTimeStr); + fflush(stdout); + if(ServerInfo) delete ServerInfo; + if(ClientInfo) delete ClientInfo; + } + +void ReportBrief ( int index ) + { + static int headerDefined = 0; + cdevMessage *ServerInfo=NULL, *ClientInfo=NULL, * temp; + while(completionCodes[index]==1 && (temp = (cdevMessage *)results[index].dequeue())!=NULL) + { + if(temp->getTransIndex()==1) + { + if(ServerInfo!=NULL) delete ServerInfo; + ServerInfo = temp; + } + else if(temp->getTransIndex()==2) + { + if(ClientInfo!=NULL) delete ClientInfo; + ClientInfo = temp; + } + } + + + cdevData * data; + if(ServerInfo && (data=ServerInfo->getData())!=NULL) + { + if(!headerDefined) + { + fprintf(stdout, "\n--------------------------------------------------------------------------------"); + headerDefined = 1; + } + fprintf(stdout, "\n DOMAIN NAME HOST PORT CPU%% START\n"); + fprintf(stdout, "--------------------------------------------------------------------------------\n"); + fflush(stdout); + + ReportServerBrief(*data); + delete ServerInfo; + } + else return; + + if(ClientInfo && (data=ClientInfo->getData())!=NULL) + { + ReportClientBrief(*data); + delete ClientInfo; + } + } + +void ReportServerBrief ( cdevData & data ) + { + char *unknown = "UNKNOWN"; + char *domain = (char *)findItem(data, "domain", CDEV_STRING, 1, unknown);; + char *server = (char *)findItem(data, "server", CDEV_STRING, 1, unknown);; + char *host = (char *)findItem(data, "host", CDEV_STRING, 1, unknown);; + int port = *(unsigned *)getItem(data, "port", 0U); + time_t starttime = *(unsigned *)getItem(data, "starttime", (unsigned)time(NULL)); + float pctcpu = *(float *)getItem(data, "pctcpu", (float)0.0); + char startTimeStr[255]; + + sprintf(startTimeStr, "%s", starttime?ctime(&starttime):"UNKNOWN"); + if(strchr(startTimeStr, '\n')!=NULL) *(strchr(startTimeStr, '\n'))=0; + + fprintf(stdout, " %-17s%-17s%-17s% 5i %5.2f %s\n", domain, server, host, port, pctcpu*100.0, startTimeStr); + fflush(stdout); + return; + } + + +void ReportClientBrief ( cdevData & data ) + { + static char * ClientInfoTags[]= + { + "username", "group", "uid", "gid", "pid", "program", + "commandline", "starttime", "connecttime", "host", + "os", "osversion", "osrelease", "machine", "shell", + "socket", "sendPktCnt", "recvPktCnt", "\0", + }; + size_t i, j; + size_t nClients = 0; + + data.getElems(ClientInfoTags[0], &nClients); + + for(i=0; *ClientInfoTags[i]!=0; i++) + { + data.getElems(ClientInfoTags[i], &j); + if(j!=nClients) + { + fprintf(stdout, "ERROR : Inconsistent data in ClientInfo Structure\n"); + fflush(stdout); + return; + } + } + + if(nClients==0) return; + + unsigned * connecttime = (unsigned *)findItem(data, "connecttime", CDEV_UINT32, nClients, NULL); + + char ** username = NULL; + char * usernamePtr = NULL; + char ** program = NULL; + char * programPtr = NULL; + char ** host = NULL; + char * hostPtr = NULL; + + if(nClients>1) + { + username = (char **) findItem(data, "username", CDEV_STRING, nClients, NULL); + program = (char **) findItem(data, "program", CDEV_STRING, nClients, NULL); + host = (char **) findItem(data, "host", CDEV_STRING, nClients, NULL); + } + else { + username = &(usernamePtr = (char *)findItem(data, "username", CDEV_STRING, nClients, NULL)); + program = &(programPtr = (char *)findItem(data, "program", CDEV_STRING, nClients, NULL)); + host = &(hostPtr = (char *)findItem(data, "host", CDEV_STRING, nClients, NULL)); + } + + if(username==NULL || program==NULL || connecttime==NULL || host==NULL) + { + fprintf(stdout, "ERROR : Inconsistent data in ClientInfo Structure\n"); + fflush(stdout); + return; + } + + for(i=0; igetTransIndex()==1) + { + if(ServerInfo!=NULL) delete ServerInfo; + ServerInfo = temp; + } + else if(temp->getTransIndex()==2) + { + if(ClientInfo!=NULL) delete ClientInfo; + ClientInfo = temp; + } + } + + cdevData * data; + if(ServerInfo && (data=ServerInfo->getData())!=NULL) + { + ReportServerComplete(*data); + delete ServerInfo; + } + else return; + + if(ClientInfo && (data=ClientInfo->getData())!=NULL) + { + ReportClientComplete(*data); + delete ClientInfo; + } + } + + +void ReportServerComplete ( cdevData & data ) + { + char *unknown = "UNKNOWN"; + char *username = (char *)findItem(data, "username", CDEV_STRING, 1, unknown); + char *group = (char *)findItem(data, "group", CDEV_STRING, 1, unknown);; + unsigned pid = *(unsigned *)getItem(data, "pid", 0U); + unsigned uid = *(unsigned *)getItem(data, "uid", 0U); + unsigned gid = *(unsigned *)getItem(data, "gid", 0U); + char *domain = (char *)findItem(data, "domain", CDEV_STRING, 1, unknown);; + char *server = (char *)findItem(data, "server", CDEV_STRING, 1, unknown);; + char *host = (char *)findItem(data, "host", CDEV_STRING, 1, unknown);; + int port = *(unsigned *)getItem(data, "port", 0U); + char *os = (char *)findItem(data, "os", CDEV_STRING, 1, unknown);; + char *osrelease = (char *)findItem(data, "osrelease", CDEV_STRING, 1, unknown);; + char *osversion = (char *)findItem(data, "osversion", CDEV_STRING, 1, unknown);; + char *machine = (char *)findItem(data, "machine", CDEV_STRING, 1, unknown);; + char *shell = (char *)findItem(data, "shell", CDEV_STRING, 1, unknown);; + char *program = (char *)findItem(data, "program", CDEV_STRING, 1, unknown);; + char *commandline = (char *)findItem(data, "commandline", CDEV_STRING, 1, unknown);; + time_t starttime = *(unsigned *)getItem(data, "starttime", (unsigned)time(NULL)); + float pctcpu = *(float *)getItem(data, "pctcpu", (float)0.0); + unsigned datasize = *(unsigned *)getItem(data, "datasize", 0U); + unsigned sendPktCnt = *(unsigned *)getItem(data, "sendPktCnt", 0U); + unsigned recvPktCnt = *(unsigned *)getItem(data, "recvPktCnt", 0U); + char startTimeStr[255]; + char userStr[255]; + char groupStr[255]; + char osStr[255]; + + sprintf (startTimeStr, "%s", starttime?ctime(&starttime):"UNKNOWN"); + if(strchr(startTimeStr, '\n')!=NULL) *(strchr(startTimeStr, '\n'))=0; + sprintf (userStr, "%s (%i)", username, uid); + sprintf (groupStr, "%s (%i)", group, gid); + + if(!strcmp(os, "UNKNOWN")) strcpy(osStr, os); + else sprintf (osStr, "%s %s %s %s", os, machine, osrelease, osversion); + + fprintf(stdout, "-------------------------------------------------------------------------------\n"); + fprintf(stdout, "DOMAIN : %-35s SERVER : %-35s\n", domain, server); + fprintf(stdout, "HOST : %-35s PORT : %i\n", host, port); + fprintf(stdout, "OWNER : %-35s GROUP : %-35s\n", userStr, groupStr); + fprintf(stdout, "OS : %-35s START : %-35s\n", osStr, startTimeStr); + fprintf(stdout, "SHELL : %-35s PROGRAM : %s (%i)\n", shell, program, pid); + fprintf(stdout, "%% CPU : %-35.2f SIZE : %i\n", pctcpu*100.0, datasize); + fprintf(stdout, "PKT SENT: %-35i PKT RECV: %-35i\n", sendPktCnt, recvPktCnt); + fprintf(stdout, "COMMAND : %s\n", commandline); + fflush(stdout); + }; + + + +void ReportClientComplete ( cdevData & data ) + { + static char * ClientInfoTags[]= + { + "username", "group", "uid", "gid", "pid", "program", + "commandline", "starttime", "connecttime", "host", + "os", "osversion", "osrelease", "machine", "shell", + "socket", "sendPktCnt", "recvPktCnt", "\0", + }; + size_t i, j; + size_t nClients = 0; + + data.getElems(ClientInfoTags[0], &nClients); + + for(i=0; *ClientInfoTags[i]!=0; i++) + { + data.getElems(ClientInfoTags[i], &j); + if(j!=nClients) + { + fprintf(stdout, "ERROR : Inconsistent data in ClientInfo Structure\n"); + fflush(stdout); + return; + } + } + + if(nClients==0) return; + + unsigned * uid = (unsigned *)findItem(data, "uid", CDEV_UINT32, nClients, NULL); + unsigned * gid = (unsigned *)findItem(data, "gid", CDEV_UINT32, nClients, NULL); + unsigned * pid = (unsigned *)findItem(data, "pid", CDEV_UINT32, nClients, NULL); + unsigned * starttime = (unsigned *)findItem(data, "starttime", CDEV_UINT32, nClients, NULL); + unsigned * connecttime = (unsigned *)findItem(data, "connecttime", CDEV_UINT32, nClients, NULL); + unsigned * socket = (unsigned *)findItem(data, "socket", CDEV_UINT32, nClients, NULL); + unsigned * sendPktCnt = (unsigned *)findItem(data, "sendPktCnt", CDEV_UINT32, nClients, NULL); + unsigned * recvPktCnt = (unsigned *)findItem(data, "recvPktCnt", CDEV_UINT32, nClients, NULL); + + char ** username = NULL; + char * usernamePtr = NULL; + char ** group = NULL; + char * groupPtr = NULL; + char ** program = NULL; + char * programPtr = NULL; + char ** commandline = NULL; + char * commandlinePtr = NULL; + char ** host = NULL; + char * hostPtr = NULL; + char ** os = NULL; + char * osPtr = NULL; + char ** osversion = NULL; + char * osversionPtr = NULL; + char ** osrelease = NULL; + char * osreleasePtr = NULL; + char ** machine = NULL; + char * machinePtr = NULL; + char ** shell = NULL; + char * shellPtr = NULL; + + if(nClients>1) + { + username = (char **) findItem(data, "username", CDEV_STRING, nClients, NULL); + group = (char **) findItem(data, "group", CDEV_STRING, nClients, NULL); + program = (char **) findItem(data, "program", CDEV_STRING, nClients, NULL); + commandline = (char **) findItem(data, "commandline", CDEV_STRING, nClients, NULL); + host = (char **) findItem(data, "host", CDEV_STRING, nClients, NULL); + os = (char **) findItem(data, "os", CDEV_STRING, nClients, NULL); + osversion = (char **) findItem(data, "osversion", CDEV_STRING, nClients, NULL); + osrelease = (char **) findItem(data, "osrelease", CDEV_STRING, nClients, NULL); + machine = (char **) findItem(data, "machine", CDEV_STRING, nClients, NULL); + shell = (char **) findItem(data, "shell", CDEV_STRING, nClients, NULL); + } + else { + username = &(usernamePtr = (char *)findItem(data, "username", CDEV_STRING, nClients, NULL)); + group = &(groupPtr = (char *)findItem(data, "group", CDEV_STRING, nClients, NULL)); + program = &(programPtr = (char *)findItem(data, "program", CDEV_STRING, nClients, NULL)); + commandline = &(commandlinePtr = (char *)findItem(data, "commandline", CDEV_STRING, nClients, NULL)); + host = &(hostPtr = (char *)findItem(data, "host", CDEV_STRING, nClients, NULL)); + os = &(osPtr = (char *)findItem(data, "os", CDEV_STRING, nClients, NULL)); + osversion = &(osversionPtr = (char *)findItem(data, "osversion", CDEV_STRING, nClients, NULL)); + osrelease = &(osreleasePtr = (char *)findItem(data, "osrelease", CDEV_STRING, nClients, NULL)); + machine = &(machinePtr = (char *)findItem(data, "machine", CDEV_STRING, nClients, NULL)); + shell = &(shellPtr = (char *)findItem(data, "shell", CDEV_STRING, nClients, NULL)); + } + + if(username==NULL || group==NULL || uid==NULL || gid==NULL || pid==NULL || program==NULL || + commandline==NULL || starttime==NULL || connecttime==NULL || host==NULL || os==NULL || + osversion==NULL || osrelease==NULL || machine==NULL || shell==NULL || socket==NULL || + sendPktCnt==NULL || recvPktCnt==NULL) + { + fprintf(stdout, "ERROR : Inconsistent data in ClientInfo Structure\n"); + fflush(stdout); + return; + } + + fprintf(stdout, "CLIENTS : %i Clients Attached\n", nClients); + + for(i=0; i0 && actualItems<=maxItems) + { + data.find(actualTag, item); + } + return item; + } diff --git a/extensions/cdevGenericServer/NameServer/examples/Makefile b/extensions/cdevGenericServer/NameServer/examples/Makefile new file mode 100755 index 0000000..a2f343f --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/examples/Makefile @@ -0,0 +1,24 @@ +ARCH = OS +SHOBJ = YES + +include ../../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Resource Name Server Test" +CXXEXTRA = -D_CDEV_MANAGE_SERVERS +LIBS = -L$(CDEVLIB) -lrsvc $(CDEVLIBS) $(OSLIBS) +BINARIES = $(BASEBIN)/rsvc_cdev_server $(BASEBIN)/rsvc_cdev_client $(BASEBIN)/rsvc_shutdown $(BASEBIN)/queryDataTest + +targets: $(BINARIES) + +$(BASEBIN)/rsvc_cdev_server: $(OBJDIR)/rsvc_cdev_server.o + $(LINK.cc) $^ $(LIBS) -o $@ + +$(BASEBIN)/rsvc_cdev_client: $(OBJDIR)/rsvc_cdev_client.o + $(LINK.cc) $^ $(LIBS) -o $@ + +$(BASEBIN)/rsvc_shutdown: $(OBJDIR)/rsvc_shutdown.o + $(LINK.cc) $^ $(LIBS) -o $@ + +$(BASEBIN)/queryDataTest: $(OBJDIR)/queryDataTest.o + $(LINK.cc) $^ $(LIBS) -o $@ + diff --git a/extensions/cdevGenericServer/NameServer/examples/NMakefile.mak b/extensions/cdevGenericServer/NameServer/examples/NMakefile.mak new file mode 100644 index 0000000..6fc9dde --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/examples/NMakefile.mak @@ -0,0 +1,42 @@ +.SUFFIXES: .cc .obj + +APPNAME = Resource Name Server Test +ARCH = WINNT-4.0 +SHOBJ = YES + +BINARIES = $(BASEBIN)\rsvc_cdev_server.exe\ + $(BASEBIN)\rsvc_cdev_client.exe\ + $(BASEBIN)\rsvc_shutdown.exe\ + $(BASEBIN)\queryDataTest.exe + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +targets : $(BINARIES) + +$(BASEBIN)\rsvc_cdev_server.exe : .exec\$(TARGETDIR)\rsvc_cdev_server.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\rsvc.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\rsvc_cdev_client.exe : .exec\$(TARGETDIR)\rsvc_cdev_client.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\rsvc.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\rsvc_shutdown.exe : .exec\$(TARGETDIR)\rsvc_shutdown.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\rsvc.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\queryDataTest.exe : .exec\$(TARGETDIR)\queryDataTest.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\rsvc.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... diff --git a/extensions/cdevGenericServer/NameServer/examples/queryDataTest.cc b/extensions/cdevGenericServer/NameServer/examples/queryDataTest.cc new file mode 100755 index 0000000..c14f181 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/examples/queryDataTest.cc @@ -0,0 +1,44 @@ +#include "../cdev/rnsQueryCollector.h" + +void populate1 ( rnsQueryCollector & collector ) + { + cdevData data; + static int index = 0; + + cdev_TS_STAMP ts; + ts.nsec = index; + ts.secPastEpoch = index; + + char str[50]; + sprintf(str, "I am the value - %i", index); + + if(index%10==0) {} + else if(index%1==0) data.insert("value", str); + else data.insert("value", index); + + data.insert("status", (short) -index); + data.insert("severity", (unsigned short) index); + if(index%1==0) data.insert("controlLow", (double)((double)index)+0.5); + if(index%2==0) data.insert("controlHigh", (float)(((float)index)+0.25)); + if(index%3==0) data.insert("displayLow", (long)-(index+10000)); + if(index%4==0) data.insert("displayHigh", (unsigned long)index+10000); + data.insert("time", ts); + data.insert("alarmHigh", (unsigned char *)str, 50); + if((index+1)%200==0) data.insert("alarmLow", (unsigned char)index); + collector.collect(data); + + index++; + } + + +int main() +{ +cdevData data; +char flat[50]; +memset(flat, 0, sizeof(char)); +rnsQueryCollector collector(data); +data.insert("controlLow", (unsigned char *)flat, 50); +for(int i=0; i<200; i++) populate1(collector); +data.asciiDump(); +} + diff --git a/extensions/cdevGenericServer/NameServer/examples/rsvc_cdev_client.cc b/extensions/cdevGenericServer/NameServer/examples/rsvc_cdev_client.cc new file mode 100755 index 0000000..e7c67dd --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/examples/rsvc_cdev_client.cc @@ -0,0 +1,87 @@ +// simple example program for cdev client to monitor cdev servers + +#include +#include +#include +#include + +static void getServerCallback (int status, void* /* arg */, rsvcData* data) +{ + if (status == RSVC_SUCCESS) { + printf ("Get server success\n"); + data->asciiDump (); + } + else + printf ("cannot get server info\n"); +} + +static void qcallback (int status, void* /* arg */, rsvcData* data) +{ + printf ("---------------------Query callback is called\n"); + if (status == RSVC_INCOMPLETE) { + printf ("Single data entry is here\n"); + data->asciiDump (); + } + else if (status == RSVC_SUCCESS) { + printf ("Query finished\n"); + data->asciiDump (); + } + else + printf ("Query error\n"); + printf ("---------------------Query finished\n"); +} + +static void monitorServerCallback (int status, void* /* arg */, rsvcData* data) +{ + if (status == RSVC_SUCCESS) { + printf (">>>>>>>>>>monitor server callback called<<<<<<<<<<<<<<<<\n"); + data->asciiDump (); + printf ("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); + } + else if (status == RSVC_CBK_FINISHED) { + printf ("server has been deleted\n"); + } + else + printf ("server monitor callback has status %d\n", status); +} + +int main (int argc, char** argv) +{ + if (argc < 4) { + fprintf (stderr, "Usage: %s servername domain rsvcserverhost rsvcserverport\n"); + exit (1); + } + + rsvcClient client; + if (client.connect (argv[3], atoi (argv[4])) != RSVC_SUCCESS) { + fprintf (stderr, "cannot connect to rsvc server\n"); + exit (1); + } + + rsvcData serverinfo; + serverinfo.insert ("name", argv[1]); + serverinfo.insert ("domain", argv[2]); + if (client.getValue ("cdevServers", serverinfo, + getServerCallback, 0) != RSVC_SUCCESS) { + fprintf (stderr, "cannot get server %s %s information\n", + argv[1], argv[2]); + exit (1); + } + + if (client.query ("cdevServers", "all", + qcallback, 0) != RSVC_SUCCESS) { + fprintf (stderr, "cannot do query callback\n"); + exit (1); + } + + if (client.monitorValue ("cdevServers", serverinfo, + monitorServerCallback, 0) != RSVC_SUCCESS) { + fprintf (stderr, "cannot do monitor on server %s %s\n", + argv[1], argv[2]); + exit (1); + } + + while (1) { + client.pendIO (5.0); + } +} diff --git a/extensions/cdevGenericServer/NameServer/examples/rsvc_cdev_server.cc b/extensions/cdevGenericServer/NameServer/examples/rsvc_cdev_server.cc new file mode 100755 index 0000000..4bf5ccf --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/examples/rsvc_cdev_server.cc @@ -0,0 +1,74 @@ +// simple program to demonstrate how a cdev server uses rsvc library +#include +#include +#include +#include +#include + +static void rsvcCallback (int status, void* /* arg */, rsvcData* /* data */) +{ + if (status == RSVC_SUCCESS) { + printf ("register server success\n"); + } + else + printf ("register server failed\n"); +} + + +int main (int argc, char** argv) +{ + rsvcData serverinfo; + rsvcData udpinfo; + + if (argc < 4) { + fprintf (stderr, "Usage: %s name domain serverhost serverport\n", argv[0]); + exit (1); + } + char hostname[256]; + gethostname (hostname, sizeof (hostname)); + struct timeval tv; + gettimeofday (&tv, 0); + + serverinfo.insert ("name", argv[1]); + serverinfo.insert ("domain", argv[2]); + serverinfo.insert ("host", hostname); + serverinfo.insert ("owner", "chen"); + serverinfo.insert ("time", (long)tv.tv_sec); + serverinfo.insert ("port", (long)tv.tv_sec%10000); + serverinfo.insert ("pid", getpid ()); + + udpinfo.insert ("name", argv[1]); + udpinfo.insert ("domain", argv[2]); + + rsvcClient client; + rsvcUdpClient udpclient; + + if (client.connect (argv[3], atoi (argv[4]), 2.0) != RSVC_SUCCESS) { + fprintf (stderr, "Cannot connect to rsvc server\n"); + exit (1); + } + + if (udpclient.connect (argv[3], atoi (argv[4]) + 1024) != RSVC_SUCCESS) { + fprintf (stderr, "Cannot connect to udp port\n"); + exit (1); + } + + // register server information + if (client.insertValue ("cdevServers", serverinfo, rsvcCallback, 0, 1) != + RSVC_SUCCESS) { + fprintf (stderr, "Cannot send server information to rsvc\n"); + client.disconnect (); + udpclient.disconnect (); + exit (1); + } + + int st = 0; + while (1) { + if ((st = client.pendIO (5.0)) != RSVC_SUCCESS && st != RSVC_TIMEOUT) + break; + if (udpclient.update (udpinfo) != RSVC_SUCCESS) + printf ("udp update failed\n"); + } +} + + diff --git a/extensions/cdevGenericServer/NameServer/examples/rsvc_shutdown.cc b/extensions/cdevGenericServer/NameServer/examples/rsvc_shutdown.cc new file mode 100755 index 0000000..ffd84a2 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/examples/rsvc_shutdown.cc @@ -0,0 +1,21 @@ +// Simple program to shutdown the rsvcServer +#include +#include +#include +#include + +int main (int argc, char** argv) +{ + if (argc < 3) { + fprintf (stderr, "Usage: %s host port\n", argv[0]); + exit (1); + } + + rsvcClient client; + if (client.connect (argv[1], atoi (argv[2])) != RSVC_SUCCESS) { + fprintf (stderr, "Cannot connect to rsvcServer\n"); + exit (1); + } + + client.shutdownServer (); +} diff --git a/extensions/cdevGenericServer/NameServer/java/Makefile b/extensions/cdevGenericServer/NameServer/java/Makefile new file mode 100644 index 0000000..cf3b483 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/Makefile @@ -0,0 +1,31 @@ +# Makefile for RSVC JAVA Package +.SUFFIXES: .class .java + +JAVAC = javac +JAVACFLAGS = -O + +CLASSOBJS = rsvcException.class \ + rsvcDataTypes.class \ + rsvcTimeStamp.class \ + rsvcDataEntry.class \ + rsvcData.class \ + rsvcDataOutputStream.class \ + rsvcDataInputStream.class \ + rsvcConfig.class \ + rsvcEvent.class \ + rsvcEventHandler.class \ + rsvcClient.class \ + rsvcClientReader.class \ + rsvcUdpClient.class \ + rsvcDisplay.class \ + rsvcClientTest.class \ + rsvcServerTest.class + +all: $(CLASSOBJS) + +.java.class: + rm -f $@ + $(JAVAC) $(JAVACFLAGS) $< + +clean: + rm -f *~ core *.class diff --git a/extensions/cdevGenericServer/NameServer/java/header.java b/extensions/cdevGenericServer/NameServer/java/header.java new file mode 100644 index 0000000..e47259d --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/header.java @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: header.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.1 1999/10/18 17:12:39 chen +// *** empty log message *** +// +// Revision 1.1.1.1 1999/09/07 15:29:10 chen +// CMLOG version 2.0 +// +// +// + + diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcClient.java b/extensions/cdevGenericServer/NameServer/java/rsvcClient.java new file mode 100644 index 0000000..d854a28 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcClient.java @@ -0,0 +1,639 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// Core part of rsvcClient Java Package +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcClient.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.1 1999/10/18 17:12:39 chen +// *** empty log message *** +// +// +// +import rsvcData; +import rsvcEvent; +import rsvcConfig; +import rsvcEventHandler; +import rsvcClientReader; +import java.io.*; +import java.net.*; +import java.util.*; + +public final class rsvcClient +{ + // connection flag + private boolean connected_ = false; + + // Socket to the server + private Socket tcpsocket_ = null; + + // server information + private String server_host_ = null; + private int server_port_ = 0; + + // internal request id + private int eventid_ = 1234; + + // internal client data reader + private rsvcClientReader reader_ = null; + + // internal thread id for reader + private Thread readerthread_ = null; + + + // output stream + private OutputStream output_ = null; + + + /** + * Construct an empty rsvcClient object + */ + public rsvcClient () + { + // empty + } + + /** + * Override default finalize method.This allows Java virtual + * machine to clean up resource when this object is no longer + * needed. + */ + protected void finalize() throws Throwable + { + if (tcpsocket_ != null && connected_ == true) { + connected_ = false; + tcpsocket_.close (); + } + } + + /** + * Connect to a server that is on a given host at a given port + */ + public synchronized void connect (String host, int port) throws UnknownHostException, IOException + { + try { + tcpsocket_ = new Socket (host, port); + }catch (UnknownHostException ue){ + System.err.println (ue); + throw ue; + }catch (IOException e) { + System.err.println(e); + throw e; + } + + // set connection flag + connected_ = true; + + // cache server information + server_host_ = new String(host); + server_port_ = port; + + + OutputStream toutput = null; + try { + toutput = tcpsocket_.getOutputStream(); + }catch (IOException e) { + System.err.println (e); + throw e; + } + + output_ = toutput; + + // create a single rsvcClient Data Reader and spawn a new thread + reader_ = new rsvcClientReader (this); + + readerthread_ = new Thread (reader_); + readerthread_.start (); + } + + /** + * Return underlying socket + */ + public Socket getSocket () throws NullPointerException + { + if (tcpsocket_ == null) + throw new NullPointerException ("Socket is invalid"); + + return tcpsocket_; + } + + /** + * Return underlying reader thread + */ + public Thread getReaderThread () throws NullPointerException + { + if (readerthread_ == null) + throw new NullPointerException ("Reader Thread is not alive"); + return readerthread_; + } + + /** + * Disconnect from the server + */ + public synchronized void disconnect () throws IOException + { + if (tcpsocket_ == null || connected_ == false) + throw new IOException ("Socket is not connected to the server"); + + try { + tcpsocket_.close(); + }catch (IOException e) { + throw e; + } + connected_ = false; + + // remove all event handlers + reader_.cleanupEventHandlers (); + } + + /** + * Is connection established + */ + public boolean connected () + { + return connected_; + } + + /** + * Register an event handler to handle disconnection event + */ + public synchronized boolean addDisconnectHandler (rsvcEventHandler handler) + { + return reader_.addDisconnectHandler (handler); + } + + /** + * Handle server unexpected close + */ + public int handleClose () + { + try { + tcpsocket_.close (); + } catch (IOException e) { + System.err.println (e); + connected_ = false; + return -1; + } + connected_ = false; + + reader_.dispatchDiscEventHandlers (); + + // clean up all callbacks + reader_.cleanupEventHandlers (); + + return 0; + } + + + /** + * Create a memory based database with an event handler. + * Data coming back to the event handler contain table definition + */ + public rsvcEvent createMemDbase (String tablename, rsvcData data, + rsvcEventHandler handler) throws IOException + { + rsvcEvent id = null; + + data.insert (rsvcConfig.RSVC_TABLE_NAME, tablename); + try { + id = sendCommand (rsvcConfig.RSVC_CREATE_MEMTABLE, data, + handler); + }catch (IOException e) { + throw e; + } + + return id; + } + + /** + * Open a database with a given name using an event handler. + * Data retured to the event handler contain definition of database + */ + public rsvcEvent openDatabase (String name, rsvcData data, + rsvcEventHandler handler) throws IOException + { + rsvcEvent id = null; + + data.insert (rsvcConfig.RSVC_TABLE_NAME, name); + try { + id = sendCommand (rsvcConfig.RSVC_OPEN_DBASE, data, + handler); + }catch (IOException e) { + throw e; + } + + return id; + } + + /** + * Insert data into a database with a given name. + * The last argument 'overwrite = 1' selects whether to overwite + * existing items in the database. + * Data must match table definition returned from the openDatabase call. + */ + public rsvcEvent insertValue (String name, rsvcData data, + rsvcEventHandler handler, + boolean overwrite) throws IOException + { + rsvcEvent id = null; + + data.insert (rsvcConfig.RSVC_TABLE_NAME, name); + if (overwrite == true) { + try { + id = sendCommand (rsvcConfig.RSVC_OVERWRITE, data, + handler); + }catch (IOException e) { + throw e; + } + } + else { + try { + id = sendCommand (rsvcConfig.RSVC_INSERT, data, + handler); + }catch (IOException e) { + throw e; + } + } + + return id; + } + + /** + * Get data out from the database with a given name. + * Outbound data either contain a tagged value to denote a key value + * such as : "id", "model+gold" or contain multiple tagged values that + * can be constructed into a key value + */ + public rsvcEvent getValue (String name, rsvcData data, + rsvcEventHandler handler) throws IOException + { + rsvcEvent id = null; + + data.insert (rsvcConfig.RSVC_TABLE_NAME, name); + try { + id = sendCommand (rsvcConfig.RSVC_GET, data, + handler); + }catch (IOException e) { + throw e; + } + + return id; + } + + /** + * Delete a data item from the database with a given name. + * Outbound data either contain a tagged value to denote a key value + * such as : "id", "model+gold" or contain multiple tagged values that + * can be constructed into a key value + */ + public rsvcEvent delValue (String name, rsvcData data, + rsvcEventHandler handler) throws IOException + { + rsvcEvent id = null; + + data.insert (rsvcConfig.RSVC_TABLE_NAME, name); + try { + id = sendCommand (rsvcConfig.RSVC_DEL, data, + handler); + }catch (IOException e) { + throw e; + } + + return id; + } + + /** + * Set value for a datum inside database with a given name. + * The outbound data item either contain a tagged value to denote + * a index value e.g.: "id", "model+gold" + * or contains multiple tagged values which can be constructed + * into a key value + * plus a subset of tagged values defined in the table definition + */ + public rsvcEvent setValue (String name, rsvcData data, + rsvcEventHandler handler) throws IOException + { + rsvcEvent id = null; + + data.insert (rsvcConfig.RSVC_TABLE_NAME, name); + try { + id = sendCommand (rsvcConfig.RSVC_SET, data, + handler); + }catch (IOException e) { + throw e; + } + + return id; + } + + /** + * Monitor on a data item inside a database with a given name. + * Any changes to this item will trigger an event coming back. + * The outbound data either contain a tagged value to denote a index value + * Example: "id", "model+gold" + * or contains multiple tagged values which can be constructed + * into a key value. + */ + public rsvcEvent monitorValue (String name, rsvcData data, + rsvcEventHandler handler) throws IOException + { + rsvcEvent id = null; + + data.insert (rsvcConfig.RSVC_TABLE_NAME, name); + try { + id = sendMonitor (rsvcConfig.RSVC_MONITOR_ON, data, + handler); + } catch (IOException e) { + throw e; + } + return id; + } + + /** + * Monitor off a data inside a database with a given name + * Outbound data either contain a tagged value to denote a index value + * Example: "id", "model+gold" + * or contains multiple tagged values which can be constructed + * into a key value. + */ + public rsvcEvent monitorOffValue (String name, rsvcData data, + rsvcEvent mid) throws IOException + { + rsvcEvent id = null; + + data.insert (rsvcConfig.RSVC_TABLE_NAME, name); + try { + id = sendMonitorOff (rsvcConfig.RSVC_MONITOR_OFF, data, mid); + } catch (IOException e) { + throw e; + } + + return id; + } + + /** + * monitor a single attribute of a data inside a database with a given name. + * any changes to this attribute will trigger an event. + * Data coming back to the event handler containing a whole data. + * Outbound data either contain a tagged value to denote a index value + * Example: "id", "model+gold" + * or contains multiple tagged values which can be constructed + * into a key value + */ + public rsvcEvent monitorAttr (String name, String attr, rsvcData data, + rsvcEventHandler handler) throws IOException + { + rsvcEvent id = null; + + data.insert (rsvcConfig.RSVC_TABLE_NAME, name); + data.insert (rsvcConfig.RSVC_MONITOR_TAG, attr); + + try { + id = sendMonitor (rsvcConfig.RSVC_MONITOR_ONATTR, data, + handler); + } catch (IOException e) { + throw e; + } + return id; + } + + /** + * Stop monitoring a single attribute of a data inside a database. + * Outbound data either contain a tagged value to denote a index value + * Example: "id", "model+gold" + * or contains multiple tagged values which can be constructed + * into a key value . + */ + public rsvcEvent monitorOffAttr (String name, String attr, rsvcData data, + rsvcEvent mid) throws IOException + { + rsvcEvent id = null; + + data.insert (rsvcConfig.RSVC_TABLE_NAME, name); + data.insert (rsvcConfig.RSVC_MONITOR_TAG, attr); + + try { + id = sendMonitorOff (rsvcConfig.RSVC_MONITOR_OFFATTR, data, + mid); + } catch (IOException e) { + throw e; + } + return id; + } + + /** + * query a particular database 'name' + * query msg can be like regular C logic expression for all + * attributes. + */ + public rsvcEvent query (String name, String qmsg, + rsvcEventHandler handler) throws IOException + { + rsvcEvent id = null; + + rsvcData data = new rsvcData (); + + data.insert (rsvcConfig.RSVC_TABLE_NAME, name); + + data.insert (rsvcConfig.RSVC_QUERY_TAG, qmsg); + + try { + id = sendCommand (rsvcConfig.RSVC_QUERY, data, + handler); + }catch (IOException e) { + throw e; + } + return id; + } + + /** + * Monitor incoming entries inside database + * any insertion to a database will trigger an event + */ + public rsvcEvent monitorIncomingEntries (String name, rsvcData data, + rsvcEventHandler handler) throws IOException + { + rsvcEvent id = null; + + data.insert (rsvcConfig.RSVC_TABLE_NAME, name); + try { + id = sendMonitor (rsvcConfig.RSVC_MONITOR_ENTRIES, data, + handler); + } catch (IOException e) { + throw e; + } + + return id; + } + + /** + * Stop monitoring the incoming entries inside database. + */ + public rsvcEvent monitorOffIncomingEntries (String name, rsvcData data, + rsvcEvent mid) throws IOException + { + rsvcEvent id = null; + + data.insert (rsvcConfig.RSVC_TABLE_NAME, name); + try { + id = sendMonitorOff(rsvcConfig.RSVC_MONITOR_OFFENTRIES, data, + mid); + }catch (IOException e) { + throw e; + } + + return id; + } + + + /** + * Generic monitor on command + */ + private synchronized rsvcEvent sendMonitor (int opcode, rsvcData data, + rsvcEventHandler handler) throws IOException + { + int status = rsvcConfig.RSVC_SUCCESS; + + // create an event that is being shipped to server + rsvcEvent cbk = new rsvcEvent (data); + cbk.setEventid (eventid_); + cbk.setOpcode (opcode); + + + // write this event to server + int len = cbk.streamSize (); + // create a buffered data output + BufferedOutputStream boutput = new BufferedOutputStream (output_, len); + try { + cbk.streamOut (boutput); + }catch (IOException e) { + System.err.println (e); + status = rsvcConfig.RSVC_IOFAILED; + throw e; + } + + if (status == rsvcConfig.RSVC_SUCCESS) { + try { + boutput.flush (); + }catch (IOException e) { + System.err.println (e); + status = rsvcConfig.RSVC_IOFAILED; + throw e; + } + } + + if (status == rsvcConfig.RSVC_SUCCESS) { + cbk.setHandler (handler); + reader_.addMonitorEventHandler (eventid_, cbk); + } + + eventid_ ++; + return cbk; + } + + + /** + * Generic monitor on command + */ + private synchronized rsvcEvent sendMonitorOff (int opcode, rsvcData data, + rsvcEvent monitorEvent) throws IOException + { + int status = rsvcConfig.RSVC_SUCCESS; + + if (reader_.containsMonitorEvent (monitorEvent) != true) { + throw new IOException ("Monitor Off using an invalid event"); + } + + // create new event with differen opcode + rsvcEvent cbk = new rsvcEvent (monitorEvent); + cbk.setOpcode (opcode); + + // write this event to server + int len = cbk.streamSize (); + // create a buffered data output + BufferedOutputStream boutput = new BufferedOutputStream (output_, len); + try { + cbk.streamOut (boutput); + }catch (IOException e) { + System.err.println (e); + status = rsvcConfig.RSVC_IOFAILED; + throw e; + } + + if (status == rsvcConfig.RSVC_SUCCESS) { + try { + boutput.flush (); + }catch (IOException e) { + System.err.println (e); + status = rsvcConfig.RSVC_IOFAILED; + throw e; + } + } + + return cbk; + } + + + /** + * Generic command call with ith an event handler. + * Data coming back to the event handler contain table definition + */ + private synchronized rsvcEvent sendCommand (int opcode, rsvcData data, + rsvcEventHandler handler) throws IOException + { + int status = rsvcConfig.RSVC_SUCCESS; + + // create an event that is being shipped to server + rsvcEvent cbk = new rsvcEvent (data); + cbk.setEventid (eventid_); + cbk.setOpcode (opcode); + + + // write this event to server + int len = cbk.streamSize (); + // create a buffered data output + BufferedOutputStream boutput = new BufferedOutputStream (output_, len); + try { + cbk.streamOut (boutput); + }catch (IOException e) { + System.err.println (e); + status = rsvcConfig.RSVC_IOFAILED; + throw e; + } + + if (status == rsvcConfig.RSVC_SUCCESS) { + try { + boutput.flush (); + }catch (IOException e) { + System.err.println (e); + status = rsvcConfig.RSVC_IOFAILED; + throw e; + } + } + + if (status == rsvcConfig.RSVC_SUCCESS) { + cbk.setHandler (handler); + reader_.addCommandEventHandler (eventid_, cbk); + } + + eventid_ ++; + return cbk; + } + + +} diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcClientReader.java b/extensions/cdevGenericServer/NameServer/java/rsvcClientReader.java new file mode 100644 index 0000000..8651b6b --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcClientReader.java @@ -0,0 +1,315 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// rsvcClient Reader that is reading data out of socket +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcClientReader.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.2 1999/12/14 15:38:15 chen +// Add scrollbar to display +// +// Revision 1.1 1999/10/18 17:12:39 chen +// *** empty log message *** +// +// +// +// +import java.io.*; +import java.net.*; +import java.util.*; +import rsvcData; +import rsvcEvent; +import rsvcEventHandler; +import rsvcClient; + +public final class rsvcClientReader implements Runnable +{ + // disconnection callback list (list of event handler) + private Vector discCbkList_ = null; + + // all send/get command callback list + private Hashtable cmdCbkList_ = null; + + // monitor callback list + private Hashtable monitorCbkTable_ = null; + + // Input and output buffer + private DataInputStream input_ = null; + + // Pointer back to rsvcClient + private rsvcClient client_; + + /** + * Construct a rsvcClientReader from a established client object + */ + public rsvcClientReader (rsvcClient client) + { + client_ = client; + + // create lists and a table for event handlers + discCbkList_ = new Vector (); + cmdCbkList_ = new Hashtable (20, (float)0.25); + monitorCbkTable_ = new Hashtable (20, (float)0.25); + + InputStream tinput = null; + Socket socket = null; + + try { + socket = client_.getSocket(); + }catch (NullPointerException e) { + System.err.print (e); + System.exit (-1); + } + + try { + tinput = socket.getInputStream(); + }catch (IOException e) { + System.err.print (e); + System.exit (-1); + } + input_ = new DataInputStream (tinput); + } + + /** + * Add an event handler to handle disconnection event. + * Return true if this event handler is registered successfully. + * Return false if this event handler is already here. + */ + public boolean addDisconnectHandler (rsvcEventHandler handler) + { + if (discCbkList_.contains (handler) == true) + return false; + discCbkList_.addElement (handler); + return true; + } + + /** + * Clean up all event handlers + */ + public void cleanupEventHandlers () + { + discCbkList_.removeAllElements (); + cmdCbkList_.clear (); + monitorCbkTable_.clear (); + } + + /** + * Add an event handler to command event handler list + */ + public void addCommandEventHandler (int id, + rsvcEvent oevent) + { + // vector is thread safe + cmdCbkList_.put (new Integer(id), oevent); + } + + /** + * Add an event handler to monitor event handler table + */ + public void addMonitorEventHandler (int id, rsvcEvent oevent) + { + // vector is thread safe + monitorCbkTable_.put (new Integer(id), oevent); + } + + /** + * Find out whether a particular event is already in the + * monitor event handler table + */ + public boolean containsMonitorEvent (rsvcEvent event) + { + Integer key = new Integer (event.getEventid ()); + return monitorCbkTable_.containsKey (key); + } + + /** + * Dispatch all event handlers when the server goes down + */ + public void dispatchDiscEventHandlers () + { + Enumeration list = discCbkList_.elements (); + rsvcEventHandler handler = null; + + rsvcEvent event = new rsvcEvent (); + event.setStatus (rsvcConfig.RSVC_DISCONNECTED); + + while (list.hasMoreElements ()) { + handler = (rsvcEventHandler)(list.nextElement()); + handler.handleEvent (event); + } + } + + public void run () + { + // buffer for header + int headerlen = rsvcEvent.headerLen (); + byte[] header = new byte[headerlen]; + ByteArrayInputStream bainput = new ByteArrayInputStream (header); + + // buffer for payload + int datasize = 4096; + int prevsize = 4096; + byte[] payload = new byte[datasize]; + ByteArrayInputStream plinput = new ByteArrayInputStream (payload); + + // event data object + rsvcEvent event = new rsvcEvent (); + + while (true) { + // read header + try { + input_.readFully (header); + }catch (IOException e) { + System.err.println ("Server is down"); + client_.handleClose (); + break; + } + + // reset input stream buffer + bainput.reset (); + try { + datasize = rsvcEvent.readHeader (bainput); + }catch (IOException e) { + System.err.println ("Receiving header error" + e); + client_.handleClose (); + break; + } + + + if (datasize > prevsize) { + datasize = 2*datasize; + prevsize = datasize; + payload = new byte[datasize]; + plinput = new ByteArrayInputStream (payload); + } + + // read raw bytes of length 'datasize' + try { + input_.readFully (payload, 0, datasize); + }catch (IOException e) { + System.err.println ("Server is down here"); + client_.handleClose (); + break; + } + + // convert above raw bytes into an event + plinput.reset (); + try { + event.streamIn (plinput); + }catch (IOException e) { + System.err.println ("Payload data format error: " + e); + client_.handleClose (); + break; + } + + // dispatch this event to an appropriate destination + if (dispatchEvent (event) != 0) { + client_.handleClose (); + break; + } + } + System.out.println ("rsvcClientReader Thread is finished"); + + } + + private int dispatchEvent (rsvcEvent event) + { + int op = event.getOpcode (); + int status = 0; + + if (op < rsvcConfig.RSVC_MONITOR_ON) + // all simple command transaction events + status = dispatchCmdEventFromServer (event); + else if (op < rsvcConfig.RSVC_OP_UNKNOWN) + // all monitor events + status = dispatchMonitorEventFromServer (event); + else { + System.err.println ("rsvcClient: Invalid option code: " + String.valueOf(op)); + status = -1; + } + return status; + } + + private int dispatchCmdEventFromServer (rsvcEvent event) + { + Integer key = new Integer (event.getEventid()); + int status = event.getStatus (); + Object obj = null; + rsvcEventHandler handler = null; + rsvcEvent oevent = null; + + // retrieve object from event which has key value + obj = cmdCbkList_.get (key); + + if (obj != null) { + oevent = (rsvcEvent)obj; + + if (oevent.match (event) == false) { + System.err.println ("Incoming and outgoing events are not match"); + return -1; + } + + try { + handler = oevent.getHandler (); + } catch (NullPointerException e) { + System.err.println (e); + return -1; + } + handler.handleEvent (event); + + if (status != rsvcConfig.RSVC_INCOMPLETE) + cmdCbkList_.remove (event); + } + else { + System.out.println ("rsvcClient: Event from server does not match"); + } + return 0; + } + + private int dispatchMonitorEventFromServer (rsvcEvent event) + { + Integer key = new Integer (event.getEventid ()); + int status = event.getStatus(); + Object obj = null; + rsvcEventHandler handler = null; + rsvcEvent oevent = null; + + obj = monitorCbkTable_.get (key); + if (obj != null) { + oevent = (rsvcEvent)obj; + try { + handler = oevent.getHandler (); + }catch (NullPointerException e) { + System.err.println (e); + return -1; + } + handler.handleEvent (event); + + if (status != rsvcConfig.RSVC_SUCCESS && + status != rsvcConfig.RSVC_INCOMPLETE) { + // if an event is bad or finished, remove it + monitorCbkTable_.remove (event); + } + } + else if (status != rsvcConfig.RSVC_SUCCESS) { + System.out.println ("rsvcClient: monitor event from server does not match any"); + System.out.println (event.toString()); + } + return 0; + } +} diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcClientTest.java b/extensions/cdevGenericServer/NameServer/java/rsvcClientTest.java new file mode 100644 index 0000000..a6d35a4 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcClientTest.java @@ -0,0 +1,110 @@ +import java.io.*; +import java.util.*; +import java.net.*; +import rsvcClient; +import rsvcEventHandler; +import rsvcConfig; + +public final class rsvcClientTest implements rsvcEventHandler +{ + public rsvcClientTest () + { + // empty + } + + public static void main (String[] args) + { + if (args.length < 4) { + System.err.println ("Usage: rsvcClientTest servername domain host port"); + System.exit (-1); + } + + rsvcClientTest test = new rsvcClientTest (); + + String host = args[2]; + int port = Integer.valueOf (args[3]).intValue(); + String server = args[0]; + String domain = args[1]; + + rsvcClient client = new rsvcClient (); + + try { + client.connect (host, port); + }catch (UnknownHostException ue) { + System.err.println (ue); + System.exit (-1); + }catch (IOException e) { + System.err.println (e); + System.exit (-1); + } + + // outbound event stream + rsvcEvent oevent = null; + + rsvcData serverinfo = new rsvcData (); + serverinfo.insert ("name", server); + serverinfo.insert ("domain", domain); + try { + oevent = client.getValue ("cdevServers", serverinfo, + test); + }catch (IOException e) { + System.err.println (e); + System.exit (-1); + } + + try { + oevent = client.query ("cdevServers", "all", + test); + }catch (IOException e) { + System.err.println (e); + System.exit (-1); + } + + try { + oevent = client.monitorValue ("cdevServers", serverinfo, + test); + }catch (IOException e) { + System.err.println (e); + System.exit (-1); + } + + Thread readerThread = client.getReaderThread (); + try { + readerThread.join (); + } catch (InterruptedException e) { + System.err.println (e); + System.exit (-1); + } + } + + public void handleEvent (rsvcEvent event) + { + int status = event.getStatus (); + int opcode = event.getOpcode (); + rsvcData data = event.getData (); + + System.out.println ("Handle event is called with status :" + String.valueOf (status)); + + switch (opcode) { + case rsvcConfig.RSVC_GET: + System.out.println ("Get Value with result :"); + break; + case rsvcConfig.RSVC_QUERY: + System.out.println ("Query Value with result :"); + break; + default: + System.out.println ("Operation : " + String.valueOf (opcode)); + } + + if (status == rsvcConfig.RSVC_NOTFOUND) + System.out.println ("Found nothing"); + + if (status == rsvcConfig.RSVC_SUCCESS) + data.asciiDump (); + } +} + + + + + diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcConfig.java b/extensions/cdevGenericServer/NameServer/java/rsvcConfig.java new file mode 100644 index 0000000..0ddbe86 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcConfig.java @@ -0,0 +1,169 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Client Configuration (Must be compatiable to C++ side) +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcConfig.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.1 1999/10/18 17:12:40 chen +// *** empty log message *** +// +// +// +public final class rsvcConfig +{ + public static final int RSVC_SERVER_PORT = 10932; + public static final int RSVC_MAX_KEY_LEN = 256; + public static final String RSVC_KEY_NAME = "key"; + public static final String RSVC_TABLE_NAME = "table"; + public static final String RSVC_TABLE_NAME_EXT = ".def"; + public static final String RSVC_KEY_TYPE_NAME = "keyType"; + public static final String RSVC_KEY_EXP_NAME = "keyExp"; + public static final String RSVC_MONITOR_TAG = "monitorOn"; + public static final String RSVC_QUERY_TAG = "query"; + public static final int RSVC_CACHE_MAX = 20; + public static final int RSVC_CACHE_LF = 5; + public static final int RSVC_RLIMIT_NOFILE = 256; + public static final int RSVC_UDP_BUFFER_SIZE = 4096; + + public static final int RSVC_OP_UNKNOWN = 2000; + + public static final int RSVC_CREATE_TABLE = 1000; + public static final int RSVC_CREATE_MEMTABLE = 1001; + public static final int RSVC_OPEN_DBASE = 1002; + public static final int RSVC_GET = 1010; + public static final int RSVC_SET = 1011; + public static final int RSVC_DEL = 1012; + public static final int RSVC_INSERT = 1013; + public static final int RSVC_OVERWRITE = 1014; + public static final int RSVC_QUERY = 1020; + + public static final int RSVC_MONITOR_ON = 1500; + public static final int RSVC_MONITOR_ONATTR = 1501; + public static final int RSVC_MONITOR_OFF = 1600; + public static final int RSVC_MONITOR_OFFATTR = 1601; + + public static final int RSVC_MONITOR_ENTRIES = 1650; + public static final int RSVC_MONITOR_OFFENTRIES = 1651; + + public static final int RSVC_SERVER_EXIT = 1700; + + public static final int RSVC_DATA_IN_MEMORY = 1; + public static final int RSVC_DATA_ON_DISK = 2; + + + // database name + public static final String _RSVC_CDEV_SERVERS = "cdevServers"; + // key name + public static final String _RSVC_CDEV_SERVERS_KEY = "svcid" ; + // if we do not see a server for 30 seconds, we assume it is dead + public static final int RSVC_CDEV_SERVER_TKO = 30; + // frequency of scanning server database + public static final int RSVC_CDEV_SCAN_PERIOD = 10; + + // the following are error status from server + /* Failure of function is non-consequential */ + public static final int RSVC_WARNING = -2; + /* Errors that are not in any categories */ + public static final int RSVC_ERROR = -1; + /* public static final int RSVC success */ + public static final int RSVC_SUCCESS = 0; + /* invalid public static final int RSVC objects */ + public static final int RSVC_INVALIDOBJ = 1; + /* invalid argument passed to public static final int RSVC calls */ + public static final int RSVC_INVALIDARG = 2; + /* wrong service during dynamic loading */ + public static final int RSVC_INVALIDSVC = 3; + /* operation is unsupported (collection) */ + public static final int RSVC_INVALIDOP = 4; + /* not connected to low network service */ + public static final int RSVC_NOTCONNECTED = 5; + /* low level network service IO failed */ + public static final int RSVC_IOFAILED = 6; + /* conflicts of data types or tags */ + public static final int RSVC_CONFLICT = 7; + /* public static final int RSVC cannot find user request */ + /* (public static final int RSVCData) */ + public static final int RSVC_NOTFOUND = 8; + /* time out */ + public static final int RSVC_TIMEOUT = 9; + /* public static final int RSVCData conversion error */ + public static final int RSVC_CONVERT = 10; + /* value out of range for device attribute */ + public static final int RSVC_OUTOFRANGE = 11; + /* insufficient access to perform request */ + public static final int RSVC_NOACCESS = 12; + /* change in access permission of device */ + public static final int RSVC_ACCESSCHANGED = 13; + /* channel has been disconnected */ + public static final int RSVC_DISCONNECTED = 60; + /* channel has been reconnected */ + public static final int RSVC_RECONNECTED = 61; + /* overflow existing data buffer */ + public static final int RSVC_OVERFLOW = 62; + /* the callback object will be deleted */ + public static final int RSVC_DELETE_CALLBACK = 70; + /* data has no key in the data */ + public static final int RSVC_NOKEY = 80; + /* connection timeout */ + public static final int RSVC_CONN_TIMEOUT = 82; + /* messages have been filtered */ + public static final int RSVC_FILTERED = 83; + /* no filtering applied */ + public static final int RSVC_NOFILTERING = 84; + /* message is dropped */ + public static final int RSVC_DROPPED = 85; + /* TCP io is bad file descriptor */ + public static final int RSVC_BADIO = 86; + /* data flow will coming (unfinished) */ + public static final int RSVC_INCOMPLETE = 88; + /* callback finished (monitor off) */ + public static final int RSVC_CBK_FINISHED = 89; + /* query callback is paused */ + public static final int RSVC_PAUSED = 90; + /* query message syntax error */ + public static final int RSVC_QUERYMSG_ERR = 91; + + /* Request object state values */ + /* request object is connected to device */ + public static final int RSVC_STATE_CONNECTED = 0; + /* request object is not connected */ + public static final int RSVC_STATE_NOTCONNECTED = 1; + /* request object is invalid */ + public static final int RSVC_STATE_INVALID = 2; + + /* Request object access values */ + /* no access to specified attribute */ + public static final int RSVC_ACCESS_NONE = 0; + /* read-only access to attribute */ + public static final int RSVC_ACCESS_READONLY = 1; + /* read-write access to attribute */ + public static final int RSVC_ACCESS_WRITE = 2; + + /* public static final int RSVCError class severity codes */ + /* informative message */ + public static final int RSVC_SEVERITY_INFO = 0; + /* warning message */ + public static final int RSVC_SEVERITY_WARN = 1; + /* error message */ + public static final int RSVC_SEVERITY_ERROR = 2; + /* severe or fatal error message */ + public static final int RSVC_SEVERITY_SEVERE = 3; + + public static final int RSVC_IOERROR = 6; +} diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcData.java b/extensions/cdevGenericServer/NameServer/java/rsvcData.java new file mode 100644 index 0000000..6951abd --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcData.java @@ -0,0 +1,1163 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// rsvc data object containing multiple dataEntry Object identified +// by a string tag +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcData.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.1 1999/10/18 17:12:40 chen +// *** empty log message *** +// +// +// +import java.io.OutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.util.Hashtable; +import java.util.Enumeration; +import java.lang.NumberFormatException; +import rsvcDataTypes; +import rsvcTimeStamp; +import rsvcDataEntry; +import rsvcException; +import rsvcDataOutputStream; + +public class rsvcData +{ + // magic number + public static final int _RSVC_MAGIC_NUM = 0x2c45da2a; + // this is a hash table holding all data entry objects + private Hashtable store_; + + // no need to put synchronized for memeber functions since + // the hashtable is thread safe + + /** + * Construct an empty rsvcData Object + */ + public rsvcData () + { + // create a hash table with initial capacity of 1 and load factor 0.25 + // to improve look up time for a data entry + store_ = new Hashtable (1, (float)0.25); + } + + /** + * Construct a rsvcData Object from an existing data object. + * This is a deep copy. + */ + public rsvcData (rsvcData data) + { + store_ = new Hashtable (1, (float)0.25); + + Object obj; + rsvcDataEntry temp; + Enumeration list = data.store_.elements(); + while (list.hasMoreElements()) { + obj = list.nextElement (); + temp = ((rsvcDataEntry)obj).copy(); + store_.put (temp.getTag(), temp); + } + } + + /** + * Return a duplicated data object: deep copy + */ + public rsvcData copy () + { + rsvcData data = new rsvcData (); + + Object obj; + rsvcDataEntry temp; + Enumeration list = store_.elements(); + while (list.hasMoreElements()) { + obj = list.nextElement (); + temp = ((rsvcDataEntry)obj).copy(); + data.store_.put (temp.getTag(), temp); + } + return data; + } + + /** + * Clean up this data object + */ + public void remove () + { + store_.clear (); + // no free individual elements :-( + } + + /** + * Remove a dataEntry with tag + */ + public int remove (String tag) + { + if (store_.remove (tag) != null) + return 0; + return -1; + } + + /** + * Insert a single byte with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, byte data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + /** + * Insert a short value with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, short data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + /** + * Insert an integer with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, int data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + + /** + * Insert a long value with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, long data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + /** + * Insert a float value with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, float data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + + /** + * Insert a double with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, double data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + /** + * Insert a timestamp with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, rsvcTimeStamp data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + /** + * Insert a String Value with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, String data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + /** + * Insert an array of byte with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, byte[] data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + /** + * Insert an array of short with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, short[] data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + /** + * Insert an array of integer with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, int[] data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + /** + * Insert an array of long with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, long[] data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + /** + * Insert an array of float with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, float[] data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + /** + * Insert an array of double with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, double[] data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + /** + * Insert an array of timestamp with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, rsvcTimeStamp[] data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + /** + * Insert an array of string with a tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (String tag, String[] data) + { + int status = remove (tag); + rsvcDataEntry entry = new rsvcDataEntry (tag, data); + store_.put (tag, entry); + return status; + } + + + /** + * Insert a data entry item with a given tag. If a data item with the same + * tag is already there, the previous data is removed and new + * data is inserted. + */ + public int insert (rsvcDataEntry data) + { + int status = remove (data.getTag()); + store_.put (data.getTag(), data); + return status; + } + + /** + * Get a data entry with a tag + */ + public rsvcDataEntry get (String tag) + { + Object obj = store_.get (tag); + if (obj != null) + return (rsvcDataEntry)obj; + return null; + } + + /** + * Find a data entry with a tag + */ + public rsvcDataEntry find (String tag) + { + Object obj = store_.get (tag); + if (obj != null) + return (rsvcDataEntry)obj; + return null; + } + + /** + * Find whether this data contains entry with a given tag + */ + public boolean contains (String tag) + { + return store_.containsKey (tag); + } + + /** + * Change a data entry tag from old to new. + * if old tag has no associated data entry, nothing is done + */ + public void changeTag (String oldtag, String newtag) + { + Object obj = store_.remove (oldtag); + if (obj != null) { + rsvcDataEntry data = (rsvcDataEntry)obj; + data.setTag (newtag); + store_.put (newtag, data); + } + } + + /** + * Copy a data entry with a oldtag to create a new entry with a newtag. + */ + public void dup (String oldtag, String newtag) throws rsvcException + { + if (store_.containsKey (oldtag) != true) + throw new rsvcException ("Dup: oldtag has no associated data"); + else if (store_.containsKey (newtag) == true) + throw new rsvcException ("Dup: newtag has associated data"); + else { + rsvcDataEntry entry = get (oldtag); + rsvcDataEntry newentry = entry.copy(); + newentry.setTag (newtag); + store_.put (newtag, newentry); + } + } + + /** + * Replace all data entries with entries inside the provided data object + */ + public void replace (rsvcData data) + { + Object obj; + rsvcDataEntry temp; + + Enumeration list = data.store_.elements(); + while (list.hasMoreElements ()) { + obj = list.nextElement (); + temp = (rsvcDataEntry)obj; + if (contains (temp.getTag())) + insert (temp); + } + } + + /** + * Compare two data objects. Return true if they equal to each other. + */ + public boolean equals (rsvcData data) + { + Object obj0; + rsvcDataEntry temp0; + + Object obj1; + rsvcDataEntry temp1; + + Enumeration list0 = data.store_.elements(); + Enumeration list1 = store_.elements(); + + int size0 = 0; + int size1 = 0; + while (list0.hasMoreElements ()) { + obj0 = list0.nextElement (); + size0 ++; + } + + while (list1.hasMoreElements ()) { + obj1 = list1.nextElement (); + size1 ++; + } + if (size0 != size1) + return false; + + list0 = data.store_.elements (); + while (list0.hasMoreElements ()) { + // for each element, find whether there is an element + // in this data + obj0 = list0.nextElement (); + temp0 = (rsvcDataEntry)obj0; + temp1 = get (temp0.getTag()); + + if (temp1 == null || temp0.equals (temp1) == false) + return false; + } + return true; + } + + /** + * Return number of data entries inside this object + */ + public int size () + { + return store_.size(); + } + + /** + * Return number of valid data entries inside this object + */ + public int numValidEntries () + { + int count = 0; + Object obj; + rsvcDataEntry temp; + + Enumeration list = store_.elements(); + while (list.hasMoreElements ()) { + obj = list.nextElement (); + temp = (rsvcDataEntry)obj; + if (temp.getType() != rsvcDataTypes.RSVC_INVALID) + count ++; + } + return count; + } + + /** + * Check whether this data is empty + */ + public boolean isEmpty () + { + return store_.isEmpty(); + } + + /** + * Return enumeration of elements + */ + public Enumeration elements() + { + return store_.elements (); + } + + /** + * Convert data object to a string representation + */ + public String toString (String title) + { + String result = new String (); + if (title != null) + result = title + "\n"; + + Object obj; + Enumeration list = store_.elements(); + while (list.hasMoreElements()) { + obj = list.nextElement (); + result += obj.toString (); + result += "\n"; + } + return result; + } + + /** + * Convert data object to a string representation + */ + public String toString () + { + return toString ("Contents: "); + } + + /** + * Output contents to standard out + */ + public void asciiDump () + { + System.out.print ("\nBeginning of display----------------------------\n"); + System.out.print (toString()); + System.out.print ("\nEnd of Display----------------------------------\n"); + } + + /** + * Calculate stream size of this object + */ + public int streamSize () + { + rsvcDataEntry tmp = null; + int datasize = 0; + int i; + + // magic number + datasize += rsvcDataOutputStream.streamSize (rsvcData._RSVC_MAGIC_NUM); + + // number of elements + datasize += rsvcDataOutputStream.streamSize (numValidEntries()); + + // add size for each valid item + Enumeration list = store_.elements(); + while (list.hasMoreElements()) { + tmp = (rsvcDataEntry)(list.nextElement()); + // individual data entry size + datasize += tmp.streamSize (); + } + return datasize; + } + + /** + * Stream rsvcData into a buffered data output stream + */ + public void streamOut (OutputStream output) throws IOException + { + rsvcDataEntry tmp; + + rsvcDataOutputStream writer = new rsvcDataOutputStream (output); + + try{ + writer.write (rsvcData._RSVC_MAGIC_NUM); + }catch (IOException e) { + throw e; + } + + try { + writer.write (numValidEntries ()); + }catch (IOException e){ + throw e; + } + + Enumeration list = store_.elements (); + while (list.hasMoreElements()) { + tmp = (rsvcDataEntry)(list.nextElement()); + try { + tmp.streamOut (writer); + }catch (IOException e) { + throw e; + } + } + } + + /** + * Stream rsvcData into a buffered data output stream + */ + public void streamOut (rsvcDataOutputStream writer) throws IOException + { + rsvcDataEntry tmp; + + try{ + writer.write (rsvcData._RSVC_MAGIC_NUM); + }catch (IOException e) { + throw e; + } + + try { + writer.write (numValidEntries ()); + }catch (IOException e){ + throw e; + } + + Enumeration list = store_.elements (); + while (list.hasMoreElements()) { + tmp = (rsvcDataEntry)(list.nextElement()); + try { + tmp.streamOut (writer); + }catch (IOException e) { + throw e; + } + } + } + + /** + * Take a input data stream and populate this data object + */ + public void streamIn (InputStream stream) throws IOException + { + int i, j; + // clean out this object first + remove (); + + // attach input stream + rsvcDataInputStream input = new rsvcDataInputStream (stream); + + // read magic number first + int magic; + try { + magic = input.readInt (); + }catch (IOException e){ + throw e; + } + + if (magic != rsvcData._RSVC_MAGIC_NUM) { + throw new IOException ("Magic number mismatch"); + } + + // read number of elements + int count; + try { + count = input.readInt (); + }catch (IOException e) { + throw e; + } + // read each data entry + for (i = 0; i < count; i++) { + short type; + short ndims; + int elems, nelems; + String tag = null; + rsvcDataEntry de = null; + + // read tag + try { + tag = input.readString (); + }catch (IOException e) { + throw e; + } + + // read type + try { + type = input.readShort (); + }catch (IOException e) { + throw e; + } + + // read dimension + try { + ndims = input.readShort (); + }catch (IOException e) { + throw e; + } + + // read number elements + try { + elems = input.readInt (); + }catch (IOException e) { + throw e; + } + + // read data stream compatible to C++ generated stream + nelems = elems; + if (type != rsvcDataTypes.RSVC_INVALID) { + if (ndims == 0) + nelems = 1; + else + nelems = elems; + } + + if (type == rsvcDataTypes.RSVC_INVALID) + throw new IOException ("Data Entry Type is invalid"); + else if (type == rsvcDataTypes.RSVC_BYTE) { + if (nelems == 1) { + byte tmp; + try { + tmp = input.readByte (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + byte[] tmp = new byte[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readByte(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + else if (type == rsvcDataTypes.RSVC_INT16) { + if (nelems == 1) { + short tmp; + try { + tmp = input.readShort (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + short[] tmp = new short[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readShort(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + else if (type == rsvcDataTypes.RSVC_INT32) { + if (nelems == 1) { + int tmp; + try { + tmp = input.readInt (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + int[] tmp = new int[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readInt(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + else if (type == rsvcDataTypes.RSVC_LONG) { + if (nelems == 1) { + long tmp; + try { + tmp = input.readLong (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + long[] tmp = new long[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readLong(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + else if (type == rsvcDataTypes.RSVC_FLOAT) { + if (nelems == 1) { + float tmp; + try { + tmp = input.readFloat (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + float[] tmp = new float[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readFloat(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + else if (type == rsvcDataTypes.RSVC_DOUBLE) { + if (nelems == 1) { + double tmp; + try { + tmp = input.readDouble (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + double[] tmp = new double[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readDouble(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + else if (type == rsvcDataTypes.RSVC_TIMESTAMP) { + if (nelems == 1) { + rsvcTimeStamp tmp; + try { + tmp = input.readTimeStamp (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + rsvcTimeStamp[] tmp = new rsvcTimeStamp[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readTimeStamp(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + else if (type == rsvcDataTypes.RSVC_STRING) { + if (nelems == 1) { + String tmp; + try { + tmp = input.readString (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + String[] tmp = new String[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readString(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + if (de != null) + insert (de); + } + + } + + + + /** + * Take a input data stream and populate this data object + */ + public void streamIn (rsvcDataInputStream input) throws IOException + { + int i, j; + // clean out this object first + remove (); + + // read magic number first + int magic; + try { + magic = input.readInt (); + }catch (IOException e){ + throw e; + } + + if (magic != rsvcData._RSVC_MAGIC_NUM) { + throw new IOException ("Magic number mismatch"); + } + + // read number of elements + int count; + try { + count = input.readInt (); + }catch (IOException e) { + throw e; + } + // read each data entry + for (i = 0; i < count; i++) { + short type; + short ndims; + int elems, nelems; + String tag = null; + rsvcDataEntry de = null; + + // read tag + try { + tag = input.readString (); + }catch (IOException e) { + throw e; + } + + // read type + try { + type = input.readShort (); + }catch (IOException e) { + throw e; + } + + // read dimension + try { + ndims = input.readShort (); + }catch (IOException e) { + throw e; + } + + // read number elements + try { + elems = input.readInt (); + }catch (IOException e) { + throw e; + } + + // read data stream compatible to C++ generated stream + nelems = elems; + if (type != rsvcDataTypes.RSVC_INVALID) { + if (ndims == 0) + nelems = 1; + else + nelems = elems; + } + + if (type == rsvcDataTypes.RSVC_INVALID) + throw new IOException ("Data Entry Type is invalid"); + else if (type == rsvcDataTypes.RSVC_BYTE) { + if (nelems == 1) { + byte tmp; + try { + tmp = input.readByte (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + byte[] tmp = new byte[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readByte(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + else if (type == rsvcDataTypes.RSVC_INT16) { + if (nelems == 1) { + short tmp; + try { + tmp = input.readShort (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + short[] tmp = new short[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readShort(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + else if (type == rsvcDataTypes.RSVC_INT32) { + if (nelems == 1) { + int tmp; + try { + tmp = input.readInt (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + int[] tmp = new int[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readInt(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + else if (type == rsvcDataTypes.RSVC_LONG) { + if (nelems == 1) { + long tmp; + try { + tmp = input.readLong (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + long[] tmp = new long[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readLong(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + else if (type == rsvcDataTypes.RSVC_FLOAT) { + if (nelems == 1) { + float tmp; + try { + tmp = input.readFloat (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + float[] tmp = new float[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readFloat(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + else if (type == rsvcDataTypes.RSVC_DOUBLE) { + if (nelems == 1) { + double tmp; + try { + tmp = input.readDouble (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + double[] tmp = new double[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readDouble(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + else if (type == rsvcDataTypes.RSVC_TIMESTAMP) { + if (nelems == 1) { + rsvcTimeStamp tmp; + try { + tmp = input.readTimeStamp (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + rsvcTimeStamp[] tmp = new rsvcTimeStamp[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readTimeStamp(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + else if (type == rsvcDataTypes.RSVC_STRING) { + if (nelems == 1) { + String tmp; + try { + tmp = input.readString (); + }catch (IOException e) { + throw e; + } + de = new rsvcDataEntry (tag, tmp); + } + else { + String[] tmp = new String[nelems]; + for (j = 0; j < nelems; j++) { + try { + tmp[j] = input.readString(); + } + catch (IOException e) { + throw e; + } + } + de = new rsvcDataEntry (tag, tmp); + } + } + if (de != null) + insert (de); + } + + } +} + + + diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcDataEntry.java b/extensions/cdevGenericServer/NameServer/java/rsvcDataEntry.java new file mode 100644 index 0000000..8b3b423 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcDataEntry.java @@ -0,0 +1,870 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// rsvcDataEntry Class Which is contained inside rsvcData +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcDataEntry.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.1 1999/10/18 17:12:40 chen +// *** empty log message *** +// +// +// +// +import java.io.IOException; +import rsvcDataTypes; +import rsvcTimeStamp; +import rsvcDataOutputStream; + +public final class rsvcDataEntry +{ + private String tag_; + private short type_; + private short ndims_; + private int nelems_; + private Number []data_; + private String []sdata_; + + /** + * Construct an empty data entry + */ + public rsvcDataEntry () + { + tag_ = null; + type_ = rsvcDataTypes.RSVC_INVALID; + ndims_ = -1; + nelems_ = 0; + } + + /** + * Construct a tagged data entry from a double value + */ + public rsvcDataEntry (String tag, double d) + { + tag_ = tag; + ndims_ = 0; + nelems_ = 1; + type_ = rsvcDataTypes.RSVC_DOUBLE; + data_ = new Double[1]; + data_[0] = new Double (d); + } + + /** + * Construct a tagged data entry from a float value + */ + public rsvcDataEntry (String tag, float f) + { + tag_ = tag; + ndims_ = 0; + nelems_ = 1; + type_ = rsvcDataTypes.RSVC_FLOAT; + data_ = new Float[1]; + data_[0] = new Float(f); + } + + + /** + * Construct a tagged data entry from a long value + */ + public rsvcDataEntry (String tag, long l) + { + tag_ = tag; + ndims_ = 0; + nelems_ = 1; + type_ = rsvcDataTypes.RSVC_LONG; + data_ = new Long[1]; + data_[0] = new Long(l); + } + + /** + * Construct a tagged data entry from an integer value + */ + public rsvcDataEntry (String tag, int i) + { + tag_ = tag; + ndims_ = 0; + nelems_ = 1; + type_ = rsvcDataTypes.RSVC_INT32; + data_ = new Integer[1]; + data_[0] = new Integer(i); + } + + /** + * Construct a tagged data entry from a short value + */ + public rsvcDataEntry (String tag, short s) + { + tag_ = tag; + ndims_ = 0; + nelems_ = 1; + type_ = rsvcDataTypes.RSVC_INT16; + data_ = new Short[1]; + data_[0] = new Short(s); + } + + /** + * Construct a tagged data entry from a byte value + */ + public rsvcDataEntry (String tag, byte b) + { + tag_ = tag; + ndims_ = 0; + nelems_ = 1; + type_ = rsvcDataTypes.RSVC_BYTE; + data_ = new Byte[1]; + data_[0] = new Byte(b); + } + + /** + * Construct a tagged data entry from a string + */ + public rsvcDataEntry (String tag, String str) + { + tag_ = tag; + ndims_ = 0; + nelems_ = 1; + type_ = rsvcDataTypes.RSVC_STRING; + sdata_ = new String[1]; + sdata_[0] = str; + } + + /** + * Construct a tagged data entry from a time stamp + */ + public rsvcDataEntry (String tag, rsvcTimeStamp ts) + { + tag_ = tag; + ndims_ = 0; + nelems_ = 1; + type_ = rsvcDataTypes.RSVC_TIMESTAMP; + data_ = new rsvcTimeStamp[1]; + data_[0] = ts; + } + + /** + * Construct a tagged data entry from an array of byte + */ + public rsvcDataEntry (String tag, byte[] barray) + { + tag_ = tag; + ndims_ = 1; + nelems_ = barray.length; + type_ = rsvcDataTypes.RSVC_BYTE; + data_ = new Byte[nelems_]; + for (int i = 0; i < nelems_; i++) + data_[i] = new Byte(barray[i]); + } + + /** + * Construct a tagged data entry from an array of short + */ + public rsvcDataEntry (String tag, short[] sarray) + { + tag_ = tag; + ndims_ = 1; + nelems_ = sarray.length; + type_ = rsvcDataTypes.RSVC_INT16; + data_ = new Short[nelems_]; + for (int i = 0; i < nelems_; i++) + data_[i] = new Short(sarray[i]); + } + + /** + * Construct a tagged data entry from an array of integer + */ + public rsvcDataEntry (String tag, int[] iarray) + { + tag_ = tag; + ndims_ = 1; + nelems_ = iarray.length; + type_ = rsvcDataTypes.RSVC_INT32; + data_ = new Integer[nelems_]; + for (int i = 0; i < nelems_; i++) + data_[i] = new Integer(iarray[i]); + } + + /** + * Construct a tagged data entry from an array of long + */ + public rsvcDataEntry (String tag, long[] larray) + { + tag_ = tag; + ndims_ = 1; + nelems_ = larray.length; + type_ = rsvcDataTypes.RSVC_LONG; + data_ = new Long[nelems_]; + for (int i = 0; i < nelems_; i++) + data_[i] = new Long(larray[i]); + } + + /** + * Construct a tagged data entry from an array of float + */ + public rsvcDataEntry (String tag, float[] farray) + { + tag_ = tag; + ndims_ = 1; + nelems_ = farray.length; + type_ = rsvcDataTypes.RSVC_FLOAT; + data_ = new Float[nelems_]; + for (int i = 0; i < nelems_; i++) + data_[i] = new Float (farray[i]); + } + + /** + * Construct a tagged data entry from an array of double + */ + public rsvcDataEntry (String tag, double[] darray) + { + tag_ = tag; + ndims_ = 1; + nelems_ = darray.length; + type_ = rsvcDataTypes.RSVC_DOUBLE; + data_ = new Double[nelems_]; + for (int i = 0; i < nelems_; i++) + data_[i] = new Double(darray[i]); + } + + /** + * Construct a tagged data entry from an array of strings + */ + public rsvcDataEntry (String tag, String[] strs) + { + tag_ = tag; + ndims_ = 1; + nelems_ = strs.length; + type_ = rsvcDataTypes.RSVC_STRING; + sdata_ = new String[nelems_]; + for (int i = 0; i < nelems_; i++) + sdata_[i] = strs[i]; + } + + /** + * Construct a tagged data entry from an array of time stamps + */ + public rsvcDataEntry (String tag, rsvcTimeStamp[] tsarray) + { + tag_ = tag; + ndims_ = 1; + nelems_ = tsarray.length; + type_ = rsvcDataTypes.RSVC_TIMESTAMP; + data_ = new rsvcTimeStamp[nelems_]; + for (int i = 0; i < nelems_; i++) + data_[i] = tsarray[i]; + } + + /** + * Hash code for this data entry + */ + public int hashCode() + { + return tag_.hashCode(); + } + + /** + * Compare two data entries + */ + public boolean equals(rsvcDataEntry dobj) + { + if (dobj.type_ != type_ || + dobj.nelems_ != nelems_ || + dobj.ndims_ != ndims_ || + dobj.tag_.equals(tag_) == false) + return false; + + int i, j; + if (type_ != rsvcDataTypes.RSVC_INVALID) { + if (type_ == rsvcDataTypes.RSVC_STRING) { + for (i = 0; i < nelems_; i++) { + if (sdata_[i].equals (dobj.sdata_[i]) == false) + return false; + } + } + else { + for (i = 0; i < nelems_; i++) { + if (data_[i].equals (dobj.data_[i]) == false) + return false; + } + } + } + return true; + } + + + /** + * Retrieve internal data as a byte value + */ + public byte byteValue () + { + if (type_ != rsvcDataTypes.RSVC_INVALID && + type_ != rsvcDataTypes.RSVC_STRING) + return data_[0].byteValue(); + else if (type_ == rsvcDataTypes.RSVC_STRING) + return Byte.valueOf(sdata_[0]).byteValue(); + else throw new NumberFormatException("Uninitialize rsvcDataEntry Object"); + } + + /** + * Retrieve internal data as a short value + */ + public short shortValue () + { + if (type_ != rsvcDataTypes.RSVC_INVALID && + type_ != rsvcDataTypes.RSVC_STRING) + return data_[0].shortValue(); + else if (type_ == rsvcDataTypes.RSVC_STRING) + return Short.valueOf(sdata_[0]).shortValue(); + else throw new NumberFormatException("Uninitialize rsvcDataEntry Object"); + } + + /** + * Retrieve internal data as an integer value + */ + public int intValue () + { + if (type_ != rsvcDataTypes.RSVC_INVALID && + type_ != rsvcDataTypes.RSVC_STRING) + return data_[0].intValue(); + else if (type_ == rsvcDataTypes.RSVC_STRING) + return Integer.valueOf(sdata_[0]).intValue(); + else throw new NumberFormatException("Uninitialize rsvcDataEntry Object"); + } + + /** + * Retrieve internal data as a long value + */ + public long longValue () + { + if (type_ != rsvcDataTypes.RSVC_INVALID && + type_ != rsvcDataTypes.RSVC_STRING) + return data_[0].longValue(); + else if (type_ == rsvcDataTypes.RSVC_STRING) + return Long.valueOf(sdata_[0]).longValue(); + else throw new NumberFormatException("Uninitialize rsvcDataEntry Object"); + } + + /** + * Retrieve internal data as a float value + */ + public float floatValue () + { + if (type_ != rsvcDataTypes.RSVC_INVALID && + type_ != rsvcDataTypes.RSVC_STRING) + return data_[0].floatValue(); + else if (type_ == rsvcDataTypes.RSVC_STRING) + return Float.valueOf(sdata_[0]).floatValue(); + else throw new NumberFormatException("Uninitialize rsvcDataEntry Object"); + } + + /** + * Retrieve internal data as a double value + */ + public double doubleValue () + { + if (type_ != rsvcDataTypes.RSVC_INVALID && + type_ != rsvcDataTypes.RSVC_STRING) + return data_[0].doubleValue(); + else if (type_ == rsvcDataTypes.RSVC_STRING) + return Double.valueOf(sdata_[0]).doubleValue(); + else throw new NumberFormatException("Uninitialize rsvcDataEntry Object"); + } + + /** + * Retrieve internal data as a string + */ + public String stringValue () + { + if (type_ != rsvcDataTypes.RSVC_INVALID && + type_ != rsvcDataTypes.RSVC_STRING) + return String.valueOf (data_[0]); + else if (type_ == rsvcDataTypes.RSVC_STRING) + return sdata_[0]; + else throw new NumberFormatException("Uninitialize rsvcDataEntry Object"); + } + + /** + * Retrieve internal data as an array of byte + */ + public byte[] byteArray () + { + int i; + if (type_ != rsvcDataTypes.RSVC_INVALID && + type_ != rsvcDataTypes.RSVC_STRING) { + byte[] barray = new byte[nelems_]; + for (i = 0; i < nelems_; i++) + barray[i] = data_[i].byteValue(); + return barray; + } + else if (type_ == rsvcDataTypes.RSVC_STRING) { + byte[] barray = new byte[nelems_]; + for (i = 0; i < nelems_; i++) + barray[i] = Byte.valueOf(sdata_[i]).byteValue(); + return barray; + } + else throw new NumberFormatException("Uninitialize rsvcDataEntry Object"); + } + + /** + * Retrieve internal data as an array of short + */ + public short[] shortArray () + { + int i; + if (type_ != rsvcDataTypes.RSVC_INVALID && + type_ != rsvcDataTypes.RSVC_STRING) { + short[] sarray = new short[nelems_]; + for (i = 0; i < nelems_; i++) + sarray[i] = data_[i].shortValue(); + return sarray; + } + else if (type_ == rsvcDataTypes.RSVC_STRING) { + short[] sarray = new short[nelems_]; + for (i = 0; i < nelems_; i++) + sarray[i] = Short.valueOf(sdata_[i]).shortValue(); + return sarray; + } + else throw new NumberFormatException("Uninitialize rsvcDataEntry Object"); + } + + /** + * Retrieve internal data as an array of integer + */ + public int[] intArray () + { + int i; + if (type_ != rsvcDataTypes.RSVC_INVALID && + type_ != rsvcDataTypes.RSVC_STRING) { + int[] iarray = new int[nelems_]; + for (i = 0; i < nelems_; i++) + iarray[i] = data_[i].intValue(); + return iarray; + } + else if (type_ == rsvcDataTypes.RSVC_STRING) { + int[] iarray = new int[nelems_]; + for (i = 0; i < nelems_; i++) + iarray[i] = Integer.valueOf(sdata_[i]).intValue(); + return iarray; + } + else throw new NumberFormatException("Uninitialize rsvcDataEntry Object"); + } + + /** + * Retrieve internal data as an array of float + */ + public float[] floatArray () + { + int i; + if (type_ != rsvcDataTypes.RSVC_INVALID && + type_ != rsvcDataTypes.RSVC_STRING) { + float[] farray = new float[nelems_]; + for (i = 0; i < nelems_; i++) + farray[i] = data_[i].floatValue(); + return farray; + } + else if (type_ == rsvcDataTypes.RSVC_STRING) { + float[] farray = new float[nelems_]; + for (i = 0; i < nelems_; i++) + farray[i] = Float.valueOf(sdata_[i]).floatValue(); + return farray; + } + else throw new NumberFormatException("Uninitialize rsvcDataEntry Object"); + } + + /** + * Retrieve internal data as an array of double + */ + public double[] doubleArray () + { + int i; + if (type_ != rsvcDataTypes.RSVC_INVALID && + type_ != rsvcDataTypes.RSVC_STRING) { + double[] darray = new double[nelems_]; + for (i = 0; i < nelems_; i++) + darray[i] = data_[i].doubleValue(); + return darray; + } + else if (type_ == rsvcDataTypes.RSVC_STRING) { + double[] darray = new double[nelems_]; + for (i = 0; i < nelems_; i++) + darray[i] = Double.valueOf(sdata_[i]).doubleValue(); + return darray; + } + else throw new NumberFormatException("Uninitialize rsvcDataEntry Object"); + } + + /** + * Retrieve internal data as an array of long + */ + public long[] longArray () + { + int i; + if (type_ != rsvcDataTypes.RSVC_INVALID && + type_ != rsvcDataTypes.RSVC_STRING) { + long[] larray = new long[nelems_]; + for (i = 0; i < nelems_; i++) + larray[i] = data_[i].longValue(); + return larray; + } + else if (type_ == rsvcDataTypes.RSVC_STRING) { + long[] larray = new long[nelems_]; + for (i = 0; i < nelems_; i++) + larray[i] = Long.valueOf(sdata_[i]).longValue(); + return larray; + } + else throw new NumberFormatException("Uninitialize rsvcDataEntry Object"); + } + + /** + * Retrieve internal data as an array of strings + */ + public String[] stringArray () + { + int i; + if (type_ != rsvcDataTypes.RSVC_INVALID && + type_ != rsvcDataTypes.RSVC_STRING) { + String[] sarray = new String[nelems_]; + for (i = 0; i < nelems_; i++) + sarray[i] = String.valueOf (data_[i]); + return sarray; + } + else if (type_ == rsvcDataTypes.RSVC_STRING) { + String[] sarray = new String[nelems_]; + for (i = 0; i < nelems_; i++) + sarray[i] = sdata_[i]; + return sarray; + } + else throw new NumberFormatException("Uninitialize rsvcDataEntry Object"); + } + + /** + *convert the data entry into a string representation + */ + public String toString () + { + StringBuffer result = new StringBuffer(); + int i, j; + + if (type_ == rsvcDataTypes.RSVC_INVALID) + result.append ("Invalid DataEntry Object"); + else { + result.append ("Key: ").append (tag_).append ("\n"); + result.append ("Type: ").append (rsvcDataTypes.types[type_]).append("\n"); + result.append ("NElems: ").append(nelems_).append("\n"); + result.append ("Values: \n"); + + j = 0; + String[] sarray = stringArray(); + for (i = 0; i < nelems_; i++) { + if (j == 0) + result.append ("\t"); + result.append(sarray[i]).append(" "); + j++; + if (j >= 8) { + result.append ("\n"); + j = 0; + } + } + } + return result.toString(); + } + + /** + * Provide an exact deep copy of this data entry + */ + public rsvcDataEntry copy () + { + int i; + rsvcDataEntry de = new rsvcDataEntry(); + + de.type_ = type_; + de.nelems_ = nelems_; + de.ndims_ = ndims_; + if (tag_ != null) + de.tag_ = new String (tag_); + else + de.tag_ = null; + + if (type_ != rsvcDataTypes.RSVC_INVALID) { + switch (type_) { + case rsvcDataTypes.RSVC_STRING: + de.sdata_ = new String[nelems_]; + for (i = 0; i < nelems_; i++) + de.sdata_[i] = new String(sdata_[i]); + break; + case rsvcDataTypes.RSVC_BYTE: + de.data_ = new Byte[nelems_]; + for (i = 0; i < nelems_; i++) + de.data_[i] = new Byte(data_[i].byteValue()); + break; + case rsvcDataTypes.RSVC_INT16: + de.data_ = new Short[nelems_]; + for (i = 0; i < nelems_; i++) + de.data_[i] = new Short(data_[i].shortValue()); + break; + case rsvcDataTypes.RSVC_INT32: + de.data_ = new Integer[nelems_]; + for (i = 0; i < nelems_; i++) + de.data_[i] = new Integer(data_[i].intValue()); + break; + case rsvcDataTypes.RSVC_FLOAT: + de.data_ = new Float[nelems_]; + for (i = 0; i < nelems_; i++) + de.data_[i] = new Float(data_[i].floatValue()); + break; + case rsvcDataTypes.RSVC_DOUBLE: + de.data_ = new Double[nelems_]; + for (i = 0; i < nelems_; i++) + de.data_[i] = new Double(data_[i].doubleValue()); + break; + case rsvcDataTypes.RSVC_LONG: + de.data_ = new Long[nelems_]; + for (i = 0; i < nelems_; i++) + de.data_[i] = new Long(data_[i].longValue()); + break; + } + } + return de; + } + + /** + * Return tag of this data entry + */ + public String getTag () + { + return tag_; + } + + /** + * Set tag to new tag + */ + public void setTag (String tag) + { + tag_ = tag; + } + + /** + * Return data type in numeric value + */ + public short getType () + { + return type_; + } + + /** + * Return data type in Class + */ + public Class getClassType () throws ClassNotFoundException + { + if (type_ == rsvcDataTypes.RSVC_INVALID) + throw new ClassNotFoundException ("Invalid data entry object"); + else { + if (type_ == rsvcDataTypes.RSVC_STRING) + return sdata_.getClass(); + else + return data_.getClass(); + } + } + + /** + * Return dimensionality information + */ + public short getDimension () + { + return ndims_; + } + + /** + * Return number of elements + */ + public int getNumElements () + { + return nelems_; + } + + /** + * Return streamed data size for this data entry + */ + public int streamSize () + { + int datasize = 0; + int i; + + if (type_ == rsvcDataTypes.RSVC_INVALID) + return datasize; + + // size of tag is fixed + datasize += rsvcDataOutputStream.streamSize (tag_, + rsvcDataTypes.RSVC_TAG_MAX_LEN); + // data type, dim, nelems + datasize += 3*rsvcDataOutputStream.streamSize ((int)1); + + if (type_ == rsvcDataTypes.RSVC_STRING) { + if (nelems_ == 1) + datasize += rsvcDataOutputStream.streamSize (sdata_[0]); + else { + for (i = 0; i < nelems_; i++) + datasize += rsvcDataOutputStream.streamSize (sdata_[i]); + } + } + else if(type_ == rsvcDataTypes.RSVC_BYTE) + datasize += nelems_*rsvcDataOutputStream.streamSize ((byte)1); + else if(type_ == rsvcDataTypes.RSVC_INT16) + datasize += nelems_*rsvcDataOutputStream.streamSize ((short)1); + else if(type_ == rsvcDataTypes.RSVC_INT32) + datasize += nelems_*rsvcDataOutputStream.streamSize ((int)1); + else if(type_ == rsvcDataTypes.RSVC_FLOAT) + datasize += nelems_*rsvcDataOutputStream.streamSize ((float)1.0); + else if(type_ == rsvcDataTypes.RSVC_DOUBLE) + datasize += nelems_*rsvcDataOutputStream.streamSize ((double)1.0); + else if(type_ == rsvcDataTypes.RSVC_TIMESTAMP){ + rsvcTimeStamp ts = new rsvcTimeStamp(); + datasize += nelems_*rsvcDataOutputStream.streamSize (ts); + } + else if(type_ == rsvcDataTypes.RSVC_LONG) + datasize += nelems_*rsvcDataOutputStream.streamSize ((long)1); + + return datasize; + } + + /** + * Convert this data entry into a byte stream + */ + public void streamOut (rsvcDataOutputStream output) throws IOException + { + int i; + if (type_ != rsvcDataTypes.RSVC_INVALID) { + try { + output.write (tag_, rsvcDataTypes.RSVC_TAG_MAX_LEN); + }catch (IOException e) { + throw e; + } + + try { + output.write (type_); + }catch (IOException e) { + throw e; + } + + try { + output.write (ndims_); + }catch (IOException e) { + throw e; + } + + // to make stream data compatible to output generated + // by C++ code + int numelems; + if (type_ == rsvcDataTypes.RSVC_STRING) { + if (ndims_ == 0) + numelems = sdata_[0].length() + 1; + else + numelems = nelems_; + } + else { + if (ndims_ == 0) + numelems = 0; + else + numelems = nelems_; + } + + try { + output.write (numelems); + }catch (IOException e) { + throw e; + } + + if (type_ == rsvcDataTypes.RSVC_STRING) { + for (i = 0; i < nelems_; i++) { + try { + output.write (sdata_[i]); + }catch (IOException e) { + throw e; + } + } + } + else if (type_ == rsvcDataTypes.RSVC_BYTE) { + for (i = 0; i < nelems_; i++) { + try { + output.write (data_[i].byteValue()); + }catch (IOException e) { + throw e; + } + } + } + else if (type_ == rsvcDataTypes.RSVC_INT16) { + for (i = 0; i < nelems_; i++) { + try { + output.write (data_[i].shortValue()); + }catch (IOException e) { + throw e; + } + } + } + else if (type_ == rsvcDataTypes.RSVC_INT32) { + for (i = 0; i < nelems_; i++) { + try { + output.write (data_[i].intValue()); + }catch (IOException e) { + throw e; + } + } + } + else if (type_ == rsvcDataTypes.RSVC_LONG) { + for (i = 0; i < nelems_; i++) { + try { + output.write (data_[i].longValue()); + }catch (IOException e) { + throw e; + } + } + } + else if (type_ == rsvcDataTypes.RSVC_FLOAT) { + for (i = 0; i < nelems_; i++) { + try { + output.write (data_[i].floatValue()); + }catch (IOException e) { + throw e; + } + } + } + else if (type_ == rsvcDataTypes.RSVC_DOUBLE) { + for (i = 0; i < nelems_; i++) { + try { + output.write (data_[i].doubleValue()); + }catch (IOException e) { + throw e; + } + } + } + else if (type_ == rsvcDataTypes.RSVC_TIMESTAMP) { + for (i = 0; i < nelems_; i++) { + try { + output.write ((rsvcTimeStamp)data_[i]); + }catch (IOException e) { + throw e; + } + } + } + } + + } + +} + + + diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcDataInputStream.java b/extensions/cdevGenericServer/NameServer/java/rsvcDataInputStream.java new file mode 100644 index 0000000..4824274 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcDataInputStream.java @@ -0,0 +1,240 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// rsvcDataInputStream that converts a byte stream into a rsvcData +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcDataInputStream.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.1 1999/10/18 17:12:41 chen +// *** empty log message *** +// +// +// +import java.io.*; +import java.math.*; + +public class rsvcDataInputStream +{ + // for 32 bit machine + public static final int _RSVC_STREAM_BYTE_UNIT = 4; + + /** + * Return a long word (32 bit) aligned size from original size + */ + public static final int _RSVC_RNDUP (int x) + { + return ((x + _RSVC_STREAM_BYTE_UNIT - 1)/_RSVC_STREAM_BYTE_UNIT) + * _RSVC_STREAM_BYTE_UNIT; + } + + // underlying data output stream + private DataInputStream input = null; + + /** + * Construct a data output stream + */ + public rsvcDataInputStream (InputStream stream) + { + try { + input = new DataInputStream (stream); + }catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Read a single byte char from stream + */ + public byte readByte () throws IOException + { + int tmp; + try { + tmp = input.readInt (); + }catch (IOException e) { + throw e; + } + return (byte)tmp; + } + + /** + * Read a value of short from the stream + */ + public short readShort () throws IOException + { + int tmp; + try { + tmp = input.readInt (); + }catch (IOException e) { + throw e; + } + return (short)tmp; + } + + /** + * Read a value of int from stream + */ + public int readInt () throws IOException + { + int tmp; + try { + tmp = input.readInt (); + }catch (IOException e) { + throw e; + } + return tmp; + } + + /** + * Read a value of long from stream + */ + public long readLong () throws IOException + { + long tmp; + try { + tmp = input.readLong (); + }catch (IOException e) { + throw e; + } + return tmp; + } + + + /** + * Read a value of float from stream + */ + public float readFloat () throws IOException + { + float tmp; + try { + tmp = input.readFloat (); + }catch (IOException e) { + throw e; + } + return tmp; + } + + + /** + * Read a value of double to stream + */ + public double readDouble () throws IOException + { + double tmp; + try { + tmp = input.readDouble (); + }catch (IOException e) { + throw e; + } + return tmp; + } + + /** + * Read a string as series of byte using default encoding + */ + public String readString () throws IOException + { + int len, rlen, i; + + // first find out str size + try { + len = input.readInt (); + }catch (IOException e) { + throw e; + } + + // readout next bytes of strlen + byte[] tmp = new byte[len]; + try { + input.readFully (tmp, 0, len); + }catch (IOException e) { + throw e; + } + + // find out read length of this string by looking for the first 0 + // in this byte array + rlen = 0; + for (i = 0; i < len; i++) { + if (tmp[i] == 0) + break; + } + rlen = i; + + return new String (tmp, 0, rlen); + } + + /** + * Read a series of byte + */ + public byte[] readBytes () throws IOException + { + int len; + + try { + len = input.readInt(); + }catch (IOException e){ + throw e; + } + + byte[] result = new byte[len]; + try { + input.readFully (result, 0, len); + }catch (IOException e){ + throw e; + } + + return result; + } + + + /** + * Read a number of bytes: blocked until all bytes are read + */ + public byte[] readBytes (int len) throws IOException + { + byte[] result = new byte[len]; + try { + input.readFully (result, 0, len); + }catch (IOException e){ + throw e; + } + + return result; + } + + /** + * Read a time stamp from the stream + */ + public rsvcTimeStamp readTimeStamp () throws IOException + { + rsvcTimeStamp ts = new rsvcTimeStamp (); + + try { + ts.secPastEpoch = input.readInt(); + }catch (IOException e){ + throw e; + } + + try{ + ts.nsec = input.readInt(); + }catch (IOException e){ + throw e; + } + return ts; + } + +} diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcDataOutputStream.java b/extensions/cdevGenericServer/NameServer/java/rsvcDataOutputStream.java new file mode 100644 index 0000000..dc8c8e0 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcDataOutputStream.java @@ -0,0 +1,416 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// rsvcDataOutputStream that converts a rsvcData into byte stream +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcDataOutputStream.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.1 1999/10/18 17:12:41 chen +// *** empty log message *** +// +// +// +import java.io.*; + +public class rsvcDataOutputStream +{ + // for 32 bit machine + public static final int _RSVC_STREAM_BYTE_UNIT = 4; + + /** + * Return a long word (32 bit) aligned size from original size + */ + public static final int _RSVC_RNDUP (int x) + { + return ((x + _RSVC_STREAM_BYTE_UNIT - 1)/_RSVC_STREAM_BYTE_UNIT) + * _RSVC_STREAM_BYTE_UNIT; + } + + /** + * Return size information for a single byte + */ + public static int streamSize (byte c) + { + return rsvcDataOutputStream._RSVC_RNDUP ((int)1); + } + + /** + * Return size information for a short + */ + public static int streamSize (short c) + { + return rsvcDataOutputStream._RSVC_RNDUP ((int)2); + } + + /** + * Return size information for a int + */ + public static int streamSize (int c) + { + return rsvcDataOutputStream._RSVC_RNDUP ((int)4); + } + + /** + * Return size information for a long + */ + public static int streamSize (long c) + { + return rsvcDataOutputStream._RSVC_RNDUP ((int)8); + } + + /** + * Return size information for a float + */ + public static int streamSize (float c) + { + return rsvcDataOutputStream._RSVC_RNDUP ((int)4); + } + + /** + * Return size information for a double + */ + public static int streamSize (double c) + { + return rsvcDataOutputStream._RSVC_RNDUP ((int)8); + } + + /** + * Return size information for a string + */ + public static int streamSize (String c) + { + return rsvcDataOutputStream.streamSize ((int)4) + + rsvcDataOutputStream._RSVC_RNDUP ((int)(c.length() + 1)); + } + + /** + * Return size information for a fix buffer of string + */ + public static int streamSize (String str, int buflen) + { + return rsvcDataOutputStream.streamSize (buflen) + + rsvcDataOutputStream._RSVC_RNDUP(buflen); + } + + + /** + * Return size information for a double + */ + public static int streamSize (rsvcTimeStamp ts) + { + return 2*rsvcDataOutputStream._RSVC_RNDUP ((int)4); + } + + + // underlying data output stream + private DataOutputStream out = null; + + /** + * Construct a data output stream + */ + public rsvcDataOutputStream (OutputStream stream) + { + try { + out = new DataOutputStream (stream); + }catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Return how many bytes have been written to this stream + */ + public final int size () + { + return out.size (); + } + + + /** + * Write a single byte char to stream + */ + public void write (char c) throws IOException + { + int tmp = (int)c; + try { + out.writeInt (tmp); + }catch (IOException e) { + throw e; + } + } + + /** + * Write a value of short to stream + */ + public void write (short c) throws IOException + { + int tmp = (int)c; + try { + out.writeInt (tmp); + }catch (IOException e) { + throw e; + } + } + + /** + * Write a value of int to stream + */ + public void write (int c) throws IOException + { + try { + out.writeInt (c); + }catch (IOException e) { + throw e; + } + } + + + /** + * Write a value of float to stream + */ + public void write (float c) throws IOException + { + try { + out.writeFloat (c); + }catch (IOException e) { + throw e; + } + } + + + /** + * Write a value of double to stream + */ + public void write (double c) throws IOException + { + try { + out.writeDouble (c); + }catch (IOException e) { + throw e; + } + } + + /** + * Write a value of long to stream + */ + public void write (long c) throws IOException + { + try { + out.writeLong (c); + }catch (IOException e) { + throw e; + } + } + + /** + * Write a string as series of byte using default encoding + */ + public void write (String str) throws IOException + { + byte []barray = str.getBytes(); + int len = barray.length + 1; + int rlen = rsvcDataOutputStream._RSVC_RNDUP (len); + + // first write out how many bytes that follow + try { + out.writeInt (rlen); + }catch (IOException e) { + throw e; + } + + // write out string as bytes + try { + out.writeBytes (str); + }catch (IOException e) { + throw e; + } + + // write out remainder as 0 + for (int i = 0; i < rlen - len + 1; i++) { + try { + out.writeByte (0); + }catch (IOException e) { + throw e; + } + } + } + + + /** + * Write a string as series of byte using default encoding + * to a maximum length len + */ + public void write (String str, int len) throws IOException + { + if (len % rsvcDataOutputStream._RSVC_STREAM_BYTE_UNIT != 0) { + throw new IOException ("Fix buffer len is not long word aligned"); + } + + byte []barray = str.getBytes(); + if (barray.length >= len) { + // need last 0 for out string buffer + throw new IOException ("Overflow fix buffer"); + } + + // first write out how many bytes that follow + try { + out.writeInt (len); + }catch (IOException e) { + throw e; + } + + // write out string as bytes + try { + out.writeBytes (str); + }catch (IOException e) { + throw e; + } + + // write out remainder as 0 + for (int i = 0; i < len - barray.length; i++) { + try { + out.writeByte (0); + }catch (IOException e) { + throw e; + } + } + } + + /** + * Write a series of byte + */ + public void write (byte[] c) throws Exception + { + if (c == null) throw new NullPointerException(); + + int len = c.length; + int rlen = rsvcDataOutputStream._RSVC_RNDUP (len); + + try { + out.writeInt (rlen); + }catch (IOException e){ + throw e; + } + + try { + out.write (c, 0, len); + }catch (IOException e){ + throw e; + } + + for (int i = 0; i < rlen - len; i++) { + try { + out.writeByte (0); + }catch (IOException e){ + throw e; + } + } + } + + /** + * Write out a time stamp to the stream + */ + public void write (rsvcTimeStamp ts) throws IOException + { + try { + out.writeInt (ts.secPastEpoch); + }catch (IOException e) { + throw e; + } + + try { + out.writeInt (ts.nsec); + }catch (IOException e) { + throw e; + } + } + + + /** + * Write out Byte to the stream + */ + public void write (Byte c) throws IOException + { + try { + write (c.byteValue()); + }catch (IOException e) { + throw e; + } + } + + /** + * Write out Short to the stream + */ + public void write (Short c) throws IOException + { + try { + write (c.shortValue()); + }catch (IOException e) { + throw e; + } + } + + /** + * Write out Integer to the stream + */ + public void write (Integer c) throws IOException + { + try { + write (c.intValue()); + }catch (IOException e) { + throw e; + } + } + + /** + * Write out Float to the stream + */ + public void write (Float c) throws IOException + { + try { + write (c.floatValue()); + }catch (IOException e) { + throw e; + } + } + + /** + * Write out Double to the stream + */ + public void write (Double c) throws IOException + { + try { + write (c.doubleValue()); + }catch (IOException e) { + throw e; + } + } + + /** + * Flush data out calling underlying real data stream flush method + */ + public final void flush () throws IOException + { + try { + out.flush (); + }catch (IOException e) { + throw new IOException (e.toString()); + } + } + +} diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcDataTest.java b/extensions/cdevGenericServer/NameServer/java/rsvcDataTest.java new file mode 100644 index 0000000..2c2909e --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcDataTest.java @@ -0,0 +1,408 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// rsvc data package test +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcDataTest.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.1 1999/10/18 17:12:41 chen +// *** empty log message *** +// +// +// +// +import java.io.*; +import rsvcData; + +public class rsvcDataTest +{ + public static final byte bdata = 1; + public static final short sdata = 2; + public static final int idata = 3; + public static final long ldata = 4; + public static final float fdata = (float)5.0; + public static final double ddata = 6.0; + public static final String strdata = new String ("Hello World I am Here"); + public static final String file = new String ("/home/chen/java/rsvc/test.dat"); + public static final String coutputfile = new String ("/home/chen/java/rsvc/coutput.dat"); + public static final String cinputfile = new String ("/home/chen/java/rsvc/cinput.dat"); + + static public void integerConvTest () + { + + // test array insert + int []iarray = new int[127]; + for (int i = 0; i < 127; i++) + iarray[i] = i; + + rsvcData data = new rsvcData (); + data.insert ("value", iarray); + + // get data test + rsvcDataEntry de = data.get ("value"); + + // byte converstion + byte[] ba = de.byteArray (); + rsvcData data1 = new rsvcData (); + data1.insert ("value", ba); + + de = data1.get ("value"); + int []ia = de.intArray(); + rsvcData data2 = new rsvcData(); + data2.insert ("value", ia); + if (data.equals (data2)) + System.out.print ("Integer -> Byte -> Integer OK\n"); + else + System.out.print ("Integer -> Byte -> Integer Failed\n"); + + // short conversion + de = data.get ("value"); + short[] sa = de.shortArray (); + rsvcData data3 = new rsvcData (); + data3.insert ("value", sa); + de = data3.get ("value"); + ia = de.intArray (); + + rsvcData data4 = new rsvcData(); + data4.insert ("value", ia); + + if (data.equals (data4)) + System.out.print ("Integer -> Short -> Integer OK\n"); + else + System.out.print ("Integer -> Short -> Integer Failed\n"); + + + // long conversion + de = data.get ("value"); + long[] la = de.longArray (); + rsvcData data5 = new rsvcData (); + data5.insert ("value", la); + de = data5.get ("value"); + ia = de.intArray (); + + rsvcData data6 = new rsvcData(); + data6.insert ("value", ia); + + if (data.equals (data6)) + System.out.print ("Integer -> Long -> Integer OK\n"); + else + System.out.print ("Integer -> Long -> Integer Failed\n"); + + + // float conversion + de = data.get ("value"); + float[] fa = de.floatArray (); + rsvcData data7 = new rsvcData (); + data7.insert ("value", fa); + de = data7.get ("value"); + ia = de.intArray (); + + rsvcData data8 = new rsvcData(); + data8.insert ("value", ia); + + if (data.equals (data8)) + System.out.print ("Integer -> Float -> Integer OK\n"); + else + System.out.print ("Integer -> Float -> Integer Failed\n"); + + // Double conversion + de = data.get ("value"); + double[] da = de.doubleArray (); + rsvcData data9 = new rsvcData (); + data9.insert ("value", da); + de = data9.get ("value"); + ia = de.intArray (); + + rsvcData data10 = new rsvcData(); + data10.insert ("value", ia); + + if (data.equals (data10)) + System.out.print ("Integer -> Double -> Integer OK\n"); + else + System.out.print ("Integer -> Double -> Integer Failed\n"); + } + + static public void floatConvTest () + { + + // test array insert + float []farray = new float[127]; + for (int i = 0; i < 127; i++) + farray[i] = (float)i; + + rsvcData data = new rsvcData (); + data.insert ("value", farray); + + // get data test + rsvcDataEntry de = data.get ("value"); + + // byte converstion + byte[] ba = de.byteArray (); + rsvcData data1 = new rsvcData (); + data1.insert ("value", ba); + + de = data1.get ("value"); + float []ia = de.floatArray(); + rsvcData data2 = new rsvcData(); + data2.insert ("value", ia); + if (data.equals (data2)) + System.out.print ("Float -> Byte -> Float OK\n"); + else + System.out.print ("Float -> Byte -> Float Failed\n"); + + // short conversion + de = data.get ("value"); + short[] sa = de.shortArray (); + rsvcData data3 = new rsvcData (); + data3.insert ("value", sa); + de = data3.get ("value"); + ia = de.floatArray (); + + rsvcData data4 = new rsvcData(); + data4.insert ("value", ia); + + if (data.equals (data4)) + System.out.print ("Float -> Short -> Float OK\n"); + else + System.out.print ("Float -> Short -> Float Failed\n"); + + + // long conversion + de = data.get ("value"); + long[] la = de.longArray (); + rsvcData data5 = new rsvcData (); + data5.insert ("value", la); + de = data5.get ("value"); + ia = de.floatArray (); + + rsvcData data6 = new rsvcData(); + data6.insert ("value", ia); + + if (data.equals (data6)) + System.out.print ("Float -> Long -> Float OK\n"); + else + System.out.print ("Float -> Long -> Float Failed\n"); + + + // Integer conversion + de = data.get ("value"); + int[] fa = de.intArray (); + rsvcData data7 = new rsvcData (); + data7.insert ("value", fa); + de = data7.get ("value"); + ia = de.floatArray (); + + rsvcData data8 = new rsvcData(); + data8.insert ("value", ia); + + if (data.equals (data8)) + System.out.print ("Float -> Integer -> Float OK\n"); + else + System.out.print ("Float -> Integer -> Float Failed\n"); + + // Double conversion + de = data.get ("value"); + double[] da = de.doubleArray (); + rsvcData data9 = new rsvcData (); + data9.insert ("value", da); + de = data9.get ("value"); + ia = de.floatArray (); + + rsvcData data10 = new rsvcData(); + data10.insert ("value", ia); + + if (data.equals (data10)) + System.out.print ("Float -> Double -> Float OK\n"); + else + System.out.print ("Float -> Double -> Float Failed\n"); + } + + public static rsvcData arrayData () + { + rsvcData data = new rsvcData (); + int i; + + // insert array of double + double[] darray = new double[127]; + for (i = 0; i < 127; i++) + darray[i] = 123.232 + i*121.121 + i/89.12; + data.insert ("value0", darray); + + // insert array of string + String[] sarray = new String[211]; + for (i = 0; i < 211; i++) + sarray[i] = new String("value plus " + String.valueOf(i)); + data.insert ("value1", sarray); + + return data; + } + + + public static void main (String[] args) + { + rsvcData data = new rsvcData(); + + // test scaler data insert + data.insert ("value0", bdata); + data.insert ("value1", sdata); + data.insert ("value2", idata); + data.insert ("value3", ldata); + data.insert ("value4", fdata); + data.insert ("value5", ddata); + data.insert ("value6", strdata); + + + try { + data.dup ("value4", "value3"); + }catch (rsvcException e) { + data.remove ("value3"); + data.dup ("value4", "value3"); + } + + data.asciiDump (); + + rsvcData data1 = new rsvcData (data); + if (data.equals (data1)) + System.out.print ("Data == Data1\n"); + else + System.out.print ("Data != Data1\n"); + + data1.insert ("value0", (byte)12); + if (data.equals (data1)) + System.out.print ("Data == Data1\n"); + else + System.out.print ("Data != Data1\n"); + + data1.changeTag ("value2", "value12"); + + data1.asciiDump (); + + rsvcTimeStamp ts = new rsvcTimeStamp(); + data1.insert ("value1", ts); + data1.asciiDump (); + + integerConvTest (); + floatConvTest(); + + // test stream out and stream in + File outputfile = new File (rsvcDataTest.file); + FileOutputStream output = null; + try { + output = new FileOutputStream (outputfile); + }catch (IOException e) { + System.out.println (e); + System.exit (-1); + } + + // find out how big stream rsvcData will be + // rsvcData olddata = arrayData (); + rsvcData olddata = new rsvcData (); + olddata.insert ("value0", (double)129.01); + olddata.insert ("value1", (double)142323.01); + int dsize = olddata.streamSize (); + + System.out.print ("Data size is " + String.valueOf(dsize) + "\n"); + + // Create Buffered output stream + BufferedOutputStream boutput = new BufferedOutputStream (output, dsize); + try { + olddata.streamOut (boutput); + }catch (IOException e) { + System.out.println (e); + System.exit (-1); + } + + try { + boutput.flush(); + }catch (IOException e) { + System.out.println (e); + System.exit (-1); + } + + + // create a buffered input stream + rsvcData newdata = new rsvcData (); + FileInputStream input = null; + try { + input = new FileInputStream (outputfile); + }catch (IOException e) { + System.out.println (e); + System.exit (-1); + } + BufferedInputStream binput = new BufferedInputStream(input, dsize); + try { + newdata.streamIn (binput); + }catch (IOException e) { + System.out.println (e); + System.exit (-1); + } + + newdata.asciiDump (); + + // test equality between newdata and data + if (olddata.equals (newdata) ) + System.out.print ("Data == newdata\n"); + else + System.out.print ("Data != newdata\n"); + + // test whether we can read from a file generated by C code + // create a buffered input stream + + rsvcData cdata = new rsvcData (); + try { + input = new FileInputStream (coutputfile); + }catch (IOException e) { + System.out.println (e); + System.exit (-1); + } + binput = new BufferedInputStream(input, 2400); + try { + cdata.streamIn (binput); + }catch (IOException e) { + System.out.println (e); + System.exit (-1); + } + + cdata.asciiDump (); + + // output some data stream let C++ to pick it up + try { + output = new FileOutputStream (cinputfile); + }catch (IOException e) { + System.out.println (e); + System.exit (-1); + } + boutput = new BufferedOutputStream(output, 2400); + try { + cdata.streamOut (boutput); + }catch (IOException e) { + System.out.println (e); + System.exit (-1); + } + + try { + boutput.flush(); + }catch (IOException e) { + System.out.println (e); + System.exit (-1); + } + + } +} + + diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcDataTypes.java b/extensions/cdevGenericServer/NameServer/java/rsvcDataTypes.java new file mode 100644 index 0000000..65913ef --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcDataTypes.java @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// rsvcDataType Class +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcDataTypes.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.1 1999/10/18 17:12:42 chen +// *** empty log message *** +// +// +// +// +public final class rsvcDataTypes +{ + static public final short RSVC_BYTE = 0; + static public final short RSVC_INT16 = 1; + static public final short RSVC_UINT16 = 2; + static public final short RSVC_INT32 = 3; + static public final short RSVC_UINT32 = 4; + static public final short RSVC_FLOAT = 5; + static public final short RSVC_DOUBLE = 6; + static public final short RSVC_STRING = 7; + static public final short RSVC_TIMESTAMP = 8; + static public final short RSVC_INVALID = 9; + static public final short RSVC_ULONG = 10; + static public final short RSVC_LONG = 11; + + static public final short RSVC_TAG_MAX_LEN = 16; + + static final String[] types = {"Byte", + "Short", + "Unsigned Short", + "Integer", + "Unsigned Integer", + "Float", + "Double", + "Char String", + "TimeStamp", + "Invalid", + "Unsigned long 64", + "Long 64" + }; +} + diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcDisplay.html b/extensions/cdevGenericServer/NameServer/java/rsvcDisplay.html new file mode 100644 index 0000000..636e292 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcDisplay.html @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcDisplay.java b/extensions/cdevGenericServer/NameServer/java/rsvcDisplay.java new file mode 100644 index 0000000..fbaac10 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcDisplay.java @@ -0,0 +1,592 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// JAVA Applet for rsvc name server +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcDisplay.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.3 1999/12/14 15:38:16 chen +// Add scrollbar to display +// +// Revision 1.2 1999/10/18 17:16:06 chen +// minor changes +// +// Revision 1.1 1999/10/18 17:12:42 chen +// *** empty log message *** +// +// +// +// +import java.io.*; +import java.awt.*; +import java.awt.event.*; +import java.applet.*; +import java.net.*; +import rsvcData; +import rsvcDataEntry; +import rsvcClient; +import rsvcEventHandler; +import rsvcConfig; + +public class rsvcDisplay extends Applet implements Runnable, rsvcEventHandler +{ + // display tag names + private final String[] tags_ = {"name","domain","status","host", "port", "owner"}; + private final int numtags_ = 6; + + // top level scroll pane + private ScrollPane sclp_ = null; + // top level panel + private Panel dpanel_ = null; + + // title field of display + private Label title_ = null; + // information field of display + private Label info_ = null; + + // maximum number of entries + private final int size_ = 40; + + // current number of entries + private int num_ = 0; + + // category filed labels + private Label nameLabel_ = null; + private Label domainLabel_ = null; + private Label statusLabel_ = null; + private Label hostLabel_ = null; + private Label portLabel_ = null; + private Label userLabel_ = null; + + + // diffrent fields + private TextField[] name_; + private TextField[] domain_; + private TextField[] status_; + private TextField[] host_; + private TextField[] port_; + private TextField[] user_; + + // layout + private GridBagLayout layout_ = null; + private GridBagConstraints c_ = null; + + // network connection + private rsvcClient client_ = null; + private String serverHost_ = null; + private int serverPort_ = 0; + + // seperate thread to handle clean up information box + private Thread timerThread_ = null; + + public void setServerHost (String host) + { + serverHost_ = host; + } + + public void setServerPort (int p) + { + serverPort_ = p; + } + + private void startTimerThread () + { + if (timerThread_ == null) { + timerThread_ = new Thread (this); + timerThread_.start(); + } + else + timerThread_.resume (); + + } + + private void createLabel (String label) + { + Font lfont = new Font ("times", Font.BOLD, 14); + Color lc = Color.blue; + + c_.weightx = 0; + c_.gridwidth = GridBagConstraints.REMAINDER; + title_ = new Label (label, Label.CENTER); + title_.setFont (lfont); + title_.setForeground (lc); + layout_.setConstraints(title_, c_); + dpanel_.add(title_); + } + + private void createInfoLabel () + { + Font lfont = new Font ("times", Font.BOLD, 12); + + c_.weightx = 0; + c_.gridwidth = GridBagConstraints.REMAINDER; + info_ = new Label (); + info_.setFont (lfont); + layout_.setConstraints(info_, c_); + dpanel_.add (info_); + } + + private void setInformation (String info) + { + info_.setText (info); + } + + private void clearInformation () + { + info_.setText (null); + } + + private void createFieldLabels () + { + Font lfont = new Font ("helvetica", Font.ITALIC, 12); + c_.weightx = 1; + c_.gridwidth = 1; + nameLabel_ = new Label ("Name", Label.CENTER); + nameLabel_.setFont (lfont); + layout_.setConstraints(nameLabel_, c_); + dpanel_.add(nameLabel_); + + domainLabel_ = new Label ("Domain", Label.CENTER); + domainLabel_.setFont (lfont); + layout_.setConstraints(domainLabel_, c_); + dpanel_.add(domainLabel_); + + statusLabel_ = new Label ("Status", Label.CENTER); + statusLabel_.setFont (lfont); + layout_.setConstraints(statusLabel_, c_); + dpanel_.add(statusLabel_); + + c_.gridwidth = 2; + hostLabel_ = new Label ("Host", Label.CENTER); + hostLabel_.setFont (lfont); + layout_.setConstraints(hostLabel_, c_); + dpanel_.add(hostLabel_); + + c_.gridwidth = 1; + portLabel_ = new Label ("Port", Label.CENTER); + portLabel_.setFont (lfont); + layout_.setConstraints(portLabel_, c_); + dpanel_.add(portLabel_); + + c_.gridwidth = GridBagConstraints.REMAINDER; + userLabel_ = new Label ("User Name", Label.CENTER); + userLabel_.setFont (lfont); + layout_.setConstraints(userLabel_, c_); + dpanel_.add(userLabel_); + } + + private void createEmptyFields (int index) + { + c_.gridwidth = 1; + + name_[index] = new TextField (10); + name_[index].setEditable (false); + layout_.setConstraints(name_[index], c_); + dpanel_.add(name_[index]); + + domain_[index] = new TextField (10); + domain_[index].setEditable (false); + layout_.setConstraints(domain_[index], c_); + dpanel_.add(domain_[index]); + + status_[index] = new TextField (10); + status_[index].setEditable (false); + layout_.setConstraints(status_[index], c_); + dpanel_.add(status_[index]); + + c_.gridwidth = 2; + host_[index] = new TextField (20); + host_[index].setEditable (false); + layout_.setConstraints(host_[index], c_); + dpanel_.add(host_[index]); + + port_[index] = new TextField (10); + port_[index].setEditable (false); + layout_.setConstraints(port_[index], c_); + dpanel_.add(port_[index]); + + + c_.gridwidth = GridBagConstraints.REMAINDER; + user_[index] = new TextField (10); + user_[index].setEditable (false); + layout_.setConstraints(user_[index], c_); + dpanel_.add(user_[index]); + + // force to display + validate (); + } + + private void updateEntryAt (rsvcData data, int index) + { + String dispval = null; + int i = 0; + + rsvcDataEntry dentry = data.get (tags_[i++]); + dentry = data.get (tags_[i++]); + + dentry = data.get (tags_[i++]); + int statusval; + if (dentry != null) { + statusval = dentry.intValue (); + if (statusval == 0) { + status_[index].setBackground (Color.green); + status_[index].setText ("Alive"); + } + else if (statusval == 2) { + status_[index].setBackground (Color.red); + status_[index].setText ("Dead"); + } + else if (statusval == 1) { + status_[index].setBackground (Color.yellow); + status_[index].setText ("Dormant"); + } + else { + status_[index].setBackground (Color.white); + status_[index].setText ("Unknown"); + } + } + + dentry = data.get (tags_[i++]); + if (dentry != null) { + dispval = dentry.stringValue (); + host_[index].setText (dispval); + } + + dentry = data.get (tags_[i++]); + if (dentry != null) { + dispval = dentry.stringValue (); + port_[index].setText (dispval); + } + + + dentry = data.get (tags_[i++]); + if (dentry != null) { + dispval = dentry.stringValue (); + user_[index].setText (dispval); + } + } + + + public void updateEntry (rsvcData data, boolean create) + { + int i = 0; + String dispval = null; + String name = null; + String domain = null; + + rsvcDataEntry dentry = data.get (tags_[i++]); + if (dentry != null) { + dispval = dentry.stringValue (); + name = dispval; + } + + dentry = data.get (tags_[i++]); + if (dentry != null) { + dispval = dentry.stringValue (); + domain = dispval; + } + + i = 0; + String tname = null; + String tdomain = null; + int found = 0; + + if (name != null && domain != null) { + for (i = 0; i < num_; i++) { + tname = name_[i].getText (); + tdomain = domain_[i].getText (); + if (name.compareTo (tname) == 0 && + domain.compareTo (tdomain) == 0) { + updateEntryAt (data, i); + found = 1; + break; + } + } + } + if (found == 0 && create == true) + addEntry (data); + } + + + public void addEntry (rsvcData data) + { + String dispval = null; + int i = 0; + String name = null; + String domain = null; + + + createEmptyFields (num_); + + rsvcDataEntry dentry = data.get (tags_[i++]); + if (dentry != null) { + dispval = dentry.stringValue (); + name_[num_].setText (dispval); + name = dispval; + } + + dentry = data.get (tags_[i++]); + if (dentry != null) { + dispval = dentry.stringValue (); + domain_[num_].setText (dispval); + domain = dispval; + } + + dentry = data.get (tags_[i++]); + int statusval; + if (dentry != null) { + statusval = dentry.intValue (); + if (statusval == 0) { + status_[num_].setBackground (Color.green); + status_[num_].setText ("Alive"); + } + else if (statusval == 2) { + status_[num_].setBackground (Color.red); + status_[num_].setText ("Dead"); + } + else if (statusval == 1) { + status_[num_].setBackground (Color.yellow); + status_[num_].setText ("Dormant"); + } + else { + status_[num_].setBackground (Color.white); + status_[num_].setText ("Unknown"); + } + } + + dentry = data.get (tags_[i++]); + if (dentry != null) { + dispval = dentry.stringValue (); + host_[num_].setText (dispval); + } + + dentry = data.get (tags_[i++]); + if (dentry != null) { + dispval = dentry.stringValue (); + port_[num_].setText (dispval); + } + + + dentry = data.get (tags_[i++]); + if (dentry != null) { + dispval = dentry.stringValue (); + user_[num_].setText (dispval); + } + num_ ++; + + if (name != null && domain != null) { + rsvcData serverinfo = new rsvcData (); + rsvcEvent oevent = null; + + serverinfo.insert ("name", name); + serverinfo.insert ("domain", domain); + + try { + oevent = client_.monitorValue ("cdevServers", serverinfo, + this); + }catch (IOException e) { + ; + } + } + + } + + private void cleanupEntries () + { + for (int i = 0; i < num_; i++) { + remove (name_[i]); + remove (domain_[i]); + remove (status_[i]); + remove (host_[i]); + remove (port_[i]); + remove (user_[i]); + } + num_ = 0; + + validate (); + } + + public void init () + { + // create a border layout for applet + setLayout(new BorderLayout ()); + + // create top level scroll pane + sclp_ = new ScrollPane (ScrollPane.SCROLLBARS_ALWAYS); + add (sclp_); + sclp_.setSize (400, 100); + + // create layout manager + layout_ = new GridBagLayout(); + c_ = new GridBagConstraints(); + c_.fill = GridBagConstraints.BOTH; + + // create top level panel + dpanel_ = new Panel (layout_); + dpanel_.setSize (700, 100); + + // add this panel to scroll pane + sclp_.add (dpanel_); + + // create array of text fields + name_ = new TextField[size_]; + domain_ = new TextField[size_]; + status_ = new TextField[size_]; + host_ = new TextField[size_]; + port_ = new TextField[size_]; + user_ = new TextField[size_]; + + num_ = 0; + + // create top label + createLabel ("CDEV Name Server Information"); + + // create information label + createInfoLabel (); + + // create category labels + createFieldLabels (); + + // create network handler to rsvcServer + client_ = new rsvcClient(); + + if (serverHost_ == null) { + // get parameters for server host and server port + serverHost_ = getParameter ("host"); + serverPort_ = Integer.valueOf (getParameter ("port")).intValue(); + } + } + + + public void start () + { + // start timer thread + startTimerThread (); + + setInformation ("Connecting to server on " + serverHost_ + " at port " + String.valueOf (serverPort_)); + try { + client_.connect (serverHost_, serverPort_); + }catch (UnknownHostException ue) { + setInformation ("Unknown Host " + serverHost_); + }catch (IOException e) { + setInformation ("Cannot connect to the server"); + } + + // if connected + if (client_.connected() == true) { + setInformation ("Connection to the server is established"); + + // get all + rsvcEvent oevent = null; + try { + oevent = client_.query ("cdevServers", "all", this); + }catch (IOException e) { + setInformation ("Cannot send out query information to the server"); + } + + // monitor on new entries + rsvcData noused = new rsvcData(); + try { + oevent = client_. monitorIncomingEntries ("cdevServers", + noused, this); + } catch (IOException e) { + setInformation ("Cannot send out monitor request to the server"); + } + + // add disconnection handler + client_.addDisconnectHandler (this); + + } + + } + + public void stop () + { + if (client_.connected () == true) { + try { + client_.disconnect (); + }catch (IOException e) { + ; + } + } + timerThread_.suspend (); + } + + + public void handleEvent (rsvcEvent event) + { + int status = event.getStatus (); + int opcode = event.getOpcode (); + rsvcData data = event.getData (); + + if (status == rsvcConfig.RSVC_DISCONNECTED) { + setInformation ("Server is Gone"); + cleanupEntries (); + } + else { + if (opcode == rsvcConfig.RSVC_QUERY) { + if (status == rsvcConfig.RSVC_INCOMPLETE || + status == rsvcConfig.RSVC_SUCCESS) + addEntry (data); + } + else if (opcode == rsvcConfig.RSVC_MONITOR_ON) { + if (status == rsvcConfig.RSVC_SUCCESS) + updateEntry (data, false); + } + else if (opcode == rsvcConfig.RSVC_MONITOR_ENTRIES) { + if (status == rsvcConfig.RSVC_SUCCESS && data.isEmpty() != true) + updateEntry (data, true); + } + } + } + + public void run () + { + while (true) { + // check to see whether there is something in the + // information display area. If there is, clean out + String infotext = info_.getText (); + if (infotext != null) + info_.setText (null); + // sleep 3 seconds + try { + Thread.sleep (3000); + } catch (InterruptedException e) { + ; + } + } + } + + public static void main(String args[]) { + if (args.length < 2) { + System.err.println ("Usage: rsvcDisplay host port"); + System.exit (-1); + } + Frame f = new Frame("CDEV Name Server Information"); + rsvcDisplay display = new rsvcDisplay(); + display.setServerHost (args[0]); + display.setServerPort (Integer.valueOf (args[1]).intValue()); + display.init(); + display.start (); + + f.add("Center", display); + f.pack(); + f.setSize(f.getPreferredSize()); + f.show(); + } +} diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcEvent.java b/extensions/cdevGenericServer/NameServer/java/rsvcEvent.java new file mode 100644 index 0000000..6ee61fb --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcEvent.java @@ -0,0 +1,548 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server/Client Protocol Information and Data Information +// This class contains protocol information related to callbacks +// 1. operation code +// 2. request id +// 3. socket id -->for server only +// 4. client id +// 5. callback id -->from client to server +// +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcEvent.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.1 1999/10/18 17:12:42 chen +// *** empty log message *** +// +// +// +import java.io.*; +import rsvcConfig; +import rsvcData; +import rsvcEventHandler; + +public final class rsvcEvent +{ + private int opcode_; + private int cbkid_; + private int eventid_; + private int clientid_; + private int socketid_; + private int status_; + private rsvcData data_; + private rsvcEventHandler handler_ = null; + + /** + * Construct an emtpy rsvcEvent object + */ + public rsvcEvent () + { + opcode_ = rsvcConfig.RSVC_OP_UNKNOWN; + cbkid_ = 0; + eventid_ = 0; + clientid_ = 0; + socketid_ = 0; + status_ = rsvcConfig.RSVC_SUCCESS; + data_ = new rsvcData (); + handler_ = null; + } + + /** + * Construct a rsvcEvent Object with given parameters + */ + public rsvcEvent (rsvcData data, int opcode, int cbkid) + + { + data_ = new rsvcData (data); + opcode_ = opcode; + cbkid_ = cbkid; + eventid_ = 0; + clientid_ = 0; + socketid_ = 0; + status_ = rsvcConfig.RSVC_SUCCESS; + handler_ = null; + } + + /** + * Construct a rsvcEvent Object with given parameters + */ + public rsvcEvent (rsvcData data, int opcode, int cbkid, + int eventid, int clientid, int socketid, + int status) + { + data_ = new rsvcData (data); + opcode_ = opcode; + cbkid_ = cbkid; + eventid_ = eventid; + clientid_ = clientid; + socketid_ = socketid; + status_ = status; + handler_ = null; + } + + + /** + * Construct a rsvcEvent Object without data object + */ + public rsvcEvent (int opcode, int cbkid, + int eventid, int clientid, int socketid, + int status) + { + data_ = new rsvcData(); + opcode_ = opcode; + cbkid_ = cbkid; + eventid_ = eventid; + clientid_ = clientid; + socketid_ = socketid; + status_ = status; + handler_ = null; + } + + + /** + * Construct a rsvcEvent Object with data object only + */ + public rsvcEvent (rsvcData data) + { + data_ = new rsvcData(data); + opcode_ = 0; + cbkid_ = 0; + eventid_ = 0; + clientid_ = 0; + socketid_ = 0; + status_ = rsvcConfig.RSVC_SUCCESS; + handler_ = null; + } + + /** + * Construct a rsvcEvent Object using an exising rsvcEvent + */ + public rsvcEvent (rsvcEvent event) + { + data_ = new rsvcData (event.data_); + opcode_ = event.opcode_; + cbkid_ = event.cbkid_; + eventid_ = event.eventid_; + clientid_ = event.clientid_; + socketid_ = event.socketid_; + status_ = event.status_; + handler_ = event.handler_; + } + + /** + * Check whether two events have the same signature + */ + public boolean match (rsvcEvent event) + { + if (opcode_ == event.opcode_ && + cbkid_ == event.cbkid_ && + eventid_ == event.eventid_) + return true; + return false; + } + + /** + * Set data and other paremeters + */ + public void set (rsvcData data, + int opcode, int cbkid, + int eventid, int clientid, + int socketid, int status) + { + data_ = new rsvcData (data); + opcode_ = opcode; + cbkid_ = cbkid; + eventid_ = eventid; + clientid_ = clientid; + socketid_ = socketid; + status_ = status; + } + + /** + * Set data and other paremeters + */ + public void set (int opcode, int cbkid, + int eventid, int clientid, + int socketid, int status) + { + opcode_ = opcode; + cbkid_ = cbkid; + eventid_ = eventid; + clientid_ = clientid; + socketid_ = socketid; + status_ = status; + } + + /** + * Clean up everything + */ + public void cleanup () + { + data_.remove (); + cbkid_ = 0; + eventid_ = 0; + clientid_ = 0; + socketid_ = 0; + status_ = rsvcConfig.RSVC_SUCCESS; + handler_ = null; + } + + /** + * Get Opcode of this event + */ + public int getOpcode () + { + return opcode_; + } + + /** + * Set opcode of this event + */ + public void setOpcode (int opcode) + { + opcode_ = opcode; + } + + /** + * Get request id + */ + public int getEventid () + { + return eventid_; + } + + /** + * Set request id + */ + public void setEventid (int eventid) + { + eventid_ = eventid; + } + + /** + * Get client id + */ + public int getClientid () + { + return clientid_; + } + + /** + * Set client id + */ + public void setClientid (int clientid) + { + clientid_ = clientid; + } + + /** + * Get cbk id + */ + public int getCbkid () + { + return cbkid_; + } + + /** + * Set cbk id + */ + public void setCbkid (int cbkid) + { + cbkid_ = cbkid; + } + + /** + * Get socket id + */ + public int getSocketid () + { + return socketid_; + } + + /** + * Set socket id + */ + public void setSocketid (int socketid) + { + socketid_ = socketid; + } + + /** + * Get Status of event + */ + public int getStatus () + { + return status_; + } + + /** + * Set Status Field + */ + public void setStatus (int status) + { + status_ = status; + } + + /** + * Get Data Field + */ + public rsvcData getData () + { + return data_; + } + + /** + * Set Data Field + */ + public void setData (rsvcData data) + { + data_ = new rsvcData (data); + } + + /** + * Set Handler field + */ + public void setHandler (rsvcEventHandler handler) + { + handler_ = handler; + } + + /** + * Get handler field + */ + public rsvcEventHandler getHandler () throws NullPointerException + { + if (handler_ == null) { + throw new NullPointerException ("rsvcEvent has a null handler"); + } + return handler_; + } + + /** + * Return binary data stream size for this event + */ + public int streamSize () + { + int dsize = 0; + int size = 0; + + // magic number first + dsize += rsvcDataOutputStream.streamSize (rsvcData._RSVC_MAGIC_NUM); + + // size of the data to follow after this + dsize += rsvcDataOutputStream.streamSize (size); + + // size of 6 integer fields + dsize += 6*rsvcDataOutputStream.streamSize ((int)0); + + dsize += data_.streamSize (); + + return dsize; + } + + /** + * Convert object into a binary data stream + */ + public void streamOut (OutputStream output) throws IOException + { + // calculate total size of this binary stream + int binarysize = streamSize (); + + // payload size without magic number and size information + int rsize = binarysize - + rsvcDataOutputStream.streamSize (rsvcData._RSVC_MAGIC_NUM) - + rsvcDataOutputStream.streamSize (binarysize); + + rsvcDataOutputStream writer = new rsvcDataOutputStream (output); + + // write out magic number first + try{ + writer.write (rsvcData._RSVC_MAGIC_NUM); + }catch (IOException e) { + throw e; + } + + try { + writer.write (rsize); + }catch (IOException e) { + throw e; + } + + // write out six integer field + try { + writer.write (opcode_); + }catch (IOException e) { + throw e; + } + + try { + writer.write (cbkid_); + }catch (IOException e) { + throw e; + } + + try { + writer.write (eventid_); + }catch (IOException e) { + throw e; + } + + try { + writer.write (clientid_); + }catch (IOException e) { + throw e; + } + + try { + writer.write (socketid_); + }catch (IOException e) { + throw e; + } + + try { + writer.write (status_); + }catch (IOException e) { + throw e; + } + + // finally data item itself + try { + data_.streamOut (writer); + }catch (IOException e) { + throw e; + } + } + + /** + * Read header information of an incoming stream to find out + * size information of data stream n + */ + public static int readHeader (InputStream stream) throws IOException + { + // attach input stream + rsvcDataInputStream input = new rsvcDataInputStream (stream); + + // read magic number first + int magic; + try { + magic = input.readInt (); + }catch (IOException e){ + throw e; + } + + if (magic != rsvcData._RSVC_MAGIC_NUM) { + throw new IOException ("Magic number mismatch"); + } + + // get data size + int datasize; + try { + datasize = input.readInt (); + }catch (IOException e) { + throw e; + } + return datasize; + } + + /** + * Return streamed event header length + */ + public static int headerLen () + { + return rsvcDataOutputStream.streamSize (rsvcData._RSVC_MAGIC_NUM) + + rsvcDataOutputStream.streamSize ((int)1); + } + + /** + * Convert a stream into an event object + */ + public void streamIn (InputStream stream) throws IOException + { + // clean up this object + cleanup (); + + // attach input stream + rsvcDataInputStream input = new rsvcDataInputStream (stream); + + try { + opcode_ = input.readInt (); + } catch (IOException e) { + throw e; + } + + try { + cbkid_ = input.readInt (); + } catch (IOException e) { + throw e; + } + + try { + eventid_ = input.readInt (); + } catch (IOException e) { + throw e; + } + + try { + clientid_ = input.readInt (); + } catch (IOException e) { + throw e; + } + + try { + socketid_ = input.readInt (); + } catch (IOException e) { + throw e; + } + + try { + status_ = input.readInt (); + } catch (IOException e) { + throw e; + } + + try { + data_.streamIn (input); + }catch (IOException e) { + throw e; + } + } + + public String toString () + { + StringBuffer result = new StringBuffer (); + + result.append ("Event Contains \n"); + result.append ("opcode: ").append (opcode_).append ("\n"); + result.append ("cbkid: ").append (cbkid_).append ("\n"); + result.append ("eventid: ").append (eventid_).append ("\n"); + result.append ("clientid: ").append (clientid_).append ("\n"); + result.append ("socketid: ").append (socketid_).append ("\n"); + result.append ("status: ").append (status_).append ("\n"); + result.append (data_.toString()); + + return result.toString(); + } + +} + + + + + + diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcEventHandler.java b/extensions/cdevGenericServer/NameServer/java/rsvcEventHandler.java new file mode 100644 index 0000000..c203f21 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcEventHandler.java @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Client Event Handler +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcEventHandler.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.1 1999/10/18 17:12:42 chen +// *** empty log message *** +// +// +// +// +public interface rsvcEventHandler +{ + public void handleEvent (rsvcEvent event); +} + + diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcException.java b/extensions/cdevGenericServer/NameServer/java/rsvcException.java new file mode 100644 index 0000000..09d910e --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcException.java @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// Simple RSVC Package Exception Class +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcException.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.1 1999/10/18 17:12:43 chen +// *** empty log message *** +// +// +// +public class rsvcException extends RuntimeException +{ + rsvcException () + { + super (); + } + + rsvcException (String s) + { + super (s); + } +} + + diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcNetData.java b/extensions/cdevGenericServer/NameServer/java/rsvcNetData.java new file mode 100644 index 0000000..9ddba75 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcNetData.java @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Net Data (Protocol Part for RSVC Client) +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcNetData.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.1 1999/10/18 17:12:43 chen +// *** empty log message *** +// +// +// +// +import rsvcData; + +public final class rsvcNetData +{ + private rsvcData data_ = null; + private rsvc + diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcServerTest.java b/extensions/cdevGenericServer/NameServer/java/rsvcServerTest.java new file mode 100644 index 0000000..7041c1f --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcServerTest.java @@ -0,0 +1,127 @@ +import java.io.*; +import java.util.*; +import java.net.*; +import rsvcClient; +import rsvcEventHandler; +import rsvcConfig; + +public final class rsvcServerTest implements rsvcEventHandler +{ + public rsvcServerTest () + { + // empty + } + + public static void main (String[] args) + { + if (args.length < 4) { + System.err.println ("Usage: rsvcServerTest name domain host port"); + System.exit (-1); + } + + rsvcServerTest test = new rsvcServerTest (); + + String host = args[2]; + int port = Integer.valueOf (args[3]).intValue(); + int udpport = port + 1024; + String server = args[0]; + String domain = args[1]; + + rsvcData serverinfo = new rsvcData (); + rsvcData udpinfo = new rsvcData (); + + serverinfo.insert ("name", server); + serverinfo.insert ("domain", domain); + serverinfo.insert ("host", host); + serverinfo.insert ("owner", "chen"); + serverinfo.insert ("time", (int)(System.currentTimeMillis()/1000)); + serverinfo.insert ("port", (int)(System.currentTimeMillis()%65535)); + serverinfo.insert ("pid", (int)1234); + + udpinfo.insert ("name", server); + udpinfo.insert ("domain", domain); + + rsvcClient client = new rsvcClient (); + rsvcUdpClient udpclient = new rsvcUdpClient(); + + try { + client.connect (host, port); + }catch (UnknownHostException ue) { + System.err.println (ue); + System.exit (-1); + }catch (IOException e) { + System.err.println (e); + System.exit (-1); + } + + try { + udpclient.connect (host, udpport); + }catch (UnknownHostException ue) { + System.err.println (ue); + System.exit (-1); + }catch (IOException e) { + System.err.println (e); + System.exit (-1); + } + + + // outbound event stream + rsvcEvent oevent = null; + try { + oevent = client.insertValue ("cdevServers", serverinfo, + test, true); + }catch (IOException e) { + System.err.println (e); + System.exit (-1); + } + + + Thread readerThread = client.getReaderThread (); + + while (true) { + try { + udpclient.update (udpinfo); + } catch (IOException e) { + System.err.println (e); + System.exit (-1); + } + + // wait for 5 seconds + try { + readerThread.join (5000); + } catch (InterruptedException e) { + System.err.println (e); + System.exit (-1); + } + } + } + + public void handleEvent (rsvcEvent event) + { + int status = event.getStatus (); + int opcode = event.getOpcode (); + rsvcData data = event.getData (); + + System.out.println ("Handle event is called with status :" + String.valueOf (status)); + + switch (opcode) { + case rsvcConfig.RSVC_GET: + System.out.println ("Get Value with result :"); + break; + case rsvcConfig.RSVC_QUERY: + System.out.println ("Query Value with result :"); + break; + case rsvcConfig.RSVC_SET: + System.out.println ("Set Value with result :"); + break; + default: + System.out.println ("Operation : " + String.valueOf (opcode)); + } + + if (status == rsvcConfig.RSVC_NOTFOUND) + System.out.println ("Found nothing"); + + if (status == rsvcConfig.RSVC_SUCCESS) + data.asciiDump (); + } +} diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcTimeStamp.java b/extensions/cdevGenericServer/NameServer/java/rsvcTimeStamp.java new file mode 100644 index 0000000..6a378a3 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcTimeStamp.java @@ -0,0 +1,114 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// Data Type Of Time Stamp +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcTimeStamp.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.1 1999/10/18 17:12:44 chen +// *** empty log message *** +// +// +// +import java.util.Date; + +public final class rsvcTimeStamp extends Number +{ + public int secPastEpoch; // seconds since Jan. 1, 1970 + public int nsec; // nano seconds + + /** + * Construct a time stamp with current time + */ + public rsvcTimeStamp () + { + Date d = new Date(); + long t = d.getTime(); + secPastEpoch = (int)(t/1000); + nsec = (int)(t - secPastEpoch)*1000; + } + + /** + * Construct a time stamp with provided second and nano second fields + */ + public rsvcTimeStamp (int sec, int nsec) + { + secPastEpoch = sec + nsec/1000000000; + nsec = nsec - nsec/1000000000 * 1000000000; + } + + // all inherited functions + /** + * Return byte value of time stamp + */ + public byte byteValue () + { + return (byte)secPastEpoch; + } + + /** + * Return short value of time stamp + */ + public short shortValue () + { + return (short)secPastEpoch; + } + + /** + * Return integer value of time stamp + */ + public int intValue () + { + return secPastEpoch; + } + + /** + * Return long value of time stamp + */ + public long longValue () + { + return (long)secPastEpoch; + } + + /** + * Return float value of time stamp + */ + public float floatValue () + { + return (secPastEpoch + nsec/(float)1000000000.0); + } + + /** + * Return double value of time stamp + */ + public double doubleValue () + { + return (secPastEpoch + nsec/1000000000.0); + } + + /** + * Return string representation + */ + public String toString () + { + Date d = new Date ((long)((long)secPastEpoch*1000)); + return d.toString(); + } + +} + diff --git a/extensions/cdevGenericServer/NameServer/java/rsvcUdpClient.java b/extensions/cdevGenericServer/NameServer/java/rsvcUdpClient.java new file mode 100644 index 0000000..c1e1af1 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/java/rsvcUdpClient.java @@ -0,0 +1,135 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 +//----------------------------------------------------------------------------- +// +// Description: +// RSVC UDP Client for Servers to update their time stamps +// +// Author: +// Jie Chen +// Jefferson Lab HPC Group +// +// Revision History: +// $Log: rsvcUdpClient.java,v $ +// Revision 1.1.1.1 2000/05/23 15:12:50 pal +// cdev_psi_1.7.2 +// +// Revision 1.1 1999/10/18 17:12:44 chen +// *** empty log message *** +// +// +// +import java.io.*; +import java.util.*; +import java.net.*; +import rsvcEvent; +import rsvcData; +import rsvcConfig; + +public final class rsvcUdpClient +{ + // UDP Socket + private DatagramSocket udpsocket_ = null; + // Destination address for packets + private InetAddress dest_ = null; + // Destination port for packets + private int port_ = 0; + + /** + * Construct an empty rsvcUdpClient Object + */ + public rsvcUdpClient () + { + // empty + } + + /** + * Override default finalize method.This allows Java virtual + * machine to clean up resource when this object is no longer + * needed. + */ + protected void finalize() throws Throwable + { + if (udpsocket_ != null) + udpsocket_.close (); + } + + /** + * Connect to a server that is on a given host at a given port + */ + public synchronized void connect (String host, int port) throws UnknownHostException, IOException + { + try { + udpsocket_ = new DatagramSocket (); + }catch (IOException e) { + System.err.println(e); + throw e; + } + + try { + dest_ = InetAddress.getByName (host); + }catch (UnknownHostException ue) { + throw ue; + } + port_ = port; + } + + /** + * A server that is being managed by RSVC sends a very simple data + * to the rsvcServer to manifest itself being alive. + * data is in the form of two tagged ("name", "domain") values or + * anything that will make up an index + */ + public synchronized int update (rsvcData data) throws IOException + { + if (udpsocket_ == null) + return rsvcConfig.RSVC_ERROR; + + rsvcEvent cbk = new rsvcEvent (data); + cbk.setOpcode (rsvcConfig.RSVC_SET); + cbk.setEventid (0); + + int datasize = cbk.streamSize (); + ByteArrayOutputStream baoutput = new ByteArrayOutputStream (datasize); + try { + cbk.streamOut (baoutput); + }catch (IOException e) { + throw e; + } + + // return underlying byte from this byteArrayStream + byte[] obuffer = baoutput.toByteArray (); + if (datasize != obuffer.length) { + throw new IOException ("Streamed out buffer size != original calculated stream size"); + } + + // construct a datapacket to send data out + DatagramPacket packet = new DatagramPacket (obuffer, datasize, + dest_, port_); + + try { + udpsocket_.send (packet); + } catch (IOException e) { + throw e; + } + return rsvcConfig.RSVC_SUCCESS; + } + + /** + * Shutdown connection (close socket) + */ + public void disconnect () + { + if (udpsocket_ != null) + udpsocket_.close (); + } + + +} + diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/lex.yy.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/lex.yy.o new file mode 100644 index 0000000..5e36ec9 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/lex.yy.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcAcceptor.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcAcceptor.o new file mode 100644 index 0000000..1e2fc19 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcAcceptor.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcCacheData.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcCacheData.o new file mode 100644 index 0000000..8bd2c6a Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcCacheData.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcCacheDataAttr.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcCacheDataAttr.o new file mode 100644 index 0000000..74d5564 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcCacheDataAttr.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcCallback.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcCallback.o new file mode 100644 index 0000000..09dc0ba Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcCallback.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcCbk.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcCbk.o new file mode 100644 index 0000000..f3846fd Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcCbk.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcClient.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcClient.o new file mode 100644 index 0000000..099ba28 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcClient.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcData.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcData.o new file mode 100644 index 0000000..0ae5959 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcData.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcDataEntry.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcDataEntry.o new file mode 100644 index 0000000..56cc369 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcDataEntry.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcDataStore.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcDataStore.o new file mode 100644 index 0000000..c6b4f7e Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcDataStore.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcDataStoreMem.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcDataStoreMem.o new file mode 100644 index 0000000..2f4c37b Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcDataStoreMem.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcDataStoreTable.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcDataStoreTable.o new file mode 100644 index 0000000..e3ca79e Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcDataStoreTable.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcDataStreamer.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcDataStreamer.o new file mode 100644 index 0000000..e755104 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcDataStreamer.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcHSlist.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcHSlist.o new file mode 100644 index 0000000..15884f9 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcHSlist.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcHash.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcHash.o new file mode 100644 index 0000000..2b27f15 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcHash.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcHashable.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcHashable.o new file mode 100644 index 0000000..bb43093 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcHashable.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcIO.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcIO.o new file mode 100644 index 0000000..753e13d Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcIO.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcLocalConfig.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcLocalConfig.o new file mode 100644 index 0000000..2ed694a Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcLocalConfig.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcLogicQEng.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcLogicQEng.o new file mode 100644 index 0000000..e598e22 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcLogicQEng.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcLogicSup.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcLogicSup.o new file mode 100644 index 0000000..28ad876 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcLogicSup.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcNetData.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcNetData.o new file mode 100644 index 0000000..7bcf541 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcNetData.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcServer.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcServer.o new file mode 100644 index 0000000..66fa251 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcServer.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcServerConfig.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcServerConfig.o new file mode 100644 index 0000000..2752992 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcServerConfig.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcServerStore.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcServerStore.o new file mode 100644 index 0000000..55914fc Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcServerStore.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcSignal.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcSignal.o new file mode 100644 index 0000000..a76b34a Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcSignal.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcSlist.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcSlist.o new file mode 100644 index 0000000..cef9632 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcSlist.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcStreamMsg.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcStreamMsg.o new file mode 100644 index 0000000..eb912b0 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcStreamMsg.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcStreamable.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcStreamable.o new file mode 100644 index 0000000..04bf964 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcStreamable.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcTableDef.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcTableDef.o new file mode 100644 index 0000000..b1af2ec Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcTableDef.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcUdpClient.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcUdpClient.o new file mode 100644 index 0000000..29fe082 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcUdpClient.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcUdpHandler.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcUdpHandler.o new file mode 100644 index 0000000..6a209be Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcUdpHandler.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcVirtualDbase.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcVirtualDbase.o new file mode 100644 index 0000000..7ef2de4 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/rsvcVirtualDbase.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.obj/Linux/y.tab.o b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/y.tab.o new file mode 100644 index 0000000..f369b33 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.obj/Linux/y.tab.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/lex.yy.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/lex.yy.o new file mode 100644 index 0000000..17ee081 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/lex.yy.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcAcceptor.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcAcceptor.o new file mode 100644 index 0000000..e698f45 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcAcceptor.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcCacheData.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcCacheData.o new file mode 100644 index 0000000..36f7bd7 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcCacheData.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcCacheDataAttr.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcCacheDataAttr.o new file mode 100644 index 0000000..8a6f953 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcCacheDataAttr.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcCallback.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcCallback.o new file mode 100644 index 0000000..65bd721 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcCallback.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcCbk.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcCbk.o new file mode 100644 index 0000000..0defab1 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcCbk.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcClient.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcClient.o new file mode 100644 index 0000000..0b6275a Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcClient.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcData.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcData.o new file mode 100644 index 0000000..e6353a3 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcData.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcDataEntry.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcDataEntry.o new file mode 100644 index 0000000..507cd3d Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcDataEntry.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcDataStore.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcDataStore.o new file mode 100644 index 0000000..284425a Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcDataStore.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcDataStoreMem.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcDataStoreMem.o new file mode 100644 index 0000000..628cd97 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcDataStoreMem.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcDataStoreTable.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcDataStoreTable.o new file mode 100644 index 0000000..7acdccc Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcDataStoreTable.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcDataStreamer.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcDataStreamer.o new file mode 100644 index 0000000..a04fc6b Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcDataStreamer.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcHSlist.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcHSlist.o new file mode 100644 index 0000000..6a79aca Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcHSlist.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcHash.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcHash.o new file mode 100644 index 0000000..9182008 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcHash.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcHashable.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcHashable.o new file mode 100644 index 0000000..0307f76 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcHashable.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcIO.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcIO.o new file mode 100644 index 0000000..5a1faf5 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcIO.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcLocalConfig.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcLocalConfig.o new file mode 100644 index 0000000..0974b3d Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcLocalConfig.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcLogicQEng.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcLogicQEng.o new file mode 100644 index 0000000..8858843 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcLogicQEng.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcLogicSup.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcLogicSup.o new file mode 100644 index 0000000..9a168b6 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcLogicSup.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcNetData.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcNetData.o new file mode 100644 index 0000000..3f747a9 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcNetData.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcServer.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcServer.o new file mode 100644 index 0000000..48ebe8c Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcServer.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcServerConfig.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcServerConfig.o new file mode 100644 index 0000000..09b0fc7 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcServerConfig.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcServerStore.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcServerStore.o new file mode 100644 index 0000000..e31502f Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcServerStore.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcSignal.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcSignal.o new file mode 100644 index 0000000..5421da4 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcSignal.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcSlist.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcSlist.o new file mode 100644 index 0000000..ec1e9be Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcSlist.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcStreamMsg.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcStreamMsg.o new file mode 100644 index 0000000..c810a15 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcStreamMsg.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcStreamable.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcStreamable.o new file mode 100644 index 0000000..5b462cb Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcStreamable.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcTableDef.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcTableDef.o new file mode 100644 index 0000000..81897e0 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcTableDef.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcUdpClient.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcUdpClient.o new file mode 100644 index 0000000..86bdb28 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcUdpClient.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcUdpHandler.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcUdpHandler.o new file mode 100644 index 0000000..987c87e Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcUdpHandler.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcVirtualDbase.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcVirtualDbase.o new file mode 100644 index 0000000..edb5cf6 Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/rsvcVirtualDbase.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/y.tab.o b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/y.tab.o new file mode 100644 index 0000000..2de5ffd Binary files /dev/null and b/extensions/cdevGenericServer/NameServer/src/.shobj/Linux/y.tab.o differ diff --git a/extensions/cdevGenericServer/NameServer/src/Makefile b/extensions/cdevGenericServer/NameServer/src/Makefile new file mode 100755 index 0000000..eff45e5 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/Makefile @@ -0,0 +1,84 @@ +ARCH = OS +SHOBJ = YES + +include ../../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Resource Name Server and Library" + +OBJS = $(OBJDIR)/rsvcDataStreamer.o \ + $(OBJDIR)/rsvcDataEntry.o \ + $(OBJDIR)/rsvcData.o \ + $(OBJDIR)/rsvcVirtualDbase.o \ + $(OBJDIR)/rsvcServerConfig.o \ + $(OBJDIR)/rsvcTableDef.o \ + $(OBJDIR)/rsvcHashable.o \ + $(OBJDIR)/rsvcStreamable.o \ + $(OBJDIR)/rsvcCbk.o \ + $(OBJDIR)/rsvcSlist.o \ + $(OBJDIR)/rsvcHSlist.o \ + $(OBJDIR)/rsvcHash.o \ + $(OBJDIR)/lex.yy.o \ + $(OBJDIR)/y.tab.o \ + $(OBJDIR)/rsvcLogicSup.o \ + $(OBJDIR)/rsvcLogicQEng.o \ + $(OBJDIR)/rsvcNetData.o \ + $(OBJDIR)/rsvcDataStore.o \ + $(OBJDIR)/rsvcDataStoreMem.o \ + $(OBJDIR)/rsvcServerStore.o \ + $(OBJDIR)/rsvcDataStoreTable.o \ + $(OBJDIR)/rsvcCacheData.o \ + $(OBJDIR)/rsvcCacheDataAttr.o \ + $(OBJDIR)/rsvcStreamMsg.o \ + $(OBJDIR)/rsvcAcceptor.o \ + $(OBJDIR)/rsvcIO.o \ + $(OBJDIR)/rsvcUdpHandler.o \ + $(OBJDIR)/rsvcLocalConfig.o + +CLNTOBJS = $(OBJDIR)/rsvcSlist.o \ + $(OBJDIR)/rsvcHSlist.o \ + $(OBJDIR)/rsvcHash.o \ + $(OBJDIR)/rsvcDataStreamer.o \ + $(OBJDIR)/rsvcDataEntry.o \ + $(OBJDIR)/rsvcData.o \ + $(OBJDIR)/rsvcNetData.o \ + $(OBJDIR)/rsvcCbk.o \ + $(OBJDIR)/rsvcHashable.o \ + $(OBJDIR)/rsvcStreamable.o \ + $(OBJDIR)/rsvcCallback.o \ + $(OBJDIR)/rsvcClient.o \ + $(OBJDIR)/rsvcUdpClient.o + +ifeq ($(SHOBJ),YES) + TARGETS = $(BASELIB)/librsvc.$(SHARED_EXT) $(CDEVBIN)/rsvcServer +else + TARGETS = $(BASELIB)/librsvc.a $(CDEVBIN)/rsvcServer +endif + +CXXEXTRA = -D_CDEV_MANAGE_SERVERS +CCEXTRA = -w +CXXINCLUDES = -I./ +LIBS = -L$(CDEVLIB) -lcdevReactor $(OSLIBS) +BINARIES = $(BASEBIN)/rsvcServer $(BASELIB)/librsvc.$(SHARED_EXT) $(BASELIB)/librsvc.a lex.yy.c y.tab.c + +targets : $(TARGETS) + +$(CDEVBIN)/rsvcServer: $(OBJDIR)/rsvcServer.o $(OBJDIR)/rsvcSignal.o $(OBJS) + $(LINK.cc) $^ $(LIBS) -o $@ + +$(BASELIB)/librsvc.a: $(CLNTOBJS) + $(LINK.a) $@ $^ + @$(RANLIB) $@ > /dev/null + @cp $@ $(CDEVLIB) + +$(BASELIB)/librsvc.$(SHARED_EXT): $(CLNTOBJS) + $(LINK.so) -o $@ $^ $(NETLIBS) + @cp $@ $(CDEVLIB) + +lex.yy.c : rsvc_logic.l + $(LEX_CMD_ECHO)\ + $(LEX) rsvc_logic.l + +y.tab.c : rsvc_logic.y + $(YACC_CMD_ECHO)\ + $(YACC) -d rsvc_logic.y + diff --git a/extensions/cdevGenericServer/NameServer/src/NMakefile.mak b/extensions/cdevGenericServer/NameServer/src/NMakefile.mak new file mode 100755 index 0000000..ad31895 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/NMakefile.mak @@ -0,0 +1,97 @@ +.SUFFIXES: .cc .obj + +ARCH = WINNT-4.0 +SHOBJ = YES +APPNAME = CDEV Resource Name Server + +# ****************************************************************************** +# * The BINARIES definition names all of the binary files that should be deleted +# * whenever "make clean" is executed. +# ****************************************************************************** +BINARIES = $(BASEBIN)\rsvcServer.exe \ + $(CDEVLIB)\rsvc.dll \ + $(CDEVLIB)\rsvc.lib + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +SERVEROBJS = .exec\$(TARGETDIR)\rsvcServer.obj \ + .exec\$(TARGETDIR)\rsvcSignal.obj \ + .exec\$(TARGETDIR)\rsvcDataStreamer.obj \ + .exec\$(TARGETDIR)\rsvcDataEntry.obj \ + .exec\$(TARGETDIR)\rsvcData.obj \ + .exec\$(TARGETDIR)\rsvcVirtualDbase.obj \ + .exec\$(TARGETDIR)\rsvcServerConfig.obj \ + .exec\$(TARGETDIR)\rsvcTableDef.obj \ + .exec\$(TARGETDIR)\rsvcHashable.obj \ + .exec\$(TARGETDIR)\rsvcStreamable.obj \ + .exec\$(TARGETDIR)\rsvcCbk.obj \ + .exec\$(TARGETDIR)\rsvcSlist.obj \ + .exec\$(TARGETDIR)\rsvcHSlist.obj \ + .exec\$(TARGETDIR)\rsvcHash.obj \ + .exec\$(TARGETDIR)\lex-nt.obj \ + .exec\$(TARGETDIR)\yacc-nt.obj \ + .exec\$(TARGETDIR)\rsvcLogicSup.obj \ + .exec\$(TARGETDIR)\rsvcLogicQEng.obj \ + .exec\$(TARGETDIR)\rsvcNetData.obj \ + .exec\$(TARGETDIR)\rsvcDataStore.obj \ + .exec\$(TARGETDIR)\rsvcDataStoreMem.obj \ + .exec\$(TARGETDIR)\rsvcServerStore.obj \ + .exec\$(TARGETDIR)\rsvcDataStoreTable.obj \ + .exec\$(TARGETDIR)\rsvcCacheData.obj \ + .exec\$(TARGETDIR)\rsvcCacheDataAttr.obj \ + .exec\$(TARGETDIR)\rsvcStreamMsg.obj \ + .exec\$(TARGETDIR)\rsvcAcceptor.obj \ + .exec\$(TARGETDIR)\rsvcIO.obj \ + .exec\$(TARGETDIR)\rsvcUdpHandler.obj \ + .exec\$(TARGETDIR)\rsvcLocalConfig.obj + + +CLIENTOBJS = $(OBJDIR)\rsvcSlist.obj \ + $(OBJDIR)\rsvcHSlist.obj \ + $(OBJDIR)\rsvcHash.obj \ + $(OBJDIR)\rsvcDataStreamer.obj \ + $(OBJDIR)\rsvcDataEntry.obj \ + $(OBJDIR)\rsvcData.obj \ + $(OBJDIR)\rsvcNetData.obj \ + $(OBJDIR)\rsvcCbk.obj \ + $(OBJDIR)\rsvcHashable.obj \ + $(OBJDIR)\rsvcStreamable.obj \ + $(OBJDIR)\rsvcCallback.obj \ + $(OBJDIR)\rsvcClient.obj \ + $(OBJDIR)\rsvcUdpClient.obj + +CXXEXTRA = /D "_CDEV_MANAGE_SERVERS=1" +CXXEXTRA_DLL = /D "_RSVC_CORE_EXPORTS_=1" +CXXEXTRA_EXE = /D "_RSVC_BUILD_EXE=1" +CXXINCLUDES = -I./ + +!IF "$(SHOBJ)" == "YES" +TARGETS = $(CDEVLIB)\rsvc.dll $(CDEVBIN)\rsvcServer.exe +!ELSE +TARGETS = $(CDEVLIB)\rsvc.lib $(CDEVBIN)\rsvcServer.exe +!ENDIF + +targets : $(TARGETS) + +$(CDEVBIN)\rsvcServer.exe : $(SERVEROBJS) + @echo =^> Building $(@F) + @echo =^> Objects: $(?F) + -@if exist $@ erase $@ + $(LINK) $(CDEVLIB)\cdevReactor.lib \ + $(LINK_EXE_FLAGS) /out:$@ \ + $(SERVEROBJS) + @echo ^<= Done... + +$(CDEVLIB)\rsvc.lib : $(CLIENTOBJS) + @echo =^> Building $(@F) + @echo =^> Objects: $(?F) + -@if exist $@ erase $@ + $(LIB32) $(LINK_LIB_FLAGS) /out:$@ $(CLIENTOBJS) + @echo ^<= Done... + +$(CDEVLIB)\rsvc.dll : $(CLIENTOBJS) + @echo =^> Building $(@F) + @echo =^> Objects: $(?F) + -@if exist $@ erase $@ + $(LIB32) $(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $(CLIENTOBJS) + @echo ^<= Done... diff --git a/extensions/cdevGenericServer/NameServer/src/header.h b/extensions/cdevGenericServer/NameServer/src/header.h new file mode 100755 index 0000000..0d5bb2e --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/header.h @@ -0,0 +1,16 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// +// +// Author: Jie Chen +// +// +// diff --git a/extensions/cdevGenericServer/NameServer/src/lex-nt.c b/extensions/cdevGenericServer/NameServer/src/lex-nt.c new file mode 100644 index 0000000..95a2996 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/lex-nt.c @@ -0,0 +1,1695 @@ +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/pss060/sls/controls/CVSROOT/PACKAGES/cdev/cdev_psi_1.7.2/cdev_1.7.2/extensions/cdevGenericServer/NameServer/src/lex-nt.c,v 1.1.1.1 2000/05/23 15:12:50 pal Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 19 +#define YY_END_OF_BUFFER 20 +static yyconst short int yy_accept[39] = + { 0, + 0, 0, 0, 0, 20, 18, 17, 19, 11, 18, + 18, 7, 8, 18, 18, 13, 2, 18, 3, 15, + 15, 18, 4, 10, 0, 16, 0, 13, 14, 5, + 1, 6, 15, 15, 9, 15, 12, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 5, 1, 1, 1, 6, 7, 8, + 9, 1, 1, 1, 10, 11, 1, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 1, 1, 13, + 14, 15, 1, 1, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 1, 1, 1, 1, 5, 1, 16, 16, 16, 16, + + 17, 16, 16, 16, 18, 16, 19, 20, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 1, 21, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[22] = + { 0, + 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, + 1 + } ; + +static yyconst short int yy_base[41] = + { 0, + 0, 0, 0, 0, 47, 48, 48, 48, 32, 39, + 19, 48, 48, 12, 32, 16, 29, 28, 27, 0, + 22, 18, 48, 48, 22, 48, 26, 19, 25, 48, + 48, 48, 0, 17, 48, 18, 0, 48, 31, 32 + } ; + +static yyconst short int yy_def[41] = + { 0, + 38, 1, 1, 1, 38, 38, 38, 38, 38, 38, + 39, 38, 38, 38, 38, 38, 38, 38, 38, 40, + 40, 38, 38, 38, 39, 38, 38, 38, 38, 38, + 38, 38, 40, 40, 38, 40, 40, 0, 38, 38 + } ; + +static yyconst short int yy_nxt[70] = + { 0, + 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 20, 20, 20, 21, + 22, 26, 27, 28, 26, 26, 27, 28, 26, 27, + 28, 25, 25, 33, 37, 36, 29, 29, 35, 34, + 32, 31, 30, 29, 24, 23, 38, 5, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38 + } ; + +static yyconst short int yy_chk[70] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 11, 14, 14, 25, 11, 16, 16, 25, 28, + 28, 39, 39, 40, 36, 34, 29, 27, 22, 21, + 19, 18, 17, 15, 10, 9, 5, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +char *yytext; +#line 1 "rsvc_logic.l" +#define INITIAL 0 +/*---------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// Description: +// Lexer for rsvc logic expression +// +// Author: jie chen +// +// +// +//---------------------------------------------------------------------------*/ +#line 19 "rsvc_logic.l" +#include +#include +#include + +#if defined (__VMS) +/* Assume we are using BISON as our yacc compiler if this is a VMS platform.*/ +#define _BISON_YACC +#endif + +#ifdef _BISON_YACC +/* When using gnu bison, bison produces ns_tab.c, not y.tab.h. + (also, can't have two periods in a filename under VMS). */ +#include "rsvc_logic_tab.c" +#else +#include "y.tab.h" +#endif + +static char *_logic_input_text = 0; + +void +set_input_text (char* text) +{ + _logic_input_text = text; +} + +#ifdef FLEX_SCANNER +/* Flex defines yywrap() as a macro by default. + We define it below (in rsvc_logic) as a function, so we must undefine it + here first. */ +#ifdef yywrap +#undef yywrap +#endif + +/* The flex manual states that the flex implementation does not permit + input() to be redefined. This is because input() in FLEX is a function, + not a macro. + + The flex manual also states that the proper thing to do in flex is + redefine the macro YY_INPUT, which is what we do below. + + unput() is also a function in flex, but since we are now using + YYINPUT(), hopefully unput() will work correctly. */ + +#ifdef YY_INPUT +#undef YY_INPUT +#endif +#define YY_INPUT(buf,result,max_size) { \ + int text_left = strlen(_logic_input_text) ; /* get length of input. */ \ + (result) = ((max_size) +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 89 "rsvc_logic.l" + + +#line 615 "lex.yy.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 39 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 48 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 91 "rsvc_logic.l" +{return EQUAL; } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 92 "rsvc_logic.l" +{return LESS; } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 93 "rsvc_logic.l" +{return GREATER; } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 94 "rsvc_logic.l" +{return NOTEQUAL; } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 95 "rsvc_logic.l" +{return LESSOREQUAL;} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 96 "rsvc_logic.l" +{return GREATEROREQUAL;} + YY_BREAK +case 7: +YY_RULE_SETUP +#line 97 "rsvc_logic.l" +{return LEFTP;} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 98 "rsvc_logic.l" +{return RIGHTP;} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 99 "rsvc_logic.l" +{return OR;} + YY_BREAK +case 10: +YY_RULE_SETUP +#line 100 "rsvc_logic.l" +{return AND;} + YY_BREAK +case 11: +YY_RULE_SETUP +#line 101 "rsvc_logic.l" +{return NOT;} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 102 "rsvc_logic.l" +{return LIKE;} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 103 "rsvc_logic.l" +{yylval.data = new_logic_data (); + logic_data_assign_int (yylval.data, atoi (yytext)); + return IVALUE; + } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 107 "rsvc_logic.l" +{yylval.data = new_logic_data (); + logic_data_assign_dbl (yylval.data, atof (yytext)); + return DVALUE; + } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 111 "rsvc_logic.l" +{yylval.data = new_logic_data (); + logic_data_assign_str (yylval.data, yytext); + return TAGNAME; } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 114 "rsvc_logic.l" +{yylval.data = new_logic_data (); + logic_data_assign_str (yylval.data, yytext + 1); + if (yylval.data->u.string[yyleng - 2] != '\'') { + printf ("Unterminated char string %s\n", yytext); + return CERROR; + } + else + yylval.data->u.string[yyleng - 2] = '\0'; + return CSTRING; + } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 125 "rsvc_logic.l" +; + YY_BREAK +case 18: +YY_RULE_SETUP +#line 126 "rsvc_logic.l" +{fprintf(stdout,"unrecognized char %02x\n",yytext[0]);} + YY_BREAK +case 19: +YY_RULE_SETUP +#line 127 "rsvc_logic.l" +ECHO; + YY_BREAK +#line 810 "lex.yy.c" +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMENT): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a singled characater, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 39 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 39 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 38); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + yytext_ptr = yy_c_buf_p; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + { + yy_c_buf_p = + yytext_ptr + YY_MORE_ADJ; + return EOF; + } + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *str ) +#else +YY_BUFFER_STATE yy_scan_string( str ) +yyconst char *str; +#endif + { + int len; + for ( len = 0; str[len]; ++len ) + ; + + return yy_scan_bytes( str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n - YY_MORE_ADJ; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 127 "rsvc_logic.l" + + +#ifdef __cplusplus +void yyerror() +#elif defined(_BISON_YACC) +/* BISON produces calls to a yyerror function that takes a single char *. + Since yyerror is not previously declared, the compiler assumes that + yyerror must be of type "int yyerror( char * c )" */ +int yyerror( char * c ) +#else +yyerror() +#endif +{ + fprintf(stderr, "syntax error for logical expression\n"); +} + +#if defined(__cplusplus) +int yywrap(void) +#else +yywrap() +#endif +{ + return EOF; +} + diff --git a/extensions/cdevGenericServer/NameServer/src/lex.yy.c b/extensions/cdevGenericServer/NameServer/src/lex.yy.c new file mode 100644 index 0000000..d6c5a16 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/lex.yy.c @@ -0,0 +1,1722 @@ +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 19 +#define YY_END_OF_BUFFER 20 +static yyconst short int yy_accept[39] = + { 0, + 0, 0, 0, 0, 20, 18, 17, 19, 11, 18, + 18, 7, 8, 18, 18, 13, 2, 18, 3, 15, + 15, 18, 4, 10, 0, 16, 0, 13, 14, 5, + 1, 6, 15, 15, 9, 15, 12, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 5, 1, 1, 1, 6, 7, 8, + 9, 1, 1, 1, 10, 11, 1, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 1, 1, 13, + 14, 15, 1, 1, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 1, 1, 1, 1, 5, 1, 16, 16, 16, 16, + + 17, 16, 16, 16, 18, 16, 19, 20, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 1, 21, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[22] = + { 0, + 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, + 1 + } ; + +static yyconst short int yy_base[41] = + { 0, + 0, 0, 0, 0, 47, 48, 48, 48, 32, 39, + 19, 48, 48, 12, 32, 16, 29, 28, 27, 0, + 22, 18, 48, 48, 22, 48, 26, 19, 25, 48, + 48, 48, 0, 17, 48, 18, 0, 48, 31, 32 + } ; + +static yyconst short int yy_def[41] = + { 0, + 38, 1, 1, 1, 38, 38, 38, 38, 38, 38, + 39, 38, 38, 38, 38, 38, 38, 38, 38, 40, + 40, 38, 38, 38, 39, 38, 38, 38, 38, 38, + 38, 38, 40, 40, 38, 40, 40, 0, 38, 38 + } ; + +static yyconst short int yy_nxt[70] = + { 0, + 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 20, 20, 20, 21, + 22, 26, 27, 28, 26, 26, 27, 28, 26, 27, + 28, 25, 25, 33, 37, 36, 29, 29, 35, 34, + 32, 31, 30, 29, 24, 23, 38, 5, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38 + } ; + +static yyconst short int yy_chk[70] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 11, 14, 14, 25, 11, 16, 16, 25, 28, + 28, 39, 39, 40, 36, 34, 29, 27, 22, 21, + 19, 18, 17, 15, 10, 9, 5, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "rsvc_logic.l" +#define INITIAL 0 +/*---------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// Description: +// Lexer for rsvc logic expression +// +// Author: jie chen +// +// +// +//---------------------------------------------------------------------------*/ +#line 19 "rsvc_logic.l" +#include +#include +#include + +#if defined (__VMS) +/* Assume we are using BISON as our yacc compiler if this is a VMS platform.*/ +#define _BISON_YACC +#endif + +#ifdef _BISON_YACC +/* When using gnu bison, bison produces ns_tab.c, not y.tab.h. + (also, can't have two periods in a filename under VMS). */ +#include "rsvc_logic_tab.c" +#else +#include "y.tab.h" +#endif + +static char *_logic_input_text = 0; + +void +set_input_text (char* text) +{ + _logic_input_text = text; +} + +#ifdef FLEX_SCANNER +/* Flex defines yywrap() as a macro by default. + We define it below (in rsvc_logic) as a function, so we must undefine it + here first. */ +#ifdef yywrap +#undef yywrap +#endif + +/* The flex manual states that the flex implementation does not permit + input() to be redefined. This is because input() in FLEX is a function, + not a macro. + + The flex manual also states that the proper thing to do in flex is + redefine the macro YY_INPUT, which is what we do below. + + unput() is also a function in flex, but since we are now using + YYINPUT(), hopefully unput() will work correctly. */ + +#ifdef YY_INPUT +#undef YY_INPUT +#endif +#define YY_INPUT(buf,result,max_size) { \ + int text_left = strlen(_logic_input_text) ; /* get length of input. */ \ + (result) = ((max_size) +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp = NULL, *yy_bp = NULL; + register int yy_act; + +#line 89 "rsvc_logic.l" + + +#line 621 "lex.yy.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 39 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 48 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 91 "rsvc_logic.l" +{return EQUAL; } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 92 "rsvc_logic.l" +{return LESS; } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 93 "rsvc_logic.l" +{return GREATER; } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 94 "rsvc_logic.l" +{return NOTEQUAL; } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 95 "rsvc_logic.l" +{return LESSOREQUAL;} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 96 "rsvc_logic.l" +{return GREATEROREQUAL;} + YY_BREAK +case 7: +YY_RULE_SETUP +#line 97 "rsvc_logic.l" +{return LEFTP;} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 98 "rsvc_logic.l" +{return RIGHTP;} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 99 "rsvc_logic.l" +{return OR;} + YY_BREAK +case 10: +YY_RULE_SETUP +#line 100 "rsvc_logic.l" +{return AND;} + YY_BREAK +case 11: +YY_RULE_SETUP +#line 101 "rsvc_logic.l" +{return NOT;} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 102 "rsvc_logic.l" +{return LIKE;} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 103 "rsvc_logic.l" +{yylval.data = new_logic_data (); + logic_data_assign_int (yylval.data, atoi (yytext)); + return IVALUE; + } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 107 "rsvc_logic.l" +{yylval.data = new_logic_data (); + logic_data_assign_dbl (yylval.data, atof (yytext)); + return DVALUE; + } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 111 "rsvc_logic.l" +{yylval.data = new_logic_data (); + logic_data_assign_str (yylval.data, yytext); + return TAGNAME; } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 114 "rsvc_logic.l" +{yylval.data = new_logic_data (); + logic_data_assign_str (yylval.data, yytext + 1); + if (yylval.data->u.string[yyleng - 2] != '\'') { + printf ("Unterminated char string %s\n", yytext); + return CERROR; + } + else + yylval.data->u.string[yyleng - 2] = '\0'; + return CSTRING; + } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 125 "rsvc_logic.l" +; + YY_BREAK +case 18: +YY_RULE_SETUP +#line 126 "rsvc_logic.l" +{fprintf(stdout,"unrecognized char %02x\n",yytext[0]);} + YY_BREAK +case 19: +YY_RULE_SETUP +#line 127 "rsvc_logic.l" +ECHO; + YY_BREAK +#line 816 "lex.yy.c" +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMENT): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 39 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 39 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 38); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 127 "rsvc_logic.l" + + +#ifdef __cplusplus +void yyerror() +#elif defined(_BISON_YACC) +/* BISON produces calls to a yyerror function that takes a single char *. + Since yyerror is not previously declared, the compiler assumes that + yyerror must be of type "int yyerror( char * c )" */ +int yyerror( char * c ) +#else +yyerror() +#endif +{ + fprintf(stderr, "syntax error for logical expression\n"); +} + +#if defined(__cplusplus) +int yywrap(void) +#else +yywrap() +#endif +{ + return EOF; +} + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcAcceptor.cc b/extensions/cdevGenericServer/NameServer/src/rsvcAcceptor.cc new file mode 100755 index 0000000..aebd151 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcAcceptor.cc @@ -0,0 +1,195 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcAcceptor Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcAcceptor.cc,v +// Revision 1.3 1998/02/26 19:08:20 chen +// add list lock to prevent rsvcIO from deleting itself twice +// +// Revision 1.2 1998/02/25 19:52:41 chen +// minor change +// +// Revision 1.1 1998/01/22 17:07:57 akers +// Addition of new NameServer +// +// +// +#include +#include "rsvcAcceptor.h" +#include "rsvcIO.h" + +rsvcAcceptor::rsvcAcceptor (cdevReactor & r, rsvcDataStoreTable& st) +:cdevEventHandler (), listener_ (), reactor_ (r), + connectionList_ (), storeTable_ (st), listLock_ (0) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcAcceptor Class Object\n"); +#endif +} + +rsvcAcceptor::~rsvcAcceptor (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete rsvcAcceptor Class Object\n"); +#endif + listLock_ = 1; + // delete all clients + deleteAllConnections (); + + listLock_ = 0; + + // close sockets + handleClose (); +} + +int +rsvcAcceptor::handleClose ( void ) +{ + return listener_.close (); +} + +int +rsvcAcceptor::getHandle (void) const +{ + return listener_.getHandle (); +} + + +int +rsvcAcceptor::handleInput ( void ) +{ + cdevInetAddr rem_addr; + + rsvcIO* client = new rsvcIO (reactor_, this, storeTable_); + + if (listener_.accept (*client, &rem_addr) != -1) { + printf ("Receivied client connection from host %s at port %d\n", + rem_addr.getHostName (), client->getHandle ()); + + // remember client address + client->peerAddr (rem_addr); + + // set socket options to KEEP_ALIVE + int alive = 1; + client->setSockOption (SOL_SOCKET, SO_KEEPALIVE, + (void *)&alive, sizeof (alive)); + + +/* int sendsize = 4096; + client->setSockOption (SOL_SOCKET, SO_SNDBUF, (void *)&sendsize, + sizeof (sendsize)); +*/ + + // register client to reactor + int event_mask = cdevEventHandler::READ_MASK; + + if (reactor_.registerHandler (client, event_mask) == -1) { + printf ("Unable to register rsvcIO handler\n"); + return -1; + } + connectionList_.add ((void *)client); + + // enable non block io + client->enable (O_NONBLOCK); + } + else { + printf ("rsvcAcceptor accepting client connection failed\n"); + return -1; + } + return 0; +} + + + +int +rsvcAcceptor::open (unsigned short port) +{ + printf ("RSVC: Create TCP listening port at %d\n", port); + cdevInetAddr addr (port); + + // reuse address option + if (listener_.open (addr, 1) == -1) + return -1; + else if (listener_.setFlags (O_NONBLOCK) == -1) + return -1; + else + return 0; +} + +unsigned short +rsvcAcceptor::port_number (void) +{ + cdevInetAddr addr; + + listener_.getLocalAddress (addr); + + // port number is in the host byte order + return addr.getPortNum (); +} + +int +rsvcAcceptor::numberConnections (void) +{ + return connectionList_.count (); +} + +int +rsvcAcceptor::remove (rsvcIO* client) +{ + return connectionList_.remove ((void *)client); +} + +int +rsvcAcceptor::includes (rsvcIO* client) +{ + return connectionList_.includes ((void *)client); +} + +int +rsvcAcceptor::sendToAllConnections (rsvcNetData* data) +{ + rsvcSlistIterator ite (connectionList_); + rsvcIO* io = 0; + int status = RSVC_SUCCESS; + + for (ite.init (); !ite; ++ite) { + io = (rsvcIO *) ite (); + if (io->sendToPeer (data) != RSVC_SUCCESS) + status = RSVC_ERROR; + } + return status; +} + +void +rsvcAcceptor::deleteAllConnections (void) +{ + rsvcSlistIterator ite (connectionList_); + rsvcIO* io = 0; + int status = RSVC_SUCCESS; + + for (ite.init (); !ite; ++ite) { + io = (rsvcIO *) ite (); + delete io; + } +} + +rsvcSlist& +rsvcAcceptor::connectionList (void) +{ + return connectionList_; +} + + + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcAcceptor.h b/extensions/cdevGenericServer/NameServer/src/rsvcAcceptor.h new file mode 100755 index 0000000..0776d76 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcAcceptor.h @@ -0,0 +1,90 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC TCP Connection Acceptor +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_ACCEPTOR_H +#define _RSVC_ACCEPTOR_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +class rsvcIO; + +class rsvcAcceptor : public cdevEventHandler +{ +public: + // constructor: deny direct instantiation + rsvcAcceptor (cdevReactor& reactor, + rsvcDataStoreTable& table); + + // destructor + ~rsvcAcceptor (void); + + // open local address + int open (unsigned short port); + // return number of IO connections + int numberConnections (void); + // remove a connection from the list + int remove (rsvcIO* channel); + // check whether a rsvcIO is in this list + int includes (rsvcIO* channel); + + + // send a result to all clients + int sendToAllConnections (rsvcNetData* data); + + // return port number + unsigned short port_number (void); + + // return all connection list + rsvcSlist& connectionList (void); + +protected: + // inherited operations + int getHandle (void) const; + int handleClose (void); + + // inherited operations + int handleInput (void); + + // delete all clients : only used in the destructor + void deleteAllConnections (void); + + // data area + + cdevSocketAcceptor listener_; + cdevReactor & reactor_; + rsvcSlist connectionList_; + int listLock_; + + // global data store table + rsvcDataStoreTable& storeTable_; + + // friend class + friend class rsvcIO; +}; +#endif + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcCacheData.cc b/extensions/cdevGenericServer/NameServer/src/rsvcCacheData.cc new file mode 100755 index 0000000..e4d27d6 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcCacheData.cc @@ -0,0 +1,409 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of cached data in the RSVC Server +// +// Author: Jie Chen +// +// Revision History: +// rsvcCacheData.cc,v +// Revision 1.1 1998/01/22 17:07:58 akers +// Addition of new NameServer +// +// +// +#include "rsvcCacheData.h" +#include +#include +#include +#include + +rsvcCacheData::rsvcCacheData (rsvcData& data, rsvcVirtualDbase* dbase, + rsvcTableDef* table) +:rsvcHashable (), data_ (data), monitorTable_ (200, 5), + attributes_ (100, 5), database_ (dbase), table_ (table) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcCacheData Class Object\n"); +#endif + createAllAttrs (); +} + +rsvcCacheData::~rsvcCacheData (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete rsvcCacheData Class Object\n"); +#endif + removeAllMonitors (); + removeAllAttrs (); +} + +void +rsvcCacheData::removeAllMonitors (void) +{ + rsvcHashIterator ite (monitorTable_); + rsvcCbk* cbk = 0; + + for (ite.init (); !ite; ++ite) { + cbk = (rsvcCbk *)ite (); + delete cbk; + } + monitorTable_.deleteAllValues (); +} + +void +rsvcCacheData::removeAllAttrs (void) +{ + rsvcHashIterator ite (attributes_); + rsvcCacheDataAttr* attr; + + for (ite.init (); !ite; ++ite) { + attr = (rsvcCacheDataAttr *)ite (); + delete attr; + } + attributes_.deleteAllValues (); +} + +void +rsvcCacheData::createAllAttrs (void) +{ + rsvcCacheDataAttr* attr = 0; + rsvcDataEntry* entry = 0; + rsvcDataIterator ite (&data_); + + for (ite.init (); !ite; ++ite) { + entry = ite (); + if (strcmp (entry->tag_, rsvcServerConfig::table ()) != 0 && + strcmp (entry->tag_, rsvcServerConfig::key ()) != 0 && + strcmp (entry->tag_, rsvcServerConfig::keyType ()) != 0 && + strcmp (entry->tag_, rsvcServerConfig::keyExp ()) != 0 && + strcmp (entry->tag_, rsvcServerConfig::monitorTag ()) != 0 ){ + attr = new rsvcCacheDataAttr (entry->tag_, *this); + attributes_.add (attr); + } + } +} + +unsigned int +rsvcCacheData::hash (void) +{ + // return hash value + unsigned int h = 0; + // first get key type + int keytype = table_->keyType (); + + if (keytype != RSVC_STRING) { + void* keyvalue; + + if (data_.find (table_->keyName (), keyvalue) != RSVC_SUCCESS) { + // impossible to get here: data was created with key value checked + fprintf (stderr, "The rsvcCacheData has no key value with key name %s\n", + table_->keyName ()); + exit (1); + } + + size_t keysize; + if (keytype == RSVC_INT32) { + int tkey; + keysize = sizeof (int); + data_.get (table_->keyName (), &tkey); + keyvalue = (void *)&tkey; + } + else if (keytype == RSVC_FLOAT) { + float tkey; + keysize = sizeof (float); + data_.get (table_->keyName (), &tkey); + keyvalue = (void *)&tkey; + } + else { + double tkey; + keysize = sizeof (double); + data_.get (table_->keyName (), &tkey); + keyvalue = (void *)&tkey; + } + + unsigned char *k, *e; + + k = (unsigned char *)keyvalue; + e = k + keysize; + for (h = 0; k < e; ++k) { + h *= 16777619; + h ^= *k; + } + } + else { + char keyvalue[1024]; + unsigned int g; + + if (data_.get (table_->keyName (), keyvalue, sizeof (keyvalue)) + != RSVC_SUCCESS) { + // impossible to get here: data was created with key value checked + fprintf (stderr, "The rsvcCacheData has no key value with key name %s\n", + table_->keyName ()); + exit (1); + } + + for (int i = 0; keyvalue[i] != '\0'; i++){ + h = (h << 4) + keyvalue[i]; + // assume 32 bit integer + if (g = h & 0xf0000000){ + h ^= g >> 24; + h ^= g; + } + } + } + return h; +} + +int +rsvcCacheData::sameKey (rsvcCacheData* key) +{ + // first get key type + int keytype = table_->keyType (); + rsvcData& data1 = key->data (); + + if (keytype == RSVC_STRING) { + char keystr[1024]; + char keystr1[1024]; + + if (data_.get (table_->keyName (), keystr, sizeof (keystr)) + != RSVC_SUCCESS) + return 0; + if (data1.get (table_->keyName (), keystr1, sizeof (keystr1)) + != RSVC_SUCCESS) + return 0; + + if (strcmp (keystr, keystr1) != 0) + return 0; + } + else if (keytype == RSVC_INT32) { + int keyv; + int keyv1; + + if (data_.get (table_->keyName (), &keyv) != RSVC_SUCCESS) + return 0; + if (data1.get (table_->keyName (), &keyv1) != RSVC_SUCCESS) + return 0; + + if (keyv != keyv1) + return 0; + } + else if (keytype == RSVC_FLOAT) { + float keyv; + float keyv1; + + if (data_.get (table_->keyName (), &keyv) != RSVC_SUCCESS) + return 0; + if (data1.get (table_->keyName (), &keyv1) != RSVC_SUCCESS) + return 0; + + if (keyv != keyv1) + return 0; + } + else if (keytype == RSVC_DOUBLE) { + double keyv; + double keyv1; + + if (data_.get (table_->keyName (), &keyv) != RSVC_SUCCESS) + return 0; + if (data1.get (table_->keyName (), &keyv1) != RSVC_SUCCESS) + return 0; + + if (keyv != keyv1) + return 0; + } + else + return 0; + + // finally successfule run + return 1; +} + +int +rsvcCacheData::assign (rsvcData& value) +{ + // value is a subset of the whole data + rsvcDataIterator ite (&value); + rsvcDataEntry* entryv; + rsvcDataEntry* entry; + int changed = 0; + rsvcCacheDataAttr* attr; + + // find out values coresponding to all tags from values + for (ite.init (); !ite; ++ite) { + entryv = ite (); + if ((entry = data_.lookupTag (entryv->tag_)) != 0) { + *entry = *entryv; + changed = 1; + // call this attibute monitor table + if ((attr = attribute (entryv->tag_)) != 0) + attr->notifyChannels (); + } + } + if (changed) // call all monitored parties + notifyChannels (); + + return RSVC_SUCCESS; +} + +int +rsvcCacheData::monitorOn (rsvcCbk& cbk) +{ + rsvcCbk* tcbk = new rsvcCbk (cbk); + monitorTable_.add (tcbk); + + return RSVC_SUCCESS; +} + +int +rsvcCacheData::monitorOff (rsvcCbk& cbk) +{ + rsvcHSlist& list = monitorTable_.bucketRef (&cbk); + rsvcHSlistIterator ite (list); + rsvcCbk* tcbk = 0; + int found = 0; + + for (ite.init (); !ite; ++ite) { + tcbk = (rsvcCbk *) ite (); + if (rsvcCbk::sameCallback (tcbk, &cbk, 1)) { + found = 1; + break; + } + } + if (found) { + list.remove (tcbk); + delete tcbk; + return RSVC_SUCCESS; + } + return RSVC_NOTFOUND; +} + + +int +rsvcCacheData::monitorOff (void* ioptr) +{ + rsvcCbk* cbk = 0; + rsvcHashIterator ite (monitorTable_); + + for (ite.init (); !ite; ++ite) { + cbk = (rsvcCbk *) ite (); + if (cbk->userptr () == ioptr) { + delete cbk; + ite.removeCurrent (); + } + } + + // remove all callbacks from all attributes + rsvcCacheDataAttr* attr; + rsvcHashIterator hite (attributes_); + + for (hite.init (); !hite; ++hite) { + attr = (rsvcCacheDataAttr *) hite (); + attr->monitorOff (ioptr); + } + return RSVC_SUCCESS; +} + +int +rsvcCacheData::monitored (void) +{ + if (monitorTable_.isEmpty ()) + return 0; + return 1; +} + + +rsvcData& +rsvcCacheData::data (void) +{ + return data_; +} + +int +rsvcCacheData::monitorAttr (char* name, rsvcCbk& cbk) +{ + rsvcCacheDataAttr* attr = attribute (name); + + if (attr == 0) + return RSVC_NOTFOUND; + + return attr->monitorOn (cbk); +} + +int +rsvcCacheData::monitorOffAttr (char* name, rsvcCbk& cbk) +{ + rsvcCacheDataAttr* attr = attribute (name); + + if (attr == 0) + return RSVC_NOTFOUND; + + return attr->monitorOff (cbk); +} + +rsvcCacheDataAttr * +rsvcCacheData::attribute (char* attrname) +{ + rsvcHashIterator ite (attributes_); + rsvcCacheDataAttr* attr; + + for (ite.init (); !ite; ++ite) { + attr = (rsvcCacheDataAttr *)ite (); + if (strcmp (attr->attrName (), attrname) == 0) + return attr; + } + return 0; +} + +void +rsvcCacheData::notifyChannels (int status) +{ + rsvcHashIterator ite (monitorTable_); + rsvcCbk* cbk = 0; + rsvcNetData* ndata = 0; + rsvcIO* channel = 0; + + for (ite.init (); !ite; ++ite) { + cbk = (rsvcCbk *) ite (); + + // connection channel + channel = (rsvcIO *)cbk->userptr (); + + cbk->cbkstatus (status); + ndata = new rsvcNetData (data_, *cbk); + + channel->sendToPeer (ndata); + } +} + +void +rsvcCacheData::notifySingleChannel (rsvcCbk* cbk) +{ + // connection channel + rsvcIO *channel = (rsvcIO *)cbk->userptr (); + + cbk->cbkstatus (RSVC_SUCCESS); + rsvcNetData* ndata = new rsvcNetData (data_, *cbk); + + channel->sendToPeer (ndata); +} + +void +rsvcCacheData::notifyChannels (char* attr) +{ + rsvcCacheDataAttr* rattr = 0; + rattr = attribute (attr); + + if (rattr) + rattr->notifyChannels (); +} + + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcCacheData.h b/extensions/cdevGenericServer/NameServer/src/rsvcCacheData.h new file mode 100755 index 0000000..57ddf93 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcCacheData.h @@ -0,0 +1,126 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server Cached Data Class +// +// This Class models the data objects that are stored inside +// cache information of a database +// +// Data always stored with key value +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_CACHE_DATA +#define _RSVC_CACHE_DATA + +#include +#include +#include +#include +#include +#include +#include + +class rsvcVirtualDbase; +class rsvcTableDef; +class rsvcCacheDataAttr; + +class rsvcCacheData : public rsvcHashable +{ +public: + // constructor + + // construct a cache data with a rsvcData which is transmitted + // over from network or database with key tag specified + rsvcCacheData (rsvcData& data, rsvcVirtualDbase* dbase, + rsvcTableDef* table); + + // destructor + virtual ~rsvcCacheData (void); + + // return hash code : inherited operation from rsvcHashable + unsigned int hash (void); + + // monitor on/off methods for the whole data + virtual int monitorOn (rsvcCbk& cbk); + virtual int monitorOff (rsvcCbk& cbk); + + // monitor on/off a single attribute + virtual int monitorAttr (char* attr, rsvcCbk& cbk); + virtual int monitorOffAttr (char* attr, rsvcCbk& cbk); + + // remove monitor specified by a io ptr + virtual int monitorOff (void* ioptr); + + // remove all monitors and attributes + void removeAllMonitors (void); + + // remove all attributes + void removeAllAttrs (void); + + // create all attributes + void createAllAttrs (void); + + // check whether this data or any attributes are being monitored + int monitored (void); + + // assignment or update method + int assign (rsvcData& value); + + // in case of any change in value. send new value to all interested + // parties + virtual void notifyChannels (int status = RSVC_SUCCESS); + + // notify channels with a particular attribute name + virtual void notifyChannels (char* attr); + + // retrieve internal data + rsvcData& data (void); + + // return attribute data + rsvcCacheDataAttr* attribute (char* attr); + + // check whether data has the same key value as data 'key' + int sameKey (rsvcCacheData* key); + +protected: + + // notify a single channel denoted by a cbk pointer + virtual void notifySingleChannel (rsvcCbk* cbk); + + // real data + rsvcData data_; + + // all monitor callback list: callback pointers + rsvcHash monitorTable_; + + // all data for attributes + rsvcHash attributes_; + + // assocaited database + rsvcVirtualDbase* database_; + + // assocaited table definition + rsvcTableDef* table_; + + // friend class + friend class rsvcCacheDataAttr; + + + // deny copy and assignment operations + rsvcCacheData (const rsvcCacheData& data); + rsvcCacheData& operator = (const rsvcCacheData& data); +}; +#endif + + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcCacheDataAttr.cc b/extensions/cdevGenericServer/NameServer/src/rsvcCacheDataAttr.cc new file mode 100755 index 0000000..028bad9 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcCacheDataAttr.cc @@ -0,0 +1,145 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of cached data attribute class +// +// Author: Jie Chen +// +// Revision History: +// rsvcCacheDataAttr.cc,v +// Revision 1.1 1998/01/22 17:07:59 akers +// Addition of new NameServer +// +// +// +#include +#include "rsvcCacheDataAttr.h" + +rsvcCacheDataAttr::rsvcCacheDataAttr (char* attr, rsvcCacheData& data) +:cache_ (data), monitorList_ (100, 3) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcCacheDataAttr Class Object\n"); +#endif + name_ = new char[strlen (attr) + 1]; + strcpy (name_, attr); +} + +rsvcCacheDataAttr::~rsvcCacheDataAttr (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcCacheDataAttr Class Object\n"); +#endif + delete []name_; + + removeAllCbks (); +} + + +void +rsvcCacheDataAttr::removeAllCbks (void) +{ + rsvcCbk* cbk = 0; + + rsvcHashIterator ite2 (monitorList_); + for (ite2.init (); !ite2; ++ite2) { + cbk = (rsvcCbk *)ite2 (); + delete cbk; + } +} + +unsigned int +rsvcCacheDataAttr::hash (void) +{ + unsigned int h = 0, g; + + for (int i = 0; name_[i] != '\0'; i++){ + h = (h << 4) + name_[i]; + // assume 32 bit integer + if (g = h & 0xf0000000){ + h ^= g >> 24; + h ^= g; + } + } + return h; +} + +char* +rsvcCacheDataAttr::attrName (void) const +{ + return name_; +} + +int +rsvcCacheDataAttr::monitorOn (rsvcCbk& cbk) +{ + rsvcCbk* tcbk = new rsvcCbk (cbk); + monitorList_.add (tcbk); + + return RSVC_SUCCESS; +} + +int +rsvcCacheDataAttr::monitorOff (rsvcCbk& cbk) +{ + rsvcHSlist& list = monitorList_.bucketRef (&cbk); + rsvcHSlistIterator ite (list); + rsvcCbk* tcbk = 0; + int found = 0; + + for (ite.init (); !ite; ++ite) { + tcbk = (rsvcCbk *) ite (); + if (rsvcCbk::sameCallback (tcbk, &cbk, 1)) { + found = 1; + break; + } + } + if (found) { + list.remove (tcbk); + delete tcbk; + return RSVC_SUCCESS; + } + return RSVC_NOTFOUND; +} + +void +rsvcCacheDataAttr::notifyChannels (void) +{ + rsvcHashIterator ite (monitorList_); + rsvcCbk* cbk = 0; + + for (ite.init (); !ite; ++ite) { + cbk = (rsvcCbk *) ite (); + cache_.notifySingleChannel (cbk); + } +} + +int +rsvcCacheDataAttr::getValue (rsvcCbk& /* cbk */) +{ + return RSVC_SUCCESS; +} + +int +rsvcCacheDataAttr::monitorOff (void* ioptr) +{ + rsvcCbk* cbk = 0; + rsvcHashIterator ite (monitorList_); + + for (ite.init (); !ite; ++ite) { + cbk = (rsvcCbk *) ite (); + if (cbk->userptr () == ioptr) { + delete cbk; + ite.removeCurrent (); + } + } + return RSVC_SUCCESS; +} + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcCacheDataAttr.h b/extensions/cdevGenericServer/NameServer/src/rsvcCacheDataAttr.h new file mode 100755 index 0000000..ac005b3 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcCacheDataAttr.h @@ -0,0 +1,73 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server Cache Data Attributes +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_CACHE_DATA_ATTR_H +#define _RSVC_CACHE_DATA_ATTR_H + +#include +#include +#include +#include +#include +#include +#include + +class rsvcCbk; + +class rsvcCacheDataAttr : public rsvcHashable +{ +public: + // constructor and destructor + rsvcCacheDataAttr (char* attr, rsvcCacheData& cache); + virtual ~rsvcCacheDataAttr (void); + + // return hash code + unsigned int hash (void); + + // monitor on/off + // outdata's are newly allocated data. + // remember to free those + virtual int monitorOn (rsvcCbk& cbk); + virtual int monitorOff (rsvcCbk& cbk); + // monitor off all with same ioptr + virtual int monitorOff (void* ioptr); + virtual int getValue (rsvcCbk& cbk); + + // return attribute name + char* attrName (void) const; + + // notify channels + void notifyChannels (void); + +protected: + + // remove all callbacks from the lists + void removeAllCbks (void); + + // attribute name + char* name_; + + // all callback list : (with all cbk pointers) + rsvcHash monitorList_; + + // whole cached data storage + rsvcCacheData& cache_; + + // deny access to copy and assignment operations + rsvcCacheDataAttr (const rsvcCacheDataAttr& attr); + rsvcCacheDataAttr& operator = (const rsvcCacheDataAttr& attr); +}; +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcCallback.cc b/extensions/cdevGenericServer/NameServer/src/rsvcCallback.cc new file mode 100755 index 0000000..73c7cd4 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcCallback.cc @@ -0,0 +1,94 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcCallback Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcCallback.cc,v +// Revision 1.1 1998/01/22 17:08:00 akers +// Addition of new NameServer +// +// +// +#include "rsvcCallback.h" + +rsvcCallback::rsvcCallback (void) +:cbk_ (0), arg_ (0) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcCallback Class Object\n"); +#endif +} + +rsvcCallback::rsvcCallback (rsvcCbkFunc func, void* arg) +:cbk_ (func), arg_ (arg) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcCallback Class Object\n"); +#endif +} + +rsvcCallback::rsvcCallback (const rsvcCallback& cbk) +:cbk_ (cbk.cbk_), arg_ (cbk.arg_) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcCallback Class Object\n"); +#endif +} + +rsvcCallback & +rsvcCallback::operator = (const rsvcCallback& cbk) +{ + if (this != &cbk) { + cbk_ = cbk.cbk_; + arg_ = cbk.arg_; + } + return *this; +} + +rsvcCallback::~rsvcCallback (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcCallback Class Object\n"); +#endif +} + +int +rsvcCallback::operator == (const rsvcCallback& cbk) +{ + return (cbk_ == cbk.cbk_ && arg_ == cbk.arg_); +} + +int +rsvcCallback::operator != (const rsvcCallback& cbk) +{ + return !(cbk_ == cbk.cbk_ && arg_ == cbk.arg_); +} + +rsvcCbkFunc +rsvcCallback::cbkFunc (void) const +{ + return cbk_; +} + +void * +rsvcCallback::userarg (void) const +{ + return arg_; +} + +int +rsvcCallback::empty (void) +{ + return !cbk_; +} + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcCallback.h b/extensions/cdevGenericServer/NameServer/src/rsvcCallback.h new file mode 100755 index 0000000..74bcac8 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcCallback.h @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Callback Class for Client +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_CALLBACK_H +#define _RSVC_CALLBACK_H + +#include +#include +#include + +typedef void (*rsvcCbkFunc) (int status, void* arg, rsvcData* data); + +class RSVC_CLASS_SPEC rsvcCallback +{ +public: + // constructor + rsvcCallback (void); + rsvcCallback (rsvcCbkFunc func, void* arg); + rsvcCallback (const rsvcCallback& cbk); + rsvcCallback& operator = (const rsvcCallback& cbk); + // destructor + ~rsvcCallback (void); + + int operator == (const rsvcCallback& cbk); + int operator != (const rsvcCallback& cbk); + + virtual rsvcCbkFunc cbkFunc (void) const; + virtual void* userarg (void) const; + + // return whether this callback is empty + int empty (void); + +private: + rsvcCbkFunc cbk_; + void* arg_; +}; +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcCbk.cc b/extensions/cdevGenericServer/NameServer/src/rsvcCbk.cc new file mode 100755 index 0000000..637d481 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcCbk.cc @@ -0,0 +1,377 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcCbk class +// +// Author: Jie Chen +// +// Revision History: +// rsvcCbk.cc,v +// Revision 1.1 1998/01/22 17:08:01 akers +// Addition of new NameServer +// +// +// +#include +#include +#include + +#ifdef _WIN32 + #include +#else + #include +#endif + +#include +#include "rsvcCbk.h" + +rsvcCbk::rsvcCbk (void) +:rsvcStreamable (), rsvcHashable (), + opcode_ (RSVC_OP_UNKNOWN), cbkid_ (0), reqid_ (0), + clientid_ (0), socketid_ (0), status_ (RSVC_SUCCESS), private_ (0) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcCbk Class Object\n"); +#endif + + // empty +} + +rsvcCbk::rsvcCbk (int opcode, int cbkid, int reqid, + int clientid, int socketid, int status, void* ptr) +:rsvcStreamable (), rsvcHashable (), + opcode_ (opcode), cbkid_ (cbkid), reqid_ (reqid), + clientid_ (clientid), socketid_ (socketid), + status_ (status), private_ (ptr) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcCbk Class Object\n"); +#endif + // empty +} + +rsvcCbk::rsvcCbk (const rsvcCbk& cbk) +:rsvcStreamable (), rsvcHashable (), + opcode_ (cbk.opcode_), cbkid_ (cbk.cbkid_), reqid_ (cbk.reqid_), + clientid_ (cbk.clientid_), socketid_ (cbk.socketid_), + status_ (cbk.status_), private_ (cbk.private_) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcCbk Class Object\n"); +#endif + // empty +} + +rsvcCbk & +rsvcCbk::operator = (const rsvcCbk& cbk) +{ + if (this != &cbk) { + opcode_ = cbk.opcode_; + cbkid_ = cbk.cbkid_; + reqid_ = cbk.reqid_; + clientid_ = cbk.clientid_; + socketid_ = cbk.socketid_; + status_ = cbk.status_; + private_ = cbk.private_; + } + return *this; +} + +rsvcCbk::~rsvcCbk (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcCbk Class Object\n"); +#endif + // empty +} + + +void +rsvcCbk::cleanup (void) +{ + opcode_ = 0; + cbkid_ = 0; + reqid_ = 0; + clientid_ = 0; + socketid_ = 0; + status_ = 0; + private_ = 0; +} + +void +rsvcCbk::socketid (int socketid) +{ + socketid_ = socketid; +} + +int +rsvcCbk::socketid (void) const +{ + return socketid_; +} + +void +rsvcCbk::cbkstatus (int st) +{ + status_ = st; +} + +int +rsvcCbk::cbkstatus (void) const +{ + return status_; +} + +int +rsvcCbk::opcode (void) const +{ + return opcode_; +} + +void +rsvcCbk::opcode (int op) +{ + opcode_ = op; +} + +int +rsvcCbk::reqid (void) const +{ + return reqid_; +} + +void +rsvcCbk::reqid (int req) +{ + reqid_ = req; +} + +int +rsvcCbk::cbkid (void) const +{ + return cbkid_; +} + +void +rsvcCbk::cbkid (int id) +{ + cbkid_ = id; +} + +int +rsvcCbk::clientid (void) const +{ + return clientid_; +} + +void +rsvcCbk::clientid (int cid) +{ + clientid_ = cid; +} + +void * +rsvcCbk::userptr (void) const +{ + return private_; +} + +void +rsvcCbk::userptr (void* ptr) +{ + private_ = ptr; +} + +size_t +rsvcCbk::streamSize (void) +{ + return 6*sizeof (int); +} + +int +rsvcCbk::streamOut (char** buf, size_t* len) +{ + char* buffer = new char[6*sizeof (int)]; + + if (buffer == 0) { + fprintf (stderr, "Allocate buffer for rsvcCbk error, quit\n"); + exit (1); + } + + *len = 6*sizeof (int); + *buf = buffer; + + int tmp; + int i = 0; + + tmp = htonl (opcode_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (cbkid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (reqid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (clientid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (socketid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (status_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + return RSVC_SUCCESS; +} + +int +rsvcCbk::streamOut (char* buffer, size_t len) +{ + if (buffer == 0) { + fprintf (stderr, "Allocate buffer for rsvcCbk error, quit\n"); + exit (1); + } + + if (len < 6*sizeof (int)) { + fprintf (stderr, "Streaming out rsvcCbk has not enough buffer size\n"); + return RSVC_OVERFLOW; + } + + int tmp; + int i = 0; + + tmp = htonl (opcode_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (cbkid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (reqid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (clientid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (socketid_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + tmp = htonl (status_); + memcpy (&(buffer[i]), &tmp, sizeof (int)); + i += sizeof (int); + + return RSVC_SUCCESS; +} + +int +rsvcCbk::streamIn (char* buffer, size_t len) +{ + if (buffer == 0) { + fprintf (stderr, "Stream in buffer == 0 error, quit\n"); + exit (1); + } + + if (len < 6*sizeof (int)) { + fprintf (stderr, "Streaming in rsvcCbk has not enough buffer size\n"); + return RSVC_OVERFLOW; + } + + int tmp; + int i = 0; + + memcpy (&tmp, &(buffer[i]), sizeof (int)); + i += sizeof (int); + opcode_ = ntohl (tmp); + + memcpy (&tmp, &(buffer[i]), sizeof (int)); + i += sizeof (int); + cbkid_ = ntohl (tmp); + + memcpy (&tmp, &(buffer[i]), sizeof (int)); + i += sizeof (int); + reqid_ = ntohl (tmp); + + memcpy (&tmp, &(buffer[i]), sizeof (int)); + i += sizeof (int); + clientid_ = ntohl (tmp); + + memcpy (&tmp, &(buffer[i]), sizeof (int)); + i += sizeof (int); + socketid_ = ntohl (tmp); + + memcpy (&tmp, &(buffer[i]), sizeof (int)); + i += sizeof (int); + status_ = ntohl (tmp); + + return RSVC_SUCCESS; +} + +int +rsvcCbk::sameCallback (rsvcCbk* cbk1, rsvcCbk* cbk2, + int checkreq) +{ + if (checkreq) { + if (cbk1->reqid_ == cbk2->reqid_ && + cbk1->clientid_ == cbk2->clientid_ && + cbk1->socketid_ == cbk2->socketid_ && + cbk1->cbkid_ == cbk2->cbkid_) + return 1; + else + return 0; + } + else { + if (cbk1->clientid_ == cbk2->clientid_ && + cbk1->socketid_ == cbk2->socketid_ && + cbk1->cbkid_ == cbk2->cbkid_) + return 1; + else + return 0; + } +} + + +int +rsvcCbk::match (rsvcCbk* cbk) +{ + if (opcode_ == cbk->opcode_ && + reqid_ == cbk->reqid_ && + clientid_ == cbk->clientid_ && + cbkid_ == cbk->cbkid_) + return 1; + return 0; +} + +unsigned int +rsvcCbk::hash (void) +{ + // return hash value of callback id + unsigned int h = 0; + unsigned char *k, *e; + + k = (unsigned char *)&cbkid_; + e = k + sizeof (int); + for (h = 0; k < e; ++k) { + h *= 16777619; + h ^= *k; + } + return h; +} + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcCbk.h b/extensions/cdevGenericServer/NameServer/src/rsvcCbk.h new file mode 100755 index 0000000..58c1b71 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcCbk.h @@ -0,0 +1,105 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Callback Class (Used on Server/Client Side) +// +// This class contains protocol information related to callbacks +// 1. operation code +// 2. request id +// 3. socket id -->for server only +// 4. client id +// 5. callback id -->from client to server +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_CBK_H +#define _RSVC_CBK_H + +#include +#include +#include +#include +#include +#include + +class rsvcCbk : public rsvcStreamable, public rsvcHashable +{ +public: + // constructor + rsvcCbk (void); + rsvcCbk (int opcode, int cbkid, int reqid, int clientid, + int socketid = 0, int status = RSVC_SUCCESS, + void* usrptr = 0); + rsvcCbk (const rsvcCbk& cbk); + rsvcCbk& operator = (const rsvcCbk& cbk); + ~rsvcCbk (void); + + // clean up all values + void cleanup (void); + + void socketid (int id); + int socketid (void) const; + + void cbkstatus (int st); + int cbkstatus (void) const; + + int reqid (void) const; + void reqid (int req); + int opcode (void) const; + void opcode (int op); + int cbkid (void) const; + void cbkid (int id); + int clientid (void) const; + void clientid (int cid); + + // use by local only , not transmitted through wire + void* userptr (void) const; + void userptr (void* ptr); + + // inherited operation + unsigned int hash (void); + + size_t streamSize (void); + // stream out to a newly allocated buffer with size 'size' + int streamOut (char** buf, size_t* size); + // stream out to a preallocate buffer with buffer size 'size' + int streamOut (char* buf, size_t len); + // stream in from a buffer + int streamIn (char* buf, size_t len); + + // check whether two callbacks are the same. + // if checkreq == 1, check reqid otherwise no + // this function is used by server side to check + // whether a monitoroff callback is inside the callback table + // on the server. + static int sameCallback (rsvcCbk* cbk1, rsvcCbk* callback2, + int checkreq = 1); + + // check whether a callback coming back from the server + // match a callback in the table + int match (rsvcCbk* scbk); + +private: + // all data + int opcode_; + int cbkid_; + int reqid_; + int clientid_; + int socketid_; + int status_; + + // used by local only, not transmitted on wire + void* private_; +}; +#endif + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcClient.cc b/extensions/cdevGenericServer/NameServer/src/rsvcClient.cc new file mode 100755 index 0000000..3876310 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcClient.cc @@ -0,0 +1,1119 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcClient Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcClient.cc,v +// Revision 1.8 1998/03/19 18:30:56 chen +// add monitorEntry capability to server table +// +// Revision 1.6 1998/02/25 19:52:55 chen +// keep alive option on +// +// Revision 1.5 1998/02/24 14:13:39 chen +// remove errno check on read_n +// +// Revision 1.4 1998/02/20 19:37:28 chen +// reset errno after using it (hpux) sometimes not resetting it +// +// Revision 1.3 1998/02/06 15:12:32 chen +// add connection management to the name server +// +// Revision 1.2 1998/01/22 20:04:06 chen +// to make it work with cdevReactor +// +// Revision 1.1 1998/01/22 17:08:02 akers +// Addition of new NameServer +// +// +// +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include + +#define RSVC_ERRNO WSAGetLastError() +#define EADDRINUSE WSAEADDRINUSE +#define EINPROGRESS WSAEINPROGRESS +#define SYSINTR WSAEINTR +#define EISCONN WSAEISCONN +#define ETIMEDOUT WSAETIMEDOUT +#define EWOULDBLOCK WSAEWOULDBLOCK + +#define RSVC_SET_ERRNO(e) WSASetLastError(e) + +#define SOCKOPT_VALUE_PTR (const char *) + +#else /* _WIN32 */ +#include +#include +#include +#include + +#define RSVC_ERRNO errno +#define SYSINTR EINTR +#define RSVC_SET_ERRNO(e) errno=e + +#ifndef solaris +#define SOCKOPT_VALUE_PTR (void *) +#else +#define SOCKOPT_VALUE_PTR (char *) +#endif + +#endif + +#if defined(AIX) || defined(__linux) + typedef unsigned int SOCKOPT_SIZE_PARM; +#else + typedef int SOCKOPT_SIZE_PARM; +#endif + +#include +#include "rsvcClient.h" + +rsvcClient::rsvcClient (void) +:connected_ (0), tcp_fd_ (-1), server_host_ (0), server_port_ (0), + lock_ (0), reqid_ (1234), cbkid_ (93), discCbkList_ (), cmdCbkList_ (), + monitorCbkTable_ (1000, 3) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcClient Class Object\n"); +#endif + +#ifdef _WIN32 + WORD wVersion; + WSADATA wsaData; + + wVersion = MAKEWORD (2, 0); /* WinSock 2.0 */ + if (WSAStartup (wVersion, &wsaData) != 0) { + WSACleanup (); + fprintf (stderr, "rsvcClient: Cannot initialize win socket\n"); + } +#endif + + cbuflen_ = 4096; + cbuffer_ = new char[cbuflen_]; + if (!cbuffer_) { + fprintf (stderr, "rsvcClient Fatal: malloc error\n"); + exit (1); + } +} + +rsvcClient::~rsvcClient (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcClient Class Object\n"); +#endif + + if (server_host_) + delete []server_host_; + + if (connected_) + disconnect (); + + delete []cbuffer_; + +#ifdef _WIN32 + WSACleanup (); +#endif +} + +int +rsvcClient::connect (char* host, unsigned short port, + double seconds) +{ + if (connected_) + return RSVC_SUCCESS; + + struct hostent* phe = 0; + struct sockaddr_in sin; + + memset (&sin, 0, sizeof (sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons (port); + + if (phe = gethostbyname (host)) + memcpy (&sin.sin_addr, phe->h_addr, phe->h_length); + else { + fprintf (stderr, "RSVC Client: gethostbyname %s error\n", host); + return RSVC_ERROR; + } + + tcp_fd_ = socket (AF_INET, SOCK_STREAM, 0); + + if (tcp_fd_ < 0) { + fprintf (stderr, "RSVC Client: cannot create tcp socket\n"); + return RSVC_ERROR; + } + + // if timeout is zero we do simple blocked connect + int status; + if (seconds < 0.00001) { + if ((status = ::connect (tcp_fd_, (struct sockaddr *)&sin, + sizeof (sin))) < 0) { + fprintf (stderr, "RSVC Client: cannot connect to server %s@%d\n", + host, port); + return RSVC_ERROR; + } + else { + connected_ = 1; + + // remember the server information + if (server_host_) + delete server_host_; + server_host_ = new char[strlen (host) + 1]; + strcpy (server_host_, host); + server_port_ = port; + + // set socket option keep alive + int alive = 1; + setsockopt (tcp_fd_, SOL_SOCKET, SO_KEEPALIVE, SOCKOPT_VALUE_PTR &alive, + (SOCKOPT_SIZE_PARM)sizeof (alive)); + return RSVC_SUCCESS; + } + } + else { + struct timeval timeout; + + timeout.tv_sec = (int)seconds; + timeout.tv_usec = (int) ((seconds - timeout.tv_sec)*1000000); + if (connect_nonblock (tcp_fd_, (struct sockaddr *)&sin, + sizeof (sin), &timeout) != RSVC_SUCCESS) { + close (tcp_fd_); + tcp_fd_ = -1; + return RSVC_ERROR; + } + connected_ = 1; + + // remember the server information + if (server_host_) + delete server_host_; + server_host_ = new char[strlen (host) + 1]; + strcpy (server_host_, host); + server_port_ = port; + + // set socket option keep alive + int alive = 1; + setsockopt (tcp_fd_, SOL_SOCKET, SO_KEEPALIVE, SOCKOPT_VALUE_PTR &alive, + (SOCKOPT_SIZE_PARM)sizeof (alive)); + return RSVC_SUCCESS; + } +} + +int +rsvcClient::connect_nonblock (int sockfd, struct sockaddr* addr, + size_t addrlen, struct timeval* timeout) +{ + int flags, n, error; + int len; + fd_set rset, wset; + +#ifndef _WIN32 + // set non block mode + flags = fcntl (sockfd, F_GETFL, 0); + fcntl (sockfd, F_SETFL, flags | O_NONBLOCK); +#endif + + error = 0; + + if ((n = ::connect (sockfd, addr, addrlen)) < 0) { + if (errno != EINPROGRESS && errno != EWOULDBLOCK) + return RSVC_ERROR; + } + + if (n == 0) + goto connect_done; // connection complete + + FD_ZERO (&rset); + FD_SET (sockfd, &rset); + memcpy (&wset, &rset, sizeof (rset)); + +#ifdef _SELECT_USES_INT_ + if ((n = select (sockfd + 1, (int *)&rset, (int *)&wset, (int *)0, timeout)) == 0) +#else + if ((n = select (sockfd + 1, &rset, &wset, 0, timeout)) == 0) +#endif + { + // timeout + RSVC_SET_ERRNO (ETIMEDOUT); + return RSVC_ERROR; + } + if (FD_ISSET (sockfd, &rset) || FD_ISSET (sockfd, &wset)) { + len = sizeof (error); + if (getsockopt (sockfd, SOL_SOCKET, SO_ERROR, (char *)&error, (SOCKOPT_SIZE_PARM *)&len) < 0) + return RSVC_ERROR; // solaris pending error + } + else + return RSVC_ERROR; + +connect_done: +#ifndef _WIN32 + // restore old flag + fcntl (sockfd, F_SETFL, flags); +#endif + + if (error) { + RSVC_SET_ERRNO(error); + return RSVC_ERROR; + } + return RSVC_SUCCESS; +} + +int +rsvcClient::disconnect (void) +{ + if (connected_) { + shutdown (tcp_fd_, 0); + close (tcp_fd_); + tcp_fd_ = -1; + connected_ = 0; + + // remove all callbacks + cleanupCallbacks (); + } + return RSVC_SUCCESS; +} + +int +rsvcClient::connected (void) +{ + return connected_; +} + +int +rsvcClient::disconnectCallback (rsvcCbkFunc func, void* arg) +{ + rsvcCallback* cbk = new rsvcCallback (func, arg); + + rsvcSlistIterator ite (discCbkList_); + rsvcCallback* tcbk = 0; + int error = 0; + + for (ite.init (); !ite; ++ite) { + tcbk = (rsvcCallback *) ite (); + if (*tcbk == *cbk) { + error = 1; + break; + } + } + if (!error) { + discCbkList_.add ((void *)cbk); + return RSVC_SUCCESS; + } + delete cbk; + return RSVC_ERROR; +} + + +void +rsvcClient::cleanupCallbacks (void) +{ + // delete everything from disconnect callback list + rsvcSlistIterator ite (discCbkList_); + rsvcCallback* cbk = 0; + + for (ite.init (); !ite; ++ite) { + cbk = (rsvcCallback *) ite (); + delete cbk; + } + discCbkList_.deleteAllValues (); + + // delete all from command callback list + rsvcSlistIterator cite (cmdCbkList_); + rsvcCbk* scbk = 0; + + for (cite.init (); !cite; ++cite) { + scbk = (rsvcCbk *) cite (); + cbk = (rsvcCallback *)scbk->userptr (); + delete cbk; + delete scbk; + } + cmdCbkList_.deleteAllValues (); + + // delete all from monitor table + rsvcHashIterator hite (monitorCbkTable_); + + for (hite.init (); !hite; ++hite) { + scbk = (rsvcCbk *) hite (); + cbk = (rsvcCallback *)scbk->userptr (); + delete cbk; + delete scbk; + } + monitorCbkTable_.deleteAllValues (); +} + +void +rsvcClient::callAllDiscCbks (void) +{ + rsvcSlistIterator ite (discCbkList_); + rsvcCallback* cbk = 0; + rsvcCbkFunc func = 0; + void *arg = 0; + + for (ite.init (); !ite; ++ite) { + cbk = (rsvcCallback *)ite (); + func = cbk->cbkFunc (); + arg = cbk->userarg (); + (*func)(RSVC_DISCONNECTED, arg, (rsvcData *)0); + } +} + + +int +rsvcClient::getFd (void) const +{ + return tcp_fd_; +} + +int +rsvcClient::pendIO (double seconds) +{ + // first prevent recursice calling from a callback + if (lock_) + return RSVC_INVALID; + + if (tcp_fd_ == -1) + return RSVC_BADIO; + + int nfound = 0; + fd_set readfd; + struct timeval tv; + + if (seconds <= 0.000001) { + tv.tv_sec = 0; + tv.tv_usec = 0; + } + else { + tv.tv_sec = (int)seconds; + tv.tv_usec = (int)((seconds - tv.tv_sec)*1000000); + } + + FD_ZERO (&readfd); + FD_SET (tcp_fd_, &readfd); + + do { +#ifndef __hpux + nfound = select (tcp_fd_ + 1, &readfd, 0, 0, &tv); +#else + +#ifdef _SELECT_USES_INT_ + nfound = select (tcp_fd_ + 1, (int *)&readfd, (int *)0, (int *)0, + &tv); +#else + nfound = select (tcp_fd_ + 1, &readfd, 0, 0, &tv); +#endif + +#endif + }while (nfound == -1 && errno == SYSINTR); + + if (nfound == -1) { // something wrong with tcp_fd_ + fprintf (stderr, "rsvcClient: Bad tcp fd %d\n", tcp_fd_); + tcp_fd_ = -1; + return RSVC_BADIO; + } + else if (nfound == 0) // timeout + return RSVC_TIMEOUT; + else { + if (FD_ISSET (tcp_fd_, &readfd)) { + if (handle_input (tcp_fd_) < 0) { // bad io + handle_close (tcp_fd_); + return RSVC_IOERROR; + } + } + } + return RSVC_SUCCESS; +} + +int +rsvcClient::pendIO (void) +{ + if (lock_) + return RSVC_INVALID; + + if (tcp_fd_ == -1) + return RSVC_BADIO; + + int nfound = 0; + fd_set readfd; + + FD_ZERO (&readfd); + FD_SET (tcp_fd_, &readfd); + + do { +#ifndef __hpux + nfound = select (tcp_fd_ + 1, &readfd, 0, 0, 0); +#else + +#ifdef _SELECT_USES_INT_ + nfound = select (tcp_fd_ + 1, (int *)&readfd, (int *)0, (int *)0, + (struct timeval *)0); +#else + nfound = select (tcp_fd_ + 1, &readfd, 0, 0, 0); +#endif + +#endif + }while (nfound == -1 && errno == EINTR); + + if (nfound == -1) { // something wrong with tcp_fd_ + fprintf (stderr, "rsvcClient: bad tcp fd %d\n", tcp_fd_); + tcp_fd_ = -1; + return RSVC_BADIO; + } + else if (nfound == 0) // timeout + return RSVC_TIMEOUT; + else { + if (FD_ISSET (tcp_fd_, &readfd)) { + if (handle_input (tcp_fd_) < 0) { // bad io + handle_close (tcp_fd_); + return RSVC_IOERROR; + } + } + } + return RSVC_SUCCESS; +} + +int +rsvcClient::handle_input (int) +{ + int n; + rsvcNetData ndata; + + // lock thus event processing function to prevent a recursive call + rsvcClientLocker locker (this); + + // read header information + char header[32]; + n = rsvcClient::read_n (tcp_fd_, header, rsvcNetData::headerLen ()); + if (n != rsvcNetData::headerLen ()) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: Receiving netdata header error\n"); +#endif + printf ("rsvcClient: Server is dead\n"); + return -1; + } + + size_t datasize; + if (rsvcNetData::readHeader (header, n, &datasize) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: reading netdata header error\n"); +#endif + return -1; + } + + if (datasize > cbuflen_) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: incoming data size %d > %d, resize\n", + datasize, cbuflen_); +#endif + delete []cbuffer_; + cbuflen_ = 2*datasize; + cbuffer_ = new char[cbuflen_]; + if (!cbuffer_) { + fprintf (stderr, "rsvcClientIO: malloc error in hanlde_input\n"); + exit (1); + } + } + + // now really try to read data + n = rsvcClient::read_n (tcp_fd_, cbuffer_, datasize); + if (n != datasize) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: Received %d bytes != %d bytes\n", + n, datasize); +#endif + return -1; + } + + // convert data + if (ndata.streamIn (cbuffer_, datasize) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: stream in netdata error\n"); +#endif + return -1; + } + + return processData (ndata); +} + +int +rsvcClient::handle_close (int) +{ + shutdown (tcp_fd_, 0); + close (tcp_fd_); + tcp_fd_ = -1; + connected_ = 0; + + // call all disconnect callback + callAllDiscCbks (); + + // cleanup all callbacks + cleanupCallbacks (); + + return 0; +} + + +int +rsvcClient::processData (rsvcNetData& ndata) +{ + rsvcData& data = ndata.data (); + rsvcCbk& cbk = ndata.cbk (); + int op = cbk.opcode (); + int status = 0; + + if (op < RSVC_MONITOR_ON) { + // all simple transaction callback + status = cmdCbkFromServer ((int)cbk.cbkstatus (), data, cbk); + } + else if (op < RSVC_OP_UNKNOWN){ + // all monitor callbacks + status = monitorCbkFromServer ((int)cbk.cbkstatus (), data, cbk); + } + else { + fprintf (stderr, "rsvcClient: Invalid operation code\n"); + status = -1; + } + return status; +} + +int +rsvcClient::cmdCbkFromServer (int status, rsvcData& data, rsvcCbk& cbk) +{ + rsvcSlistIterator ite (cmdCbkList_); + rsvcCbk* tcbk = 0; + rsvcCallback* rcbk = 0; + int found = 0; + + for (ite.init (); !ite; ++ite) { + tcbk = (rsvcCbk *) ite (); + if (tcbk->match (&cbk)) { + found = 1; + rcbk = (rsvcCallback *)tcbk->userptr (); + (*rcbk->cbkFunc() )(status, rcbk->userarg (), &data); + } + } + if (found && status != RSVC_INCOMPLETE) { + cmdCbkList_.remove ((void *)tcbk); + delete rcbk; + delete tcbk; + } + else { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: Callback from server does not match any\n"); +#endif + } + + return 0; +} + +int +rsvcClient::monitorCbkFromServer (int status, rsvcData& data, + rsvcCbk& cbk) +{ + rsvcHSlist& list = monitorCbkTable_.bucketRef (&cbk); + rsvcHSlistIterator ite (list); + + rsvcCbk* tcbk = 0; + rsvcCallback* rcbk = 0; + int found = 0; + + for (ite.init (); !ite; ++ite) { + tcbk = (rsvcCbk *) ite (); + if (tcbk->match (&cbk)) { + found = 1; + rcbk = (rsvcCallback *)tcbk->userptr (); + (*rcbk->cbkFunc())(status, rcbk->userarg (), &data); + } + } + if (found && cbk.cbkstatus () != RSVC_SUCCESS + && cbk.cbkstatus () != RSVC_INCOMPLETE) { + // if callback is bad or finished remove it from the list + list.remove (tcbk); + delete rcbk; + delete tcbk; + } + else if (cbk.cbkstatus () != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: monitorCallback from server does not match any\n"); + printf ("rsvcClient: cbk has %d %d %d %d %d\n", + cbk.opcode (), cbk.reqid (), cbk.cbkid (), cbk.clientid (), + cbk.cbkstatus()); +#endif + } + + return 0; +} + + +int +rsvcClient::createMemDbase (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = commandCallback ((int)RSVC_CREATE_MEMTABLE, data, + func, arg); + return status; +} + + +int +rsvcClient::openDatabase (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = commandCallback ((int)RSVC_OPEN_DBASE, data, + func, arg); + return status; +} + +int +rsvcClient::insertValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg, int overwrite) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else { + if (!overwrite) + status = commandCallback ((int)RSVC_INSERT, data, + func, arg); + else + status = commandCallback ((int)RSVC_OVERWRITE, data, + func, arg); + } + return status; +} + +int +rsvcClient::getValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = commandCallback ((int)RSVC_GET, data, + func, arg); + return status; +} + + +int +rsvcClient::delValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = commandCallback ((int)RSVC_DEL, data, + func, arg); + return status; +} + +int +rsvcClient::setValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = commandCallback ((int)RSVC_SET, data, + func, arg); + return status; +} + + +int +rsvcClient::commandCallback (int opcode, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + size_t nbytes = 0; + size_t nw = 0; + + rsvcCallback* cbk = new rsvcCallback (func, arg); + rsvcCbk* cbkid = new rsvcCbk (opcode, cbkid_++, + reqid_++, tcp_fd_, 0, + RSVC_SUCCESS, (void *)cbk); + + // create netdata + rsvcNetData netdata (data, *cbkid); + + if ((nbytes = streamData (netdata)) <= 0) + status = RSVC_ERROR; + else { + // block write + if ((nw = rsvcClient::write_n (tcp_fd_, cbuffer_, nbytes)) != nbytes) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: wrote %d nbytes and expect to write %d bytes\n", + nw, nbytes); +#endif + status = RSVC_ERROR; + } + else + // register callback and so on + cmdCbkList_.add ((void *)cbkid); + } + if (status != RSVC_SUCCESS) { + delete cbkid; + delete cbk; + } + + return status; +} + + +int +rsvcClient::monitorValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = monitorCallback ((int)RSVC_MONITOR_ON, data, + func, arg); + return status; +} + +int +rsvcClient::monitorOffValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = monitorOffCallback ((int)RSVC_MONITOR_OFF, data, + func, arg); + return status; +} + +int +rsvcClient::monitorIncomingEntries (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = monitorCallback ((int)RSVC_MONITOR_ENTRIES, data, + func, arg); + + return status; +} + +int +rsvcClient::monitorOffIncomingEntries (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + else + status = monitorOffCallback ((int)RSVC_MONITOR_OFFENTRIES, data, + func, arg); + + return status; +} + + +int +rsvcClient::monitorCallback (int opcode, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + size_t nbytes = 0; + size_t nw = 0; + + // this callback is in the table already + if (monitorCbkInTable (func, arg) != 0) { + printf ("rsvcClient: monitor callback function already in use\n"); + return RSVC_INVALIDARG; + } + + rsvcCallback* cbk = new rsvcCallback (func, arg); + rsvcCbk* cbkid = new rsvcCbk (opcode, cbkid_++, + reqid_++, tcp_fd_, 0, + RSVC_SUCCESS, (void *)cbk); + + + // create netdata + rsvcNetData netdata (data, *cbkid); + + if ((nbytes = streamData (netdata)) <= 0) + status = RSVC_ERROR; + else { + // block write + if ((nw = rsvcClient::write_n (tcp_fd_, cbuffer_, nbytes)) != nbytes) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: wrote %d nbytes and expect to write %d bytes\n", + nw, nbytes); +#endif + status = RSVC_ERROR; + } + else + // register callback and so on + monitorCbkTable_.add (cbkid); + } + + if (status != RSVC_SUCCESS) { + delete cbkid; + delete cbk; + } + return status; +} + +int +rsvcClient::monitorOffCallback (int opcode, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + size_t nbytes = 0; + size_t nw = 0; + rsvcCbk* cbk = 0; + + + if ((cbk = monitorCbkInTable (func, arg)) == 0) + return RSVC_INVALIDARG; + + // create netdata + // change cbk opcode into monitor off + cbk->opcode (opcode); + rsvcNetData netdata (data, *cbk); + + if ((nbytes = streamData (netdata)) <= 0) + status = RSVC_ERROR; + else { + // block write + if ((nw = rsvcClient::write_n (tcp_fd_, cbuffer_, nbytes)) != nbytes) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: wrote %d nbytes and expect to write %d bytes\n", + nw, nbytes); +#endif + status = RSVC_ERROR; + } + } + + return status; +} + +rsvcCbk* +rsvcClient::monitorCbkInTable (rsvcCbkFunc func, void* arg) +{ + rsvcHashIterator ite (monitorCbkTable_); + rsvcCbk* tcbk = 0; + rsvcCallback* usrcbk0 = 0; + int found = 0; + rsvcCallback tmp (func, arg); + + for (ite.init (); !ite; ++ite) { + tcbk = (rsvcCbk *) ite (); + usrcbk0 = (rsvcCallback *)tcbk->userptr (); + if (*usrcbk0 == tmp) { + found = 1; + break; + } + } + if (found) + return tcbk; + return 0; +} + +int +rsvcClient::monitorAttr (char* name, char* attr, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + + + if (data.insert (RSVC_MONITOR_TAG, attr) != RSVC_SUCCESS) + status = RSVC_ERROR; + + if (status == RSVC_SUCCESS) + status = monitorCallback ((int)RSVC_MONITOR_ONATTR, data, + func, arg); + return status; +} + +int +rsvcClient::monitorOffAttr (char* name, char* attr, rsvcData& data, + rsvcCbkFunc func, void* arg) +{ + int status = RSVC_SUCCESS; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + + if (data.insert (RSVC_MONITOR_TAG, attr) != RSVC_SUCCESS) + status = RSVC_ERROR; + + if (status == RSVC_SUCCESS) + status = monitorOffCallback ((int)RSVC_MONITOR_OFFATTR, data, + func, arg); + return status; +} + +int +rsvcClient::query (char* name, char* qmsg, + rsvcCbkFunc func, void *arg) +{ + int status = RSVC_SUCCESS; + rsvcData data; + + if (data.insert (RSVC_TABLE_NAME, name) != RSVC_SUCCESS) + status = RSVC_ERROR; + + if (data.insert (RSVC_QUERY_TAG, qmsg) != RSVC_SUCCESS) + status = RSVC_ERROR; + + if (status == RSVC_SUCCESS) + status = commandCallback ((int)RSVC_QUERY, data, + func, arg); + return status; +} + +void +rsvcClient::shutdownServer (void) +{ + rsvcData data; + + commandCallback ((int)RSVC_SERVER_EXIT, data, 0, 0); +} + +int +rsvcClient::streamData (rsvcNetData& data) +{ + size_t datasize = data.streamSize (); + + if (datasize > cbuflen_) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: Streamed data size %d is exceeding %d, resize\n", + datasize, cbuflen_); +#endif + delete []cbuffer_; + cbuflen_ = 2*datasize; + cbuffer_ = new char[cbuflen_]; + if (!cbuffer_) { + fprintf (stderr, "rsvcClient: malloc error on stream data\n"); + exit (1); + } + } + if (data.streamOut (cbuffer_, datasize) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcClient: rsvcNetData stream out error\n"); +#endif + return -1; + } + return datasize; +} + +int +rsvcClient::write_n (int fd, const char* buffer, size_t len) +{ + size_t bytes_written; + int n; + + for (bytes_written = 0; bytes_written < len; bytes_written += n) + { +#ifdef _WIN32 + n = ::send (fd, buffer + bytes_written, len - bytes_written, 0); +#else + n = ::write (fd, buffer + bytes_written, len - bytes_written); +#endif + if (n == -1) { + return -1; + } + } + return bytes_written; +} + +int +rsvcClient::read_n (int fd, char* buffer, size_t len) +{ + size_t bytes_read; + int n = 0; + + for (bytes_read = 0; bytes_read < len; bytes_read += n) + { +#ifdef _WIN32 + n = ::recv (fd, buffer + bytes_read, len - bytes_read, 0); +#else + n = ::read (fd, buffer + bytes_read, len - bytes_read); +#endif + if (n == -1) + return -1; + else if (n == 0) + break; + } + return bytes_read; +} + +void +rsvcClient::lock (void) +{ + lock_ = 1; +} + +void +rsvcClient::unlock (void) +{ + lock_ = 0; +} + + +//============================================================ +// Implemenation of rsvcClientLocker Class +//============================================================ +rsvcClientLocker::rsvcClientLocker (rsvcClient* client) + :cl_ (client) +{ + cl_->lock (); +} + +rsvcClientLocker::~rsvcClientLocker (void) +{ + cl_->unlock (); +} + + + + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcClient.h b/extensions/cdevGenericServer/NameServer/src/rsvcClient.h new file mode 100755 index 0000000..66ad76f --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcClient.h @@ -0,0 +1,290 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Client Handler Class +// +// Limitation on monitor: Callers cannot use same function with same user +// argument to monitor on different pieces +// of database +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_CLIENT_H +#define _RSVC_CLIENT_H + +#include +#include +#include +#include + +#ifdef _WIN32 + #include +#else + #include +#endif + +#include +#include +#include +#include +#include +#include + +class rsvcClientLocker; + +class RSVC_CLASS_SPEC rsvcClient +{ +public: + // constructor + rsvcClient (void); + ~rsvcClient (void); + + // connect to a rsvc server + // if timeout is zero, blocked connect will be used + int connect (char* host, unsigned short port, + double timeout = 0.0); + + // disconnect from the server + int disconnect (void); + + // return whether this client is connected + int connected (void); + + // register a disconnect callback + int disconnectCallback (rsvcCbkFunc func, void* arg); + + // get tcp file descriptor + int getFd (void) const; + + // pend io on this connected client + // Wait until outstanding events occur + // seconds = 0.0 polling + int pendIO (double seconds); + + // wait on this connection forever + int pendIO (void); + + // operations + + // create a table with definition defined in the data object + // the data object has to contain the following tags + // "key" "name" + // "keyExp" "attributename" or "attr0+attr1" + // "keyType" anything + // followed by taged values + + // data return from server inside callback is the database definition + int createMemDbase (char* tablename, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // open a database + // data return from server inside callback is the database definition + int openDatabase (char* tablename, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // insert data into database + // data must be match table definition + int insertValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg, + int overwrite = 0); + + // get data out from database + // data either contain a tagged value to denote a index value + // Example: "id", "model+gold" + // or contains multiple tagged values which can be constructed + // into a key value + int getValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // delete data from database + // data either contain a tagged value to denote a index value + // Example: "id", "model+gold" + // or contains multiple tagged values which can be constructed + // into a key value + int delValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg); + + + // set value for a datum inside database + // data either contain a tagged value to denote a index value + // Example: "id", "model+gold" + // or contains multiple tagged values which can be constructed + // into a key value + // plus a subset of tagged values defined in the table definition + int setValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // monitor incoming entries inside database + // any insertion to a database will trigger a callback + int monitorIncomingEntries (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // stop monitoring the incoming entries inside database + int monitorOffIncomingEntries (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg); + + + // monitor on a data inside a database + // any changes to this data will trigger a callback + // data either contain a tagged value to denote a index value + // Example: "id", "model+gold" + // or contains multiple tagged values which can be constructed + // into a key value + int monitorValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg); + + + // monitor off on a data inside a database + // data either contain a tagged value to denote a index value + // Example: "id", "model+gold" + // or contains multiple tagged values which can be constructed + // into a key value + int monitorOffValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // monitor a single attribute of a data inside a database + // any changes to this attribute will trigger a callback containing a whole data + // data either contain a tagged value to denote a index value + // Example: "id", "model+gold" + // or contains multiple tagged values which can be constructed + // into a key value + int monitorAttr (char* name, char* attrname, + rsvcData& data, rsvcCbkFunc func, void* arg); + + + // monitor a single attribute of a data inside a database + // any changes to this attribute will trigger a callback containing a whole data + // data either contain a tagged value to denote a index value + // Example: "id", "model+gold" + // or contains multiple tagged values which can be constructed + // into a key value + int monitorOffAttr (char* name, char* attrname, + rsvcData& data, rsvcCbkFunc func, void* arg); + + // query a particular database 'name' + // query msg can be like regular C logic expression for all + // attributes + int query (char* name, char* qmsg, + rsvcCbkFunc func, void* arg); + + // test purpose only + void shutdownServer (void); + + +protected: + + // non block tcp connect + static int connect_nonblock (int fd, struct sockaddr* addr, + size_t addrlen, + struct timeval* timeout); + + // cleanup all callbacks + void cleanupCallbacks (void); + + // call all disconnection callbacks + void callAllDiscCbks (void); + + // stream out a network data and return actual number of bytes + int streamData (rsvcNetData& data); + + // low level handle input and handle close + int handle_input (int fd); + int handle_close (int fd); + + // read and write for block socket + static int read_n (int fd, char* buffer, size_t len); + static int write_n (int fd, const char* buffer, size_t len); + + // real processing function + int processData (rsvcNetData& data); + + // real command callback + int commandCallback (int opcode, rsvcData& data, + rsvcCbkFunc func, void* arg); + + + // monitor command callback + int monitorCallback (int opcode, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // monitoroff command callback + int monitorOffCallback (int opcode, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // handle callbacks from server + int cmdCbkFromServer (int status, rsvcData& data, rsvcCbk& cbk); + int monitorCbkFromServer (int status, rsvcData& data, rsvcCbk& cbk); + + // check a monitor callback is in the table + rsvcCbk* monitorCbkInTable (rsvcCbkFunc func, void* arg); + + +private: + // flag of connection + int connected_; + + // tcp socket to the server + int tcp_fd_; + + // server information + char* server_host_; + unsigned short server_port_; + + // lock for client object to prevent from this object being called + // recursivly + int lock_; + void lock (void); + void unlock (void); + + // request id + int reqid_; + // unique callback id + int cbkid_; + + + // disconnection callback list + rsvcSlist discCbkList_; + + // all send/get command callback list + rsvcSlist cmdCbkList_; + // all monitor callback list + rsvcHash monitorCbkTable_; + + // data convertion buffer + char* cbuffer_; + size_t cbuflen_; + + // friend class + friend class rsvcClientLocker; + friend class rsvcDBHandler; + + // deny copy and assignment operator + rsvcClient (const rsvcClient& client); + rsvcClient& operator = (const rsvcClient& client); + +}; + +class rsvcClientLocker +{ +public: + rsvcClientLocker (rsvcClient* client); + ~rsvcClientLocker (void); + +private: + rsvcClient* cl_; + + // deny copy and assignment operations + rsvcClientLocker (const rsvcClientLocker& locker); + rsvcClientLocker& operator = (const rsvcClientLocker& locker); +}; + +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcConfig.h b/extensions/cdevGenericServer/NameServer/src/rsvcConfig.h new file mode 100755 index 0000000..f6e4592 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcConfig.h @@ -0,0 +1,62 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Configuration Header +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_CONFIG_H +#define _RSVC_CONFIG_H + +#define RSVC_SERVER_PORT 10932 +#define RSVC_MAX_KEY_LEN (unsigned int)256 +#define RSVC_KEY_NAME "key" +#define RSVC_TABLE_NAME "table" +#define RSVC_TABLE_NAME_EXT ".def" +#define RSVC_KEY_TYPE_NAME "keyType" +#define RSVC_KEY_EXP_NAME "keyExp" +#define RSVC_MONITOR_TAG "monitorOn" +#define RSVC_QUERY_TAG "query" +#define RSVC_CACHE_MAX 20 /* tuned for name server */ +#define RSVC_CACHE_LF 5 +#define RSVC_RLIMIT_NOFILE 256 +#define RSVC_UDP_BUFFER_SIZE 4096 + + +#define RSVC_OP_UNKNOWN (unsigned int)2000 + +#define RSVC_CREATE_TABLE (unsigned int)1000 +#define RSVC_CREATE_MEMTABLE (unsigned int)1001 +#define RSVC_OPEN_DBASE (unsigned int)1002 +#define RSVC_GET (unsigned int)1010 +#define RSVC_SET (unsigned int)1011 +#define RSVC_DEL (unsigned int)1012 +#define RSVC_INSERT (unsigned int)1013 +#define RSVC_OVERWRITE (unsigned int)1014 +#define RSVC_QUERY (unsigned int)1020 + +#define RSVC_MONITOR_ON (unsigned int)1500 +#define RSVC_MONITOR_ONATTR (unsigned int)1501 +#define RSVC_MONITOR_OFF (unsigned int)1600 +#define RSVC_MONITOR_OFFATTR (unsigned int)1601 + +#define RSVC_MONITOR_ENTRIES (unsigned int)1650 +#define RSVC_MONITOR_OFFENTRIES (unsigned int)1651 + +#define RSVC_SERVER_EXIT (unsigned int)1700 + +#define RSVC_DATA_IN_MEMORY 1 +#define RSVC_DATA_ON_DISK 2 + +#include + +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDBT.cc b/extensions/cdevGenericServer/NameServer/src/rsvcDBT.cc new file mode 100755 index 0000000..be08b93 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDBT.cc @@ -0,0 +1,79 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of C++ DBT wrapper +// +// Author: Jie Chen +// +// Revision History: +// rsvcDBT.cc,v +// Revision 1.1 1998/01/22 17:08:03 akers +// Addition of new NameServer +// +// +// +#include "rsvcDBT.h" + +rsvcDBT::rsvcDBT (void) +:dealloc_ (1) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcDBT Class Object\n"); +#endif + memset (&data_, 0, sizeof (DBT)); +} + +rsvcDBT::~rsvcDBT (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcDBT Class Object\n"); +#endif + if (data_.data && dealloc_) + delete []data_.data; + data_.size = 0; +} + +void * +rsvcDBT::data (void) const +{ + return data_.data; +} + +size_t +rsvcDBT::size (void) const +{ + return data_.size; +} + +void +rsvcDBT::data (void* ptr, int dealloc) +{ + data_.data = ptr; + dealloc_ = dealloc; +} + +void +rsvcDBT::size (size_t len) +{ + data_.size = len; +} + +DBT * +rsvcDBT::dbt (void) +{ + return &data_; +} + +void +rsvcDBT::datacpy (void* data) +{ + memcpy (data_.data, data, data_.size); +} + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDBT.h b/extensions/cdevGenericServer/NameServer/src/rsvcDBT.h new file mode 100755 index 0000000..bbb162a --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDBT.h @@ -0,0 +1,46 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// C++ wrapper class for DBT class with user allocated memory +// +// Reason: Enable automatic memory release +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_DBT_H +#define _RSVC_DBT_H + +#include +#include +#include +#include + +class rsvcDBT +{ +public: + rsvcDBT (void); + ~rsvcDBT (void); + + void* data (void) const; + void data (void *ptr, int dealloc = 1); + size_t size (void) const; + void size (size_t len); + void datacpy (void* data); + + // return data pointer to internal DBT + DBT* dbt (void); + +private: + DBT data_; + int dealloc_; +}; +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcData.cc b/extensions/cdevGenericServer/NameServer/src/rsvcData.cc new file mode 100755 index 0000000..23d9ca5 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcData.cc @@ -0,0 +1,3382 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: rsvc.h +// Generic tool designed to convert arrays of data types from one +// type to another +// +// Author: Walt Akers and Danjin Wu +// +// Revision History: +// rsvcData.cc,v +// Revision 1.3 1998/05/27 16:26:55 chen +// fix a iterator bug on ++ operation +// +// Revision 1.2 1998/01/29 19:10:58 akers +// Ongoing development +// +// Revision 1.1 1998/01/22 17:08:04 akers +// Addition of new NameServer +// +// +// +//-------------------------------------------------------------------------- + +#include +#include +#include +#include "rsvcData.h" +#include "rsvcDataStreamer.h" + +static char* rsvcStrncpy (char* dst, const char* src, size_t len) +{ + if (strlen (src) + 1 <= len) + return strncpy (dst, src, len); + strncpy (dst, src, len - 1); + dst[len - 1] = 0; + return dst; +} + +// ***************************************************************************** +// * rsvc_gcvt: +// * This overloaded function is being used in conjunction with the +// * standard library rsvc_gcvt to correct conversion errors when converting +// * float values. +// ***************************************************************************** +char * rsvcData::rsvc_gcvt(float value, size_t ndigit, char *buf) +{ + char tbuf[32]; + sprintf(tbuf, "%.7g", value); + rsvcStrncpy(buf, tbuf, ndigit); + return buf; +} + +char * rsvcData::rsvc_gcvt(double value, size_t ndigit, char * buf) +{ + char tbuf[32]; + sprintf(tbuf, "%.14g", value); + rsvcStrncpy(buf, tbuf, ndigit); + return buf; +} + +// ***************************************************************************** +// * RSVCConverter: +// * This is the type definition for all RSVC conversion functions. These +// * functions are used to perform data conversion from one RSVC datatype +// * to another. +// ***************************************************************************** +typedef void (*rsvcConverter)(void * input, void * output, size_t nElems); + +// ***************************************************************************** +// * RSVCConversionMatrix: +// * This matrix contains the cdev conversion functions necessary to convert +// * between all cdev data types. The user requests a conversion routime +// * by using the enumerated cdevDataType values that represent the from +// * type and the too type. +// * +// * For instance: +// * To convert from 16 bit integer to 32 bit integer, cdevData would +// * use the command... +// * cdevConversionMatrix[CDEV_INT16][CDEV_INT32](&in16, &out32, 1); +// * +// * To convert an array of 25 floats to an array of 25 doubles, +// * cdevData would use the command... +// * cdevConversionMatrix[CDEV_FLOAT][CDEV_DOUBLE](in, out, 25) +// ***************************************************************************** +extern const rsvcConverter rsvcConversionMatrix [RSVC_INVALID+1][RSVC_INVALID+1]; + +// ***************************************************************************** +// * copy: +// * This function copies the contents of the rsvcData object specified by +// * data into this rsvcData object. It is used by both the copy constructor +// * and by the assignment operator. +// ***************************************************************************** +rsvcData & +rsvcData::copy (const rsvcData & data) +{ + if(this != (rsvcData *)&data) { + remove(); + for(rsvcDataEntry *ptr = data.entries; ptr!=0; ptr = ptr->next_) { + switch(ptr->dataType_) { + case RSVC_BYTE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.cval); + else insert(ptr->tag_, ptr->data_.cptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_INT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.sval); + else insert(ptr->tag_, ptr->data_.sptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_UINT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.usval); + else insert(ptr->tag_, ptr->data_.usptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_INT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.lval); + else insert(ptr->tag_, ptr->data_.lptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_UINT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.ulval); + else insert(ptr->tag_, ptr->data_.ulptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_FLOAT: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.fval); + else insert(ptr->tag_, ptr->data_.fptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_DOUBLE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.dval); + else insert(ptr->tag_, ptr->data_.dptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_STRING: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.str); + else insert(ptr->tag_, ptr->data_.strarr, ptr->elems_, ptr->dim_); + break; + + case RSVC_TIMESTAMP: + if (ptr->dim_==0) insert(ptr->tag_, ptr->data_.ts); + else insert(ptr->tag_, ptr->data_.tsptr, ptr->elems_, ptr->dim_); + break; + + default: + break; + } + } + } + return *this; +} + +// **************************************************************************** +// * insert +// * This function insert entry into data directly +// **************************************************************************** +int +rsvcData::insert (rsvcDataEntry* entry) +{ + + rsvcDataEntry *result = 0, *prev = 0; + + // ********************************************************************* + // * Walk through the list of rsvcDataEntry objects until a matching + // * tag is found, or until no more items are available. + // ********************************************************************* + for(result=entries; result!=0; prev=result, result = result->next_); + + // ********************************************************************* + // * If result is 0, then a matching entry was not found. If the + // * user has specified create, then create a new entry. + // ********************************************************************* + + // ************************************************************* + // * The prev flag is used to indicate the last known + // * rsvcDataEntry object in the list. If prev contains 0, + // * then the list was empty and must be allocated directly. + // ************************************************************* + if( prev == 0 ) + entries = entry; + + // ************************************************************* + // * Otherwise, the new rsvcDataEntry object should be placed + // * at the bottom of the list. + // ************************************************************* + else + prev->next_ = entry; + return RSVC_SUCCESS; +} + + +// ***************************************************************************** +// * lookupTag: +// * This function attempts to locate the specified tag within the rsvcData +// * objects list of rsvcDataEntry objects. If the tag is found, then +// * its associated rsvcDataEntry object will be returned, otherwise, +// * if the caller has specified a non-zero value in the create flag, then +// * the new tag will be added to the list. +// ***************************************************************************** +rsvcDataEntry * +rsvcData::lookupTag(char* tag, int create) +{ + rsvcDataEntry *result = 0, *prev = 0; + + // ********************************************************************* + // * Walk through the list of rsvcDataEntry objects until a matching + // * tag is found, or until no more items are available. + // ********************************************************************* + for(result=entries; + result!=0 && (strcmp (result->tag_, tag)) != 0; + prev=result, result = result->next_); + + // ********************************************************************* + // * If result is 0, then a matching entry was not found. If the + // * user has specified create, then create a new entry. + // ********************************************************************* + if ( result==0 && create ) { + // ************************************************************* + // * The prev flag is used to indicate the last known + // * rsvcDataEntry object in the list. If prev contains 0, + // * then the list was empty and must be allocated directly. + // ************************************************************* + if( prev == 0 ) { + entries = new rsvcDataEntry; + result = entries; + } + // ************************************************************* + // * Otherwise, the new rsvcDataEntry object should be placed + // * at the bottom of the list. + // ************************************************************* + else { + prev->next_ = new rsvcDataEntry; + result = prev->next_; + } + } + + return result; +} + +// ***************************************************************************** +// * setupTag: +// * Convenience function to allow the rsvcData object to more efficiently +// * prepare new rsvcDataEntry objects for data insertion. +// * elemSize is the size of one element in bytes, numElems is the number of +// * elements to allocate, and numDims is the number of dimensions to create. +// ***************************************************************************** +rsvcDataEntry * +rsvcData::setupTag (char* tag, rsvcDataTypes type, size_t elemSize, + size_t numElems, size_t numDims ) +{ + rsvcDataEntry * entry; + if((entry = lookupTag(tag, 1))!=0) { + // ************************************************************* + // * If the entry is already populated and the new data is not + // * multidimensional, clear the old contents. + // ************************************************************* + if((strcmp (entry->tag_, tag) == 0) && numDims<=0) entry->clear(); + + // ************************************************************* + // * If the entry is multidimensional, allocate a new data + // * block for storing the data. + // ************************************************************* + if(numDims == 1) + entry->allocate(numDims, numElems, elemSize); + + // ************************************************************* + // * Populate the entry with the new data. + // ************************************************************* + rsvcStrncpy (entry->tag_, tag, RSVC_TAG_MAX_LEN); + entry->dataType_ = type; + } + return entry; +} + + +// ***************************************************************************** +// * rsvcData: +// * Default constructor for the rsvcData object. Initializes local data. +// ***************************************************************************** +rsvcData::rsvcData ( void ) +:entries (0) +{ + // empty +} + +// ***************************************************************************** +// * rsvcData: +// * Copy constructor. This constructor duplicates the rsvcData object that +// * it has been passed as a parameter. +// ***************************************************************************** +rsvcData::rsvcData ( const rsvcData & data ) +:entries (0) +{ + copy(data); +} + +// ***************************************************************************** +// * ~rsvcData: +// * Default destructor for the rsvcData object. Deallocates local data. +// ***************************************************************************** +rsvcData::~rsvcData( void ) +{ + remove(); +} + +// ***************************************************************************** +// * asciiDump: +// * This function will dump the contents of the rsvcData object to the +// * user specified file descriptor. +// ***************************************************************************** +#ifdef _WIN32 +void rsvcData::asciiDump (long osfHandle) +{ + int fd = _open_osfhandle(osfHandle, _O_WRONLY | _O_APPEND ); + FILE* fp = _fdopen (fd, "a"); +#else +void rsvcData::asciiDump ( FILE * fp ) +{ +#endif + rsvcDataEntry * entry; + char tagText[RSVC_INVALID+1][20]; + int i; + + // ************************************* + // * Load the names of the dataTypes * + // ************************************* + sprintf(tagText[RSVC_BYTE], "8 Bit Integer"); + sprintf(tagText[RSVC_INT16], "16 Bit Integer"); + sprintf(tagText[RSVC_UINT16], "Unsigned 16 Bit Int"); + sprintf(tagText[RSVC_INT32], "32 Bit Integer"); + sprintf(tagText[RSVC_UINT32], "Unsigned 32 Bit Int"); + sprintf(tagText[RSVC_FLOAT], "Float"); + sprintf(tagText[RSVC_DOUBLE], "Double"); + sprintf(tagText[RSVC_STRING], "Char String"); + sprintf(tagText[RSVC_TIMESTAMP], "Time Stamp"); + sprintf(tagText[RSVC_INVALID], "Invalid Data"); + + for(entry=entries; entry!=0; entry=entry->next_) + { + fprintf(fp, "Tag Name: %s\n", entry->tag_); + fprintf(fp, "Data Type: %s", tagText[entry->dataType_]); + fprintf(fp, "[%i]", entry->elems_); + + fprintf(fp, "\nValues: "); + + switch(entry->dataType_) + { + case RSVC_BYTE: + if(entry->dim_==0) fprintf(fp, "% 4i", entry->data_.cval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 4i%s", entry->data_.cptr[i], + (i%13==12)?"\n ":" "); + break; + + case RSVC_INT16: + if(entry->dim_==0) fprintf(fp, "% 6hi", entry->data_.sval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 6hi%s", entry->data_.sptr[i], + (i%9==8)?"\n ":" "); + break; + + case RSVC_UINT16: + if(entry->dim_==0) fprintf(fp, "% 6hu", entry->data_.usval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 6hu%s", entry->data_.usptr[i], + (i%9==8)?"\n ":" "); + break; + + case RSVC_INT32: + if(entry->dim_==0) fprintf(fp, "% 8li", entry->data_.lval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 8li%s", entry->data_.lptr[i], + (i%7==6)?"\n ":" "); + break; + + case RSVC_UINT32: + if(entry->dim_==0) fprintf(fp, "% 8lu", entry->data_.ulval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 8lu%s", entry->data_.ulptr[i], + (i%7==6)?"\n ":" "); + break; + + case RSVC_FLOAT: + if(entry->dim_==0) fprintf(fp, "% 12.5f", entry->data_.fval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 12.5f%s", entry->data_.fptr[i], + (i%5==4)?"\n ":" "); + break; + + case RSVC_DOUBLE: + if(entry->dim_==0) fprintf(fp, "% 14.7f", entry->data_.dval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 14.7f%s", entry->data_.dptr[i], + (i%4==3)?"\n ":" "); + break; + + case RSVC_STRING: + if(entry->dim_==0) fprintf(fp, "%s\n", entry->data_.str); + else for(i=0; ielems_; i++) + fprintf(fp, "%s\n ", entry->data_.strarr[i]); + break; + + case RSVC_TIMESTAMP: + if(entry->dim_==0) + fprintf(fp, "%u sec and %u nsec \n", + entry->data_.ts.secPastEpoch, entry->data_.ts.nsec); + else for(i=0; ielems_; i++) + fprintf(fp, "%u sec and %u nsec \n", + entry->data_.tsptr[i].secPastEpoch, entry->data_.tsptr[i].nsec); + break; + + case RSVC_INVALID: + break; + } + fprintf(fp, "\n\n"); + } + fflush (fp); +#ifdef _WIN32 + _commit (fd); +#endif +} + + +// ***************************************************************************** +// * streamSize: +// * Calculates the size of the Buffer necessary to store the rsvcData +// * object. This function may be used to determine the size of a +// * preallocated buffer for storing the xdr representation of a rsvcData +// * object. The bufLen parameter will receive the size of the buffer, and +// * the elementCount variable will receive the number of elements that will +// * be stored in the buffer. +// ***************************************************************************** +int +rsvcData::streamSize (size_t * bufLen, size_t * elementCount) +{ + rsvcDataEntry * ptr = entries; + int dataSize = 0; + int rsvcElementCnt = 0; + int i; + + // ************************************# + // * CALCULATE THE SIZE OF THE BUFFER # + // ************************************# + + // ************************************* + // * First is magic number * + // ************************************* + dataSize += rsvcStreamSize (_RSVC_MAGIC_NUM); + + // ************************************* + // * Add the size of the tag count int * + // ************************************* + dataSize += rsvcStreamSize (rsvcElementCnt); + + // ************************************* + // * Add the size of each valid item * + // ************************************* + for(ptr=entries; ptr!=0; ptr = ptr->next_) + { + // ***************************** + // * Do not process entries * + // * with RSVC_INVALID as the * + // * dataType or 0 as the tag. * + // ***************************** + if(ptr->dataType_==RSVC_INVALID || ptr->tag_[0] ==0) continue; + + // ***************************** + // * Calculate the number of * + // * elements in this tagged * + // * data item. * + // ***************************** + int numElements = ptr->dim_!=0?ptr->elems_:1; + + // ***************************** + // * Increment the counter * + // ***************************** + rsvcElementCnt++; + + // ***************************** + // * Add the size of the * + // * rsvcDataEntries tag_, * + // ***************************** + dataSize += rsvcStreamSize ((void *)ptr->tag_, RSVC_TAG_MAX_LEN); + + //****************************** + // * dataType_, dim_, elems_. * + // ***************************** + dataSize += 3 * rsvcStreamSize ((int)1); + + // ***************************** + // * Add the size of the data * + // ***************************** + if (ptr->dataType_==RSVC_BYTE) + dataSize += numElements * rsvcStreamSize ((char)1); + else if(ptr->dataType_==RSVC_INT16) + dataSize += numElements * rsvcStreamSize ((short)1); + else if(ptr->dataType_==RSVC_UINT16) + dataSize += numElements * rsvcStreamSize ((unsigned short)1); + else if(ptr->dataType_==RSVC_INT32) + dataSize += numElements * rsvcStreamSize ((int)1); + else if(ptr->dataType_==RSVC_UINT32) + dataSize += numElements * rsvcStreamSize ((unsigned int)1); + else if(ptr->dataType_==RSVC_FLOAT) + dataSize += numElements * rsvcStreamSize ((float) 1.0); + else if(ptr->dataType_==RSVC_DOUBLE) + dataSize += numElements * rsvcStreamSize ((double)1.0); + else if(ptr->dataType_==RSVC_STRING) + { + if(numElements==1) + dataSize += rsvcStreamSize (ptr->data_.str); + else + for(i=0; idata_.strarr[i]); + } + else if(ptr->dataType_==RSVC_TIMESTAMP) + dataSize += numElements * rsvcStreamSize (ptr->data_.ts); + } + + *elementCount = rsvcElementCnt; + *bufLen = dataSize; + + return *bufLen>0?RSVC_SUCCESS:RSVC_ERROR; +} + +// ***************************************************************************** +// * streamOut: +// * This function encapsulates the contents of the rsvcData class into a +// * binary stream. This function allocates the buffer and returns the new +// * buffer and the buffer size. +// ***************************************************************************** +int +rsvcData::streamOut ( char ** buf, size_t * bufLen ) +{ + size_t count = 0; + int st = RSVC_SUCCESS; + + // ************************************# + // * Calculate the size of the buffer # + // ************************************# + if ((st = streamSize(bufLen, &count)) != RSVC_SUCCESS) + return st; + + // ************************************# + // * Allocate the buffer and call the # + // * export function. # + // ************************************# + if((*buf = new char[*bufLen])!=0) streamOut (*buf, *bufLen, count); + + return buf==0?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * streamOut +// * This function encapsulates the contents of the rsvcData class into a +// * preallocated binary stream. The buf parameter contains the address of +// * the caller allocated buffer, the bufLen parameter specifies the size +// * of the buffer, and the count parameter specifies the number of tagged +// * data items that will be copied from the rsvcData object into the +// * binary stream. +// ***************************************************************************** +int +rsvcData::streamOut ( char * buf, size_t bufLen, size_t count) +{ + rsvcDataEntry * ptr; + int dataSize = bufLen; + int rsvcElementCnt = count; + int i; + int idx = 0; + // float ftmp; + // double dtmp; + int rsvcError = RSVC_SUCCESS; + + // create stream writer without deleting buffer + rsvcDataStreamWriter writer (buf, bufLen, 0); + + // ************************************# + // * Transfer the data to the buffer # + // ************************************# + + // ************************************* + // * Write magic number first * + // ************************************* + if ((rsvcError = writer.write (_RSVC_MAGIC_NUM)) != RSVC_SUCCESS) + return rsvcError; + + // ************************************* + // * Write the number of elements * + // ************************************* + if ((rsvcError = writer.write (rsvcElementCnt)) != RSVC_SUCCESS) + return rsvcError; + + // ************************************* + // * Write each valid item. * + // ************************************* + for(ptr = entries; ptr != 0 && rsvcError == RSVC_SUCCESS; ptr = ptr->next_) + { + // ***************************** + // * Do not process entries * + // * with RSVC_INVALID as the * + // * dataType or 0 as the tag. * + // ***************************** + if(ptr->dataType_==RSVC_INVALID || ptr->tag_==0) continue; + + // ***************************** + // * Calculate the number of * + // * elements in this tagged * + // * data item. * + // ***************************** + int numElements = ptr->dim_!=0?ptr->elems_:1; + + // ***************************** + // * Decrement the counter * + // ***************************** + rsvcElementCnt--; + + // ***************************** + // * Write the tag_, * + // * write dataType_ * + // * dim_, and elems_ of the * + // * rsvcDataEntry object. * + // ***************************** + + if (writer.write ((void *)ptr->tag_, RSVC_TAG_MAX_LEN) != RSVC_SUCCESS || + writer.write (ptr->dataType_) != RSVC_SUCCESS || + writer.write (ptr->dim_) != RSVC_SUCCESS || + writer.write (ptr->elems_) != RSVC_SUCCESS) { + rsvcError = RSVC_ERROR; + return rsvcError; + } + + // ***************************** + // * Write the data * + // ***************************** + if (ptr->dataType_==RSVC_BYTE) { + if(numElements==1) + rsvcError = writer.write (ptr->data_.cval); + else { + for(i=0; idata_.cptr[i]); + } + } + else if(ptr->dataType_==RSVC_INT16) + { + if(numElements==1) + rsvcError = writer.write (ptr->data_.sval); + else { + for(i=0; idata_.sptr[i]); + } + } + else if(ptr->dataType_==RSVC_UINT16) + { + if(numElements==1) + rsvcError = writer.write (ptr->data_.usval); + else { + for(i=0; idata_.usptr[i]); + } + } + else if(ptr->dataType_==RSVC_INT32) + { + if(numElements==1) + rsvcError = writer.write (ptr->data_.lval); + else { + for(i=0; idata_.lptr[i]); + } + } + else if(ptr->dataType_==RSVC_UINT32) + { + if(numElements==1) + rsvcError = writer.write (ptr->data_.ulval); + else { + for(i=0; idata_.ulptr[i]); + } + } + else if(ptr->dataType_==RSVC_FLOAT) + { + if(numElements==1) + rsvcError = writer.write (ptr->data_.fval); + else { + for(i=0; idata_.fptr[i]); + } + } + else if(ptr->dataType_==RSVC_DOUBLE) + { + if(numElements==1) + rsvcError = writer.write (ptr->data_.dval); + else { + for(i=0; idata_.dptr[i]); + } + } + else if(ptr->dataType_==RSVC_STRING) + { + if(numElements==1) + rsvcError = writer.write (ptr->data_.str); + else { + for(i=0; idata_.strarr[i]); + } + } + else if(ptr->dataType_==RSVC_TIMESTAMP) + { + // rsvc_TS_STAMP tmpts; + if(numElements==1) + rsvcError = writer.write (ptr->data_.ts); + else { + for(i=0; idata_.tsptr[i]); + } + } + } + + return rsvcError; +} + +// ***************************************************************************** +// * streamIn +// * This function populates the rsvcData class using the contents of a +// * binary buffer that has bee created by the xdrExport function. +// ***************************************************************************** +int +rsvcData::streamIn ( char * buf, size_t bufLen) +{ + int rsvcElementCnt; + int i, j; + int rsvcError = RSVC_SUCCESS; + + if(buf==0 || bufLen==0) return RSVC_INVALIDARG; + + rsvcDataStreamReader reader (buf, bufLen, 0); + // ************************************* + // * Deallocate any data previously * + // * assigned to the rsvcData class. * + // ************************************* + remove(); + + // ************************************* + // * Read the magic number from buffer * + // ************************************* + long magic; + + if (reader.read (magic) != RSVC_SUCCESS || magic != _RSVC_MAGIC_NUM) { + printf ("Magic number mismatch 0x%x != 0x%x\n", magic, _RSVC_MAGIC_NUM); + rsvcError = RSVC_ERROR; + return rsvcError; + } + + // ************************************* + // * Read the element count from the * + // * buffer. * + // ************************************* + rsvcError = reader.read (rsvcElementCnt); + + // ************************************* + // * Process each tagged element in * + // * the buffer. * + // ************************************* + for(i=0; idata_.cval); + else for(j=0; jdata_.cptr[j]); + } + break; + + case RSVC_INT16: + if((entry = setupTag(tag_, dataType_, sizeof(short), + numElements, dim_))!=0) { + if(numElements==1) + rsvcError = reader.read(entry->data_.sval); + else + for(j=0; jdata_.sptr[j]); + } + break; + + case RSVC_UINT16: + if((entry = setupTag(tag_, dataType_, sizeof(unsigned short), + numElements, dim_))!=0) { + if(numElements==1) + rsvcError = reader.read (entry->data_.usval); + else + for(j=0; jdata_.usptr[j]); + } + break; + + case RSVC_INT32: + if((entry = setupTag(tag_, dataType_, sizeof(long), + numElements, dim_))!=0) { + + if(numElements==1) + rsvcError = reader.read (entry->data_.lval); + else + for(j=0; jdata_.lptr[j]); + } + break; + + case RSVC_UINT32: + if((entry = setupTag(tag_, dataType_, sizeof(unsigned long), + numElements, dim_))!=0) { + if(numElements==1) + rsvcError = reader.read(entry->data_.ulval); + else + for(j=0; jdata_.ulptr[j]); + } + break; + + case RSVC_FLOAT: + if((entry = setupTag(tag_, dataType_, sizeof(float), + numElements, dim_))!=0) { + if(numElements==1) + rsvcError = reader.read (entry->data_.fval); + else + for(j=0; jdata_.fptr[j]); + } + break; + + case RSVC_DOUBLE: + if((entry = setupTag(tag_, dataType_, sizeof(double), + numElements, dim_))!=0) { + if(numElements==1) + rsvcError = reader.read (entry->data_.dval); + else for(j=0; jdata_.dptr[j]); + } + break; + + case RSVC_STRING: + { + char ** ptr = new char *[numElements]; + memset(ptr, 0, sizeof(char *)*numElements); + + for(j=0; jdata_.ts); + else + for(j=0; jdata_.tsptr[j]); + } + break; + + case RSVC_INVALID: + break; + } + } + + } + + return rsvcError; +} + +// ***************************************************************************** +// * remove: +// * Removes the all rsvcDataEntry objects from the rsvcData object. +// ***************************************************************************** +void rsvcData::remove( void ) +{ + while(entries!=0) + { + rsvcDataEntry * ptr = entries; + entries = ptr->next_; + delete ptr; + } +} + +// ***************************************************************************** +// * remove: +// * Removes a specified tagged data item from the rsvcData object. +// ***************************************************************************** +void rsvcData::remove(char* tag) +{ + rsvcDataEntry *result = 0, *prev = 0; + + // ********************************************************************* + // * Walk through the list of rsvcDataEntry objects until a matching + // * tag is found, or until no more items are available. + // ********************************************************************* + for(result=entries; + result!=0 && strcmp (result->tag_, tag) != 0; + prev=result, result = result->next_); + + if(result!=0) + { + if(prev!=0) prev->next_ = result->next_; + else entries = result->next_; + delete result; + } +} + +// ********************************************************************* +// * changeTag: +// * Replace a new tag with the old one within the +// * rsvcData object. If the old one can not be not found, +// * RSVC_NOTFOUND is returned. If the new tag has already +// * been found in that rsvcData object, RSVC_ERROR is returned. +// ********************************************************************* +int rsvcData::changeTag(char* oldTag, char* newTag) +{ + int result; + rsvcDataEntry *entry; + if((entry=lookupTag(oldTag)) == 0) result = RSVC_NOTFOUND; + else { + if( lookupTag(newTag) != 0) result = RSVC_ERROR; + else { + rsvcStrncpy (entry->tag_, newTag, RSVC_TAG_MAX_LEN); + result = RSVC_SUCCESS; + } + } + return result; +} + +// ********************************************************************* +// * dupWithTag: +// * copy data with tag 'old_tag' to tag 'new_tag'. +// * rsvcData object. If the old one can not be not found, +// * RSVC_NOTFOUND is returned. If the new tag has already +// * been found in that rsvcData object, RSVC_ERROR is returned. +// ********************************************************************* +int rsvcData::dupWithTag (char* old_tag, char* new_tag) +{ + int result; + rsvcDataEntry* entry; + rsvcDataEntry* newentry; + + if ((entry = lookupTag (old_tag)) == 0) + result = RSVC_NOTFOUND; + else { + if (lookupTag (new_tag) != 0) + result = RSVC_ERROR; + else { + newentry = new rsvcDataEntry (*entry); + rsvcStrncpy (newentry->tag_, new_tag, RSVC_TAG_MAX_LEN); + // now put this entry into the list + newentry->next_ = entries; + entries = newentry; + result = RSVC_SUCCESS; + } + } + return result; +} + +// ***************************************************************************** +// * getType: +// * Retrieves the rsvcDataTypes of the referenced tagged data item. +// * If no item with that tag is within the rsvcData object, then +// * RSVC_INVALID is returned. +// ***************************************************************************** +rsvcDataTypes rsvcData::getType(char* tag) +{ + rsvcDataEntry * entry = lookupTag(tag); + return entry==0?RSVC_INVALID:entry->dataType_; +} + +// ***************************************************************************** +// * getDim: +// * Obtains the number of dimensions in the specified tagged data +// * item. Returns RSVC_SUCCESS if the tagged item exists, otherwise, +// * RSVC_NOTFOUND is returned. +// ***************************************************************************** +int rsvcData::getDim(char* tag, size_t *dim) +{ + rsvcDataEntry * entry = lookupTag(tag); + *dim = entry==0?0:entry->dim_; + return entry==0?RSVC_NOTFOUND:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * getElems: +// * Obtains the number of elements in the specified tagged data +// * item. Returns RSVC_SUCCESS if the tagged item exists, otherwise, +// * RSVC_NOTFOUND is returned. +// ***************************************************************************** +int rsvcData::getElems(char* tag, size_t *elems) +{ + rsvcDataEntry * entry = lookupTag(tag); + *elems = entry==0?0:(entry->dim_>0?entry->elems_:1); + return entry==0?RSVC_NOTFOUND:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar character value into a rsvcDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, BYTE data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_BYTE, sizeof(char), 1, 0))!=0) + { + entry->data_.cval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar short int value into a rsvcDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, short data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_INT16, sizeof(short), 1, 0))!=0) + { + entry->data_.sval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar unsigned short int value into a +// * rsvcDataEntry object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, unsigned short data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_UINT16, sizeof(unsigned short), 1, 0))!=0) + { + entry->data_.usval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar long int value into a rsvcDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, int data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_INT32, sizeof(long), 1, 0))!=0) + { + entry->data_.lval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar unsigned long int value into a +// * rsvcDataEntry object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, unsigned int data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_UINT32, sizeof(long), 1, 0))!=0) + { + entry->data_.ulval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar long int value into a rsvcDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, long data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_INT32, sizeof(long), 1, 0))!=0) + { + entry->data_.lval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar unsigned long int value into a +// * rsvcDataEntry object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, unsigned long data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_UINT32, sizeof(long), 1, 0))!=0) + { + entry->data_.ulval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar float value into a rsvcDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, float data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_FLOAT, sizeof(float), 1, 0))!=0) + { + entry->data_.fval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar double value into a rsvcDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert(char* tag, double data) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_DOUBLE, sizeof(double), 1, 0))!=0) + { + entry->data_.dval= data; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a time stamp value into a rsvcDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int rsvcData::insert ( char* tag, rsvc_TS_STAMP data ) +{ + rsvcDataEntry * entry; + + if((entry = setupTag(tag, RSVC_TIMESTAMP, sizeof(rsvc_TS_STAMP), 1, 0))!=0) + { + entry->data_.ts.secPastEpoch = data.secPastEpoch; + entry->data_.ts.nsec = data.nsec; + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of characters arrays of data +// * into a rsvcData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, BYTE * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_BYTE, sizeof(char), len, ndim))!=0) + { + memcpy(entry->data_.cptr, data, len*sizeof(char)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of short int arrays of data +// * into a rsvcData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, short * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_INT16, sizeof(short), len, ndim))!=0) + { + memcpy(entry->data_.sptr, data, len*sizeof(short)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of unsigned short int arrays +// * of data into a rsvcData object. The len variable contains the total +// * number of elements to be inserted, the ndim variable indicates the +// * number of dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, unsigned short * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_UINT16, sizeof(unsigned short), len, ndim))!=0) + { + memcpy(entry->data_.usptr, data, len*sizeof(unsigned short)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of long int arrays of data +// * into a rsvcData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, int * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_INT32, sizeof(long), len, ndim))!=0) + { + memcpy(entry->data_.lptr, data, len*sizeof(long)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of unsigned long int arrays +// * of data into a rsvcData object. The len variable contains the total +// * number of elements to be inserted, the ndim variable indicates the +// * number of dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, unsigned int * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_UINT32, sizeof(unsigned long), len, ndim))!=0) + { + memcpy(entry->data_.ulptr, data, len*sizeof(unsigned long)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of long int arrays of data +// * into a rsvcData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, long * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_INT32, sizeof(long), len, ndim))!=0) + { + memcpy(entry->data_.lptr, data, len*sizeof(long)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of unsigned long int arrays +// * of data into a rsvcData object. The len variable contains the total +// * number of elements to be inserted, the ndim variable indicates the +// * number of dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, unsigned long * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_UINT32, sizeof(unsigned long), len, ndim))!=0) + { + memcpy(entry->data_.ulptr, data, len*sizeof(unsigned long)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of float arrays of data +// * into a rsvcData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, float * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_FLOAT, sizeof(float), len, ndim))!=0) + { + memcpy(entry->data_.fptr, data, len*sizeof(float)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of double arrays of data +// * into a rsvcData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int rsvcData::insert (char* tag, double * data, size_t len, size_t ndim) +{ + rsvcDataEntry * entry; + + if(len==1 && data!=0) return insert(tag, *data); + else if(len<=0 || data==0) return RSVC_INVALIDARG; + else if((entry = setupTag(tag, RSVC_DOUBLE, sizeof(double), len, ndim))!=0) + { + memcpy(entry->data_.dptr, data, len*sizeof(double)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of a character string into +// * a rsvcData object. The length of the string is calculated using the +// * strlen function. It is important to note, that although this data item +// * uses the array_ block within the rsvcDataEntry object, it has no +// * rsvcBounds information associated with it. +// ***************************************************************************** +int rsvcData::insert (char* tag, char * data ) +{ + rsvcDataEntry * entry; + int result = RSVC_ERROR; + int len = data!=0?strlen(data)+1:0; + + if(len>0 && (entry = lookupTag(tag, 1))!=0) { + // ************************************************************* + // * Allocate a new data block for storing the character string. + // * Note that the number of dimensions will be zero, but the + // * array_ element within the rsvcDataEntry object will still + // * be used. + // ************************************************************* + entry->allocate(0, len, sizeof(char)); + + // ************************************************************* + // * Populate the entry with the new data. + // ************************************************************* + rsvcStrncpy (entry->tag_, tag, RSVC_TAG_MAX_LEN); + entry->dataType_ = RSVC_STRING; + memcpy(entry->data_.str, data, len); + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of an array of character +// * strings. Unlike the individual character string, this data may have +// * rsvcBounds data associated within it. +// ***************************************************************************** +int rsvcData::insert (char* tag, char ** data, size_t len, size_t ndim ) +{ + int result = RSVC_SUCCESS; + rsvcDataEntry * entry; + + // ********************************************************************* + // * If the user specified len is invalid (or 0 by default), walk + // * through the array of pointers until 0 is found. + // ********************************************************************* + if(len<=0) for(len=0; data && data[len]!=0; len++); + if(len==0) result = RSVC_INVALIDARG; + else if(len==1) result = insert(tag, *data); + else + { + int i; + size_t dataLen = 0; + + // ************************************************************* + // * To determine the data space needed to store an array of + // * character strings, the function must calculate the length + // * of each character string (plus one for the 0 terminator), + // * then add in the space necessary to store the pointers. + // ************************************************************* + for(i=0; ielems_ = len; + entry->bytes_ = 4; + + // ***************************************************** + // * Set the pointer within the string array to point + // * to the extra memory allocated at the end of the + // * entry->data_.strarr block. Then copy the new data + // * into the string array. + // ***************************************************** + char ** ptr = entry->data_.strarr; + ptr[0] = (char *)(&entry->data_.strarr[len+1]); + strcpy(ptr[0], data[0]); + for(i=1; idata_.tsptr, data, len*sizeof(rsvc_TS_STAMP)); + } + return (entry==0)?RSVC_ERROR:RSVC_SUCCESS; +} + + +// ***************************************************************************** +// * get: +// * This function retrieves a character value specified by tag from the +// * rsvcData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, BYTE * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_BYTE] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_BYTE] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves an short integer value specified by tag from the +// * rsvcData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, short * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_INT16] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_INT16] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves an unsigned short integer value specified by tag +// * from the rsvcData object. This value may be either scalar or an array. +// * If the data is an array, the user must have preallocated sufficient +// * space to store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, unsigned short * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_UINT16] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_UINT16] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves an long integer value specified by tag from the +// * rsvcData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, int * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_INT32] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_INT32] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves an unsigned long integer value specified by tag +// * from the rsvcData object. This value may be either scalar or an array. +// * If the data is an array, the user must have preallocated sufficient +// * space to store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, unsigned int * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_UINT32] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_UINT32] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + + +// ***************************************************************************** +// * get: +// * This function retrieves an long integer value specified by tag from the +// * rsvcData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, long * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_INT32] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_INT32] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves an unsigned long integer value specified by tag +// * from the rsvcData object. This value may be either scalar or an array. +// * If the data is an array, the user must have preallocated sufficient +// * space to store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, unsigned long * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_UINT32] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_UINT32] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves a floating point value specified by tag from the +// * rsvcData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, float * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_FLOAT] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_FLOAT] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + + +// ***************************************************************************** +// * get: +// * This function retrieves a double float value specified by tag from the +// * rsvcData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int rsvcData::get(char* tag, double * data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_DOUBLE] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_DOUBLE] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves a time stamp value specified by tag from the +// * rsvcData object. +// ***************************************************************************** +int rsvcData::get(char* tag, rsvc_TS_STAMP * data) +{ + int result; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_TIMESTAMP] + (entry->data_.vptr, data, entry->elems_); + else + rsvcConversionMatrix[entry->dataType_][RSVC_TIMESTAMP] + (&entry->data_, data, 1); + result = RSVC_SUCCESS; + } + return result; +} + + +// ***************************************************************************** +// * get: +// * This function retrieves a char string value specified by tag from the +// * rsvcData object. For simplicity, this method operates differently +// * than the other get methods. +// ***************************************************************************** +int rsvcData::get(char* tag, char * data, size_t len) +{ + int nelem = 1, result = RSVC_NOTFOUND; + rsvcDataEntry * entry; + if(data!=0 && (entry=lookupTag(tag, 0))!=0) + { + if(entry->dim_ > 0)nelem = entry->elems_; + + switch(entry->dataType_) + { + case RSVC_BYTE: + if(nelem==1) sprintf(data, "%.*s", len, ltoa(entry->data_.cval)); + else sprintf(data, "%.*s", len, ltoa(*entry->data_.str)); + break; + case RSVC_INT16: + if(nelem==1) sprintf(data, "%.*s", len, ltoa(entry->data_.sval)); + else sprintf(data, "%.*s", len, ltoa(*entry->data_.sptr)); + break; + case RSVC_UINT16: + if(nelem==1) sprintf(data, "%.*s", len, ultoa(entry->data_.usval)); + else sprintf(data, "%.*s", len, ultoa(*entry->data_.usptr)); + break; + case RSVC_INT32: + if(nelem==1) sprintf(data, "%.*s", len, ltoa(entry->data_.lval)); + else sprintf(data, "%.*s", len, ltoa(*entry->data_.lptr)); + break; + case RSVC_UINT32: + if(nelem==1) sprintf(data, "%.*s", len, ultoa(entry->data_.ulval)); + else sprintf(data, "%.*s", len, ultoa(*entry->data_.ulptr)); + break; + case RSVC_FLOAT: + if(nelem==1) rsvc_gcvt(entry->data_.fval, len, data); + else rsvc_gcvt(*entry->data_.fptr, len, data); + break; + case RSVC_DOUBLE: + if(nelem==1) rsvc_gcvt(entry->data_.dval, len, data); + else rsvc_gcvt(*entry->data_.dptr, len, data); + break; + case RSVC_STRING: + if(nelem==1) rsvcStrncpy(data, entry->data_.str, len); + else rsvcStrncpy(data, entry->data_.strarr[0], len); + data[len-1] = 0; + break; + case RSVC_TIMESTAMP: + if(nelem==1) + rsvcStrncpy(data, ctime((time_t *)&(entry->data_.ts.secPastEpoch)), len); + data[len-1] = 0; + break; + + default: + break; + } + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * get: +// * This function retrieves a char string array specified by tag from the +// * rsvcData object. For simplicity, this method operates differently +// * than the other get methods. +// ***************************************************************************** +int rsvcData::get(char* tag, char ** data) +{ + int result, nelem=1; + rsvcDataEntry * entry; + + if(data==0) result = RSVC_INVALIDARG; + else if((entry=lookupTag(tag, 0))==0) result = RSVC_NOTFOUND; + else + { + if(entry->dim_ > 0) + rsvcConversionMatrix[entry->dataType_][RSVC_STRING] + (entry->data_.vptr, data, entry->elems_); + else rsvcConversionMatrix[entry->dataType_][RSVC_STRING] + (&entry->data_, data, 1); + + result = RSVC_SUCCESS; + } + return result; +} + +// ***************************************************************************** +// * find: +// * Allows the user to directly extract a pointer to the internal data +// * buffer that the rsvcDataEntry object uses to store data. +// ***************************************************************************** +int rsvcData::find(char* tag, void* &data) +{ + int result = RSVC_NOTFOUND; + rsvcDataEntry * entry; + if((entry=lookupTag(tag, 0))!=0) + { + if(entry->dim_>0 || entry->dataType_==RSVC_STRING) data = entry->data_.vptr; + else data = &entry->data_; + result = RSVC_SUCCESS; + } + else data = 0; + return result; +} + +// ********************************************************************* +// * replace: +// * This function allows part or all taged values being replaced +// * by other taged values represented by a rsvcData +// ********************************************************************* +int +rsvcData::replace (const rsvcData& data) +{ + void* dptr = 0; + int found = 0; + for(rsvcDataEntry *ptr = data.entries; ptr!=0; ptr = ptr->next_) { + if (find (ptr->tag_, dptr) == RSVC_SUCCESS) { + found = 1; + remove (ptr->tag_); + switch(ptr->dataType_) { + case RSVC_BYTE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.cval); + else insert(ptr->tag_, ptr->data_.cptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_INT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.sval); + else insert(ptr->tag_, ptr->data_.sptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_UINT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.usval); + else insert(ptr->tag_, ptr->data_.usptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_INT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.lval); + else insert(ptr->tag_, ptr->data_.lptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_UINT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.ulval); + else insert(ptr->tag_, ptr->data_.ulptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_FLOAT: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.fval); + else insert(ptr->tag_, ptr->data_.fptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_DOUBLE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.dval); + else insert(ptr->tag_, ptr->data_.dptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_STRING: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.str); + else insert(ptr->tag_, ptr->data_.strarr, ptr->elems_, ptr->dim_); + break; + + case RSVC_TIMESTAMP: + if (ptr->dim_==0) insert(ptr->tag_, ptr->data_.ts); + else insert(ptr->tag_, ptr->data_.tsptr, ptr->elems_, ptr->dim_); + break; + + default: + break; + } + } + } + if (found) + return RSVC_SUCCESS; + return RSVC_ERROR; +} + + +// ***************************************************************************** +// * operator == : +// * This method will allow the caller to rapidly determine if two rsvcData +// * objects contain identical fields and values... +// * +// * In the first step, the method will count the total number of fields in +// * both objects... if they are not equal an error will be returned... +// * +// * Next the method will begin getting pointers to the rsvcDataEntry objects +// * that are stored in each object and will use their embedded comparison +// * operators to compare the contents of each of them. +// ***************************************************************************** +int rsvcData::operator == ( rsvcData & data ) +{ + int result = 1; + rsvcDataEntry *entry1, *entry2; + int entry1Cnt=0, entry2Cnt=0; + + for(entry1=entries; entry1!=0; entry1=entry1->next_) entry1Cnt++; + for(entry2=data.entries; entry2!=0; entry2=entry2->next_) entry2Cnt++; + if(entry1Cnt==entry2Cnt) + { + result = 0; + for(entry1=entries; !result && entry1!=0; entry1=entry1->next_) + { + if((entry2 = data.lookupTag(entry1->tag_))!=0) + { + result = !(entry1->operator == (*entry2)); + } + else result = -1; + } + } + return !result; +} + +// ***************************************************************************** +// * Assignment operation: +// * This operation will reassign data object to another object +// ***************************************************************************** +rsvcData& +rsvcData::operator = (const rsvcData& data) +{ + return copy (data); +} + +// ***************************************************************************** +// * Append operation: +// * This operation will append a rsvcData onto an existing rsvcData +// * and return this object. If there is confilicts among tags, the +// * appended one wins +// ***************************************************************************** +rsvcData& +rsvcData::operator += (const rsvcData& data) +{ + for(rsvcDataEntry *ptr = data.entries; ptr!=0; ptr = ptr->next_) { + switch(ptr->dataType_) { + case RSVC_BYTE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.cval); + else insert(ptr->tag_, ptr->data_.cptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_INT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.sval); + else insert(ptr->tag_, ptr->data_.sptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_UINT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.usval); + else insert(ptr->tag_, ptr->data_.usptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_INT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.lval); + else insert(ptr->tag_, ptr->data_.lptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_UINT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.ulval); + else insert(ptr->tag_, ptr->data_.ulptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_FLOAT: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.fval); + else insert(ptr->tag_, ptr->data_.fptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_DOUBLE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.dval); + else insert(ptr->tag_, ptr->data_.dptr, ptr->elems_, ptr->dim_); + break; + + case RSVC_STRING: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.str); + else insert(ptr->tag_, ptr->data_.strarr, ptr->elems_, ptr->dim_); + break; + + case RSVC_TIMESTAMP: + if (ptr->dim_==0) insert(ptr->tag_, ptr->data_.ts); + else insert(ptr->tag_, ptr->data_.tsptr, ptr->elems_, ptr->dim_); + break; + + default: + break; + } + } + return *this; +} + + +// ***************************************************************************** +// * rsvc Conversion Utilities +// * These functions are incorporated into the rsvcConversionMatrix and are +// * used to convert between rsvcDataTypes. Because these functions are +// * defined for use specifically within the rsvcData object, they are not +// * declared in the header file and should not be used by external modules +// * or applications. +// * +// * All rsvc function sthat use these utilities should access them through +// * the rsvcConversionMatrix array as described at the beginning of this +// * file. +// ***************************************************************************** + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_BYTE ( void * input, void * output, size_t nElems ) +{ + memcpy(output, input, nElems*sizeof(char)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((short *)output)[nElems] = (short)((BYTE *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((BYTE *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((long *)output)[nElems] = (long)((BYTE *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((BYTE *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((float *)output)[nElems] = (float)((BYTE *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((double *)output)[nElems] = (double)((BYTE *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_STRING ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = new char[strlen(ltoa(((BYTE *)input)[nElems]))+1]; + strcpy(((char **)output)[nElems], ltoa(((BYTE *)input)[nElems])); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_BYTE_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch = (unsigned long)((BYTE *)input)[nElems]; + ((rsvc_TS_STAMP *)output)[nElems].nsec = 0; + } + fprintf(stderr, "warning: Byte converts to timestamp struct, data may be invalid\n"); +} + +// ***************************************************************************** +// * rsvcConvert: +// * 8 Bit Integer to Invalid Conversion Facilities... Does nothing +// ***************************************************************************** +void rsvcConvert_BYTE_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((char *)output)[nElems] = (char)((short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_INT16 ( void * input, void * output, size_t nElems ) +{ + memcpy(output, input, nElems*sizeof(short)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((long *)output)[nElems] = (long)((short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((float *)output)[nElems] = (float)((short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((double *)output)[nElems] = (double)((short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_STRING ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = new char[strlen(ltoa(((short *)input)[nElems]))+1]; + strcpy(((char **)output)[nElems], ltoa(((short *)input)[nElems])); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT16_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch = (unsigned long)((short *)input)[nElems]; + ((rsvc_TS_STAMP *)output)[nElems].nsec = 0; + } + fprintf(stderr, "warning: INT16 converts to timestamp struct, data may be invalid\n"); +} + +// ***************************************************************************** +// * rsvcConvert: +// * 16 Bit Integer to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_INT16_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((char *)output)[nElems] = (char)((unsigned short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((short *)output)[nElems] = (unsigned short)((unsigned short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + memcpy(output, input, nElems*sizeof(unsigned short)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((long *)output)[nElems] = (long)((unsigned short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((unsigned short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((float *)output)[nElems] = (float)((unsigned short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0){ + nElems--; ((double *)output)[nElems] = (double)((unsigned short *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_STRING ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = new char[strlen(ultoa(((unsigned short *)input)[nElems]))+1]; + strcpy(((char **)output)[nElems], ultoa(((unsigned short *)input)[nElems])); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT16_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch=(unsigned long)((unsigned short *)input)[nElems]; + ((rsvc_TS_STAMP *)output)[nElems].nsec = 0; + } + fprintf(stderr, "warning: UINT16 converts to timestamp struct, data may be invalid\n"); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 16 Bit Integer to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_UINT16_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((char *)output)[nElems] = (char)((long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((short *)output)[nElems] = (short)((long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_INT32 ( void * input, void * output, size_t nElems ) +{ + memcpy(output, input, nElems*sizeof(long)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((float *)output)[nElems] = (float)((long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((double *)output)[nElems] = (double)((long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_STRING ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = new char[strlen(ltoa(((long *)input)[nElems]))+1]; + strcpy(((char **)output)[nElems], ltoa(((long *)input)[nElems])); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_INT32_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch=(unsigned long)((long *)input)[nElems]; + ((rsvc_TS_STAMP *)output)[nElems].nsec = 0; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * 32 Bit Integer to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_INT32_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((char *)output)[nElems] = (char)((unsigned long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((short *)output)[nElems] = (short)((unsigned long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((unsigned long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((long *)output)[nElems] = (unsigned long)((unsigned long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + memcpy(output, input, nElems*sizeof(unsigned long)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((float *)output)[nElems] = (float)((unsigned long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((double *)output)[nElems] = (double)((unsigned long *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_STRING ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = new char[strlen(ultoa(((unsigned long *)input)[nElems]))+1]; + strcpy(((char **)output)[nElems], ultoa(((unsigned long *)input)[nElems])); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_UINT32_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch=((unsigned long *)input)[nElems]; + ((rsvc_TS_STAMP *)output)[nElems].nsec = 0; + } +} + + +// ***************************************************************************** +// * rsvcConvert: +// * Unsigned 32 Bit Integer to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_UINT32_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((char *)output)[nElems] = (char)((float *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((short *)output)[nElems] = (short)((float *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((float *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((long *)output)[nElems] = (long)((float *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((float *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + memcpy(output, input, nElems*sizeof(float)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((double *)output)[nElems] = (double)((float *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_STRING ( void * input, void * output, size_t nElems ) +{ + char buf[32]; + while(nElems>0) { + nElems--; + rsvcData::rsvc_gcvt(((float *)input)[nElems], (size_t)32, buf); + ((char **)output)[nElems] = new char[strlen(buf)+1]; + strcpy(((char **)output)[nElems], buf); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_FLOAT_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch=(unsigned long)((float *)input)[nElems]; + ((rsvc_TS_STAMP *)output)[nElems].nsec = + (unsigned long)(((float)((float *)input)[nElems]-(unsigned long)((float *)input)[nElems])*1000000000); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Floating Point to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_FLOAT_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((char *)output)[nElems] = (char)((double *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((short *)output)[nElems] = (short)((double *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((double *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((long *)output)[nElems] = (long)((double *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((double *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((float *)output)[nElems] = (float)((double *)input)[nElems]; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + memcpy(output, input, nElems*sizeof(double)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_STRING ( void * input, void * output, size_t nElems ) +{ + char buf[32]; + while(nElems>0) { + nElems--; + rsvcData::rsvc_gcvt(((double *)input)[nElems], 32, buf); + ((char **)output)[nElems] = new char[strlen(buf)+1]; + strcpy(((char **)output)[nElems], buf); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch= + (unsigned long)((double *)input)[nElems]; + ((rsvc_TS_STAMP *)output)[nElems].nsec = + (unsigned long)(((double)((double *)input)[nElems]-(unsigned long)((double *)input)[nElems])*1000000000); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Double Floating Point to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_DOUBLE_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((char *)output)[nElems] = (char)atof(((char **)input)[nElems]); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((short *)output)[nElems] = (short)atof(((char **)input)[nElems]); + } + +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)atof(((char **)input)[nElems]); + } + +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((long *)output)[nElems] = (long)atof(((char **)input)[nElems]); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)atof(((char **)input)[nElems]); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to Float Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((float *)output)[nElems] = (float)atof(((char **)input)[nElems]); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to Double Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; ((double *)output)[nElems] = (double)atof(((char **)input)[nElems]); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to String Array Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_STRING ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = new char[strlen(((char **)input)[nElems])+1]; + strcpy(((char **)output)[nElems], ((char **)input)[nElems]); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to Timestamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_STRING_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + double tmp = atof(((char **)input)[nElems]); + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch=(unsigned long)tmp; + ((rsvc_TS_STAMP *)output)[nElems].nsec =(unsigned long)((tmp-(unsigned long)tmp)*1000000000); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * String Array to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_STRING_to_INVALID ( void *, void *, size_t ) +{ +} + + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_BYTE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char *)output)[nElems] = (char)(((rsvc_TS_STAMP *)input)[nElems].secPastEpoch); + } + fprintf(stderr, "warning: Timestamp struct converts to Byte, data may be invalid\n"); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_INT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((short *)output)[nElems] = (short)(((rsvc_TS_STAMP *)input)[nElems].secPastEpoch); + } + fprintf(stderr, "warning: Timestamp struct converts to INT16, data may be invalid\n"); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_UINT16 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((unsigned short *)output)[nElems]= + (unsigned short)(((rsvc_TS_STAMP *)input)[nElems].secPastEpoch); + } + fprintf(stderr, "warning: Timestamp struct converts to UINT16, data may be invalid\n"); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_INT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((long *)output)[nElems]= + (long)(((rsvc_TS_STAMP *)input)[nElems].secPastEpoch); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_UINT32 ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((unsigned long *)output)[nElems]= + ((rsvc_TS_STAMP *)input)[nElems].secPastEpoch; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to Floating Point Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_FLOAT ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((float *)output)[nElems]= + (float)(((rsvc_TS_STAMP *)input)[nElems].secPastEpoch+ + ((rsvc_TS_STAMP *)input)[nElems].nsec/1000000000.); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to Doouble Floating Point Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_DOUBLE ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((double *)output)[nElems]= + (double)(((rsvc_TS_STAMP *)input)[nElems].secPastEpoch+ + ((rsvc_TS_STAMP *)input)[nElems].nsec/1000000000.); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to Char String Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_STRING ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = new char[30]; + strcpy( ((char **)output)[nElems], + ctime((time_t *)(&(((rsvc_TS_STAMP *)input)[nElems].secPastEpoch))) ); + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to Time Stamp Conversion Facilities +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_TIMESTAMP ( void * input, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch = + ((rsvc_TS_STAMP *)input)[nElems].secPastEpoch; + ((rsvc_TS_STAMP *)output)[nElems].nsec = + ((rsvc_TS_STAMP *)input)[nElems].nsec; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Time Stamp to Invalid Conversion Facilities...Dose Nothing +// ***************************************************************************** +void rsvcConvert_TIMESTAMP_to_INVALID ( void *, void *, size_t ) +{ +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to 8 Bit Integer Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_BYTE ( void *, void * output, size_t nElems ) +{ + memset((char *)output, 0, nElems*sizeof(char)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to 16 Bit Integer Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_INT16 ( void *, void * output, size_t nElems ) +{ + memset((short *)output, 0, nElems*sizeof(short)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to Unsigned 16 Bit Integer Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_UINT16 ( void *, void * output, size_t nElems ) +{ + memset((short *)output, 0, nElems*sizeof(unsigned short)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to 32 Bit Integer Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_INT32 ( void *, void * output, size_t nElems ) +{ + memset((long *)output, 0, nElems*sizeof(long)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to Unsigned 32 Bit Integer Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_UINT32 ( void *, void * output, size_t nElems ) +{ + memset((long *)output, 0, nElems*sizeof(unsigned long)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to Float Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_FLOAT ( void *, void * output, size_t nElems ) +{ + memset((float *)output, 0, nElems*sizeof(float)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to Double Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_DOUBLE ( void *, void * output, size_t nElems ) +{ + memset((double *)output, 0, nElems*sizeof(double)); +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to String Array Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_STRING ( void *, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((char **)output)[nElems] = 0; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to Timestamp Conversion Facilities... Clears Output +// ***************************************************************************** +void rsvcConvert_INVALID_to_TIMESTAMP ( void *, void * output, size_t nElems ) +{ + while(nElems>0) { + nElems--; + ((rsvc_TS_STAMP *)output)[nElems].secPastEpoch=0; + ((rsvc_TS_STAMP *)output)[nElems].nsec =0; + } +} + +// ***************************************************************************** +// * rsvcConvert: +// * Invalid to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void rsvcConvert_INVALID_to_INVALID ( void *, void *, size_t ) +{ +} + + +// ***************************************************************************** +// * rsvcConversionMatrix: +// * Instanciation of the conversion matrix defined at the beginning of this +// * file. +// ***************************************************************************** +const rsvcConverter rsvcConversionMatrix [RSVC_INVALID+1][RSVC_INVALID+1] = +{ + { + rsvcConvert_BYTE_to_BYTE, + rsvcConvert_BYTE_to_INT16, + rsvcConvert_BYTE_to_UINT16, + rsvcConvert_BYTE_to_INT32, + rsvcConvert_BYTE_to_UINT32, + rsvcConvert_BYTE_to_FLOAT, + rsvcConvert_BYTE_to_DOUBLE, + rsvcConvert_BYTE_to_STRING, + rsvcConvert_BYTE_to_TIMESTAMP, + rsvcConvert_BYTE_to_INVALID + }, + { + rsvcConvert_INT16_to_BYTE, + rsvcConvert_INT16_to_INT16, + rsvcConvert_INT16_to_UINT16, + rsvcConvert_INT16_to_INT32, + rsvcConvert_INT16_to_UINT32, + rsvcConvert_INT16_to_FLOAT, + rsvcConvert_INT16_to_DOUBLE, + rsvcConvert_INT16_to_STRING, + rsvcConvert_INT16_to_TIMESTAMP, + rsvcConvert_INT16_to_INVALID, + }, + { + rsvcConvert_UINT16_to_BYTE, + rsvcConvert_UINT16_to_INT16, + rsvcConvert_UINT16_to_UINT16, + rsvcConvert_UINT16_to_INT32, + rsvcConvert_UINT16_to_UINT32, + rsvcConvert_UINT16_to_FLOAT, + rsvcConvert_UINT16_to_DOUBLE, + rsvcConvert_UINT16_to_STRING, + rsvcConvert_UINT16_to_TIMESTAMP, + rsvcConvert_UINT16_to_INVALID, + }, + { + rsvcConvert_INT32_to_BYTE, + rsvcConvert_INT32_to_INT16, + rsvcConvert_INT32_to_UINT16, + rsvcConvert_INT32_to_INT32, + rsvcConvert_INT32_to_UINT32, + rsvcConvert_INT32_to_FLOAT, + rsvcConvert_INT32_to_DOUBLE, + rsvcConvert_INT32_to_STRING, + rsvcConvert_INT32_to_TIMESTAMP, + rsvcConvert_INT32_to_INVALID, + }, + { + rsvcConvert_UINT32_to_BYTE, + rsvcConvert_UINT32_to_INT16, + rsvcConvert_UINT32_to_UINT16, + rsvcConvert_UINT32_to_INT32, + rsvcConvert_UINT32_to_UINT32, + rsvcConvert_UINT32_to_FLOAT, + rsvcConvert_UINT32_to_DOUBLE, + rsvcConvert_UINT32_to_STRING, + rsvcConvert_UINT32_to_TIMESTAMP, + rsvcConvert_UINT32_to_INVALID, + }, + { + rsvcConvert_FLOAT_to_BYTE, + rsvcConvert_FLOAT_to_INT16, + rsvcConvert_FLOAT_to_UINT16, + rsvcConvert_FLOAT_to_INT32, + rsvcConvert_FLOAT_to_UINT32, + rsvcConvert_FLOAT_to_FLOAT, + rsvcConvert_FLOAT_to_DOUBLE, + rsvcConvert_FLOAT_to_STRING, + rsvcConvert_FLOAT_to_TIMESTAMP, + rsvcConvert_FLOAT_to_INVALID, + }, + { + rsvcConvert_DOUBLE_to_BYTE, + rsvcConvert_DOUBLE_to_INT16, + rsvcConvert_DOUBLE_to_UINT16, + rsvcConvert_DOUBLE_to_INT32, + rsvcConvert_DOUBLE_to_UINT32, + rsvcConvert_DOUBLE_to_FLOAT, + rsvcConvert_DOUBLE_to_DOUBLE, + rsvcConvert_DOUBLE_to_STRING, + rsvcConvert_DOUBLE_to_TIMESTAMP, + rsvcConvert_DOUBLE_to_INVALID, + }, + { + rsvcConvert_STRING_to_BYTE, + rsvcConvert_STRING_to_INT16, + rsvcConvert_STRING_to_UINT16, + rsvcConvert_STRING_to_INT32, + rsvcConvert_STRING_to_UINT32, + rsvcConvert_STRING_to_FLOAT, + rsvcConvert_STRING_to_DOUBLE, + rsvcConvert_STRING_to_STRING, + rsvcConvert_STRING_to_TIMESTAMP, + rsvcConvert_STRING_to_INVALID, + }, + { + rsvcConvert_TIMESTAMP_to_BYTE, + rsvcConvert_TIMESTAMP_to_INT16, + rsvcConvert_TIMESTAMP_to_UINT16, + rsvcConvert_TIMESTAMP_to_INT32, + rsvcConvert_TIMESTAMP_to_UINT32, + rsvcConvert_TIMESTAMP_to_FLOAT, + rsvcConvert_TIMESTAMP_to_DOUBLE, + rsvcConvert_TIMESTAMP_to_STRING, + rsvcConvert_TIMESTAMP_to_TIMESTAMP, + rsvcConvert_TIMESTAMP_to_INVALID, + }, + { + rsvcConvert_INVALID_to_BYTE, + rsvcConvert_INVALID_to_INT16, + rsvcConvert_INVALID_to_UINT16, + rsvcConvert_INVALID_to_INT32, + rsvcConvert_INVALID_to_UINT32, + rsvcConvert_INVALID_to_FLOAT, + rsvcConvert_INVALID_to_DOUBLE, + rsvcConvert_INVALID_to_STRING, + rsvcConvert_INVALID_to_TIMESTAMP, + rsvcConvert_INVALID_to_INVALID, + } +}; + + +// ***************************************************************************** +// *rsvcDataIterator: +// * +// ***************************************************************************** +rsvcDataIterator::rsvcDataIterator(rsvcData* data) { + dataobj_ = data; + cur_ = 0; +} + +int rsvcDataIterator::init() { + if (dataobj_) { + cur_ = dataobj_->entries; + return cur_ != 0; } + else { return 0; } +} + +int rsvcDataIterator::operator !() { + return cur_ != 0; +} + +int rsvcDataIterator::operator ++() { + if (cur_) + cur_ = cur_->next_; + return cur_ != 0; +} + +const char* rsvcDataIterator::tag(void) { + return (cur_!=0)?cur_->tag_:0; +} + +rsvcDataEntry * +rsvcDataIterator::operator () (void) +{ + return cur_; +} + + +// ***************************************************************************** +// * ltoa and ultoa +// * Supporing routines for non hpux platform +// * the return values point to static data whose content is overwritten by +// * each call +// ***************************************************************************** +#ifndef hpux +char *ltoa (long val) +{ + static char ltoabuf[80]; + + sprintf (ltoabuf,"%ld", val); + + return ltoabuf; +} + +char *ultoa (unsigned long val) +{ + static char ultoabuf[80]; + + sprintf (ultoabuf,"%lu", val); + + return ultoabuf; +} +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcData.h b/extensions/cdevGenericServer/NameServer/src/rsvcData.h new file mode 100755 index 0000000..a708ddd --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcData.h @@ -0,0 +1,316 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: rsvcData.h +// Self descibing data structure to manage the storage and transport +// of data between local rsvc functions, as well as remote client and +// server applications. +// +// Author: Walt Akers and Danjin Wu +// +// +// +//-------------------------------------------------------------------------- + +#ifndef _RSVC_DATA_H +#define _RSVC_DATA_H + +#ifdef _WIN32 +#include +#include +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef hpux +char * ltoa (long val); +char * ultoa (unsigned long val); +#endif + +#ifndef _WIN32 + extern "C" char *ctime (__const time_t *__timer) __THROW; +#endif + + +class RSVC_CLASS_SPEC rsvcData +{ +friend class rsvcDataIterator; +protected: + rsvcDataEntry *entries; + + // ********************************************************************* + // * copy: + // * This function copies the contents of the rsvcData object + // * specified by data into this rsvcData object. It is used by + // * both the copy constructor and by the assignment operator. + // ********************************************************************* + rsvcData & copy (const rsvcData & data); + +public: + + // ********************************************************************* + // * Convert data from a floating point value to a string. + // ********************************************************************* + static char * rsvc_gcvt(float value, size_t ndigit, char *buf); + static char * rsvc_gcvt(double value, size_t ndigit, char * buf); + + // ********************************************************************* + // * lookupTag: + // * This function is for internal use and allows a cdevData object + // * to locate and optionally create a tagged data item. + // ********************************************************************* + rsvcDataEntry * lookupTag(char * ctag, int create = 0); + + // ********************************************************************* + // * setupTag: + // * This function is for internal use and is used to prepare a new + // * rsvcDataEntry object prior to inserting data into it. + // ********************************************************************* + rsvcDataEntry * setupTag (char* tag, rsvcDataTypes type, size_t elemSize, + size_t numElems, size_t numDims ); + + // ********************************************************************* + // * insert: + // * The following functions insert a data entry into this datan + // ********************************************************************* + int insert (rsvcDataEntry* entry); + + + + // ********************************************************************* + // * rsvcData: + // * This is the default constructor, it simply initializes + // * variables within the rsvcData object. + // ********************************************************************* + rsvcData ( void ); + + // ********************************************************************* + // * rsvcData: + // * Copy constructor. This constructor duplicates the rsvcData + // * object that it has been passed as a parameter. + // ********************************************************************* + rsvcData ( const rsvcData & data ); + + // ********************************************************************* + // * ~rsvcData: + // * This is the default destructor for the rsvcData object. It + // * frees any memory allocated for storage and deletes the object. + // ********************************************************************* + ~rsvcData( void ); + + // ********************************************************************* + // * Assignment operator: + // * This function copies the contents of a rsvcData object to this + // * object. + // ********************************************************************* + rsvcData & operator = (const rsvcData & data); + + // ********************************************************************* + // * Append operation: + // * This operation will append a rsvcData onto an existing rsvcData + // * and return this object. If there is confilicts among tags, the + // * appended one wins + // ********************************************************************* + rsvcData& operator += (const rsvcData& data); + + // ********************************************************************* + // * asciiDump: + // * Performs a diagnostic dump of the entire contents of the + // * rsvcData object to the specified file pointer. + // ********************************************************************* +#ifdef _WIN32 + inline void asciiDump (FILE* fp = stdout) { + int fd = _fileno (fp); + long osfHandle = _get_osfhandle (fd); + asciiDump (osfHandle); + _lseek(fd, 0L, SEEK_END); + } + void asciiDump (long osfHandle); +#else + void asciiDump ( FILE * fp = stdout ); +#endif + + // ********************************************************************* + // * Stream Utilities + // * These functions provide the mechanisms for converting a rsvcData + // * object into a network portable bninary stream, and then + // * reconstructing them after transport. + // ********************************************************************* + +#define _RSVC_MAGIC_NUM 0x2c45da2a + + virtual int streamSize (size_t * bufLen, size_t * elementCount); + virtual int streamOut ( char ** buf, size_t * bufLen ); + virtual int streamOut ( char * buf, size_t bufLen, size_t count); + virtual int streamIn ( char * buf, size_t bufLen); + + // ********************************************************************* + // * remove: + // * Removes rsvcDataEntry objects from the rsvcData object by tag + // * integer or by tag string. If no tag is specified, then all + // * rsvcDataEntry objects will be removed. + // ********************************************************************* + void remove( void ); + void remove( char * ctag ); + + // ********************************************************************* + // * changeTag: + // * Replace a new tag with the old one within the + // * rsvcData object. If the old one can not be not found, + // * RSVC_NOTFOUND is returned. If the new tag has already + // * been found in that rsvcData object, RSVC_ERROR is returned. + // ********************************************************************* + int changeTag(char *c_oldTag, char *c_newTag); + + + // ********************************************************************* + // * dupWithTag: + // * copy data with tag 'old_tag' to tag 'new_tag'. + // * rsvcData object. If the old one can not be not found, + // * RSVC_NOTFOUND is returned. If the new tag has already + // * been found in that rsvcData object, RSVC_ERROR is returned. + // ********************************************************************* + int dupWithTag (char* old_tag, char* new_tag); + + // ********************************************************************* + // * getType: + // * Retrieves the rsvcDataTypes of the referenced tagged data item. + // * If no item with that tag is within the rsvcData object, then + // * RSVC_INVALID is returned. + // ********************************************************************* + rsvcDataTypes getType(char *ctag); + + + // ********************************************************************* + // * getDim: + // * Obtains the number of dimensions in the specified tagged data + // * item. Returns RSVC_SUCCESS if the tagged item exists, otherwise, + // * RSVC_NOTFOUND is returned. + // ********************************************************************** + int getDim(char *ctag, size_t *dim); + + // ********************************************************************* + // * getElems: + // * Obtains the number of elements in the specified tagged data + // * item. Returns RSVC_SUCCESS if the tagged item exists, otherwise, + // * RSVC_NOTFOUND is returned. + // ********************************************************************** + int getElems(char *ctag, size_t *elems); + + // ********************************************************************* + // * insert: + // * The following functions allow the insertion of scalar data into + // * a rsvcData object. + // ********************************************************************* + int insert ( char * ctag, BYTE data); + int insert ( char * ctag, short data); + int insert ( char * ctag, unsigned short data); + int insert ( char * ctag, int data); + int insert ( char * ctag, unsigned int data); + int insert ( char * ctag, long data); + int insert ( char * ctag, unsigned long data); + int insert ( char * ctag, float data); + int insert ( char * ctag, double data); + int insert ( char * ctag, rsvc_TS_STAMP data); + + // ******************************************************************** + // * insert: + // * The following functions allow the insertion of arrays of data + // * into a rsvcData object. The len variable contains the total + // * number of elements to be inserted, the ndim variable indicates + // * the number of dimensions in the array. + // ******************************************************************** + int insert (char * ctag, BYTE * data, size_t len, size_t ndim = 1); + int insert (char * ctag, short * data, size_t len, size_t ndim = 1); + int insert (char * ctag, unsigned short * data, size_t len, size_t ndim = 1); + int insert (char * ctag, int * data, size_t len, size_t ndim = 1); + int insert (char * ctag, unsigned int * data, size_t len, size_t ndim = 1); + int insert (char * ctag, long * data, size_t len, size_t ndim = 1); + int insert (char * ctag, unsigned long * data, size_t len, size_t ndim = 1); + int insert (char * ctag, float * data, size_t len, size_t ndim = 1); + int insert (char * ctag, double * data, size_t len, size_t ndim = 1); + int insert (char * ctag, rsvc_TS_STAMP *data, size_t len, size_t ndim =1 ); + + // ********************************************************************* + // * insert: + // * The following functions insert character strings and arrays of + // * character strings. Their treatment is different from the scalar + // * data types. + // ********************************************************************* + int insert ( char * ctag, char * data); + int insert ( char * ctag, char ** data, size_t len = 0, size_t ndim = 1); + + // ********************************************************************* + // * get: + // * This group of functions allows the user to extract scalar and + // * array data from the rsvcData object. + // ********************************************************************* + int get(char * ctag, BYTE * data); + int get(char * ctag, short * data); + int get(char * ctag, unsigned short * data); + int get(char * ctag, int * data); + int get(char * ctag, unsigned int * data); + int get(char * ctag, long * data); + int get(char * ctag, unsigned long * data); + int get(char * ctag, float * data); + int get(char * ctag, double * data); + int get(char * ctag, char * data, size_t len); + int get(char * ctag, char ** data); + int get(char * ctag, rsvc_TS_STAMP * data); + + // ********************************************************************* + // * find: + // * These functions allow the user to obtain a pointer to data + // * within the actual data variables within the rsvcData object. + // ********************************************************************* + int find(char * ctag, void* &data); + + // ********************************************************************* + // * replace: + // * This function allows part or all taged values being replaced + // * by other taged values represented by a rsvcData + // ********************************************************************* + int replace (const rsvcData& rep); + + // ********************************************************************* + // * operator ==, operator !=: + // * These methods provides a fast way for the caller to identify if two + // * rsvcData objects contain the identical fields and values... + // ********************************************************************* + int operator == (rsvcData & data); + int operator != (rsvcData & data) { return !(operator == (data)); } +}; + + + +class rsvcDataIterator +{ +public: + rsvcDataIterator (rsvcData* data); + ~rsvcDataIterator (void) {}; + int init (void); + int operator ! (void); + int operator ++(void); + const char* tag (void); + rsvcDataEntry* operator () (void); + +protected: + rsvcData *dataobj_; + rsvcDataEntry *cur_; +}; + +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDataEntry.cc b/extensions/cdevGenericServer/NameServer/src/rsvcDataEntry.cc new file mode 100755 index 0000000..1316a2d --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDataEntry.cc @@ -0,0 +1,173 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//------------------------------------------------------------------------------ +// +// description: rcsDataEntry.cc +// This file contains the non-inlined functions associated with the +// rsvcDataEntry family of classes. +// +// Author: Walt Akers +// +// Revision History: +// rsvcDataEntry.cc,v +// Revision 1.1 1998/01/22 17:08:05 akers +// Addition of new NameServer +// +// +// +//------------------------------------------------------------------------------ +#include "rsvcDataEntry.h" + + +// ***************************************************************************** +// * rsvcDataEntryeStorage::operator ==: +// * This operator allows you to directly and rapidly compare two +// * rsvcDataEntryStorage objects... +// ***************************************************************************** +int rsvcDataEntryStorage::operator == (rsvcDataEntryStorage & entry) +{ + int result = 0; + int i = 0; + + // ********************************************************************* + // * First compare all of the pertinent scalar values... + // ********************************************************************* + if(strcmp (tag_, entry.tag_) == 0 && + dataType_ == entry.dataType_ && + dim_ == entry.dim_ && + elems_ == entry.elems_) + { + // ************************************************************* + // * Next compare the contents of the data items... + // ************************************************************* + if(dim_) + { + result = 0; + if(dataType_==RSVC_BYTE) + for(i=0; i 0) { + // allocate memory + allocate (entry.dim_, entry.elems_, entry.bytes_); + // copy memory + memcpy (buffer_, entry.buffer_, size_); + } + else + memcpy (&data_, &entry.data_, sizeof (data_)); +} + +rsvcDataEntry & +rsvcDataEntry::operator = (const rsvcDataEntry& entry) +{ + if (this != &entry) { + clear (); + + dataType_ = entry.dataType_; + dim_ = entry.dim_; + elems_ = entry.elems_; + bytes_ = entry.bytes_; + size_ = entry.size_; + strcpy (tag_, entry.tag_); + buffer_ = 0; + + if (dim_ > 0 || (dim_ == 0 && dataType_ == RSVC_STRING)) { + // allocate memory + allocate (entry.dim_, entry.elems_, entry.bytes_); + // copy memory + memcpy (buffer_, entry.buffer_, size_); + } + else + memcpy (&data_, &entry.data_, sizeof (data_)); + } + return *this; +} + + +// ***************************************************************************** +// * Global initialization of the static freeList_ member of the +// * rsvcDataEntry class. +// ***************************************************************************** +rsvcDataEntry * rsvcDataEntry::freeList_ = NULL; + +// ***************************************************************************** +// * new: +// * Allocation function for the object. It will get the next preallocated +// * rsvcDataEntry object from the freeList_, or, if none are available, +// * refill the freeList_ and then return a new rsvcDataEntry object. +// ***************************************************************************** +void * rsvcDataEntry::operator new ( size_t ) +{ + rsvcDataEntry * result = NULL; + + if(freeList_==NULL) + { + freeList_ = ::new rsvcDataEntry[ALLOCATION_COUNT]; + for(int i=0; inext_; + } + + return result; +} diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDataEntry.h b/extensions/cdevGenericServer/NameServer/src/rsvcDataEntry.h new file mode 100755 index 0000000..12572bb --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDataEntry.h @@ -0,0 +1,335 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//------------------------------------------------------------------------------ +// +// description: rsvcDataEntry.h +// This file defines the classes necessary for storage of an individual +// tagged data item within a rsvcData class object. +// +// Author: Walt Akers & Jie Chen +// +// +// +//------------------------------------------------------------------------------ + +#ifndef _RSVC_DATA_ENTRY_H_ +#define _RSVC_DATA_ENTRY_H_ + +#include +#include + +// ############################################################################# +// # rsvcDataEntryStorage: +// # This class contains the data elements and methods necessary to store data +// # associated with one tagged data item. +// # +// # Note: Because the rsvcData object must actively manipulate the data in +// # this structure - it has been made public to increase access speed +// # and to allow the subclassing of the rsvcData object. +// ############################################################################# +class rsvcDataEntryStorage +{ +public: + // ************************************************************* + // * tag_: + // * This is char string value that is used to uniquely identify + // * a data element within a rsvcData object. + // ************************************************************* + char tag_[RSVC_TAG_MAX_LEN]; + + // ************************************************************* + // * dataType_: + // * This is the data type of the tagged data item that is to be + // * stored in this rsvcDataEntryStorage object. + // ************************************************************* + rsvcDataTypes dataType_; + + // ************************************************************* + // * size_: + // * This variable is the allocated size of the buffer_ which is + // * used to store both the array data and its associated bounds + // * information. + // ************************************************************* + size_t size_; + + // ************************************************************* + // * dim_: + // * This variable indicates the user specified number of + // * dimensions that the array represents. + // * either 0 or 1 + // ************************************************************* + size_t dim_; + + // ************************************************************* + // * elems_: + // * This variable contains the maximum number of elements that + // * the array may contain. + // ************************************************************* + size_t elems_; + + // ************************************************************* + // * bytes_: + // * This variable contains the number of bytes per element. + // ************************************************************* + size_t bytes_; + + // ************************************************************* + // * buffer_: + // * This is the buffer that is allocated to store data and + // * bounds information. + // ************************************************************* + unsigned char * buffer_; + + // ************************************************************* + // * data_: + // * This is a union that is used to store scalar data and a + // * pointer to the array data this is stored within this object + // ************************************************************* + union dataUnion { + BYTE cval; + short sval; + unsigned short usval; + long lval; + unsigned long ulval; + float fval; + double dval; + void * vptr; + BYTE * cptr; + short * sptr; + unsigned short * usptr; + long * lptr; + unsigned long * ulptr; + float * fptr; + double * dptr; + char * str; + char ** strarr; + rsvc_TS_STAMP ts; + rsvc_TS_STAMP * tsptr; + } data_; + + // ************************************************************* + // * rsvcDataEntryStorage: + // * Default constructor for the rsvcDataEntryStorage class. It sets + // * the buffer_ pointer to NULL to prevent deletion of non- + // * allocated memory, and then calls the clear method to + // * initialize all data variables. + // ************************************************************* + rsvcDataEntryStorage ( void ) : buffer_(0) { + clear(); + } + + // ************************************************************* + // * ~rsvcDataEntryStorage: + // * Default destructor for the rsvcDaaEntry class. It calls + // * the clear method to release and reinitialize all data + // * elements. + // ************************************************************* + ~rsvcDataEntryStorage ( void ) { + clear(); + } + + // ************************************************************* + // * clear: + // * Releases and reinitializes all data variables. + // ************************************************************* + void clear ( void ) { + deallocate(); + tag_[0] = 0; + dataType_ = RSVC_INVALID; + } + + // ************************************************************* + // * allocate: + // * Allocates a block of memory sufficient to store a caller + // * specified number of bytes. If sufficient space has already + // * been allocated, then it will be used, otherwise, a new + // * block will be created to service the request. + // ************************************************************* + void allocate ( size_t dimensions, size_t elems, size_t bytesPerElem ) + { + size_t newBlockSize = (elems * bytesPerElem); + + if(buffer_==NULL || newBlockSize>size_) + { + deallocate(); + buffer_ = ::new unsigned char[newBlockSize]; + size_ = newBlockSize; + } + dim_ = dimensions; + elems_ = elems; + bytes_ = bytesPerElem; + data_.vptr = &buffer_[0]; + memset (buffer_, 0, newBlockSize); + } + + // ************************************************************* + // * deallocate: + // * Deallocates any memory previously allocated to the buffer + // * and reinitializes the size_, dim_, bytes_ and buffer_ + // * variables. Any references to the previously allocated + // * block is cleared. + // ************************************************************* + void deallocate ( void ) + { + if(buffer_ != 0) { + delete []buffer_; + buffer_ = 0; + } + size_ = 0; + dim_ = 0; + elems_ = 0; + bytes_ = 0; + data_.dval = 0.00; + } + + + // ************************************************************* + // * operator ==: + // * This operator allows you to directly and rapidly + // * compare two rsvcDataEntryStorage objects... + // ************************************************************* + int operator == (rsvcDataEntryStorage & entry); + + // ************************************************************* + // * operator !=: + // * This operator allows the caller to directly and rapidly + // * comapre two rsvcDataEntryStorage objects. + // ************************************************************* + int operator != (rsvcDataEntryStorage & entry) { + return !(operator == (entry)); + } + +}; + + +// ############################################################################# +// # rsvcDataEntry: +// # This class is used to define the node attributes necessary to support +// # linked lists of rsvcDataEntryStorage objects. It also provides an internal +// # freelist of rsvcDataEntry objects. +// # +// # Note: Because the rsvcData object must actively manipulate the data in +// # this structure - it has been made public to increase access speed +// # and to allow the subclassing of the rsvcData object. +// ############################################################################# +class rsvcDataEntry : public rsvcDataEntryStorage +{ +public: + // ************************************************************* + // * freeList_: + // * This is a pointer to a list of currently allocated + // * rsvcDataEntrys that will be provided to the user + // * upon request. This technique should reduce the number of + // * mallocs called to allocated rsvcDataEntrys. + // ************************************************************* + static rsvcDataEntry * freeList_; + + // ************************************************************* + // * ALLOCATION_COUNT: + // * This is the minimum number of rsvcDataEntrys that will + // * be allocated when the freeList_ becomes empty. + // ************************************************************* + enum { ALLOCATION_COUNT = 16 }; + + // ************************************************************* + // * next_ : + // * This is the pointer to the next element in the list of + // * rsvcDataEntry objects. + // ************************************************************* + rsvcDataEntry * next_; + + // ************************************************************* + // * rsvcDataEntry: + // * Constructor for the class. It serves only to set the next_ + // * pointer to NULL. + // ************************************************************* + rsvcDataEntry ( void ) : next_(NULL), rsvcDataEntryStorage() + { + } + + // ************************************************************* + // * ~rsvcDataEntry: + // * Destructor for the class. It is a placeholder that + // * does nothing when called. + // ************************************************************* + ~rsvcDataEntry ( void ) { } + + // ************************************************************* + // * next: + // * Retrieves a pointer to the next_ rsvcDataEntry object. + // * Incorporation of this function into a list object is the + // * responsibility of the caller. + // ************************************************************* + rsvcDataEntry * &next ( void ) + { + return next_; + } + + // ************************************************************* + // * new: + // * Allocation function for the object. It will get the next + // * preallocated rsvcDataEntry object from the freeList_, + // * or, if none are available, refill the freeList_ and then + // * return a new rsvcDataEntry object. + // ************************************************************* + void * operator new ( size_t size ); + + // ************************************************************* + // * delete: + // * Rather than deallocating the rsvcDataEntry object, this + // * function returns it to the freeList_ where it may be + // * retrieved by a later call of new. + // ************************************************************* + void operator delete ( void * ptr ) + { + rsvcDataEntry * node = (rsvcDataEntry *)ptr; + if(node != NULL) { + node->next_ = freeList_; + freeList_ = node; + } + } + + // ************************************************************* + // * Copy operation + // * Copy an existing data entry to a new data entry + // * this may allow new data entry to be inserted into data object + // * quickly + // ************************************************************* + rsvcDataEntry (const rsvcDataEntry& entry); + + // ************************************************************* + // * Assignment operation + // * Copy an existing data entry to a data entry + // ************************************************************* + rsvcDataEntry& operator = (const rsvcDataEntry& entry); + + // ************************************************************* + // * operator ==: + // * This operator allows you to directly and rapidly + // * compare two rsvcDataEntry objects... + // ************************************************************* + int operator == (rsvcDataEntry & entry) + { + rsvcDataEntryStorage *storage = &entry; + + return rsvcDataEntryStorage::operator == (*storage); + } + + // ************************************************************* + // * operator !=: + // * This operator allows the caller to directly and rapidly + // * comapre two rsvcDataEntry objects. + // ************************************************************* + int operator != (rsvcDataEntry & entry) + { + rsvcDataEntryStorage *storage = &entry; + return !(rsvcDataEntryStorage::operator == (*storage)); + } + +}; + +#endif /* __RSVC_DATA_ENTRY_H_ */ diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDataStore.cc b/extensions/cdevGenericServer/NameServer/src/rsvcDataStore.cc new file mode 100755 index 0000000..54b6f8d --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDataStore.cc @@ -0,0 +1,414 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcDataStore Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcDataStore.cc,v +// Revision 1.3 1998/03/19 18:30:58 chen +// add monitorEntry capability to server table +// +// Revision 1.2 1998/02/26 19:09:43 chen +// remove all cached data when finished +// +// Revision 1.1 1998/01/22 17:08:06 akers +// Addition of new NameServer +// +// +// +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "rsvcDataStore.h" +#include "rsvcDataStoreMem.h" + +#ifdef _WIN32 +#include +#include +#else +#include +#endif + +#ifndef DB_CREATE +#define DB_CREATE 0x00001 +#endif + +#ifdef _WIN32 +#define _RSVC_DIR_CHAR '\\' +#define _RSVC_DIR_SELF ".\\" +#else +#define _RSVC_DIR_CHAR '/' +#define _RSVC_DIR_SELF "./" +#endif + + + +rsvcDataStore::rsvcDataStore (char* name) +:rsvcHashable (), timestamp_ (0.0), tableDef_(name), + cache_ (rsvcServerConfig::dbaseCacheMax (),rsvcServerConfig::dbaseCacheLf ()), + idataMonitorList_ (), odataMonitorList_ (), database_ (0) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcDataStore Class Object\n"); +#endif + name_ = new char[strlen (name) + 1]; + strcpy (name_, name); +} + +rsvcDataStore::~rsvcDataStore (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete rsvcDataStore Class Object\n"); +#endif + + // remove all monitors + removeAllMonitors (); + delete []name_; + + if (database_) + delete database_; + + rsvcHashIterator ite (cache_); + rsvcCacheData* cdata = 0; + + for (ite.init (); !ite; ++ite) { + cdata = (rsvcCacheData *) ite (); + delete cdata; + } + cache_.deleteAllValues (); +} + + +char* +rsvcDataStore::name (void) const +{ + return name_; +} + +void +rsvcDataStore::removeAllMonitors (void) +{ + rsvcHSlistIterator ite (idataMonitorList_); + rsvcCbk* cbk = 0; + + for (ite.init (); !ite; ++ite) { + cbk = (rsvcCbk *)ite (); + delete cbk; + } + idataMonitorList_.deleteAllValues (); + + rsvcHSlistIterator oite (odataMonitorList_); + for (oite.init (); !oite; ++oite) { + cbk = (rsvcCbk *)oite (); + delete cbk; + } + odataMonitorList_.deleteAllValues (); +} + +int +rsvcDataStore::createDatabase (rsvcNetData& incoming, + rsvcNetData* out[], size_t* num) +{ + int status = RSVC_SUCCESS; + + // if table already defined, do nothing + if (tableDef_.tableDefined ()) // table is defined + status = RSVC_ERROR; + else if (tableDef_.create () == RSVC_SUCCESS) // table is defined on disk + status = RSVC_ERROR; + else { + // try to create table definition from incoming netdata + rsvcData& def = incoming.data (); + if (tableDef_.create (def) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStore: Cannot create table definition\n"); +#endif + status = RSVC_ERROR; + } + else + tableDef_.output (); // write to disk + } + + if (status == RSVC_SUCCESS && database_) { + // create database + char fullname[128]; + sprintf (fullname, "%s.%s", name_, tableDef_.keyName ()); + if (database_->create (fullname, DB_CREATE|O_RDWR, tableDef_.keyType ()) + != RSVC_SUCCESS) + status = RSVC_ERROR; + } + + // construct returning message + out[0] = new rsvcNetData (incoming.cbk ()); + out[0]->cbkstatus (status); + *num = 1; + + return status; +} + + +int +rsvcDataStore::openDatabase (rsvcNetData& incoming, + rsvcNetData* out[], size_t* num) +{ + int status = RSVC_SUCCESS; + rsvcData def; + + // if table already defined, do nothing + if (!tableDef_.tableDefined () && tableDef_.create () != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStore: Cannot open table definition\n"); +#endif + status = RSVC_ERROR; + } + + if (status == RSVC_SUCCESS && database_) { + // create database + char fullname[128]; + sprintf (fullname, "%s.%s", name_, tableDef_.keyName ()); + if (!database_->opened ()) + if (database_->open (fullname, O_RDWR, tableDef_.keyType ()) + != RSVC_SUCCESS) + status = RSVC_ERROR; + if (status == RSVC_SUCCESS) + tableDef_.output (def); + } + + // construct returning message + if (status == RSVC_SUCCESS) + out[0] = new rsvcNetData (def, incoming.cbk ()); + else + out[0] = new rsvcNetData (incoming.cbk ()); + out[0]->cbkstatus (status); + *num = 1; + + return status; +} + +int +rsvcDataStore::getTableDef (rsvcNetData& incoming, + rsvcNetData* out[], size_t* num) +{ + int status = RSVC_SUCCESS; + rsvcData def; + + if (tableDef_.tableDefined () != RSVC_SUCCESS) + status = RSVC_ERROR; + else + tableDef_.output (def); + + // construct returning message + out[0] = new rsvcNetData (def, incoming.cbk ()); + out[0]->cbkstatus (status); + *num = 1; + + return status; +} + +unsigned int +rsvcDataStore::hash (void) +{ + unsigned int h = 0, g; + + for (int i = 0; name_[i] != '\0'; i++){ + h = (h << 4) + name_[i]; + // assume 32 bit integer + if (g = h & 0xf0000000){ + h ^= g >> 24; + h ^= g; + } + } + return h; +} + +int +rsvcDataStore::openDatabase (void) +{ + int status = RSVC_SUCCESS; + + // if table already defined, do nothing + if (!tableDef_.tableDefined () && tableDef_.create () != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStore: Cannot open table definition\n"); +#endif + status = RSVC_ERROR; + } + if (database_ && status == RSVC_SUCCESS) { + char fullname[128]; + sprintf (fullname, "%s.%s", name_, tableDef_.keyName ()); + if (!database_->opened ()) + status = database_->open (fullname, O_RDWR, tableDef_.keyType ()); + } + return status; +} + +int +rsvcDataStore::closeDatabase (void) +{ + if (database_) + return database_->close (); + return RSVC_ERROR; +} + +void +rsvcDataStore::updateTimeStamp (void) +{ +#ifdef _WIN32 + struct _timeb tv; + + _ftime (&tv); + + timestamp_ = tv.time + tv.millitm/1000.0; + +#else + + struct timeval tv; + + gettimeofday (&tv, 0); + + timestamp_ = tv.tv_sec + tv.tv_usec/1000000.0; +#endif +} + +int +rsvcDataStore::notifyAnEntryToChannels (rsvcData& entry) +{ + if (idataMonitorList_.isEmpty ()) + return RSVC_SUCCESS; + + rsvcHSlistIterator ite (idataMonitorList_); + rsvcCbk* cbk = 0; + rsvcNetData* ndata = 0; + rsvcIO* channel = 0; + + for (ite.init (); !ite; ++ite) { + cbk = (rsvcCbk *) ite (); + + // connection channel + channel = (rsvcIO *)cbk->userptr (); + + cbk->cbkstatus (RSVC_SUCCESS); + ndata = new rsvcNetData (entry, *cbk); + + channel->sendToPeer (ndata); + } + return RSVC_SUCCESS; +} + +rsvcDataStore * +rsvcDataStore::createDataStore (char* name) +{ + // get database home directory + char tdir[256]; + + strncpy (tdir, rsvcServerConfig::dbaseHome (), sizeof (tdir)); + char *lslash = strrchr (tdir, _RSVC_DIR_CHAR); + if (lslash == 0) + return 0; + + *lslash = '\0'; + +#ifdef _RSVC_DEBUG + printf ("rsvcDataStore: database home directory is %s\n", tdir); +#endif + + // construct table definition filename and datafile name + rsvcTableDef tdef (name); + // read table definition file from disk + if (tdef.create () == RSVC_ERROR) + return 0; + + char tabledefname[128]; + char datafname[128]; + + sprintf (tabledefname, "%s%s", name, rsvcServerConfig::tableNameExt ()); + sprintf (datafname, "%s.%s", name, tdef.keyName ()); + +#ifdef _RSVC_DEBUG + printf ("rsvcDataStore: table definition filename %s\n", tabledefname); + printf ("rsvcDataStore: data file name is %s\n", datafname); +#endif + +#ifdef _WIN32 + HANDLE sh; + WIN32_FIND_DATA fdata; + char wfname[256]; + int len; + int count = 0; + + len = strlen (tdir) + 1; + if (len > sizeof (wfname) - 1) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStore: directory name is too long: %d\n", len); +#endif + return 0; + } + strcpy (wfname, tdir); + strcat (wfname, "*"); + + // find file name one by one + sh = FindFirstFile (wfname, &fdata); + if (sh == INVALID_HANDLE_VALUE) { + fprintf (stderr, "rsvcDataStore: cannot do FindFirstFile\n"); + return 0; + } + if (strcmp (fdata.cFileName, tabledefname) == 0) + count ++; + else if (strcmp (fdata.cFileName, datafname) == 0) + count ++; + + while (FindNextFile (sh, &fdata)) { + if (strcmp (fdata.cFileName, tabledefname) == 0) + count ++; + else if (strcmp (fdata.cFileName, datafname) == 0) + count ++; + } + FindClose (sh); + +#else /* _WIN32 */ + + DIR* dbasedir = opendir (tdir); + if (dbasedir == 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStore: cannot open database directory %s\n", tdir); +#endif + return 0; + } + + struct dirent* direntp = 0; + int count = 0; + while ((direntp = readdir (dbasedir)) != 0) { + if (strcmp (direntp->d_name, tabledefname) == 0) + count ++; + else if (strcmp (direntp->d_name, datafname) == 0) + count ++; + } + closedir (dbasedir); +#endif + + rsvcDataStore* nstore = 0; + if (count == 1) { + nstore = new rsvcDataStoreMem (name); + } + else + nstore = 0; // eventually change to database + + return nstore; +} + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDataStore.h b/extensions/cdevGenericServer/NameServer/src/rsvcDataStore.h new file mode 100755 index 0000000..026ad9e --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDataStore.h @@ -0,0 +1,174 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server All Data Storage Class (Abstract Class) +// +// This class behaves like a wrapper class that direct +// all actions to right components contained inside this class +// +// All member functions have 3 arguments. The first is the network +// incoming data, the second is the result of the action in the +// form of array of network data, and the 3rd argument is size +// of the array. Callers must free memory for the elements +// in the array +// +// Author: Jie Chen +// +// +// +// +#ifndef _RSVC_DATA_STORE_H +#define _RSVC_DATA_STORE_H + +#include +#include +#include + +#ifndef _WIN32 +#include +#include +#endif + +#include +#include +#include +#include +#include + + +class rsvcVirtualDbase; + +class rsvcDataStore : public rsvcHashable +{ +public: + // destrcutor + virtual ~rsvcDataStore (void); + + // operations + + // create table definition + virtual int createDatabase (rsvcNetData& data, + rsvcNetData* outdata[], size_t* num); + + virtual int openDatabase (rsvcNetData& data, + rsvcNetData* outdata[], size_t* num); + + // retrieve table definition and store inside data + virtual int getTableDef (rsvcNetData& data, + rsvcNetData* outdata[], size_t* num); + + // get data value + // specified by a key + virtual int getValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + // insert a rsvcData which must have a key inside + virtual int putValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num, + int overwite = 0) = 0; + // delete a data object pointed by key value + virtual int delValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + // flush all internal buffer to disk + virtual int flush (void) = 0; + + // set data value + // specified either by a key + virtual int setValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + + // monitor on incoming database entries + virtual int monitorIncomingEntries (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + + // monitor off the above incoming database entries + virtual int monitorOffIncomingEntries (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + // monitor on data values + // monitor on the whole data + virtual int monitorValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + + // monitor on attribute of a data + virtual int monitorAttr (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + + // monitor off data values + virtual int monitorOffValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + + // monitor off attribute of a data + virtual int monitorOffAttr (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + + // monitor off value for a single io channel + virtual int monitorOff (void* io) = 0; + + // query the data store + virtual int query (rsvcNetData& data, char* msg, + rsvcNetData* outdata[], size_t* num) = 0; + + // get every entry in the store + virtual int getAll (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + + // inherited operation from hashable + unsigned int hash (void); + + // return name of this data store + char* name (void) const; + + // open and close data store operation + virtual int openDatabase (void); + virtual int closeDatabase (void); + + // handle client close + virtual void handleClose (void * /* client */) {} + + // from existing table definition and files + // to create a right dataStore object + static rsvcDataStore* createDataStore (char* name); + +protected: + // constructor + // construct data store with a unique name + rsvcDataStore (char* name); + + // remove all monitors on incoming data + void removeAllMonitors (void); + + + // update this data store time stamp which is the time when last + // action was done on the store. + void updateTimeStamp (void); + + // notify interested parties about an incoming entry + int notifyAnEntryToChannels (rsvcData& entry); + + // data area + char* name_; + + // time stamp of this data store + double timestamp_; + + // table definition + rsvcTableDef tableDef_; + + // data cache handler + rsvcHash cache_; + + // insert/deleted data monitor + rsvcHSlist idataMonitorList_; + rsvcHSlist odataMonitorList_; + + // database handler + rsvcVirtualDbase* database_; +}; +#endif + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDataStoreMem.cc b/extensions/cdevGenericServer/NameServer/src/rsvcDataStoreMem.cc new file mode 100755 index 0000000..299bdbb --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDataStoreMem.cc @@ -0,0 +1,678 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcDataStoreMem Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcDataStoreMem.cc,v +// Revision 1.2 1998/03/19 18:30:59 chen +// add monitorEntry capability to server table +// +// Revision 1.1 1998/01/22 17:08:07 akers +// Addition of new NameServer +// +// +// +#include +#include +#include +#include +#include +#include "rsvcDataStoreMem.h" + +#ifdef _WIN32 +#define strcasecmp _stricmp +#endif + + +rsvcDataStoreMem::rsvcDataStoreMem (char* name) +:rsvcDataStore (name) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcDataStoreMem Class Object\n"); +#endif + database_ = new rsvcVirtualDbase (); +} + +rsvcDataStoreMem::~rsvcDataStoreMem (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete rsvcDataStoreMem Class Object\n"); +#endif +} + +int +rsvcDataStoreMem::putValue (rsvcNetData& incoming, + rsvcNetData* out[], size_t* num, int overwrite) +{ + rsvcData& data = incoming.data (); + int status = RSVC_SUCCESS; + rsvcCacheData* cdata; + + if (tableDef_.tableDefined () && tableDef_.dataInsertable (data)) { + if (tableDef_.hasKey (data)) { + cdata = cachedData (data); + if (cdata) { +#ifdef _RSVC_DEBUG + printf ("Data with same key is already there\n"); +#endif + if (!overwrite) + status = RSVC_ERROR; + else { + cdata->assign (data); + notifyAnEntryToChannels (data); + } + } + else { + cache_.add (new rsvcCacheData (data, database_, &tableDef_)); + notifyAnEntryToChannels (data); + } + } + // check whether this data is compatable with table definition + else if (tableDef_.keyValue (data) == RSVC_SUCCESS) { + cdata = cachedData (data); + if (cdata) { +#ifdef _RSVC_DEBUG + printf ("Data with same key is already there\n"); +#endif + if (!overwrite) + status = RSVC_ERROR; + else { + cdata->assign (data); + notifyAnEntryToChannels (data); + } + } + else { + cache_.add (new rsvcCacheData (data, database_, &tableDef_)); + notifyAnEntryToChannels (data); + } + } + else + status = RSVC_ERROR; + } + else + status = RSVC_ERROR; + + // construct returning message + out[0] = new rsvcNetData (incoming.cbk ()); + out[0]->cbkstatus (status); + *num = 1; + + return status; +} + +int +rsvcDataStoreMem::query (rsvcNetData& incoming, char* msg, + rsvcNetData* out[], size_t *num) +{ + rsvcData& data = incoming.data (); + int status = RSVC_SUCCESS; + rsvcCacheData* cdata; + int i = 0; + + if (strcasecmp (msg, "all") == 0) // get all entries + return getAll (incoming, out, num); + + // first check whether the query string is valid + rsvcLogicQEng qe (msg); + if (qe.parse () != 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStoreMem: query msg <%s> systax error\n", msg); +#endif + status = RSVC_QUERYMSG_ERR; + } + else { + if (tableDef_.tableDefined ()) { + rsvcHashIterator ite (cache_); + + for (ite.init (); !ite; ++ite) { + cdata = (rsvcCacheData *) ite (); + rsvcData& rdata = cdata->data (); + if (qe.execute (rdata)) // match logic expression + if (i < *num) { + out[i] = new rsvcNetData (rdata, incoming.cbk ()); + out[i]->cbkstatus (RSVC_INCOMPLETE); + i++; + } + } + if (i > 0) { + *num = i; + out[i - 1]->cbkstatus (RSVC_SUCCESS); // turn last one to success + } + else + status = RSVC_NOTFOUND; + } + else + status = RSVC_ERROR; + } + + if (status != RSVC_SUCCESS) { + out[0] = new rsvcNetData (incoming.cbk ()); + out[0]->cbkstatus (status); + *num = 1; + } + + return status; +} + +int +rsvcDataStoreMem::getAll (rsvcNetData& incoming, + rsvcNetData* out[], size_t* num) +{ + int i = 0; + rsvcHashIterator ite (cache_); + rsvcCacheData* cdata = 0; + + for (ite.init (); !ite; ++ite) { + cdata = (rsvcCacheData *) ite (); + rsvcData& rdata = cdata->data (); + if (i < *num) { + out[i] = new rsvcNetData (rdata, incoming.cbk ()); + out[i]->cbkstatus (RSVC_INCOMPLETE); + i++; + } + } + + if (i == 0) { + *num = 1; + out[0] = new rsvcNetData (incoming.cbk ()); + out[0]->cbkstatus (RSVC_NOTFOUND); + return RSVC_NOTFOUND; + } + *num = i; + out[i - 1]->cbkstatus (RSVC_SUCCESS); // turn last one to success + + return RSVC_SUCCESS; +} + +rsvcCacheData * +rsvcDataStoreMem::cachedData (rsvcData& key) +{ + // create a fake cache data to do search + rsvcCacheData keydata (key, database_, &tableDef_); + rsvcHSlist& list = cache_.bucketRef (&keydata); + rsvcHSlistIterator ite (list); + rsvcCacheData* cdata; + + for (ite.init (); !ite; ++ite) { + cdata = (rsvcCacheData *) ite (); + if (cdata->sameKey (&keydata)) + return cdata; + } + return 0; +} + +int +rsvcDataStoreMem::deleteCachedData (rsvcData& key) +{ + // create a fake cache data to do search + rsvcCacheData keydata (key, database_, &tableDef_); + rsvcHSlist& list = cache_.bucketRef (&keydata); + rsvcHSlistIterator ite (list); + rsvcCacheData* cdata; + int found = 0; + + for (ite.init (); !ite; ++ite) { + cdata = (rsvcCacheData *) ite (); + if (cdata->sameKey (&keydata)) { + found = 1; + break; + } + } + if (found) { + // call all monitor callbacks on this data + cdata->notifyChannels (RSVC_CBK_FINISHED); + list.remove (cdata); + return RSVC_SUCCESS; + } + return RSVC_NOTFOUND; +} + +int +rsvcDataStoreMem::getValue (rsvcNetData& incoming, + rsvcNetData* out[], size_t* num) +{ + // check whether this data is compatable with table definition + rsvcData& data = incoming.data (); + int status = RSVC_SUCCESS; + rsvcNetData* retdata = 0; + + if (!tableDef_.tableDefined ()) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStoreMem: table definition is not defined\n"); +#endif + status = RSVC_ERROR; + } + else { + if (!tableDef_.hasKey (data)) { + if (tableDef_.keyValue (data) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStoreMem: cannot construct key value from data\n"); +#endif + status = RSVC_NOKEY; + } + } + } + + if (status == RSVC_SUCCESS) { + rsvcCacheData* cdata = cachedData (data); + if (!cdata) { + status = RSVC_NOTFOUND; + } + else + retdata = new rsvcNetData (cdata->data (), incoming.cbk ()); + } + + if (!retdata) { + retdata = new rsvcNetData (incoming.cbk ()); + } + retdata->cbkstatus (status); + out[0] = retdata; + *num = 1; + + return status; +} + + +int +rsvcDataStoreMem::delValue (rsvcNetData& incoming, + rsvcNetData* out[], size_t* num) +{ + // check whether this data is compatable with table definition + rsvcData& data = incoming.data (); + int status = RSVC_SUCCESS; + + if (!tableDef_.tableDefined () ) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStoreMem: table definition is not valid\n"); +#endif + status = RSVC_ERROR; + } + else { + if (!tableDef_.hasKey (data)) { + if (tableDef_.keyValue (data) != RSVC_SUCCESS) + status = RSVC_NOKEY; + } + } + + if (status == RSVC_SUCCESS) + status = deleteCachedData (data); + + out[0] = new rsvcNetData (incoming.cbk ()); + out[0]->cbkstatus (status); + *num = 1; + + return status; +} + +int +rsvcDataStoreMem::flush (void) +{ + return RSVC_SUCCESS; +} + +int +rsvcDataStoreMem::setValue (rsvcNetData& incoming, + rsvcNetData* out[], size_t* num) +{ + // check whether this data is compatable with table definition + rsvcData& data = incoming.data (); + int status = RSVC_SUCCESS; + + if (!tableDef_.tableDefined ()) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStoreMem: table definition is not defined yet\n"); +#endif + status = RSVC_ERROR; + } + else { + if (!tableDef_.dataValid (data)) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStoreMem: data not valid for settting\n"); +#endif + status = RSVC_INVALIDARG; + } + else { + if (!tableDef_.hasKey (data)) { + if (tableDef_.keyValue (data) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStoreMem: data has no key information for setting\n"); +#endif + status = RSVC_NOKEY; + } + } + } + } + + if (status == RSVC_SUCCESS) { + rsvcCacheData* cdata = cachedData (data); + if (!cdata) + status = RSVC_NOTFOUND; + else + status = cdata->assign (data); + } + + if (*num > 0) { + out[0] = new rsvcNetData (incoming.cbk ()); + out[0]->cbkstatus (status); + *num = 1; + } + + return status; +} + +int +rsvcDataStoreMem::monitorIncomingEntries (rsvcNetData& incoming, + rsvcNetData* out[], + size_t* num) +{ + int status = RSVC_SUCCESS; + rsvcNetData* retdata = 0; + int i = 0; + + // get all existing entries + rsvcHashIterator ite (cache_); + rsvcCacheData* cdata = 0; + + for (ite.init (); !ite; ++ite) { + cdata = (rsvcCacheData *) ite (); + rsvcData& rdata = cdata->data (); + if (i < *num) { + out[i] = new rsvcNetData (rdata, incoming.cbk ()); + out[i]->cbkstatus (RSVC_INCOMPLETE); + i++; + } + } + if (i > 0) { + *num = i; + out[i - 1]->cbkstatus (RSVC_SUCCESS); + } + else + status = RSVC_NOTFOUND; + + if (status != RSVC_SUCCESS) { + out[0] = new rsvcNetData (incoming.cbk ()); + // empty table is ok + out[0]->cbkstatus (RSVC_SUCCESS); + *num = 1; + } + + // add callback to monitor list + rsvcCbk* tcbk = new rsvcCbk (incoming.cbk ()); + idataMonitorList_.add (tcbk); + + return status; +} + +int +rsvcDataStoreMem::monitorOffIncomingEntries (rsvcNetData& incoming, + rsvcNetData* out[], + size_t* num) +{ + rsvcHSlistIterator ite (idataMonitorList_); + rsvcCbk* tcbk = 0; + int found = 0; + int status = RSVC_SUCCESS; + + for (ite.init (); !ite; ++ite) { + tcbk = (rsvcCbk *) ite (); + if (rsvcCbk::sameCallback (tcbk, &incoming.cbk (), 1)) { + found = 1; + break; + } + } + if (found) { + idataMonitorList_.remove (tcbk); + delete tcbk; + status = RSVC_CBK_FINISHED; + } + else + status = RSVC_NOTFOUND; + + out[0] = new rsvcNetData (incoming.cbk ()); + out[0]->cbkstatus (status); + *num = 1; + + return status; +} + +int +rsvcDataStoreMem::monitorValue (rsvcNetData& incoming, + rsvcNetData* out[], size_t* num) +{ + // check whether this data is compatable with table definition + rsvcData& data = incoming.data (); + int status = RSVC_SUCCESS; + rsvcNetData* retdata = 0; + + if (!tableDef_.tableDefined ()) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStoreMem: table definition is not defined\n"); +#endif + status = RSVC_ERROR; + } + else { + if (!tableDef_.hasKey (data)) { + if (tableDef_.keyValue (data) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStoreMem: data has no key for monitoring\n"); +#endif + status = RSVC_NOKEY; + } + } + } + + if (status == RSVC_SUCCESS) { + rsvcCacheData* cdata = cachedData (data); + if (!cdata) { + status = RSVC_NOTFOUND; + } + else + if ((status = cdata->monitorOn (incoming.cbk ())) == RSVC_SUCCESS) + retdata = new rsvcNetData (cdata->data (), incoming.cbk ()); + } + + if (!retdata) + retdata = new rsvcNetData (incoming.cbk ()); + + retdata->cbkstatus (status); + out[0] = retdata; + *num = 1; + + return status; +} + + +int +rsvcDataStoreMem::monitorAttr (rsvcNetData& incoming, + rsvcNetData* out[], size_t* num) +{ + // check whether this data is compatable with table definition + rsvcData& data = incoming.data (); + int status = RSVC_SUCCESS; + rsvcNetData* retdata = 0; + + if (!tableDef_.tableDefined ()) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStoreMem: table definition is not defined\n"); +#endif + status = RSVC_ERROR; + } + else { + if (!tableDef_.hasKey (data)) { + if (tableDef_.keyValue (data) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStoreMem: data has no key for monitoring\n"); +#endif + status = RSVC_NOKEY; + } + } + } + + if (status == RSVC_SUCCESS) { + // get attribute name from incoming data + char attribute[RSVC_TAG_MAX_LEN]; + if (data.get (rsvcServerConfig::monitorTag (), attribute, sizeof (attribute)) + != RSVC_SUCCESS) + status = RSVC_INVALIDARG; + else { + rsvcCacheData* cdata = cachedData (data); + if (!cdata) { + status = RSVC_NOTFOUND; + } + else { + if ((status = cdata->monitorAttr (attribute, incoming.cbk ())) == RSVC_SUCCESS) { + retdata = new rsvcNetData (cdata->data (), incoming.cbk ()); + // put monitor and attaribute into the outbound data + retdata->data ().insert (rsvcServerConfig::monitorTag (), attribute); + } + } + } + } + + if (!retdata) + retdata = new rsvcNetData (incoming.cbk ()); + + retdata->cbkstatus (status); + out[0] = retdata; + *num = 1; + + return status; +} + +int +rsvcDataStoreMem::monitorOffValue (rsvcNetData& incoming, + rsvcNetData* out[], size_t* num) +{ + // check whether this data is compatable with table definition + rsvcData& data = incoming.data (); + int status = RSVC_SUCCESS; + rsvcNetData* retdata = 0; + + if (!tableDef_.tableDefined ()) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStoreMem: Table is not defined yet\n"); +#endif + status = RSVC_ERROR; + } + else { + if (!tableDef_.hasKey (data)) { + if (tableDef_.keyValue (data) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStoreMem: data has no key for monitoring off\n"); +#endif + status = RSVC_NOKEY; + } + } + } + + if (status == RSVC_SUCCESS) { + rsvcCacheData* cdata = cachedData (data); + if (!cdata) { + status = RSVC_NOTFOUND; + } + else + if ((status = cdata->monitorOff (incoming.cbk ())) == RSVC_SUCCESS) + status = RSVC_CBK_FINISHED; + } + if (!retdata) + retdata = new rsvcNetData (incoming.cbk ()); + + retdata->cbkstatus (status); + out[0] = retdata; + *num = 1; + + return status; +} + + +int +rsvcDataStoreMem::monitorOffAttr (rsvcNetData& incoming, + rsvcNetData* out[], size_t* num) +{ + // check whether this data is compatable with table definition + rsvcData& data = incoming.data (); + int status = RSVC_SUCCESS; + rsvcNetData* retdata = 0; + + if (!tableDef_.tableDefined ()) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStoreMem: table definition is not defined\n"); +#endif + status = RSVC_ERROR; + } + else { + if (!tableDef_.hasKey (data)) { + if (tableDef_.keyValue (data) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcDataStoreMem: data has no key for monitoring\n"); +#endif + status = RSVC_NOKEY; + } + } + } + + if (status == RSVC_SUCCESS) { + // get attribute name from incoming data + char attribute[RSVC_TAG_MAX_LEN]; + if (data.get (rsvcServerConfig::monitorTag (), attribute, sizeof (attribute)) + != RSVC_SUCCESS) + status = RSVC_INVALIDARG; + else { + rsvcCacheData* cdata = cachedData (data); + if (!cdata) { + status = RSVC_NOTFOUND; + } + else + if (status = cdata->monitorOffAttr (attribute, incoming.cbk ()) == RSVC_SUCCESS) + status = RSVC_CBK_FINISHED; + } + } + + retdata = new rsvcNetData (incoming.cbk ()); + + retdata->cbkstatus (status); + out[0] = retdata; + *num = 1; + + return status; +} + + +int +rsvcDataStoreMem::monitorOff (void* ioptr) +{ + rsvcCacheData* cdata = 0; + rsvcHashIterator ite (cache_); + + int i = 0; + for (ite.init (); !ite; ++ite) { + cdata = (rsvcCacheData *) ite (); + cdata->monitorOff (ioptr); + i++; + } + + // remove monitor entry callbacks for this client + rsvcHSlistIterator eite (idataMonitorList_); + rsvcCbk* cbk = 0; + + for (eite.init (); !eite; ++eite) { + cbk = (rsvcCbk *) eite (); + + // connection channel + if (cbk->userptr () == ioptr) { + delete cbk; + eite.removeCurrent (); + } + } + return RSVC_SUCCESS; +} diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDataStoreMem.h b/extensions/cdevGenericServer/NameServer/src/rsvcDataStoreMem.h new file mode 100755 index 0000000..11c7b57 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDataStoreMem.h @@ -0,0 +1,105 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server In Memory Data Store +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_DATASTORE_MEM_H +#define _RSVC_DATASTORE_MEM_H + +#include +#include +#include +#include +#include + +class rsvcCacheData; + +class rsvcDataStoreMem: public rsvcDataStore +{ +public: + // constructor and destructor + rsvcDataStoreMem (char* name); + ~rsvcDataStoreMem (void); + + // inherited operations + // get data values + // specified by a key + virtual int getValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + // insert a rsvcData which may have a key inside or not + virtual int putValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num, + int overwrite = 0); + + // delete a data object pointed by key value + virtual int delValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + // flush all internal buffer to disk + virtual int flush (void); + + // set data value + // specified either by a key or a whole data + virtual int setValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + // monitor on incoming database entries + virtual int monitorIncomingEntries (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + // monitor off the above incoming database entries + virtual int monitorOffIncomingEntries (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + // monitor on data values + // monitor on either the whole data + virtual int monitorValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + // monitor on attribute of a data + virtual int monitorAttr (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + // monitor off data value + virtual int monitorOffValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + // monitor off attribute of a data + virtual int monitorOffAttr (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + + // monitor off data value for all monitors from same socket id + virtual int monitorOff (void* io); + + // query the data store + virtual int query (rsvcNetData& data, char* msg, + rsvcNetData* outdata[], size_t* num); + + // get every entry in the store + virtual int getAll (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + +protected: + + // find cached data item inside cache from a key data + rsvcCacheData* cachedData (rsvcData& keydata); + + // delete a cached data item inside cache from a key dta + int deleteCachedData (rsvcData& key); +}; +#endif + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDataStoreTable.cc b/extensions/cdevGenericServer/NameServer/src/rsvcDataStoreTable.cc new file mode 100755 index 0000000..02aa867 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDataStoreTable.cc @@ -0,0 +1,141 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcDataStoreTable Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcDataStoreTable.cc,v +// Revision 1.2 1998/01/22 20:04:07 chen +// to make it work with cdevReactor +// +// Revision 1.1 1998/01/22 17:08:08 akers +// Addition of new NameServer +// +// +// +#include "rsvcDataStoreTable.h" + +static unsigned int +store_table_hash (char* str) +{ + unsigned int h = 0, g; + + for (int i = 0; str[i] != '\0'; i++){ + h = (h << 4) + str[i]; + // assume 32 bit integer + if (g = h & 0xf0000000){ + h ^= g >> 24; + h ^= g; + } + } + return h; +} + +rsvcDataStoreTable::rsvcDataStoreTable (unsigned int max, unsigned int lf) +:table_ (max, lf) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcDataStoreTable Class Object\n"); +#endif +} + +rsvcDataStoreTable::~rsvcDataStoreTable (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcDataStoreTable Class Object\n"); +#endif + + rsvcHashIterator ite (table_); + rsvcDataStore* store = 0; + + for (ite.init (); !ite; ++ite) { + store = (rsvcDataStore *) ite (); + delete store; + } +} + +rsvcDataStore * +rsvcDataStoreTable::find (char* name) +{ + // calculate hash code for this name + unsigned int hashcode = store_table_hash (name); + + // access a particular bucket + rsvcHSlist& list = table_.bucketRef (hashcode); + rsvcHSlistIterator ite (list); + rsvcDataStore* store = 0; + + for (ite.init (); !ite; ++ite) { + store = (rsvcDataStore *) ite (); + if (strcmp (store->name (), name) == 0) + return store; + } + return 0; +} + + +int +rsvcDataStoreTable::add (rsvcDataStore* store) +{ + rsvcHSlist& list = table_.bucketRef (store); + + rsvcHSlistIterator ite (list); + rsvcDataStore* tstore = 0; + + for (ite.init (); !ite; ++ite) { + tstore = (rsvcDataStore *) ite (); + if (strcmp (store->name (), tstore->name ()) == 0) + return RSVC_ERROR; + } + list.add (store); + return RSVC_SUCCESS; +} + + +void +rsvcDataStoreTable::monitorOff (void* io) +{ + rsvcHashIterator ite (table_); + rsvcDataStore *store = 0; + + for (ite.init (); !ite; ++ite) { + store = (rsvcDataStore *) ite (); + store->monitorOff (io); + } +} + +void +rsvcDataStoreTable::handleClose (void* io) +{ + rsvcHashIterator ite (table_); + rsvcDataStore *store = 0; + + for (ite.init (); !ite; ++ite) { + store = (rsvcDataStore *) ite (); + store->handleClose (io); + } +} + +int +rsvcDataStoreTable::openDatabase (char* name) +{ + rsvcDataStore* datastore = rsvcDataStore::createDataStore (name); + + if (datastore && add (datastore) == RSVC_SUCCESS) + return datastore->openDatabase (); + return RSVC_ERROR; +} + + + + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDataStoreTable.h b/extensions/cdevGenericServer/NameServer/src/rsvcDataStoreTable.h new file mode 100755 index 0000000..7afd63b --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDataStoreTable.h @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server All Data Store Table +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_DATA_STORE_TABLE_H +#define _RSVC_DATA_STORE_TABLE_H + +#include +#include +#include +#include +#include + +class rsvcDataStoreTable +{ +public: + // constructor + rsvcDataStoreTable (unsigned int max = 100, unsigned int lf = 5); + + // destructor + ~rsvcDataStoreTable (void); + + // add a data store + int add (rsvcDataStore* store); + + // find a data store + rsvcDataStore* find (char* name); + + // open a datastore with name + int openDatabase (char* name); + + // monitor off all values for a client + void monitorOff (void* io); + + // handle close for a client + void handleClose (void* io); + +private: + + // data area + rsvcHash table_; + + // deny access to copy and assignment operations + rsvcDataStoreTable (const rsvcDataStoreTable& table); + rsvcDataStoreTable operator = (const rsvcDataStoreTable& table); +}; +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDataStreamer.cc b/extensions/cdevGenericServer/NameServer/src/rsvcDataStreamer.cc new file mode 100755 index 0000000..ebb9bb7 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDataStreamer.cc @@ -0,0 +1,630 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// rsvc data streamer class +// +// Author: Jie Chen +// +// Revision History: +// rsvcDataStreamer.cc,v +// Revision 1.1 1998/01/22 17:08:08 akers +// Addition of new NameServer +// +// +// +#include "rsvcErr.h" +#include "rsvcDataStreamer.h" + +// ****************************************************************** +// float and double conversion routines +// not portable yet especially for VAX machines +// ****************************************************************** +static float htonf (float f) +{ + float fret; + long *p = (long *)&f; + long nl = htonl (*p); + fret = *(float *)&nl; + return fret; +} + +static float ntohf (float f) +{ + float fret; + + long *p = (long *)&f; + long nl = ntohl (*p); + fret = *(float *)&nl; + return fret; +} + +static double htond (double d) +{ + long *lp, *lq; + long *dp, *dq; + double ret; + + // move high byte first + lp = lq = (long *)&d; + lp++; + + dp = dq = (long *)&ret; + *dp = htonl (*lp); + + lp--; dp++; + *dp = htonl (*lp); + + ret = *(double *)dq; + return ret; +} + +static double ntohd (double d) +{ + long *lp, *lq; + long *dp, *dq; + double ret; + + // low byte of incoming data should be high byte of host native data + lp = lq = (long *)&d; + dp = dq = (long *)&ret; + dp++; + + *dp = ntohl (*lp); + + lp++; dp--; + *dp = ntohl (*lp); + + ret = *(double *)dq; + return ret; +} + +static rsvc_TS_STAMP htonts (rsvc_TS_STAMP& ts) +{ + rsvc_TS_STAMP rts; + + rts.secPastEpoch = htonl (ts.secPastEpoch); + rts.nsec = htonl (ts.nsec); + return rts; +} + +static rsvc_TS_STAMP ntohts (rsvc_TS_STAMP& ts) +{ + rsvc_TS_STAMP rts; + + rts.secPastEpoch = ntohl (ts.secPastEpoch); + rts.nsec = ntohl (ts.nsec); + return rts; +} + + +rsvcDataStreamer::rsvcDataStreamer (char* buffer, size_t buflen, + int dealloc) +:buffer_ (buffer), buflen_ (buflen), dealloc_ (dealloc), pos_ (0), + err_ (RSVC_SUCCESS) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcDataStreamer Class Object\n"); +#endif +} + +rsvcDataStreamer::~rsvcDataStreamer (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcDataStreamer Class Object\n"); +#endif + if (dealloc_) + if (buffer_) { + delete []buffer_; + buffer_ = 0; + } +} + +char* +rsvcDataStreamer::buffer (void) const +{ + return buffer_; +} + +size_t +rsvcDataStreamer::bufferLength (void) const +{ + return buflen_; +} + +int +rsvcDataStreamer::streamStatus (void) const +{ + return err_; +} + + +//=============================================================== +// Implementation of rsvcDataStreamWriter +//=============================================================== +rsvcDataStreamWriter::rsvcDataStreamWriter (char* buffer, size_t size, + int dealloc) +:rsvcDataStreamer (buffer, size, dealloc) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcDataStreamWriter Class Object\n"); +#endif +} + +rsvcDataStreamWriter::~rsvcDataStreamWriter (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete rsvcDataStreamWriter Class Object\n"); +#endif +} + +int +rsvcDataStreamWriter::write (char c) +{ + long tmp = (long)c; + return write (tmp); +} + +int +rsvcDataStreamWriter::write (unsigned char c) +{ + long tmp = (long)c; + return write (tmp); +} + +int +rsvcDataStreamWriter::write (short c) +{ + long tmp = (long)c; + return write (tmp); +} + +int +rsvcDataStreamWriter::write (unsigned short c) +{ + long tmp = (long)c; + return write (tmp); +} + + +int +rsvcDataStreamWriter::write (int c) +{ + long tmp = (long)c; + return write (tmp); +} + +int +rsvcDataStreamWriter::write (unsigned int c) +{ + long tmp = (long)c; + return write (tmp); +} + +int +rsvcDataStreamWriter::write (long c) +{ + long tmp = htonl (c); + if (pos_ + rsvcStreamSize (c) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: write overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + memcpy (&(buffer_[pos_]), &tmp, rsvcStreamSize (c)); + pos_ += rsvcStreamSize (c); + + return RSVC_SUCCESS; +} + +int +rsvcDataStreamWriter::write (unsigned long c) +{ + long tmp = (long)c; + return write (tmp); +} + +int +rsvcDataStreamWriter::write (float c) +{ + float ftmp = htonf (c); + + if (pos_ + rsvcStreamSize (c) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: write float overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + memcpy (&(buffer_[pos_]), &ftmp, rsvcStreamSize (c)); + pos_ += rsvcStreamSize (c); + + return RSVC_SUCCESS; +} + +int +rsvcDataStreamWriter::write (double c) +{ + double dtmp = htond (c); + + if (pos_ + rsvcStreamSize (c) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: write double overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + memcpy (&(buffer_[pos_]), &dtmp, rsvcStreamSize (c)); + + pos_ += rsvcStreamSize (c); +#ifdef _RSVC_DEBUG + printf ("Write cursor is %d\n", pos_); +#endif + return RSVC_SUCCESS; +} + +int +rsvcDataStreamWriter::write (char* str) +{ + size_t slen = strlen (str) + 1; + size_t rlen = _RSVC_RNDUP (slen); + size_t len = sizeof (long) + _RSVC_RNDUP (slen); + + if (pos_ + len > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: write string %s overflow buffer at %d with bufsize %d\n", + str, pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + + // write size of string first + write ((long)rlen); + + memcpy (&(buffer_[pos_]), str, slen); + pos_ += slen; + + if (rlen > slen) + memset (&(buffer_[pos_]), 0, rlen - slen); + pos_ += (rlen - slen); + + return RSVC_SUCCESS; +} + +int +rsvcDataStreamWriter::write (void* data, size_t len) +{ + size_t rlen = _RSVC_RNDUP (len); + size_t wlen = sizeof (long) + rlen; + + if (pos_ + wlen > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: write void * overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + + // write out size of data first + write ((long)rlen); + + memcpy (&(buffer_[pos_]), data, len); + pos_ += len; + + if (rlen > len) + memset (&(buffer_[pos_]), 0, rlen - len); + + pos_ += (rlen - len); + + return RSVC_SUCCESS; +} + +int +rsvcDataStreamWriter::write (rsvc_TS_STAMP& ts) +{ + rsvc_TS_STAMP tts = htonts (ts); + + if (pos_ + rsvcStreamSize (ts) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: write TS overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + memcpy (&(buffer_[pos_]), &tts, rsvcStreamSize (ts)); + pos_ += rsvcStreamSize (ts); + + return RSVC_SUCCESS; +} + +//=============================================================== +// Implementation of rsvcDataStreamReader +//=============================================================== +rsvcDataStreamReader::rsvcDataStreamReader (char* buffer, size_t buflen, + int dealloc) +:rsvcDataStreamer (buffer, buflen, dealloc) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcDataStreamReader Class Object\n"); +#endif +} + +rsvcDataStreamReader::~rsvcDataStreamReader (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete rsvcDataStreamReader Class Object\n"); +#endif +} + + +int +rsvcDataStreamReader::read (char& c) +{ + long tmp; + int st; + + if ((st = read (tmp)) == RSVC_SUCCESS) + c = (char)tmp; + else + c = 0; + + return st; +} + +int +rsvcDataStreamReader::read (unsigned char& c) +{ + long tmp; + int st; + + if ((st = read (tmp)) == RSVC_SUCCESS) + c = (unsigned char)tmp; + else + c = 0; + + return st; +} + +int +rsvcDataStreamReader::read (short & c) +{ + long tmp; + int st; + + if ((st = read (tmp)) == RSVC_SUCCESS) + c = (short)tmp; + else + c = 0; + + return st; +} + +int +rsvcDataStreamReader::read (unsigned short& c) +{ + long tmp; + int st; + + if ((st = read (tmp)) == RSVC_SUCCESS) + c = (unsigned short)tmp; + else + c = 0; + + return st; +} + +int +rsvcDataStreamReader::read (int& c) +{ + long tmp; + int st; + + if ((st = read (tmp)) == RSVC_SUCCESS) + c = (int)tmp; + else + c = 0; + + return st; +} + +int +rsvcDataStreamReader::read (unsigned int& c) +{ + long tmp; + int st; + + if ((st = read (tmp)) == RSVC_SUCCESS) + c = (unsigned int)tmp; + else + c = 0; + + return st; +} + +int +rsvcDataStreamReader::read (long& c) +{ + long tmp; + + if (pos_ + sizeof (c) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read long overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + + memcpy (&tmp, &(buffer_[pos_]), sizeof (long)); + pos_ += sizeof (long); + + c = ntohl (tmp); + return RSVC_SUCCESS; +} + +int +rsvcDataStreamReader::read (unsigned long& c) +{ + long tmp; + int st; + + if ((st = read (tmp)) == RSVC_SUCCESS) + c = (unsigned long)tmp; + else + c = 0; + + return st; +} + +int +rsvcDataStreamReader::read (float& c) +{ + float ftmp; + + if (pos_ + rsvcStreamSize (c) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read float overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + memcpy (&ftmp, &(buffer_[pos_]), rsvcStreamSize (c)); + pos_ += rsvcStreamSize (c); + + c = ntohf (ftmp); + + return RSVC_SUCCESS; +} + +int +rsvcDataStreamReader::read (double& c) +{ + double dtmp; + + if (pos_ + rsvcStreamSize (c) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read double overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + memcpy (&dtmp, &(buffer_[pos_]), rsvcStreamSize (c)); + pos_ += rsvcStreamSize (c); + + c = ntohd (dtmp); + + return RSVC_SUCCESS; +} + +int +rsvcDataStreamReader::read (rsvc_TS_STAMP & ts) +{ + rsvc_TS_STAMP tts; + + if (pos_ + rsvcStreamSize (ts) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read TS overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + memcpy (&tts, &(buffer_[pos_]), rsvcStreamSize (ts)); + pos_ += rsvcStreamSize (ts); + + ts = ntohts (tts); + return RSVC_SUCCESS; +} + +int +rsvcDataStreamReader::read (char* & str) +{ + long str_size = 0; + int st = RSVC_SUCCESS; + + if (pos_ + sizeof (long) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read string header overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + st = err_ = RSVC_ERROR; + return err_; + } + + if ((st = read (str_size)) == RSVC_SUCCESS) { + if (pos_ + str_size > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read string overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + err_ = RSVC_ERROR; + return err_; + } + + if (str_size > 0) { + str = new char[str_size]; + memcpy (str, &(buffer_[pos_]), (unsigned int)str_size); + pos_ += (int)str_size; + } + else { + str = 0; + err_ = st = RSVC_ERROR; + } + } + else { + str = 0; + st = err_ = RSVC_ERROR; + } + return st; +} + +int +rsvcDataStreamReader::read (void* data, size_t size) +{ + long data_size = 0; + int st = RSVC_SUCCESS; + + if (pos_ + sizeof (long) > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read void * header overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + st = err_ = RSVC_ERROR; + return err_; + } + + if ((st = read (data_size)) == RSVC_SUCCESS) { + if (pos_ + data_size > buflen_) { +#ifdef _RSVC_DEBUG + fprintf (stderr, "Fatal Error: read void * overflow buffer at %d with bufsize %d\n", + pos_, buflen_); +#endif + st = err_ = RSVC_ERROR; + return err_; + } + if (data_size > 0) { + memcpy (data, &(buffer_[pos_]), size); + pos_ += (int)data_size; + } + else + st = err_ = RSVC_ERROR; + } + return st; +} + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDataStreamer.h b/extensions/cdevGenericServer/NameServer/src/rsvcDataStreamer.h new file mode 100755 index 0000000..d819611 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDataStreamer.h @@ -0,0 +1,183 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// rsvc data streamer class +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_DATA_STREAMER +#define _RSVC_DATA_STREAMER + +#include +#include +#include +#include +#ifdef _WIN32 + #include +#else + #include + #include +#endif + +#include + +#define _RSVC_STREAM_BYTE_UNIT (sizeof (long)) + +inline int _RSVC_RNDUP (size_t x) +{ + return ((x + _RSVC_STREAM_BYTE_UNIT - 1) / _RSVC_STREAM_BYTE_UNIT) + * _RSVC_STREAM_BYTE_UNIT; +} + +inline size_t rsvcStreamSize (char c) +{ + return _RSVC_RNDUP (sizeof (c)); +} + +inline size_t rsvcStreamSize (unsigned char c) +{ + return _RSVC_RNDUP (sizeof (c)); +} + +inline size_t rsvcStreamSize (short c) +{ + return _RSVC_RNDUP (sizeof (c)); +} + +inline size_t rsvcStreamSize (unsigned short c) +{ + return _RSVC_RNDUP (sizeof (c)); +} + +inline size_t rsvcStreamSize (int c) +{ + return _RSVC_RNDUP (sizeof (c)); +} + +inline size_t rsvcStreamSize (unsigned int c) +{ + return _RSVC_RNDUP (sizeof (c)); +} + +inline size_t rsvcStreamSize (long c) +{ + return sizeof (c); +} + +inline size_t rsvcStreamSize (unsigned long c) +{ + return sizeof (c); +} + +inline size_t rsvcStreamSize (float c) +{ + return sizeof (c); +} + +inline size_t rsvcStreamSize (double c) +{ + return sizeof (c); +} + +inline size_t rsvcStreamSize (char* str) +{ + return sizeof (long) + _RSVC_RNDUP (strlen (str) + 1); +} + +inline size_t rsvcStreamSize (void*, size_t size) +{ + return sizeof (long) + _RSVC_RNDUP (size); +} + +inline size_t rsvcStreamSize (rsvc_TS_STAMP& ts) +{ + return sizeof (ts); +} + +class rsvcDataStreamer +{ +public: + // destructor + virtual ~rsvcDataStreamer (void); + + char* buffer (void) const; + size_t bufferLength (void) const; + + int streamStatus (void) const; + +protected: + // constructor + // attach to a stream buffer. + // dealloc == 1 free buffer in the detrcutor. + rsvcDataStreamer (char* buffer, size_t buflen, int dealloc = 1); + + // binray stream buffer + char* buffer_; + size_t buflen_; + + // free memory stratege + int dealloc_; + + // index pointing to current position + int pos_; + + // streaming status + int err_; +}; + +class rsvcDataStreamWriter : public rsvcDataStreamer +{ +public: + // constructor and destrcutor + rsvcDataStreamWriter (char* buffer, size_t buflen, int dealloc = 1); + ~rsvcDataStreamWriter (void); + + // operations + int write (char c); + int write (unsigned char c); + int write (short c); + int write (unsigned short c); + int write (int c); + int write (unsigned int c); + int write (long c); + int write (unsigned long c); + int write (float c); + int write (double c); + int write (char* str); + int write (void* data, size_t size); + int write (rsvc_TS_STAMP& ts); +}; + +class rsvcDataStreamReader : public rsvcDataStreamer +{ +public: + // constructor and destrcutor + rsvcDataStreamReader (char* buffer, size_t buflen, int dealloc = 1); + ~rsvcDataStreamReader (void); + + // operations + int read (char& c); + int read (unsigned char& c); + int read (short& c); + int read (unsigned short& c); + int read (int& c); + int read (unsigned int& c); + int read (long& c); + int read (unsigned long& c); + int read (float& c); + int read (double& c); + int read (char* &str); + int read (void* data, size_t size); + int read (rsvc_TS_STAMP& ts); +}; + +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDataTypes.h b/extensions/cdevGenericServer/NameServer/src/rsvcDataTypes.h new file mode 100755 index 0000000..088bb08 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDataTypes.h @@ -0,0 +1,43 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: Data Type Definition +// +// Author: Jie Chen +// +// +// +//-------------------------------------------------------------------------- + +#ifndef _RSVC_TYPES_H +#define _RSVC_TYPES_H + +typedef unsigned char BYTE; + +enum rsvcDataTypes + { + RSVC_BYTE, + RSVC_INT16, + RSVC_UINT16, + RSVC_INT32, + RSVC_UINT32, + RSVC_FLOAT, + RSVC_DOUBLE, + RSVC_STRING, + RSVC_TIMESTAMP, + RSVC_INVALID + }; + +// rsvc time struct +typedef struct { + unsigned long secPastEpoch; // seconds since Jan. 1, 1970 + unsigned long nsec; // nanoseconds within second +} rsvc_TS_STAMP; + +#define RSVC_TAG_MAX_LEN 16 +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDatabase.cc b/extensions/cdevGenericServer/NameServer/src/rsvcDatabase.cc new file mode 100755 index 0000000..fba72e6 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDatabase.cc @@ -0,0 +1,880 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcDatabase +// +// Author: Jie Chen +// +// Revision History: +// rsvcDatabase.cc,v +// Revision 1.1 1998/01/22 17:08:09 akers +// Addition of new NameServer +// +// +// +#include +#include "rsvcDatabase.h" + +//========================================================================= +// All possible comparison functions for B+tree +//========================================================================= +static int rsvcUcharFunc (const DBT *key1, const DBT* key2) +{ + unsigned char s1 = *(unsigned char *)key1->data; + unsigned char s2 = *(unsigned char *)key2->data; + return s1 - s2; +} + +static int rsvcUshortFunc (const DBT *key1, const DBT* key2) +{ + unsigned short s1; + unsigned short s2; + + memcpy (&s1, key1->data, sizeof (s1)); + memcpy (&s2, key2->data, sizeof (s2)); + + return s1 - s2; +} + +static int rsvcShortFunc (const DBT *key1, const DBT* key2) +{ + short s1; + short s2; + + memcpy (&s1, key1->data, sizeof (s1)); + memcpy (&s2, key2->data, sizeof (s2)); + + return s1 - s2; +} + +static int rsvcUintFunc (const DBT *key1, const DBT* key2) +{ + unsigned int s1; + unsigned int s2; + + memcpy (&s1, key1->data, sizeof (s1)); + memcpy (&s2, key2->data, sizeof (s2)); + + return s1 - s2; +} + +static int rsvcIntFunc (const DBT *key1, const DBT* key2) +{ + int s1; + int s2; + + memcpy (&s1, key1->data, sizeof (s1)); + memcpy (&s2, key2->data, sizeof (s2)); + + return s1 - s2; +} + +static int rsvcFloatFunc (const DBT *key1, const DBT* key2) +{ + float s1; + float s2; + float res; + + memcpy (&s1, key1->data, sizeof (s1)); + memcpy (&s2, key2->data, sizeof (s2)); + + res = s1 - s2; + if (res > 0.00001) + return 1; + else if (res < -1*0.00001) + return -1; + return 0; +} + +static int rsvcDoubleFunc (const DBT *key1, const DBT* key2) +{ + double s1; + double s2; + double res; + + memcpy (&s1, key1->data, sizeof (s1)); + memcpy (&s2, key2->data, sizeof (s2)); + + res = s1 - s2; + if (res > 0.00001) + return 1; + else if (res < -1*0.00001) + return -1; + return 0; +} + +static int rsvcStringFunc (const DBT* key1, const DBT* key2) +{ + return strcmp ((char *)key1->data, (char *)key2->data); +} + +static int rsvcTSFunc (const DBT* key1, const DBT* key2) +{ + rsvc_TS_STAMP s1; + rsvc_TS_STAMP s2; + + memcpy (&s1, key1->data, sizeof (s1)); + memcpy (&s2, key2->data, sizeof (s2)); + + double t1 = s1.secPastEpoch + s1.nsec/1000000000.0; + double t2 = s2.secPastEpoch + s2.nsec/1000000000.0; + + double res = t1 - t2; + if (res > 0.00001) + return 1; + else if (res < -1*0.00001) + return -1; + return 0; +} + +rsvcCompFunc +rsvcDatabase::compFuncs_[] = { + rsvcUcharFunc, + rsvcShortFunc, + rsvcUshortFunc, + rsvcIntFunc, + rsvcUintFunc, + rsvcFloatFunc, + rsvcDoubleFunc, + rsvcStringFunc, + rsvcTSFunc +}; + +#if defined (_RSVC_USE_THREAD) && defined (_REENTRANT) +rsvcDatabase::rsvcDatabase (void) +:rsvcVirtualDbase (), dbp_ (0), dbc_ (0), wsize_ (0), mutex_ () +#else +rsvcDatabase::rsvcDatabase (void) +:rsvcVirtualDbase (), dbp_ (0), dbc_ (0), wsize_ (0) +#endif +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcDatabase Class Object\n"); +#endif +} + +#if defined (_RSVC_USE_THREAD) && defined (_REENTRANT) +rsvcDatabase::rsvcDatabase (char* name, int flags, int keyType, + size_t data_size, + size_t cache_size, + size_t page_size, int mode) +:rsvcVirtualDbase (name, flags, keyType, data_size, cache_size, page_size, mode), + dbp_ (0), dbc_ (0), wsize_ (0), mutex_ () +#else +rsvcDatabase::rsvcDatabase (char* name, int flags, int keyType, + size_t data_size, + size_t cache_size, + size_t page_size, int mode) +:rsvcVirtualDbase (name, flags, keyType, data_size, cache_size, page_size, mode), + dbp_ (0), dbc_ (0), wsize_ (0) +#endif +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcDatabase Class Object\n"); +#endif + + create (name, flags, keyType, data_size, cache_size, page_size, mode); +} + +rsvcDatabase::~rsvcDatabase (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcDatabase Class Object\n"); +#endif + + if (dbc_) + (void)(*dbc_->c_close)(dbc_); + + if (dbp_) + (void)(*dbp_->close)(dbp_, 0); + + dbp_ = 0; + + opened_ = 0; +} + +int +rsvcDatabase::create (char* name, int flags, int keyType, + size_t data_size, size_t cache_size, + size_t page_size, int mode) +{ + // get database environment + rsvcDatabaseEnv* env = rsvcDatabaseEnv::dbaseEnv (); + DB_ENV* dbenv = env->dbenv (); + + memset (&b_, 0, sizeof (b_)); + if (cache_size == 0) + b_.db_cachesize = rsvcServerConfig::dbaseCacheSize (); + else + b_.db_cachesize = cache_size; + + if (page_size == 0) + b_.db_pagesize = rsvcServerConfig::dbasePageSize (); + else + b_.db_pagesize = page_size; + + page_size_ = b_.db_pagesize; + + b_.db_lorder = 4321; // big endien + b_.flags = DB_DUP; // allow duplicated key + // the following are related to b+ tree only + b_.bt_minkey = page_size/data_size; + b_.bt_compare = rsvcDatabase::compFuncs_[keyType]; + + // create database + name_ = new char[::strlen (name) + 1]; + ::strcpy (name_, name); + if ((err_ = db_open (name_, DB_BTREE, DB_CREATE | O_RDWR, + mode, dbenv, &b_, &dbp_)) != 0) { + fprintf (stderr, "Fatal Error: cannot create database %s\n", name_); + fprintf (stderr, "Err_ is %d\n", err_); + err_ = err_; + return RSVC_ERROR; + } + else { // force database to flush its meta data onto the disk + (*dbp_->sync)(dbp_, 0); + err_ = 0; + opened_ = 1; + keyType_ = keyType; + return RSVC_SUCCESS; + } +} + + +int +rsvcDatabase::open (char* name, int flags, int keyType, + size_t cache_size, int mode) +{ + if (err_ == 0 && opened_ && dbp_) + return RSVC_SUCCESS; + + // get database environment + rsvcDatabaseEnv* env = rsvcDatabaseEnv::dbaseEnv (); + DB_ENV* dbenv = env->dbenv (); + + memset (&b_, 0, sizeof (b_)); + if (cache_size == 0) + b_.db_cachesize = rsvcServerConfig::dbaseCacheSize (); + else + b_.db_cachesize = cache_size; + + b_.db_lorder = 4321; // big endien + b_.flags = DB_DUP; // allow duplicated key + b_.bt_compare = rsvcDatabase::compFuncs_[keyType]; + + // create database + name_ = new char[::strlen (name) + 1]; + ::strcpy (name_, name); + if ((err_ = db_open (name_, DB_BTREE, DB_CREATE | O_RDWR, + mode, dbenv, &b_, &dbp_)) != 0) { + fprintf (stderr, "Fatal Error: cannot create database %s\n", name_); + fprintf (stderr, "Err_ is %d\n", err_); + err_ = err_; + return RSVC_ERROR; + } + else { // force database to flush its meta data onto the disk + err_ = 0; + opened_ = 1; + page_size_ = b_.db_pagesize; + keyType_ = keyType; + return RSVC_SUCCESS; + } +} + +int +rsvcDatabase::close (void) +{ + if (dbc_) + (*dbc_->c_close) (dbc_); + dbc_ = 0; + + if (dbp_) + (*dbp_->close)(dbp_, 0); + dbp_ = 0; + + opened_ = 0; + wsize_ = 0; + return RSVC_SUCCESS; +} + +int +rsvcDatabase::flush (void) +{ + if (opened_ && dbp_) { + (*dbp_->sync)(dbp_, 0); + return RSVC_SUCCESS; + } + return RSVC_ERROR; +} + +int +rsvcDatabase::opened (void) const +{ + return (opened_ && dbp_); +} + +int +rsvcDatabase::fd (void) +{ + if (opened_ && dbp_) { + int fdp; + (*dbp_->fd)(dbp_, &fdp); + return fdp; + } + return 0; +} + +int +rsvcDatabase::cursorInit (void) +{ + rsvcDatabaseLocker locker (this); + + if (err_ !=0 || !opened_ || !dbp_) + return RSVC_ERROR; + + if (dbc_) { + (*dbc_->c_close)(dbc_); + dbc_ = 0; + } + + if (err_ = dbp_->cursor (dbp_, 0, &dbc_) != 0) { + fprintf (stderr, "Cannot initialize the cursor operation\n"); + return RSVC_ERROR; + } + return RSVC_SUCCESS; +} + +int +rsvcDatabase::cursorSet (rsvcData& data, rsvcData& key) +{ + rsvcDatabaseLocker locker (this); + + if (err_ !=0 || !opened_ || !dbp_ || !dbc_) + return RSVC_ERROR; + + rsvcDBT tkey; + DBT res; memset (&res, 0, sizeof (res)); + + if (rsvcDatabase::convertKey (&tkey, key, keyType_, keybuf_) != RSVC_SUCCESS) + return RSVC_ERROR; + + + err_ = (*dbc_->c_get)(dbc_, tkey.dbt (), &res, DB_SET_RANGE); + + // success + if (err_ == 0) { + rsvcDatabase::copyKeyData (key, tkey.dbt(), keyType_); + return rsvcDatabase::convertData (data, &res); + } + else if (err_ != DB_NOTFOUND) { + // not found + return RSVC_NOTFOUND; + } + else + return RSVC_ERROR; +} + + +int +rsvcDatabase::cursorNext (rsvcData& data, rsvcData& key) +{ + rsvcDatabaseLocker locker (this); + + if (err_ !=0 || !opened_ || !dbp_ || !dbc_) + return RSVC_ERROR; + + DBT tkey; memset (&tkey, 0, sizeof (tkey)); + DBT res; memset (&res, 0, sizeof (res)); + + err_ = (*dbc_->c_get)(dbc_, &tkey, &res, DB_NEXT); + + if (err_ == 0) { + // success + rsvcDatabase::copyKeyData (key, &tkey, keyType_); + return rsvcDatabase::convertData (data, &res); + } + else if (err_ != DB_NOTFOUND) { + // not found + return RSVC_NOTFOUND; + } + else + return RSVC_ERROR; +} + +int +rsvcDatabase::cursorPrev (rsvcData& data, rsvcData& key) +{ + rsvcDatabaseLocker locker (this); + + if (err_ !=0 || !opened_ || !dbp_ || !dbc_) + return RSVC_ERROR; + + DBT tkey; memset (&tkey, 0, sizeof (tkey)); + DBT res; memset (&res, 0, sizeof (res)); + + err_ = (*dbc_->c_get)(dbc_, &tkey, &res, DB_PREV); + + if (err_ == 0) { + // success + rsvcDatabase::copyKeyData (key, &tkey, keyType_); + return rsvcDatabase::convertData (data, &res); + } + else if (err_ != DB_NOTFOUND) { + // not found + return RSVC_NOTFOUND; + } + else + return RSVC_ERROR; +} + +int +rsvcDatabase::cursorUpdate (rsvcData& value) +{ + rsvcDatabaseLocker locker (this); + + if (err_ != 0 || !opened_ || !dbp_ || !dbc_) + return RSVC_ERROR; + + rsvcDBT out; + + if (rsvcDatabase::convertData (&out, value) != RSVC_SUCCESS) + return RSVC_ERROR; + + DBT res, key; + memset (&res, 0, sizeof (res)); + memset (&key, 0, sizeof (key)); + + // get current data + err_ = (*dbc_->c_get)(dbc_, &key, &res, DB_CURRENT); + if (err_ != 0) + return RSVC_ERROR; + + if (out.size () > res.size) { + fprintf (stderr, "Overflow data buffer with cursor update\n"); + return RSVC_OVERFLOW; + } + + // clean out old data + memset (res.data, 0, res.size); + // copy new data in + memcpy (res.data, out.data (), out.size ()); + // use database routine to set data + err_ = (*dbc_->c_put)(dbc_, 0, &res, DB_CURRENT); + + if (err_ == 0) { + // success + return RSVC_SUCCESS; + } + else + return RSVC_ERROR; +} + +int +rsvcDatabase::cursorFirst (rsvcData& data, rsvcData& key) +{ + rsvcDatabaseLocker locker (this); + + if (err_ !=0 || !opened_ || !dbp_ || !dbc_) + return RSVC_ERROR; + + DBT tkey; memset (&tkey, 0, sizeof (tkey)); + DBT res; memset (&res, 0, sizeof (res)); + + err_ = (*dbc_->c_get)(dbc_, &tkey, &res, DB_FIRST); + + // success + if (err_ == 0) { + rsvcDatabase::copyKeyData (key, &tkey, keyType_); + return rsvcDatabase::convertData (data, &res); + } + else if (err_ != DB_NOTFOUND) { + // not found + return RSVC_NOTFOUND; + } + else + return RSVC_ERROR; +} + +int +rsvcDatabase::cursorLast (rsvcData& data, rsvcData& key) +{ + rsvcDatabaseLocker locker (this); + + if (err_ !=0 || !opened_ || !dbp_ || !dbc_) + return RSVC_ERROR; + + DBT tkey; memset (&tkey, 0, sizeof (tkey)); + DBT res; memset (&res, 0, sizeof (res)); + + err_ = (*dbc_->c_get)(dbc_, &tkey, &res, DB_LAST); + + // success + if (err_ == 0) { + rsvcDatabase::copyKeyData (key, &tkey, keyType_); + return rsvcDatabase::convertData (data, &res); + } + else if (err_ != DB_NOTFOUND) { + // not found + return RSVC_NOTFOUND; + } + else + return RSVC_ERROR; +} + +int +rsvcDatabase::cursorFinish (void) +{ + rsvcDatabaseLocker locker (this); + + if (err_ !=0 || !opened_ || !dbp_) + return RSVC_ERROR; + + if (!dbc_) + return RSVC_ERROR; + + (*dbc_->c_close)(dbc_); + dbc_ = 0; + return RSVC_SUCCESS; +} + +int +rsvcDatabase::put (rsvcData& value, rsvcData& key) +{ + rsvcDatabaseLocker locker (this); + + int status; + + if (err_ != 0 || !opened_ || dbp_ == 0) + return RSVC_INVALIDOP; + + if (wsize_ >= page_size_) { + (*dbp_->sync)(dbp_, 0); + wsize_ = 0; + } + + rsvcDBT out, tkey; + + if (rsvcDatabase::convertData (&out, &tkey, value, key, keyType_) + != RSVC_SUCCESS) + return RSVC_ERROR; + + wsize_ += out.size (); + + if ((status = (*dbp_->put)(dbp_, 0, tkey.dbt (), out.dbt (), 0)) == 0) + return RSVC_SUCCESS; + else + return RSVC_ERROR; +} + +int +rsvcDatabase::get (rsvcData& data, rsvcData& key) +{ + rsvcDatabaseLocker locker (this); + + if (err_ != 0 || !opened_ || dbp_ == 0) + return RSVC_INVALIDOP; + + rsvcDBT tkey; + DBT res; memset (&res, 0, sizeof (res)); + + if (rsvcDatabase::convertKey (&tkey, key, keyType_, keybuf_)!= RSVC_SUCCESS) + return RSVC_ERROR; + + int status; + + if ((status = (*dbp_->get)(dbp_, 0, tkey.dbt (), &res, 0)) == 0) // success + return rsvcDatabase::convertData (data, &res); + else if (status == DB_NOTFOUND) // not found + return RSVC_NOTFOUND; + else + return RSVC_ERROR; +} + +int +rsvcDatabase::del (rsvcData& key) +{ + rsvcDatabaseLocker locker (this); + + if (err_ != 0 || !opened_ || dbp_ == 0) + return RSVC_INVALIDOP; + + rsvcDBT tkey; + + if (rsvcDatabase::convertKey (&tkey, key, keyType_, keybuf_)!= RSVC_SUCCESS) + return RSVC_ERROR; + + int status; + + if ((status = (*dbp_->del)(dbp_, 0, tkey.dbt (), 0)) == 0) // success + return RSVC_SUCCESS; + else if (status == DB_NOTFOUND) // not found + return RSVC_NOTFOUND; + else + return RSVC_ERROR; +} + + +int +rsvcDatabase::convertData (rsvcDBT* out, rsvcDBT* key, + rsvcData & data, rsvcData& tkey, + int keyType) +{ + void *keydata = 0; + int status = RSVC_SUCCESS; + + // find out whether this key data has key tag in it + if ((status = tkey.find (rsvcServerConfig::key (), keydata)) + != RSVC_SUCCESS) + return status; + + char* buffer; + size_t len; + // figure out size of the key + len = rsvcDatabase::keySize (tkey, keydata, keyType); + if (len == 0) + return RSVC_ERROR; + + // allocate memory and copy data to the memory + buffer = new char[len]; + key->size (len); + key->data ((void *)buffer); + key->datacpy (keydata); + + // data is streamed buffer of incoming data + if ((status = data.streamOut (&buffer, &len)) == RSVC_SUCCESS) { + out->data ((void *)buffer); + out->size (len); + } + return status; +} + + +int +rsvcDatabase::convertData (rsvcDBT* out, rsvcData & data) +{ + int status = RSVC_SUCCESS; + + char* buffer; + size_t len; + if ((status = data.streamOut (&buffer, &len)) == RSVC_SUCCESS) { + out->data ((void *)buffer); + out->size (len); + } + return status; +} + +int +rsvcDatabase::convertData (rsvcData& data, const DBT* res) +{ + char* buffer = (char *)res->data; + int size = res->size; + + // note: data out of database in not aligned + char *nbuf = new char[size]; + memcpy (nbuf, buffer, size); + if (data.streamIn (nbuf, size) == RSVC_SUCCESS) { + delete []nbuf; + return RSVC_SUCCESS; + } + else { + delete []nbuf; + return RSVC_ERROR; + } +} + + +int +rsvcDatabase::convertKey (rsvcDBT* key, rsvcData& tkey, int keyType, + char* keybuf) +{ + void *keydata = 0; + int status = RSVC_SUCCESS; + + if ((status = tkey.find (rsvcServerConfig::key (), keydata)) != RSVC_SUCCESS) + return status; + + size_t len; + len = rsvcDatabase::keySize (tkey, keydata, keyType); + if (len == 0 || len > RSVC_MAX_KEY_LEN) + return RSVC_ERROR; + + key->data ((void *)keybuf, 0); + key->size (len); + key->datacpy (keydata); + + return RSVC_SUCCESS; +} + + +size_t +rsvcDatabase::keySize (rsvcData& key, void* data, int keyType) +{ + int status = RSVC_SUCCESS; + size_t ksize; + rsvcDataTypes keytype; + + if ((keytype = key.getType (rsvcServerConfig::key ())) != RSVC_INVALID && + keytype == keyType) { + switch (keytype) { + case RSVC_BYTE: + return sizeof ((char)1); + break; + case RSVC_INT16: + case RSVC_UINT16: + return sizeof ((short)1); + break; + case RSVC_INT32: + case RSVC_UINT32: + return sizeof ((int)1); + break; + case RSVC_FLOAT: + return sizeof ((float)1.0); + break; + case RSVC_DOUBLE: + return sizeof ((double)1.0); + break; + case RSVC_STRING: + { + char* str = (char *)data; + return (strlen (str) + 1); + } + break; + case RSVC_TIMESTAMP: + return sizeof (rsvc_TS_STAMP); + break; + default: + return 0; + } + } + return 0; +} + +int +rsvcDatabase::copyKeyData (rsvcData& key, DBT* data, int keyType) +{ + register size_t len; + register u_char *p1, *p2; + + /* + * XXX + * If a size_t doesn't fit in an int, this routine can lose. + * What we need is a integral type which is guaranteed to be + * larger than a size_t, and there is no such thing. + */ + switch (keyType) { + case RSVC_BYTE: + { + if (len = data->size != sizeof ((char)1)) + return RSVC_ERROR; + char c; + memcpy (&c, data->data, len); + return key.insert (rsvcServerConfig::key (), c); + } + break; + case RSVC_INT16: + { + if (len = data->size != sizeof ((short)1)) + return RSVC_ERROR; + short c; + memcpy (&c, data->data, len); + return key.insert (rsvcServerConfig::key (), c); + } + break; + case RSVC_UINT16: + { + if (len = data->size != sizeof ((unsigned short)1)) + return RSVC_ERROR; + unsigned short c; + memcpy (&c, data->data, len); + return key.insert (rsvcServerConfig::key (), c); + } + break; + case RSVC_INT32: + { + if (len = data->size != sizeof ((int)1)) + return RSVC_ERROR; + int c; + memcpy (&c, data->data, len); + return key.insert (rsvcServerConfig::key (), c); + } + break; + case RSVC_UINT32: + { + if (len = data->size != sizeof ((unsigned int)1)) + return RSVC_ERROR; + unsigned int c; + memcpy (&c, data->data, len); + return key.insert (rsvcServerConfig::key (), c); + } + break; + case RSVC_FLOAT: + { + if (len = data->size != sizeof ((float)1.0)) + return RSVC_ERROR; + float c; + memcpy (&c, data->data, len); + return key.insert (rsvcServerConfig::key (), c); + } + break; + case RSVC_DOUBLE: + { + if (len = data->size != sizeof ((double)1.0)) + return RSVC_ERROR; + double c; + memcpy (&c, data->data, len); + return key.insert (rsvcServerConfig::key (), c); + } + break; + case RSVC_STRING: + return key.insert (rsvcServerConfig::key (), (char *)data->data); + break; + case RSVC_TIMESTAMP: + { + if (len = data->size != sizeof (rsvc_TS_STAMP)) + return RSVC_ERROR; + rsvc_TS_STAMP ts; + memcpy (&ts, data->data, len); + return key.insert (rsvcServerConfig::key (), ts); + } + break; + default: + break; + } + return RSVC_ERROR; +} + +#if defined (_RSVC_USE_THREAD) && defined (_REENTRANT) + +rsvcDatabaseLocker::rsvcDatabaseLocker (rsvcDatabase* dbase) +:dbase_ (dbase) +{ + dbase_->mutex_.acquire (); +} + +rsvcDatabaseLocker::~rsvcDatabaseLocker (void) +{ + dbase_->mutex_.release (); +} +#else +rsvcDatabaseLocker::rsvcDatabaseLocker (rsvcDatabase* dbase) +:dbase_ (dbase) +{ + // empty +} + +rsvcDatabaseLocker::~rsvcDatabaseLocker (void) +{ + // empty +} +#endif + + + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDatabase.h b/extensions/cdevGenericServer/NameServer/src/rsvcDatabase.h new file mode 100755 index 0000000..6878891 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDatabase.h @@ -0,0 +1,205 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC database interface to db library (Thread Safe) +// +// Author: Jie Chen +// +// +// +// +#ifndef _RSVC_DATABASE_H +#define _RSVC_DATABASE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined (_RSVC_USE_THREAD) && defined (_REENTRANT) +#include +#endif + +// comparision function definition +typedef int (*rsvcCompFunc) (const DBT* key1, const DBT* key2); + +// this class will handle interface to btree based database implementation. +// data/key are rsvcData/undefined. When caller insert a rsvc, the +// rsvcData must have a key in this data with tag name 'key'. +// when caller tries to get rsvcData, caller has to specify the key +// which is in a rsvcData with tag name 'key' + +// This interface will not provide two iterators at the same time. +// This is the limitation by low level database library + +// All pointers to key must be the memory location provided by callers + +class rsvcDatabaseLocker; + +class rsvcDatabase : public rsvcVirtualDbase +{ +public: + // constructor + // default constructor, users have to call open explicitly + rsvcDatabase (void); + + // constructor: name is a file name, flags are the same flags as + // standard open routine. + // data_size is estimate of each data stored in the database + rsvcDatabase (char* name, int flags, int keyType = RSVC_STRING, + size_t data_size = 496, + size_t cache_size = 0, size_t page_size = 0, + int mode = 0666); + // destructor + ~rsvcDatabase (void); + + // operation + + // open a database + int open (char* name, int flags, int keyType = RSVC_STRING, + size_t cache_size = 0, + int mode = 0666); + // create a database + int create (char* name, int flags, int keyType = RSVC_STRING, + size_t data_size = 496, + size_t cache_size = 0, size_t page_size = 0, + int mode = 0666); + + // close connection to the database + int close (void); + + // get a rsvcData. + int get (rsvcData& data, rsvcData& key); + // insert a rsvcData which must have a key inside + int put (rsvcData& data, rsvcData& key); + // delete a data object pointed by key value + int del (rsvcData& key); + // flush all internal buffer to disk + int flush (void); + + // return database name + char* database (void) const; + // return file descriptor for the opened database + int fd (void); + // check to see the database is open or not + int opened (void) const; + + // iterator for sequential access to database + int cursorInit (void); + + // set cursor to the position pointed by key 'key', + // and return data 'data' if successful + int cursorSet (rsvcData& data, rsvcData& key); + + // move cursor to the next position. + // return CDEV_SUCCESS on success, CDEV_ERROR: check errno + // return CDEV_INVALIDOBJ: no more + int cursorNext (rsvcData& data, rsvcData& key); + + // move cursor to the previous position + // return CDEV_SUCCESS on success, CDEV_ERROR: check errno + // return CDEV_INVALIDOBJ: no more + int cursorPrev (rsvcData& data, rsvcData& key); + + // merge current value pointed by cursor: + // this routine can only used to update the data with the same + // or smaller size than the exisiting data + // If you like to update arbitrary size of data, use del and put + int cursorUpdate (rsvcData& data); + + // move cursor to the beginning of the database + // no need to provide key + int cursorFirst (rsvcData& data, rsvcData& key); + + // move cursor to the end of the database + // no need to provide key + int cursorLast (rsvcData& data, rsvcData& key); + + // close cursor operation + int cursorFinish (void); + + const char* className (void) const {return "rsvcDatabase";} + +protected: + // convert a DBT to rsvcData (database --> back to memory) + static int convertData (rsvcData& data, const DBT* res); + // convert rsvcData to rsvcDBT (memory --> to database ) + static int convertData (rsvcDBT* out, rsvcData& data); + + // convert rsvcData to DBT and a key (memory --> to database) + static int convertData (rsvcDBT* out, rsvcDBT* key, + rsvcData & data, rsvcData& tkey, int keyType); + // find key size + static size_t keySize (rsvcData& key, void* tkey, int keyType); + + // convert key from regular rsvcData to DBT format + // using convertion buffer keybuf + // used when convert memory -->to database + static int convertKey (rsvcDBT* key, rsvcData& tkey, int keyType, + char* keybuf); + + // copy key data from database back to memory + static int copyKeyData (rsvcData& key, DBT* data, int keyType); + +private: +#if defined (_RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex mutex_; +#endif + + // database access option: different site can change option + DB_INFO b_; + // internal DB pointer + DB* dbp_; + + // Database cursor pointer + DBC* dbc_; + + // keep track of size of data that have been written to a database + int wsize_; + + // static buffer for key + char keybuf_[RSVC_MAX_KEY_LEN]; + + // Function pointers to all comparision functions + static rsvcCompFunc compFuncs_[]; + + // deny access to copy and assignment operator + rsvcDatabase (const rsvcDatabase& dbase); + rsvcDatabase& operator = (const rsvcDatabase& dbase); + + // friend class + friend class rsvcDatabaseLocker; +}; + +class rsvcDatabaseLocker +{ +public: + // constructor and destructor + rsvcDatabaseLocker (rsvcDatabase* dbase); + ~rsvcDatabaseLocker (void); + +private: + rsvcDatabase* dbase_; + // deny access to assignment and copy operations + rsvcDatabaseLocker (const rsvcDatabaseLocker& ); + rsvcDatabaseLocker& operator = (const rsvcDatabaseLocker& ); +}; + +#endif + + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDatabaseEnv.cc b/extensions/cdevGenericServer/NameServer/src/rsvcDatabaseEnv.cc new file mode 100755 index 0000000..cac70f3 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDatabaseEnv.cc @@ -0,0 +1,75 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of database environment +// +// Author: Jie Chen +// +// Revision History: +// rsvcDatabaseEnv.cc,v +// Revision 1.1 1998/01/22 17:08:10 akers +// Addition of new NameServer +// +// +// +#include "rsvcDatabaseEnv.h" +#include "rsvcServerConfig.h" + +rsvcDatabaseEnv* rsvcDatabaseEnv::env_ = 0; + +rsvcDatabaseEnv::rsvcDatabaseEnv (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcDatabaseEnv Class Object\n"); +#endif + dbenv_ = new DB_ENV (); + if (dbenv_ == 0) { + fprintf (stderr, "Cannot allocate memory for DB_ENV structure\n"); + exit (1); + } + dbenv_->db_errfile = stderr; + dbenv_->db_errpfx = "rsvcDatabase"; + if (db_appinit (rsvcServerConfig::dbaseHome (), 0, dbenv_, DB_CREATE) != 0){ + fprintf (stderr, "dp_appinit failed \n"); + exit (1); + } +} + +rsvcDatabaseEnv::~rsvcDatabaseEnv (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcDatabaseEnv Class Object\n"); +#endif + db_appexit (dbenv_); + delete dbenv_; +} + +rsvcDatabaseEnv * +rsvcDatabaseEnv::dbaseEnv (void) +{ + if (rsvcDatabaseEnv::env_ == 0) + rsvcDatabaseEnv::env_ = new rsvcDatabaseEnv (); + return rsvcDatabaseEnv::env_; +} + +DB_ENV * +rsvcDatabaseEnv::dbenv (void) const +{ + return dbenv_; +} + +void +rsvcDatabaseEnv::close (void) +{ + if (rsvcDatabaseEnv::env_) + delete rsvcDatabaseEnv::env_; +} + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcDatabaseEnv.h b/extensions/cdevGenericServer/NameServer/src/rsvcDatabaseEnv.h new file mode 100755 index 0000000..1d082ef --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcDatabaseEnv.h @@ -0,0 +1,49 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Database Environment Class +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_DATABASE_ENV_H +#define _RSVC_DATABASE_ENV_H + +#include +#include +#include +#include + +class rsvcDatabaseEnv +{ +public: + // destructor + ~rsvcDatabaseEnv (void); + + // static access to pointer of this object + static rsvcDatabaseEnv* dbaseEnv (void); + + DB_ENV* dbenv (void) const; + + // close all database actions, This is last one to call + static void close (void); + +protected: + // constructor + rsvcDatabaseEnv (void); + +private: + // single database environment + static rsvcDatabaseEnv* env_; + // real database stuff + DB_ENV* dbenv_; +}; +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcErr.h b/extensions/cdevGenericServer/NameServer/src/rsvcErr.h new file mode 100755 index 0000000..7f7e1b3 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcErr.h @@ -0,0 +1,78 @@ +/* +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC error codes +// +// Author: Jie Chen +// +// +// +*/ +#ifndef _RSVC_ERROR_CODE_H +#define _RSVC_ERROR_CODE_H + +/* Error and status values */ +#define RSVC_WARNING -2 /* Failure of function is non-consequential */ +#define RSVC_ERROR -1 /* Errors that are not in any categories */ +#define RSVC_SUCCESS 0 /* RSVC success */ +#define RSVC_INVALIDOBJ 1 /* invalid RSVC objects */ +#define RSVC_INVALIDARG 2 /* invalid argument passed to RSVC calls */ +#define RSVC_INVALIDSVC 3 /* wrong service during dynamic loading */ +#define RSVC_INVALIDOP 4 /* operation is unsupported (collection) */ + +#define RSVC_NOTCONNECTED 5 /* not connected to low network service */ +#define RSVC_IOFAILED 6 /* low level network service IO failed */ +#define RSVC_CONFLICT 7 /* conflicts of data types or tags */ +#define RSVC_NOTFOUND 8 /* RSVC cannot find user request (RSVCData) */ + +#define RSVC_TIMEOUT 9 /* time out */ +#define RSVC_CONVERT 10 /* RSVCData conversion error */ +#define RSVC_OUTOFRANGE 11 /* value out of range for device attribute */ +#define RSVC_NOACCESS 12 /* insufficient access to perform request */ +#define RSVC_ACCESSCHANGED 13 /* change in access permission of device */ + +#define RSVC_DISCONNECTED 60 /* channel has been disconnected */ +#define RSVC_RECONNECTED 61 /* channel has been reconnected */ +#define RSVC_OVERFLOW 62 /* overflow existing data buffer */ + +#define RSVC_DELETE_CALLBACK 70 /* the callback object will be deleted */ + +#define RSVC_NOKEY 80 /* data has no key in the data */ +#define RSVC_CONN_TIMEOUT 82 /* connection timeout */ +#define RSVC_FILTERED 83 /* messages have been filtered */ +#define RSVC_NOFILTERING 84 /* no filtering applied */ +#define RSVC_DROPPED 85 /* message is dropped */ +#define RSVC_BADIO 86 /* TCP io is bad file descriptor */ +#define RSVC_INCOMPLETE 88 /* data flow will coming (unfinished) */ +#define RSVC_CBK_FINISHED 89 /* callback finished (monitor off) */ +#define RSVC_PAUSED 90 /* query callback is paused */ +#define RSVC_QUERYMSG_ERR 91 /* query message syntax error */ + +/* Request object state values */ +#define RSVC_STATE_CONNECTED 0 /* request object is connected to device */ +#define RSVC_STATE_NOTCONNECTED 1 /* request object is not connected */ +#define RSVC_STATE_INVALID 2 /* request object is invalid */ + +/* Request object access values */ +#define RSVC_ACCESS_NONE 0 /* no access to specified attribute */ +#define RSVC_ACCESS_READONLY 1 /* read-only access to attribute */ +#define RSVC_ACCESS_WRITE 2 /* read-write access to attribute */ + +/* RSVCError class severity codes */ +#define RSVC_SEVERITY_INFO 0 /* informative message */ +#define RSVC_SEVERITY_WARN 1 /* warning message */ +#define RSVC_SEVERITY_ERROR 2 /* error message */ +#define RSVC_SEVERITY_SEVERE 3 /* severe or fatal error message */ + +#define RSVC_IOERROR RSVC_IOFAILED + + +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcHSlist.cc b/extensions/cdevGenericServer/NameServer/src/rsvcHSlist.cc new file mode 100755 index 0000000..d5856c1 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcHSlist.cc @@ -0,0 +1,762 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Single Linked List for rsvcHashable* pointer +// +// Note: remove and clean operations on the list +// will only remove link nodes without removal of +// the content inside the nodes. It is callers' +// responsiblity to clean up those contents +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// Revision History: +// rsvcHSlist.cc,v +// Revision 1.1 1998/01/22 17:08:12 akers +// Addition of new NameServer +// +// +// +#include +#include "rsvcHSlist.h" + +//====================================================================== +// class rsvcHSlist implementation +//====================================================================== +rsvcHSlist::rsvcHSlist (void) +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +:ptrToFirstLink(0), count_ (0), lock_ () +#else +:ptrToFirstLink(0), count_ (0) +#endif +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcHSlist Class Object\n"); +#endif + // no further initialization +} + +rsvcHSlist::rsvcHSlist (const rsvcHSlist & source) +:count_ (source.count_) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcHSlist Class Object\n"); +#endif + + // duplicate elements from source list + if (source.isEmpty_i()) + ptrToFirstLink = 0; + else{ + rsvcHSlistLink * firstLink = source.ptrToFirstLink; + ptrToFirstLink = firstLink->duplicate(); + } +} + +rsvcHSlist::~rsvcHSlist (void) +{ + // empty all elements from the list +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcHSlist Class Object\n"); +#endif + deleteAllValues(); +} + +void +rsvcHSlist::add (rsvcHashable* val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // add a new value to the front of a linked list + ptrToFirstLink = new rsvcHSlistLink(val, ptrToFirstLink); + count_ ++; + assert(ptrToFirstLink != 0); +} + +void +rsvcHSlist::addToEnd (rsvcHashable* val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + count_ ++; + if (ptrToFirstLink == 0) { + ptrToFirstLink = new rsvcHSlistLink(val, ptrToFirstLink); + return; + } + + // loop through until last element + rsvcHSlistLink *p = 0; + for (p = ptrToFirstLink; p->ptrToNextLink; p = p->ptrToNextLink) + ; + + rsvcHSlistLink* q = new rsvcHSlistLink (val, 0); + p->ptrToNextLink = q; +} + +void +rsvcHSlist::add_i (rsvcHashable* val) +{ + // add a new value to the front of a linked list + count_ ++; + ptrToFirstLink = new rsvcHSlistLink(val, ptrToFirstLink); + assert(ptrToFirstLink != 0); +} + +int +rsvcHSlist::remove (rsvcHashable* val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // remove an element from the list + // loop to test each element + rsvcHSlistLink *q = ptrToFirstLink; + for (rsvcHSlistLink * p = ptrToFirstLink; p; p = p->ptrToNextLink){ + if (val == p->value){ + if (q == p){ + // remove first element + ptrToFirstLink = p->ptrToNextLink; + delete p; + } + else{ + q->ptrToNextLink = p->ptrToNextLink; + delete p; + } + count_ --; + return 1; + } + q = p; + } + // not found + return 0; +} + +void +rsvcHSlist::deleteAllValues (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // clear all items from the list + rsvcHSlistLink * next; + + for (rsvcHSlistLink * p = ptrToFirstLink; p != 0; p = next){ + // delete the element pointed to by p + next = p->ptrToNextLink; + p->ptrToNextLink = 0; + delete p; + } + + // set count to zero + count_ = 0; + // mark that the list contains no elements + ptrToFirstLink = 0; +} + +void +rsvcHSlist::deleteAllValues_i (void) +{ + // clear all items from the list + rsvcHSlistLink * next; + + for (rsvcHSlistLink * p = ptrToFirstLink; p != 0; p = next){ + // delete the element pointed to by p + next = p->ptrToNextLink; + p->ptrToNextLink = 0; + delete p; + } + + // set count to zero + count_ = 0; + + // mark that the list contains no elements + ptrToFirstLink = 0; +} + +int +rsvcHSlist::count (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + return count_; +} + +rsvcHSlist* +rsvcHSlist::duplicate (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + rsvcHSlist * newlist = new rsvcHSlist; + assert(newlist != 0); + + // copy list + if (ptrToFirstLink) + newlist->ptrToFirstLink = ptrToFirstLink->duplicate(); + + // set new list count + newlist->count_ = count_; + // return the new list + return newlist; +} + +rsvcHashable* +rsvcHSlist::firstElement (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // return first value in list + assert(ptrToFirstLink != 0); + return ptrToFirstLink->value; +} + +rsvcHashable* +rsvcHSlist::firstElement_i (void) +{ + // return first value in list + assert(ptrToFirstLink != 0); + return ptrToFirstLink->value; +} + +rsvcHashable* +rsvcHSlist::lastElement (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + assert(ptrToFirstLink != 0); + // loop through until last element + rsvcHSlistLink *p = 0; + for (p = ptrToFirstLink; p->ptrToNextLink; p = p->ptrToNextLink) + ; + return p->value; +} + +rsvcHashable* +rsvcHSlist::lastElement_i (void) +{ + assert(ptrToFirstLink != 0); + // loop through until last element + rsvcHSlistLink *p = 0; + for (p = ptrToFirstLink; p->ptrToNextLink; p = p->ptrToNextLink) + ; + return p->value; +} + +int +rsvcHSlist::includes(rsvcHashable* v) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // loop to test each element + for (rsvcHSlistLink * p = ptrToFirstLink; p; p = p->ptrToNextLink) + if (v == p->value) + return 1; + + // not found + return 0; +} + +int +rsvcHSlist::isEmpty (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // test to see if the list is empty + // list is empty if the pointer to the first link is null + return ptrToFirstLink == 0; +} + +int +rsvcHSlist::isEmpty_i (void) const +{ + // test to see if the list is empty + // list is empty if the pointer to the first link is null + return ptrToFirstLink == 0; +} + +void +rsvcHSlist::removeFirst (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // make sure there is a first element + assert(ptrToFirstLink != 0); + + // save pointer to the removed node + rsvcHSlistLink * p = ptrToFirstLink; + + // reassign the ptrToFirstLink node + ptrToFirstLink = p->ptrToNextLink; + + // decrease the count + count_ --; + // recover memory used by the first element + delete p; +} + +void +rsvcHSlist::removeFirst_i (void) +{ + // make sure there is a first element + assert(ptrToFirstLink != 0); + + // save pointer to the removed node + rsvcHSlistLink * p = ptrToFirstLink; + + // reassign the ptrToFirstLink node + ptrToFirstLink = p->ptrToNextLink; + + // decrease the count + count_ --; + + // recover memory used by the first element + delete p; +} + +//====================================================================== +// class slink implementation +// No need to add any mutex protection since all member +// functions are called with lock held +//====================================================================== +rsvcHSlistLink* +rsvcHSlistLink::insert(rsvcHashable* val) +{ + // insert a new link after current node + ptrToNextLink = new rsvcHSlistLink(val, ptrToNextLink); + + // check that allocation was successful + assert(ptrToNextLink != 0); + return ptrToNextLink; +} + +rsvcHSlistLink::rsvcHSlistLink (rsvcHashable* val, rsvcHSlistLink * nxt) +:value(val), ptrToNextLink(nxt) +{ + // create and initialize a new link field +} + +rsvcHSlistLink* +rsvcHSlistLink::duplicate (void) +{ + rsvcHSlistLink * newlink; + + // if there is a next field. copy remainder of list + if (ptrToNextLink != 0) + newlink = new rsvcHSlistLink(value, ptrToNextLink->duplicate()); + else + newlink = new rsvcHSlistLink (value, 0); + + // check that allocation was successful + assert(newlink != 0); + return newlink; +} + +rsvcHSlistLink* +rsvcHSlistLink::next (void) +{ + return ptrToNextLink; +} + +rsvcHashable* +rsvcHSlistLink::data (void) +{ + return value; +} + +//====================================================================== +// class listIterator implementation +//====================================================================== +rsvcHSlistIterator::rsvcHSlistIterator(rsvcHSlist & aList) +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +:theList(aList), lock_ () +#else +:theList(aList) +#endif +{ + // create and initialize a new list + init_i(); +} + +int +rsvcHSlistIterator::init_i() +{ + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +int +rsvcHSlistIterator::init() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +rsvcHashable* +rsvcHSlistIterator::operator () (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + // return value of current element + // check to see if there is a current element + assert(currentLink != 0); + + // return value associated with current element + return currentLink->value; +} + +int rsvcHSlistIterator::operator ! (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + // test for termination of the iterator + // if current link references a removed value, + // update current to point to next position + if (currentLink == 0) + if (previousLink != 0) + currentLink = previousLink->ptrToNextLink; + + // now see if currentLink is valid + return currentLink != 0; +} + +int rsvcHSlistIterator::forward_i (void) +{ + // move current pointer to nect element + // special processing if current link is deleted + if (currentLink == 0){ + if (previousLink == 0) + currentLink = theList.ptrToFirstLink; + else + currentLink = previousLink->ptrToNextLink; + } + else{ + // advance pointer + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + + +int rsvcHSlistIterator::operator ++() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // move current pointer to nect element + // special processing if current link is deleted + if (currentLink == 0){ + if (previousLink == 0) + currentLink = theList.ptrToFirstLink; + else + currentLink = previousLink->ptrToNextLink; + } + else{ + // advance pointer + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +void rsvcHSlistIterator::operator = (rsvcHashable* val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // modify value of current element + assert(currentLink != 0); + + // modify value of the current link + currentLink->value = val; +} + +void rsvcHSlistIterator::removeCurrent_i (void) +{ + // remove the current element from a list + // make sure there is a current element + assert(currentLink != 0); + + // case 1, removing first element + if (previousLink == 0) + theList.ptrToFirstLink = currentLink->ptrToNextLink; + + // case 2, not removing the first element + else + previousLink->ptrToNextLink = currentLink->ptrToNextLink; + + // delete current node + delete currentLink; + + // and set current pointer to null + currentLink = 0; + + // decrease list count element + theList.count_ --; +} + +void rsvcHSlistIterator::removeCurrent (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // remove the current element from a list + // make sure there is a current element + assert(currentLink != 0); + + // case 1, removing first element + if (previousLink == 0) + theList.ptrToFirstLink = currentLink->ptrToNextLink; + + // case 2, not removing the first element + else + previousLink->ptrToNextLink = currentLink->ptrToNextLink; + + // delete current node + delete currentLink; + + // and set current pointer to null + currentLink = 0; + + // decrease list count element + theList.count_ --; +} + +void rsvcHSlistIterator::addBefore(rsvcHashable* val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // add a new element to list before current value + // case 1, not at start + if (previousLink) + previousLink = previousLink->insert(val); + + // case 2, at start of list + else{ + theList.rsvcHSlist::add(val); + previousLink = theList.ptrToFirstLink; + currentLink = previousLink->ptrToNextLink; + } + + // increase the count + theList.count_ ++; +} + +void rsvcHSlistIterator::addAfter(rsvcHashable* val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // a a new element to list after current value + // case 1, not at start + if (currentLink != 0) + currentLink->insert(val); + + // case 2, at end of list + else if (previousLink != 0) + currentLink = previousLink->insert(val); + + // case 3, start of list + else + theList.rsvcHSlist::add(val); + + // increase the count + theList.count_ ++; +} + +int rsvcHSlistIterator::searchSame(rsvcHashable* &val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // search the list to find out whether we have this element + // if we do, move cursor to this element return 1 + // if we don't return 0 + init_i(); + + if (currentLink == 0){ + // empty link + return 0; + } + while (currentLink != 0){ + // advance pointer + if (currentLink->value == val) + break; + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +//======================================================================== +// Implementation of rsvcHSlistCursor +// Implements of cursor without changing list +//======================================================================== +rsvcHSlistCursor::rsvcHSlistCursor(const rsvcHSlist & aList) +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +:theList(aList), lock_ () +#else +:theList(aList) +#endif +{ + // create and initialize a new list + init_i(); +} + +int +rsvcHSlistCursor::init_i() +{ + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +int +rsvcHSlistCursor::init() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +rsvcHashable* +rsvcHSlistCursor::operator () (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // return value of current element + // check to see if there is a current element + assert(currentLink != 0); + + // return value associated with current element + return currentLink->value; +} + +int rsvcHSlistCursor::operator ! (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // test for termination of the iterator + // if current link references a removed value, + // update current to point to next position + if (currentLink == 0) + if (previousLink != 0) + currentLink = previousLink->ptrToNextLink; + + // now see if currentLink is valid + return currentLink != 0; +} + +int rsvcHSlistCursor::operator ++ (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // move current pointer to nect element + // special processing if current link is deleted + if (currentLink == 0){ + if (previousLink == 0) + currentLink = theList.ptrToFirstLink; + else + currentLink = previousLink->ptrToNextLink; + } + else{ + // advance pointer + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +int rsvcHSlistCursor::searchSame (rsvcHashable* &val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + // search the list to find out whether we have this element + // if we do, move cursor to this element return 1 + // if we don't return 0 + init_i(); + + if (currentLink == 0){ + // empty link + return 0; + } + while (currentLink != 0){ + // advance pointer + if (currentLink->value == val) + break; + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +void rsvcHSlistCursor::operator = (rsvcHashable* ) +{ + // empty +} diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcHSlist.h b/extensions/cdevGenericServer/NameServer/src/rsvcHSlist.h new file mode 100755 index 0000000..07a95bf --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcHSlist.h @@ -0,0 +1,256 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Single Linked List for pointers rsvcHashable pointer +// Primary used inside rsvcHash +// +// Note: remove and clean operations on the list +// will only remove link nodes without removal of +// the content inside the nodes. It is callers' +// responsiblity to clean up those contents +// +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// +// +// +#ifndef _RSVC_HSLIST_H +#define _RSVC_HSLIST_H + +#include +#include + +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +#include +#endif + +#include +#include +#include +#include + + +//====================================================================== +// class rsvcSlist +// Single Linked List for void* pointer +//====================================================================== +class rsvcHSlistLink; +class rsvcHSlistIterator; +class rsvcHSlistCursor; +class rsvcHash; +class rsvcHashable; + +class rsvcHSlist +{ +public: + // constructors + rsvcHSlist (void); + rsvcHSlist (const rsvcHSlist & source); + virtual ~rsvcHSlist (void); + + // operations + + // add list item to the beginning of the list + virtual void add (rsvcHashable* value); + // add item to the end of list + virtual void addToEnd (rsvcHashable* value); + + // remove a list item from the list + // return 0: nothing to remove + // return 1: remove success + virtual int remove (rsvcHashable* value); + + // clean up the list. + virtual void deleteAllValues (void); + + // return first element of the list + virtual rsvcHashable* firstElement (void); + + // return last element of the list + virtual rsvcHashable* lastElement (void); + + // duplicate ths whole list + virtual rsvcHSlist* duplicate (void); + + // check whether this list contains a particular item + // return 1: yes. return 0: no + virtual int includes (rsvcHashable* value); + + // Is list empty + // return 1: yes. return 0: no + virtual int isEmpty (void); + + // remove first element of the list + virtual void removeFirst (void); + + // return number of elements inside the list + virtual int count (void); + +protected: + // data field + rsvcHSlistLink* ptrToFirstLink; + + // number elements in the list + int count_; + +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif + + // some internal functions which must be called with lock held + virtual void add_i (rsvcHashable* value); + virtual int isEmpty_i (void) const; + virtual void deleteAllValues_i (void); + virtual void removeFirst_i (void); + virtual rsvcHashable* firstElement_i (void); + virtual rsvcHashable* lastElement_i (void); + + // friends + friend class rsvcHSlistIterator; + // cannot modify list in anyways + friend class rsvcHSlistCursor; + friend class rsvcHash; + +private: + // deny access to assignment operation + rsvcHSlist& operator = (const rsvcHSlist& list); +}; + +//====================================================================== +// class rsvcHSlistLink +// Single linked list link node +//====================================================================== +class rsvcHSlistLink +{ +public: + // constructor + rsvcHSlistLink (rsvcHashable* linkValue, rsvcHSlistLink * nextPtr); + + // insert a new element following the current value + rsvcHSlistLink* insert (rsvcHashable* val); + // return data value + rsvcHashable* data (void); + + // return next data item + rsvcHSlistLink* next (void); + + +private: + + // duplicate + rsvcHSlistLink* duplicate (void); + + // data areas + rsvcHashable* value; + rsvcHSlistLink* ptrToNextLink; + + // friends + friend class rsvcHSlist; + friend class rsvcHSlistIterator; + friend class rsvcHSlistCursor; +}; + +//=================================================================== +// class rsvcHSlistIterator +// implements iterator protocol for linked lists +// also permits removal and addition of elements +//=================================================================== + +class rsvcHashIterator; + +class rsvcHSlistIterator +{ +public: + // constructor + rsvcHSlistIterator (rsvcHSlist& aList); + + // iterator protocol + virtual int init (void); + virtual rsvcHashable* operator () (void); + virtual int operator ! (void); + virtual int operator ++ (void); + virtual void operator = (rsvcHashable* value); + + // new methods specific to list iterators + + // remove current item pointed by the iterator from the list + void removeCurrent(void); + + // add an item to the list before the position pointed by the iterator + void addBefore(rsvcHashable* newValue); + + // add an item to the list after the position pointed by the iterator + void addAfter(rsvcHashable* newValue); + + // search an item and move the iterator to that position + int searchSame(rsvcHashable* &value); + +protected: + // some internal functions which must be called with lock held + virtual int init_i (void); + // move cursor forward + virtual int forward_i (void); + // internal remove current + void removeCurrent_i (void); + // data areas + rsvcHSlistLink * currentLink; + rsvcHSlistLink * previousLink; + rsvcHSlist& theList; +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif + +private: + // friend class + friend class rsvcHashIterator; + + // deny access of copy and assignment + rsvcHSlistIterator (const rsvcHSlistIterator& ir); + rsvcHSlistIterator& operator = (const rsvcHSlistIterator& ir); +}; + +//=================================================================== +// class rsvcHSlistCursor +// implements cursor protocol for linked lists +//=================================================================== +class rsvcHSlistCursor +{ +public: + // constructor + rsvcHSlistCursor (const rsvcHSlist& aList); + + // iterator protocol + virtual int init (void); + virtual rsvcHashable* operator () (void); + virtual int operator ! (void); + virtual int operator ++ (void); + virtual void operator = (rsvcHashable* value); + + int searchSame (rsvcHashable* &value); + +protected: + // internal functions which must be called with lock + virtual int init_i (void); + // data areas + rsvcHSlistLink * currentLink; + rsvcHSlistLink * previousLink; + const rsvcHSlist& theList; +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif + +private: + // deny access to copy and assignment operations + rsvcHSlistCursor (const rsvcHSlistCursor &); + rsvcHSlistCursor& operator = (const rsvcHSlistCursor &); +}; +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcHash.cc b/extensions/cdevGenericServer/NameServer/src/rsvcHash.cc new file mode 100755 index 0000000..a4bfcb5 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcHash.cc @@ -0,0 +1,351 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606 +// Email: coda@cebaf.gov Tel: (804) 249-7101 Fax: (804) 249-7363 +//----------------------------------------------------------------------------- +// +// Description: +// rsvcHash: rsvc hash table keyed by a variable length string +// Open Hash with buckets implemented by single linked lists +// +// Note: void *s are stored inside the table. This class +// will not manage these pointers. Callers have to +// manage these pointers +// +// Note: this is unsafe C++ practice. Use at your own risk +// +// Reason: It is so difficult to use a template class inside +// a shared library. (Cfront based C++ compiler cannot +// instantiate a template class during compilation time +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// Revision History: +// rsvcHash.cc,v +// Revision 1.3 1998/02/26 19:10:24 chen +// provide direct access to array of linked list +// +// Revision 1.2 1998/02/20 19:29:54 chen +// Remove debug print +// +// Revision 1.1 1998/01/22 17:08:13 akers +// Addition of new NameServer +// +// +// +#include +#include +#include +#include +#include +#include "rsvcHash.h" + +// the following are 10 prime numbers. Each is twice of value of the +// one in front of it. + +static unsigned int rsvc_prime_table[] = +{11, 97, 199, 499, 997, 1999, 4999, 9973, 25013, 49999, 99991}; + +static unsigned int rsvc_prime_table_size = 11; + +static unsigned int +rsvc_pick_prime (unsigned max, int* index) +{ + unsigned int diff = 12345678; + unsigned int tmp; + + for (int i = 0; i < rsvc_prime_table_size; i++) { + tmp = abs ((int)((int)max - (int)rsvc_prime_table[i])); + if (tmp < diff) { + diff = tmp; + *index = i; + } + } + return rsvc_prime_table[*index]; +} + +// a simple string hash function +unsigned int rsvcHashFunc (const char *src) +{ + unsigned int hash = 0, g; + + for (int i = 0; src[i] != '\0'; i++){ + hash = (hash << 4) + src[i]; + // assume 32 bit integer + if (g = hash & 0xf0000000){ + hash ^= g >> 24; + hash ^= g; + } + } + return hash; +} + + +//====================================================================== +// class rsvcHash implementation +//====================================================================== + +// lock_ has default constructor, so compiler will do it for us + +rsvcHash::rsvcHash (unsigned int max, unsigned int loadfactor) +:lf (loadfactor) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcHash Class Objects\n"); +#endif + + // figure out nearest prime number for max + tablesize = rsvc_pick_prime (max, &primeindex); +#ifdef _RSVC_DEBUG + /*printf ("table size for str hash is %d, index is %d\n", tablesize, + primeindex);*/ +#endif + // rsvcSlist has a default constructor, so one can create an array of the list + buckets = new rsvcHSlist[tablesize]; + assert (buckets); +} + +rsvcHash::~rsvcHash (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcHash Class Objects\n"); +#endif + delete []buckets; + buckets = 0; +} + +void +rsvcHash::rehash (void) +{ + if (primeindex == rsvc_prime_table_size - 1) { + fprintf (stderr, "Cannot exapnd the hash table size %d anymore\n", + rsvc_prime_table[primeindex]); + return; + } + // remember old values + unsigned int oldtablesize = tablesize; + rsvcHSlist* oldbuckets = buckets; + + // create new values + tablesize = rsvc_prime_table[primeindex + 1]; + buckets = new rsvcHSlist[tablesize]; + assert (buckets); + +#ifdef _RSVC_DEBUG + /* fprintf (stderr, "Expand hash table from %d to %d (reaching lf %d) \n", + oldtablesize, tablesize, lf);*/ +#endif + primeindex ++; + + rsvcHashable* elem = 0; + for (int i = 0; i < oldtablesize; i++) { + rsvcHSlistIterator site (oldbuckets[i]); + for (site.init (); !site; ++site) { + elem = site (); + add (elem); + } + } + + // remove old memory + delete []oldbuckets; +} + + + +int +rsvcHash::isEmpty() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + // if any table is non-empty, return 0 + for (int i = 0; i < tablesize; i++) + if (!buckets[i].isEmpty_i()) + return 0; + + // all empty + return 1; +} + +void +rsvcHash::deleteAllValues() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + // delete all values from a hash table + // clear the elements from each of teh buckets + for (int i = 0; i < tablesize; i++) + buckets[i].deleteAllValues_i(); +} + +unsigned int +rsvcHash::hash(rsvcHashable* ele) const +{ + // return hashed value of key + return (ele->hash () % tablesize); +} + +void +rsvcHash::add (rsvcHashable* newele) +{ + buckets[hash (newele)].add (newele); + if (buckets[hash (newele)].count () > lf) { +#ifdef _RSVC_DEBUG +/* fprintf (stderr, "Hash buckets %d has %d elements > load factor %d, resize\n", + hash (newele), buckets[hash (newele)].count (), lf);*/ +#endif + rehash (); + } +} + +rsvcHSlist& +rsvcHash::bucketRef (rsvcHashable* ele) +{ + return (buckets[hash (ele)]); +} + +rsvcHSlist& +rsvcHash::bucketRef (unsigned int hashcode) +{ + return (buckets[hashcode % tablesize]); +} + +void +rsvcHash::bucketList (rsvcHSlist* &lists, unsigned int& size) +{ + lists = buckets; + size = tablesize; +} + + +void +rsvcHash::asciiDump (FILE* fd) +{ + fprintf (fd, "Hash table looks like the following\n"); + fprintf (fd, "====================================================\n"); + + for (int i = 0; i < tablesize; i++) + fprintf (fd, "Bucket[%d] contains %d elements\n", i, buckets[i].count ()); + fprintf (fd, "====================================================\n"); +} + + +//====================================================================== +// class rsvcHashIterator implementation +//====================================================================== +rsvcHashIterator::rsvcHashIterator (rsvcHash& v) +:base(v), currentIndex(0), itr(0) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcHashIterator Class Object \n"); +#endif + // no further initialization +} + +rsvcHashIterator::~rsvcHashIterator (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcHashIterator Class Object \n"); +#endif + currentIndex = 0; + if (itr) + delete itr; +} + +int +rsvcHashIterator::init (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // initialize iterator, + // start search with first bucket + currentIndex = 0; + itr = 0; + return getNextIterator(); +} + +rsvcHashable * +rsvcHashIterator::operator() (void) +{ + // return current element + return (*itr)(); +} + +int +rsvcHashIterator::operator ! (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // test if there is a current element + return itr != 0; +} + +int +rsvcHashIterator::operator ++ (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // see if current iterator can be advanced + if (itr && itr->forward_i ()) + return 1; + + // if not, get next iterator + currentIndex++; + return getNextIterator(); +} + +void +rsvcHashIterator::operator = (rsvcHashable* val) +{ + // change the current value + (*itr) = val; +} + +void +rsvcHashIterator::removeCurrent (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + if (itr) + itr->removeCurrent_i (); +} + +int +rsvcHashIterator::getNextIterator (void) +{ + // if there is an old iterator, delete it + if (itr != 0) + delete itr; + + // now search for a new one + for (; currentIndex < base.tablesize; currentIndex++){ + // generate a new iterator at the current point + itr = new rsvcHSlistIterator (base.buckets[currentIndex]); + assert(itr != 0); + + // if it has at least one element, we're done + if (itr->init_i()) + return 1; + + // otherwise delete it, try again + delete itr; + } + // all out of iterators, can quit + itr = 0; + return 0; +} diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcHash.h b/extensions/cdevGenericServer/NameServer/src/rsvcHash.h new file mode 100755 index 0000000..def1821 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcHash.h @@ -0,0 +1,144 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606 +// Email: coda@cebaf.gov Tel: (804) 249-7101 Fax: (804) 249-7363 +//----------------------------------------------------------------------------- +// +// Description: +// rsvcStrHash: rsvc hash table keyed by a variable length string +// Open Hash with buckets implemented by single linked lists +// +// Note: void *s are stored inside the table. This class +// will not manage these pointers. Callers have to +// manage these pointers +// +// Note: this is unsafe C++ practice. Use at your own risk +// +// Reason: It is so difficult to use a template class inside +// a shared library. (Cfront based C++ compiler cannot +// instantiate a template class during compilation time +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// +// +// +#ifndef _RSVC_HASH_H +#define _RSVC_HASH_H + +#include +#include +#include +#include + + +//====================================================================== +// class rsvcHash +// collection of buckets indexed by hashed values +//====================================================================== +class rsvcHashIterator; + +class rsvcHash +{ +public: + // constructor + + // construct a hash table with estimate max entry and load fator + rsvcHash (unsigned int estimatemax, unsigned int lf = 5); + + // destructor + virtual ~rsvcHash (void); + + // operations + + // is the table empty: return 1: yes. return 0: no + virtual int isEmpty(); + + // clear the elements of the set + virtual void deleteAllValues(); + + // add an element to the collection + virtual void add (rsvcHashable* ele); + + // dump all hash distribution + void asciiDump (FILE* fd = stdout); + + // return a reference to a particular bucket according to the key + rsvcHSlist& bucketRef (rsvcHashable* ele); + + // return a reference to a particular bucket according to a hash value + rsvcHSlist& bucketRef (unsigned int hashcode); + + // return a pointer to an array of linked list + void bucketList (rsvcHSlist* &list, unsigned int& size); + +protected: + friend class rsvcHashIterator; + + // the actual table itself is a vector of buckets + unsigned int tablesize; + unsigned int lf; + // current index of prime number table + int primeindex; + // buckets + rsvcHSlist* buckets; + + // convert key into unsigned integer value in range + unsigned int hash(rsvcHashable* ele) const; + + // expand the hash table size to next prime number when + // load factor reaches the preset value + void rehash (void); + +private: + +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif +}; + +//====================================================================== +// class rsvcHashIterator +// iterator protocol for hash tables +//====================================================================== +class rsvcHashIterator +{ +public: + // constructor and destructor + rsvcHashIterator (rsvcHash& v); + ~rsvcHashIterator (void); + + // iterator protocol + int init (void); + rsvcHashable* operator ()(void); + int operator ! (void); + int operator ++(void); + + // change value at this position + // make sure the hash key are the same inside the value + void operator = (rsvcHashable* value); + + // new operations + // remove current item pointed by this cursor + void removeCurrent (void); + +protected: + rsvcHash& base; + unsigned int currentIndex; + // Single iterator within a bucket + rsvcHSlistIterator* itr; + // getNextIterator used to set internal iterator pointer + // return 1: got it. return 0: no more iterator + int getNextIterator (void); + +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif +}; +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcHashable.cc b/extensions/cdevGenericServer/NameServer/src/rsvcHashable.cc new file mode 100755 index 0000000..ebb6e86 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcHashable.cc @@ -0,0 +1,38 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Hashable Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcHashable.cc,v +// Revision 1.1 1998/01/22 17:08:13 akers +// Addition of new NameServer +// +// +// +#include +#include "rsvcHashable.h" + +rsvcHashable::rsvcHashable (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcHashable Class Object\n"); +#endif +} + +rsvcHashable::~rsvcHashable (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcHashable Class Object\n"); +#endif +} + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcHashable.h b/extensions/cdevGenericServer/NameServer/src/rsvcHashable.h new file mode 100755 index 0000000..ec04dec --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcHashable.h @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Abstract class +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_HASHABLE_H +#define _RSVC_HASHABLE_H + +class rsvcHashable +{ +public: + // destructor + virtual ~rsvcHashable (void); + virtual unsigned int hash (void) = 0; + +protected: + rsvcHashable (void); +}; +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcIO.cc b/extensions/cdevGenericServer/NameServer/src/rsvcIO.cc new file mode 100755 index 0000000..64b7e51 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcIO.cc @@ -0,0 +1,977 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcIO Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcIO.cc,v +// Revision 1.8 1998/03/31 18:40:21 chen +// add monitorEntryOff +// +// Revision 1.7 1998/03/19 18:31:00 chen +// add monitorEntry capability to server table +// +// Revision 1.6 1998/02/26 19:10:52 chen +// minor changes +// +// Revision 1.5 1998/02/25 19:53:12 chen +// Put more debug information +// +// Revision 1.4 1998/02/24 19:49:34 chen +// turn on some dbug printf +// +// Revision 1.3 1998/02/20 19:30:22 chen +// Fix a bug on blocked write by resetting errno +// +// Revision 1.2 1998/01/22 20:04:07 chen +// to make it work with cdevReactor +// +// Revision 1.1 1998/01/22 17:08:14 akers +// Addition of new NameServer +// +// +// +#include +#include +#include "rsvcIO.h" + +#ifdef _WIN32 +#include +#endif + +extern int rsvc_finished; + +rsvcIO::rsvcIO (cdevReactor & r, rsvcAcceptor* acceptor, + rsvcDataStoreTable& table) +:cdevEventHandler (), sockStream_ (), reactor_ (r), acceptor_ (acceptor), + clientHost_ (0), dataQueue_ (), wmsg_ (), storeTable_ (table), + wmaskSet_ (0) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcIO Class Object\n"); +#endif + + // create output buffer + dbuffer_ = new char[1024]; + dbuflen_ = 1024; + wmsg_.attach (dbuffer_, dbuflen_, 0); + + // create input buffer + ibuffer_ = new char[1024]; + ibuflen_ = 1024; +} + +rsvcIO::~rsvcIO (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete rsvcIO Class Object\n"); +#endif + + handleClose (); + + sockStream_.close (); + + if (clientHost_) + delete []clientHost_; + + if (dbuffer_) + delete []dbuffer_; + + if (ibuffer_) + delete []ibuffer_; + + // clean out unfinished data items in the data queue + rsvcNetData* data = 0; + while (!dataQueue_.isEmpty ()) { + data = (rsvcNetData *)dataQueue_.dequeue (); + delete data; + } +} + +rsvcIO::operator cdevSocketStream & (void) +{ + return sockStream_; +} + +int +rsvcIO::peerAddr (const cdevInetAddr & addr) +{ + if (clientHost_) + delete []clientHost_; + + clientHost_ = new char[strlen (addr.getHostName ()) + 1]; + strcpy (clientHost_, addr.getHostName ()); + return RSVC_SUCCESS; +} + +int +rsvcIO::getHandle (void) const +{ + return sockStream_.getHandle (); +} + +int +rsvcIO::setSockOption (int level, int option, void *optval, int optlen) const +{ + return sockStream_.setOption (level, option, optval, optlen); +} + +int +rsvcIO::sendToPeer (rsvcNetData* data) +{ +#ifdef _CDEV_MANAGE_SERVERS + if (dataQueue_.count () > 50) { + fprintf (stderr, "Fatal: Client from %s at port %d is not responding\n", + clientHost_, getHandle ()); + fprintf (stderr, "Fatal: Server close down this connection %d\n", getHandle ()); + shutdownIO (); + + return 0; + } +#endif + + // put this data to the end of queue + dataQueue_.enqueue ((void *)data); + + // if write mask is set, the socket is write blocked. + // I do not want to call write directly + if (!wmaskSet_) + handleOutput (); + return RSVC_SUCCESS; +} + +int +rsvcIO::handleClose ( void ) +{ + // ask all data store to handle close + storeTable_.handleClose ((void *)this); + + // check all callback lists and remove all related callbacks + storeTable_.monitorOff ((void *)this); + + // remove this client from client list + if (!acceptor_->listLock_) + acceptor_->remove (this); + + // get current time to print out +#ifdef _WIN32 + struct _timeb tv; + _ftime (&tv); + long ts = (long)tv.time; +#else + struct timeval tv; + gettimeofday (&tv, 0); + long ts = (long)tv.tv_sec; +#endif + printf ("At %s rsvcIO: client %s disconnects at port %d from server\n", + ctime (&ts), clientHost_, getHandle ()); + + // deallocate all the resources since this one is created dynamically. + // Reactor will only remove it from its array and calls this handleClose + // delete this; + + + + return 0; +} + +int +rsvcIO::writeStreamBuffer (void) +{ + int nbytes = 0; + + while (wmsg_.size () > 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: Trying to write %u bytes to output socket %d\n", + wmsg_.size (), getHandle ()); +#endif + nbytes = sockStream_.send (wmsg_.actionPtr (), wmsg_.size ()); + if (nbytes <= 0) { + if (errno == EWOULDBLOCK || errno == EAGAIN) { +//#ifdef _RSVC_DEBUG + printf ("rsvcIO: Unable to write on to the output socket %d, break out\n", + getHandle ()); +//#endif + // reset errno to prevent the system to ckeck these errno again + errno = 0; + return 0; + } + else { +//#ifdef _RSVC_DEBUG + printf ("rsvcIO: Writing to a socket %d error %d\n", getHandle(), errno); +//#endif + errno = 0; + return -1; + } + } + else { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: Wrote %d bytes to socket %d in the rsvcIO\n", nbytes, + getHandle ()); +#endif + wmsg_.actionPtr (nbytes); // move pointer ahead + } + } + // reset the msg buffer + wmsg_.reset (); + return 1; +} + + +int +rsvcIO::handleOutput ( void ) +{ + // check whether write mask is set or not, if yes, remove the mask + // without calling handleClose + int wstatus; + if (wmaskSet_ == 1) { + setMask(READ_MASK); + wmaskSet_ = 0; + } + + if (wmsg_.active ()) { + if ((wstatus = writeStreamBuffer ()) == 0) { + // unable to write, turn on write mask + setMask(WRITE_MASK); + wmaskSet_ = 1; + return 0; + } + else if (wstatus == -1) // write error + return -1; + else { // success, remove from queue + rsvcNetData* data = (rsvcNetData *)dataQueue_.dequeue (); + if (data == 0) { + fprintf (stderr, "Fatal: data queue cannot be empty here\n"); + } + else + delete data; + } + } + + while (!dataQueue_.isEmpty ()) { + // take the first netdata and convert to stream msg + rsvcNetData* data = (rsvcNetData *)dataQueue_.front (); + size_t datasize = data->streamSize (); + + // resize buffer if necessary + if (datasize > dbuflen_) { +#ifdef _RSVC_DEBUG + printf (" data size is greater that %d resize databuffer to %d\n", + 2*datasize); +#endif + delete []dbuffer_; + dbuflen_ = 2*datasize; + dbuffer_ = new char[dbuflen_]; + } + // stream network data + if (data->streamOut (dbuffer_, datasize) != RSVC_SUCCESS) { + fprintf (stderr, "FATAL: Stream error for network data\n"); + data = (rsvcNetData *)dataQueue_.dequeue (); + delete data; + } + else { + wmsg_.attach (dbuffer_, datasize, 0); + + if ((wstatus = writeStreamBuffer ()) == 0) { + // unable to write, turn on write mask + setMask(WRITE_MASK); + wmaskSet_ = 1; + return 0; + } + else if (wstatus == -1) + return -1; + else { + rsvcNetData* data = (rsvcNetData *)dataQueue_.dequeue (); + delete data; + } + } + } + return 0; +} + +int +rsvcIO::handleInput ( void ) +{ + rsvcNetData recvdata; + int n = 0; + int err = 0; + + // first read header length information + char header[32]; + n = sockStream_.recv_n (header, rsvcNetData::headerLen ()); + if (n != rsvcNetData::headerLen ()) { + //#ifdef _RSVC_DEBUG + printf ("rsvcIO:Receiving net data header error:expect %d bytes got %d\n", + rsvcNetData::headerLen (), n); + //#endif + + shutdownIO (); + // above shutdown will trigger handleClose, no need to + // return -1 to trigger handleClose again + return 0; + } + + size_t datasize; + if (rsvcNetData::readHeader (header, n, &datasize) != RSVC_SUCCESS) { + //#ifdef _RSVC_DEBUG + printf ("rsvcIO: Reading rsvcNetData Header error in rsvcIO handleInput\n"); + //#endif + shutdownIO (); + // above shutdown will trigger handleClose, no need to + // return -1 to trigger handleClose again + return 0; + } + + if (datasize > ibuflen_) { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: Input data size %d > buffer size %d, resize buffer size to %d\n", + datasize, ibuflen_, 2*datasize); +#endif + delete []ibuffer_; + ibuflen_ = 2*datasize; + ibuffer_ = new char[ibuflen_]; + } + + n = sockStream_.recv_n (ibuffer_, datasize); + if (n != datasize) { + //#ifdef _RSVC_DEBUG + printf ("rsvcIO: Received %d bytes, expecting %d bytes\n", n, datasize); + //#endif + shutdownIO (); + // above shutdown will trigger handleClose, no need to + // return -1 to trigger handleClose again + return 0; + } + +#ifdef _RSVC_DEBUG + printf ("rsvcIO: Received data with size %d from port %d\n", datasize, + getHandle ()); +#endif + if (recvdata.streamIn (ibuffer_, datasize) != RSVC_SUCCESS) { + //#ifdef _RSVC_DEBUG + printf ("rsvcIO: stream data in error\n"); + //#endif + shutdownIO (); + // above shutdown will trigger handleClose, no need to + // return -1 to trigger handleClose again + return 0; + } + + // do something with recvdata here + return processData (recvdata); +} + +int +rsvcIO::processData (rsvcNetData& ndata) +{ + int status = 0; + rsvcCbk& cbk = ndata.cbk (); + // assign socket id to the cbk object + cbk.userptr ((void *)this); + + switch (cbk.opcode ()) { + case RSVC_CREATE_MEMTABLE: + status = createMemTable (ndata); + break; + case RSVC_OPEN_DBASE: + status = openTable (ndata); + break; + case RSVC_INSERT: + status = insertValue (ndata, 0); + break; + case RSVC_OVERWRITE: + status = insertValue (ndata, 1); + break; + case RSVC_GET: + status = getValue (ndata); + break; + case RSVC_DEL: + status = delValue (ndata); + break; + case RSVC_SET: + status = setValue (ndata); + break; + case RSVC_MONITOR_ON: + status = monitorValue (ndata); + break; + case RSVC_MONITOR_OFF: + status = monitorOffValue (ndata); + break; + case RSVC_MONITOR_ONATTR: + status = monitorAttr (ndata); + break; + case RSVC_MONITOR_OFFATTR: + status = monitorOffAttr (ndata); + break; + case RSVC_MONITOR_ENTRIES: + status = monitorEntries (ndata); + break; + case RSVC_MONITOR_OFFENTRIES: + status = monitorOffEntries (ndata); + break; + case RSVC_QUERY: + status = query (ndata); + break; + case RSVC_SERVER_EXIT: + rsvc_finished = 1; + break; + default: + status = -1; + break; + } + return status; +} + + +int +rsvcIO::createMemTable (rsvcNetData& ndata) +{ + // get real data and callback information + rsvcData& data = ndata.data (); + rsvcCbk& cbk = ndata.cbk (); + rsvcNetData* retdata[1024]; + size_t num = 1024; + int i = 0; + + rsvcDataStore* datastore = 0; + // get name of the table + char tablename[128]; + if (data.get ("table", tablename, sizeof (tablename)) != RSVC_SUCCESS) { + cbk.cbkstatus (RSVC_ERROR); + // construct return message + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else { + if ((datastore = storeTable_.find (tablename)) != 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: table name %s is already here\n", tablename); +#endif + cbk.cbkstatus (RSVC_INVALIDOP); + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else { + datastore = new rsvcDataStoreMem (tablename); + storeTable_.add (datastore); + + // now create data store table definition + datastore->createDatabase (ndata, retdata, &num); + } + } + for (i = 0; i < num; i++) + sendToPeer (retdata[i]); + + return 0; +} + + +int +rsvcIO::openTable (rsvcNetData& ndata) +{ + // get real data and callback information + rsvcData& data = ndata.data (); + rsvcCbk& cbk = ndata.cbk (); + rsvcNetData* retdata[1024]; + size_t num = 1024; + int i = 0; + + rsvcDataStore* datastore = 0; + // get name of the table + char tablename[128]; + if (data.get ("table", tablename, sizeof (tablename)) != RSVC_SUCCESS) { + cbk.cbkstatus (RSVC_ERROR); + // construct return message + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else { + if ((datastore = storeTable_.find (tablename)) == 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: table name %s is not found\n", tablename); +#endif + datastore = rsvcDataStore::createDataStore (tablename); + if (!datastore) { + cbk.cbkstatus (RSVC_INVALIDOP); + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: add database \"%s\" to the index table\n", tablename); +#endif + storeTable_.add (datastore); + // now open database + datastore->openDatabase (ndata, retdata, &num); + } + } + else { + // now open database + datastore->openDatabase (ndata, retdata, &num); + } + } + for (i = 0; i < num; i++) + sendToPeer (retdata[i]); + + return 0; +} + +int +rsvcIO::insertValue (rsvcNetData& ndata, int overwrite) +{ + // get real data and callback information + rsvcData& data = ndata.data (); + rsvcCbk& cbk = ndata.cbk (); + rsvcNetData* retdata[1024]; + size_t num = 1024; + int i = 0; + + rsvcDataStore* datastore = 0; + // get name of the table + char tablename[128]; + if (data.get ("table", tablename, sizeof (tablename)) != RSVC_SUCCESS) { + cbk.cbkstatus (RSVC_ERROR); + // construct return message + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else { + if ((datastore = storeTable_.find (tablename)) == 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: table name %s is not found\n", tablename); +#endif + cbk.cbkstatus (RSVC_NOTFOUND); + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else + datastore->putValue (ndata, retdata, &num, overwrite); + } + + for (i = 0; i < num; i++) + sendToPeer (retdata[i]); + + return 0; +} + +int +rsvcIO::getValue (rsvcNetData& ndata) +{ + // get real data and callback information + rsvcData& data = ndata.data (); + rsvcCbk& cbk = ndata.cbk (); + rsvcNetData* retdata[1024]; + size_t num = 1024; + int i = 0; + + rsvcDataStore* datastore = 0; + // get name of the table + char tablename[128]; + if (data.get ("table", tablename, sizeof (tablename)) != RSVC_SUCCESS) { + cbk.cbkstatus (RSVC_ERROR); + // construct return message + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else { + if ((datastore = storeTable_.find (tablename)) == 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: table name %s is not found\n", tablename); +#endif + cbk.cbkstatus (RSVC_NOTFOUND); + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else + datastore->getValue (ndata, retdata, &num); + } + + for (i = 0; i < num; i++) + sendToPeer (retdata[i]); + + return 0; +} + + +int +rsvcIO::delValue (rsvcNetData& ndata) +{ + // get real data and callback information + rsvcData& data = ndata.data (); + rsvcCbk& cbk = ndata.cbk (); + rsvcNetData* retdata[1024]; + size_t num = 1024; + int i = 0; + + rsvcDataStore* datastore = 0; + // get name of the table + char tablename[128]; + if (data.get ("table", tablename, sizeof (tablename)) != RSVC_SUCCESS) { + cbk.cbkstatus (RSVC_ERROR); + // construct return message + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else { + if ((datastore = storeTable_.find (tablename)) == 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: table name %s is not found\n", tablename); +#endif + cbk.cbkstatus (RSVC_NOTFOUND); + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else + datastore->delValue (ndata, retdata, &num); + } + + for (i = 0; i < num; i++) + sendToPeer (retdata[i]); + + return 0; +} + + +int +rsvcIO::setValue (rsvcNetData& ndata) +{ + // get real data and callback information + rsvcData& data = ndata.data (); + rsvcCbk& cbk = ndata.cbk (); + rsvcNetData* retdata[1024]; + size_t num = 1024; + int i = 0; + + rsvcDataStore* datastore = 0; + // get name of the table + char tablename[128]; + if (data.get ("table", tablename, sizeof (tablename)) != RSVC_SUCCESS) { + cbk.cbkstatus (RSVC_ERROR); + // construct return message + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else { + if ((datastore = storeTable_.find (tablename)) == 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: table name %s is not found\n", tablename); +#endif + cbk.cbkstatus (RSVC_NOTFOUND); + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else + datastore->setValue (ndata, retdata, &num); + } + + for (i = 0; i < num; i++) + sendToPeer (retdata[i]); + + return 0; +} + + +int +rsvcIO::monitorValue (rsvcNetData& ndata) +{ + // get real data and callback information + rsvcData& data = ndata.data (); + rsvcCbk& cbk = ndata.cbk (); + rsvcNetData* retdata[1024]; + size_t num = 1024; + int i = 0; + + rsvcDataStore* datastore = 0; + // get name of the table + char tablename[128]; + if (data.get ("table", tablename, sizeof (tablename)) != RSVC_SUCCESS) { + cbk.cbkstatus (RSVC_ERROR); + // construct return message + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else { + if ((datastore = storeTable_.find (tablename)) == 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: table name %s is not found\n", tablename); +#endif + cbk.cbkstatus (RSVC_NOTFOUND); + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else + datastore->monitorValue (ndata, retdata, &num); + } + + for (i = 0; i < num; i++) + sendToPeer (retdata[i]); + + return 0; +} + + +int +rsvcIO::monitorEntries (rsvcNetData& ndata) +{ + // get real data and callback information + rsvcData& data = ndata.data (); + rsvcCbk& cbk = ndata.cbk (); + rsvcNetData* retdata[1024]; + size_t num = 1024; + int i = 0; + + rsvcDataStore* datastore = 0; + // get name of the table + char tablename[128]; + if (data.get ("table", tablename, sizeof (tablename)) != RSVC_SUCCESS) { + cbk.cbkstatus (RSVC_ERROR); + // construct return message + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else { + if ((datastore = storeTable_.find (tablename)) == 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: table name %s is not found\n", tablename); +#endif + cbk.cbkstatus (RSVC_NOTFOUND); + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else + datastore->monitorIncomingEntries (ndata, retdata, &num); + } + + for (i = 0; i < num; i++) + sendToPeer (retdata[i]); + + return 0; +} + +int +rsvcIO::monitorAttr (rsvcNetData& ndata) +{ + // get real data and callback information + rsvcData& data = ndata.data (); + rsvcCbk& cbk = ndata.cbk (); + rsvcNetData* retdata[1024]; + size_t num = 1024; + int i = 0; + + rsvcDataStore* datastore = 0; + // get name of the table + char tablename[128]; + if (data.get ("table", tablename, sizeof (tablename)) != RSVC_SUCCESS) { + cbk.cbkstatus (RSVC_ERROR); + // construct return message + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else { + if ((datastore = storeTable_.find (tablename)) == 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: table name %s is not found\n", tablename); +#endif + cbk.cbkstatus (RSVC_NOTFOUND); + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else + datastore->monitorAttr (ndata, retdata, &num); + } + + for (i = 0; i < num; i++) + sendToPeer (retdata[i]); + + return 0; +} + +int +rsvcIO::monitorOffValue (rsvcNetData& ndata) +{ + // get real data and callback information + rsvcData& data = ndata.data (); + rsvcCbk& cbk = ndata.cbk (); + rsvcNetData* retdata[1024]; + size_t num = 1024; + int i = 0; + + rsvcDataStore* datastore = 0; + // get name of the table + char tablename[128]; + if (data.get ("table", tablename, sizeof (tablename)) != RSVC_SUCCESS) { + cbk.cbkstatus (RSVC_ERROR); + // construct return message + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else { + if ((datastore = storeTable_.find (tablename)) == 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: table name %s is not found\n", tablename); +#endif + cbk.cbkstatus (RSVC_NOTFOUND); + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else + datastore->monitorOffValue (ndata, retdata, &num); + } + + for (i = 0; i < num; i++) + sendToPeer (retdata[i]); + + return 0; +} + +int +rsvcIO::monitorOffEntries (rsvcNetData& ndata) +{ + // get real data and callback information + rsvcData& data = ndata.data (); + rsvcCbk& cbk = ndata.cbk (); + rsvcNetData* retdata[1024]; + size_t num = 1024; + int i = 0; + + rsvcDataStore* datastore = 0; + // get name of the table + char tablename[128]; + if (data.get ("table", tablename, sizeof (tablename)) != RSVC_SUCCESS) { + cbk.cbkstatus (RSVC_ERROR); + // construct return message + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else { + if ((datastore = storeTable_.find (tablename)) == 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: table name %s is not found\n", tablename); +#endif + cbk.cbkstatus (RSVC_NOTFOUND); + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else + datastore->monitorOffIncomingEntries (ndata, retdata, &num); + } + + for (i = 0; i < num; i++) + sendToPeer (retdata[i]); + + return 0; +} + + +int +rsvcIO::monitorOffAttr (rsvcNetData& ndata) +{ + // get real data and callback information + rsvcData& data = ndata.data (); + rsvcCbk& cbk = ndata.cbk (); + rsvcNetData* retdata[1024]; + size_t num = 1024; + int i = 0; + + rsvcDataStore* datastore = 0; + // get name of the table + char tablename[128]; + if (data.get ("table", tablename, sizeof (tablename)) != RSVC_SUCCESS) { + cbk.cbkstatus (RSVC_ERROR); + // construct return message + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else { + if ((datastore = storeTable_.find (tablename)) == 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: table name %s is not found\n", tablename); +#endif + cbk.cbkstatus (RSVC_NOTFOUND); + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else + datastore->monitorOffAttr (ndata, retdata, &num); + } + + for (i = 0; i < num; i++) + sendToPeer (retdata[i]); + + return 0; +} + +int +rsvcIO::query (rsvcNetData& ndata) +{ + rsvcData& data = ndata.data (); + rsvcCbk& cbk = ndata.cbk (); + rsvcNetData* retdata[10240]; + size_t num = 10240; + int i = 0; + + + rsvcDataStore* datastore = 0; + // get name of the table + char tablename[128]; + char qmsg[1024]; + if (data.get ("table", tablename, sizeof (tablename)) != RSVC_SUCCESS) { + cbk.cbkstatus (RSVC_ERROR); + // construct return message + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else if (data.get (rsvcServerConfig::queryTag (), qmsg, sizeof (qmsg)) != + RSVC_SUCCESS) { + cbk.cbkstatus (RSVC_ERROR); + // construct return message + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else { + if ((datastore = storeTable_.find (tablename)) == 0) { +#ifdef _RSVC_DEBUG + printf ("rsvcIO: table name %s is not found\n", tablename); +#endif + cbk.cbkstatus (RSVC_NOTFOUND); + retdata[0] = new rsvcNetData (cbk); + num = 1; + } + else + datastore->query (ndata, qmsg, retdata, &num); + } + + for (i = 0; i < num; i++) + sendToPeer (retdata[i]); + + return 0; +} + + +void +rsvcIO::shutdownIO (void) +{ + reactor_.removeHandler (this); +} + +void +rsvcIO::enable (int num) +{ + sockStream_.setFlags (num); +} + +void +rsvcIO::disable (int num) +{ + sockStream_.setFlags (sockStream_.getFlags()^num); +} + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcIO.h b/extensions/cdevGenericServer/NameServer/src/rsvcIO.h new file mode 100755 index 0000000..30852ed --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcIO.h @@ -0,0 +1,146 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC TCP IO handler (Generic Class) +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_IO_H +#define _RSVC_IO_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +class rsvcAcceptor; + +class rsvcIO: public cdevEventHandler +{ +public: + // constructor + rsvcIO (cdevReactor& r, rsvcAcceptor* acceptor, + rsvcDataStoreTable& st); + + // destructor + virtual ~rsvcIO (void); + + // remember connected peer address + int peerAddr (const cdevInetAddr & addr); + + // conversion operator for SOCK_Stream + operator cdevSocketStream & (void); + + // set socket options + int setSockOption (int level, int option, void* optval, + int optlen) const; + + // send result to the connected peer + int sendToPeer (rsvcNetData* data); + + // return socket file descriptor + int getHandle (void) const; + + // enable/disable socket io options + void enable (int num); + void disable (int num); + +protected: + // handle socket close + int handleClose ( void ); + + // handleOutput + int handleOutput ( void ); + + // handleInput + int handleInput ( void ); + + // write msg buffer + int writeStreamBuffer (void); + + // shutdown this io stream + void shutdownIO (void); + + // handle process data + int processData (rsvcNetData& data); + + // all those processing functions + int createMemTable (rsvcNetData& ndata); + + int openTable (rsvcNetData& ndata); + + int insertValue (rsvcNetData& ndata, int overwrite = 0); + + int getValue (rsvcNetData& ndata); + + int delValue (rsvcNetData& ndata); + + int setValue (rsvcNetData& ndata); + + int monitorValue (rsvcNetData& ndata); + + int monitorOffValue (rsvcNetData& ndata); + + int monitorAttr (rsvcNetData& ndata); + + int monitorOffAttr (rsvcNetData& ndata); + + int monitorEntries (rsvcNetData& ndata); + + int monitorOffEntries (rsvcNetData& ndata); + + int query (rsvcNetData& ndata); + + // connection to remote client + cdevSocketStream sockStream_; + // Reactor reference + cdevReactor & reactor_; + // client host address + char* clientHost_; + // acceptor that creates this IO + rsvcAcceptor* acceptor_; + + // data queue for writing + rsvcQueue dataQueue_; + + // current writing msg + rsvcStreamMsg wmsg_; + + // output data streaming buffer + char* dbuffer_; + size_t dbuflen_; + + // input data convertion buffer + char* ibuffer_; + size_t ibuflen_; + + // data store index table + rsvcDataStoreTable& storeTable_; + + // flag to tell whether write mask is set or not + int wmaskSet_; + + // deny copy and assignment operations + rsvcIO (const rsvcIO& io); + rsvcIO& operator = (const rsvcIO& io); +}; +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcLocalConfig.cc b/extensions/cdevGenericServer/NameServer/src/rsvcLocalConfig.cc new file mode 100755 index 0000000..b01944e --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcLocalConfig.cc @@ -0,0 +1,109 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Local Configuration Routines +// +// Author: Jie Chen +// +// Revision History: +// rsvcLocalConfig.cc,v +// Revision 1.3 1998/02/26 19:11:45 chen +// use reguler timer instead of sig alarm to scan server entries +// +// Revision 1.2 1998/01/29 19:11:01 akers +// Ongoing development +// +// Revision 1.1 1998/01/22 17:08:15 akers +// Addition of new NameServer +// +// +// +#ifdef _CDEV_MANAGE_SERVERS + +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include +#include +#include +#include + +extern cdevReactor* rsvc_reactor; + +class rsvcServerEntryScanTask : public cdevEventHandler +{ +public: + // constructor + rsvcServerEntryScanTask (rsvcServerStore* serverStore); + // destructor + ~rsvcServerEntryScanTask (void); + + int handleTimeout (void); + +private: + rsvcServerStore* serverStore_; +}; + +rsvcServerEntryScanTask::rsvcServerEntryScanTask (rsvcServerStore* store) +:cdevEventHandler (), serverStore_ (store) +{ +#ifdef _TARCE_OBJECTS + printf (" Create rsvcServerEntryScanTask Class Object\n"); +#endif + setTimeoutRate ((double)_RSVC_CDEV_SCAN_PERIOD); +} + +rsvcServerEntryScanTask::~rsvcServerEntryScanTask (void) +{ +#ifdef _TARCE_OBJECTS + printf (" Delete rsvcServerEntryScanTask Class Object\n"); +#endif + // server store will be deleted by data store table +} + + +int +rsvcServerEntryScanTask::handleTimeout (void) +{ + serverStore_->checkAll (); + return 0; +} + +void rsvcLocalConfig (rsvcDataStoreTable& table) +{ + rsvcServerStore *serverStore = new rsvcServerStore (); + + if (serverStore->openDatabase () != RSVC_SUCCESS) { + fprintf (stderr, "Cannot open cdev server management service\n"); + exit (1); + } + table.add (serverStore); + + // spawn a timer to scan all data entries + rsvcServerEntryScanTask* scanTask = new rsvcServerEntryScanTask(serverStore); + if (rsvc_reactor) { + rsvc_reactor->registerTimer (scanTask); + } +} + +#else +void rsvcLocalConfig (class rsvcDataStoreTable& /* table */) +{ + +} +#endif + + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcLocalConfig.h b/extensions/cdevGenericServer/NameServer/src/rsvcLocalConfig.h new file mode 100755 index 0000000..ea274a5 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcLocalConfig.h @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// This a local configuration header file for JLAB use only +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_LOCAL_CONFIG_H +#define _RSVC_LOCAL_CONFIG_H + +#ifdef _CDEV_MANAGE_SERVERS + +#define _RSVC_CDEV_SERVERS "cdevServers" // database name +#define _RSVC_CDEV_SERVERS_KEY "svcid" // key name +#define _RSVC_CDEV_SERVER_TKO 30 // if we do not see a server + // for this long, it is dead +#define _RSVC_CDEV_SCAN_PERIOD 10 + +#endif + +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcLogic.h b/extensions/cdevGenericServer/NameServer/src/rsvcLogic.h new file mode 100755 index 0000000..006ee0e --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcLogic.h @@ -0,0 +1,128 @@ +/* +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606 +// coda@cebaf.gov Tel: (804) 249-7030 Fax: (804) 249-5800 +//----------------------------------------------------------------------------- +// +// Description: +// Header File for rsvcServer Query +// +// Author: +// Jie Chen +// CEBAF Data Acquisition Group +// +// +// +*/ +#ifndef _RSVC_LOGIC_H +#define _RSVC_LOGIC_H + +#define RSVC_LOGIC_UNK 200 +#define RSVC_LOGIC_INT 201 +#define RSVC_LOGIC_DBL 202 +#define RSVC_LOGIC_STR 203 + +/* data structure to hold all values on the stack */ +typedef struct _rsvc_logic_data +{ + short type; + union { + int ival; + double dval; + char* string; + }u; +}rsvc_logic_data; + +/* global input test string for parser */ +extern char* _logic_input_text; + +/* global parsing engine */ +extern void* _logic_q_eng; + +/* instruction set */ +typedef int (*rsvcLogicInst)(void* data); + +#define RSVC_LOGIC_STOP (rsvcLogicInst) 0 + +/* function decleration of supporting functions */ +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (__STDC__) || defined (__cplusplus) +extern rsvc_logic_data* new_logic_data (void); +extern rsvc_logic_data* logic_data_dup (rsvc_logic_data* data); +extern void logic_data_assign_int (rsvc_logic_data* data, int val); +extern void logic_data_assign_dbl (rsvc_logic_data* data, double val); +extern void logic_data_assign_str (rsvc_logic_data* data, char* str); +extern void free_logic_data (rsvc_logic_data* data); + +extern void set_input_text (char* text); +extern void set_query_engine (void* eng); + +extern rsvcLogicInst* logic_code (rsvcLogicInst f); +extern int logic_val_push (void* data); +extern int rsvc_data_equal_int (void* data); +extern int rsvc_data_equal_dbl (void* data); +extern int rsvc_data_equal_str (void* data); +extern int rsvc_data_has_str (void* data); +extern int rsvc_data_less_int (void* data); +extern int rsvc_data_less_dbl (void* data); +extern int rsvc_data_greater_int (void* data); +extern int rsvc_data_greater_dbl (void* data); +extern int rsvc_data_lesseq_int (void* data); +extern int rsvc_data_lesseq_dbl (void* data); +extern int rsvc_data_greatereq_int (void* data); +extern int rsvc_data_greatereq_dbl (void* data); +extern int rsvc_data_noequal_int (void* data); +extern int rsvc_data_noequal_dbl (void* data); +extern int rsvc_data_noequal_str (void* data); +extern int rsvc_logic_and (void* data); +extern int rsvc_logic_or (void* data); +extern int rsvc_logic_neg (void* data); +extern int rsvc_logic_end (void* data); + +#else +extern rsvc_logic_data* new_logic_data (); +extern rsvc_logic_data* logic_data_dup (); +extern void logic_data_assign_int (); +extern void logic_data_assign_dbl (); +extern void logic_data_assign_str (); +extern void free_logic_data (); +extern void set_input_text (); +extern void set_query_engine (); +extern rsvcLogicInst* logic_code (); +extern int logic_val_push (); +extern int rsvc_data_equal_int (); +extern int rsvc_data_equal_dbl (); +extern int rsvc_data_equal_str (); +extern int rsvc_data_has_str (); +extern int rsvc_data_less_int (); +extern int rsvc_data_less_dbl (); +extern int rsvc_data_greater_int (); +extern int rsvc_data_greater_dbl (); +extern int rsvc_data_lesseq_int (); +extern int rsvc_data_lesseq_dbl (); +extern int rsvc_data_greatereq_int (); +extern int rsvc_data_greatereq_dbl (); +extern int rsvc_data_noequal_int (); +extern int rsvc_data_noequal_dbl (); +extern int rsvc_data_noequal_str (); +extern int rsvc_logic_and (); +extern int rsvc_logic_or (); +extern int rsvc_logic_neg (); +extern int rsvc_logic_end (); +#endif + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcLogicQEng.cc b/extensions/cdevGenericServer/NameServer/src/rsvcLogicQEng.cc new file mode 100755 index 0000000..c465dde --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcLogicQEng.cc @@ -0,0 +1,866 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606 +// coda@cebaf.gov Tel: (804) 249-7030 Fax: (804) 249-5800 +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of simple computing machine for query +// +// Author: +// Jie Chen +// CEBAF Data Acquisition Group +// +// Revision History: +// rsvcLogicQEng.cc,v +// Revision 1.1 1998/01/22 17:08:16 akers +// Addition of new NameServer +// +// +// +#include "rsvcLogicQEng.h" +#include "y.tab.h" + +extern "C" int yyparse (void); + +rsvcLogicQEng::rsvcLogicQEng (char* qstr) +:result_ (-1) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcLogicQEng Class Object\n"); +#endif + stackp_ = stack_; + progp_ = prog_; + pc_ = prog_; + + qstr_ = new char[::strlen (qstr) + 1]; + ::strcpy (qstr_, qstr); + + int i = 0; + + for (i = 0; i < RSVC_NSTACK; i++) + stack_[i] = 0; + + for (i = 0; i < RSVC_NPROG; i++) + prog_[i] = RSVC_LOGIC_STOP; +} + +rsvcLogicQEng::~rsvcLogicQEng (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delele rsvcLogicQEng Class Object\n"); +#endif + // delete data item on the stack + rsvc_logic_data** ptr = stack_; + while (ptr < stackp_) { // stackp_ is the next free slot + free_logic_data (*ptr); + ptr++; + } + + delete []qstr_; +} + +int +rsvcLogicQEng::parse (void) +{ + // need mutex lock here for MT case + set_input_text (qstr_); + set_query_engine ((void *)this); + + if (yyparse ()) + return -1; + else + return 0; +} + +int +rsvcLogicQEng::execute (rsvcData& data) +{ + pc_ = prog_; + while (*pc_ != RSVC_LOGIC_STOP) { + (*(*pc_)) ((void *)&data); + pc_++; + } + + return result_; +} + +int +rsvcLogicQEng::clean (void) +{ + pc_ = prog_; + while (*pc_ != RSVC_LOGIC_STOP) { + (*(*pc_)) ((void *)0); + pc_++; + } + + return result_; +} + + +int +rsvcLogicQEng::push (rsvc_logic_data* data) +{ + if (stackp_ > &stack_[RSVC_NSTACK-1]) { + fprintf (stderr, "Rsvc Logic Stack Overflow\n"); + return -1; + } + *stackp_ = data; + stackp_++; + return 0; +} + +rsvc_logic_data* +rsvcLogicQEng::pop (void) +{ + if (stackp_ <= stack_) { + fprintf (stderr, "Rsvc Logic Stack Underflow\n"); + return 0; + } + // since stackp is the next free slot + stackp_ --; + rsvc_logic_data* data = *stackp_; + return data; +} + +rsvcLogicInst* +logic_code (rsvcLogicInst f) +{ + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcLogicInst* oprogp = eng->progp_; + if (eng->progp_ > &(eng->prog_[RSVC_NPROG - 1]) ) { + fprintf (stderr, "Programm is too big\n"); + return 0; + } + *(eng->progp_) = f; + (eng->progp_)++; + + return oprogp; +} + +int +logic_val_push (void* arg) +{ + rsvc_logic_data* tmp = 0; + rsvc_logic_data* data0 = 0; + rsvc_logic_data* data1 = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcLogicInst* pc; + // increment program counter + (eng->pc_)++; + pc = eng->pc_; + + tmp = (rsvc_logic_data *)(*pc); + if (arg == 0) + free_logic_data (tmp); + else + data0 = logic_data_dup (tmp); + + // increment program counter + (eng->pc_)++; + pc = eng->pc_; + tmp = (rsvc_logic_data *)(*pc); + if (arg == 0) + free_logic_data (tmp); + else + data1 = logic_data_dup (tmp); + + if (arg != 0) { + eng->push (data0); + eng->push (data1); + } + + return 0; +} + + +int +rsvc_data_equal_int (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcData* data = (rsvcData *)d; + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_STR && d2->type == RSVC_LOGIC_INT) { + int temp; + + if (data->get (d1->u.string, &temp) == RSVC_SUCCESS) { + if (temp == d2->u.ival) + res = 1; + } + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + + +int +rsvc_data_equal_dbl (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcData* data = (rsvcData *)d; + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_STR && d2->type == RSVC_LOGIC_DBL) { + double temp; + + if (data->get (d1->u.string, &temp) == RSVC_SUCCESS) { + if (temp == d2->u.dval) + res = 1; + } + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + +int +rsvc_data_equal_str (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcData* data = (rsvcData *)d; + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_STR && d2->type == RSVC_LOGIC_STR) { + char temp[256]; + + if (data->get (d1->u.string, temp, sizeof (temp)) == RSVC_SUCCESS) { + if (strcmp (temp, d2->u.string) == 0) + res = 1; + } + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + +int +rsvc_data_less_int (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcData* data = (rsvcData *)d; + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_STR && d2->type == RSVC_LOGIC_INT) { + int temp; + + if (data->get (d1->u.string, &temp) == RSVC_SUCCESS) { + if (temp < d2->u.ival) + res = 1; + } + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + + +int +rsvc_data_less_dbl (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcData* data = (rsvcData *)d; + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_STR && d2->type == RSVC_LOGIC_DBL) { + double temp; + + if (data->get (d1->u.string, &temp) == RSVC_SUCCESS) { + if (temp < d2->u.dval) + res = 1; + } + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + + +int +rsvc_data_greater_int (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcData* data = (rsvcData *)d; + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_STR && d2->type == RSVC_LOGIC_INT) { + int temp; + + if (data->get (d1->u.string, &temp) == RSVC_SUCCESS) { + if (temp > d2->u.ival) + res = 1; + } + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + +int +rsvc_data_greater_dbl (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcData* data = (rsvcData *)d; + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_STR && d2->type == RSVC_LOGIC_DBL) { + double temp; + + if (data->get (d1->u.string, &temp) == RSVC_SUCCESS) { + if (temp > d2->u.dval) + res = 1; + } + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + +int +rsvc_data_lesseq_int (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcData* data = (rsvcData *)d; + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_STR && d2->type == RSVC_LOGIC_INT) { + int temp; + + if (data->get (d1->u.string, &temp) == RSVC_SUCCESS) { + if (temp <= d2->u.ival) + res = 1; + } + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + +int +rsvc_data_lesseq_dbl (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcData* data = (rsvcData *)d; + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_STR && d2->type == RSVC_LOGIC_DBL) { + double temp; + + if (data->get (d1->u.string, &temp) == RSVC_SUCCESS) { + if (temp <= d2->u.dval) + res = 1; + } + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + +int +rsvc_data_greatereq_int (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcData* data = (rsvcData *)d; + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_STR && d2->type == RSVC_LOGIC_INT) { + int temp; + + if (data->get (d1->u.string, &temp) == RSVC_SUCCESS) { + if (temp >= d2->u.ival) + res = 1; + } + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + +int +rsvc_data_greatereq_dbl (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcData* data = (rsvcData *)d; + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_STR && d2->type == RSVC_LOGIC_DBL) { + double temp; + + if (data->get (d1->u.string, &temp) == RSVC_SUCCESS) { + if (temp >= d2->u.dval) + res = 1; + } + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + +int +rsvc_data_noequal_int (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcData* data = (rsvcData *)d; + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_STR && d2->type == RSVC_LOGIC_INT) { + int temp; + + if (data->get (d1->u.string, &temp) == RSVC_SUCCESS) { + if (temp != d2->u.ival) + res = 1; + } + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + +int +rsvc_data_noequal_dbl (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcData* data = (rsvcData *)d; + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_STR && d2->type == RSVC_LOGIC_DBL) { + double temp; + + if (data->get (d1->u.string, &temp) == RSVC_SUCCESS) { + if (temp != d2->u.dval) + res = 1; + } + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + +int +rsvc_data_noequal_str (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcData* data = (rsvcData *)d; + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_STR && d2->type == RSVC_LOGIC_STR) { + char temp[256]; + + if (data->get (d1->u.string, temp, sizeof (temp)) == RSVC_SUCCESS) { + if (strcmp (temp, d2->u.string) != 0) + res = 1; + } + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + +int +rsvc_data_has_str (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvcData* data = (rsvcData *)d; + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_STR && d2->type == RSVC_LOGIC_STR) { + char temp[256]; + + if (data->get (d1->u.string, temp, sizeof (temp)) == RSVC_SUCCESS) { + if (strstr (temp, d2->u.string)) + res = 1; + } + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + +int +rsvc_logic_and (void* d) +{ + if (d == 0) + return 0; + + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_INT && d2->type == RSVC_LOGIC_INT) { + if (d1->u.ival && d2->u.ival) + res = 1; + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + + +int +rsvc_logic_or (void* d) +{ + if (d == 0) + return 0; + + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvc_logic_data* d2 = eng->pop (); + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_INT && d2->type == RSVC_LOGIC_INT) { + if (d1->u.ival || d2->u.ival) + res = 1; + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + free_logic_data (d2); + + return res; +} + + +int +rsvc_logic_neg (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_INT) { + if (d1->u.ival > 0) + res = 0; + else + res = 1; + } + + rsvc_logic_data* ndata = new_logic_data (); + logic_data_assign_int (ndata, res); + + // push new data onto the stack + eng->push (ndata); + + // release memory of old data + free_logic_data (d1); + + return res; +} + +int +rsvc_logic_end (void* d) +{ + if (d == 0) + return 0; + + int res = 0; + // this routine is called with mutex lock held + rsvcLogicQEng* eng = (rsvcLogicQEng *)_logic_q_eng; + + rsvc_logic_data* d1 = eng->pop (); + + // check stack varaibles + if (d1->type == RSVC_LOGIC_INT) { + res = d1->u.ival; + } + + // release memory of old data + free_logic_data (d1); + + eng->result_ = res; + return res; +} diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcLogicQEng.h b/extensions/cdevGenericServer/NameServer/src/rsvcLogicQEng.h new file mode 100755 index 0000000..6cdda74 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcLogicQEng.h @@ -0,0 +1,84 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606 +// coda@cebaf.gov Tel: (804) 249-7030 Fax: (804) 249-5800 +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server Query Simple Engine +// +// Author: +// Jie Chen +// CEBAF Data Acquisition Group +// +// +// +#ifndef _RSVC_LOGIC_Q_ENG_H +#define _RSVC_LOGIC_Q_ENG_H + +#include +#include +#include +#include + +/* stack size */ +#define RSVC_NSTACK 1024 + +/* program counter */ +#define RSVC_NPROG 4096 + +class rsvcLogicQEng +{ +public: + // constructor and destructor + rsvcLogicQEng (char* qstring); + ~rsvcLogicQEng (void); + + // operation + + // parse string and produce simple engine + // return 0 success, return -1 syntax error + int parse (void); + + // execute the engine + int execute (rsvcData& data); + + // clean the engine + int clean (void); + + // stack operation + int push (rsvc_logic_data* data); + rsvc_logic_data* pop (void); + +private: + // machine stack + rsvc_logic_data* stack_[RSVC_NSTACK]; + // next free slot on the stack + rsvc_logic_data** stackp_; + + // simple computing machine + rsvcLogicInst prog_[RSVC_NPROG]; + // next free spot for code + rsvcLogicInst* progp_; + // program counter + rsvcLogicInst* pc_; + + // parsing string + char* qstr_; + + // result of execution + int result_; + + friend rsvcLogicInst* logic_code (rsvcLogicInst f); + friend int logic_val_push (void* d); + friend int rsvc_logic_end (void* d); +}; + + +#endif + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcLogicSup.cc b/extensions/cdevGenericServer/NameServer/src/rsvcLogicSup.cc new file mode 100755 index 0000000..9ec40da --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcLogicSup.cc @@ -0,0 +1,136 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606 +// coda@cebaf.gov Tel: (804) 249-7030 Fax: (804) 249-5800 +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server Query Message Logic Expression Parser Supporting Routines +// +// Author: +// Jie Chen +// CEBAF Data Acquisition Group +// +// Revision History: +// rsvcLogicSup.cc,v +// Revision 1.1 1998/01/22 17:08:17 akers +// Addition of new NameServer +// +// +// +#include +#include +#include +#include + +/* global parsing engine */ +void* _logic_q_eng = 0; + +rsvc_logic_data* +new_logic_data (void) +{ + rsvc_logic_data* data = + (rsvc_logic_data *)malloc (sizeof (rsvc_logic_data)); + data->type = RSVC_LOGIC_UNK; + return data; +} + +rsvc_logic_data* +logic_data_dup (rsvc_logic_data* data) +{ + rsvc_logic_data* ndata = new_logic_data (); + ndata->type = data->type; + if (data->type == RSVC_LOGIC_INT) + ndata->u.ival = data->u.ival; + else if (data->type == RSVC_LOGIC_DBL) + ndata->u.dval = data->u.dval; + else if (data->type == RSVC_LOGIC_STR) { + ndata->u.string = (char *)malloc ((strlen (data->u.string) + 1)* + sizeof (char)); + strcpy (ndata->u.string, data->u.string); + } + return ndata; +} + +void +logic_data_assign_int (rsvc_logic_data* data, int val) +{ + data->type = RSVC_LOGIC_INT; + data->u.ival = val; +} + +void +logic_data_assign_dbl (rsvc_logic_data* data, double val) +{ + data->type = RSVC_LOGIC_DBL; + data->u.dval = val; +} + +void +logic_data_assign_str (rsvc_logic_data* data, char* val) +{ + data->type = RSVC_LOGIC_STR; + data->u.string = (char *)malloc ((strlen (val) + 1)*sizeof (char)); + strcpy (data->u.string, val); +} + +void +free_logic_data (rsvc_logic_data* data) +{ + if (data->type == RSVC_LOGIC_STR) + free (data->u.string); + data->type = RSVC_LOGIC_UNK; + free (data); +} + +void +set_query_engine (void* eng) +{ + _logic_q_eng = eng; +} + +#ifdef _RSVC_PARSE_DEBUG +#include + +//char* log_exp = "(value > 50 && severity > 8) && !class like 'epics'"; +char* log_exp = "(value > 50 && severity > 8) && ! class like 'epics'"; + +main (int argc, char** argv) +{ + char expression[256]; + rsvcData data[100]; + int i = 0; + rsvcLogicQEng qeng (log_exp); + + + for (i = 0; i < 100; i++) { + data[i].insert ("value", i); + data[i].insert ("severity", i/10); + if (i < 50) { + data[i].insert ("status", 0); + data[i].insert ("class", "epics"); + } + else { + data[i].insert ("status", 1); + data[i].insert ("class", "coda"); + } + } + + + if (qeng.parse () != -1) { + for (i = 0; i < 100; i++) { + if (qeng.execute (data[i])) + printf ("data %d is ok\n", i); + } + } + + qeng.clean (); +} +#endif + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcLogicSup.h b/extensions/cdevGenericServer/NameServer/src/rsvcLogicSup.h new file mode 100755 index 0000000..f0cb666 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcLogicSup.h @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606 +// coda@cebaf.gov Tel: (804) 249-7030 Fax: (804) 249-5800 +//----------------------------------------------------------------------------- +// +// Description: +// Simple Header File for rsvc logic expression parser +// +// Author: +// Jie Chen +// CEBAF Data Acquisition Group +// +// +// +#ifndef _RSVC_LOGIC_SUP_H +#define _RSVC_LOGIC_SUP_H + +// check whether a cdevData matches a logic expression +// return -1: string has grammer error +// return 0: not matching +// return 1: yes +extern int dataMatchLogic (rsvcData& data, char* string); + +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcNetData.cc b/extensions/cdevGenericServer/NameServer/src/rsvcNetData.cc new file mode 100755 index 0000000..629a9d9 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcNetData.cc @@ -0,0 +1,354 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcNetData Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcNetData.cc,v +// Revision 1.1 1998/01/22 17:08:18 akers +// Addition of new NameServer +// +// +// +#include +#include "rsvcNetData.h" + +rsvcNetData::rsvcNetData (void) +:cbk_ (), data_ () +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcNetData Class Object\n"); +#endif + // empty +} + +rsvcNetData::rsvcNetData (rsvcData& data, long opcode, long cbkid, + long reqid, long clientid, long socketid, + long status) +:cbk_ (opcode, cbkid, reqid, clientid, socketid, status), data_ (data) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcNetData Class Object\n"); +#endif + // empty +} + +rsvcNetData::rsvcNetData (rsvcData& data, rsvcCbk& cbk) +:cbk_ (cbk), data_ (data) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcNetData Class Object\n"); +#endif + // empty +} + +rsvcNetData::rsvcNetData (rsvcData& data) +: cbk_ (), data_ (data) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcNetData Class Object\n"); +#endif + // empty +} + +rsvcNetData::rsvcNetData (rsvcCbk& cbk) +:cbk_ (cbk), data_ () +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcNetData Class Object\n"); +#endif + // empty +} + +rsvcNetData::rsvcNetData (const rsvcNetData& data) +:cbk_ (data.cbk_), data_ (data.data_) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcNetData Class Object\n"); +#endif + // empty +} + +rsvcNetData::~rsvcNetData (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete rsvcNetData Class Object\n"); +#endif + // empty +} + +void +rsvcNetData::set (rsvcData& data, rsvcCbk& cbk) +{ + data_ = data; + cbk_ = cbk; +} + +void +rsvcNetData::set (rsvcCbk& cbk) +{ + cbk_ = cbk; +} + + +void +rsvcNetData::cleanup (void) +{ + cbk_.cleanup (); + data_.remove (); +} + +long +rsvcNetData::opcode (void) const +{ + return cbk_.opcode (); +} + +void +rsvcNetData::opcode (long op) +{ + cbk_.opcode (op); +} + +long +rsvcNetData::cbkid (void) const +{ + return cbk_.cbkid (); +} + +void +rsvcNetData::cbkid (long cid) +{ + cbk_.cbkid (cid); +} + +long +rsvcNetData::reqid (void) const +{ + return cbk_.reqid (); +} + +void +rsvcNetData::reqid (long req) +{ + cbk_.reqid (req); +} + +long +rsvcNetData::clientid (void) const +{ + return cbk_.clientid (); +} + +void +rsvcNetData::clientid (long cid) +{ + cbk_.clientid (cid); +} + +long +rsvcNetData::socketid (void) const +{ + return cbk_.socketid (); +} + +void +rsvcNetData::socketid (long sid) +{ + cbk_.socketid (sid); +} + +void +rsvcNetData::cbkstatus (long status) +{ + cbk_.cbkstatus (status); +} + +long +rsvcNetData::cbkstatus (void) const +{ + return cbk_.cbkstatus (); +} + +rsvcData& +rsvcNetData::data (void) +{ + return data_; +} + +rsvcCbk& +rsvcNetData::cbk (void) +{ + return cbk_; +} + +size_t +rsvcNetData::streamSize (void) +{ + int st = RSVC_SUCCESS; + size_t dataSize = 0; + long size = 0; + + // First is magic number + dataSize += rsvcStreamSize (_RSVC_MAGIC_NUM); + + // Size of the data to follow after this + dataSize += rsvcStreamSize (size); + + // send all cbk information + dataSize += cbk_.streamSize (); + + // send data itself + size_t buflen, count; + data_.streamSize (&buflen, &count); + + dataSize += buflen; + + return dataSize; +} + +int +rsvcNetData::streamOut (char** buffer, size_t* len) +{ + size_t datasize = streamSize (); + char* buf = new char[datasize]; + int i = 0; + + if (!buf) { + fprintf (stderr, "Cannot allocate buffer to rsvcNetData streamout\n"); + exit (1); + } + + *buffer = buf; + *len = datasize; + return streamOut (buf, *len, datasize); +} + +int +rsvcNetData::streamOut (char* buffer, size_t buflen, size_t size) +{ + int st = RSVC_SUCCESS; + int i = 0; + + if (size > buflen) { + fprintf (stderr, "Fatal: rsvcNetData streamout buffer overflow %d > %d\n", + size , buflen); + return RSVC_ERROR; + } + + // write magic number first + long tmp = htonl ((long)_RSVC_MAGIC_NUM); + memcpy (&(buffer[i]), &tmp, rsvcStreamSize (_RSVC_MAGIC_NUM)); + i += rsvcStreamSize (_RSVC_MAGIC_NUM); + + // write data size without header information + size_t real_size = size - rsvcStreamSize (_RSVC_MAGIC_NUM) + - rsvcStreamSize (size); + + tmp = htonl (real_size); + memcpy (&(buffer[i]), &tmp, rsvcStreamSize (size)); + i += rsvcStreamSize (real_size); + + // write cbk data + long cbksize = cbk_.streamSize (); + if (cbk_.streamOut (&(buffer[i]), buflen - i) != RSVC_SUCCESS) + return RSVC_ERROR; + i += (int)cbksize; + + // write data itself + size_t databuflen, datacount; + data_.streamSize (&databuflen, &datacount); + + if (data_.streamOut (&(buffer[i]), buflen - i, datacount) != RSVC_SUCCESS) + return RSVC_ERROR; + + i += databuflen; + + if (i != size) { + fprintf (stderr, "Fatal: Overflow rsvcNetData the stream out buffer\n"); + return RSVC_ERROR; + } + return RSVC_SUCCESS; +} + +int +rsvcNetData::streamOut (char* buffer, size_t len) +{ + size_t datasize = streamSize (); + + if (datasize > len) { + fprintf (stderr, "Fatal: rsvcNetData streamout buffer overflow %d > %d\n", + datasize, len); + return RSVC_ERROR; + } + return streamOut (buffer, len, datasize); +} + +int +rsvcNetData::streamIn (char* buffer, size_t len) +{ + int st = RSVC_SUCCESS; + int i = 0; + + if ((st = cbk_.streamIn (&(buffer[i]), len)) != RSVC_SUCCESS) + return st; + + i += cbk_.streamSize (); + + if ((st = data_.streamIn (&(buffer[i]), len - i)) != RSVC_SUCCESS) + return st; + + return st; +} + +int +rsvcNetData::readHeader (char* buffer, size_t len, size_t* datasize) +{ + long magicnum; + size_t size = 0; + + if (len < rsvcStreamSize (_RSVC_MAGIC_NUM) + rsvcStreamSize (size)) { + fprintf (stderr, "Fatal: reading rsvcNetData Header error: overflow\n"); + return RSVC_ERROR; + } + + int i = 0; + long tmp; + + // get magic number + memcpy (&tmp, &(buffer[i]), rsvcStreamSize (_RSVC_MAGIC_NUM)); + magicnum = ntohl (tmp); + if (magicnum != _RSVC_MAGIC_NUM) { + fprintf (stderr, "Fatal: reading rsvcNetData header error: magic number mismatch\n"); + return RSVC_ERROR; + } + i += rsvcStreamSize (_RSVC_MAGIC_NUM); + + // get data size + memcpy (&tmp, &(buffer[i]), rsvcStreamSize (size)); + size = (unsigned int)ntohl (tmp); + i += rsvcStreamSize (size); + + *datasize = size; + + return RSVC_SUCCESS; +} + +size_t +rsvcNetData::headerLen (void) +{ + return rsvcStreamSize (_RSVC_MAGIC_NUM) + rsvcStreamSize ((size_t)1); +} + + + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcNetData.h b/extensions/cdevGenericServer/NameServer/src/rsvcNetData.h new file mode 100755 index 0000000..a7dd048 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcNetData.h @@ -0,0 +1,124 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Network Protocol Data +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_NET_DATA_H +#define _RSVC_NET_DATA_H + +#include +#include +#include +#include +#include +#include +#include +#include + +class RSVC_CLASS_SPEC rsvcNetData : public rsvcStreamable +{ +public: + // constructors + // create empty data + rsvcNetData (void); + + // create a data with operation code and reqid + rsvcNetData (rsvcData& data, long opcode, long cbkid, + long reqid = 0, long clientid = 0, long socketid = 0, + long status = RSVC_SUCCESS); + + // create a data with explicit callback data + rsvcNetData (rsvcData& data, rsvcCbk& cbk); + + // create a data with callback data only + rsvcNetData (rsvcCbk& cbk); + + // create a data with real data only + rsvcNetData (rsvcData& data); + + // copy operation + rsvcNetData (const rsvcNetData& data); + + // destructor + ~rsvcNetData (void); + + // set method + void set (rsvcData& data, rsvcCbk& cbk); + void set (rsvcCbk& cbk); + + // cleanup everything + void cleanup (void); + + // opcode + long opcode (void) const; + void opcode (long op); + + // request id + long reqid (void) const; + void reqid (long id); + + // client id + long clientid (void) const; + void clientid (long cid); + + // callback id + long cbkid (void) const; + void cbkid (long cid); + + // socket id + long socketid (void) const; + void socketid (long id); + + // net operation status + long cbkstatus (void) const; + void cbkstatus (long status); + + // return underlying data object + rsvcData& data (void); + // return underlying callback object + rsvcCbk& cbk (void); + + // stream in and out operation + size_t streamSize (void); + + // stream out to a newly allocated buffer with size 'size' + int streamOut (char** buf, size_t* size); + // stream out to a preallocate buffer with buffer size 'size' + int streamOut (char* buf, size_t len); + + // stream in from a buffer + // this function is called after one has read in the header + // information already + int streamIn (char* buf, size_t len); + + // stream out to a preallocate buffer with buffer size 'len' + // and data size 'datasize' + int streamOut (char* buf, size_t len, size_t datasize); + + // retrieve header information + static int readHeader (char* buf, size_t len, size_t* datasize); + + // return header length + static size_t headerLen (void); + +private: + // callback object + rsvcCbk cbk_; + + // data object + rsvcData data_; +}; +#endif + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcServer.cc b/extensions/cdevGenericServer/NameServer/src/rsvcServer.cc new file mode 100755 index 0000000..64cd766 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcServer.cc @@ -0,0 +1,148 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Resource Management Service (Server) +// +// Author: Jie Chen +// +// Revision History: +// rsvcServer.cc,v +// Revision 1.2 1998/02/11 18:46:45 akers +// Ongoing development +// +// Revision 1.1 1998/01/22 17:08:19 akers +// Addition of new NameServer +// +// +// +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +int rsvc_finished = 0; +cdevReactor* rsvc_reactor = 0; + +extern void rsvcLocalConfig (rsvcDataStoreTable& table); + +int main (int argc, char** argv) +{ + // first parse server configuraton file + if (argc > 1) + rsvcServerConfig::configure (argv[1]); + else + rsvcServerConfig::configure (); + +#ifndef _WIN32 + // change limit on how many files can be open at a time + struct rlimit limit, nlimit; + if (getrlimit (RLIMIT_NOFILE, &limit) != 0) + printf ("Cannot get resouce limit\n"); + else { + printf ("RSVC Info: Current limit on number of opened files is %d\n", + limit.rlim_cur); + + nlimit.rlim_cur = rsvcServerConfig::maxNoFiles (); + nlimit.rlim_max = limit.rlim_max; + if (setrlimit (RLIMIT_NOFILE, &nlimit) != 0) + printf ("RSVC Info: Cannot change the limit on number of opened files\n"); + else { + if (getrlimit (RLIMIT_NOFILE, &limit) == 0) + printf ("RSVC Info: Limit on number of opened files has been changed to %d\n", + limit.rlim_cur); + else + printf ("RSVC Info: Cannot change the limit on number of opened files\n"); + } + } +#endif + + // create data store table + rsvcDataStoreTable table; + + // create reactor + cdevReactor reactor; + rsvc_reactor = &reactor; + +#ifdef _CDEV_MANAGE_SERVERS + // create udp handler + rsvcUdpHandler udphandler (_RSVC_CDEV_SERVERS, + reactor, table); + if (udphandler.open (rsvcServerConfig::serverPort ()) == -1) { + fprintf (stderr, "Cannot open udp handler at port %d\n", + rsvcServerConfig::serverPort ()); + exit (1); + } + printf ("RSVC Info: rsvc server opens a udp port at %d\n", + udphandler.port_number ()); + + if (reactor.registerHandler (&udphandler, + cdevEventHandler::READ_MASK) == -1) { + fprintf (stderr, "Cannot register udp handler\n"); + exit (1); + } +#endif + + // create TCP handler + rsvcAcceptor acceptor (reactor, table); + if (acceptor.open (rsvcServerConfig::port ()) == -1) { + fprintf (stderr, "Cannot open TCP handler at port %d\n", + rsvcServerConfig::port ()); + exit (1); + } + + printf ("RSVC Info: rsvc server opens a tcp port at %d\n", + acceptor.port_number ()); + + if (reactor.registerHandler (&acceptor, + cdevEventHandler::READ_MASK) == -1) { + fprintf (stderr, "Cannot register tcp handler\n"); + exit (1); + } + + if (rsvcSignal::registerSignalHandlers () != 0) { + fprintf (stderr, "RSVC Error: Cannot register signal handler\n"); + exit (1); + } + + // open a set of databases that are listed in the config file + char** names = rsvcServerConfig::defaultDbases (); + int i = 0; + if (names) { + while (names[i] != 0) { + if (table.openDatabase (names[i]) == RSVC_SUCCESS) + printf ("Database <%s> is open and registerd\n", names[i]); + i++; + } + } + + // start up local configuration + rsvcLocalConfig (table); + + printf ("Starting up rsvc server .....................\n"); + + while (!rsvc_finished) reactor.handleEvents (); + printf ("Shutting down rsvc server\n"); + + return 0; +} + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcServerConfig.cc b/extensions/cdevGenericServer/NameServer/src/rsvcServerConfig.cc new file mode 100755 index 0000000..ee626db --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcServerConfig.cc @@ -0,0 +1,262 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of RSVC Server Configuration Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcServerConfig.cc,v +// Revision 1.2 1998/08/03 16:30:23 chen +// AIX porting +// +// Revision 1.1 1998/01/22 17:08:19 akers +// Addition of new NameServer +// +// +// +#include +#include + +#if defined (AIX) +#include +#endif + +#ifdef _WIN32 +#define strcasecmp _stricmp +#endif + +#include "rsvcServerConfig.h" + +unsigned short rsvcServerConfig::port_ = RSVC_SERVER_PORT; +size_t rsvcServerConfig::pageSize_ = 4096; +size_t rsvcServerConfig::cacheSize_ = 10*4096; +size_t rsvcServerConfig::cacheMax_ = RSVC_CACHE_MAX; +size_t rsvcServerConfig::cacheLf_ = RSVC_CACHE_LF; +size_t rsvcServerConfig::maxnofiles_ = RSVC_RLIMIT_NOFILE; +char* rsvcServerConfig::keyName_ = 0; +char* rsvcServerConfig::keyType_ = 0; +char* rsvcServerConfig::keyExp_ = 0; +char* rsvcServerConfig::tableName_ = 0; +char* rsvcServerConfig::tableNameExt_ = 0; +char* rsvcServerConfig::dbaseHome_ = 0; +char* rsvcServerConfig::monitorTag_ = 0; +char* rsvcServerConfig::queryTag_ = 0; +char** rsvcServerConfig::defaultDbases_ = 0; + +unsigned short +rsvcServerConfig::serverPort (void) +{ + return rsvcServerConfig::port_ + 1024; +} + +unsigned short +rsvcServerConfig::port (void) +{ + return rsvcServerConfig::port_; +} + +size_t +rsvcServerConfig::dbasePageSize (void) +{ + return rsvcServerConfig::pageSize_; +} + +size_t +rsvcServerConfig::dbaseCacheSize (void) +{ + return rsvcServerConfig::cacheSize_; +} + +size_t +rsvcServerConfig::dbaseCacheMax (void) +{ + return rsvcServerConfig::cacheMax_; +} + +size_t +rsvcServerConfig::dbaseCacheLf (void) +{ + return rsvcServerConfig::cacheLf_; +} + +size_t +rsvcServerConfig::maxNoFiles (void) +{ + return rsvcServerConfig::maxnofiles_; +} + + +char * +rsvcServerConfig::key (void) +{ + if (rsvcServerConfig::keyName_ == 0) { + rsvcServerConfig::keyName_ = new char[strlen (RSVC_KEY_NAME) + 1]; + ::strcpy (rsvcServerConfig::keyName_, RSVC_KEY_NAME); + } + return rsvcServerConfig::keyName_; +} + +char * +rsvcServerConfig::keyType (void) +{ + if (rsvcServerConfig::keyType_ == 0) { + rsvcServerConfig::keyType_ = new char[strlen (RSVC_KEY_TYPE_NAME) + 1]; + ::strcpy (rsvcServerConfig::keyType_, RSVC_KEY_TYPE_NAME); + } + return rsvcServerConfig::keyType_; +} + +char * +rsvcServerConfig::keyExp (void) +{ + if (rsvcServerConfig::keyExp_ == 0) { + rsvcServerConfig::keyExp_ = new char[strlen (RSVC_KEY_EXP_NAME) + 1]; + ::strcpy (rsvcServerConfig::keyExp_, RSVC_KEY_EXP_NAME); + } + return rsvcServerConfig::keyExp_; +} + +char * +rsvcServerConfig::table (void) +{ + if (rsvcServerConfig::tableName_ == 0) { + rsvcServerConfig::tableName_ = new char[strlen (RSVC_TABLE_NAME) + 1]; + ::strcpy (rsvcServerConfig::tableName_, RSVC_TABLE_NAME); + } + return rsvcServerConfig::tableName_; +} + +char * +rsvcServerConfig::tableNameExt (void) +{ + if (rsvcServerConfig::tableNameExt_ == 0) { + rsvcServerConfig::tableNameExt_ = new char[strlen (RSVC_TABLE_NAME_EXT) + + 1]; + ::strcpy (rsvcServerConfig::tableNameExt_, RSVC_TABLE_NAME_EXT); + } + return rsvcServerConfig::tableNameExt_; +} + +char * +rsvcServerConfig::dbaseHome (void) +{ + if (rsvcServerConfig::dbaseHome_ == 0) { + rsvcServerConfig::dbaseHome_ = new char[strlen (RSVC_DBASE_HOME) + 1]; + ::strcpy (rsvcServerConfig::dbaseHome_, RSVC_DBASE_HOME); + } + return rsvcServerConfig::dbaseHome_; +} + +char * +rsvcServerConfig::monitorTag (void) +{ + if (rsvcServerConfig::monitorTag_ == 0) { + rsvcServerConfig::monitorTag_ = new char[strlen (RSVC_MONITOR_TAG) + 1]; + ::strcpy (rsvcServerConfig::monitorTag_, RSVC_MONITOR_TAG); + } + return rsvcServerConfig::monitorTag_; +} + +char * +rsvcServerConfig::queryTag (void) +{ + if (rsvcServerConfig::queryTag_ == 0) { + rsvcServerConfig::queryTag_ = new char[strlen (RSVC_QUERY_TAG) + 1]; + ::strcpy (rsvcServerConfig::queryTag_, RSVC_QUERY_TAG); + } + return rsvcServerConfig::queryTag_; +} + +char** +rsvcServerConfig::defaultDbases (void) +{ + return rsvcServerConfig::defaultDbases_; +} + + +int +rsvcServerConfig::configure (char *filename) +{ + char *fname; + char realname[256]; + + if (!filename) { + fname = getenv (RSVC_SERVER_ENV); + if (fname) { + strncpy (realname, fname, sizeof (realname) - 1); + realname[sizeof (realname) - 1] = 0; + } + else + return RSVC_ERROR; + } + strncpy (realname, filename, sizeof (realname) - 1); + realname[sizeof (realname) - 1] = 0; + + FILE *fd = fopen (realname, "r"); + if (!fd) { + fprintf (stderr, "Cannot open server configuration file %s.\n", realname); + fprintf (stderr, "Using default paramerters to startup server\n"); + return RSVC_ERROR; + } + + char line[256]; + char token[80], value[80]; + int st; + int i = 0; + char defdbase[100][100]; + + while (!feof (fd)) { + memset (line, 0, sizeof (line)); + fgets (line, sizeof (line), fd); + if (line[0] == '#' && line[0] == 0) + continue; + if ((st = sscanf (line, "%s %s", token, value)) >= 2) { + if (::strcasecmp (token, "serverPort") == 0) { + rsvcServerConfig::port_ = atoi (value); + printf ("rsvcServerConfig: server starts at port %d\n", atoi (value)); + } + else if (::strcasecmp (token, "dbasePageSize") == 0) { + rsvcServerConfig::pageSize_ = atoi (value); + printf ("rsvcServerConfig: server uses database pagesize %d\n", atoi (value)); + } + else if (::strcasecmp (token, "dbaseCacheSize") == 0) { + rsvcServerConfig::cacheSize_ = atoi (value); + printf ("rsvcServerConfig: server uses cache size %d\n", atoi (value)); + } + else if (::strcasecmp (token, "dbaseCacheMaxEle") == 0) + rsvcServerConfig::cacheMax_ = atoi (value); + else if (::strcasecmp (token, "dbaseCacheLoadFactor") == 0) + rsvcServerConfig::cacheLf_ = atoi (value); + else if (::strcasecmp (token, "dbaseHome") == 0) { + if (rsvcServerConfig::dbaseHome_) + delete []rsvcServerConfig::dbaseHome_; + rsvcServerConfig::dbaseHome_ = new char[strlen (value) + 1]; + strcpy (rsvcServerConfig::dbaseHome_, value); + printf ("rsvcServerConfig: server store database files at %s\n", value); + } + else if (::strcasecmp (token, "defaultDbase") == 0) { + strncpy (defdbase[i], value, sizeof (defdbase[i])); + i++; + } + } + } + fclose (fd); + + // construct default databases that need to be open + rsvcServerConfig::defaultDbases_ = new char*[i + 1]; + for (int j = 0; j < i; j++) { + rsvcServerConfig::defaultDbases_[j] = new char[strlen (defdbase[j]) + 1]; + strcpy (rsvcServerConfig::defaultDbases_[j], defdbase[j]); + } + rsvcServerConfig::defaultDbases_[j] = 0; + + return RSVC_SUCCESS; +} diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcServerConfig.h b/extensions/cdevGenericServer/NameServer/src/rsvcServerConfig.h new file mode 100755 index 0000000..c4d4980 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcServerConfig.h @@ -0,0 +1,68 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Configuration Class +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_SERVER_CONFIG_H +#define _RSVC_SERVER_CONFIG_H + +#include +#include +#include +#include + +#define RSVC_DBASE_HOME "/tmp/" +#define RSVC_SERVER_ENV "RSVC_SERVER_CONFIG" + +class rsvcServerConfig +{ +public: + static int configure (char* filename = 0); + // this is the port all servers to connected to (udp) + static unsigned short serverPort (void); + // this is the port all client program to connect to + static unsigned short port (void); + static size_t dbasePageSize (void); + static size_t dbaseCacheSize (void); + static size_t dbaseCacheMax (void); + static size_t dbaseCacheLf (void); + static size_t maxNoFiles (void); + static char* key (void); + static char* table (void); + static char* keyType (void); + static char* keyExp (void); + static char* dbaseHome (void); + static char* tableNameExt (void); + static char* monitorTag (void); + static char* queryTag (void); + static char** defaultDbases (void); + +protected: + static unsigned short port_; + static size_t pageSize_; + static size_t cacheSize_; + static size_t cacheMax_; + static size_t cacheLf_; + static size_t maxnofiles_; + static char* keyName_; + static char* keyType_; + static char* keyExp_; + static char* tableName_; + static char* dbaseHome_; + static char* tableNameExt_; + static char* monitorTag_; + static char* queryTag_; + static char** defaultDbases_; +}; +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcServerStore.cc b/extensions/cdevGenericServer/NameServer/src/rsvcServerStore.cc new file mode 100755 index 0000000..730bd1b --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcServerStore.cc @@ -0,0 +1,347 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcServerStore Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcServerStore.cc,v +// Revision 1.3 1998/03/19 18:31:00 chen +// add monitorEntry capability to server table +// +// Revision 1.2 1998/02/26 19:13:13 chen +// use directy array to scan server entries to speed up and remove an entry if it is not being monitored +// +// Revision 1.1 1998/01/22 17:08:20 akers +// Addition of new NameServer +// +// +// +#ifdef _CDEV_MANAGE_SERVERS + +#include +#include +#include +#include "rsvcServerStore.h" + + +rsvcServerStore::rsvcServerStore (void) +:rsvcDataStoreMem (_RSVC_CDEV_SERVERS), tdata_ () +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcServerStore Class Object\n"); +#endif + // table header + tdata_.insert (rsvcServerConfig::table (), _RSVC_CDEV_SERVERS); + tdata_.insert (rsvcServerConfig::key (), _RSVC_CDEV_SERVERS_KEY); + tdata_.insert (rsvcServerConfig::keyExp (), "name+domain"); + tdata_.insert (rsvcServerConfig::keyType (), "string type"); + + tdata_.insert ("name", "cdevServerName"); + tdata_.insert ("domain", "cdevDomainName"); + tdata_.insert ("host", "cdevServerHost"); + tdata_.insert ("port", (long)8900); + tdata_.insert ("owner", "yourname"); + tdata_.insert ("time", (long)1234); + tdata_.insert ("pid", (long)1234); + tdata_.insert ("status", (long)0); + tdata_.insert ("severity", (long)0); + tdata_.insert ("ping", (long)0); + + // create table + if (tableDef_.create (tdata_) != RSVC_SUCCESS) { + fprintf (stderr, "rsvcServerStore:Cannot create table definition for %s\n", + _RSVC_CDEV_SERVERS); + } +} + +rsvcServerStore::~rsvcServerStore (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete rsvcServerStore Class Object\n"); +#endif +} + +int +rsvcServerStore::putValue (rsvcNetData& incoming, + rsvcNetData* out[], size_t* num, + int overwrite) +{ + rsvcData& data = incoming.data (); + rsvcCbk& cbk = incoming.cbk (); + int status = RSVC_SUCCESS; + rsvcCacheData* cdata; + + + // in order to achieve efficiency we do not check error condition + // since we trust our clients + if (tableDef_.keyValue (data) == RSVC_SUCCESS) { + cdata = cachedData (data); + if (cdata) { +#ifdef _RSVC_DEBUG + printf ("Data with same key is already there\n"); +#endif + if (!overwrite) + status = RSVC_ERROR; + else { + if (!dataValid (cdata)) { + rsvcData& rdata = cdata->data (); + + // assign new value + rdata = data; + rdata.insert ("status", 3); + rdata.insert ("severity", 0); + rdata.insert ("ping", 0); + rdata.insert ("client", (long)cbk.userptr ()); + // update ping time + ping (cdata); + + cdata->notifyChannels ("status"); + cdata->notifyChannels ("severity"); + cdata->notifyChannels (); + + // notify this is a new entry + notifyAnEntryToChannels (data); + } + else + status = RSVC_ERROR; + } + } + else { + cdata = new rsvcCacheData (data, database_, &tableDef_); + + // lets append some extra information onto this data + rsvcData& rdata = cdata->data (); + rdata.insert ("status", 0); + rdata.insert ("severity", 0); + rdata.insert ("ping", 0); + rdata.insert ("client", (long)cbk.userptr ()); + + // update ping time + ping (cdata); + + cache_.add (cdata); + + // notif this is a new entry + notifyAnEntryToChannels (data); + } + } + else + status = RSVC_NOKEY; + + // construct returning message + out[0] = new rsvcNetData (incoming.cbk ()); + out[0]->cbkstatus (status); + *num = 1; + + return status; +} + + +int +rsvcServerStore::dataValid (rsvcCacheData* cdata) +{ + long stval = 0; + rsvcData& data = cdata->data (); + + if (data.get ("severity", &stval) == RSVC_SUCCESS && stval == 0) + return 1; + return 0; +} + +void +rsvcServerStore::ping (rsvcCacheData* cdata) +{ + long pingval = 0; + rsvcData& data = cdata->data (); + +#ifdef _WIN32 + struct _timeb tv; + _ftime (&tv); + pingval = (long)tv.time; +#else + struct timeval tv; + gettimeofday (&tv, 0); + pingval = (long)tv.tv_sec; +#endif + + if (data.insert ("ping", pingval) != RSVC_SUCCESS) { + fprintf (stderr, "rsvcServerStore: cannot insert new ping value\n"); + } +} + +void +rsvcServerStore::checkPing (rsvcCacheData* cdata) +{ + long pingval = 0; + rsvcData& data = cdata->data (); + long stval; + long sval; +#ifdef _WIN32 + struct _timeb tv; + _ftime (&tv); +#else + struct timeval tv; + gettimeofday (&tv, 0); +#endif + + + + if (data.get ("ping", &pingval) != RSVC_SUCCESS) + fprintf (stderr, "rsvcServerStore: cannot get ping value\n"); + else { + if (data.get ("status", &stval) != RSVC_SUCCESS || + data.get ("severity", &sval) != RSVC_SUCCESS) + fprintf (stderr, "rsvcServerStore: Cannot get status and severity\n"); + else { +#ifdef _WIN32 + if (tv.time - pingval > _RSVC_CDEV_SERVER_TKO) { +#else + if (tv.tv_sec - pingval > _RSVC_CDEV_SERVER_TKO) { +#endif + if (sval == 0) { + // assign new value + rsvcData& rdata = cdata->data (); + + rdata.insert ("status", 1); + rdata.insert ("severity", 1); + + cdata->notifyChannels ("status"); + cdata->notifyChannels ("severity"); + cdata->notifyChannels (); + } + } + else { + if (sval == 1) { + // assign new value + rsvcData& rdata = cdata->data (); + + rdata.insert ("status", 0); + rdata.insert ("severity", 0); + + cdata->notifyChannels ("status"); + cdata->notifyChannels ("severity"); + cdata->notifyChannels (); + } + } + } + } +} + +int +rsvcServerStore::setValue (rsvcNetData& incoming, + rsvcNetData* out[], size_t* num) +{ + // check whether this data is compatable with table definition + rsvcData& data = incoming.data (); + int stval; + int status = RSVC_SUCCESS; + + + if (tableDef_.keyValue (data) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcServerStore: data has no key information for setting\n"); +#endif + status = RSVC_NOKEY; + } + + if (status == RSVC_SUCCESS) { + rsvcCacheData* cdata = cachedData (data); + if (!cdata) + status = RSVC_NOTFOUND; + else { + // update ping time + ping (cdata); + // assign new value + rsvcData& rdata = cdata->data (); + if (rdata.get ("status", &stval) == RSVC_SUCCESS && stval != 0) { + rdata.insert ("status", 0); + rdata.insert ("severity", 0); + + cdata->notifyChannels ("status"); + cdata->notifyChannels ("severity"); + cdata->notifyChannels (); + } + } + } + + if (*num > 0) { + out[0] = new rsvcNetData (incoming.cbk ()); + out[0]->cbkstatus (status); + *num = 1; + } + + return status; +} + +void +rsvcServerStore::checkAll (void) +{ + // use direct array instead of iterator to save new/delete + rsvcHSlist* lists = 0; + unsigned int listsize = 0; + + cache_.bucketList (lists, listsize); + + for (int i = 0; i < listsize; i++) { + if (!lists[i].isEmpty () ) { + rsvcHSlistIterator ite (lists[i]); + rsvcCacheData* cdata = 0; + + for (ite.init (); !ite; ++ite) { + cdata = (rsvcCacheData *) ite (); + checkPing (cdata); + } + } + } + +/* + rsvcHashIterator ite (cache_); + rsvcCacheData* cdata = 0; + + for (ite.init (); !ite; ++ite) { + cdata = (rsvcCacheData *) ite (); + checkPing (cdata); + } +*/ +} + +void +rsvcServerStore::handleClose (void* ptr) +{ + rsvcHashIterator ite (cache_); + rsvcCacheData* cdata = 0; + long userptr = 0; + + for (ite.init (); !ite; ++ite) { + cdata = (rsvcCacheData *) ite (); + // check socket id with client + rsvcData& rdata = cdata->data (); + if (rdata.get ("client", &userptr) == RSVC_SUCCESS && + userptr == (long)ptr) { + if (cdata->monitored ()) { // this data is monitored + // assign new value + rdata.insert ("status", 2); + rdata.insert ("severity", 2); + + cdata->notifyChannels ("status"); + cdata->notifyChannels ("severity"); + cdata->notifyChannels (); + } + else { // this data is not being monitored. remove it + ite.removeCurrent (); + delete cdata; + } + + } + } +} +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcServerStore.h b/extensions/cdevGenericServer/NameServer/src/rsvcServerStore.h new file mode 100755 index 0000000..f5677a6 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcServerStore.h @@ -0,0 +1,106 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// rsvcServerStore Class for JLAB Control System Use Only +// +// This is a storage class for all network servers running +// in the JLAB control system +// +// This database has a fixed definition as the following +// "table" "cdevServers" +// "key" "svid" +// "keyExp" "name+domain" +// "keyType" RSVC_STRING +// "name" RSVC_STRING +// "domain" RSVC_STRING +// "host" RSVC_STRING +// "owner" RSVC_STRING +// "time" RSVC_LONG +// "port" LONG +// "pid" LONG +// +// the following are appended by this class +// 0 --> active +// "status" 1 --> dormant +// 2 --> dead +// 3 --> newserver +// +// 0 --> normal +// "severity" 1 --> minor +// 2 --> major +// +// "ping" RSVC_LONG +// "client" RSVC_LONG +// +// +// +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_SERVER_STORE_H +#define _RSVC_SERVER_STORE_H + +#ifdef _CDEV_MANAGE_SERVERS + +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#else +#include +#endif + +#include + +class rsvcCacheData; + +class rsvcServerStore: public rsvcDataStoreMem +{ +public: + // constructor + rsvcServerStore (void); + ~rsvcServerStore (void); + + // inherited operations + virtual int putValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num, + int overwrite = 0); + + virtual int setValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + virtual void handleClose (void* ptr); + + // check all data inside table + void checkAll (void); + +protected: + // check whether a data is valid or not by checking + // status field of cached data + int dataValid (rsvcCacheData* data); + + // update ping number + void ping (rsvcCacheData* data); + + // check ping number + void checkPing (rsvcCacheData* data); + +private: + // Fixed table definition + rsvcData tdata_; +}; +#endif + +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcSignal.cc b/extensions/cdevGenericServer/NameServer/src/rsvcSignal.cc new file mode 100755 index 0000000..421ba08 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcSignal.cc @@ -0,0 +1,130 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implemenation of signal handler +// +// Author: +// Jie Chen +// +// Revision History: +// rsvcSignal.cc,v +// Revision 1.5 1998/03/19 18:31:01 chen +// add monitorEntry capability to server table +// +// Revision 1.4 1998/03/06 13:37:41 chen +// Use exit to quit +// +// Revision 1.3 1998/02/26 19:17:25 chen +// change exit to set rsvc_finished = 1 +// +// Revision 1.2 1998/02/11 18:46:46 akers +// Ongoing development +// +// Revision 1.1 1998/01/22 17:08:21 akers +// Addition of new NameServer +// +// +// +#include +#include +#include +#include +#include "rsvcSignal.h" + +#if defined (__linux) + +#ifndef SIGSYS +#define SIGSYS SIGUNUSED +#endif + +#endif + +#ifdef _WIN32 +int rsvcSignal::signals[] = +{SIGINT, SIGILL, SIGFPE, SIGSEGV, + SIGTERM, SIGABRT, SIGBREAK}; + +int rsvcSignal::numSignals = 7; + +int +rsvcSignal::registerSignalHandlers (void) +{ + for (int i = 0; i < rsvcSignal::numSignals; i++) + if (signal (rsvcSignal::signals[i], rsvcSignal::signalFunc) < 0) + return -1; + + return 0; +} + +void +rsvcSignal::signalFunc (int signo) +{ + fprintf (stderr, "Interrupted by %d signal\n", signo); + exit (1); +} + +#else +int rsvcSignal::signals[] = +{SIGINT, SIGQUIT, SIGILL, SIGFPE, + SIGSYS, SIGPIPE, SIGBUS, SIGSEGV, + SIGTERM, SIGIO, SIGHUP, SIGPOLL}; + +int rsvcSignal::numSignals = 12; + +int +rsvcSignal::registerSignalHandlers (void) +{ + struct sigaction act, oact; + + act.sa_handler = &(rsvcSignal::signalFunc); + sigemptyset (&act.sa_mask); + act.sa_flags = 0; + + for (int i = 0; i < rsvcSignal::numSignals; i++) + if (sigaction (rsvcSignal::signals[i], &act, &oact) < 0) + return -1; + + return 0; +} + +void +rsvcSignal::signalFunc (int signo) +{ +#ifdef sun + char signame[SIG2STR_MAX]; + if (sig2str (signo, signame) == -1) + sprintf (signame, "unknown"); + + fprintf (stderr, "Interrupted by %s signal\n", signame); + + if (signo == SIGSEGV || signo == SIGBUS) { + fprintf (stderr, "Fatal: Caught signal %s, Quit.......\n", signame); + abort (); + } + else if (signo != SIGPIPE && signo != SIGTSTP && + signo != SIGCONT && signo != SIGHUP) { + exit (1); + } +#else + fprintf (stderr, "Interrupted by %d signal\n", signo); + + if (signo == SIGSEGV || signo == SIGBUS) { + fprintf (stderr, "Fatal: Caught signal %d, Quit.......\n", signo); + abort (); + } + else if (signo != SIGPIPE && signo != SIGTSTP && + signo != SIGCONT && signo != SIGHUP) { + // rsvc_finished = 1; + exit (1); + } +#endif +} +#endif + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcSignal.h b/extensions/cdevGenericServer/NameServer/src/rsvcSignal.h new file mode 100755 index 0000000..7cf6b34 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcSignal.h @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// rsvc server signal handler +// +// Author: +// Jie Chen +// +// +// +#ifndef _RSVC_SIGNAL_HANDLER_H +#define _RSVC_SIGNAL_HANDLER_H + +class cdevReactor; + +extern int rsvc_finished; +extern cdevReactor* rsvc_reactor; + +class rsvcSignal +{ +public: + // operation + static int registerSignalHandlers (void); + + // all signal handlers + static void signalFunc (int signo); + +private: + // all signals we want to catch + static int signals[]; + static int numSignals; + // deny direct access + rsvcSignal (void); +}; +#endif + + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcSlist.cc b/extensions/cdevGenericServer/NameServer/src/rsvcSlist.cc new file mode 100755 index 0000000..e9c58c6 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcSlist.cc @@ -0,0 +1,903 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Single Linked List for void * +// +// Note: remove and clean operations on the list +// will only remove link nodes without removal of +// the content inside the nodes. It is callers' +// responsiblity to clean up those contents +// +// This is unsafe C++ practice, use this list at you own risk +// +// Reason for this list: It is very difficult to instantiate +// a template class in a stand alone shared library +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// Revision History: +// rsvcSlist.cc,v +// Revision 1.1 1998/01/22 17:08:22 akers +// Addition of new NameServer +// +// +// +#include "rsvcSlist.h" + +//====================================================================== +// class rsvcSlist implementation +//====================================================================== +rsvcSlist::rsvcSlist (void) +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +:ptrToFirstLink(0), count_ (0), lock_ () +#else +:ptrToFirstLink(0), count_ (0) +#endif +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcSlist Class Object\n"); +#endif + // no further initialization +} + +rsvcSlist::rsvcSlist (const rsvcSlist & source) +:count_ (source.count_) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcSlist Class Object\n"); +#endif + + // duplicate elements from source list + if (source.isEmpty_i()) + ptrToFirstLink = 0; + else{ + rsvcSlistLink * firstLink = source.ptrToFirstLink; + ptrToFirstLink = firstLink->duplicate(); + } +} + +rsvcSlist::~rsvcSlist (void) +{ + // empty all elements from the list +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcSlist Class Object\n"); +#endif + deleteAllValues(); +} + +void +rsvcSlist::add (rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // add a new value to the front of a linked list + ptrToFirstLink = new rsvcSlistLink(val, ptrToFirstLink); + count_ ++; + assert(ptrToFirstLink != 0); +} + +void +rsvcSlist::addToEnd (rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + count_ ++; + if (ptrToFirstLink == 0) { + ptrToFirstLink = new rsvcSlistLink(val, ptrToFirstLink); + return; + } + + // loop through until last element + rsvcSlistLink *p = 0; + for (p = ptrToFirstLink; p->ptrToNextLink; p = p->ptrToNextLink) + ; + + rsvcSlistLink* q = new rsvcSlistLink (val, 0); + p->ptrToNextLink = q; +} + +void +rsvcSlist::add_i (rsvcSlistItem val) +{ + // add a new value to the front of a linked list + count_ ++; + ptrToFirstLink = new rsvcSlistLink(val, ptrToFirstLink); + assert(ptrToFirstLink != 0); +} + +int +rsvcSlist::remove (rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // remove an element from the list + // loop to test each element + rsvcSlistLink *q = ptrToFirstLink; + for (rsvcSlistLink * p = ptrToFirstLink; p; p = p->ptrToNextLink){ + if (val == p->value){ + if (q == p){ + // remove first element + ptrToFirstLink = p->ptrToNextLink; + delete p; + } + else{ + q->ptrToNextLink = p->ptrToNextLink; + delete p; + } + count_ --; + return 1; + } + q = p; + } + // not found + return 0; +} + +void +rsvcSlist::deleteAllValues (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // clear all items from the list + rsvcSlistLink * next; + + for (rsvcSlistLink * p = ptrToFirstLink; p != 0; p = next){ + // delete the element pointed to by p + next = p->ptrToNextLink; + p->ptrToNextLink = 0; + delete p; + } + + // set count to zero + count_ = 0; + // mark that the list contains no elements + ptrToFirstLink = 0; +} + +void +rsvcSlist::deleteAllValues_i (void) +{ + // clear all items from the list + rsvcSlistLink * next; + + for (rsvcSlistLink * p = ptrToFirstLink; p != 0; p = next){ + // delete the element pointed to by p + next = p->ptrToNextLink; + p->ptrToNextLink = 0; + delete p; + } + + // set count to zero + count_ = 0; + + // mark that the list contains no elements + ptrToFirstLink = 0; +} + +int +rsvcSlist::count (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + return count_; +} + +rsvcSlist* +rsvcSlist::duplicate (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + rsvcSlist * newlist = new rsvcSlist; + assert(newlist != 0); + + // copy list + if (ptrToFirstLink) + newlist->ptrToFirstLink = ptrToFirstLink->duplicate(); + + // set new list count + newlist->count_ = count_; + // return the new list + return newlist; +} + +rsvcSlistItem +rsvcSlist::firstElement (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // return first value in list + assert(ptrToFirstLink != 0); + return ptrToFirstLink->value; +} + +rsvcSlistItem +rsvcSlist::firstElement_i (void) +{ + // return first value in list + assert(ptrToFirstLink != 0); + return ptrToFirstLink->value; +} + +rsvcSlistItem +rsvcSlist::lastElement (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + assert(ptrToFirstLink != 0); + // loop through until last element + rsvcSlistLink *p = 0; + for (p = ptrToFirstLink; p->ptrToNextLink; p = p->ptrToNextLink) + ; + return p->value; +} + +rsvcSlistItem +rsvcSlist::lastElement_i (void) +{ + assert(ptrToFirstLink != 0); + // loop through until last element + rsvcSlistLink *p = 0; + for (p = ptrToFirstLink; p->ptrToNextLink; p = p->ptrToNextLink) + ; + return p->value; +} + +int +rsvcSlist::includes(rsvcSlistItem v) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // loop to test each element + for (rsvcSlistLink * p = ptrToFirstLink; p; p = p->ptrToNextLink) + if (v == p->value) + return 1; + + // not found + return 0; +} + +int +rsvcSlist::isEmpty (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // test to see if the list is empty + // list is empty if the pointer to the first link is null + return ptrToFirstLink == 0; +} + +int +rsvcSlist::isEmpty_i (void) const +{ + // test to see if the list is empty + // list is empty if the pointer to the first link is null + return ptrToFirstLink == 0; +} + +void +rsvcSlist::removeFirst (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // make sure there is a first element + assert(ptrToFirstLink != 0); + + // save pointer to the removed node + rsvcSlistLink * p = ptrToFirstLink; + + // reassign the ptrToFirstLink node + ptrToFirstLink = p->ptrToNextLink; + + // decrease the count + count_ --; + // recover memory used by the first element + delete p; +} + +void +rsvcSlist::removeFirst_i (void) +{ + // make sure there is a first element + assert(ptrToFirstLink != 0); + + // save pointer to the removed node + rsvcSlistLink * p = ptrToFirstLink; + + // reassign the ptrToFirstLink node + ptrToFirstLink = p->ptrToNextLink; + + // decrease the count + count_ --; + + // recover memory used by the first element + delete p; +} + +//====================================================================== +// class slink implementation +// No need to add any mutex protection since all member +// functions are called with lock held +//====================================================================== +rsvcSlistLink* +rsvcSlistLink::insert(rsvcSlistItem val) +{ + // insert a new link after current node + ptrToNextLink = new rsvcSlistLink(val, ptrToNextLink); + + // check that allocation was successful + assert(ptrToNextLink != 0); + return ptrToNextLink; +} + +rsvcSlistLink::rsvcSlistLink (rsvcSlistItem val, rsvcSlistLink * nxt) +:value(val), ptrToNextLink(nxt) +{ + // create and initialize a new link field +} + +rsvcSlistLink* +rsvcSlistLink::duplicate (void) +{ + rsvcSlistLink * newlink; + + // if there is a next field. copy remainder of list + if (ptrToNextLink != 0) + newlink = new rsvcSlistLink(value, ptrToNextLink->duplicate()); + else + newlink = new rsvcSlistLink (value, 0); + + // check that allocation was successful + assert(newlink != 0); + return newlink; +} + +rsvcSlistLink* +rsvcSlistLink::next (void) +{ + return ptrToNextLink; +} + +rsvcSlistItem +rsvcSlistLink::data (void) +{ + return value; +} + +//====================================================================== +// class listIterator implementation +//====================================================================== +rsvcSlistIterator::rsvcSlistIterator(rsvcSlist & aList) +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +:theList(aList), lock_ () +#else +:theList(aList) +#endif +{ + // create and initialize a new list + init_i(); +} + +int +rsvcSlistIterator::init_i() +{ + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +int +rsvcSlistIterator::init() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +rsvcSlistItem +rsvcSlistIterator::operator () (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + // return value of current element + // check to see if there is a current element + assert(currentLink != 0); + + // return value associated with current element + return currentLink->value; +} + +int rsvcSlistIterator::operator ! (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + // test for termination of the iterator + // if current link references a removed value, + // update current to point to next position + if (currentLink == 0) + if (previousLink != 0) + currentLink = previousLink->ptrToNextLink; + + // now see if currentLink is valid + return currentLink != 0; +} + +int rsvcSlistIterator::forward_i (void) +{ + // move current pointer to nect element + // special processing if current link is deleted + if (currentLink == 0){ + if (previousLink == 0) + currentLink = theList.ptrToFirstLink; + else + currentLink = previousLink->ptrToNextLink; + } + else{ + // advance pointer + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + + +int rsvcSlistIterator::operator ++() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // move current pointer to nect element + // special processing if current link is deleted + if (currentLink == 0){ + if (previousLink == 0) + currentLink = theList.ptrToFirstLink; + else + currentLink = previousLink->ptrToNextLink; + } + else{ + // advance pointer + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +void rsvcSlistIterator::operator = (rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // modify value of current element + assert(currentLink != 0); + + // modify value of the current link + currentLink->value = val; +} + +void rsvcSlistIterator::removeCurrent_i (void) +{ + // remove the current element from a list + // make sure there is a current element + assert(currentLink != 0); + + // case 1, removing first element + if (previousLink == 0) + theList.ptrToFirstLink = currentLink->ptrToNextLink; + + // case 2, not removing the first element + else + previousLink->ptrToNextLink = currentLink->ptrToNextLink; + + // delete current node + delete currentLink; + + // and set current pointer to null + currentLink = 0; + + // decrease list count element + theList.count_ --; +} + +void rsvcSlistIterator::removeCurrent (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // remove the current element from a list + // make sure there is a current element + assert(currentLink != 0); + + // case 1, removing first element + if (previousLink == 0) + theList.ptrToFirstLink = currentLink->ptrToNextLink; + + // case 2, not removing the first element + else + previousLink->ptrToNextLink = currentLink->ptrToNextLink; + + // delete current node + delete currentLink; + + // and set current pointer to null + currentLink = 0; + + // decrease list count element + theList.count_ --; +} + +void rsvcSlistIterator::addBefore(rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard (lock_); +#endif + + // add a new element to list before current value + // case 1, not at start + if (previousLink) + previousLink = previousLink->insert(val); + + // case 2, at start of list + else{ + theList.rsvcSlist::add(val); + previousLink = theList.ptrToFirstLink; + currentLink = previousLink->ptrToNextLink; + } + + // increase the count + theList.count_ ++; +} + +void rsvcSlistIterator::addAfter(rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // a a new element to list after current value + // case 1, not at start + if (currentLink != 0) + currentLink->insert(val); + + // case 2, at end of list + else if (previousLink != 0) + currentLink = previousLink->insert(val); + + // case 3, start of list + else + theList.rsvcSlist::add(val); + + // increase the count + theList.count_ ++; +} + +int rsvcSlistIterator::searchSame(rsvcSlistItem &val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // search the list to find out whether we have this element + // if we do, move cursor to this element return 1 + // if we don't return 0 + init_i(); + + if (currentLink == 0){ + // empty link + return 0; + } + while (currentLink != 0){ + // advance pointer + if (currentLink->value == val) + break; + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +//======================================================================== +// Implementation of rsvcSlistCursor +// Implements of cursor without changing list +//======================================================================== +rsvcSlistCursor::rsvcSlistCursor(const rsvcSlist & aList) +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +:theList(aList), lock_ () +#else +:theList(aList) +#endif +{ + // create and initialize a new list + init_i(); +} + +int +rsvcSlistCursor::init_i() +{ + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +int +rsvcSlistCursor::init() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +rsvcSlistItem +rsvcSlistCursor::operator () (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // return value of current element + // check to see if there is a current element + assert(currentLink != 0); + + // return value associated with current element + return currentLink->value; +} + +int rsvcSlistCursor::operator ! (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // test for termination of the iterator + // if current link references a removed value, + // update current to point to next position + if (currentLink == 0) + if (previousLink != 0) + currentLink = previousLink->ptrToNextLink; + + // now see if currentLink is valid + return currentLink != 0; +} + +int rsvcSlistCursor::operator ++ (void) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // move current pointer to nect element + // special processing if current link is deleted + if (currentLink == 0){ + if (previousLink == 0) + currentLink = theList.ptrToFirstLink; + else + currentLink = previousLink->ptrToNextLink; + } + else{ + // advance pointer + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +int rsvcSlistCursor::searchSame (rsvcSlistItem &val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + // search the list to find out whether we have this element + // if we do, move cursor to this element return 1 + // if we don't return 0 + init_i(); + + if (currentLink == 0){ + // empty link + return 0; + } + while (currentLink != 0){ + // advance pointer + if (currentLink->value == val) + break; + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +void rsvcSlistCursor::operator = (rsvcSlistItem ) +{ + // empty +} + + +//======================================================================== +// Implementation of doubleEndedList +//======================================================================== +rsvcDoubleEndedSlist::rsvcDoubleEndedSlist() +:rsvcSlist() +{ + ptrToLastLink = 0; +} + +rsvcDoubleEndedSlist::rsvcDoubleEndedSlist(const rsvcDoubleEndedSlist &v) +:rsvcSlist(v) +{ + ptrToLastLink = v.ptrToLastLink; +} + +void +rsvcDoubleEndedSlist::add(rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + // add method needs to check one special case when the first element + // is added to the list + if (isEmpty_i()) { + // call parent method + rsvcSlist::add_i (val); + ptrToLastLink = ptrToFirstLink; + } + else{ + // always add to the head + rsvcSlist::add_i(val); + } +} + +void +rsvcDoubleEndedSlist::addToEnd (rsvcSlistItem val) +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + + //add new value T to the end of the list + // if there is an end, add to it + if(ptrToLastLink != 0) { + ptrToLastLink = ptrToLastLink->insert(val); + count_ ++; + } + else { + assert (isEmpty_i ()); + // call parent method + rsvcSlist::add_i (val); + ptrToLastLink = ptrToFirstLink; + } +} + +void +rsvcDoubleEndedSlist::deleteAllValues() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + //delete all values from the list + rsvcSlist::deleteAllValues_i(); + ptrToLastLink = 0; +} + +void +rsvcDoubleEndedSlist::removeFirst() +{ +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutexGuard guard(lock_); +#endif + //remove the first element from the list + // invoke the parent method + rsvcSlist::removeFirst_i(); + + // only do something if we removed last element + if(isEmpty_i()) + ptrToLastLink = 0; +} + + +//======================================================================== +// Implementation of queue +//======================================================================== +rsvcQueue::rsvcQueue (void) +:rsvcDoubleEndedSlist () +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcQueue Class Object\n"); +#endif +} + +rsvcSlistItem +rsvcQueue::front (void) +{ + return firstElement (); +} + +void +rsvcQueue::enqueue (rsvcSlistItem val) +{ + // add new value val to the end of the list + // if there is an end, add to it + if(ptrToLastLink != 0) { + ptrToLastLink = ptrToLastLink->insert(val); + count_ ++; + } + else { + assert (isEmpty_i ()); + // call parent method + rsvcSlist::add_i (val); + ptrToLastLink = ptrToFirstLink; + } +} + +rsvcSlistItem +rsvcQueue::dequeue (void) +{ + if (isEmpty_i ()) + return 0; + + // get first element + rsvcSlistItem result = firstElement_i (); + //remove the first element from the list + // invoke the parent method + rsvcSlist::removeFirst_i(); + + // only do something if we removed last element + if(isEmpty_i()) + ptrToLastLink = 0; + + return result; +} diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcSlist.h b/extensions/cdevGenericServer/NameServer/src/rsvcSlist.h new file mode 100755 index 0000000..2ca3955 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcSlist.h @@ -0,0 +1,304 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Single Linked List for pointers void * +// +// Note: remove and clean operations on the list +// will only remove link nodes without removal of +// the content inside the nodes. It is callers' +// responsiblity to clean up those contents +// +// This is unsafe C++ practice, use this list at you own risk +// +// Reason for this list: It is very difficult to instantiate +// a template class in a stand alone shared library +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// +// +// +#ifndef _RSVC_SLIST_H +#define _RSVC_SLIST_H + +#include +#include + +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +#include +#endif + +#include +#include +#include +#include + + +typedef void* rsvcSlistItem; + +//====================================================================== +// class rsvcSlist +// Single Linked List for void* pointer +//====================================================================== +class rsvcSlistLink; +class rsvcSlistIterator; +class rsvcSlistCursor; +class rsvcHash; + +class rsvcSlist +{ +public: + // constructors + rsvcSlist (void); + rsvcSlist (const rsvcSlist & source); + virtual ~rsvcSlist (void); + + // operations + + // add list item to the beginning of the list + virtual void add (rsvcSlistItem value); + // add item to the end of list + virtual void addToEnd (rsvcSlistItem value); + + // remove a list item from the list + // return 0: nothing to remove + // return 1: remove success + virtual int remove (rsvcSlistItem value); + + // clean up the list. + virtual void deleteAllValues (void); + + // return first element of the list + virtual rsvcSlistItem firstElement (void); + + // return last element of the list + virtual rsvcSlistItem lastElement (void); + + // duplicate ths whole list + virtual rsvcSlist* duplicate (void); + + // check whether this list contains a particular item + // return 1: yes. return 0: no + virtual int includes (rsvcSlistItem value); + + // Is list empty + // return 1: yes. return 0: no + virtual int isEmpty (void); + + // remove first element of the list + virtual void removeFirst (void); + + // return number of elements inside the list + virtual int count (void); + +protected: + // data field + rsvcSlistLink* ptrToFirstLink; + + // number elements in the list + int count_; + +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif + + // some internal functions which must be called with lock held + virtual void add_i (rsvcSlistItem value); + virtual int isEmpty_i (void) const; + virtual void deleteAllValues_i (void); + virtual void removeFirst_i (void); + virtual rsvcSlistItem firstElement_i (void); + virtual rsvcSlistItem lastElement_i (void); + + // friends + friend class rsvcSlistIterator; + // cannot modify list in anyways + friend class rsvcSlistCursor; + friend class rsvcHash; + +private: + // deny access to assignment operation + rsvcSlist& operator = (const rsvcSlist& list); +}; + +//====================================================================== +// class rsvcSlistLink +// Single linked list link node +//====================================================================== +class rsvcSlistLink +{ +public: + // constructor + rsvcSlistLink (rsvcSlistItem linkValue, rsvcSlistLink * nextPtr); + + // insert a new element following the current value + rsvcSlistLink* insert (rsvcSlistItem val); + // return data value + rsvcSlistItem data (void); + + // return next data item + rsvcSlistLink* next (void); + + +private: + + // duplicate + rsvcSlistLink* duplicate (void); + + // data areas + rsvcSlistItem value; + rsvcSlistLink* ptrToNextLink; + + // friends + friend class rsvcSlist; + friend class rsvcSlistIterator; + friend class rsvcSlistCursor; +}; + +//=================================================================== +// class rsvcSlistIterator +// implements iterator protocol for linked lists +// also permits removal and addition of elements +//=================================================================== + +class rsvcHashIterator; + +class rsvcSlistIterator +{ +public: + // constructor + rsvcSlistIterator (rsvcSlist& aList); + + // iterator protocol + virtual int init (void); + virtual rsvcSlistItem operator () (void); + virtual int operator ! (void); + virtual int operator ++ (void); + virtual void operator = (rsvcSlistItem value); + + // new methods specific to list iterators + + // remove current item pointed by the iterator from the list + void removeCurrent(void); + + // add an item to the list before the position pointed by the iterator + void addBefore(rsvcSlistItem newValue); + + // add an item to the list after the position pointed by the iterator + void addAfter(rsvcSlistItem newValue); + + // search an item and move the iterator to that position + int searchSame(rsvcSlistItem &value); + +protected: + // some internal functions which must be called with lock held + virtual int init_i (void); + // move cursor forward + virtual int forward_i (void); + // internal remove current + void removeCurrent_i (void); + // data areas + rsvcSlistLink * currentLink; + rsvcSlistLink * previousLink; + rsvcSlist& theList; +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif + +private: + // friend class + friend class rsvcHashIterator; + + // deny access of copy and assignment + rsvcSlistIterator (const rsvcSlistIterator& ir); + rsvcSlistIterator& operator = (const rsvcSlistIterator& ir); +}; + +//=================================================================== +// class rsvcSlistCursor +// implements cursor protocol for linked lists +//=================================================================== +class rsvcSlistCursor +{ +public: + // constructor + rsvcSlistCursor (const rsvcSlist& aList); + + // iterator protocol + virtual int init (void); + virtual rsvcSlistItem operator () (void); + virtual int operator ! (void); + virtual int operator ++ (void); + virtual void operator = (rsvcSlistItem value); + + int searchSame (rsvcSlistItem &value); + +protected: + // internal functions which must be called with lock + virtual int init_i (void); + // data areas + rsvcSlistLink * currentLink; + rsvcSlistLink * previousLink; + const rsvcSlist& theList; +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif + +private: + // deny access to copy and assignment operations + rsvcSlistCursor (const rsvcSlistCursor &); + rsvcSlistCursor& operator = (const rsvcSlistCursor &); +}; + +//====================================================================== +// class doubleEndedList +// Not only keeps a pointer to first node +// but also keeps a pointer to last node +//====================================================================== +class rsvcDoubleEndedSlist: public rsvcSlist{ +public: + //constructor + rsvcDoubleEndedSlist (void); + rsvcDoubleEndedSlist (const rsvcDoubleEndedSlist &v); + + // override the following methods from the rsvcSlist + virtual void add (rsvcSlistItem value); + virtual void deleteAllValues (void); + virtual void removeFirst (void); + + // add new element to the end of the list + virtual void addToEnd (rsvcSlistItem value); + +protected: + rsvcSlistLink *ptrToLastLink; + +private: + // deny access to assignment operation + rsvcDoubleEndedSlist& operator = (const rsvcDoubleEndedSlist); +}; + +class rsvcQueue: public rsvcDoubleEndedSlist +{ +public: + // constructor and destructor + rsvcQueue (void); + + // operations + rsvcSlistItem dequeue (void); + void enqueue (rsvcSlistItem value); + rsvcSlistItem front (void); + +private: + // deny access to assignment and copy operations + rsvcQueue (const rsvcQueue& queue); + rsvcQueue& operator = (const rsvcQueue& queue); +}; +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcSpec.h b/extensions/cdevGenericServer/NameServer/src/rsvcSpec.h new file mode 100755 index 0000000..6b8ee09 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcSpec.h @@ -0,0 +1,62 @@ +/*----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + *----------------------------------------------------------------------------- + * + * Description: + * RSVC and API Specification + * + * Every class header file and C interface header should include + * this header + * + * Authors: Jie Chen + * + * Revision History: + * $Log: rsvcSpec.h,v $ + * Revision 1.1.1.1 2000/05/23 15:12:51 pal + * cdev_psi_1.7.2 + * + * Revision 1.1 1999/03/15 16:40:09 chen + * New file + * + * + */ +#ifndef _RSVC_SPEC_H +#define _RSVC_SPEC_H + +#if defined (_WIN32) + +#if !defined (DLLIMPORT) +#define DLLIMPORT __declspec(dllimport) +#endif + +#if !defined (DLLEXPORT) +#define DLLEXPORT __declspec(dllexport) +#endif + +#if defined (_RSVC_CORE_EXPORTS_) +#define RSVCAPI DLLEXPORT +#define RSVC_CLASS_SPEC DLLEXPORT +#elif defined (_RSVC_BUILD_EXE) +#define RSVCAPI +#define RSVC_CLASS_SPEC +#else +#define RSVCAPI DLLIMPORT +#define RSVC_CLASS_SPEC DLLIMPORT +#endif + +#else /* WIN32 */ + +#define RSVCAPI +#define DLLIMPORT +#define DLLEXPORT +#define RSVC_CLASS_SPEC + +#endif + +#endif + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcStreamMsg.cc b/extensions/cdevGenericServer/NameServer/src/rsvcStreamMsg.cc new file mode 100755 index 0000000..4673b12 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcStreamMsg.cc @@ -0,0 +1,167 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcStreamMsg Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcStreamMsg.cc,v +// Revision 1.1 1998/01/22 17:08:23 akers +// Addition of new NameServer +// +// +// +#include +#include "rsvcStreamMsg.h" + +rsvcStreamMsg::rsvcStreamMsg (void) +:buffer_ (0), buflen_ (0), cursor_ (0), deleteBuffer_ (0), active_ (0) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcStreamMsg Class Object\n"); +#endif + //empty +} + +rsvcStreamMsg::rsvcStreamMsg (char* data, size_t len, int deletebuf) +:buffer_ (data), buflen_ (len), deleteBuffer_ (deletebuf), active_ (0) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcStreamMsg Class Object\n"); +#endif + cursor_ = 0; +} + +rsvcStreamMsg::rsvcStreamMsg (rsvcNetData* data) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcStreamMsg Class Object\n"); +#endif + + char* buffer; + size_t len; + + if (data->streamOut (&buffer, &len) == RSVC_SUCCESS) { + buffer_ = buffer; + buflen_ = len; + deleteBuffer_ = 1; + cursor_ = 0; + active_ = 0; + } + else { + buffer_ = 0; + buflen_ = 0; + deleteBuffer_ = 0; + cursor_ = 0; + active_ = 0; + } +} + +rsvcStreamMsg::~rsvcStreamMsg (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcStreamMsg Class Object\n"); +#endif + if (buffer_ && deleteBuffer_) + delete []buffer_; +} + +size_t +rsvcStreamMsg::length (void) const +{ + return buflen_; +} + +void +rsvcStreamMsg::length (size_t size) +{ + buflen_ = size; +} + +char* +rsvcStreamMsg::base (void) const +{ + return buffer_; +} + +char* +rsvcStreamMsg::actionPtr (void) const +{ + return &(buffer_[cursor_]); +} + +void +rsvcStreamMsg::actionPtr (char* p) +{ + if (p < buffer_ || p > &(buffer_[buflen_ - 1])) { + fprintf (stderr, "Fatal Error: rsvcStreamMsg actionPtr overflow\n"); + return; + } + cursor_ = p - buffer_; + active_ = 1; +} + +void +rsvcStreamMsg::actionPtr (size_t n) +{ + cursor_ += n; + active_ = 1; +} + +size_t +rsvcStreamMsg::size (void) +{ + if (cursor_ >= buflen_) + return 0; + else + return (buflen_ - cursor_); +} + +int +rsvcStreamMsg::endMsg (void) +{ + return (cursor_ >= buflen_); +} + +void +rsvcStreamMsg::reset (void) +{ + cursor_ = 0; + active_ = 0; +} + +void +rsvcStreamMsg::attach (char* data, size_t size, int deleteit) +{ + buffer_ = data; + buflen_ = size; + deleteBuffer_ = deleteit; + cursor_ = 0; + active_ = 0; +} + +int +rsvcStreamMsg::active (void) const +{ + return active_; +} + +void +rsvcStreamMsg::resize (void) +{ + char* newbuffer = new char[2*buflen_]; + memcpy (newbuffer, buffer_, buflen_); + buflen_ = 2*buflen_; + delete []buffer_; + buffer_ = newbuffer; +} + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcStreamMsg.h b/extensions/cdevGenericServer/NameServer/src/rsvcStreamMsg.h new file mode 100755 index 0000000..b5b7c30 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcStreamMsg.h @@ -0,0 +1,98 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server Streamed Message +// +// This class allows either partial read/write not both +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_STREAM_MSG_H +#define _RSVC_STREAM_MSG_H + +#include +#include +#include + +class rsvcNetData; + +class rsvcStreamMsg +{ +public: + // constructor + + // create an empty stream + rsvcStreamMsg (void); + + // create a stream with data buffer and size and flag denoting + // whether we delete this data buffer we we are done + rsvcStreamMsg (char* data, size_t size, int deleteit = 1); + + // create a stream from rsvcNetData + rsvcStreamMsg (rsvcNetData* data); + + // destructor + ~rsvcStreamMsg (void); + + // attach buffer + void attach (char* data, size_t size, int deleteit = 1); + + // check we are in the middle of action + int active (void) const; + + // set action pointer + void actionPtr (char* ptr); + // move ptr forward + void actionPtr (size_t n); + // return action pointer + char* actionPtr (void) const; + + // total message size + size_t length (void) const; + + // set msg length + void length (size_t len); + + // base pointer + char* base (void) const; + + // remaining message size (or space) + size_t size (void); + // check whether we have reached end of message buffer + int endMsg (void); + + // reset everything + void reset (void); + + // resize buffer to twice of current size + void resize (void); + +private: + + // data area + char* buffer_; + size_t buflen_; + + // pointer to current action ptr + size_t cursor_; + + // flag denoting whether we are deleting the buffer or not + int deleteBuffer_; + + // flag to denoting whether this stream is in the middle of read/write + int active_; + + // deny copy and assignment operations + rsvcStreamMsg (const rsvcStreamMsg& msg); + rsvcStreamMsg& operator = (const rsvcStreamMsg& msg); +}; +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcStreamable.cc b/extensions/cdevGenericServer/NameServer/src/rsvcStreamable.cc new file mode 100755 index 0000000..f8f0f51 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcStreamable.cc @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Streamable class +// +// Author: Jie Chen +// +// Revision History: +// rsvcStreamable.cc,v +// Revision 1.1 1998/01/22 17:08:23 akers +// Addition of new NameServer +// +// +// +#include +#include +#include "rsvcStreamable.h" + +rsvcStreamable::rsvcStreamable (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcStreamable Class Object\n"); +#endif + // empty +} + +rsvcStreamable::~rsvcStreamable (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcStreamable Class Object\n"); +#endif + // empty +} + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcStreamable.h b/extensions/cdevGenericServer/NameServer/src/rsvcStreamable.h new file mode 100755 index 0000000..fd6929f --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcStreamable.h @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Abstract class for network streamable class +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_STREAMABLE_H +#define _RSVC_STREAMABLE_H + +#include +#include + +class rsvcStreamable +{ +public: + // virtual destrcutor + virtual ~rsvcStreamable (void); + // return stream size + virtual size_t streamSize (void) = 0; + + // stream data object out into a newly allocated buffer + virtual int streamOut (char** buffer, size_t* size) = 0; + + // stream data object out into a preallocated buffer + virtual int streamOut (char* buffer, size_t len) = 0; + + // recreate data from incoming data buffer + virtual int streamIn (char* buffer, size_t len) = 0; + +protected: + rsvcStreamable (void); +}; +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcTableDef.cc b/extensions/cdevGenericServer/NameServer/src/rsvcTableDef.cc new file mode 100755 index 0000000..b49d602 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcTableDef.cc @@ -0,0 +1,603 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of table definition +// +// Author: Jie Chen +// +// Revision History: +// rsvcTableDef.cc,v +// Revision 1.1 1998/01/22 17:08:24 akers +// Addition of new NameServer +// +// +// +#include +#include +#include "rsvcTableDef.h" +#include +#include + +#ifndef _WIN32 +#include +#endif + +rsvcTableDef::rsvcTableDef (char* name) +:table_ (), defined_ (0), keyname_ (0), keyexp_ (0), keytype_ (RSVC_INVALID), + keyfunc_ (0), attr0_ (0), attr1_ (0) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcTableDef Class Object\n"); +#endif + name_ = new char[strlen (name) + 1]; + strcpy (name_, name); +} + +rsvcTableDef::~rsvcTableDef (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcTableDef Class Object\n"); +#endif + delete []name_; + + if (keyname_) + delete []keyname_; + if (keyexp_) + delete []keyexp_; + + if (attr0_) + delete []attr0_; + if (attr1_) + delete []attr1_; +} + +int +rsvcTableDef::create (rsvcData& def) +{ + rsvcDataIterator ite (&def); + int match = 0; + int empty = 1; + + for (ite.init (); !ite; ++ite) { + + if (strcmp (ite.tag (), rsvcServerConfig::table ()) == 0) + match ++; + else if (strcmp (ite.tag (), rsvcServerConfig::key ()) == 0) + match ++; + else if (strcmp (ite.tag (), rsvcServerConfig::keyExp ()) == 0) + match ++; + else if (strcmp (ite.tag (), rsvcServerConfig::keyType ()) == 0) + match++; + else + empty = 0; + } + if (match == 4 && !empty) { + table_ = def; + defined_ = 1; + + // get key name and key exp + char temp[256]; + def.get (rsvcServerConfig::key (), temp, sizeof (temp)); + keyname_ = new char[strlen (temp) + 1]; + strcpy (keyname_, temp); + + def.get (rsvcServerConfig::keyExp (), temp, sizeof (temp)); + keyexp_ = new char[strlen (temp) + 1]; + strcpy (keyexp_, temp); + + keytype_ = def.getType (rsvcServerConfig::keyType ()); + switch (keytype_) { + case RSVC_BYTE: + case RSVC_INT16: + case RSVC_UINT16: + case RSVC_INT32: + case RSVC_UINT32: + keytype_ = RSVC_INT32; + break; + case RSVC_FLOAT: + case RSVC_DOUBLE: + keytype_ = RSVC_DOUBLE; + break; + }; + + if (parseKeyExp (keyexp_) != RSVC_SUCCESS) + return RSVC_ERROR; + + return RSVC_SUCCESS; + } + else + return RSVC_ERROR; +} + +int +rsvcTableDef::create (void) +{ + FILE* fd = 0; + + char* filename = tableDefFileName (name_); + + fd = fopen (filename, "r"); + if (!fd) { + fprintf (stderr, "Cannot open database table definition file %s\n", + filename); + return RSVC_ERROR; + } + + struct stat ffs; + + if (fstat (fileno (fd), &ffs) != 0) { + fprintf (stderr, "Cannot do fstat on table def file %s\n", filename); + fclose (fd); + return RSVC_ERROR; + } + size_t buflen = (unsigned int)ffs.st_size; + + if (buflen == 0) { + fprintf (stderr, "Fatal: file size on table def file %s is zero\n", filename); + fclose (fd); + return RSVC_ERROR; + } + + char* buffer = new char[buflen]; + + if (read (fileno (fd), (void *)buffer, buflen) != buflen) { + fprintf (stderr, "Fatal: Read Error from table def %s\n", filename); + fclose (fd); + return RSVC_ERROR; + } + fclose (fd); + + rsvcData tbdata; + if (tbdata.streamIn (buffer, buflen) != RSVC_SUCCESS) { + delete []buffer; + return RSVC_ERROR; + } + + delete []buffer; + return create (tbdata); +} + +int +rsvcTableDef::output (void) +{ + if (!defined_) + return RSVC_ERROR; + + FILE* fd = 0; + char* filename = tableDefFileName (name_); + + fd = fopen (filename, "w"); + if (!fd) { + fprintf (stderr, "Cannot write database table def file %s\n", filename); + return RSVC_ERROR; + } + + char* buffer; + size_t len; + + if (table_.streamOut (&buffer, &len) != RSVC_SUCCESS) { + fprintf (stderr, "Cannot stream table definition %s\n", filename); + return RSVC_ERROR; + } + + if (write (fileno (fd), buffer, len) != len) { + fprintf (stderr, "Writing table def to %s file failed\n", filename); + delete []buffer; + return RSVC_ERROR; + } + + fclose (fd); + delete []buffer; + return RSVC_SUCCESS; +} + +int +rsvcTableDef::output (rsvcData& data) +{ + if (!defined_) + return RSVC_ERROR; + + data = table_; + + return RSVC_SUCCESS; +} + +int +rsvcTableDef::tableDefined (void) const +{ + return defined_; +} + +char* +rsvcTableDef::name (void) const +{ + return name_; +} + +int +rsvcTableDef::rowNameValid (char* name) +{ + if (!defined_) + return RSVC_ERROR; + + void* data; + if (table_.find (name, data) != RSVC_SUCCESS) + return 0; + return 1; +} + +int +rsvcTableDef::typeConvertable (int type0, int type1) +{ + int st = 1; + + if (type0 >= RSVC_INVALID || type0 < RSVC_BYTE || + type1 >= RSVC_INVALID || type1 < RSVC_BYTE) + return 0; + + switch (type0) { + case RSVC_BYTE: + case RSVC_INT16: + case RSVC_UINT16: + case RSVC_INT32: + case RSVC_UINT32: + case RSVC_FLOAT: + case RSVC_DOUBLE: + if (type1 == RSVC_STRING || type1 == RSVC_TIMESTAMP) + st = 0; + break; + case RSVC_STRING: + if (type1 != RSVC_STRING) + st = 0; + break; + case RSVC_TIMESTAMP: + if (type1 != RSVC_STRING) + st = 0; + break; + default: + st = 0; + } + return st; +} + +int +rsvcTableDef::rowValid (char* name, int type) +{ + if (!defined_) + return RSVC_ERROR; + + rsvcDataTypes datatype; + datatype = table_.getType (name); + + if (rsvcTableDef::typeConvertable (type, datatype)) + return 1; + return 0; +} + +int +rsvcTableDef::dataValid (rsvcData& data) +{ + if (!defined_) + return RSVC_ERROR; + + rsvcDataIterator ite0 (&data); + int datatype; + + rsvcDataEntry *entry = 0; + for (ite0.init (); !ite0; ++ite0) { + entry = ite0 (); + datatype = table_.getType (entry->tag_); + if (strcmp (entry->tag_, keyname_) != 0) { + // do not need to check key name tag + if (!rsvcTableDef::typeConvertable (datatype, entry->dataType_)) { +#ifdef _RSVC_DEBUG + printf ("Error: table has type %d and data type %d incompatable for tag %s\n", + datatype, entry->dataType_, entry->tag_); +#endif + return 0; + } + } + } + return 1; +} + + +int +rsvcTableDef::dataInsertable (rsvcData& data) +{ + if (!defined_) + return RSVC_ERROR; + + rsvcDataIterator ite0 (&data); + int datatype; + + // make sure tags in the data appears in the table + rsvcDataEntry *entry = 0; + for (ite0.init (); !ite0; ++ite0) { + entry = ite0 (); + datatype = table_.getType (entry->tag_); + if (!rsvcTableDef::typeConvertable (datatype, entry->dataType_)) { +#ifdef _RSVC_DEBUG + printf ("Error: tabke has type %d and data has type %d for tag %s\n", + datatype, entry->dataType_, entry->tag_); +#endif + return 0; + } + } + + // make sure tags in the table appears in the data + rsvcDataIterator ite1 (&table_); + for (ite1.init (); !ite1; ++ite1) { + entry = ite1 (); + if (strcmp (entry->tag_, rsvcServerConfig::table ()) != 0 && + strcmp (entry->tag_, rsvcServerConfig::key ()) != 0 && + strcmp (entry->tag_, rsvcServerConfig::keyType ()) != 0 && + strcmp (entry->tag_, rsvcServerConfig::keyExp ()) != 0) { + datatype = data.getType (entry->tag_); + if (!rsvcTableDef::typeConvertable (datatype, entry->dataType_)) { +#ifdef _RSVC_DEBUG + printf ("Error: data has type %d and table has type %d for tag %s\n", + datatype, entry->dataType_, entry->tag_); +#endif + return 0; + } + } + } + return 1; +} + +char* +rsvcTableDef::keyName (void) const +{ + return keyname_; +} + +char* +rsvcTableDef::keyExp (void) const +{ + return keyexp_; +} + +int +rsvcTableDef::keyType (void) const +{ + return keytype_; +} + + +char* +rsvcTableDef::tableDefFileName (char* tablename) +{ + size_t len; + + len = strlen (rsvcServerConfig::dbaseHome ()) + + strlen (tablename) + strlen (rsvcServerConfig::tableNameExt ()) + 1; + + char *fname = new char[len]; + if (!fname) { + fprintf (stderr, "Cannot allocated memory for table def file name\n"); + exit (1); + } + strcpy (fname, rsvcServerConfig::dbaseHome ()); + strcat (fname, tablename); + strcat (fname, rsvcServerConfig::tableNameExt ()); + return fname; +} + +int +rsvcTableDef::parseKeyExp (char* exp) +{ + char attr0[RSVC_TAG_MAX_LEN]; + char attr1[RSVC_TAG_MAX_LEN]; + char* a0; + char* a1; + char* e = exp; + char op = 0; + + a0 = attr0; + a1 = attr1; + *a0 = 0; + *a1 = 0; + + // parse the expression + while (*e != '\0') { + // skip white spaces + while (*e == ' ' || *e == '\t') + e++; + + // get first attribute + while (*e != ' ' && *e != '\t' && *e != '+' && *e != '\0') { + *a0 = *e; + a0++; e++; + } + *a0 = '\0'; + + // skip white spaces + while (*e == ' ' || *e == '\t') + e++; + + // get operation + if (*e != '+' && *e != '\0') { + fprintf (stderr, "Fatal error: syntax error for key expression %s\n", + exp); + return RSVC_ERROR; + } + if (*e == '+') { + op = *e; + e++; + } + + // skip white spaces + while (*e == ' ' || *e == '\t') + e++; + + // get second attribute + while (*e != ' ' && *e != '\t' && *e != '\0') { + *a1 = *e; + a1++; e++; + } + *a1 = '\0'; + } + + a0 = attr0; + a1 = attr1; + if (*a0 == 0) { + fprintf (stderr, "Fatal error: parsing key expression %s error\n", + exp); + return RSVC_ERROR; + } + + if (*a1 == 0 && op != 0) { + fprintf (stderr, "Fatal error: parsing key expression %s error\n", + exp); + return RSVC_ERROR; + } + else if (*a1 != 0 && op == 0) { + fprintf (stderr, "Fatal error: parsing key expression %s error\n", + exp); + return RSVC_ERROR; + } + else { + // find whether attributes are indeed inside the table definition + void *data; + if (table_.find (attr0, data) != RSVC_SUCCESS) { + fprintf (stderr, "Fatal error: attr0 %s is invalid\n", attr0); + return RSVC_ERROR; + } + + if (*a1 != 0) { + if (table_.find (attr1, data) != RSVC_SUCCESS) { + fprintf (stderr, "Fatal error: attr1 %s is invalid\n", attr1); + return RSVC_ERROR; + } + } + } + + + if (*a1 == 0 && op == 0) { + attr0_ = new char[strlen (a0) + 1]; + strcpy (attr0_, a0); + attr1_ = 0; + keyfunc_ = sameAttr; + printf ("Same attribute function set\n"); + } + else { + attr0_ = new char[strlen (a0) + 1]; + strcpy (attr0_, a0); + + attr1_ = new char[strlen (a1) + 1]; + strcpy (attr1_, a1); + + switch (op) { + case '+': + keyfunc_ = attrPlus; +#ifdef _RSVC_DEBUG + printf ("Add key functon set\n"); +#endif + break; + } + } + return RSVC_SUCCESS; +} + +int +rsvcTableDef::sameAttr (rsvcData& data, rsvcTableDef* t) +{ + void* tmp; + + // check whether this data has key tag in or not + if (data.find (t->keyname_, tmp) == RSVC_SUCCESS) + return RSVC_SUCCESS; + + // duplicate dataentry pointed by tag attr0_ with new tag keyname + return data.dupWithTag (t->attr0_, t->keyname_); +} + +int +rsvcTableDef::attrPlus (rsvcData& data, rsvcTableDef* t) +{ + void* tmp; + + // check whether this data has key tag in or not + if (data.find (t->keyname_, tmp) == RSVC_SUCCESS) + return RSVC_SUCCESS; + + rsvcDataTypes type0 = data.getType (t->attr0_); + rsvcDataTypes type1 = data.getType (t->attr1_); + + if (type0 == RSVC_INVALID) { + fprintf (stderr, "Fatal error: attr %s has invalid data type\n", t->attr0_); + return RSVC_ERROR; + } + if (type1 == RSVC_INVALID) { + fprintf (stderr, "Fatal error: attr %s has invalid data type\n", t->attr1_); + return RSVC_ERROR; + } + + if (type0 == RSVC_STRING && type1 != RSVC_STRING) { + fprintf (stderr, "Fatal: Cannot calculate key from incompatable data types\n"); + return RSVC_ERROR; + } + else if (type0 != RSVC_STRING && type1 == RSVC_STRING) { + fprintf (stderr, "Fatal: Cannot calculate key from incompatable data types\n"); + return RSVC_ERROR; + } + else if (type0 == RSVC_STRING && type1 == RSVC_STRING) { + char sval0[512]; + char sval1[512]; + + if (data.get (t->attr0_, sval0, sizeof (sval0)) != RSVC_SUCCESS) { + fprintf (stderr, "Fatal: cannot find data with attr %s\n", t->attr0_); + return RSVC_ERROR; + } + + if (data.get (t->attr1_, sval1, sizeof (sval1)) != RSVC_SUCCESS) { + fprintf (stderr, "Fatal: cannot find data with attr %s\n", t->attr1_); + return RSVC_ERROR; + } + + char newsval[1024]; + sprintf (newsval, "%s+%s", sval0, sval1); + data.insert (t->keyname_, newsval); + } + else { + double dval0; + double dval1; + + data.get (t->attr0_, &dval0); + data.get (t->attr1_, &dval1); + + double newdval = dval0 + dval1; + + data.insert (t->keyname_, newdval); + } + + return RSVC_SUCCESS; +} + +int +rsvcTableDef::keyValue (rsvcData& data) +{ + if (keyfunc_) + return (*keyfunc_) (data, this); + return RSVC_ERROR; +} + +int +rsvcTableDef::hasKey (rsvcData& data) +{ + if (defined_) { + void* tmp; + if (data.find (keyname_, tmp) == RSVC_SUCCESS) + return 1; + } + return 0; +} + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcTableDef.h b/extensions/cdevGenericServer/NameServer/src/rsvcTableDef.h new file mode 100755 index 0000000..390cb8e --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcTableDef.h @@ -0,0 +1,142 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Database (Memory) Table Definition +// +// Author: Jie Chen +// +// +// +// +#ifndef _RSVC_TABLE_DEF_H +#define _RSVC_TABLE_DEF_H + +#include +#include +#include +#include + +//========================================================================= +// Table Definition by a rsvcData Object +// tag value +// +// "table" "name" +// "key" "name" +// "keyExp" "expression" +// "keyType" something +// "*******" "anything" +// "*******" "anything" +//========================================================================= + +// currently the key can be only in the form of the following +// attr0 + attr1 +// eventually I am going to use yacc to build a better function + +class rsvcTableDef; + +typedef int (*rsvcKeyFunc)(rsvcData& data, rsvcTableDef* table); + +class rsvcTableDef +{ +public: + // constructor and destructor + + // create an empty table definition + rsvcTableDef (char* name); + ~rsvcTableDef (void); + + // construct table definition from a rsvcData + int create (rsvcData& data); + // construct table definition from disk + int create (void); + // dump table definition to disk: overwrite existing table definition + int output (void); + // output table definition to a rsvcData object + int output (rsvcData& data); + + // is table definition set + int tableDefined (void) const; + + // some commonly used operations + + // check whether this row name is valid + int rowNameValid (char* row); + int rowValid (char* row, int type); + // is this data valid: all tags must be a subset of table + int dataValid (rsvcData& data); + // does this data look the same as the table? + int dataInsertable (rsvcData& data); + // check whether this data has key value in it + int hasKey (rsvcData& data); + + // get key information + // What is the name for the key? This determines the file name + // of the datafile + char* keyName (void) const; + // What is the expression for the key? Currently the expression + // must be one of the row name + char* keyExp (void) const; + // what is the key type for the key? + int keyType (void) const; + + // insert tagged key value into a data + int keyValue (rsvcData& data); + + // table name + char* name (void) const; + +protected: + + // all key calculation functions + static int sameAttr (rsvcData& data, rsvcTableDef* table); + static int attrPlus (rsvcData& data, rsvcTableDef* table); + +private: + // function for figure out real table definition file name + // caller release returned memory + static char* tableDefFileName (char* tablename); + + // check whether two types are convertable or not + static int typeConvertable (int type0, int type1); + + // parse simple key expression + int parseKeyExp (char* exp); + + // real rsvcData object + rsvcData table_; + int defined_; + + // table name + char* name_; + + // key name + char* keyname_; + + // key exp + char* keyexp_; + + // key type + int keytype_; + + // index calculate function pointer + rsvcKeyFunc keyfunc_; + + // attributes that make up the key + char* attr0_; + char* attr1_; + + + // deny copy and assignment operations + rsvcTableDef (const rsvcTableDef& def); + rsvcTableDef& operator = (const rsvcTableDef& def); +}; +#endif + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcUdpClient.cc b/extensions/cdevGenericServer/NameServer/src/rsvcUdpClient.cc new file mode 100755 index 0000000..ac7a2f2 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcUdpClient.cc @@ -0,0 +1,167 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC UDP Client +// +// Author: Jie Chen +// +// Revision History: +// rsvcUdpClient.cc,v +// Revision 1.2 1998/02/20 19:37:28 chen +// reset errno after using it (hpux) sometimes not resetting it +// +// Revision 1.1 1998/01/22 17:08:25 akers +// Addition of new NameServer +// +// +// +#include "rsvcUdpClient.h" +#include + +rsvcUdpClient::rsvcUdpClient (void) +:fd_ (-1) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcUdpClient Class Object\n"); +#endif +} + + +rsvcUdpClient::~rsvcUdpClient (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcUdpClient Class Object\n"); +#endif + if (fd_ != -1) + close (fd_); +} + +int +rsvcUdpClient::connect (char* host, unsigned short port) +{ + if ((openUdpPort (host, port)) == -1) + return RSVC_ERROR; + + return RSVC_SUCCESS; +} + +int +rsvcUdpClient::disconnect (void) +{ + if (fd_ != -1) + close (fd_); + return RSVC_SUCCESS; +} + +int +rsvcUdpClient::update (rsvcData& data) +{ + if (fd_ == -1) + return RSVC_ERROR; + + int nbytes; + int nw; + int status = RSVC_SUCCESS; + + rsvcCbk cbkid (RSVC_SET, (long)0, + (long)5678, (long)fd_); + // create netdata + rsvcNetData netdata (data, cbkid); + + if ((nbytes = streamData (netdata)) <= 0) + status = RSVC_ERROR; + else { + // block write + if ((nw = ::sendto (fd_, obuffer_, nbytes, 0, (sockaddr *)&udp_addr_, + sizeof (udp_addr_))) != nbytes) { +#ifdef _RSVC_DEBUG + printf ("rsvcUdpClient: wrote %d nbytes and expect to write %d bytes\n", + nw, nbytes); + printf ("rsvcUdpClient: errno is %d\n", errno); + perror ("client sendto error "); + // reset errno + errno = 0; +#endif + status = RSVC_ERROR; + } + } + return status; +} + +int +rsvcUdpClient::streamData (rsvcNetData& data) +{ + size_t datasize = data.streamSize (); + + if (datasize > sizeof (obuffer_)) { +#ifdef _RSVC_DEBUG + printf ("rsvcUdpClient: Streamed data size %d is exceeding %d, resize\n", + datasize, sizeof(obuffer_)); +#endif + return -1; + } + + if (data.streamOut (obuffer_, datasize) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcUdpClient: rsvcNetData stream out error\n"); +#endif + return -1; + } + return datasize; +} + +int +rsvcUdpClient::openUdpPort (char* host, unsigned short port) +{ + struct sockaddr_in my_addr; + struct hostent* hp = 0; + + // initialize the server inet address structure + ::memset (&udp_addr_, 0, sizeof (udp_addr_)); + udp_addr_.sin_family = AF_INET; + udp_addr_.sin_port = htons (port); + + hp = gethostbyname (host); + + if (hp == 0) { + fprintf (stderr, "rsvcUdpClient: Cannot find ip address of host %s\n", + host); + return -1; + } + ::memcpy (&udp_addr_.sin_addr, hp->h_addr, hp->h_length); + + // open a socket + if ((fd_ = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { + fprintf (stderr, "udp_open: cannot create socket\n"); + fd_ = -1; + return -1; + } + // bind local address for us + ::memset (&my_addr, 0, sizeof (my_addr)); + my_addr.sin_family = AF_INET; + my_addr.sin_addr.s_addr = htonl (INADDR_ANY); + my_addr.sin_port = htons (0); + + if (bind (fd_, (struct sockaddr *)&my_addr, sizeof (my_addr)) < 0) { + fprintf (stderr, "rsvcUdpClient : bind error\n"); + close (fd_); + fd_ = -1; + return -1; + } + return 0; +} + + + + + + + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcUdpClient.h b/extensions/cdevGenericServer/NameServer/src/rsvcUdpClient.h new file mode 100755 index 0000000..d5db6f3 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcUdpClient.h @@ -0,0 +1,69 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC UDP Client +// +// This is very limited, it only allows update to a single table +// Internal CEBAF use only +// +// Author: Jie Chen +// +// +// +// +#ifndef _RSVC_UDP_CLIENT_H +#define _RSVC_UDP_CLIENT_H + +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#else +#include +#include +#include +#include +#endif + +#include +#include +#include + +class RSVC_CLASS_SPEC rsvcUdpClient +{ +public: + // constructor + rsvcUdpClient (void); + ~rsvcUdpClient (void); + + int connect (char* host, unsigned short port); + + int update (rsvcData& data); + + int disconnect (void); + +private: + // stream a data object + int streamData (rsvcNetData& data); + + // open udp port + int openUdpPort (char* host, unsigned short port); + + // udp socket + struct sockaddr_in udp_addr_; + int fd_; + // data convertion buffer + char obuffer_[RSVC_UDP_BUFFER_SIZE]; +}; +#endif + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcUdpHandler.cc b/extensions/cdevGenericServer/NameServer/src/rsvcUdpHandler.cc new file mode 100755 index 0000000..08a1994 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcUdpHandler.cc @@ -0,0 +1,145 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of UDP handler of RSVC Server +// +// Author: Jie Chen +// +// Revision History: +// rsvcUdpHandler.cc,v +// Revision 1.1 1998/01/22 17:08:26 akers +// Addition of new NameServer +// +// +// +#include +#include +#include "rsvcUdpHandler.h" + +rsvcUdpHandler::rsvcUdpHandler (char* name, + cdevReactor& r, rsvcDataStoreTable& table) +:cdevEventHandler (), reactor_ (r), listener_ (), storeTable_ (table) +{ +#ifdef _TRACE_OBJECTS + printf (" Create rsvcUdpHandler Class Object\n"); +#endif + dbasename_ = new char[strlen (name) + 1]; + strcpy (dbasename_, name); +} + +rsvcUdpHandler::~rsvcUdpHandler (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete rsvcUdpHandler Class Object\n"); +#endif + + handleClose (); + delete []dbasename_; +} + +int +rsvcUdpHandler::open (unsigned short port, int async) +{ + cdevInetAddr addr (port); + + if (listener_.open (addr) == -1) + return -1; +#ifndef _WIN32 + else if (async && listener_.setFlags (SIGIO) == -1) + return -1; +#endif + else + return 0; +} + +unsigned short +rsvcUdpHandler::port_number (void) +{ + cdevInetAddr addr; + + listener_.getLocalAddress (addr); + + // host byte order + return addr.getPortNum (); +} + +int +rsvcUdpHandler::handleClose (void) +{ + return listener_.close (); +} + +int +rsvcUdpHandler::getHandle (void) const +{ + return listener_.getHandle (); +} + +int +rsvcUdpHandler::handleInput (void) +{ + cdevInetAddr sa; + rsvcNetData ndata; + int n; + int i = 0; + + if ((n = listener_.recv (ibuffer_, sizeof (ibuffer_), sa) < 0)) { +#ifdef _RSVC_DEBUG + printf ("rsvcUdpHandler: recv messge error with error number %d\n", errno); +#endif + return -1; + } + + size_t datasize; + i = 0; + + if (rsvcNetData::readHeader (ibuffer_, rsvcNetData::headerLen (), + &datasize) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcUdpHandler: This is not header\n"); +#endif + return -1; + } + if (datasize > sizeof (ibuffer_) - rsvcNetData::headerLen ()) { +#ifdef _RSVC_DEBUG + printf ("rsvcUdpHandler: incoming rsvcNetData is too big\n"); +#endif + return -1; + } + + // increase i by header len + i += rsvcNetData::headerLen (); + + if (ndata.streamIn (&(ibuffer_[i]), datasize) != RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcUdpHandler: rsvcNetData stream in error\n"); +#endif + return -1; + } + + // now we can call process function + rsvcDataStore* store = storeTable_.find (dbasename_); + if (store) { + rsvcNetData* backdata[1]; + size_t numdata = 0; + // put zero numdata to denote we do not want anything back + if (store->setValue (ndata, backdata, &numdata) == RSVC_SUCCESS) { +#ifdef _RSVC_DEBUG + printf ("rsvcUdpHandler: update server success\n"); +#endif + } + else + printf ("rsvcUdpHandler: update server failed\n"); + } + return 0; +} + + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcUdpHandler.h b/extensions/cdevGenericServer/NameServer/src/rsvcUdpHandler.h new file mode 100755 index 0000000..f5d1b0d --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcUdpHandler.h @@ -0,0 +1,68 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC UDP Service Handler (For managed servers only) +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_UDP_HANDLER_H +#define _RSVC_UDP_HANDLER_H + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + + +class rsvcUdpHandler : public cdevEventHandler +{ +public: + // constructor and destructor + + // constructor a UDP handler + rsvcUdpHandler (char* dbasename, cdevReactor& r, + rsvcDataStoreTable& st); + // destructor + ~rsvcUdpHandler (void); + + // open the listener of the udp + int open (unsigned short port, int async = 0); + + // return port number + unsigned short port_number (void); + +protected: + // inherited operations + int getHandle (void) const; + int handleClose (void); + int handleInput (void); + +private: + // data area + cdevReactor& reactor_; + cdevSocketDatagram listener_; + + // data conversion buffer + char ibuffer_[RSVC_UDP_BUFFER_SIZE]; + // data storage index table + rsvcDataStoreTable& storeTable_; + // database this udp to update to + char* dbasename_; +}; +#endif diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcVirtualDbase.cc b/extensions/cdevGenericServer/NameServer/src/rsvcVirtualDbase.cc new file mode 100755 index 0000000..6386f55 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcVirtualDbase.cc @@ -0,0 +1,94 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of rsvcVirtualDbase Class +// +// Author: Jie Chen +// +// Revision History: +// rsvcVirtualDbase.cc,v +// Revision 1.1 1998/01/22 17:08:26 akers +// Addition of new NameServer +// +// +// +#include "rsvcVirtualDbase.h" + +rsvcVirtualDbase::rsvcVirtualDbase (void) +:flag_ (0), mode_ (0), name_ (0), page_size_ (0), opened_ (0), + keyType_ (RSVC_STRING), err_ (-1) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcVirtualDbase Class\n"); +#endif + // empty +} + +rsvcVirtualDbase::rsvcVirtualDbase (char* name, int flags, + int keyType, + size_t data_size, + size_t cache_size, + size_t page_size, + int mode) +:flag_ (flags), mode_ (mode), page_size_ (0), + opened_ (0), keyType_ (keyType), err_ (-1) +{ +#ifdef _TRACE_OBJECTS + printf ("Create rsvcVirtualDbase Class\n"); +#endif + create (name, flags, keyType, data_size, cache_size, page_size, mode); +} + +rsvcVirtualDbase::~rsvcVirtualDbase (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete rsvcVirtualDbase Class\n"); +#endif + if (name_) + delete []name_; +} + +int +rsvcVirtualDbase::open (char* name, int flag, int keyType, + size_t /* cache_size */, + int mode) +{ + name_ = new char[strlen (name) + 1]; + strcpy (name_, name); + + err_ = 0; + flag_ = flag; + mode_ = mode; + keyType_ = keyType; + page_size_ = 4096; + opened_ = 1; + + return RSVC_SUCCESS; +} + +int +rsvcVirtualDbase::create (char* name, int flag, int keyType, + size_t /* data_size */, + size_t /* cache_size */, size_t /* page_size */, + int mode) +{ + name_ = new char[strlen (name) + 1]; + strcpy (name_, name); + + err_ = 0; + flag_ = flag; + mode_ = mode; + keyType_ = keyType; + page_size_ = 4096; + opened_ = 1; + + return RSVC_SUCCESS; +} + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvcVirtualDbase.h b/extensions/cdevGenericServer/NameServer/src/rsvcVirtualDbase.h new file mode 100755 index 0000000..4317427 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvcVirtualDbase.h @@ -0,0 +1,138 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC database interface +// +// Author: Jie Chen +// +// +// +// +#ifndef _RSVC_VIRTUAL_DATABASE_H +#define _RSVC_VIRTUAL_DATABASE_H + +#include +#include +#include +#include +#include +#include + +class rsvcVirtualDbase +{ +public: + // constructor + // default constructor, users have to call open explicitly + rsvcVirtualDbase (void); + + // constructor: name is a file name, flags are the same flags as + // standard open routine. + // data_size is estimate of each data stored in the database + rsvcVirtualDbase (char* name, int flags, int keyType = RSVC_STRING, + size_t data_size = 496, + size_t cache_size = 0, size_t page_size = 0, + int mode = 0666); + + // destructor + virtual ~rsvcVirtualDbase (void); + + // operation + + // open a database + virtual int open (char* name, int flags, int keyType = RSVC_STRING, + size_t cache_size = 0, + int mode = 0666); + // create a database + virtual int create (char* name, int flags, int keyType = RSVC_STRING, + size_t data_size = 496, + size_t cache_size = 0, size_t page_size = 0, + int mode = 0666); + + // close connection to the database + virtual int close (void) {return RSVC_SUCCESS;} + + // get a rsvcData. + virtual int get (rsvcData& /* data */, rsvcData& /* key */) {return RSVC_SUCCESS;} + // insert a rsvcData which must have a key inside + virtual int put (rsvcData& /* data */, rsvcData& /* key */) {return RSVC_SUCCESS;} + // delete a data object pointed by key value + virtual int del (rsvcData& /* key */) {return RSVC_SUCCESS;} + // flush all internal buffer to disk + virtual int flush (void) {return RSVC_SUCCESS;} + + // return database name + char* database (void) const {return name_;} + // return file descriptor for the opened database + virtual int fd (void) {return 0;} + // check to see the database is open or not + virtual int opened (void) const {return opened_;} + + // iterator for sequential access to database + virtual int cursorInit (void) {return RSVC_SUCCESS;} + + // set cursor to the position pointed by key 'key', + // and return data 'data' if successful + virtual int cursorSet (rsvcData& /* data */, rsvcData& /* key */) {return RSVC_SUCCESS;} + + // move cursor to the next position. + // return CDEV_SUCCESS on success, CDEV_ERROR: check errno + // return CDEV_INVALIDOBJ: no more + virtual int cursorNext (rsvcData& /* data */, rsvcData& /* key */) {return RSVC_SUCCESS;} + + // move cursor to the previous position + // return CDEV_SUCCESS on success, CDEV_ERROR: check errno + // return CDEV_INVALIDOBJ: no more + virtual int cursorPrev (rsvcData& /* data */, rsvcData& /* key */) {return RSVC_SUCCESS;} + + // merge current value pointed by cursor: + // this routine can only used to update the data with the same + // or smaller size than the exisiting data + // If you like to update arbitrary size of data, use del and put + virtual int cursorUpdate (rsvcData& /* data */) {return RSVC_SUCCESS;} + + // move cursor to the beginning of the database + // no need to provide key + virtual int cursorFirst (rsvcData& /* data */, rsvcData& /* key */) {return RSVC_SUCCESS;} + + // move cursor to the end of the database + // no need to provide key + virtual int cursorLast (rsvcData& /* data */, rsvcData& /* key */) {return RSVC_SUCCESS;} + + // close cursor operation + virtual int cursorFinish (void) {return RSVC_SUCCESS;} + + virtual const char* className (void) const {return "rsvcVirtualDbase";} + +protected: + // open flag and mode + int flag_; + int mode_; + // page size + size_t page_size_; + // database name + char* name_; + + // flag to tell whether this database is opened or not + int opened_; + + // key type of this database + int keyType_; + + // error status of open or create of this database + int err_; + + // deny access to copy and assignment operator + rsvcVirtualDbase (const rsvcVirtualDbase& dbase); + rsvcVirtualDbase& operator = (const rsvcVirtualDbase& dbase); +}; +#endif + + + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvc_logic.l b/extensions/cdevGenericServer/NameServer/src/rsvc_logic.l new file mode 100755 index 0000000..af93d8b --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvc_logic.l @@ -0,0 +1,151 @@ +/*---------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// Description: +// Lexer for rsvc logic expression +// +// Author: jie chen +// +// +// +//---------------------------------------------------------------------------*/ + +%{ +#include +#include +#include + +#if defined (__VMS) +/* Assume we are using BISON as our yacc compiler if this is a VMS platform.*/ +#define _BISON_YACC +#endif + +#ifdef _BISON_YACC +/* When using gnu bison, bison produces ns_tab.c, not y.tab.h. + (also, can't have two periods in a filename under VMS). */ +#include "rsvc_logic_tab.c" +#else +#include "y.tab.h" +#endif + +static char *_logic_input_text = 0; + +void +set_input_text (char* text) +{ + _logic_input_text = text; +} + +#ifdef FLEX_SCANNER +/* Flex defines yywrap() as a macro by default. + We define it below (in rsvc_logic) as a function, so we must undefine it + here first. */ +#ifdef yywrap +#undef yywrap +#endif + +/* The flex manual states that the flex implementation does not permit + input() to be redefined. This is because input() in FLEX is a function, + not a macro. + + The flex manual also states that the proper thing to do in flex is + redefine the macro YY_INPUT, which is what we do below. + + unput() is also a function in flex, but since we are now using + YYINPUT(), hopefully unput() will work correctly. */ + +#ifdef YY_INPUT +#undef YY_INPUT +#endif +#define YY_INPUT(buf,result,max_size) { \ + int text_left = strlen(_logic_input_text) ; /* get length of input. */ \ + (result) = ((max_size)" {return GREATER; } +"!=" {return NOTEQUAL; } +"<=" {return LESSOREQUAL;} +">=" {return GREATEROREQUAL;} +"(" {return LEFTP;} +")" {return RIGHTP;} +"||" {return OR;} +"&&" {return AND;} +"!" {return NOT;} +"like" {return LIKE;} +{intnum} {yylval.data = new_logic_data (); + logic_data_assign_int (yylval.data, atoi (yytext)); + return IVALUE; + } +{fnum} {yylval.data = new_logic_data (); + logic_data_assign_dbl (yylval.data, atof (yytext)); + return DVALUE; + } +{tagname} {yylval.data = new_logic_data (); + logic_data_assign_str (yylval.data, yytext); + return TAGNAME; } +{cstring} {yylval.data = new_logic_data (); + logic_data_assign_str (yylval.data, yytext + 1); + if (yylval.data->u.string[yyleng - 2] != '\'') { + printf ("Unterminated char string %s\n", yytext); + return CERROR; + } + else + yylval.data->u.string[yyleng - 2] = '\0'; + return CSTRING; + } + +[ \t] ; +. {fprintf(stdout,"unrecognized char %02x\n",yytext[0]);} +%% + +#ifdef __cplusplus +void yyerror() +#elif defined(_BISON_YACC) +/* BISON produces calls to a yyerror function that takes a single char *. + Since yyerror is not previously declared, the compiler assumes that + yyerror must be of type "int yyerror( char * c )" */ +int yyerror( char * c ) +#else +yyerror() +#endif +{ + fprintf(stderr, "syntax error for logical expression\n"); +} + +#if defined(__cplusplus) +int yywrap(void) +#else +yywrap() +#endif +{ + return EOF; +} + diff --git a/extensions/cdevGenericServer/NameServer/src/rsvc_logic.y b/extensions/cdevGenericServer/NameServer/src/rsvc_logic.y new file mode 100755 index 0000000..75b6716 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/rsvc_logic.y @@ -0,0 +1,151 @@ +%{ + +/*---------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// Description: +// Parser rsvc logic expression +// +// Author: Jie Chen +// +// Revision History: +// rsvc_logic.y,v +// Revision 1.2 1998/01/23 13:50:10 akers +// Ongoing development +// + * Revision 1.1 1998/01/22 17:08:28 akers + * Addition of new NameServer + * +// +//---------------------------------------------------------------------------*/ + +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include +#include + +#ifdef __VMS +/* VMS does not have unlink but it does have the function remove(). + Note that remove() may not be able to delete directory files . */ +#define unlink(tmp) (remove((tmp))) +#endif + +%} + +%union { + rsvc_logic_data* data; + rsvcLogicInst* inst; +} + +%token TAGNAME, CSTRING, DVALUE, IVALUE +%token EQUAL, LESS, GREATER, NOTEQUAL +%token LESSOREQUAL, GREATEROREQUAL +%token LEFTP, RIGHTP, OR, AND, LIKE, NOT, CERROR +%type logic_exp, rsvc_logic + +%left OR +%left AND +%left NOT +%left EQUAL LESS GREATER NOTEQUAL LESSOREQUAL GREATEROREQUAL LIKE + +%% +rsvc_logic_parse: rsvc_logic {logic_code (rsvc_logic_end); + logic_code (RSVC_LOGIC_STOP); + } + +rsvc_logic: logic_exp { } + | rsvc_logic AND rsvc_logic {logic_code (rsvc_logic_and);} + | rsvc_logic OR rsvc_logic {logic_code (rsvc_logic_or);} + | NOT rsvc_logic {logic_code (rsvc_logic_neg);} + | LEFTP rsvc_logic RIGHTP {} + ; + +logic_exp: TAGNAME EQUAL IVALUE {logic_code (logic_val_push); + logic_code ((rsvcLogicInst)$1); + logic_code ((rsvcLogicInst)$3); + logic_code (rsvc_data_equal_int); + } + | TAGNAME EQUAL DVALUE {logic_code (logic_val_push); + logic_code ((rsvcLogicInst)$1); + logic_code ((rsvcLogicInst)$3); + logic_code (rsvc_data_equal_dbl); + } + | TAGNAME EQUAL CSTRING {logic_code (logic_val_push); + logic_code ((rsvcLogicInst)$1); + logic_code ((rsvcLogicInst)$3); + logic_code (rsvc_data_equal_str); + } + | TAGNAME LESS IVALUE {logic_code (logic_val_push); + logic_code ((rsvcLogicInst)$1); + logic_code ((rsvcLogicInst)$3); + logic_code (rsvc_data_less_int); + } + | TAGNAME LESS DVALUE {logic_code (logic_val_push); + logic_code ((rsvcLogicInst)$1); + logic_code ((rsvcLogicInst)$3); + logic_code (rsvc_data_less_dbl); + } + + | TAGNAME GREATER IVALUE {logic_code (logic_val_push); + logic_code ((rsvcLogicInst)$1); + logic_code ((rsvcLogicInst)$3); + logic_code (rsvc_data_greater_int); + } + | TAGNAME GREATER DVALUE {logic_code (logic_val_push); + logic_code ((rsvcLogicInst)$1); + logic_code ((rsvcLogicInst)$3); + logic_code (rsvc_data_greater_dbl); + } + | TAGNAME LESSOREQUAL IVALUE{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)$1); + logic_code ((rsvcLogicInst)$3); + logic_code (rsvc_data_lesseq_int); + } + | TAGNAME LESSOREQUAL DVALUE{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)$1); + logic_code ((rsvcLogicInst)$3); + logic_code (rsvc_data_lesseq_dbl); + } + | TAGNAME GREATEROREQUAL IVALUE{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)$1); + logic_code ((rsvcLogicInst)$3); + logic_code (rsvc_data_greatereq_int); + } + | TAGNAME GREATEROREQUAL DVALUE{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)$1); + logic_code ((rsvcLogicInst)$3); + logic_code (rsvc_data_greatereq_dbl); + } + | TAGNAME NOTEQUAL IVALUE{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)$1); + logic_code ((rsvcLogicInst)$3); + logic_code (rsvc_data_noequal_int); + } + | TAGNAME NOTEQUAL DVALUE{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)$1); + logic_code ((rsvcLogicInst)$3); + logic_code (rsvc_data_noequal_dbl); + } + | TAGNAME NOTEQUAL CSTRING{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)$1); + logic_code ((rsvcLogicInst)$3); + logic_code (rsvc_data_noequal_str); + } + | TAGNAME LIKE CSTRING {logic_code (logic_val_push); + logic_code ((rsvcLogicInst)$1); + logic_code ((rsvcLogicInst)$3); + logic_code (rsvc_data_has_str); + } + ; +%% diff --git a/extensions/cdevGenericServer/NameServer/src/y.tab.c b/extensions/cdevGenericServer/NameServer/src/y.tab.c new file mode 100644 index 0000000..bb6416e --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/y.tab.c @@ -0,0 +1,641 @@ +#ifndef lint +static char const +yyrcsid[] = "$FreeBSD: src/usr.bin/yacc/skeleton.c,v 1.28 2000/01/17 02:04:06 bde Exp $"; +#endif +#include +#define YYBYACC 1 +#define YYMAJOR 1 +#define YYMINOR 9 +#define YYLEX yylex() +#define YYEMPTY -1 +#define yyclearin (yychar=(YYEMPTY)) +#define yyerrok (yyerrflag=0) +#define YYRECOVERING() (yyerrflag!=0) +static int yygrowstack(); +#define YYPREFIX "yy" +#line 2 "rsvc_logic.y" + +/*---------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// Description: +// Parser rsvc logic expression +// +// Author: Jie Chen +// +// Revision History: +// rsvc_logic.y,v +// Revision 1.2 1998/01/23 13:50:10 akers +// Ongoing development +// + * Revision 1.1 1998/01/22 17:08:28 akers + * Addition of new NameServer + * +// +//---------------------------------------------------------------------------*/ + +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include +#include + +#ifdef __VMS +/* VMS does not have unlink but it does have the function remove(). + Note that remove() may not be able to delete directory files . */ +#define unlink(tmp) (remove((tmp))) +#endif + +#line 46 "rsvc_logic.y" +typedef union { + rsvc_logic_data* data; + rsvcLogicInst* inst; +} YYSTYPE; +#line 65 "y.tab.c" +#define YYERRCODE 256 +#define TAGNAME 257 +#define CSTRING 258 +#define DVALUE 259 +#define IVALUE 260 +#define EQUAL 261 +#define LESS 262 +#define GREATER 263 +#define NOTEQUAL 264 +#define LESSOREQUAL 265 +#define GREATEROREQUAL 266 +#define LEFTP 267 +#define RIGHTP 268 +#define OR 269 +#define AND 270 +#define LIKE 271 +#define NOT 272 +#define CERROR 273 +const short yylhs[] = { -1, + 0, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, +}; +const short yylen[] = { 2, + 1, 1, 3, 3, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, +}; +const short yydefred[] = { 0, + 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 9, 8, 7, + 11, 10, 13, 12, 20, 19, 18, 15, 14, 17, + 16, 21, 6, 0, 3, +}; +const short yydgoto[] = { 4, + 5, 6, +}; +const short yysindex[] = { -257, + -241, -257, -257, 0, 0, -267, -252, -243, -228, -247, + -226, -224, -249, -242, 0, -257, -257, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -256, 0, +}; +const short yyrindex[] = { 0, + 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, +}; +const short yygindex[] = { 0, + 0, 2, +}; +#define YYTABLESIZE 270 +const short yytable[] = { 1, + 4, 16, 17, 14, 15, 18, 19, 20, 32, 2, + 25, 26, 27, 17, 3, 21, 22, 34, 35, 7, + 8, 9, 10, 11, 12, 33, 16, 17, 1, 13, + 23, 24, 28, 29, 30, 31, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, +}; +const short yycheck[] = { 257, + 0, 269, 270, 2, 3, 258, 259, 260, 258, 267, + 258, 259, 260, 270, 272, 259, 260, 16, 17, 261, + 262, 263, 264, 265, 266, 268, 269, 270, 0, 271, + 259, 260, 259, 260, 259, 260, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 268, 269, +}; +#define YYFINAL 4 +#ifndef YYDEBUG +#define YYDEBUG 0 +#endif +#define YYMAXTOKEN 273 +#if YYDEBUG +const char * const yyname[] = { +"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"TAGNAME","CSTRING","DVALUE", +"IVALUE","EQUAL","LESS","GREATER","NOTEQUAL","LESSOREQUAL","GREATEROREQUAL", +"LEFTP","RIGHTP","OR","AND","LIKE","NOT","CERROR", +}; +const char * const yyrule[] = { +"$accept : rsvc_logic_parse", +"rsvc_logic_parse : rsvc_logic", +"rsvc_logic : logic_exp", +"rsvc_logic : rsvc_logic AND rsvc_logic", +"rsvc_logic : rsvc_logic OR rsvc_logic", +"rsvc_logic : NOT rsvc_logic", +"rsvc_logic : LEFTP rsvc_logic RIGHTP", +"logic_exp : TAGNAME EQUAL IVALUE", +"logic_exp : TAGNAME EQUAL DVALUE", +"logic_exp : TAGNAME EQUAL CSTRING", +"logic_exp : TAGNAME LESS IVALUE", +"logic_exp : TAGNAME LESS DVALUE", +"logic_exp : TAGNAME GREATER IVALUE", +"logic_exp : TAGNAME GREATER DVALUE", +"logic_exp : TAGNAME LESSOREQUAL IVALUE", +"logic_exp : TAGNAME LESSOREQUAL DVALUE", +"logic_exp : TAGNAME GREATEROREQUAL IVALUE", +"logic_exp : TAGNAME GREATEROREQUAL DVALUE", +"logic_exp : TAGNAME NOTEQUAL IVALUE", +"logic_exp : TAGNAME NOTEQUAL DVALUE", +"logic_exp : TAGNAME NOTEQUAL CSTRING", +"logic_exp : TAGNAME LIKE CSTRING", +}; +#endif +#if YYDEBUG +#include +#endif +#ifdef YYSTACKSIZE +#undef YYMAXDEPTH +#define YYMAXDEPTH YYSTACKSIZE +#else +#ifdef YYMAXDEPTH +#define YYSTACKSIZE YYMAXDEPTH +#else +#define YYSTACKSIZE 10000 +#define YYMAXDEPTH 10000 +#endif +#endif +#define YYINITSTACKSIZE 200 +int yydebug; +int yynerrs; +int yyerrflag; +int yychar; +short *yyssp; +YYSTYPE *yyvsp; +YYSTYPE yyval; +YYSTYPE yylval; +short *yyss; +short *yysslim; +YYSTYPE *yyvs; +int yystacksize; +/* allocate initial stack or double stack size, up to YYMAXDEPTH */ +static int yygrowstack() +{ + int newsize, i; + short *newss; + YYSTYPE *newvs; + + if ((newsize = yystacksize) == 0) + newsize = YYINITSTACKSIZE; + else if (newsize >= YYMAXDEPTH) + return -1; + else if ((newsize *= 2) > YYMAXDEPTH) + newsize = YYMAXDEPTH; + i = yyssp - yyss; + newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) : + (short *)malloc(newsize * sizeof *newss); + if (newss == NULL) + return -1; + yyss = newss; + yyssp = newss + i; + newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) : + (YYSTYPE *)malloc(newsize * sizeof *newvs); + if (newvs == NULL) + return -1; + yyvs = newvs; + yyvsp = newvs + i; + yystacksize = newsize; + yysslim = yyss + newsize - 1; + return 0; +} + +#define YYABORT goto yyabort +#define YYREJECT goto yyabort +#define YYACCEPT goto yyaccept +#define YYERROR goto yyerrlab + +#ifndef YYPARSE_PARAM +#if defined(__cplusplus) || __STDC__ +#define YYPARSE_PARAM_ARG void +#define YYPARSE_PARAM_DECL +#else /* ! ANSI-C/C++ */ +#define YYPARSE_PARAM_ARG +#define YYPARSE_PARAM_DECL +#endif /* ANSI-C/C++ */ +#else /* YYPARSE_PARAM */ +#ifndef YYPARSE_PARAM_TYPE +#define YYPARSE_PARAM_TYPE void * +#endif +#if defined(__cplusplus) || __STDC__ +#define YYPARSE_PARAM_ARG YYPARSE_PARAM_TYPE YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#else /* ! ANSI-C/C++ */ +#define YYPARSE_PARAM_ARG YYPARSE_PARAM +#define YYPARSE_PARAM_DECL YYPARSE_PARAM_TYPE YYPARSE_PARAM; +#endif /* ANSI-C/C++ */ +#endif /* ! YYPARSE_PARAM */ + +int +yyparse (YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + register int yym, yyn, yystate; +#if YYDEBUG + register const char *yys; + + if ((yys = getenv("YYDEBUG"))) + { + yyn = *yys; + if (yyn >= '0' && yyn <= '9') + yydebug = yyn - '0'; + } +#endif + + yynerrs = 0; + yyerrflag = 0; + yychar = (-1); + + if (yyss == NULL && yygrowstack()) goto yyoverflow; + yyssp = yyss; + yyvsp = yyvs; + *yyssp = yystate = 0; + +yyloop: + if ((yyn = yydefred[yystate])) goto yyreduce; + if (yychar < 0) + { + if ((yychar = yylex()) < 0) yychar = 0; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("%sdebug: state %d, reading %d (%s)\n", + YYPREFIX, yystate, yychar, yys); + } +#endif + } + if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, shifting to state %d\n", + YYPREFIX, yystate, yytable[yyn]); +#endif + if (yyssp >= yysslim && yygrowstack()) + { + goto yyoverflow; + } + *++yyssp = yystate = yytable[yyn]; + *++yyvsp = yylval; + yychar = (-1); + if (yyerrflag > 0) --yyerrflag; + goto yyloop; + } + if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) + { + yyn = yytable[yyn]; + goto yyreduce; + } + if (yyerrflag) goto yyinrecovery; +#if defined(lint) || defined(__GNUC__) + goto yynewerror; +#endif +yynewerror: + yyerror("syntax error"); +#if defined(lint) || defined(__GNUC__) + goto yyerrlab; +#endif +yyerrlab: + ++yynerrs; +yyinrecovery: + if (yyerrflag < 3) + { + yyerrflag = 3; + for (;;) + { + if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, error recovery shifting\ + to state %d\n", YYPREFIX, *yyssp, yytable[yyn]); +#endif + if (yyssp >= yysslim && yygrowstack()) + { + goto yyoverflow; + } + *++yyssp = yystate = yytable[yyn]; + *++yyvsp = yylval; + goto yyloop; + } + else + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: error recovery discarding state %d\n", + YYPREFIX, *yyssp); +#endif + if (yyssp <= yyss) goto yyabort; + --yyssp; + --yyvsp; + } + } + } + else + { + if (yychar == 0) goto yyabort; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("%sdebug: state %d, error recovery discards token %d (%s)\n", + YYPREFIX, yystate, yychar, yys); + } +#endif + yychar = (-1); + goto yyloop; + } +yyreduce: +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, reducing by rule %d (%s)\n", + YYPREFIX, yystate, yyn, yyrule[yyn]); +#endif + yym = yylen[yyn]; + yyval = yyvsp[1-yym]; + switch (yyn) + { +case 1: +#line 63 "rsvc_logic.y" +{logic_code (rsvc_logic_end); + logic_code (RSVC_LOGIC_STOP); + } +break; +case 2: +#line 67 "rsvc_logic.y" +{ } +break; +case 3: +#line 68 "rsvc_logic.y" +{logic_code (rsvc_logic_and);} +break; +case 4: +#line 69 "rsvc_logic.y" +{logic_code (rsvc_logic_or);} +break; +case 5: +#line 70 "rsvc_logic.y" +{logic_code (rsvc_logic_neg);} +break; +case 6: +#line 71 "rsvc_logic.y" +{} +break; +case 7: +#line 74 "rsvc_logic.y" +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_equal_int); + } +break; +case 8: +#line 79 "rsvc_logic.y" +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_equal_dbl); + } +break; +case 9: +#line 84 "rsvc_logic.y" +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_equal_str); + } +break; +case 10: +#line 89 "rsvc_logic.y" +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_less_int); + } +break; +case 11: +#line 94 "rsvc_logic.y" +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_less_dbl); + } +break; +case 12: +#line 100 "rsvc_logic.y" +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_greater_int); + } +break; +case 13: +#line 105 "rsvc_logic.y" +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_greater_dbl); + } +break; +case 14: +#line 110 "rsvc_logic.y" +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_lesseq_int); + } +break; +case 15: +#line 115 "rsvc_logic.y" +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_lesseq_dbl); + } +break; +case 16: +#line 120 "rsvc_logic.y" +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_greatereq_int); + } +break; +case 17: +#line 125 "rsvc_logic.y" +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_greatereq_dbl); + } +break; +case 18: +#line 130 "rsvc_logic.y" +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_noequal_int); + } +break; +case 19: +#line 135 "rsvc_logic.y" +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_noequal_dbl); + } +break; +case 20: +#line 140 "rsvc_logic.y" +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_noequal_str); + } +break; +case 21: +#line 145 "rsvc_logic.y" +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_has_str); + } +break; +#line 586 "y.tab.c" + } + yyssp -= yym; + yystate = *yyssp; + yyvsp -= yym; + yym = yylhs[yyn]; + if (yystate == 0 && yym == 0) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: after reduction, shifting from state 0 to\ + state %d\n", YYPREFIX, YYFINAL); +#endif + yystate = YYFINAL; + *++yyssp = YYFINAL; + *++yyvsp = yyval; + if (yychar < 0) + { + if ((yychar = yylex()) < 0) yychar = 0; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("%sdebug: state %d, reading %d (%s)\n", + YYPREFIX, YYFINAL, yychar, yys); + } +#endif + } + if (yychar == 0) goto yyaccept; + goto yyloop; + } + if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yystate) + yystate = yytable[yyn]; + else + yystate = yydgoto[yym]; +#if YYDEBUG + if (yydebug) + printf("%sdebug: after reduction, shifting from state %d \ +to state %d\n", YYPREFIX, *yyssp, yystate); +#endif + if (yyssp >= yysslim && yygrowstack()) + { + goto yyoverflow; + } + *++yyssp = yystate; + *++yyvsp = yyval; + goto yyloop; +yyoverflow: + yyerror("yacc stack overflow"); +yyabort: + return (1); +yyaccept: + return (0); +} diff --git a/extensions/cdevGenericServer/NameServer/src/y.tab.h b/extensions/cdevGenericServer/NameServer/src/y.tab.h new file mode 100644 index 0000000..66a731a --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/y.tab.h @@ -0,0 +1,26 @@ +#ifndef YYERRCODE +#define YYERRCODE 256 +#endif + +#define TAGNAME 257 +#define CSTRING 258 +#define DVALUE 259 +#define IVALUE 260 +#define EQUAL 261 +#define LESS 262 +#define GREATER 263 +#define NOTEQUAL 264 +#define LESSOREQUAL 265 +#define GREATEROREQUAL 266 +#define LEFTP 267 +#define RIGHTP 268 +#define OR 269 +#define AND 270 +#define LIKE 271 +#define NOT 272 +#define CERROR 273 +typedef union { + rsvc_logic_data* data; + rsvcLogicInst* inst; +} YYSTYPE; +extern YYSTYPE yylval; diff --git a/extensions/cdevGenericServer/NameServer/src/yacc-nt.c b/extensions/cdevGenericServer/NameServer/src/yacc-nt.c new file mode 100644 index 0000000..ae05524 --- /dev/null +++ b/extensions/cdevGenericServer/NameServer/src/yacc-nt.c @@ -0,0 +1,659 @@ +#if defined(__STDC__) || defined(__cplusplus) +#define YYCONST const +#define YYPARAMS(x) x +#define YYDEFUN(name, arglist, args) name(args) +#define YYAND , +#define YYPTR void * +#else +#define YYCONST +#define YYPARAMS(x) () +#define YYDEFUN(name, arglist, args) name arglist args; +#define YYAND ; +#define YYPTR char * +#endif +#ifndef lint +YYCONST static char yysccsid[] = "@(#)yaccpar 1.8 (Berkeley +Cygnus.28) 01/20/91"; +#endif +#define YYBYACC 1 +#ifndef YYDONT_INCLUDE_STDIO +#include +#endif +#ifdef __cplusplus +#include /* for malloc/realloc/free */ +#endif + +/*---------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// Description: +// Parser rsvc logic expression +// +// Author: Jie Chen +// +// Revision History: +// rsvc_logic.y,v +// Revision 1.2 1998/01/23 13:50:10 akers +// Ongoing development +// + * Revision 1.1 1998/01/22 17:08:28 akers + * Addition of new NameServer + * +// +//---------------------------------------------------------------------------*/ + +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include +#include + +#ifdef __VMS +/* VMS does not have unlink but it does have the function remove(). + Note that remove() may not be able to delete directory files . */ +#define unlink(tmp) (remove((tmp))) +#endif + +typedef union { + rsvc_logic_data* data; + rsvcLogicInst* inst; +} YYSTYPE; +#define TAGNAME 257 +#define CSTRING 258 +#define DVALUE 259 +#define IVALUE 260 +#define EQUAL 261 +#define LESS 262 +#define GREATER 263 +#define NOTEQUAL 264 +#define LESSOREQUAL 265 +#define GREATEROREQUAL 266 +#define LEFTP 267 +#define RIGHTP 268 +#define OR 269 +#define AND 270 +#define LIKE 271 +#define NOT 272 +#define CERROR 273 +#define YYERRCODE 256 +static YYCONST short yylhs[] = { -1, + 0, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, +}; +static YYCONST short yylen[] = { 2, + 1, 1, 3, 3, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, +}; +static YYCONST short yydefred[] = { 0, + 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 9, 8, 7, + 11, 10, 13, 12, 20, 19, 18, 15, 14, 17, + 16, 21, 6, 0, 3, +}; +static YYCONST short yydgoto[] = { 4, + 5, 6, +}; +static YYCONST short yysindex[] = { -257, + -241, -257, -257, 0, 0, -267, -252, -243, -228, -247, + -226, -224, -249, -242, 0, -257, -257, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -256, 0, +}; +static YYCONST short yyrindex[] = { 0, + 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, +}; +static YYCONST short yygindex[] = { 0, + 0, 2, +}; +#define YYTABLESIZE 270 +static YYCONST short yytable[] = { 1, + 4, 16, 17, 14, 15, 18, 19, 20, 32, 2, + 25, 26, 27, 17, 3, 21, 22, 34, 35, 7, + 8, 9, 10, 11, 12, 33, 16, 17, 1, 13, + 23, 24, 28, 29, 30, 31, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, +}; +static YYCONST short yycheck[] = { 257, + 0, 269, 270, 2, 3, 258, 259, 260, 258, 267, + 258, 259, 260, 270, 272, 259, 260, 16, 17, 261, + 262, 263, 264, 265, 266, 268, 269, 270, 0, 271, + 259, 260, 259, 260, 259, 260, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 268, 269, +}; +#define YYFINAL 4 +#ifndef YYDEBUG +#define YYDEBUG 0 +#endif +#define YYMAXTOKEN 273 +#if YYDEBUG +static YYCONST char *YYCONST yyname[] = { +"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"TAGNAME","CSTRING","DVALUE", +"IVALUE","EQUAL","LESS","GREATER","NOTEQUAL","LESSOREQUAL","GREATEROREQUAL", +"LEFTP","RIGHTP","OR","AND","LIKE","NOT","CERROR", +}; +static YYCONST char *YYCONST yyrule[] = { +"$accept : rsvc_logic_parse", +"rsvc_logic_parse : rsvc_logic", +"rsvc_logic : logic_exp", +"rsvc_logic : rsvc_logic AND rsvc_logic", +"rsvc_logic : rsvc_logic OR rsvc_logic", +"rsvc_logic : NOT rsvc_logic", +"rsvc_logic : LEFTP rsvc_logic RIGHTP", +"logic_exp : TAGNAME EQUAL IVALUE", +"logic_exp : TAGNAME EQUAL DVALUE", +"logic_exp : TAGNAME EQUAL CSTRING", +"logic_exp : TAGNAME LESS IVALUE", +"logic_exp : TAGNAME LESS DVALUE", +"logic_exp : TAGNAME GREATER IVALUE", +"logic_exp : TAGNAME GREATER DVALUE", +"logic_exp : TAGNAME LESSOREQUAL IVALUE", +"logic_exp : TAGNAME LESSOREQUAL DVALUE", +"logic_exp : TAGNAME GREATEROREQUAL IVALUE", +"logic_exp : TAGNAME GREATEROREQUAL DVALUE", +"logic_exp : TAGNAME NOTEQUAL IVALUE", +"logic_exp : TAGNAME NOTEQUAL DVALUE", +"logic_exp : TAGNAME NOTEQUAL CSTRING", +"logic_exp : TAGNAME LIKE CSTRING", +}; +#endif +#define YYLEX yylex() +#define YYEMPTY -1 +#define yyclearin (yychar=(YYEMPTY)) +#define yyerrok (yyerrflag=0) +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif +#ifdef YYSTACKSIZE +#ifndef YYMAXDEPTH +#define YYMAXDEPTH YYSTACKSIZE +#endif +#else +#ifdef YYMAXDEPTH +#define YYSTACKSIZE YYMAXDEPTH +#else +#define YYSTACKSIZE 500 +#define YYMAXDEPTH 500 +#endif +#endif +#ifndef YYMAXSTACKSIZE +#define YYMAXSTACKSIZE 10000 +#endif +int yydebug; +int yynerrs; +int yyerrflag; +int yychar; +YYSTYPE yyval; +YYSTYPE yylval; +static short *yyss; +static YYSTYPE *yyvs; +static int yystacksize; +#define yyfree(x) free(x) +extern int yylex(); + +static YYPTR +YYDEFUN (yymalloc, (bytes), unsigned bytes) +{ + YYPTR ptr = (YYPTR) malloc (bytes); + if (ptr != 0) return (ptr); + yyerror ("yyparse: memory exhausted"); + return (0); +} + +static YYPTR +YYDEFUN (yyrealloc, (old, bytes), YYPTR old YYAND unsigned bytes) +{ + YYPTR ptr = (YYPTR) realloc (old, bytes); + if (ptr != 0) return (ptr); + yyerror ("yyparse: memory exhausted"); + return (0); +} + +static int +#ifdef __GNUC__ +__inline__ +#endif +yygrow () +{ + int old_stacksize = yystacksize; + short *new_yyss; + YYSTYPE *new_yyvs; + + if (yystacksize == YYMAXSTACKSIZE) + return (1); + yystacksize += (yystacksize + 1 ) / 2; + if (yystacksize > YYMAXSTACKSIZE) + yystacksize = YYMAXSTACKSIZE; +#if YYDEBUG + if (yydebug) + printf("yydebug: growing stack size from %d to %d\n", + old_stacksize, yystacksize); +#endif + new_yyss = (short *) yyrealloc ((char *)yyss, yystacksize * sizeof (short)); + if (new_yyss == 0) + return (1); + new_yyvs = (YYSTYPE *) yyrealloc ((char *)yyvs, yystacksize * sizeof (YYSTYPE)); + if (new_yyvs == 0) + { + yyfree (new_yyss); + return (1); + } + yyss = new_yyss; + yyvs = new_yyvs; + return (0); +} +#define YYABORT goto yyabort +#define YYACCEPT goto yyaccept +#define YYERROR goto yyerrlab + +#if YYDEBUG +#ifdef __cplusplus +extern "C" char *getenv(); +#else +extern char *getenv(); +#endif +#endif + +int +yyparse() +{ + register int yym, yyn, yystate; + register YYSTYPE *yyvsp; + register short *yyssp; + short *yysse; +#if YYDEBUG + register YYCONST char *yys; + + if (yys = getenv("YYDEBUG")) + { + yyn = *yys; + if (yyn >= '0' && yyn <= '9') + yydebug = yyn - '0'; + } +#endif + + yynerrs = 0; + yyerrflag = 0; + yychar = (-1); + + if (yyss == 0) + { + yyss = (short *) yymalloc (YYSTACKSIZE * sizeof (short)); + if (yyss == 0) + goto yyabort; + yyvs = (YYSTYPE *) yymalloc (YYSTACKSIZE * sizeof (YYSTYPE)); + if (yyvs == 0) + { + yyfree (yyss); + goto yyabort; + } + yystacksize = YYSTACKSIZE; + } + yysse = yyss + yystacksize - 1; + yyssp = yyss; + yyvsp = yyvs; + *yyssp = yystate = 0; + goto yyloop; + +yypush_lex: + yyval = yylval; + yystate = yytable[yyn]; +yypush: + if (yyssp >= yysse) + { + int depth = yyssp - yyss; + if (yygrow() != 0) + goto yyoverflow; + yysse = yyss + yystacksize -1; + yyssp = depth + yyss; + yyvsp = depth + yyvs; + } + *++yyssp = yystate; + *++yyvsp = yyval; + +yyloop: + if (yyn = yydefred[yystate]) goto yyreduce; + yyn = yysindex[yystate]; + if (yychar < 0) + { + if ((yychar = yylex()) < 0) yychar = 0; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("yydebug: state %d, reading %d (%s)\n", yystate, + yychar, yys); + } +#endif + } + if (yyn != 0 + && ((yyn += yychar), ((unsigned)yyn <= (unsigned)YYTABLESIZE)) + && yycheck[yyn] == yychar) + { +#if YYDEBUG + if (yydebug) + printf("yydebug: state %d, shifting to state %d\n", + yystate, yytable[yyn]); +#endif + if (yyerrflag > 0) --yyerrflag; + yychar = (-1); + goto yypush_lex; + } + yyn = yyrindex[yystate]; + if (yyn != 0 + && ((yyn += yychar), ((unsigned)yyn <= (unsigned)YYTABLESIZE)) + && yycheck[yyn] == yychar) + { + yyn = yytable[yyn]; + goto yyreduce; + } + if (yyerrflag) goto yyinrecovery; +#ifdef lint + goto yynewerror; +#endif +yynewerror: + yyerror("syntax error"); +#ifdef lint + goto yyerrlab; +#endif +yyerrlab: + ++yynerrs; +yyinrecovery: + if (yyerrflag < 3) + { + yyerrflag = 3; + for (;;) + { + yyn = yysindex[*yyssp]; + if (yyn != 0 + && ((yyn += YYERRCODE), ((unsigned)yyn <= (unsigned)YYTABLESIZE)) + && yycheck[yyn] == YYERRCODE) + { +#if YYDEBUG + if (yydebug) + printf("yydebug: state %d, error recovery shifting\ + to state %d\n", *yyssp, yytable[yyn]); +#endif + goto yypush_lex; + } + else + { +#if YYDEBUG + if (yydebug) + printf("yydebug: error recovery discarding state %d\n", + *yyssp); +#endif + if (yyssp <= yyss) goto yyabort; + --yyssp; + --yyvsp; + } + } + } + else + { + if (yychar == 0) goto yyabort; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("yydebug: state %d, error recovery discards token %d (%s)\n", + yystate, yychar, yys); + } +#endif + yychar = (-1); + goto yyloop; + } +yyreduce: +#if YYDEBUG + if (yydebug) + printf("yydebug: state %d, reducing by rule %d (%s)\n", + yystate, yyn, yyrule[yyn]); +#endif + yym = yylen[yyn]; + yyval = yyvsp[1-yym]; + switch (yyn) + { +case 1: +{logic_code (rsvc_logic_end); + logic_code (RSVC_LOGIC_STOP); + } +break; +case 2: +{ } +break; +case 3: +{logic_code (rsvc_logic_and);} +break; +case 4: +{logic_code (rsvc_logic_or);} +break; +case 5: +{logic_code (rsvc_logic_neg);} +break; +case 6: +{} +break; +case 7: +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_equal_int); + } +break; +case 8: +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_equal_dbl); + } +break; +case 9: +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_equal_str); + } +break; +case 10: +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_less_int); + } +break; +case 11: +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_less_dbl); + } +break; +case 12: +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_greater_int); + } +break; +case 13: +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_greater_dbl); + } +break; +case 14: +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_lesseq_int); + } +break; +case 15: +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_lesseq_dbl); + } +break; +case 16: +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_greatereq_int); + } +break; +case 17: +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_greatereq_dbl); + } +break; +case 18: +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_noequal_int); + } +break; +case 19: +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_noequal_dbl); + } +break; +case 20: +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_noequal_str); + } +break; +case 21: +{logic_code (logic_val_push); + logic_code ((rsvcLogicInst)yyvsp[-2].data); + logic_code ((rsvcLogicInst)yyvsp[0].data); + logic_code (rsvc_data_has_str); + } +break; + } + yyssp -= yym; + yyvsp -= yym; + yym = yylhs[yyn]; + yystate = *yyssp; + if (yystate == 0 && yym == 0) + { +#if YYDEBUG + if (yydebug) + printf("yydebug: after reduction, shifting from state 0 to\ + state %d\n", YYFINAL); +#endif + yystate = YYFINAL; + *++yyssp = YYFINAL; + *++yyvsp = yyval; + if (yychar < 0) + { + if ((yychar = yylex()) < 0) yychar = 0; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("yydebug: state %d, reading %d (%s)\n", + YYFINAL, yychar, yys); + } +#endif + } + if (yychar == 0) goto yyaccept; + goto yyloop; + } + yyn = yygindex[yym]; + if (yyn != 0 + && ((yyn += yystate), ((unsigned)yyn <= (unsigned)YYTABLESIZE)) + && yycheck[yyn] == yystate) + yystate = yytable[yyn]; + else + yystate = yydgoto[yym]; +#if YYDEBUG + if (yydebug) + printf("yydebug: after reduction, shifting from state %d \ +to state %d\n", *yyssp, yystate); +#endif + goto yypush; +yyoverflow: + yyerror("yacc stack overflow"); +yyabort: + return (1); +yyaccept: + return (0); +} diff --git a/extensions/cdevGenericServer/bin/Linux/cdev_test b/extensions/cdevGenericServer/bin/Linux/cdev_test new file mode 100755 index 0000000..ebad70e Binary files /dev/null and b/extensions/cdevGenericServer/bin/Linux/cdev_test differ diff --git a/extensions/cdevGenericServer/cdevClient/Makefile b/extensions/cdevGenericServer/cdevClient/Makefile new file mode 100755 index 0000000..b140d11 --- /dev/null +++ b/extensions/cdevGenericServer/cdevClient/Makefile @@ -0,0 +1,97 @@ +ARCH = OS +SHOBJ = YES + +include ../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "CDEV Generic Client Engine" +TEMPLINKS = cdevPacket.cc\ + cdevMessageBinary.cc\ + cdevMessage.cc\ + cdevContextMap.cc\ + SignalManager.cc\ + cdevAddr.cc\ + cdevEventHandler.cc\ + cdevHandleSet.cc\ + cdevReactor.cc\ + cdevSocket.cc\ + cdevSocketAcceptor.cc\ + cdevSocketConnector.cc\ + cdevSocketDatagram.cc\ + cdevSocketStream.cc\ + cdevStreamNode.cc\ + cdevStreamQueue.cc\ + cdevTime.cc\ + fifo.cc + +CLIENT_OBJS = $(OBJDIR)/cdevClientService.o\ + $(OBJDIR)/cdevClientRequestObject.o\ + $(OBJDIR)/ServerInterface.o\ + $(OBJDIR)/ServerHandler.o + +COMMON_OBJS = $(OBJDIR)/cdevPacket.o\ + $(OBJDIR)/cdevMessageBinary.o\ + $(OBJDIR)/cdevMessage.o\ + $(OBJDIR)/cdevContextMap.o\ + $(OBJDIR)/SignalManager.o\ + $(OBJDIR)/fifo.o + +ACE_OBJS = $(OBJDIR)/cdevAddr.o\ + $(OBJDIR)/cdevEventHandler.o\ + $(OBJDIR)/cdevHandleSet.o\ + $(OBJDIR)/cdevReactor.o\ + $(OBJDIR)/cdevSocket.o\ + $(OBJDIR)/cdevSocketAcceptor.o\ + $(OBJDIR)/cdevSocketConnector.o\ + $(OBJDIR)/cdevSocketDatagram.o\ + $(OBJDIR)/cdevSocketStream.o\ + $(OBJDIR)/cdevStreamNode.o\ + $(OBJDIR)/cdevStreamQueue.o\ + $(OBJDIR)/cdevTime.o + +OBJS = $(CLIENT_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + +# ****************************************************************************** +# * The BINARIES definition names all of the binary files that should be deleted +# * whenever "make clean" is executed. +# ****************************************************************************** +BINARIES = $(CDEVLIB)/libcdevClient.$(SHARED_EXT) \ + $(CDEVLIB)/libcdevClient.a + +ifeq ($(SHOBJ),YES) + TARGETS = $(TEMPLINKS) $(CDEVLIB)/libcdevClient.$(SHARED_EXT) +else + TARGETS = $(TEMPLINKS) $(CDEVLIB)/libcdevClient.a +endif + +targets : $(TARGETS) + +$(TEMPLINKS) : + @cp $^ $@ + +$(CDEVLIB)/libcdevClient.a : $(CLIENT_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + $(LINK.a) $@ $^ + @$(RANLIB) $@ > /dev/null + @cp $@ $(CDEVLIB) + +$(CDEVLIB)/libcdevClient.$(SHARED_EXT) : $(CLIENT_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + $(LINK.so) -o $@ $^ $(NETLIBS) + @cp $@ $(CDEVLIB) + +cdevMessage.cc : ../cdevPacket/cdevMessage.cc +cdevMessageBinary.cc : ../cdevPacket/cdevMessageBinary.cc +cdevPacket.cc : ../cdevPacket/cdevPacket.cc +cdevContextMap.cc : ../cdevContextMap/cdevContextMap.cc +SignalManager.cc : ../common/SignalManager.cc +cdevAddr.cc : ../cdevReactor/cdevAddr.cc +cdevEventHandler.cc : ../cdevReactor/cdevEventHandler.cc +cdevHandleSet.cc : ../cdevReactor/cdevHandleSet.cc +cdevReactor.cc : ../cdevReactor/cdevReactor.cc +cdevSocket.cc : ../cdevReactor/cdevSocket.cc +cdevSocketAcceptor.cc : ../cdevReactor/cdevSocketAcceptor.cc +cdevSocketConnector.cc : ../cdevReactor/cdevSocketConnector.cc +cdevSocketDatagram.cc : ../cdevReactor/cdevSocketDatagram.cc +cdevSocketStream.cc : ../cdevReactor/cdevSocketStream.cc +cdevStreamNode.cc : ../cdevReactor/cdevStreamNode.cc +cdevStreamQueue.cc : ../cdevReactor/cdevStreamQueue.cc +cdevTime.cc : ../cdevReactor/cdevTime.cc +fifo.cc : ../common/fifo.cc diff --git a/extensions/cdevGenericServer/cdevClient/NMakefile.mak b/extensions/cdevGenericServer/cdevClient/NMakefile.mak new file mode 100644 index 0000000..1f16f00 --- /dev/null +++ b/extensions/cdevGenericServer/cdevClient/NMakefile.mak @@ -0,0 +1,139 @@ +.SUFFIXES: .cc .obj + +APPNAME = CDEV Generic Client Engine +ARCH = WINNT-4.0 + +TEMPLINKS = cdevPacket.cc\ + cdevMessageBinary.cc\ + cdevMessage.cc\ + cdevContextMap.cc\ + SignalManager.cc\ + cdevAddr.cc\ + cdevEventHandler.cc\ + cdevHandleSet.cc\ + cdevReactor.cc\ + cdevSocket.cc\ + cdevSocketAcceptor.cc\ + cdevSocketConnector.cc\ + cdevSocketDatagram.cc\ + cdevSocketStream.cc\ + cdevStreamNode.cc\ + cdevStreamQueue.cc\ + cdevTime.cc\ + fifo.cc + +BINARIES = $(CDEVLIB)\cdevClient.dll \ + $(CDEVLIB)\cdevClient.lib \ + $(TEMPLINKS) + +include ..\include\makeinclude\Makefile.WINNT-4.0 + +CLIENT_OBJS = $(OBJDIR)\cdevClientService.obj\ + $(OBJDIR)\cdevClientRequestObject.obj\ + $(OBJDIR)\ServerInterface.obj\ + $(OBJDIR)\ServerHandler.obj + +COMMON_OBJS = $(OBJDIR)\cdevPacket.obj\ + $(OBJDIR)\cdevMessageBinary.obj\ + $(OBJDIR)\cdevMessage.obj\ + $(OBJDIR)\cdevContextMap.obj\ + $(OBJDIR)\SignalManager.obj\ + $(OBJDIR)\fifo.obj + +ACE_OBJS = $(OBJDIR)\cdevAddr.obj\ + $(OBJDIR)\cdevEventHandler.obj\ + $(OBJDIR)\cdevHandleSet.obj\ + $(OBJDIR)\cdevReactor.obj\ + $(OBJDIR)\cdevSocket.obj\ + $(OBJDIR)\cdevSocketAcceptor.obj\ + $(OBJDIR)\cdevSocketConnector.obj\ + $(OBJDIR)\cdevSocketDatagram.obj\ + $(OBJDIR)\cdevSocketStream.obj\ + $(OBJDIR)\cdevStreamNode.obj\ + $(OBJDIR)\cdevStreamQueue.obj\ + $(OBJDIR)\cdevTime.obj + +OBJS = $(CLIENT_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + +CXXEXTRA = /D "_CDEV_REACTOR_EXPORTS_=1" /D "_GENERIC_SERVER_EXPORTS_=1" + +!IF "$(SHOBJ)" == "YES" +TARGETS = $(TEMPLINKS) $(CDEVLIB)\cdevClient.dll +!ELSE +TARGETS = $(TEMPLINKS) $(CDEVLIB)\cdevClient.lib +!ENDIF + +targets : $(TARGETS) + @erase $(TEMPLINKS) + +$(CDEVLIB)\cdevClient.lib : $(OBJS) + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib\ + $(LINK_LIB_FLAGS) /out:$@ $(OBJS) + @echo ^ ^ ^ ^ ^ ^ Done... + +$(CDEVLIB)\cdevClient.dll : $(OBJS) + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib\ + $(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $(OBJS) + @echo ^ ^ ^ ^ ^ ^ Done... + +cdevMessage.cc : ..\cdevPacket\cdevMessage.cc + -@$(CREATE_LINK) + +cdevMessageBinary.cc : ..\cdevPacket\cdevMessageBinary.cc + -@$(CREATE_LINK) + +cdevPacket.cc : ..\cdevPacket\cdevPacket.cc + -@$(CREATE_LINK) + +cdevContextMap.cc : ..\cdevContextMap\cdevContextMap.cc + -@$(CREATE_LINK) + +SignalManager.cc : ..\common\SignalManager.cc + -@$(CREATE_LINK) + +cdevAddr.cc : ..\cdevReactor\cdevAddr.cc + -@$(CREATE_LINK) + +cdevEventHandler.cc : ..\cdevReactor\cdevEventHandler.cc + -@$(CREATE_LINK) + +cdevHandleSet.cc : ..\cdevReactor\cdevHandleSet.cc + -@$(CREATE_LINK) + +cdevReactor.cc : ..\cdevReactor\cdevReactor.cc + -@$(CREATE_LINK) + +cdevSocket.cc : ..\cdevReactor\cdevSocket.cc + -@$(CREATE_LINK) + +cdevSocketAcceptor.cc : ..\cdevReactor\cdevSocketAcceptor.cc + -@$(CREATE_LINK) + +cdevSocketConnector.cc : ..\cdevReactor\cdevSocketConnector.cc + -@$(CREATE_LINK) + +cdevSocketDatagram.cc : ..\cdevReactor\cdevSocketDatagram.cc + -@$(CREATE_LINK) + +cdevSocketStream.cc : ..\cdevReactor\cdevSocketStream.cc + -@$(CREATE_LINK) + +cdevStreamNode.cc : ..\cdevReactor\cdevStreamNode.cc + -@$(CREATE_LINK) + +cdevStreamQueue.cc : ..\cdevReactor\cdevStreamQueue.cc + -@$(CREATE_LINK) + +cdevTime.cc : ..\cdevReactor\cdevTime.cc + -@$(CREATE_LINK) + +fifo.cc : ..\common\fifo.cc + -@$(CREATE_LINK) + + diff --git a/extensions/cdevGenericServer/cdevClient/ServerHandler.cc b/extensions/cdevGenericServer/cdevClient/ServerHandler.cc new file mode 100755 index 0000000..2461bd5 --- /dev/null +++ b/extensions/cdevGenericServer/cdevClient/ServerHandler.cc @@ -0,0 +1,526 @@ +#include +#include +#include +#include +#include + +#define _CDEV_CONNECTION_RETRIES 5 + +SignalManager ServerHandler::signalManager; +int ServerHandler::signalManagerInit = 0; + +// ***************************************************************************** +// * ServerHandlerCallbackNode: +// * This is a node of a linked list that isolates the ServerHandlerCallback +// * object from inadverntently being corrupted by being placed in more +// * than one ServerHandler object. +// * +// * The ALLOCATION_COUNT of 128 forces the allocation of blocks that are +// * close to 1 kilobyte in size. +// ***************************************************************************** +class ServerHandlerCallbackNode +{ +friend class ServerHandler; +private: + static ServerHandlerCallbackNode * freeList_; + ServerHandlerCallbackNode * next; + ServerHandlerCallback * callback; + enum { ALLOCATION_COUNT=128 }; + + ServerHandlerCallbackNode ( void ); +public: + ServerHandlerCallbackNode ( ServerHandlerCallback * Callback ); + ~ServerHandlerCallbackNode( void ); + void * operator new ( size_t ); + void operator delete ( void * ptr ); +}; + +ServerHandlerCallbackNode * ServerHandlerCallbackNode::freeList_; + +// ***************************************************************************** +// * ServerHandler::ServerHandler +// * Default constructor for the ServerHandler class +// ***************************************************************************** +ServerHandler::ServerHandler ( char * Server, ServerInterface * Interface ) + : SocketReader(CLIP_MAGIC_NUMBER), SocketWriter(CLIP_MAGIC_NUMBER), + queue(*(Interface->getQueue(Server))), serverface(Interface), callbacks(NULL), + enqueuedPackets(0), enqueuedBytes(0), clientID(-1), contextID(-1), + tagChanged(1), serverQuitFlag(0) + { + strncpy(server, Server, 256); + server[255] = 0; + hostName[0] = 0; + clientID = getNextClientID(); + + if(!signalManagerInit) signalManager.installDefaults(); + + // ********************************************************************* + // * If any data exists in the queue for this server, walk through each + // * entry and determine if it is valid - if so, reenqueue it, + // * otherwise, delete it. + // ********************************************************************* + if(!queue.empty()) + { + FifoQueue tempQueue; + char * binary; + size_t len; + while(queue.dequeue(&binary, &len)==0) + { + if(serverface->isPacketValid(binary, len)) + { + tempQueue.enqueue(binary, len); + } + else delete binary; + } + while(tempQueue.dequeue(&binary, &len)==0) + { + enqueue(binary, len); + } + } + } + +// ***************************************************************************** +// * ServerHandler::outputError : +// * This mechanism is used to report errors to the system. +// ***************************************************************************** +int ServerHandler::outputError(int severity, char *name, char *formatString, ...) + { + va_list argp; + static char msg[1024]; + + va_start (argp, formatString); + vsprintf (msg, formatString, argp); + va_end (argp); + + return serverface->outputError(severity, name, msg); + } + +// ***************************************************************************** +// * open: +// * Established a connection with the host specified by remote_sap +// ***************************************************************************** +int ServerHandler::open ( const cdevAddr & addr ) + { + int result = 0; + int count = 0; + + result = stream.connect (addr); + + if (result != -1) + { + if((result = serverface->Reactor.registerHandler(this, READ_MASK|WRITE_MASK|EXCEPT_MASK))==-1) + { + handleClose(); + } + } + return result; + } + + +// ***************************************************************************** +// * ~ServerHandler: +// * Default destructor for the ServerHandler object. +// ***************************************************************************** +ServerHandler::~ServerHandler (void) + { + ServerHandlerCallbackNode * cb = callbacks; + + // ********************************************************************* + // * Write a -1 as the packetLength to the connection in order to + // * terminate. + // ********************************************************************* + if(stream.getHandle()>0 && serverQuitFlag==0) + { + #ifndef _WIN32 + void (*action)(int) = signal(SIGPIPE, SIG_IGN); + #endif + + writeGoodbye(); + + #ifndef _WIN32 + signal(SIGPIPE, action); + #endif + } + + // ********************************************************************* + // * Contact all of the objects that rely on the existance of this + // * class. + // ********************************************************************* + while(cb!=NULL) + { + ServerHandlerCallbackNode * oldCB = cb; + cb = cb->next; + oldCB->callback->executeServerHandlerCallback(this); + delete oldCB; + } + + // ********************************************************************* + // * Perform standard shutdown steps. + // ********************************************************************* + if(reactor) reactor->extractHandler(this); + handleClose(); + } + + +// ***************************************************************************** +// * ServerHandler::getHostName: +// * This function returns the name of the remote host. +// ***************************************************************************** +char * ServerHandler::getHostName( void ) + { + if(*hostName==0) + { + cdevInetAddr addr; + if(stream.getRemoteAddress (addr)==0) + { + const char * ptr=addr.getHostName(); + if(ptr) strncpy (hostName, ptr, MAXHOSTNAMELEN+1); + } + } + return hostName; + } + +// ***************************************************************************** +// * ServerHandler::getName : +// * Allows the caller to obtain the name of the class. +// ***************************************************************************** +char * ServerHandler::getName (void) const + { + return "ServerHandler"; + } + + +// ***************************************************************************** +// * ServerHandler::getHandle +// * Allows the caller to obtain the file identifier of the socket. +// ***************************************************************************** +int ServerHandler::getHandle (void) const + { + return stream.getHandle(); + } + + + +// ***************************************************************************** +// * ServerHandler::getServer: +// * Allows the caller to obtain the name of the connected server. +// ***************************************************************************** +char * ServerHandler::getServer (void) const + { + return (char *)server; + } + + +// ***************************************************************************** +// * handleClose: +// * Closes the stream. +// ***************************************************************************** +int ServerHandler::handleClose (void) + { + serverface->disconnect(server); + stream.close(); + return 0; + } + + +// ***************************************************************************** +// * handleInput : +// * This function is called when data is ready to be read from a connected +// * socket. This function will read the data from the socket, and will then +// * submit the buffer to the ServerInterface class for processing. +// ***************************************************************************** +int ServerHandler::handleInput (void) +{ +int retval = 0; +char * buf = NULL; +size_t len = 0; +int result = 1; + +// ***************************************************************************** +// * Record oriented semantics dictate that the length of the transmission +// * always preceeds the actual data. Therefore, read the length of the +// * transmission into the len variable. +// ***************************************************************************** +while(result>0) + { + result = read(&buf, (int *)&len); + + switch(result) + { + // ************************************************************* + // * A return value of SHUTDOWN_CODE indicates that a negative + // * one was provided as the packet length - indicating a + // * shutdown... + // ************************************************************* + case SHUTDOWN_CODE: + outputError(CDEV_SEVERITY_INFO, (char *)getName(), + "Connection to %s terminated by client", getHostName()); + retval = -1; + break; + + // ************************************************************* + // * A return value of -1 indicates an error occured while + // * reading from the socket. A value of -1 is returned to + // * shutdown the socket and remove it from the reactor. + // ************************************************************* + case -1: + outputError(CDEV_SEVERITY_WARN, (char *)getName(), + "Error reading from connection to client %s", getHostName()); + retval = -1; + break; + + // ************************************************************* + // * A return value of 0 means that no data was ready to be + // * retrieved from the socket. + // ************************************************************* + case 0: + break; + + // ************************************************************* + // * Any other value returned from the socket represents the + // * number of bytes actually read into the local Session object. + // ************************************************************* + default: + serverface->enqueue(ServerInterface::COMPLETED, this, buf, len); + break; + } + } + +// ***************************************************************************** +// * Return the value specified by retval. +// ***************************************************************************** +return retval; +} + + + +// ***************************************************************************** +// * handleOutput : +// * This function is called when data is ready to be transmitted to a +// * connected socket. This function will read the data from the queue, +// * translate it to XDR, and then transmit it to the client. +// ***************************************************************************** +int ServerHandler::handleOutput ( void ) +{ +int retval = 0; +char * buf = NULL; +size_t len = 0; + +// ***************************************************************************** +// * Attempt to transmit or continue transmitting the data. Note, the peek +// * method is used to attempt to writeEnqueue a data item without actually +// * removing it from the outbound queue. If the item can be writeEnqueued, +// * then the dequeue method is called to remove it from the queue... +// * This method is repeated until the output buffer is fully populated. +// ***************************************************************************** +if(!writing() && dequeue(&buf, &len)==0) + { + int full = 0; + while(!full) + { + if(!(full = writeEnqueue(buf, len))) + { + delete buf; + full = dequeue(&buf, &len); + } + else undequeue(buf, len); + } + if(writeContinue()<0) retval = -1; + } +else if(writing()) + { + if(writeContinue()<0) retval = -1; + } + +// ***************************************************************************** +// * Display an error message if the transmission failed. +// ***************************************************************************** +if(retval!=0) + { + outputError(CDEV_SEVERITY_WARN, (char *)getName(), + "Error transmitting to %s", getHostName()); + } + +// ***************************************************************************** +// * If there are no further messages in the outbound queue and the +// * ACE_Event_Handler has finished servicing the current message, turn off the +// * WRITE_MASK for this ACE_Event_Handler. +// ***************************************************************************** +if(empty() && !writing()) + { + setMask(READ_MASK|EXCEPT_MASK); + } + +// ***************************************************************************** +// * Return the value specified by retval. +// ***************************************************************************** +return retval; +} + + +// ***************************************************************************** +// * handleExcept : +// * This function is called when out of band data has been received from +// * the server. It will terminate the connection with the server. +// ***************************************************************************** +int ServerHandler::handleExcept ( void ) + { + stream.close(); + serverQuitFlag=1; + return -1; + } + + +// ***************************************************************************** +// * registerServerCallback : +// * This method is called to add a ServerHandlerCallback object to the list +// * of objects that the ServerHandler will notify when it is destroyed... +// * This notification process protects objects that use this class for +// * communications from using a pointer to a ServerHandler that has been +// * deleted. +// ***************************************************************************** +void ServerHandler::registerServerCallback(ServerHandlerCallback * cb) + { + ServerHandlerCallbackNode *cbPrev=NULL, *cbNext=callbacks; + + while(cbNext!=NULL && cbNext->callback!=cb) + { + cbPrev = cbNext; + cbNext = cbNext->next; + } + if(cbNext==NULL) + { + if(cbPrev==NULL) callbacks = new ServerHandlerCallbackNode(cb); + else cbPrev->next = new ServerHandlerCallbackNode(cb); + } + } + +// ***************************************************************************** +// * unregisterServerCallback : +// * This method is used to remove a ServerHandlerCallback object from the +// * list of objects that will be notified when the ServerHandler object +// * is destroyed. +// ***************************************************************************** +void ServerHandler::unregisterServerCallback (ServerHandlerCallback * cb) + { + ServerHandlerCallbackNode *cbPrev=NULL, *cbNext=callbacks; + + while(cbNext!=NULL && cbNext->callback!=cb) + { + cbPrev = cbNext; + cbNext = cbNext->next; + } + if(cbNext->callback==cb) + { + if(cbPrev==NULL) callbacks = cbNext->next; + else cbPrev->next = cbNext->next; + delete cbNext; + } + } + + +// ***************************************************************************** +// * enqueue : +// * This method places an object into the embedded FifoQueue and will force +// * a flush of the socket if it reaches the high water mark. +// ***************************************************************************** +void ServerHandler::enqueue (char * buf, size_t len) + { + enqueuedPackets++; + enqueuedBytes+=len; + queue.enqueue(buf, len); + if(enqueuedPackets>100 || enqueuedBytes>16000) + { + serverface->flush(getHandle()); + enqueuedPackets=0; + enqueuedBytes=0; + } + } + + +// ***************************************************************************** +// * ServerHandler::getNextClientID : +// * This method allows the caller to retrieve a unique clientID to be +// * assigned to a client. The nextClientID value is automatically +// * incremented. +// ***************************************************************************** +short ServerHandler::getNextClientID ( void ) + { + static short nextClientID = 0; + + nextClientID++; + if(nextClientID<=0) nextClientID = 1; + return nextClientID; + } + + +// ***************************************************************************** +// * ServerHandlerCallbackNode::ServerHandlerCallbackNode : +// * Default constructor for the ServerHandlerCallbackNode class. +// ***************************************************************************** +ServerHandlerCallbackNode::ServerHandlerCallbackNode ( void ) + : callback(NULL), next(NULL) + { + } + + +// ***************************************************************************** +// * ServerHandlerCallbackNode::ServerHandlerCallbackNode : +// * Parameterized constructor for the ServerHandlerCallbackNode class. +// ***************************************************************************** +ServerHandlerCallbackNode::ServerHandlerCallbackNode( ServerHandlerCallback * Callback ) + : callback(Callback), next(NULL) + { + } + + +// ***************************************************************************** +// * ServerHandlerCallbackNode::~ServerHandlerCallbackNode : +// * Destructor for the ServerHandlerCallbackNode class. +// ***************************************************************************** +ServerHandlerCallbackNode::~ServerHandlerCallbackNode( void ) + { + } + + +// ***************************************************************************** +// * ServerHandlerCallbackNode::operator new : +// * Gets a ServerHandlerCallbackNode instance from the freelist. +// ***************************************************************************** +void * ServerHandlerCallbackNode::operator new ( size_t ) + { + ServerHandlerCallbackNode * result = NULL; + + if(freeList_==NULL) + { + freeList_ = ::new ServerHandlerCallbackNode[ALLOCATION_COUNT]; + for(int i=0; inext; + result->next = NULL; + } + return result; + } + + +// ***************************************************************************** +// * ServerHandlerCallbackNode::operator delete : +// * Returns a ServerHandlerCallbackNode instance to the freelist. +// ***************************************************************************** +void ServerHandlerCallbackNode::operator delete ( void * ptr ) + { + ServerHandlerCallbackNode * node = (ServerHandlerCallbackNode *)ptr; + if(node != NULL) + { + node->next = freeList_; + freeList_ = node; + } + } + diff --git a/extensions/cdevGenericServer/cdevClient/ServerHandler.h b/extensions/cdevGenericServer/cdevClient/ServerHandler.h new file mode 100755 index 0000000..2b9d9c3 --- /dev/null +++ b/extensions/cdevGenericServer/cdevClient/ServerHandler.h @@ -0,0 +1,97 @@ +#if !defined (_SERVER_HANDLER_H_) +#define _SERVER_HANDLER_H_ + +// ***************************************************************************** +// * SIG_PIPE_HANDLED: +// * This definition tells the SocketWriter class not to independently +// * handle the SIGPIPE signal. +// ***************************************************************************** +#define SIG_PIPE_HANDLED 1 + +#include "cdevEventHandler.h" +#include "cdevAddr.h" +#include "cdevSocketConnector.h" +#include "cdevReactor.h" + +#include "SocketUtil.h" +#include "fifo.h" + +class ServerInterface; +class ServerHandlerCallbackNode; +class SignalManager; + +// ***************************************************************************** +// * ServerHandlerCallback : +// * This class is used by other classes to register to be informed when the +// * ServerHandler is destroyed. +// ***************************************************************************** +class GENERIC_SERVER_API ServerHandlerCallback +{ +public: + ServerHandlerCallback ( void ) {} + virtual ~ServerHandlerCallback ( void ) {} + virtual void executeServerHandlerCallback (class ServerHandler * handler) = 0; +}; + + +// ***************************************************************************** +// * ServerHandler: +// * This class provides the mechanisms that will be used to service the +// * requests of a client. +// ***************************************************************************** +class GENERIC_SERVER_API ServerHandler : public cdevEventHandler, + public SocketReader, + public SocketWriter +{ +protected: + static SignalManager signalManager; + static int signalManagerInit; + + char hostName [MAXHOSTNAMELEN + 1]; + char server [256]; + FifoQueue & queue; + cdevSocketConnector stream; + ServerInterface * serverface; + ServerHandlerCallbackNode * callbacks; + size_t enqueuedPackets; + size_t enqueuedBytes; + short clientID; + int contextID; + int tagChanged; + int serverQuitFlag; + +public: + ServerHandler (char * Server, ServerInterface * Interface); + ~ServerHandler (void); + virtual int outputError (int severity, char *name, char *formatString, ...); + + virtual int open (const cdevAddr &addr); + + char * getHostName (void); + char * getName (void) const; + virtual int getHandle (void) const; + virtual char * getServer (void) const; + + virtual int handleClose (void); + virtual int handleInput (void); + virtual int handleOutput (void); + virtual int handleExcept (void); + + virtual void registerServerCallback (ServerHandlerCallback *); + virtual void unregisterServerCallback (ServerHandlerCallback *); + + void enqueue (char * buf, size_t len); + void undequeue (char * buf, size_t len) { queue.undequeue(buf, len); } + int dequeue (char **buf, size_t *len) { return queue.dequeue(buf, len); } + int empty (void) { return queue.empty(); } + + static short getNextClientID ( void ); + short getClientID ( void ) { return clientID; } + void setClientID ( short ClientID ) { clientID=ClientID; } + int getContextID ( void ) { return contextID; } + void setContextID ( int ContextID ) { contextID = ContextID; } + int getTagChangeFlag ( void ) { return tagChanged; } + void setTagChangeFlag ( int flag ) { tagChanged = flag; } +}; + +#endif /* _SERVER_HANDLER_H_ */ diff --git a/extensions/cdevGenericServer/cdevClient/ServerInterface.cc b/extensions/cdevGenericServer/cdevClient/ServerInterface.cc new file mode 100755 index 0000000..76f9525 --- /dev/null +++ b/extensions/cdevGenericServer/cdevClient/ServerInterface.cc @@ -0,0 +1,506 @@ +#include "cdevClock.h" +#include "ServerInterface.h" + +cdevReactor ServerInterface::Reactor; + +// ***************************************************************************** +// * ServerConnectionList::ServerConnectionList : +// * Constructor for the list of active connections that is being managed +// * by the ServerHandler. +// ***************************************************************************** +ServerConnectionList::ServerConnectionList ( void ) + { + maxItems = ALLOCATION_COUNT; + items = (ServerHandler **)malloc(maxItems*sizeof(ServerHandler *)); + memset(items, 0, maxItems*sizeof(ServerHandler *)); + } + + +// ***************************************************************************** +// * ServerConnectionList::~ServerConnectionList : +// * Destructor for the list of active connections that is being managed +// * by the ServerHandler. +// ***************************************************************************** +ServerConnectionList::~ServerConnectionList ( void ) + { + free (items); + } + +// ***************************************************************************** +// * ServerConnectionList::find : +// * Locates a ServerHandler object that is associated with the specified +// * server name. +// ***************************************************************************** +ServerHandler * ServerConnectionList::find ( char * server ) + { + int i; + for(i=0; + igetServer()); + i++); + return (igetServer(); + for(i=0; + igetServer()); + i++); + + if(i>=maxItems) + { + items = (ServerHandler **) realloc(items, 2*maxItems*sizeof(ServerHandler *)); + memset(&items[maxItems], 0, maxItems*sizeof(ServerHandler *)); + maxItems*=2; + } + + if(items[i]==NULL) + { + items[i] = handler; + result = 0; + } + } + return result; + } + + +// ***************************************************************************** +// * ServerConnectionList::remove : +// * Removes the ServerHandler object specified by handler if it exists in +// * list. +// ***************************************************************************** +int ServerConnectionList::remove ( ServerHandler * handler ) + { + int result = -1; + if(handler!=NULL) + { + int i; + for(i=0; idequeue(&buf, &len)==0) delete buf; + connections.remove(handler); + delete handler; + } + + // ********************************************************************* + // * Iterate through the queues associated with servers and remove + // * all messages that have not been transmitted. + // ********************************************************************* + StringHashIterator iter(&connectionQueues); + iter.first(); + while((buf = iter.key())!=NULL) + { + FifoQueue * queue = (FifoQueue *)iter.data(); + connectionQueues.remove(buf); + while(queue->dequeue(&buf, &len)==0) delete buf; + delete queue; + iter.first(); + } + } + + +// ***************************************************************************** +// * ServerInterface::getDefault : +// * This method allows the caller to obtain a pointer to the name of the +// * default server. +// ***************************************************************************** +char * ServerInterface::getDefault ( void ) + { + return defaultServer; + } + + +// ***************************************************************************** +// * ServerInterface::setDefault : +// * This method allows the caller to set the name of the default server. +// ***************************************************************************** +void ServerInterface::setDefault ( char * Default ) + { + if(defaultServer!=NULL) + { + delete defaultServer; + defaultServer = NULL; + defaultServerHandler = NULL; + } + if(Default!=NULL && *Default) + { + defaultServer = strdup(Default); + defaultServerHandler = connect(defaultServer); + } + } + + +// ***************************************************************************** +// * ServerInterface::connect : +// * This is a stub method that should be overridden by the developer in +// * a child class. +// ***************************************************************************** +ServerHandler * ServerInterface::connect ( char *, char *, unsigned short ) + { + return NULL; + } + +// ***************************************************************************** +// * ServerInterface::disconnect : +// * This is a stub method that should be overridden by the developer in +// * a child class. +// ***************************************************************************** +ServerHandler * ServerInterface::disconnect ( char * ) + { + return NULL; + } + +// ***************************************************************************** +// * ServerInterface::enqueue : +// * This enqueue mechanism is called by the client if they have already +// * identified the server that they wish to communicate with and have +// * obtained a pointer to its ServerHandler object. +// * +// * If the specified server handler is NULL then the message will be +// * submitted to the default server. +// ***************************************************************************** +int ServerInterface::enqueue( ServerHandler * handler, char * binary, size_t binaryLen ) + { + int result; + + if(handler!=NULL || (handler=defaultServerHandler)!=NULL || + (defaultServer!=NULL && (handler=(defaultServerHandler=connect(defaultServer)))!=NULL)) + { + handler->enqueue(binary, binaryLen); + result = CDEV_SUCCESS; + } + else + { + outputError(CDEV_SEVERITY_ERROR, + "ServerInterface::enqueue", + "No default server has been specified"); + result = CDEV_ERROR; + } + return result; + } + + +// ***************************************************************************** +// * ServerInterface::getQueue : +// * This method allows the caller to obtain a pointer to the FifoQueue +// * associated with a specific server. This queue is then attached to +// * the ServerHandler that is connected to that server. +// ***************************************************************************** +FifoQueue * ServerInterface::getQueue ( char * server ) + { + FifoQueue * queue = (FifoQueue *)connectionQueues.find(server); + if(queue==NULL) + { + queue=new FifoQueue; + connectionQueues.insert(server, (void *)queue); + } + return queue; + } + + +// ***************************************************************************** +// * ServerInterface::isPacketValid : +// * This method is called by the ServerHandler after it has been restarted. +// * If the ServerHandler inherits packets that are already in the queue, it +// * will call this method for each pcket in order to determine if they are +// * valid. If the packets are no longer valid (i.e., there is no longer +// * a cdevTransObj associated with them, they will be deleted. Otherwise, +// * they will be submitted to the server. +// * +// * Because this functionality will be handled in a derived class, this +// * method will always return 1 to indicate that the packet is valid. +// ***************************************************************************** +int ServerInterface::isPacketValid ( char * binary, size_t binaryLen ) + { + return (binary!=NULL && binaryLen>0)?1:0; + } + +// ***************************************************************************** +// * ServerInterface::getFd : +// * This mechanism is used to obtain a list of the file descriptors that +// * are used by the ServerInterface. These file descriptors may then be +// * used for polling. +// ***************************************************************************** +int ServerInterface::getFd (int * &fd, int &numFd ) + { + int idx = 0; + + numFd = 0; + + while(connections[idx]!=NULL) + { + if((numFd+1)>maxFd) + { + maxFd*=2; + fdList = (int *)realloc(fdList, maxFd*sizeof(int)); + } + fdList[numFd++] = connections[idx++]->getHandle(); + } + + if(numFd) fd = fdList; + else fd = NULL; + + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * ServerInterface::flush : +// * This mechanism is used to flush all outbound buffers to their respective +// * servers. +// ***************************************************************************** +int ServerInterface::flush ( void ) + { + // ********************************************************************* + // * First - determine if there is any outbound data that needs to be + // * processed. Walk through the connectionQueue objects - which exist + // * even if the connection has been lost - and count up the number of + // * queues that are not empty. + // ********************************************************************* + StringHashIterator iter(&connectionQueues); + FifoQueue * queue = NULL; + int needsFlush = 0; + + // ********************************************************************* + // * Invoke a brief reactor.checkHandlers in order to cause any + // * dead ServerHandlers to be removed from the Reactor. Then + // * attempt to reattach to any ServerHandlers that have + // * outbound data. + // ********************************************************************* + char * server; + Reactor.checkHandlers(); + + for(iter.first(); (server=iter.key())!=NULL; iter++) + { + queue = (FifoQueue *)iter.data(); + if(queue && !queue->empty()) + { + needsFlush++; + connect(server); + } + } + + // ********************************************************************* + // * At this point he needsFlush variable will be non-zero if any of + // * the queues contain outbound data. The remainder of this code + // * only needs to be performed if this is the case. + // ********************************************************************* + if(needsFlush) + { + // ************************************************************* + // * Provide a maximum timeout value of 5 seconds. If the system + // * cannot be flushed in that amount of time - then an error or + // * a hang must exist on the other side. + // ************************************************************* + cdevTimeValue t(5.0); + cdevClock timer; + timer.schedule(NULL, t); + + // ************************************************************* + // * While there are sockets that have outbound data AND the + // * timer has not expired - process events. + // ************************************************************* + int idx = 0; + while(needsFlush && !timer.expired()) + { + needsFlush = 0; + for(idx=0; connections[idx]!=NULL; idx++) + { + if(!connections[idx]->empty()) + { + connections[idx]->setMask(cdevEventHandler::WRITE_MASK|cdevEventHandler::EXCEPT_MASK); + needsFlush++; + } + else connections[idx]->setMask(cdevEventHandler::READ_MASK|cdevEventHandler::EXCEPT_MASK); + } + if(needsFlush) Reactor.handleEvents(1.0, cdevReactor::UNTIL_EVENT); + } + + // ********************************************************************* + // * Walk through all of the ServerHandlers and restore them to + // * READ_MASK mode. + // ********************************************************************* + if(needsFlush) + { + for(idx=0; connections[idx]!=NULL; idx++) + { + connections[idx]->setMask(cdevEventHandler::READ_MASK|cdevEventHandler::EXCEPT_MASK); + } + } + } + + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * ServerInterface::flush : +// * This mechanism is used to flush all outbound buffers to their respective +// * servers. +// ***************************************************************************** +int ServerInterface::flush ( int fd ) + { + // ********************************************************************* + // * Walk through each item and locate the handler that needs to be + // * flushed. If the connection is located, then handle events until + // * it is empty. + // ********************************************************************* + int i; + for(i=0; connections[i]!=NULL && connections[i]->getHandle()!=fd; i++); + if(connections[i]!=NULL) + { + cdevTimeValue t(5.0); + cdevClock timer; + timer.schedule(NULL, t); + + connections[i]->setMask(cdevEventHandler::WRITE_MASK|cdevEventHandler::EXCEPT_MASK); + while(connections[i]!=NULL && !connections[i]->empty() && !timer.expired()) + { + Reactor.handleEvents(1.0, cdevReactor::UNTIL_EVENT); + } + // ************************************************************* + // * If an error occurs during the write, the ServerHandler may + // * have been deleted - therefore, check to ensure that the + // * connection is valid prior to restoring its mask. + // ************************************************************* + if(connections[i]!=NULL) + { + connections[i]->setMask(cdevEventHandler::READ_MASK|cdevEventHandler::EXCEPT_MASK); + } + } + + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * ServerInterface::pend : +// * Pends for the specified period of time. The int parameter is not used +// * in this implementation. In later designs it may be used to allow the +// * interface to pend on a specific file descriptor. +// ***************************************************************************** +int ServerInterface::pend ( double seconds, int ) + { + // ********************************************************************* + // * Test to determine if there are any ServerHandlers in operation. + // ********************************************************************* + if(connections[0]!=NULL) + { + // ************************************************************* + // * Flush outbound requests if necessary. + // ************************************************************* + flush(); + + // ************************************************************* + // * Handle events for the specified period. + // ************************************************************* + Reactor.handleEvents(seconds); + } + + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * ServerInterface::poll : +// * This method polls the cdevReactor to see if any events are ready to be +// * processed on any of the sockets. If events are ready, then they are +// * processed immediately - otherwise, the function returns immediately. +// ***************************************************************************** +int ServerInterface::poll ( void ) + { + // ********************************************************************* + // * Test to determine if there are any ServerHandlers in operation. + // ********************************************************************* + if(connections[0]!=NULL) + { + // ************************************************************* + // * Flush outbound requests if necessary. + // ************************************************************* + flush(); + + // ************************************************************* + // * Handle events for 0 seconds - effectively polling. + // ************************************************************* + Reactor.handleEvents(0.0001, cdevReactor::UNTIL_EVENT); + } + + return CDEV_SUCCESS; + } diff --git a/extensions/cdevGenericServer/cdevClient/ServerInterface.h b/extensions/cdevGenericServer/cdevClient/ServerInterface.h new file mode 100755 index 0000000..9830043 --- /dev/null +++ b/extensions/cdevGenericServer/cdevClient/ServerInterface.h @@ -0,0 +1,71 @@ +#ifndef _SERVER_INTERFACE_H_ +#define _SERVER_INTERFACE_H_ + +#include "cdevErrCode.h" +#include "ServerHandler.h" +#include "ErrorReporter.h" +#include "StringHash.h" +#include "fifo.h" +#include "cdevReactor.h" +#include "cdevEventHandler.h" +#include "cdevAddr.h" + +class GENERIC_SERVER_API ServerConnectionList +{ +private: + enum { ALLOCATION_COUNT = 32 }; + ServerHandler ** items; + int maxItems; + +public: + ServerConnectionList ( void ); + virtual ~ServerConnectionList ( void ); + + ServerHandler * find ( char * server ); + int insert ( ServerHandler * handler ); + int remove ( ServerHandler * handler ); + ServerHandler * remove ( char * server ); + + ServerHandler * operator [] ( int idx ) + { return (idx +#include +#include +#include +#include + +// ***************************************************************************** +// * cdevClientRequestObject::cdevClientRequestObject : +// * This constructor initializes the internals of a device/message +// * pair associated with a cdevClientService based service. +// * +// * Returns nothing. +// * +// * Remember it is the responsibility of the requestObject to ensure +// * that the message is not laden with extraneous spaces. +// ***************************************************************************** +cdevClientRequestObject::cdevClientRequestObject ( char * device, char * msg, cdevSystem & system) + : cdevRequestObject(device, msg, system), + syncCallback(defaultCallback, (void *)&sendStatus), + handler(NULL), contextID(-1) + { + char message[256]; + char * ptr; + + *server = 0; + *DDL_server = 0; + + // ********************************************************************* + // * Remove any extra spaces from the message. + // * Copy user supplied msg to a message buffer to allow + // * modification in this routine since the user supplied + // * msg could be a constant string + // ********************************************************************* + strncpy (message, msg, sizeof (message) - 1); + message[255] = 0; + + for(ptr=message; *ptr!=0; ptr++) + { + if(isspace(*ptr)) + { + char * nextChar; + + for(nextChar=ptr+1; isspace(*nextChar) && *nextChar!=0; nextChar++); + if(nextChar!=ptr+1) strcpy(ptr+1, nextChar); + *ptr=' '; + } + } + + // ********************************************************************* + // * Remove all trailing spaces from the message. + // ********************************************************************* + for(ptr = message+(strlen(message)-1); ptr>=message && isspace(*ptr); ptr--) + { + *ptr=0; + } + // ********************************************************************* + // * Determine the commandCode from the message string. + // ********************************************************************* + if(!strncmp(message, "get ", 4)) commandCode = GET_COMMAND; + else if(!strncmp(message, "set ", 4)) commandCode = SET_COMMAND; + else if(!strncmp(message, "monitorOn ", 10)) commandCode = MONITOR_ON_COMMAND; + else if(!strncmp(message, "monitorOff ", 11)) commandCode = MONITOR_OFF_COMMAND; + else commandCode = OTHER_COMMAND; + + // ********************************************************************* + // * Determine the messageCode from the message string. + // ********************************************************************* + if(!strcmp(message, "get servers")) messageCode = GET_SERVERS_MESSAGE; + else if(!strcmp(message, "get default")) messageCode = GET_DEFAULT_MESSAGE; + else if(!strcmp(message, "set default")) messageCode = SET_DEFAULT_MESSAGE; + else if(!strcmp(message, "disconnect")) messageCode = DISCONNECT_MESSAGE; + else if(!strcmp(message, "get ClientInfo")) messageCode = GET_CLIENTINFO_MESSAGE; + else if(!strcmp(message, "get ServerInfo")) messageCode = GET_SERVERINFO_MESSAGE; + else messageCode = OTHER_MESSAGE; + + // ********************************************************************* + // * Attempt to read the server name from the DDL file. + // ********************************************************************* + cdevData output; + + sprintf (DDL_server, "resolveServiceData %s %s", device, message); + if((system.nameServer()).send(DDL_server, NULL, &output)==CDEV_SUCCESS) + { + *DDL_server = 0; + output.get ("server", DDL_server, 256); + } + else *DDL_server = 0; + } + + +// ***************************************************************************** +// * cdevClientRequestObject::~cdevClientRequestObject: +// * This is the destructor for the object. It will free any memory that it +// * has allocated and remove itself from its associated ServerHandler +// * callback. +// ***************************************************************************** +cdevClientRequestObject::~cdevClientRequestObject ( void ) + { + if(handler!=NULL) handler->unregisterServerCallback(this); + } + + +// ***************************************************************************** +// * cdevClientRequestObject::getState : +// * Returns the connection state of the cdevClientRequestObject. +// ***************************************************************************** +int cdevClientRequestObject::getState ( void ) + { + ServerHandler * Handler = NULL; + return (getServerHandler(&Handler)==CDEV_SUCCESS)?CDEV_STATE_NOTCONNECTED:CDEV_STATE_CONNECTED; + } + + + +// ***************************************************************************** +// * cdevClientRequestObject::className : +// * Obtains the name of this class as a string. +// ***************************************************************************** +const char * cdevClientRequestObject::className ( void ) const + { + return "cdevClientRequestObject"; + } + + +// ***************************************************************************** +// * cdevClientRequestObject::setContext : +// * This method is called to set the context of the request object. The +// * first step in this process is to determine if the caller has specified +// * a server in the context. If so, the server name should be set to that +// * value. Next call the setContext method of the underlying +// * cdevRequestObject... +// ***************************************************************************** +int cdevClientRequestObject::setContext (cdevData& cxt) + { + cdevClientService * svc = (cdevClientService *)service_; + int result = CDEV_SUCCESS; + int newContextID = 0; + + if((newContextID = svc->contexts.insert(cxt))!=contextID) + { + ServerHandler * Handler = NULL; + + if(handler!=NULL) handler->unregisterServerCallback(this); + + contextID = newContextID; + *server = 0; + handler = NULL; + + cxt.get ("server", server, 256); + getServerHandler(&Handler); + + result = cdevRequestObject::setContext(cxt); + } + return result; + } + + +// ***************************************************************************** +// * cdevClientRequestObject::sendNoBlock : +// * This function allows the caller to submit an asynchronous message to the +// * server for processing. +// ***************************************************************************** +int cdevClientRequestObject::sendNoBlock (cdevData & in, cdevData & out) + { return sendNoBlock(&in, &out); } +int cdevClientRequestObject::sendNoBlock (cdevData * in, cdevData & out) + { return sendNoBlock(in, &out); } +int cdevClientRequestObject::sendNoBlock (cdevData & in, cdevData * out) + { return sendNoBlock(&in, out); } +int cdevClientRequestObject::sendNoBlock (cdevData * in, cdevData * out) + { + cdevClientService * svc = (cdevClientService *)service_; + cdevTranObj * xobj = new cdevTranObj(&system_, this, out, &svc->syncCallback); + ServerHandler * Handler = NULL; + int status = CDEV_SUCCESS; + + xobj->disableDeleteCbk(); + + if((status=getServerHandler(&Handler))==CDEV_SUCCESS) + { + status = svc->enqueue(Handler, in, *xobj); + } + else delete xobj; + return status; + } + + +// ***************************************************************************** +// * cdevClientRequestObject::sendCallback : +// * This function allows the caller to submit an asynchronous message to the +// * server for processing. +// ***************************************************************************** +int cdevClientRequestObject::sendCallback (cdevData & in, cdevCallback & callback) + { return sendCallback(&in, callback); } +int cdevClientRequestObject::sendCallback (cdevData * in, cdevCallback & callback) + { + cdevCallback * cb = new cdevCallback(callback); + cdevClientService * svc = (cdevClientService *)service_; + cdevTranObj * xobj = new cdevTranObj(&system_, this, NULL, cb); + ServerHandler * Handler = NULL; + int status = CDEV_SUCCESS; + + xobj->enableDeleteCbk(); + + if((status=getServerHandler(&Handler))==CDEV_SUCCESS) + { + status = svc->enqueue(Handler, in, *xobj); + } + else delete xobj; + return status; + } + + +// ***************************************************************************** +// * cdevClientRequestObject::send : +// * The send interface is used to provide synchronous I/O with the service. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int cdevClientRequestObject::send ( cdevData & in, cdevData & out ) + { return send(&in, &out); } +int cdevClientRequestObject::send ( cdevData * in, cdevData & out ) + { return send(in, &out); } +int cdevClientRequestObject::send ( cdevData & in, cdevData * out ) + { return send(&in, out); } +int cdevClientRequestObject::send ( cdevData * in, cdevData * out ) + { + int status = CDEV_SUCCESS; + cdevClientService * svc = (cdevClientService *)service_; + cdevTranObj * xobj = new cdevTranObj(&system_, this, out, &syncCallback); + ServerHandler * Handler; + + sendStatus.completionCode = 0; + sendStatus.finished = 0; + xobj->disableDeleteCbk(); + + if((status=getServerHandler(&Handler))==CDEV_SUCCESS) + { + if((status = svc->enqueue(Handler, in, *xobj))==CDEV_SUCCESS) + { + // ***************************************************** + // * I used to wait for a response here only if the outbound + // * cdevData object was non-null. However, that provided + // * unexpected behavior to the client. Now I wait whether + // * output data is expected or not. + // ***************************************************** + cdevTimeValue t(waitPeriod()); + cdevClock timer; + timer.schedule(NULL,t); + + // ***************************************************** + // * WAITING WITH system_.pend(): + // * Previously I was using system_.pend() to process + // * events while waiting for the service to respond. + // * This resulted in a lock-up when the connection + // * could not be established or if the connection + // * collapsed while in use. + // * + // * WAITING WITH system_.poll(): + // * When in a heavy inbound traffic situation, the + // * calls from other services will trample all over + // * the inbound data coming from the server. + // * This results in unreliable delivery and processing + // * of messages from the server. + // * + // * WAITING WITH service_.poll(): + // * So far so good. + // ***************************************************** + + while(!sendStatus.finished && !timer.expired()) service_->poll(); + if (!sendStatus.finished) + { + svc->cancel(*xobj); + status = CDEV_ERROR; + system_.reportError( + CDEV_SEVERITY_ERROR, + "cdevRequestObject", + this, + "Server failed to respond after %.1f seconds", + (float)waitPeriod()); + } + else + { + status = sendStatus.completionCode; + } + } + } + else delete xobj; + + return status; + } + + +// ***************************************************************************** +// * cdevClientRequestObject::defaultCallback : +// * This is the callback function that is used by the object to +// * receive callbacks for send operations. +// ***************************************************************************** +void cdevClientRequestObject::defaultCallback (int status, void * user, cdevRequestObject &, cdevData &) + { + SendStatus * result = (SendStatus *)user; + + if(result) + { + result->completionCode = status; + result->finished = 1; + } + } + + +// ***************************************************************************** +// * cdevClientRequestObject::executeServerHandlerCallback : +// * The requestObject registers itself with the ServerHandler when it +// * attaches to it... If the Serverhandler is destroyed, it will +// * call this method on all of the registered request objects in order +// * to notify them that it is going away. This allows the request +// * object to clear the pointer to the ServerHandler. +// ***************************************************************************** +void cdevClientRequestObject::executeServerHandlerCallback (ServerHandler * Handler) + { + if(Handler==handler) + { + /* + * system_.reportError(CDEV_SEVERITY_INFO, "cdevRequestObject", + * this, "Connection to %s broken for %s:%s", + * Handler->get_server(), device().name(), message()); + */ + handler=NULL; + } + } + + +// ***************************************************************************** +// * cdevClientRequestObject::getServerHandler : +// * This method is used to obtain the ServerHandler for this request +// * object... +// * +// * The following rules will be followed: +// * +// * 1) If a server has been specified in the context, then that +// * server will be used. +// * +// * - otherwise - +// * +// * 2) If a server has been specified in the service data of the +// * DDL file, then that server will be used. +// * +// * - otherwise - +// * +// * 3) The default server as specified at the cdevClientService will +// * be used. +// ***************************************************************************** +int cdevClientRequestObject::getServerHandler (ServerHandler ** Handler) + { + cdevClientService * svc = (cdevClientService *)service_; + int result = CDEV_SUCCESS; + + *Handler = NULL; + + if (*server==0 && *DDL_server!=0) strcpy(server, DDL_server); + if (*server!=0 && handler==NULL) + { + if((*Handler = svc->connect(server))==NULL) result = CDEV_ERROR; + else + { + handler = *Handler; + handler->registerServerCallback(this); + } + } + else *Handler = handler; + + return result; + } + +// ***************************************************************************** +// * cdevClientRequestObject::isRequestRestartable : +// * This method allows the caller to determine if the request object +// * is restartable. If a server goes down and then a new server comes +// * up in its place, this method will be called for each request object +// * that has an outstanding request that has not been serviced. +// * If the isRequestRestartable method returns 1, the request will be +// * sent to the new server - otherwise, the request will be terminated. +// ***************************************************************************** +int cdevClientRequestObject::isRequestRestartable ( void ) + { + int result = 0; + + switch(getCommandCode()) + { + case GET_COMMAND: + case MONITOR_ON_COMMAND: + result = 1; + break; + + case SET_COMMAND: + case MONITOR_OFF_COMMAND: + default: + result = 0; + break; + } + + return result; + } + +// ***************************************************************************** +// * cdevClientRequestObject::getContextID : +// * This method will retrieve the identifier of the context that is +// * currently in use by this object. +// ***************************************************************************** +int cdevClientRequestObject::getContextID ( void ) + { + return contextID; + } + + +// ***************************************************************************** +// * getCommandCode : +// * This method will return the current value of the commandCode variable. +// * This variable is used to identify the VERB that is utilized by this +// * cdevClientRequestObject. The default set of verbs are "get", "set", +// * "monitorOn", and "monitorOff". +// ***************************************************************************** +int cdevClientRequestObject::getCommandCode ( void ) { return commandCode; } + +// ***************************************************************************** +// * getMessageCode : +// * This method will return the current value of the messageCode variable. +// * This variable is used to identify the message that is utilized by this +// * cdevClientRequestObject. The default set of supported messages are +// * "get servers", "get default", "set default", and "disconnect". +// ***************************************************************************** +int cdevClientRequestObject::getMessageCode ( void ) { return messageCode; } + diff --git a/extensions/cdevGenericServer/cdevClient/cdevClientRequestObject.h b/extensions/cdevGenericServer/cdevClient/cdevClientRequestObject.h new file mode 100755 index 0000000..fc71085 --- /dev/null +++ b/extensions/cdevGenericServer/cdevClient/cdevClientRequestObject.h @@ -0,0 +1,223 @@ +#if !defined (_CDEV_CLIENT_REQUEST_OBJECT_H_) +#define _CDEV_CLIENT_REQUEST_OBJECT_H_ + +#include +#include +#include + +// ***************************************************************************** +// * cdevClientRequestObject: +// * The cdevClientRequestObject class provides the interface for sending +// * messages to a server. All device/message commands are routed +// * through a cdevClientRequestObject either directly or indirectly. +// ***************************************************************************** +class GENERIC_SERVER_API cdevClientRequestObject : public cdevRequestObject, public ServerHandlerCallback +{ +protected: + typedef struct + { + int completionCode; + int finished; + } SendStatus; + + SendStatus sendStatus; + char server [256]; + char DDL_server[256]; + cdevCallback syncCallback; + ServerHandler * handler; + int contextID; + + int commandCode; + int messageCode; + +public: + // ********************************************************************* + // * These enumerated type are used to identify the basic four commands + // * that might be represented by a cdevClientRequestObject... By using + // * these identifiers the cdevService does not have to perform a + // * string compare in order to identify the nature of the request + // * object. + // * + // * At construction the cdevClientRequestObject will set the + // * commandCode to contain the correct value, the developer may + // * override this setting in the constructor for an inherited class. + // * + // * Enumerated list extensions created by developers should begin at + // * value cdevClientRequestObject::MONITOR_OFF_COMMAND+1. + // * + // * The current setting of the commandCode may be obtained by calling + // * the getCommandCode method of the class. + // ********************************************************************* + enum {OTHER_COMMAND = 0, + GET_COMMAND, + SET_COMMAND, + MONITOR_ON_COMMAND, + MONITOR_OFF_COMMAND}; + + // ********************************************************************* + // * These enumerated type are used to identify the messages that are + // * intrinisicly supported by the cdevService... By using + // * these identifiers the cdevService does not have to perform a + // * string compare in order to identify the nature of the request + // * object. + // * + // * At construction the cdevClientRequestObject will set the + // * messageCode to contain the correct value, the developer may + // * override this setting in the constructor for an inherited class. + // * + // * Enumerated list extensions created by developers should begin at + // * value cdevClientRequestObject::SET_DEFAULT_MESSAGE+1 + // * + // * The current setting of the commandCode may be obtained by calling + // * the getMessageCode method of the class. + // ********************************************************************* + enum {OTHER_MESSAGE = 0, + GET_SERVERS_MESSAGE, + GET_DEFAULT_MESSAGE, + SET_DEFAULT_MESSAGE, + DISCONNECT_MESSAGE, + GET_CLIENTINFO_MESSAGE, + GET_SERVERINFO_MESSAGE}; + + cdevClientRequestObject ( char * device, char * message, + cdevSystem & system = cdevSystem::defaultSystem()); + + virtual ~cdevClientRequestObject ( void ); + + // ********************************************************************* + // * cdevClientRequestObject::getState : + // * Returns the connection state of the cdevClientRequestObject. + // ********************************************************************* + virtual int getState ( void ); + + // ********************************************************************* + // * cdevClientRequestObject::setContext : + // * This mechanism is used to specify the default server that will + // * be used for the request. + // ********************************************************************* + virtual int setContext ( cdevData & ctx); + + // ********************************************************************* + // * cdevClientRequestObject::send : + // * The send interface is used to provide synchronous I/O with the + // * service. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int send ( cdevData & in, cdevData & out ); + virtual int send ( cdevData * in, cdevData & out ); + virtual int send ( cdevData & in, cdevData * out ); + virtual int send ( cdevData * in, cdevData * out ); + + // ********************************************************************* + // * cdevClientRequestObject::sendNoBlock : + // * The sendNoBlock interface is used in conjunction with cdevGroup + // * or cdevSystem to execute a series of operations. During the + // * early implementation of this product, these functions will be + // * linked directly to the send call. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int sendNoBlock (cdevData & in, cdevData & out); + virtual int sendNoBlock (cdevData * in, cdevData & out); + virtual int sendNoBlock (cdevData & in, cdevData * out); + virtual int sendNoBlock (cdevData * in, cdevData * out); + + // ********************************************************************* + // * cdevClientRequestObject::sendCallback : + // * The sendCallback interface provides asynchronous communications + // * with the server. During the early implementation of this + // * product, these functions will be linked directly to the send + // * call. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int sendCallback (cdevData & in, cdevCallback & callback); + virtual int sendCallback (cdevData * in, cdevCallback & callback); + + virtual const char * className ( void ) const; + + // ********************************************************************* + // * cdevClientRequestObject::deafultCallback : + // * This is the callback function that is used by the object to + // * receive callbacks for send operations. + // ********************************************************************* + static void defaultCallback (int status, void * user, cdevRequestObject &, cdevData &); + + // ********************************************************************* + // * The requestObject registers itself with the ServerHandler when it + // * attaches to it... If the Serverhandler is destroyed, it will + // * call this method on all of the registered request objects in order + // * to notify them that it is going away. This allows the request + // * object to clear the pointer to the ServerHandler. + // ********************************************************************* + virtual void executeServerHandlerCallback (ServerHandler * Handler); + + // ********************************************************************* + // * This method is used to obtain the ServerHandler for this request + // * object... + // * + // * The following rules will be followed: + // * 1) If a server has been specified in the context, then that + // * server will be used. + // * + // * - otherwise - + // * + // * 2) If a server has been specified in the service data of the + // * DDL file, then that server will be used. + // * + // * - otherwise - + // * + // * 3) The default server as specified at the cdevClientService will + // * be used. + // ********************************************************************* + virtual int getServerHandler (ServerHandler ** Handler); + + // ********************************************************************* + // * This method allows the caller to determine if the request object + // * is restartable. If a server goes down and then a new server comes + // * up in its place, this method will be called for each request object + // * that has an outstanding request that has not been serviced. + // * If the isRequestRestartable method returns 1, the request will be + // * sent to the new server - otherwise, the request will be terminated. + // ********************************************************************* + virtual int isRequestRestartable ( void ); + + // ********************************************************************* + // * getContextID : + // * This method will retrieve the identifier of the context that + // * is currently in use by this object. + // ********************************************************************* + int getContextID ( void ); + + // ********************************************************************* + // * getCommandCode : + // * This method will return the current value of the commandCode + // * variable. This variable is used to identify the VERB that is + // * utilized by this cdevRequestObject. The default set of verbs + // * are "get", "set", "monitorOn", and "monitorOff". + // ********************************************************************* + int getCommandCode ( void ); + + // ********************************************************************* + // * getMessageCode : + // * This method will return the current value of the messageCode + // * variable. This variable is used to identify the message that is + // * utilized by this cdevRequestObject. The default set of + // * supported messages are "get servers", "get default", + // * "set default", and "disconnect". + // ********************************************************************* + int getMessageCode ( void ); + + + // ********************************************************************* + // * waitPeriod : + // * This method returns a double that indicates the maximum amount + // * of time that the service should wait for a synchronous result to + // * be returned. + // ********************************************************************* + virtual double waitPeriod ( void ) { return 10.0; } +}; + + +#endif /* _CDEV_CLIENT_REQUEST_OBJECT_H_ */ diff --git a/extensions/cdevGenericServer/cdevClient/cdevClientService.cc b/extensions/cdevGenericServer/cdevClient/cdevClientService.cc new file mode 100755 index 0000000..e3f6950 --- /dev/null +++ b/extensions/cdevGenericServer/cdevClient/cdevClientService.cc @@ -0,0 +1,1219 @@ +#include +#include +#include +#include +#include + +int cdevClientService::ServerTag = 0; +int cdevClientService::HostTag = 0; +int cdevClientService::PortTag = 0; + +cdevGenericServerTagDef cdevClientService::tags; + +// ***************************************************************************** +// * ClientInfo clientInfo : +// * This is a static member of the cdevClientService class that contains +// * descriptive information about the client process. +// ***************************************************************************** +ClientInfo cdevClientService::clientInfo; + +// ***************************************************************************** +// * cdevClientTransaction::freeList_ : +// * This is the free list for the cdevClientTransaction object that is +// * used to reduce run-time memory allocations. +// ***************************************************************************** +cdevClientTransaction * cdevClientTransaction::freeList_ = NULL; + +// ***************************************************************************** +// * This is the text string that will be used to define the cdevNameServer +// * if it has not yet been defined in the cdevDirectory file. +// ***************************************************************************** +static char * NameServerDefinitionString = +"service rns { tags {PV} }\n\ +class RNS { messages { query rns; get rns; monitorOn rns; monitorOff rns; monitorEntry rns; monitorEntryOff rns; } }\n\ +RNS :\nNameServer\n;\n"; + +// ***************************************************************************** +// * cdevClientService::cdevClientService : +// * This is the constructor for the object. Its is responsible for +// * initializing the underlying classes and data items. +// ***************************************************************************** +cdevClientService::cdevClientService ( char * Domain, char * name, cdevSystem & system ) + : ServerInterface (), + syncCallback (defaultCallback, NULL), + domain (strdup(Domain)), + cdevService (name, system), + transactions (), + contexts (), + nsCallbackArgs (0) + { + // ********************************************************************* + // * Determine if the NameServer has been provided in the CDEVDDL file. + // * If not, add the NameServer to the cdevDirectory. + // ********************************************************************* + cdevDirectory & nameServer = system.nameServer(); + cdevData request; + cdevData reply; + + request.insert("device", "NameServer"); + if(nameServer.send("queryClass", request, reply)==CDEV_NOTFOUND) + { + request.insert("file", NameServerDefinitionString); + nameServer.send("update", request, NULL); + } + + // ********************************************************************* + // * If the tags used by this service have not yet been defined in the + // * cdevGlobalTagTable, then automatically define them here. + // ********************************************************************* + if(ServerTag==0) + { + cdevData::insertTag(ServiceTagBase+1, "server"); + cdevData::insertTag(ServiceTagBase+2, "host"); + cdevData::insertTag(ServiceTagBase+3, "port"); + cdevData::tagC2I("server", &ServerTag); + cdevData::tagC2I("host", &HostTag); + cdevData::tagC2I("port", &PortTag); + } + + // ********************************************************************* + // * Install a tag callback that will automicatically be executed each + // * time a new tag is added to the cdevGlobalTagTable. + // ********************************************************************* + cdevData::addTagCallback(this); + } + + +// ***************************************************************************** +// * cdevClientService::~cdevClientService : +// * This is the destructor for the object. It will call release any +// * memory that was allocated by the class. +// ***************************************************************************** +cdevClientService::~cdevClientService ( void ) + { + AddressIndexIterator iter (&transactions); + StringHashIterator sIter(&nsCallbackArgs); + cdevClientTransaction * xobj; + + if(domain) delete domain; + + for(iter.first(); (xobj = (cdevClientTransaction *)iter.data())!=NULL; iter++) + { + transactions.remove(iter.key()); + + delete xobj; + } + + NSCallbackArg * nsData; + for(sIter.first(); (nsData = (NSCallbackArg *)sIter.data())!=NULL; sIter++) + { + delete nsData; + } + + cdevData::delTagCallback(this); + } + + +// ***************************************************************************** +// * cdevClientService::defaultCallback : +// * This is the callback function that is used to support sendNoBlock +// * requests that are issued by the cdevRequestObject. +// ***************************************************************************** +void cdevClientService::defaultCallback (int, void *, cdevRequestObject &, cdevData & ) + { + } + + +// ***************************************************************************** +// * cdevClientService::nameServerCallback : +// * This is the callback function that is executed whenever one of the +// * connected servers becomes disconnected. This function will call each +// * of the request objects associated with the server and notify them +// * of the server's change in status. +// ***************************************************************************** +void cdevClientService::nameServerCallback(int, void *userarg, cdevRequestObject &, cdevData & data) + { + NSCallbackArg * arg = (NSCallbackArg *)userarg; + cdevClientService * cService = arg->service; + unsigned short port = 0; + int statusCode = -1; + cdevData userData; + char server[255]; + char host[255]; + + // ********************************************************************* + // * Initialize the server and host variables to empty strings, this + // * will allow me to detect if the data was actually extracted from the + // * cdevData object. + // ********************************************************************* + *server = 0; + *host = 0; + + // ********************************************************************* + // * The status code from the name server should be between 0 and 3. + // * If the status code is out of range, display an error and return. + // ********************************************************************* + data.get("status", &statusCode); + if(statusCode<0) + { + cService->outputError(CDEV_SEVERITY_ERROR, + "cdevClientService", + "Name Server is down..."); + return; + } + else if(statusCode>3) + { + cService->outputError(CDEV_SEVERITY_ERROR, + "cdevClientService", + "Unknown status code (%i) received from Name Server", + statusCode); + return; + } + + // ********************************************************************* + // * Read critical tags from the cdevData object. + // ********************************************************************* + data.get("name", server, 255); + data.get("host", host, 255); + data.get("port", &port); + + // ********************************************************************* + // * Determine if a live connection still exists to the specified server + // ********************************************************************* + ServerHandler * handler = cService->connections.find(server); + + // ********************************************************************* + // * If the handler is NULL this means that the application has already + // * become disconnected from the server. Consequently, all restartable + // * requests will have to be resent and all other requests will have + // * to be terminated. + // * For this reason, if the statusCode coming from Name Server is 0, + // * it should be set to 3 (indicating a server restart). If the status + // * code coming from the server is a 1 then it should be set to 2 + // * (indicating a dead server). + // ********************************************************************* + if(handler==NULL && statusCode==0) statusCode=3; + if(handler==NULL && statusCode==1) statusCode=2; + + // ********************************************************************* + // * If the statusCode is 2 (terminated server) and the ServerHandler + // * is not equal to NULL, then delete the ServerHandler to force the + // * connection to be closed. + // ********************************************************************* + if(statusCode==2 && handler!=NULL) + { + delete handler; + handler = NULL; + } + + // ********************************************************************* + // * Report the condition of the connection. + // ********************************************************************* + cService->outputError(CDEV_SEVERITY_INFO, "cdevClientService", + "Name Server reports server %s in domain %s has been %s", + server, cService->getDomain(), + ((statusCode==0)?"CONNECTED":((statusCode==1)?"DISCONNECTED": + ((statusCode==2)?"TERMINATED":"RESTARTED")))); + + // ********************************************************************* + // * Walk through the list of transactions and process those with a + // * matching server name and a differing status code. + // ********************************************************************* + AddressIndexIterator iter(&cService->transactions); + cdevClientTransaction * trans; + + for(iter.first(); (trans = (cdevClientTransaction *)iter.data())!=NULL; iter++) + { + cdevTranObj * xobj = trans->xobj; + cdevCallback * cb = xobj->userCallback_; + + // ************************************************************* + // * Process transactions associated with this specific server. + // ************************************************************* + if(trans->statusCode!=statusCode && !strcmp(trans->server, server)) + { + // ***************************************************** + // * Status code of 0 indicates that the server is + // * online and operational. We also check the + // * ServerHandler to ensure that we still have a + // * valid connection. + // ***************************************************** + if(statusCode==0) + { + cb->fireCallback(CDEV_RECONNECTED, cb->userarg(), + *xobj->reqObj_, userData, 1); + if(trans->statusCode<0) + { + trans->reconnect(host, port, iter.key()); + } + } + // ***************************************************** + // * Status code of 1 indicates that the server has + // * ceased sending periodic updates to the name server + // ***************************************************** + else if (statusCode==1) + { + cb->fireCallback(CDEV_DISCONNECTED, cb->userarg(), + *xobj->reqObj_, userData, 1); + trans->statusCode = statusCode; + } + // ***************************************************** + // * Status code of 2 indicates that the server has + // * terminated and all connections are lost. + // ***************************************************** + else if (statusCode==2 && trans->restartable) + { + cb->fireCallback(CDEV_DISCONNECTED, cb->userarg(), + *xobj->reqObj_, userData, 1); + trans->statusCode = statusCode; + } + // ***************************************************** + // * Status code of 3 indicates that a new server with + // * an identical name and domain has taken the place + // * of the dead server. If the transaction is + // * restartable, resubmit the request to the server. + // ***************************************************** + else if (statusCode==3 && trans->restartable) + { + trans->statusCode = -1; + trans->reconnect(host, port, iter.key()); + } + // ***************************************************** + // * This section will catch the statusCode 2 and 3 + // * events where the request is not restartable and + // * will delete these transactions. + // ***************************************************** + else if (statusCode==2 || statusCode==3) + { + cb->fireCallback(CDEV_ERROR, cb->userarg(), + *xobj->reqObj_, userData, 0); + cService->transactions.remove(iter.key()); + delete trans; + } + } + } + } + + +// ***************************************************************************** +// * cdevClientService::outputError : +// * This mechanism is used to report errors to the system. +// ***************************************************************************** +int cdevClientService::outputError(int severity, char *name, char *formatString, ...) + { + int status; + va_list argp; + + va_start (argp, formatString); + status = system_.vreportError(severity, name, NULL, formatString, argp); + va_end (argp); + + return status; + } + + +// ***************************************************************************** +// * cdevClientService::connect : +// * This mechanism will establish a new connection with a server and will +// * will return a pointer to the ServerHandler. If the host and port are +// * specified in the arguments, then the method will attempt to connect +// * using those values without going through the CDEV Name Server. +// * +// * Note: This method will insert the ServerHandler into the connections +// * object and will install it in the Reactor. +// ***************************************************************************** +ServerHandler * cdevClientService::connect ( char * server, char * host, unsigned short port ) + { + ServerHandler * handler = NULL; + + // ********************************************************************* + // * First attempt to locate the handler from the existing connections. + // ********************************************************************* + if(server && *server && (handler = connections.find(server))==NULL) + { + int errCode = CDEV_SUCCESS; + char serverHost[255]; + unsigned short serverPort; + int serverStatus; + + // ************************************************************* + // * If the host and port have been specified, then use them + // * rather than going through the CDEV Name Server. + // ************************************************************* + if(host!=NULL && *host && port>0) + { + strcpy(serverHost, host); + serverPort = port; + } + else { + cdevData input; + cdevData output; + cdevRequestObject & rnsReq = + cdevRequestObject::attachRef("NameServer", "get"); + + *serverHost = 0; + serverPort = 0; + + // ***************************************************** + // * Insert domain and name in the input request object + // * to be sent to the CDEV Name Server. + // ***************************************************** + input.insert("name", server); + input.insert("domain", domain); + + // ***************************************************** + // * Query the Name Server to obtain the hostname and + // * port of the specified domain and server. + // ***************************************************** + if((errCode=rnsReq.send(input, output))!=CDEV_SUCCESS || + output.get("host", serverHost, 255)!=CDEV_SUCCESS || + output.get("port", &serverPort)!=CDEV_SUCCESS || + output.get("status", &serverStatus)!=CDEV_SUCCESS || + *serverHost==0 || serverPort<=0 || serverStatus!=0) + { + errCode = CDEV_ERROR; + + // ********************************************* + // * If the hostname could not be found, report + // * the error and set the return value to + // * CDEV_ERROR. + // ********************************************* + outputError(CDEV_SEVERITY_ERROR, + "cdevClientService::connect", + "Cannot find host for server \"%s\" in domain \"%s\"", + server, domain); + } + } + + + // ************************************************************* + // * If the hostname was discovered, then the errCode should be + // * CDEV_SUCCESS. Attempt to connect to the server using the + // * cdevReactor mechanisms. + // ************************************************************* + if(errCode==CDEV_SUCCESS) + { + cdevInetAddr addr; + + addr.set (serverPort, serverHost); + + handler = new ServerHandler(server, this); + + if(handler->open(addr)!=0) + { + outputError(CDEV_SEVERITY_ERROR, + "cdevClientService::connect", + "Failed to connect to %s on port %i", + serverHost, + serverPort); + delete handler; + handler = NULL; + } + else { + outputError(CDEV_SEVERITY_INFO, + "cdevClientService::connect", + "Connected to %s on port %i", + serverHost, + serverPort); + connections.insert(handler); + + // ********************************************* + // * This calls the registerFd method of the + // * service which will cause the FD Changed + // * callbacks to be triggered. + // ********************************************* + registerFd(handler->getHandle(), 1); + + // ********************************************* + // * Install a Name Server monitor to maintain + // * the status of the connection. + // * Note: If a monitor has already been + // * installed using this informations, then the + // * CDEV Name Server service should not create + // * a second monitor. + // * + // * Note: I am using the FifoQueue associated + // * with the specific server in order to + // * differentiate between the various servers. + // ********************************************* + cdevData monData; + cdevCallback monCb(nameServerCallback, (void *)getCallbackArg(server)); + cdevRequestObject & monReq = cdevRequestObject::attachRef("NameServer", "monitorOn"); + + monData.insert("name", server); + monData.insert("domain", domain); + monReq.sendCallback(monData, monCb); + + // ********************************************* + // * Here is where a "set ClientInfo" message + // * will be sent to the server to provide + // * descriptive information about the client. + // ********************************************* + cdevData tagMap; + int * itags; + char ** ctags; + int ntags; + char * binary = NULL; + size_t binaryLen = 0; + + cdevData::readTagTable(itags, ctags, ntags); + tagMap.insert(1, itags, ntags); + tagMap.insert(2, ctags, ntags); + + delete itags; + delete ctags; + handler->setTagChangeFlag(0); + + cdevMessageBinary packet(handler->getClientID(), + 0, 0, 0, 0, CDEV_SERVER_OP, 0, 0, + NULL, "set ClientInfo", + &clientInfo.getClientData(), + NULL, &tagMap); + + packet.streamOut(&binary, &binaryLen); + packet.detachData(); + + ServerInterface::enqueue(handler, binary, binaryLen); + } + } + } + return handler; + } + + +// ***************************************************************************** +// * cdevClientService::disconnect : +// * This mechanism will remove the ServerHandler pointer from the +// * connections list and will return the ServerHandler pointer to the +// * caller. It is the responsibility of the caller to delete the +// * ServerHandler pointer. +// ***************************************************************************** +ServerHandler * cdevClientService::disconnect ( char * server ) + { + ServerHandler * handler; + + // ********************************************************************* + // * Find and remove the specified server. This method will also check + // * to determine if the handler that is being disconnected is the + // * defaultServer - if so, the defaultServerHandler variable will be + // * set to NULL. + // ********************************************************************* + if((handler = connections.remove(server))==defaultServerHandler) + { + defaultServerHandler = NULL; + } + // ********************************************************************* + // * This calls the registerFd method of the service which will cause + // * the FD Changed callbacks to be triggered. + // ********************************************************************* + if(handler!=NULL && handler->getHandle()!=cdevSocket::INVALID_HANDLE) + { + registerFd(handler->getHandle(), 0); + } + + return handler; + } + +// ***************************************************************************** +// * cdevClientService::flush : +// * This is method calls the flush mechanism of the underlying +// * ServerInterface class. +// ***************************************************************************** +int cdevClientService::flush ( void ) + { + return ServerInterface::flush(); + } + + + +// ***************************************************************************** +// * cdevClientService::pend : +// * This method calls the pend mechanism of the underlying +// * ServerInterface class. +// ***************************************************************************** +int cdevClientService::pend ( double seconds, int fd ) + { + return ServerInterface::pend(seconds, fd); + } + + +// ***************************************************************************** +// * cdevClientService::getFd : +// * This method calls the getFd mechanism of the underlying +// * ServerInterface class. +// ***************************************************************************** +int cdevClientService::getFd( int * &fd, int & numFd ) + { + return ServerInterface::getFd(fd, numFd); + } + + +// ***************************************************************************** +// * cdevClientService::poll : +// * This is the polling mechanism for the service. +// ***************************************************************************** +int cdevClientService::poll ( void ) + { + return ServerInterface::poll(); + } + + +// ***************************************************************************** +// * cdevClientService::pend : +// * This method does not implement the full functionality of the +// * cdev prototype. Rather it pends for a default amount of time. +// ***************************************************************************** +int cdevClientService::pend( int fd) + { + return pend(0.01, fd); + } + + +// ***************************************************************************** +// * cdevClientService::getNameServer : +// * This method is used to provide a cdevDevice that can be used as the +// * name server for the service. It is not implemented here. +// ***************************************************************************** +int cdevClientService::getNameServer ( cdevDevice * &ns ) + { + ns = NULL; + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * cdevClientService::getRequestObject : +// * This is the interface that cdev objects will use to obtain a +// * cdevClientRequestObject object. The cdevClientRequestObject +// * represents a combined device and message pair that is associated +// * with the cdevClientService. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int cdevClientService::getRequestObject ( char * device, char * message, cdevRequestObject * &req) + { + req = new cdevClientRequestObject (device, message, system_); + return (req ? CDEV_SUCCESS : CDEV_ERROR); + } + + +// ***************************************************************************** +// * cdevClientService::enqueue : +// * This is the method that is used by the cdevRequestObject to submit a +// * message to the cdevServer when the name of the server is known, but a +// * ServerHandler object has not yet been obtained... +// ***************************************************************************** +int cdevClientService::enqueue ( char * server, cdevData * in, cdevTranObj & xobj ) + { + ServerHandler * handler = server==NULL?defaultServerHandler:connect(server); + + return enqueue(handler, in, xobj); + } + + +// ***************************************************************************** +// * cdevClientService::enqueue : +// * This method is used by the cdevRequestObject to enqueue an outbound +// * message to the cdevServer when the ServerHandler has already been +// * obtained. +// ***************************************************************************** +int cdevClientService::enqueue ( ServerHandler * handler, cdevData * in, cdevTranObj &xobj) + { + int result = CDEV_SUCCESS; + + // ********************************************************************* + // * Determine if the message will be processed locally first. + // * If not, then submit it to the underlying ServerInterface + // * for processing. + // ********************************************************************* + if(processLocal(in, xobj)!=0) + { + // ************************************************************* + // * Determine if the handler is valid or use the + // * defaultServerHandler + // ************************************************************* + if(handler==NULL) + { + if(defaultServerHandler!=NULL) + { + handler=defaultServerHandler; + } + else if(defaultServerHandler==NULL && defaultServer!=NULL) + { + handler = (defaultServerHandler=connect(defaultServer)); + } + else { + system_.reportError(CDEV_SEVERITY_ERROR, + "cdevClientService::enqueue", + xobj.reqObj_, + "No default server has been defined for this service"); + } + } + + // ************************************************************* + // * If a valid ServerHandler has been located. + // ************************************************************* + if(handler!=NULL) + { + cdevClientRequestObject * reqObj; + int restart; + int ctxID; + cdevClientTransaction * node; + unsigned index; + + reqObj = (cdevClientRequestObject *)xobj.reqObj_; + restart = reqObj->isRequestRestartable(); + ctxID = reqObj->getContextID(); + node = new cdevClientTransaction(xobj, *handler, restart, in, ctxID); + index = transactions.insert(node); + + if((result=enqueue(handler, *node, index))!=CDEV_SUCCESS) + { + transactions.remove(index); + delete node; + } + else { + // ********************************************* + // * If the message is monitorOff, then the + // * method will walk through all of the active + // * monitors and remove those that exactly match + // * all attributes of the request.... + // * - Server name + // * - Device name + // * - Attribute name + // * - Context values + // ********************************************* + if(reqObj->getCommandCode()==cdevClientRequestObject::MONITOR_OFF_COMMAND) + { + #define xCommand ((cdevClientRequestObject *)trans->xobj->reqObj_)->getCommandCode() + #define xDevice xobj->reqObj_->device().name() + #define xMessage xobj->reqObj_->message() + #define xUserarg xobj->userCallback_->userarg() + #define xCallback xobj->userCallback_->callbackFunction() + + AddressIndexIterator iter(&transactions); + cdevClientTransaction * trans; + cdevMessageBinary packet; + char * device = (char *)reqObj->device().name(); + char * binary; + size_t binaryLen; + + for(iter.first(); (trans=(cdevClientTransaction *)iter.data())!=NULL; iter++) + { + if(xCommand==cdevClientRequestObject::MONITOR_ON_COMMAND && + (node->xUserarg==NULL || node->xUserarg==trans->xUserarg) && + (node->xCallback==NULL || node->xCallback==trans->xCallback) && + !strcmp(node->xDevice, trans->xDevice) && + !strcmp(node->xMessage+11, trans->xMessage+10) && + !strcmp(node->server, trans->server)) + { + int cancelTransIdx = iter.key(); + + // ********************************************** + // * Remove the transaction and delete it. + // ********************************************** + transactions.remove(cancelTransIdx); + + // ********************************************** + // * Fire the callback with the + // * partialTransaction flag set to 0 to notify + // * the developer that the transaction is + // * finished. Note that the status is + // * CDEV_WARNING because no actual data is + // * being delivered. + // ********************************************** + fireCallback(CDEV_WARNING, *trans->xobj, NULL, 0); + + delete trans; + + // ********************************************** + // * Send a packet containing the transaction to + // * be destroyed. + // ********************************************** + packet.set(handler->getClientID(), 0, cancelTransIdx, 0, 0, 0, 0, 1, + &device, xobj.reqObj_->message()); + + packet.streamOut(&binary, &binaryLen); + packet.detachData(); + ServerInterface::enqueue(handler, binary, binaryLen); + } + } + + #undef xCommand + #undef xDevice + #undef XMessage + #undef XUserarg + #undef XCallback + } + } + } + else result = CDEV_ERROR; + } + + return result; + } + + +// ***************************************************************************** +// * cdevClientService::enqueue : +// * This method is called by the internals of the cdevClientService to +// * submit a message to a server. This method is called by either the +// * enqueue method (to initially submit a request), or the nameServerCallback +// * method ( to resubmit a request when a server has restarted). +// ***************************************************************************** +int cdevClientService::enqueue ( ServerHandler * handler, cdevClientTransaction &trans, unsigned transID ) + { + int result; + + // ********************************************************************* + // * If the server handler is valid and a connection has been + // * established. + // ********************************************************************* + if(handler!=NULL) + { + cdevTranObj * xobj = trans.xobj; + cdevClientRequestObject * reqObj = (cdevClientRequestObject *)xobj->reqObj_; + char * device = (char *)reqObj->device().name(); + int ctxID = trans.contextID; + cdevData * in = trans.userData; + cdevData * context = NULL; + cdevData * tagMap = NULL; + int opCode = CDEV_NORMAL_OP; + + // ************************************************************* + // * Set the operation code to CDEV_SERVER_OP if the message + // * should be processed by the cdevGenericServer Engine rather + // * than the user defined server engine. + // ************************************************************* + if(reqObj->getMessageCode()==cdevClientRequestObject::GET_CLIENTINFO_MESSAGE || + reqObj->getMessageCode()==cdevClientRequestObject::GET_SERVERINFO_MESSAGE) + { + opCode=CDEV_SERVER_OP; + } + + // ************************************************************* + // * Switch to the contextID specified in trans parameter. + // ************************************************************* + if(handler->getContextID()!=ctxID) + { + context = contexts.find(ctxID); + handler->setContextID(ctxID); + } + + // ************************************************************* + // * If the tag map has changed, include it in the transmission + // ************************************************************* + if(handler->getTagChangeFlag()) + { + int * itags; + char ** ctags; + int ntags; + + cdevData::readTagTable(itags, ctags, ntags); + tagMap = new cdevData; + tagMap->insert(1, itags, ntags); + tagMap->insert(2, ctags, ntags); + + delete itags; + delete ctags; + handler->setTagChangeFlag(0); + } + + // ************************************************************* + // * Construct the outbound packet. + // ************************************************************* + cdevMessageBinary packet(handler->getClientID(), transID, + 0, 0, 0, opCode, 0, 1, + &device, + reqObj->message(), + in, + context, + tagMap); + + // ************************************************************* + // * Delete the tag map if it was allocated. + // ************************************************************* + if(tagMap) delete tagMap; + + // ************************************************************* + // * Extract the binary stream representation of the data and + // * then use the detach data mechanism to ensure that the + // * binary buffer is not deleted when the packet object is + // * destroyed. + // ************************************************************* + char * binary = NULL; + size_t binaryLen = 0; + packet.streamOut(&binary, &binaryLen); + packet.detachData(); + + + // ************************************************************* + // * Enqueue the message into the outbound queue. + // ************************************************************* + result=ServerInterface::enqueue(handler, binary, binaryLen); + } + else result = CDEV_ERROR; + + return result; + } + +// ***************************************************************************** +// * cdevClientService::cancel : +// * This method is used to cancel a transaction that has taken too long +// * to be processed. +// ***************************************************************************** +int cdevClientService::cancel ( cdevTranObj & xobj ) + { + AddressIndexIterator iter(&transactions); + cdevClientTransaction * node; + + for(iter.first(); (node=(cdevClientTransaction *)iter.data())!=NULL && node->xobj!=&xobj; iter++); + if(node!=NULL) + { + transactions.remove(iter.key()); + delete node; + } + + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * cdevClientService::enqueue : +// * This is the mechanism that is used by the underlying ServerInterface +// * to return the result of a transmission to the caller. DO NOT DELETE +// * THE BINARY PROVIDED TO THIS CLASS. +// ***************************************************************************** +int cdevClientService::enqueue ( int status, ServerHandler * /*handler*/, char * binary, size_t binaryLen ) + { + cdevMessage message(binary, binaryLen); + cdevClientTransaction * node; + + if((node=(cdevClientTransaction *)transactions.find(message.getTransIndex()))!=NULL) + { + int completionCode = (status==FAILED_TO_SEND)?CDEV_ERROR:message.getCompletionCode(); + + if(status==FAILED_TO_SEND) node->permanent = 0; + + fireCallback(completionCode, *node->xobj, message.getData(), node->permanent); + + if(!node->permanent) + { + transactions.remove(message.getTransIndex()); + delete node; + } + } + + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * cdevClientService::fireCallback : +// * This method is used to deploy a callback on a specific transaction. +// ***************************************************************************** +void cdevClientService::fireCallback ( int status, + cdevTranObj &xobj, + cdevData *resultData, + int partialTransaction) + { + static cdevData dummy; + + if(resultData==NULL) + { + dummy.remove(); + resultData = &dummy; + } + if(xobj.resultData_!=NULL) *xobj.resultData_ = *resultData; + + xobj.userCallback_->fireCallback + (status, + xobj.userCallback_->userarg(), + *xobj.reqObj_, + xobj.resultData_!=NULL?*xobj.resultData_:*resultData, + partialTransaction); + } + + +// ***************************************************************************** +// * cdevClientService::processLocal: +// * This method performs any localized data processing that the service +// * might require. If the message is processed locally, this method should +// * return 0... otherwise, the method should return non-zero. +// ***************************************************************************** +int cdevClientService::processLocal ( cdevData * in, cdevTranObj & xobj) + { + int result = 1; + int status = CDEV_SUCCESS; + cdevClientRequestObject * reqObj = (cdevClientRequestObject *)xobj.reqObj_; + + switch(reqObj->getMessageCode()) + { + case cdevClientRequestObject::GET_SERVERS_MESSAGE: + { + char queryMsg[256]; + cdevData input; + cdevData output; + cdevRequestObject & nsReq = + cdevRequestObject::attachRef("NameServer", "query"); + + sprintf(queryMsg, "domain=='%s'", getDomain()); + input.insert("queryMsg", queryMsg); + if((status=nsReq.send(input, output))==CDEV_SUCCESS) + { + output.changeTag ("name", "value"); + } + fireCallback(status, xobj, &output); + result = CDEV_SUCCESS; + } + break; + + case cdevClientRequestObject::GET_DEFAULT_MESSAGE: + { + cdevData resultData; + resultData.insert("value", getDefault()); + fireCallback(CDEV_SUCCESS, xobj, &resultData); + result = CDEV_SUCCESS; + } + break; + + case cdevClientRequestObject::SET_DEFAULT_MESSAGE: + { + cdevData resultData; + char DefaultServer[128]; + + *DefaultServer = 0; + + if(in!=NULL && in->get("value", DefaultServer, 128)==CDEV_SUCCESS && *DefaultServer!=0) + { + setDefault(DefaultServer); + } + else status=CDEV_ERROR; + fireCallback(status, xobj, &resultData); + result = CDEV_SUCCESS; + } + break; + + case cdevClientRequestObject::DISCONNECT_MESSAGE: + { + cdevData resultData; + char server [128]; + int status; + + if(xobj.reqObj_->getContext().get("server", server, 128)==CDEV_SUCCESS) + { + disconnect(server); + status = CDEV_SUCCESS; + } + else status = CDEV_ERROR; + + fireCallback(status, xobj, &resultData); + result = CDEV_SUCCESS; + } + break; + + default: + break; + } + return result; + } + + +// ***************************************************************************** +// * cdevClientService::isPacketValid : +// * This method is called by the ServerHandler after it has been restarted. +// * If the ServerHandler inherits packets that are already in the queue, it +// * will call this method for each packet in order to determine if they are +// * valid. If the packets are no longer valid (i.e., there is no longer +// * a cdevTransObj associated with them, they will be deleted. Otherwise, +// * they will be submitted to the server. +// ***************************************************************************** +int cdevClientService::isPacketValid ( char * binary, size_t binaryLen ) + { + int result; + + if(binary!=NULL && binaryLen>0) + { + cdevMessageBinary message; + unsigned int trans; + message.getTransIndex(trans); + message.attachData(binary, binaryLen); + result = transactions.find(trans)?1:0; + message.detachData(); + } + else result = 0; + + return result; + } + + +// ***************************************************************************** +// * cdevClientService::callback : +// * This method is called by the cdevData object whenever a new tag is +// * added. +// ***************************************************************************** +void cdevClientService::callback ( int, char * ) + { + for(int idx=0; connections[idx]!=NULL; idx++) + { + connections[idx]->setTagChangeFlag(1); + } + } + + +// ***************************************************************************** +// * cdevClientService::getCallbackArg : +// * This method creates a unique callback argument that can be passed to the +// * CDEV Name Server service to allow it to differentiate between two +// * servers that are being accessed through the same service. +// ***************************************************************************** +NSCallbackArg * cdevClientService::getCallbackArg ( char * server ) + { + NSCallbackArg * ptr; + if((ptr = (NSCallbackArg *)nsCallbackArgs.find(server))==NULL) + { + ptr = new NSCallbackArg(server, this); + nsCallbackArgs.insert(ptr->server, ptr); + } + return ptr; + } + +// ***************************************************************************** +// * cdevClientTransaction::operator new: +// * Allocation function for the object. It will get the next preallocated +// * cdevClientTransaction object from the free list, or, if none are available, +// * refill the free list and then return a new cdevClientTransaction object. +// ***************************************************************************** +void * cdevClientTransaction::operator new ( size_t ) + { + cdevClientTransaction * result = NULL; + + if(freeList_==NULL) + { + freeList_ = ::new cdevClientTransaction[ALLOCATION_COUNT]; + for(int i=0; ifreeListNext_; + result->freeListNext_ = NULL; + } + + return result; + } + +// ***************************************************************************** +// * cdevClientTransaction::delete: +// * Rather than deallocating the cdevClientTransaction object, this function +// * returns it to the free list where it may be retrieved by a later call +// * of new. +// ***************************************************************************** +void cdevClientTransaction::operator delete ( void * ptr ) + { + cdevClientTransaction * node = (cdevClientTransaction *)ptr; + if(node != NULL) + { + node->freeListNext_ = freeList_; + freeList_ = node; + } + } + +// ***************************************************************************** +// * cdevClienTransaction::cdevClientTransaction : +// * Array constructor for the cdevClientTransaction object. +// ***************************************************************************** +cdevClientTransaction::cdevClientTransaction (void) + : xobj (NULL), + permanent (0), + statusCode (0), + restartable(0), + contextID (0), + userData (NULL) + { + *server = 0; + } + + +// ***************************************************************************** +// * cdevClienTransaction::cdevClientTransaction : +// * Constructor for the cdevClientTransaction object. +// ***************************************************************************** +cdevClientTransaction::cdevClientTransaction (cdevTranObj & XObj, ServerHandler &handler, + int Restartable, cdevData * data, + unsigned ContextID) + : xobj (&XObj), + permanent (0), + statusCode (0), + restartable(Restartable), + contextID (ContextID), + userData (NULL) + { + permanent = ((cdevClientRequestObject *)xobj->reqObj_)->getCommandCode()== + cdevClientRequestObject::MONITOR_ON_COMMAND; + strncpy(server, handler.getServer(), 256); + server[255] = 0; + + if(restartable && data) userData = new cdevData(*data); + else userData = data; + } + +// ***************************************************************************** +// * cdevClientTransaction::~cdevClientTransaction : +// * Destructor for the cdevClientTransaction object. +// ***************************************************************************** +cdevClientTransaction::~cdevClientTransaction ( void ) + { + if(xobj) delete xobj; + if(restartable && userData) delete userData; + } + + +// ***************************************************************************** +// * cdevClientTransaction::reconnect : +// * This method will attempt to recreate a connection for a server to +// * a specified host and port. If the host and port are not specified, +// * the the cdevClientService::connect and cdevClientService::find methods +// * will be used to reattach to the specified server. +// ***************************************************************************** +void cdevClientTransaction::reconnect ( char * host, unsigned short port, unsigned key) + { + cdevClientService &service = (cdevClientService &)xobj->reqObj_->service(); + + if(key==0) key = service.transactions.find((void *)this); + + if(restartable && statusCode<0 && key) + { + ServerHandler *handler = NULL; + + // ************************************************************* + // * Use the find method to locate the ServerHandler if + // * possible, otherwise use the connect method to reconnect to + // * the server. + // ************************************************************* + if((handler=service.connections.find(server))==NULL) + handler = service.connect(server, host, port); + + // ************************************************************* + // * If a connection was established to the server, then use + // * the enqueue method to resubmit the request to the server. + // ************************************************************* + if(handler!=NULL) + { + if(service.enqueue(handler, *this, key)==CDEV_SUCCESS) + { + cdevData cData; + statusCode = 0; + xobj->userCallback_->fireCallback + (CDEV_RECONNECTED, + xobj->userCallback_->userarg(), + *xobj->reqObj_, cData, 1); + } + } + } + } diff --git a/extensions/cdevGenericServer/cdevClient/cdevClientService.h b/extensions/cdevGenericServer/cdevClient/cdevClientService.h new file mode 100755 index 0000000..4d34ab4 --- /dev/null +++ b/extensions/cdevGenericServer/cdevClient/cdevClientService.h @@ -0,0 +1,140 @@ +#if !defined (_CDEV_CLIENT_SERVICE_H_) +#define _CDEV_CLIENT_SERVICE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ***************************************************************************** +// * class NSCallbackArg : +// * This class is provided as a technique for allowing the name server +// * to differentiate when making monitorOn requests between two servers that +// * use the same service. +// ***************************************************************************** +class GENERIC_SERVER_API NSCallbackArg +{ +friend class cdevClientService; + +private: + char * server; + cdevClientService * service; + + NSCallbackArg ( char * Server, cdevClientService * Service ) + : server(strdup(Server)), service(Service) + { + } + + ~NSCallbackArg ( void ) + { + if(server) delete server; + } +}; + + +// ***************************************************************************** +// * cdevClientService: +// * This is class provides the mechanisms that the cdev system will use +// * to communicate with the model service. +// ***************************************************************************** +class GENERIC_SERVER_API cdevClientService : public cdevService, + public ServerInterface, + public cdevTagTableCallback +{ +friend class cdevClientRequestObject; +friend class cdevClientTransaction; + +public: + enum { ServiceTagBase=511 }; + + static int ServerTag; + static int HostTag; + static int PortTag; + + cdevClientService ( char * domain, char * name, cdevSystem & system = cdevSystem::defaultSystem()); + static void defaultCallback (int, void *, cdevRequestObject &, cdevData &); + static void nameServerCallback(int, void *, cdevRequestObject &, cdevData &); + virtual int outputError (int severity, char *name, char *formatString, ...); + ServerHandler * connect ( char * server, char * host=NULL, unsigned short port = 0); + ServerHandler * disconnect ( char * server ); + + int flush ( void ); + int pend ( double seconds, int fd = -1 ); + int getFd ( int * &fd, int & numFd ); + + int poll ( void ); + int pend ( int fd = -1 ); + int getNameServer ( cdevDevice * &ns ); + int getRequestObject ( char * device, char * message, cdevRequestObject * &req); + + int enqueue ( char * server, cdevData * in, cdevTranObj & xobj ); + int enqueue ( ServerHandler * handler, cdevData * in, cdevTranObj & xobj ); + int enqueue ( ServerHandler * handler, class cdevClientTransaction &, unsigned); + int cancel ( cdevTranObj & xobj ); + int enqueue ( int status, ServerHandler * handler, char * binary, size_t binaryLen ); + int isPacketValid ( char * binary, size_t binaryLen ); + void callback ( int newTag, char * newName ); + char * getDomain ( void ) const { return domain; } + +protected: + virtual ~cdevClientService ( void ); + virtual void fireCallback ( int status, cdevTranObj &xobj, cdevData *resultData, int partialTransaction = 0 ); + virtual int processLocal ( cdevData * in, cdevTranObj & xobj ); + + char * domain; + AddressIndex transactions; + cdevCallback syncCallback; + cdevContextMap contexts; + int quitFlag; + StringHash nsCallbackArgs; + static ClientInfo clientInfo; + static cdevGenericServerTagDef tags; + + NSCallbackArg * getCallbackArg ( char * server ); +}; + +class GENERIC_SERVER_API cdevClientTransaction +{ +private: + // ********************************************************************* + // * Free list data elements and private array constructor. + // ********************************************************************* + enum {ALLOCATION_COUNT = 16 }; + static cdevClientTransaction * freeList_; + cdevClientTransaction * freeListNext_; + cdevClientTransaction ( void ); + +public: + // ********************************************************************* + // * Public free list interface. + // ********************************************************************* + void * operator new ( size_t size ); + void operator delete ( void * ptr ); + + char server[256]; + cdevTranObj * xobj; + int permanent; + int statusCode; + + // ********************************************************************* + // * Data elements used for restartable transactions. + // ********************************************************************* + int restartable; + int contextID; + cdevData * userData; + + cdevClientTransaction ( cdevTranObj & XObj, ServerHandler &handler, + int Restartable=0, cdevData *data=NULL, + unsigned ContextID=0 ); + virtual ~cdevClientTransaction ( void ); + void reconnect (char * host=NULL, unsigned short port=0, unsigned key=0); + +}; + + +#endif /* _CDEV_CLIENT_SERVICE_H_ */ diff --git a/extensions/cdevGenericServer/cdevContextMap/Makefile b/extensions/cdevGenericServer/cdevContextMap/Makefile new file mode 100755 index 0000000..3b9cb7e --- /dev/null +++ b/extensions/cdevGenericServer/cdevContextMap/Makefile @@ -0,0 +1,16 @@ +ARCH = OS +SHOBJ = NO + +include ../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Context Map Source" +CXXINCLUDES = -I./ +TARGETS = $(BASEBIN)/cdevContextMapTest +LIBS = $(CDEVLIBS) $(OSLIBS) + +targets: $(TARGETS) + +$(BASEBIN)/cdevContextMapTest: $(OBJDIR)/cdevContextMap.o $(OBJDIR)/cdevContextMapTest.o + $(LINK.cc) $^ -o $@ $(LIBS) + + diff --git a/extensions/cdevGenericServer/cdevContextMap/NMakefile.mak b/extensions/cdevGenericServer/cdevContextMap/NMakefile.mak new file mode 100644 index 0000000..750b0bb --- /dev/null +++ b/extensions/cdevGenericServer/cdevContextMap/NMakefile.mak @@ -0,0 +1,21 @@ +.SUFFIXES: .cc .obj + +APPNAME = Context Map Source +ARCH = WINNT-4.0 +BINARIES = $(BASEBIN)\cdevContextMapTest.exe + +include ..\include\makeinclude\Makefile.WINNT-4.0 + +CXXEXTRA = /D "GENERIC_SERVER_API= " +CXXINCLUDES = /I .\\ +TARGETS = $(BASEBIN)\cdevContextMapTest.exe + +targets : $(TARGETS) + +$(BASEBIN)\cdevContextMapTest.exe : .exec\$(TARGETDIR)\cdevContextMap.obj .exec\$(TARGETDIR)\cdevContextMapTest.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib\ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + diff --git a/extensions/cdevGenericServer/cdevContextMap/cdevContextMap.cc b/extensions/cdevGenericServer/cdevContextMap/cdevContextMap.cc new file mode 100755 index 0000000..145e407 --- /dev/null +++ b/extensions/cdevGenericServer/cdevContextMap/cdevContextMap.cc @@ -0,0 +1,123 @@ +#include + +// ***************************************************************************** +// * cdevContextMap::cdevContextMap : +// * This is the constructor for the class and it initializes all +// * data items to 0 or NULL... +// ***************************************************************************** +cdevContextMap::cdevContextMap ( void ) + : entries(NULL), maximum(0), cnt(0) + {} + +// ***************************************************************************** +// * cdevContextMap::~cdevContextMap : +// * This is the destructor for the class and it will delete any +// * cdevData objects that have been allocated using new and will +// * then free the array that was allocated using malloc or realloc. +// ***************************************************************************** +cdevContextMap::~cdevContextMap ( void ) + { + if(entries!=NULL) + { + for(int i=0; i=maximum) resize(); + entries[i] = new cdevData(context); + cnt++; + } + return i; + } + + +// ***************************************************************************** +// * cdevContextMap::find : +// * This method allows the caller to obtain the index of a context +// * cdevData object that matches the cdevData object he provides... +// * If a matching context object cannot be found, then -1 will be +// * returned. +// ***************************************************************************** +int cdevContextMap::find ( cdevData & context ) + { + int i; + int found; + + for(i=0; + iasciiDump(fp); + fflush(fp); + } + fprintf(fp, "----------------------------------------------------------\n"); + fprintf(fp, " End of Diagnostic Dump of CDEV Context Map\n"); + fprintf(fp, "----------------------------------------------------------\n\n"); + fflush(fp); + } diff --git a/extensions/cdevGenericServer/cdevContextMap/cdevContextMap.h b/extensions/cdevGenericServer/cdevContextMap/cdevContextMap.h new file mode 100755 index 0000000..c39a7d3 --- /dev/null +++ b/extensions/cdevGenericServer/cdevContextMap/cdevContextMap.h @@ -0,0 +1,33 @@ +#ifndef _CDEV_CONTEXT_MAP_H_ +#define _CDEV_CONTEXT_MAP_H_ 1 +#include +#include + + +// ***************************************************************************** +// * class cdevContextMap : +// * The purpose of this class is to allow the user to store a list of +// * commonly used context cdevData items. This will allow the caller to +// * pass the context to maintain a list of contexts that are identifiable +// * by a unique integer identifier... +// ***************************************************************************** +class GENERIC_SERVER_API cdevContextMap +{ +protected: + cdevData ** entries; + size_t maximum; + size_t cnt; + + void resize ( void ); + +public: + cdevContextMap ( void ); + ~cdevContextMap ( void ); + int insert ( cdevData & context ); + int find ( cdevData & context ); + cdevData * find ( int idx ) { return (idx>cnt || idx<0)?(cdevData *)NULL:entries[idx]; } + void asciiDump ( FILE * fp = stdout ); +}; + +#endif /* _CDEV_CONTEXT_MAP_H_ */ + diff --git a/extensions/cdevGenericServer/cdevContextMap/cdevContextMapTest.cc b/extensions/cdevGenericServer/cdevContextMap/cdevContextMapTest.cc new file mode 100755 index 0000000..a7a115d --- /dev/null +++ b/extensions/cdevGenericServer/cdevContextMap/cdevContextMapTest.cc @@ -0,0 +1,41 @@ +#include "cdevContextMap.h" + +cdevContextMap map; + + +int main() +{ +int i=0; +cdevData data; + +data.insert(1, "Test String 1"); +data.insert(2, "Test String 2"); +data.insert(3, "Test String 3"); +data.insert(4, "Test String 4"); + +for(i=0; i<255; i++) + { + data.insert(5, i); + map.insert(data); + + if(i%255==0) fprintf(stdout,"\n"); + else if(i%100==0) fprintf(stdout,"*"); + else if(i%10==0) fprintf(stdout,":"); + else fprintf(stdout, "."); + fflush(stdout); + } +for(i=255; i>0; i--) + { + data.insert(5, i); + map.insert(data); + + if(i%255==0) fprintf(stdout,"\n"); + else if(i%100==0) fprintf(stdout,"*"); + else if(i%10==0) fprintf(stdout,":"); + else fprintf(stdout, "."); + fflush(stdout); + } + +map.asciiDump(); +return 0; +} diff --git a/extensions/cdevGenericServer/cdevMonitorTable/Makefile b/extensions/cdevGenericServer/cdevMonitorTable/Makefile new file mode 100755 index 0000000..c9e5dd7 --- /dev/null +++ b/extensions/cdevGenericServer/cdevMonitorTable/Makefile @@ -0,0 +1,31 @@ +ARCH = OS +SHOBJ = NO + +include ../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Monitor Table Source" +TEMPLINKS = cdevMessage.cc cdevMessageBinary.cc cdevPacket.cc cdevTagMap.cc +CXXINCLUDES = -I./ +LIBS = $(CDEVLIBS) $(OSLIBS) +TARGETS = $(TEMPLINKS) $(BASEBIN)/cdevMonitorTableTest +OBJS = $(OBJDIR)/cdevMonitorTable.o\ + $(OBJDIR)/cdevMessage.o\ + $(OBJDIR)/cdevMessageBinary.o\ + $(OBJDIR)/cdevPacket.o\ + $(OBJDIR)/cdevTagMap.o\ + $(OBJDIR)/test.o + +targets: $(TARGETS) + @rm -rf $(TEMPLINKS) + +$(TEMPLINKS) : + @cp $^ $@ + +$(BASEBIN)/cdevMonitorTableTest: $(OBJS) + $(LINK.cc) $^ -o $@ $(LIBS) + +cdevPacket.cc : ../cdevPacket/cdevPacket.cc +cdevMessage.cc : ../cdevPacket/cdevMessage.cc +cdevMessageBinary.cc : ../cdevPacket/cdevMessageBinary.cc +cdevTagMap.cc : ../cdevTagMap/cdevTagMap.cc + diff --git a/extensions/cdevGenericServer/cdevMonitorTable/NMakefile.mak b/extensions/cdevGenericServer/cdevMonitorTable/NMakefile.mak new file mode 100644 index 0000000..1cac42e --- /dev/null +++ b/extensions/cdevGenericServer/cdevMonitorTable/NMakefile.mak @@ -0,0 +1,44 @@ +.SUFFIXES: .cc .obj + +APPNAME = Monitor Table Source +ARCH = WINNT-4.0 +TEMPLINKS = cdevMessage.cc\ + cdevMessageBinary.cc\ + cdevPacket.cc\ + cdevTagMap.cc + +BINARIES = $(BASEBIN)\cdevMonitorTableTest.exe $(TEMPLINKS) + +include ..\include\makeinclude\Makefile.WINNT-4.0 + +CXXEXTRA = /D "GENERIC_SERVER_API= " +CXXINCLUDES = /I .\ /I ..\cdevPacket /I ..\cdevTagMap +TARGETS = $(BASEBIN)\cdevMonitorTableTest.exe +OBJS = .exec\$(TARGETDIR)\cdevMonitorTable.obj\ + .exec\$(TARGETDIR)\cdevMessage.obj\ + .exec\$(TARGETDIR)\cdevMessageBinary.obj\ + .exec\$(TARGETDIR)\cdevPacket.obj\ + .exec\$(TARGETDIR)\cdevTagMap.obj\ + .exec\$(TARGETDIR)\test.obj + +targets : $(TEMPLINKS) $(BASEBIN)\cdevMonitorTableTest.exe + @erase $(TEMPLINKS) + +$(BASEBIN)\cdevMonitorTableTest.exe : $(OBJS) + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib\ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +cdevMessage.cc : ..\cdevPacket\cdevMessage.cc + -@$(CREATE_LINK) + +cdevMessageBinary.cc : ..\cdevPacket\cdevMessageBinary.cc + -@$(CREATE_LINK) + +cdevPacket.cc : ..\cdevPacket\cdevPacket.cc + -@$(CREATE_LINK) + +cdevTagMap.cc : ..\cdevTagMap\cdevTagMap.cc + -@$(CREATE_LINK) diff --git a/extensions/cdevGenericServer/cdevMonitorTable/cdevMonitorTable.cc b/extensions/cdevGenericServer/cdevMonitorTable/cdevMonitorTable.cc new file mode 100755 index 0000000..8801128 --- /dev/null +++ b/extensions/cdevGenericServer/cdevMonitorTable/cdevMonitorTable.cc @@ -0,0 +1,1022 @@ +#include + +// ***************************************************************************** +// * cdevMonitorNode::cdevMonitorEntry Static Variables. +// ***************************************************************************** +int cdevMonitorNode::cdevMonitorEntry::VALUE_TAG = 0; +int cdevMonitorNode::cdevMonitorEntry::STATUS_TAG = 0; +int cdevMonitorNode::cdevMonitorEntry::TIME_TAG = 0; +int cdevMonitorNode::cdevMonitorEntry::DEVICE_TAG = 0; + + +// ***************************************************************************** +// * cdevMonitorData::cdevMonitorData: +// * This is the default constructor. +// ***************************************************************************** +cdevMonitorData::cdevMonitorData ( void ) : + criticalTags(NULL), criticalTagCnt(0), cdevData() + { + } + +// ***************************************************************************** +// * cdevMonitorData::cdevMonitorData: +// * This builds a cdevMonitorData from a cdevData. +// ***************************************************************************** +cdevMonitorData::cdevMonitorData ( const cdevData & data ) : + criticalTags(NULL), criticalTagCnt(0), cdevData(data) + { + } + +// ***************************************************************************** +// * cdevMonitorData::cdevMonitorData: +// * This builds a cdevMonitorData from a cdevMonitorData. +// ***************************************************************************** +cdevMonitorData::cdevMonitorData ( const cdevMonitorData & data ) : + criticalTags(data.criticalTags), + criticalTagCnt(data.criticalTagCnt), + cdevData(*(const cdevData *)&data) + { + } + +// ***************************************************************************** +// * isTagCritical : +// * This method will walk through the list of tags and attempt to find +// * the caller specified tag. This method returns 1 if it is present, or +// * 0 if it is not. +// ***************************************************************************** +int cdevMonitorData::isTagCritical ( int tag ) + { + for(int i=0; inext_) + { + // ***************************** + // * Do not process entries * + // * with CDEV_INVALID as the * + // * dataType or 0 as the tag. * + // ***************************** + if(ptr->dataType_==CDEV_INVALID || + ptr->tag_==0 || + !isTagCritical(ptr->tag_)) continue; + + // ***************************** + // * Calculate the number of * + // * elements in this tagged * + // * data item. * + // ***************************** + int numElements = ptr->dim_!=0?ptr->elems_:1; + + // ***************************** + // * Increment the counter * + // ***************************** + cdevElementCnt++; + + // ***************************** + // * Add the size of the * + // * cdevDataEntries tag_, * + // * dataType_, dim_, elems_. * + // ***************************** + xdrDataSize += 4 * XDR_Sizeof((int)1); + + // ***************************** + // * Add the size of the * + // * cdevBounds data. * + // ***************************** + xdrDataSize += ptr->dim_ * (XDR_Sizeof((int)1) * 2); + + // ***************************** + // * Add the size of the data * + // ***************************** + if (ptr->dataType_==CDEV_BYTE) xdrDataSize += numElements * XDR_Sizeof((unsigned char)'c'); + else if(ptr->dataType_==CDEV_INT16) xdrDataSize += numElements * XDR_Sizeof((short)1); + else if(ptr->dataType_==CDEV_UINT16) xdrDataSize += numElements * XDR_Sizeof((unsigned short)1); + else if(ptr->dataType_==CDEV_INT32) xdrDataSize += numElements * XDR_Sizeof((long)1); + else if(ptr->dataType_==CDEV_UINT32) xdrDataSize += numElements * XDR_Sizeof((unsigned long)1); + else if(ptr->dataType_==CDEV_FLOAT) xdrDataSize += numElements * XDR_Sizeof((float)1); + else if(ptr->dataType_==CDEV_DOUBLE) xdrDataSize += numElements * XDR_Sizeof((double)1); + else if(ptr->dataType_==CDEV_STRING) + { + if(numElements==1) xdrDataSize += XDR_Sizeof(ptr->data_.str); + else for(i=0; idata_.strarr[i]); + } + else if(ptr->dataType_==CDEV_TIMESTAMP) xdrDataSize += numElements * XDR_Sizeof(ptr->data_.ts); + } + + *elementCount = cdevElementCnt; + *bufLen = xdrDataSize; + + return *bufLen>0?CDEV_SUCCESS:CDEV_ERROR; + } + + +// ***************************************************************************** +// * xdrExport: +// * This function encapsulates the contents of the cdevData class into a +// * binary stream. This function allocates the buffer and returns the new +// * buffer and the buffer size. +// ***************************************************************************** +int cdevMonitorData::xdrExport ( char ** buf, size_t * bufLen ) +{ + size_t count = 0; + + // ************************************# + // * Calculate the size of the buffer # + // ************************************# + xdrSize(bufLen, &count); + + // ************************************# + // * Allocate the buffer and call the # + // * export function. # + // ************************************# + if((*buf = new char[*bufLen])!=NULL) xdrExport(*buf, *bufLen, count); + + return buf==NULL?CDEV_ERROR:CDEV_SUCCESS; +} + + +// ***************************************************************************** +// * xdrExport: +// * This function encapsulates the contents of the cdevData class into a +// * preallocated binary stream. The buf parameter contains the address of +// * the caller allocated buffer, the bufLen parameter specifies the size +// * of the buffer, and the count parameter specifies the number of tagged +// * data items that will be copied from the cdevData object into the +// * binary stream. +// ***************************************************************************** +int cdevMonitorData::xdrExport ( char * buf, size_t bufLen, size_t count ) + { + cdevDataEntry * ptr; + XDR_Writer writer; + int xdrDataSize = bufLen; + int cdevElementCnt = count; + int i; + + // ************************************# + // * Allocate the buffer # + // ************************************# + writer.attachData(buf, bufLen); + + // ************************************# + // * Transfer the data to the buffer # + // ************************************# + // ************************************* + // * Write the number of elements * + // ************************************* + writer.put(cdevElementCnt); + + // ************************************* + // * Write each valid item. * + // ************************************* + for(ptr = entries; ptr != NULL; ptr = ptr->next_) + { + // ***************************** + // * Do not process entries * + // * with CDEV_INVALID as the * + // * dataType or 0 as the tag. * + // ***************************** + if(ptr->dataType_==CDEV_INVALID || + ptr->tag_==0 || + !isTagCritical(ptr->tag_)) continue; + + // ***************************** + // * Calculate the number of * + // * elements in this tagged * + // * data item. * + // ***************************** + int numElements = ptr->dim_!=0?ptr->elems_:1; + + // ***************************** + // * Decrement the counter * + // ***************************** + cdevElementCnt--; + + // ***************************** + // * Write the tag_, dataType_ * + // * dim_, and elems_ of the * + // * cdevDataEntry object. * + // ***************************** + writer.put((int)ptr->tag_); + writer.put((int)ptr->dataType_); + writer.put((int)ptr->dim_); + writer.put((int)ptr->elems_); + + // ***************************** + // * Write the cdevBounds * + // * values asssociated with * + // * the cdevDataEntry (if any)* + // ***************************** + cdevBounds * bounds = ptr->bounds(); + for(i=0; idim_; i++) + { + writer.put((int)bounds[i].offset); + writer.put((int)bounds[i].length); + } + + // ***************************** + // * Write the data * + // ***************************** + if(ptr->dataType_==CDEV_BYTE) + { + if(numElements==1) writer.put(ptr->data_.cval); + else for(i=0; idata_.cptr[i]); + } + else if(ptr->dataType_==CDEV_INT16) + { + if(numElements==1) writer.put(ptr->data_.sval); + else for(i=0; idata_.sptr[i]); + } + else if(ptr->dataType_==CDEV_UINT16) + { + if(numElements==1) writer.put(ptr->data_.usval); + else for(i=0; idata_.usptr[i]); + } + else if(ptr->dataType_==CDEV_INT32) + { + if(numElements==1) writer.put(ptr->data_.lval); + else for(i=0; idata_.lptr[i]); + } + else if(ptr->dataType_==CDEV_UINT32) + { + if(numElements==1) writer.put(ptr->data_.ulval); + else for(i=0; idata_.ulptr[i]); + } + else if(ptr->dataType_==CDEV_FLOAT) + { + if(numElements==1) writer.put(ptr->data_.fval); + else for(i=0; idata_.fptr[i]); + } + else if(ptr->dataType_==CDEV_DOUBLE) + { + if(numElements==1) writer.put(ptr->data_.dval); + else for(i=0; idata_.dptr[i]); + } + else if(ptr->dataType_==CDEV_STRING) + { + if(numElements==1) writer.put(ptr->data_.str); + else for(i=0; idata_.strarr[i]); + } + else if(ptr->dataType_==CDEV_TIMESTAMP) + { + if(numElements==1) writer.put(ptr->data_.ts); + } + } + + // ************************************* + // * Detach the data from the writer * + // * object before the object is * + // * destroyed. * + // ************************************* + writer.detachData(); + + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * cdevMonitorNode::cdevMonitorEntry::cdevMonitorEntry : +// * This is the constructor for the cdevMonitorEntry class that is internal to the +// * cdevMonitorNode class. +// * +// * This constructor will initialize all data items and will then populate +// * the list of triggers with all properties from the context that are +// * marked with 2 or 3. It will then populate the properties list with +// * all properties from the context that have any value other than 0. +// * +// * If not properties are in the context, then the following settings will +// * be used by default... +// * value = 3 +// * status = 1 +// * time = 1 +// * +// * The cdevMessage object becomes the property of the cdevMonitorNode +// * object and should not be accessed again by the caller. +// * +// * The deviceIdx indicates the specific device that is being monitored +// * within a multi-device list. +// ***************************************************************************** +cdevMonitorNode::cdevMonitorEntry::cdevMonitorEntry( cdevMessage * Message, int DeviceIdx=0 ) + : next(NULL), message(Message), triggers(NULL), trigType(NULL), + trigCnt(0), properties(NULL), propCnt(0), deviceIdx(DeviceIdx) + { + // ********************************************************************* + // * Populate the static variables if they have not already been set. + // ********************************************************************* + if(VALUE_TAG==0) + { + cdevData::tagC2I("value", &VALUE_TAG); + cdevData::tagC2I("status", &STATUS_TAG); + cdevData::tagC2I("time", &TIME_TAG); + + // ************************************************************* + // * Added to support multi-device monitors. + // ************************************************************* + cdevData::tagC2I("device", &DEVICE_TAG); + } + + if(message!=NULL) + { + int tag; + size_t tagElems; + int tagVal; + + // ************************************************************* + // * Start by removing the cdevData data if it has been + // * included. This component will not be necessary to process + // * the monitors. + // ************************************************************* + message->setData(NULL); + + // ************************************************************* + // * If the context has been specified, then read the context + // * to determine the number of monitorable data items. + // ************************************************************* + if(message->getContext()!=NULL) + { + cdevData * context = message->getContext(); + cdevDataIterator iter(context); + iter.init(); + + while((tag=iter.tag())!=0) + { + tagElems = 0; + tagVal = 0; + context->getElems(tag, &tagElems); + if(tagElems==1) + { + context->get(tag, &tagVal); + if(tagVal>1) trigCnt++; + if(tagVal>0) propCnt++; + } + ++iter; + } + // ***************************************************** + // * If the number of monitorable data items is greater + // * than 0, then allocate a sufficient buffer and copy + // * the tag names and tag types into the buffer. + // ***************************************************** + if(trigCnt>0) + { + // ********************************************* + // * Added to support multi-device list. + // ********************************************* + if(message->getDeviceCount()>1) propCnt++; + + iter.init(); + triggers = new int[trigCnt+trigCnt+propCnt]; + trigType = &triggers[trigCnt]; + properties = &triggers[trigCnt+trigCnt]; + trigCnt = 0; + propCnt = 0; + while((tag=iter.tag())!=0) + { + tagElems = 0; + tagVal = 0; + context->getElems(tag, &tagElems); + if(tagElems==1) + { + context->get(tag, &tagVal); + if(tagVal>1) + { + triggers[trigCnt] = tag; + trigType[trigCnt++] = tagVal; + } + if(tagVal>0) properties[propCnt++] = tag; + } + ++iter; + } + // ********************************************* + // * Added to support multi-device list. + // ********************************************* + if(message->getDeviceCount()>1) + properties[propCnt++] = DEVICE_TAG; + } + } + + // ************************************************************* + // * If not tags were specified or the context was blank... then + // * use the default setup. + // ************************************************************* + if(trigCnt<=0) + { + trigCnt = 1; + propCnt = 3; + + // ***************************************************** + // * Added to support multi-device list. + // ***************************************************** + if(message->getDeviceCount()>1) propCnt++; + + triggers = new int[2+propCnt]; + trigType = &triggers[1]; + properties = &triggers[2]; + triggers[0] = VALUE_TAG; + trigType[0] = 3; + properties[0] = VALUE_TAG; + properties[1] = STATUS_TAG; + properties[2] = TIME_TAG; + // ***************************************************** + // * Added to support multi-device list. + // ***************************************************** + if(message->getDeviceCount()>1) properties[3] = DEVICE_TAG; + } + } + } + + +// ***************************************************************************** +// * cdevMonitorNode::cdevMonitorEntry::~cdevMonitorEntry : +// * This is the destructor for the node object that is internal to the +// * cdevMonitorNode class. It is responsible for deleteing the cdevMessage +// * object and freeing any memory that was allocated to the triggers +// * object. +// * +// * Note that this destructor will delete all of the nodes that are stored +// * below this one in the list. +// ****************************************************************************** +cdevMonitorNode::cdevMonitorEntry::~cdevMonitorEntry ( void ) + { + if(message) delete message; + if(triggers) delete triggers; + if(next!=NULL) delete next; + } + + +// ***************************************************************************** +// * cdevMonitorNode::cdevMonitorNode : +// * This is the constructor for the cdevMonitorNode class. It will save a +// * copy of the Parent variable and will use the user specified Device and +// * Attrib to create the hashString. +// ***************************************************************************** +cdevMonitorNode::cdevMonitorNode ( cdevMonitorTable * Parent, + char * Device, + char * Attrib ) + : parent(Parent), hashString(NULL), nodes(NULL) + { + hashString = new char[strlen(Device)+strlen(Attrib)+2]; + sprintf(hashString, "%s %s", Device, Attrib); + } + + +// ***************************************************************************** +// * cdevMonitorNode::~cdevMonitorNode : +// * This is the destructor for the cdevMonitorNode object. It will delete +// * the hashString and each node from the list of monitors. +// ***************************************************************************** +cdevMonitorNode::~cdevMonitorNode ( void ) + { + if(hashString) delete hashString; + if(nodes) + { + // ************************************************************* + // * Prior to deleteing itself, this class will first fire its + // * monitors once more using a 1 in the endOfTransaction + // * parameter in order to inform the client side that it will + // * receive no further transactions. + // ************************************************************* + cdevMonitorEntry * node = nodes; + while(node) + { + fireMonitor(node, -1, &mData, 1); + node = node->next; + } + delete nodes; + } + } + +// ***************************************************************************** +// * cdevMonitorNode::insertMonitor : +// * This method is used to add a new monitor for the device / attribute +// * pair associated with this object. +// * +// * The cdevData object that is provided in the cdevData object is the +// * collection of all current property values for the device / attribute +// * pair. This data will be used to automatically dispatch the first +// * callback when the monitor is initially installed. +// * +// * The deviceIdx indicates the specific device that is being monitored +// * within a multi-device list. +// ***************************************************************************** +int cdevMonitorNode::insertMonitor ( cdevMessage * request, + cdevData * data, + int deviceIdx = 0 ) + { + int result = 0; + cdevMonitorEntry * node = new cdevMonitorEntry(request, deviceIdx); + if(node->trigCnt > 0) + { + node->next = nodes; + nodes = node; + } + else { + delete node; + result = -1; + } + if(data!=NULL) + { + mData = *data; + fireMonitor(node, -1, &mData); + } + return result; + } + +// ***************************************************************************** +// * cdevMonitorNode::removeMonitor : +// * This method is used to remove a specific monitor by submitting a +// * cdevMessage that contains the transaction index to be canceled in the +// * cancelTransIndex element. +// ***************************************************************************** +int cdevMonitorNode::removeMonitor ( cdevMessage * request ) + { + return request==NULL?-1:removeMonitor(request->getCancelTransIndex()); + } + +// ***************************************************************************** +// * cdevMonitorNode::removeMonitor : +// * This method is used to remove a specific monitor by submitting a +// * the transaction index to be canceled. +// ***************************************************************************** +int cdevMonitorNode::removeMonitor ( unsigned cancelTransIndex ) + { + int result = -1; + cdevMonitorEntry * node = nodes, *prev = NULL; + + while(node!=NULL && + node->message->getTransIndex() != cancelTransIndex) + { + prev = node; + node = node->next; + } + if(node!=NULL) + { + if(prev==NULL) nodes = node->next; + else prev->next = node->next; + node->next = NULL; + + // ************************************************************* + // * This code portion added to inform client side that the + // * monitor is terminating. When a monitor returns an + // * operationCode of 0 - it indicates that there will be no + // * further data transmissions. + // * + // * The 1 provided in the endOfTransaction parameter indicates + // * that this transaction is finished. + // ************************************************************* + fireMonitor(node, -1, &mData, 1); + + delete node; + result = 0; + } + return result; + } + + +// ***************************************************************************** +// * cdevMonitorNode::removeClientMonitors : +// * This method is used to remove all nodes that are associated with a +// * specified clientID. +// ***************************************************************************** +int cdevMonitorNode::removeClientMonitors ( short clientID, int fire ) + { + cdevMonitorEntry * node = nodes, *prev = NULL; + while(node!=NULL) + { + if(node->message->getClientID() == clientID) + { + cdevMonitorEntry * nextcdevMonitorEntry = node->next; + node->next = NULL; + + // ***************************************************** + // * This code portion added to inform client side that + // * the monitor is terminating. When a monitor returns + // * an operationCode of 0 - it indicates that there + // * will be no further data transmissions. + // * + // * The 1 provided in the endOfTransaction parameter + // * indicates that this transaction is finished. + // ***************************************************** + if(fire) fireMonitor(node, -1, &mData, 1); + + delete node; + + if(prev==NULL) nodes = nextcdevMonitorEntry; + else prev->next = nextcdevMonitorEntry; + node = nextcdevMonitorEntry; + } + else { + prev = node; + node = node->next; + } + } + return 0; + } + +// ***************************************************************************** +// * cdevMonitorNode::fireMonitor : +// * This method is used to submit a change to a monitored property. If the +// * value of property is NULL, then all of the trigger properties will be +// * fired. +// * +// * Note that the data parameter should be populated with all of the +// * properties that are associated with the particular device / attribute +// * pair. +// ***************************************************************************** +int cdevMonitorNode::fireMonitor( char * property, cdevData * data ) + { + int tag = -1; + if(property!=NULL) cdevData::tagC2I(property, &tag); + return fireMonitor(tag, data); + } + + +// ***************************************************************************** +// * cdevMonitorNode::fireMonitor : +// * This method is used to submit a change to a monitored property. If the +// * value of property is -1, then it will fire all monitors that are listed +// * in the triggers parameter. +// * +// * Note that the data parameter should be populated with all of the +// * properties that are associated with the particular device / attribute +// * pair. +// * +// * This method will return 0 if any monitors were actually dispatched, +// * otherwise it will return -1. +// ***************************************************************************** +int cdevMonitorNode::fireMonitor( int property, cdevData * data ) + { + int result = -1; + cdevMonitorEntry * node = nodes; + + // ********************************************************************* + // * Attach the data that is contained in the cdevData object to the + // * cdevMonitorData object. + // ********************************************************************* + if(data!=NULL) + { + // ************************************************************* + // * Note here I am copying the contents of the user provided + // * data to the mData structure that is local to the + // * cdevMonitorNode. + // ************************************************************* + mData = *data; + while(node!=NULL) + { + if(fireMonitor(node, property, &mData)==0) result = 0; + node = node->next; + } + } + return result; + } + +// ***************************************************************************** +// * cdevMonitorNode::fireMonitor : +// * This method is used to submit a change to a monitored property. If the +// * value of property is -1, then it will fire all monitors that are listed +// * in the triggers parameter. +// * +// * The endOfTransaction flag indicates that this is the last monitor that +// * will be returned in association with this cdevMonitorNode and, +// * therefore, the cdevMessage's operationCode should be set to indicate +// * that. +// * +// * Note that the data parameter should be populated with all of the +// * properties that are associated with the particular device / attribute +// * pair. +// * +// * This method will return 0 if any monitors were actually dispatched, +// * otherwise it will return -1. +// ***************************************************************************** +int cdevMonitorNode::fireMonitor( cdevMonitorEntry * entry, + int property, + cdevMonitorData *data, + int endOfTransaction ) + { + int result = -1; + + if(entry!=NULL && data!=NULL) + { + int found = 0; + + // ************************************************************* + // * An operationCode value with bit one set indicates that this + // * is NOT the end of the transaction, an operationCode value + // * with bit one unset indicates that this IS the end of the + // * transaction. + // ************************************************************* + entry->message->setOperationCode(endOfTransaction?0:1); + + for(int i=0; !found && itrigCnt; i++) + { + if(property<0 || entry->triggers[i]==property) + { + if(property>0) found = 1; + // ********************************************* + // * Trigger type 3 means that the callback + // * wants the changed value and all other + // * values that were specified in the + // * context. + // ********************************************* + if(entry->trigType[i]==3) + data->setCriticalTags(entry->properties, + entry->propCnt); + + // ********************************************* + // * Trigger type 2 means that the callback + // * wants only the changed value. + // ********************************************* + if(entry->trigType[i]==2) + data->setCriticalTags(&entry->triggers[i], 1); + + // ********************************************* + // * Determine if the changed data item exists + // * in the user provided data. If it does, + // * then execute the fireCallback method on + // * the cdevMonitorTable to dispatch the + // * monitor. + // ********************************************* + if(data->getType(entry->triggers[i])!=CDEV_INVALID) + { + // ************************************* + // * Added to support multi-device + // ************************************* + if(entry->message->getDeviceCount()>1) + data->insert(cdevMonitorEntry::DEVICE_TAG, + entry->message->getDeviceList() + [entry->deviceIdx]); + + entry->message->setData(data, 1); + parent->fireCallback(entry->message); + + // ************************************* + // * Added to support multi-device + // ************************************* + if(entry->message->getDeviceCount()>0) + data->remove(cdevMonitorEntry::DEVICE_TAG); + + result = 0; + } + } + } + } + + return result; + } + + +// ***************************************************************************** +// * cdevMonitorTable::cdevMonitorTable : +// * This is the constructor for the cdevMonitortable class. This class +// * contains a hash table that maintains a list of all of the monitored +// * device / attribute pairs on the system. +// ***************************************************************************** +cdevMonitorTable::cdevMonitorTable ( void ) + : monitors(0) + { + } + +// ***************************************************************************** +// * cdevMonitorTable::~cdevMonitorTable : +// * This method walks through the monitors hash table and deletes all +// * cdevMonitorNodes that have been allocated. +// ***************************************************************************** +cdevMonitorTable::~cdevMonitorTable ( void ) + { + char * ptr; + StringHashIterator iter(&monitors); + + iter.first(); + while((ptr= iter.key())!=NULL) + { + cdevMonitorNode * node = (cdevMonitorNode *)iter.data(); + monitors.remove(ptr); + delete node; + iter.first(); + } + } + +// ***************************************************************************** +// * cdevMonitorTable::insertMonitor: +// * This method allows the caller to add a new monitored device / attribute +// * pair to the cdevMonitorTable. +// * +// * The cdevData object that is provided in the cdevData object is the +// * collection of all current property values for the device / attribute +// * pair. This data will be used to automatically dispatch the first +// * callback when the monitor is initially installed. +// ***************************************************************************** +int cdevMonitorTable::insertMonitor ( cdevMessage * request, cdevData * data ) + { + return insertMonitor(request, &data, 1); + } + + +// ***************************************************************************** +// * cdevMonitorTable::insertMonitor: +// * This method allows the caller to add a new monitored device / attribute +// * pair to the cdevMonitorTable. +// * +// * The cdevData objects that are provided in the data parameter are the +// * initial values for each item in the deviceList in sequence. This data +// * will be used to automatically dispatch the first callback when the +// * monitor is initially installed. +// ***************************************************************************** +int cdevMonitorTable::insertMonitor ( cdevMessage * request, cdevData ** data, size_t dataCnt ) + { + if(request!=NULL && request->getDeviceList()!=NULL && request->getMessage()!=NULL) + { + char * attrib = strchr(request->getMessage(), ' '); + if(attrib) + { + attrib++; + cdevMonitorNode * node; + cdevMessage ** msgList; + + // ***************************************************** + // * Allocate additional cdevMessage objects if a + // * deviceList greater than 1 is specified. + // ***************************************************** + if(request->getDeviceCount()>1) + { + msgList = new cdevMessage *[request->getDeviceCount()]; + msgList[0] = request; + } + else msgList = &request; + + // ***************************************************** + // * Walk through each device in the list. + // ***************************************************** + for(int i=0; igetDeviceCount(); i++) + { + if(i>0) msgList[i] = new cdevMessage(*request); + if((node=findMonitor(request->getDeviceList()[i], attrib))==NULL) + { + node = new cdevMonitorNode(this, request->getDeviceList()[i], attrib); + monitors.insert(node->getHashString(), node); + } + if(dataCnt>0 && data!=NULL) + { + node->insertMonitor(msgList[i], ((iinsertMonitor(msgList[i], NULL, i); + } + + // ***************************************************** + // * Delete the containing array of cdevMessage pointers + // ***************************************************** + if(request->getDeviceCount()>1) delete msgList; + } + } + return 0; + } + + +// ***************************************************************************** +// * cdevMonitorTable::removeMonitor : +// * This method allows the caller to remove a specific monitor using the +// * cancelTransIndex component of the cdevMessage object. +// ***************************************************************************** +int cdevMonitorTable::removeMonitor ( cdevMessage * request ) + { + int cancelTransIndex = request->getCancelTransIndex(); + if(cancelTransIndex > 0) + { + StringHashIterator iter(&monitors); + iter.first(); + + while(iter.key()!=NULL) + { + cdevMonitorNode * node = (cdevMonitorNode *)iter.data(); + node->removeMonitor(cancelTransIndex); + ++iter; + } + } + return 0; + } + +// ***************************************************************************** +// * cdevMonitorTable::removeClientMonitors : +// * This method will walk through the hash table and will remove all +// * monitors that are associated with a specific clientID. +// ***************************************************************************** +int cdevMonitorTable::removeClientMonitors ( short clientID, int fire ) + { + char * ptr; + StringHashIterator iter(&monitors); + + iter.first(); + while((ptr= iter.key())!=NULL) + { + cdevMonitorNode * node = (cdevMonitorNode *)iter.data(); + node->removeClientMonitors(clientID, fire); + iter++; + } + return 0; + } + +// ***************************************************************************** +// * cdevMonitorTable::findMonitor : +// * This method locates a cdevMonitorNode associated with the specified +// * device / attribute pair and returns it to the caller. +// ***************************************************************************** +cdevMonitorNode * cdevMonitorTable::findMonitor ( char * device, char * attrib ) + { + char hashString [512]; + sprintf(hashString, "%s %s", device, attrib); + return (cdevMonitorNode *)monitors.find(hashString); + } + + +// ***************************************************************************** +// * cdevMonitorTable:fireMonitor : +// * This method is used to deploy all monitors associated with the +// * device / attribute / property set. +// * +// * If the property parameter is NULL, then all properties will be fired +// * for all monitor associated with the device / attribute pair. +// ***************************************************************************** +int cdevMonitorTable::fireMonitor ( char * device, char * attrib, + char * property, cdevData * data ) + { + cdevMonitorNode * node = findMonitor(device, attrib); + return node==NULL?-1:node->fireMonitor(property, data); + } + +// ***************************************************************************** +// * cdevMonitorTable:fireMonitor : +// * This method is used to deploy all monitors associated with the +// * device / attribute / property set. +// * +// * If the property parameter is -1, then all properties will be fired +// * for all monitors associated with the device / attribute pair. +// ***************************************************************************** +int cdevMonitorTable::fireMonitor ( char * device, char * attrib, + int property, cdevData * data ) + { + cdevMonitorNode * node = findMonitor(device, attrib); + return node==NULL?-1:node->fireMonitor(property, data); + } + + +// ***************************************************************************** +// * cdevMonitorTable::fireCallback : +// * This is a stub for the fireCallback method that must b e provided by +// * the developer. This method is provided here - because this method may +// * potentially be called during program termination - resulting in the +// * attempted execution of a pure virtual function. +// ***************************************************************************** +int cdevMonitorTable::fireCallback ( cdevMessage * /* message */ ) + { + return CDEV_SUCCESS; + } diff --git a/extensions/cdevGenericServer/cdevMonitorTable/cdevMonitorTable.h b/extensions/cdevGenericServer/cdevMonitorTable/cdevMonitorTable.h new file mode 100755 index 0000000..88d0027 --- /dev/null +++ b/extensions/cdevGenericServer/cdevMonitorTable/cdevMonitorTable.h @@ -0,0 +1,136 @@ +#ifndef _CDEV_MONITOR_TABLE_H_ +#define _CDEV_MONITOR_TABLE_H_ 1 + +#include +#include +#include +#include + + +// ***************************************************************************** +// * class cdevMonitorData : +// * This class gives a cdevData object the capacity to selectively place +// * its tagged data items into an XDR stream. +// ***************************************************************************** +class GENERIC_SERVER_API cdevMonitorData : public cdevData +{ +protected: + int * criticalTags; + int criticalTagCnt; + + virtual int isTagCritical ( int tag ); + +public: + cdevMonitorData (void ); + cdevMonitorData (const cdevData & data); + cdevMonitorData (const cdevMonitorData & data); + + virtual void setCriticalTags ( int * tags, int tagCnt ); + virtual int changeTag ( int oldTag, int newTag ); + virtual int xdrExport ( char ** buf, size_t * bufLen ); + virtual int xdrExport ( char * buf, size_t bufLen, size_t count); + virtual int xdrSize ( size_t * bufLen, size_t * elementCount ); +}; + + +// ***************************************************************************** +// * class cdevMonitorNode : +// * This class is used to store the list of monitors associated with a +// * device / attribute pair. It maintains a back-pointer to the +// * cdevMonitorTable object to allow it to call the fireCallback method of +// * the parent in order to submit the reply. +// ***************************************************************************** +class GENERIC_SERVER_API cdevMonitorNode +{ +friend class cdevMonitorTable; + +protected: + // ********************************************************************** + // * class cdevMonitorEntry : + // * This is an individual monitor transaction that has been installed + // * in a cdevMonitorNode. + // ********************************************************************** + class cdevMonitorEntry + { + friend class cdevMonitorNode; + private: + static int VALUE_TAG; + static int STATUS_TAG; + static int TIME_TAG; + static int DEVICE_TAG; // *** Added for multi-device + + cdevMonitorEntry * next; + cdevMessage * message; + int * triggers; + int * trigType; + int trigCnt; + int * properties; + int propCnt; + + int deviceIdx; // *** Added for multi-device + + cdevMonitorEntry ( cdevMessage * Message, int deviceIdx ); + ~cdevMonitorEntry ( void ); + }; + + class cdevMonitorTable * parent; + cdevMonitorEntry * nodes; + cdevMonitorData mData; + char * hashString; + + virtual int fireMonitor ( cdevMonitorEntry *entry, + int property, + cdevMonitorData * data, + int endOfTransaction = 0); + + virtual int insertMonitor ( cdevMessage * request, + cdevData * data, + int deviceIdx ); + + virtual int removeMonitor ( cdevMessage * request ); + virtual int removeMonitor ( unsigned transIndex ); + virtual int removeClientMonitors ( short clientID, int fire = 1 ); + char * getHashString ( void ) { return hashString; } + +public: + cdevMonitorNode ( cdevMonitorTable * Parent, + char * Device, + char * Attrib ); + virtual ~cdevMonitorNode ( void ); + + virtual int fireMonitor ( char * property, cdevData * data ); + virtual int fireMonitor ( int property, cdevData * data ); + int isMonitored ( void ) { return nodes==NULL?0:1; } +}; + + + +// ***************************************************************************** +// * class cdevMonitorTable : +// * This class is used to store the list of all monitors for all device / +// * attribute pairs in the system. The developer must provide the +// * fireCallback method which will be used to submit the callback to the +// * client. +// ***************************************************************************** +class GENERIC_SERVER_API cdevMonitorTable +{ +protected: + StringHash monitors; + +public: + cdevMonitorTable ( void ); + virtual ~cdevMonitorTable ( void ); + + virtual int insertMonitor ( cdevMessage * request, cdevData * data ); + virtual int insertMonitor ( cdevMessage * request, cdevData ** data, size_t dataCnt ); + virtual int removeMonitor ( cdevMessage * request ); + virtual int removeClientMonitors( short clientID, int fire = 1 ); + virtual cdevMonitorNode * findMonitor ( char * device, char * attrib ); + virtual int fireMonitor ( char * device, char * attrib, + char * property, cdevData * data ); + virtual int fireMonitor ( char * device, char * attrib, + int property, cdevData * data ); + virtual int fireCallback ( cdevMessage * message ); +}; + +#endif diff --git a/extensions/cdevGenericServer/cdevMonitorTable/test.cc b/extensions/cdevGenericServer/cdevMonitorTable/test.cc new file mode 100755 index 0000000..17aaa4e --- /dev/null +++ b/extensions/cdevGenericServer/cdevMonitorTable/test.cc @@ -0,0 +1,133 @@ +#include "cdevMonitorTable.h" +#include "cdevTagMap.h" + +cdevTagMap myMap; + +class myMonitorTable : public cdevMonitorTable +{ +public : + int fireCallback (cdevMessage * message ) + { + char * str; + size_t len; + cdevMessage message2; + cdevData *data = message->getData(); + if(data) myMap.localToRemote(*data); + + message->streamOut(&str, &len); + message2.streamIn(str, len); + message2.asciiDump(); + if(str!=NULL) delete str; + + if(data) myMap.remoteToLocal(*data); + + return 0; + } +}; + +myMonitorTable mTbl; + + +char * tagNames[7]= + { + "value", + "status", + "controlHigh", + "controlLow", + "time", + "alarmHigh", + "alarmLow" + }; + +int tagValues[7]= + { + 9001, + 9002, + 9003, + 9004, + 9005, + 9006, + 9007 + }; + +char * deviceList[10] = + { + "device1", + "device2", + "device3", + "device4", + "device5", + "device6", + "device7", + "device8", + "device9", + "device10" + }; + +int main() +{ +cdevMessage * message; +cdevData context; +cdevData * triggers[10]; +cdevData trigger; + +myMap.updateTagMap(tagNames, tagValues, 7); + +cdevData::insertTag(9001, "value1"); +cdevData::insertTag(9002, "status1"); +cdevData::insertTag(9003, "controlHigh1"); +cdevData::insertTag(9004, "controlLow1"); +cdevData::insertTag(9005, "time1"); +cdevData::insertTag(9006, "alarmHigh1"); +cdevData::insertTag(9007, "alarmLow1"); + +context.insert("value", 3); +context.insert("status", 3); +context.insert("controlHigh", 2); +context.insert("controlLow", 2); +context.insert("time", 1); +context.insert("alarmHigh", 1); +context.insert("alarmLow", 1); + +trigger.insert("value", 100); +trigger.insert("status", 0); +trigger.insert("controlHigh", 1000); +trigger.insert("controlLow", 0); +trigger.insert("time", 100); +trigger.insert("alarmHigh", 999); +trigger.insert("alarmLow", 1); + +for(int i=0; i<10; i++) triggers[i] = &trigger; +message = new cdevMessage(1, 1, 0, 0, 0, 0, 0, 10, deviceList, "monitorOn attrib", NULL, &context); +cdevMessage message2(*message); + +message2.setCancelTransIndex(message2.getTransIndex()); +mTbl.insertMonitor(message, triggers, 10); + +fprintf(stdout, "***************** Firing a monitor *****************\n"); +mTbl.fireMonitor ("device1", "attrib", "controlHigh", &trigger); + +mTbl.removeMonitor(&message2); + +fprintf(stdout, "*************** Firing Four Monitors ***************\n"); +mTbl.fireMonitor ("device1", "attrib", "controlHigh", &trigger); +mTbl.fireMonitor ("device2", "attrib", "controlHigh", &trigger); +mTbl.fireMonitor ("device3", "attrib", "controlHigh", &trigger); +mTbl.fireMonitor ("device10", "attrib", "controlHigh", &trigger); + +context.remove(); +context.insert("value", 3); + +cdevMessage *message3 = new cdevMessage(2, 2, 0, 0, 0, 0, 0, 10, deviceList, "monitorOn attrib", NULL, &context); +mTbl.insertMonitor(message3, &trigger); + +for(i=0; i<100; i++) + { + trigger.insert("value", i); + mTbl.fireMonitor("device1", "attrib", "value", &trigger); + } + +mTbl.removeClientMonitors(2); +mTbl.fireMonitor("device1", "attrib", "value", &trigger); +return 0; +} diff --git a/extensions/cdevGenericServer/cdevPacket/Makefile b/extensions/cdevGenericServer/cdevPacket/Makefile new file mode 100755 index 0000000..faa8527 --- /dev/null +++ b/extensions/cdevGenericServer/cdevPacket/Makefile @@ -0,0 +1,18 @@ +ARCH = OS +SHOBJ = YES + +include ../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Packet/Message Source" +CXXINCLUDES = -I./ +LIBS = $(CDEVLIBS) $(OSLIBS) +TARGETS = $(BASEBIN)/cdevPacketTest $(BASEBIN)/sparsePacketTest + +targets: $(TARGETS) + +$(BASEBIN)/cdevPacketTest: $(OBJDIR)/test.o $(OBJDIR)/cdevPacket.o $(OBJDIR)/cdevMessageBinary.o $(OBJDIR)/cdevMessage.o + $(LINK.cc) $^ -o $@ $(LIBS) + +$(BASEBIN)/sparsePacketTest: $(OBJDIR)/sparsePacketTest.o $(OBJDIR)/cdevPacket.o $(OBJDIR)/cdevMessageBinary.o $(OBJDIR)/cdevMessage.o + $(LINK.cc) $^ -o $@ $(LIBS) + diff --git a/extensions/cdevGenericServer/cdevPacket/NMakefile.mak b/extensions/cdevGenericServer/cdevPacket/NMakefile.mak new file mode 100644 index 0000000..df754e2 --- /dev/null +++ b/extensions/cdevGenericServer/cdevPacket/NMakefile.mak @@ -0,0 +1,28 @@ +.SUFFIXES: .cc .obj + +APPNAME = CDEV Packet/Message Test Program +ARCH = WINNT-4.0 +BASEBIN = . +BINARIES = $(BASEBIN)\cdevPacketTest.exe $(BASEBIN)\sparsePacketTest.exe + +include ..\include\makeinclude\Makefile.WINNT-4.0 + +CXXINCLUDES = /I .\\ +CXXEXTRA = /D "GENERIC_SERVER_API= " +TARGETS = $(BASEBIN)\cdevPacketTest.exe $(BASEBIN)\sparsePacketTest.exe + +targets : $(TARGETS) + +$(BASEBIN)\cdevPacketTest.exe : .exec\$(TARGETDIR)\test.obj .exec\$(TARGETDIR)\cdevPacket.obj .exec\$(TARGETDIR)\cdevMessageBinary.obj .exec\$(TARGETDIR)\cdevMessage.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib\ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\sparsePacketTest.exe : .exec\$(TARGETDIR)\sparsePacketTest.obj .exec\$(TARGETDIR)\cdevPacket.obj .exec\$(TARGETDIR)\cdevMessageBinary.obj .exec\$(TARGETDIR)\cdevMessage.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib\ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... diff --git a/extensions/cdevGenericServer/cdevPacket/cdevMessage.cc b/extensions/cdevGenericServer/cdevPacket/cdevMessage.cc new file mode 100755 index 0000000..9e8b9e4 --- /dev/null +++ b/extensions/cdevGenericServer/cdevPacket/cdevMessage.cc @@ -0,0 +1,310 @@ +#include + +// ***************************************************************************** +// * cdevMessage::import : +// * This metod is used by the cdevPacket class to generate a cdevMessage +// * object from a cdevBinaryPacket object. In order for the cdevPacket +// * class to perform this task, the import method and the +// * CDEV_PACKET_VERSION must be registered using the +// * cdevPacket::registerImportMethod function. +// ***************************************************************************** +cdevPacket * cdevMessage::import( cdevPacketBinary & packet) + { + char * binary = NULL; + size_t binaryLen = 0; + + packet.streamOut(&binary, &binaryLen); + + return new cdevMessage(binary, binaryLen); + } + +// ***************************************************************************** +// * cdevMessage::cdevMessage : +// * This is a parameterized constructor for the cdevMessage object. If none +// * of the parameters are specified then this constructor will build a +// * cdevMessage object made completely from defaults. +// ***************************************************************************** +cdevMessage::cdevMessage ( short ClientID, + unsigned TransIndex, + unsigned CancelTransIndex, + unsigned LocalDataIndex, + unsigned ForeignDataIndex, + unsigned OperationCode, + int CompletionCode, + unsigned DeviceCount, + char ** DeviceList, + char * Message, + cdevData * Data, + cdevData * Context, + cdevData * TagMap) + : clientID (ClientID), + transIndex (TransIndex), + cancelTransIndex (CancelTransIndex), + localDataIndex (LocalDataIndex), + foreignDataIndex (ForeignDataIndex), + operationCode (OperationCode), + completionCode (CompletionCode), + deviceCount (DeviceCount), + deviceList (NULL), + message (NULL), + data (NULL), + context (NULL), + tagMap (NULL) + { + saveTbl.rawData=0; + + if(DeviceCount>0 && DeviceList!=NULL) + { + deviceList = (char **)new char * [deviceCount]; + for(int i=0; i0 && Message.deviceList!=NULL) + { + deviceList = (char **)new char * [deviceCount]; + for(int i=0; iasciiDump(fp); + + fprintf(fp, "Context Object : %s", context!=NULL?"\n":"(not specified)\n"); + fflush(fp); + if(context) context->asciiDump(fp); + + fprintf(fp, "Tag Map : %s", tagMap!=NULL?"\n":"(not specified)\n"); + if(tagMap) + { + size_t tagNumCnt = 0; + int * tagNums = NULL; + size_t tagNameCnt = 0; + char ** tagNames = NULL; + + if(tagMap->getElems(1, &tagNumCnt)==CDEV_SUCCESS && + tagMap->getElems(2, &tagNameCnt)==CDEV_SUCCESS && + tagMap->getType (2)==CDEV_STRING && + tagNumCnt==tagNameCnt) + { + char ** tagNames = NULL; + char * singleName = NULL; + + tagNums = new int[tagNumCnt]; + tagMap->get(1, tagNums); + + if(tagNameCnt==1) + { + tagNames = &singleName; + tagMap->find(2, (void *&)singleName); + } + else tagMap->find(2, (void *&)tagNames); + + for(int i=0; i +#include +#include + +class GENERIC_SERVER_API cdevMessage : public cdevPacket +{ +private: + typedef union + { + unsigned char rawData; + struct { + unsigned char saveDeviceList : 1; + unsigned char saveMessage : 1; + unsigned char saveData : 1; + unsigned char saveContext : 1; + unsigned char saveTagMap : 1; + unsigned pad : 3; + } value; + } SaveTable; + + SaveTable saveTbl; + + short clientID; + unsigned transIndex; + unsigned cancelTransIndex; + unsigned localDataIndex; + unsigned foreignDataIndex; + unsigned operationCode; + int completionCode; + unsigned deviceCount; + char ** deviceList; + char * message; + cdevData * data; + cdevData * context; + cdevData * tagMap; + +public: + enum { CDEV_PACKET_VERSION = cdevMessageBinary::CDEV_PACKET_VERSION }; + + static cdevPacket *import( cdevPacketBinary & ); + + cdevMessage ( short ClientID = -1, + unsigned TransIndex = 0, + unsigned CancelTransIndex = 0, + unsigned LocalDataIndex = 0, + unsigned ForeignDataIndex = 0, + unsigned OperationCode = 0, + int CompletionCode = 0, + unsigned DeviceCount = 0, + char ** DeviceList = NULL, + char * Message = NULL, + cdevData * Data = NULL, + cdevData * Context = NULL, + cdevData * TagMap = NULL); + + cdevMessage ( char * binary, size_t binaryLen ); + cdevMessage ( class cdevMessage & message ); + virtual ~cdevMessage ( void ); + virtual void clear ( void ); + virtual int streamIn ( char * binary, size_t binaryLen ); + virtual int streamOut ( char ** binary, size_t * binaryLen ); + virtual void asciiDump ( FILE * fp = stdout ); + + virtual short getVersion ( void ) { return CDEV_PACKET_VERSION; } + virtual short getClientID ( void ) { return clientID; } + virtual unsigned getTransIndex ( void ) { return transIndex; } + + unsigned getCancelTransIndex ( void ) { return cancelTransIndex; } + unsigned getLocalDataIndex ( void ) { return localDataIndex; } + unsigned getForeignDataIndex ( void ) { return foreignDataIndex; } + unsigned getOperationCode ( void ) { return operationCode; } + int getCompletionCode ( void ) { return completionCode; } + unsigned getDeviceCount ( void ) { return deviceCount; } + char ** getDeviceList ( void ) { return deviceList; } + char * getMessage ( void ) { return message; } + cdevData * getData ( void ) { return data; } + cdevData * getContext ( void ) { return context; } + cdevData * getTagMap ( void ) { return tagMap; } + + virtual void setClientID ( short ClientID ) { clientID = ClientID; } + virtual void setTransIndex( unsigned TransIndex ) { transIndex = TransIndex; } + + void setCancelTransIndex ( unsigned CancelTransIndex ) { cancelTransIndex = CancelTransIndex; } + void setLocalDataIndex ( unsigned LocalDataIndex ) { localDataIndex = LocalDataIndex; } + void setForeignDataIndex ( unsigned ForeignDataIndex ) { foreignDataIndex = ForeignDataIndex; } + void setOperationCode ( unsigned OperationCode ) { operationCode = OperationCode; } + void setCompletionCode ( int CompletionCode ) { completionCode = CompletionCode; } + void setDeviceList ( char ** DeviceList, int DeviceCount, int permanent = 0 ) + { + if(deviceList!=NULL && !saveTbl.value.saveDeviceList) + { + for(int i=0; i + +const unsigned BIT01 = 1; +const unsigned BIT02 = 2; +const unsigned BIT03 = 4; +const unsigned BIT04 = 8; +const unsigned BIT05 = 16; +const unsigned BIT06 = 32; +const unsigned BIT07 = 64; +const unsigned BIT08 = 128; +const unsigned BIT09 = 256; +const unsigned BIT10 = 512; +const unsigned BIT11 = 1024; +const unsigned BIT12 = 2048; +const unsigned BIT13 = 4096; +const unsigned BIT14 = 8192; +const unsigned BIT15 = 16384; +const unsigned BIT16 = 32768; + +// ***************************************************************************** +// * cdevMessageBinary::map2int ( void ) +// * This method will convert the cdevMessageBinaryMap to a long integer. +// ***************************************************************************** +unsigned cdevMessageBinary::map2int ( cdevMessageBinaryMap mapdata, unsigned & value) + { + value = (mapdata.value.version << 16); + if(mapdata.value.clientIDSet!=0) value |= BIT16; + if(mapdata.value.transIndexSet!=0) value |= BIT15; + if(mapdata.value.cancelTransIndexSet!=0) value |= BIT14; + if(mapdata.value.localDataIndexSet!=0) value |= BIT13; + if(mapdata.value.foreignDataIndexSet!=0) value |= BIT12; + if(mapdata.value.operationCodeSet!=0) value |= BIT11; + if(mapdata.value.completionCodeSet!=0) value |= BIT10; + if(mapdata.value.deviceListSet!=0) value |= BIT09; + if(mapdata.value.messageSet!=0) value |= BIT08; + if(mapdata.value.dataSet!=0) value |= BIT07; + if(mapdata.value.contextSet!=0) value |= BIT06; + if(mapdata.value.tagMapSet!=0) value |= BIT05; + return value; + } + +// ***************************************************************************** +// * cdevMessageBinary::int2map ( void ) +// * This method will convert a long integer to a cdevMessageBinaryMap. +// ***************************************************************************** +cdevMessageBinaryMap cdevMessageBinary::int2map ( cdevMessageBinaryMap &mapdata, unsigned value) + { + mapdata.rawData = 0; + mapdata.value.version = (value >> 16); + mapdata.value.clientIDSet = (value & BIT16)?1:0; + mapdata.value.transIndexSet = (value & BIT15)?1:0; + mapdata.value.cancelTransIndexSet = (value & BIT14)?1:0; + mapdata.value.localDataIndexSet = (value & BIT13)?1:0; + mapdata.value.foreignDataIndexSet = (value & BIT12)?1:0; + mapdata.value.operationCodeSet = (value & BIT11)?1:0; + mapdata.value.completionCodeSet = (value & BIT10)?1:0; + mapdata.value.deviceListSet = (value & BIT09)?1:0; + mapdata.value.messageSet = (value & BIT08)?1:0; + mapdata.value.dataSet = (value & BIT07)?1:0; + mapdata.value.contextSet = (value & BIT06)?1:0; + mapdata.value.tagMapSet = (value & BIT05)?1:0; + return mapdata; + } + +// ***************************************************************************** +// * cdevMessageBinary::cdevMessageBinary : +// * Copy constructaor for the class. Sets all of the variables to the +// * values stored in the referenced objects. +// ***************************************************************************** +cdevMessageBinary::cdevMessageBinary ( cdevMessageBinary & packet ) + : cdevPacketBinary() + { + streamIn(packet.binary, packet.binaryLen); + } + + +// ***************************************************************************** +// * cdevMessageBinary::cdevMessageBinary : +// * This is the default and parameterized constructor. Allows the caller to +// * directly specify each of the components. +// ***************************************************************************** +cdevMessageBinary::cdevMessageBinary ( short clientID, + unsigned transIndex, + unsigned cancelTransIndex, + unsigned localDataIndex, + unsigned foreignDataIndex, + unsigned operationCode, + int completionCode, + unsigned deviceCount, + char ** deviceList, + char * message, + cdevData * data, + cdevData * context, + cdevData * tagMap) + : cdevPacketBinary() + { + set(clientID, transIndex, cancelTransIndex, localDataIndex, + foreignDataIndex, operationCode, completionCode, deviceCount, + deviceList, message, data, context, tagMap); + } + + +// ***************************************************************************** +// * cdevMessageBinary::~cdevMessageBinary : +// * This is the destructor for the class. +// ***************************************************************************** +cdevMessageBinary::~cdevMessageBinary ( void ) + { + // ********************************************************************* + // * Execute a detach on the embedded data to ensure that it is not + // * deleted locally. + // ********************************************************************* + reader.detachData(); + } + + +// ***************************************************************************** +// * cdevMessageBinary::streamIn : +// * The streamIn function will read a memory buffer provided by the caller +// * and then populate the class with these values. This stream remains the +// * property of the caller and he is responsible for deleting it. +// ***************************************************************************** +int cdevMessageBinary::streamIn ( char *stream, size_t len ) + { + int result = -1; + unsigned packetMap = 0; + + // ********************************************************************* + // * Delete the binary data buffer and set its length to 0. + // ********************************************************************* + if(binary!=NULL) + { + delete binary; + binary = NULL; + } + binaryLen = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(stream, len); + + // ********************************************************************* + // * Clear the packet map prior to reading data from the stream. + // ********************************************************************* + map.rawData = 0; + + // ********************************************************************* + // * Read the packet map from the stream. This object contains a bit + // * field that identifies the version of the packet and tells what + // * other components are embedded in the binary stream. + // ********************************************************************* + result = !reader.get(packetMap); + int2map (map, packetMap); + + // ********************************************************************* + // * Before processing anything else, the method must ensure that this + // * packet is of the correct version. Version 1 for this object. + // * + // * Note that reading each field is contingent on the prior fields + // * being read correctly. + // ********************************************************************* + if(!result && map.value.version == CDEV_PACKET_VERSION) + { + binaryLen = len; + binary = new char[binaryLen]; + memcpy(binary, stream, binaryLen); + } + else result = -1; + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + +// ********************************************************************* +// * cdevMessageBinary::attachData : +// * This method allows the caller to assign a preallocated binary +// * buffer to this object. This prevents the cdevMessageBinary class +// * from having to allocate the data. +// ********************************************************************* +int cdevMessageBinary::attachData ( char * stream, size_t len ) + { + int result = -1; + unsigned packetMap = 0; + + // ********************************************************************* + // * Delete the binary data buffer and set its length to 0. + // ********************************************************************* + if(binary!=NULL) + { + delete binary; + binary = NULL; + } + binaryLen = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(stream, len); + + // ********************************************************************* + // * Clear the packet map prior to reading data from the stream. + // ********************************************************************* + map.rawData = 0; + + // ********************************************************************* + // * Read the packet map from the stream. This object contains a bit + // * field that identifies the version of the packet and tells what + // * other components are embedded in the binary stream. + // ********************************************************************* + result = !reader.get(packetMap); + int2map (map, packetMap); + + // ********************************************************************* + // * Before processing anything else, the method must ensure that this + // * packet is of the correct version. Version 1 for this object. + // * + // * Note that reading each field is contingent on the prior fields + // * being read correctly. + // ********************************************************************* + if(!result && map.value.version == CDEV_PACKET_VERSION) + { + binaryLen = len; + binary = stream; + } + else result = -1; + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + +// ***************************************************************************** +// * cdevMessageBinary::asciiDump : +// * This method performs a diagnostic dump of the text representation of the +// * packets contents. +// ***************************************************************************** +void cdevMessageBinary::asciiDump ( FILE * fp ) + { + short clientID; + unsigned transIndex, cancelTransIndex, localDataIndex; + unsigned foreignDataIndex, operationCode, deviceCount; + int completionCode; + char ** deviceList; + char * message; + cdevData temp; + + getClientID(clientID); + getTransIndex(transIndex); + getCancelTransIndex(cancelTransIndex); + getLocalDataIndex(localDataIndex); + getForeignDataIndex(foreignDataIndex); + getOperationCode (operationCode); + getCompletionCode (completionCode); + getDeviceList(deviceList, deviceCount); + getMessage(message); + + fprintf(fp, "----------------------------------------------------------\n"); + fprintf(fp, " Diagnostic Dump of CDEV Packet\n"); + fprintf(fp, "----------------------------------------------------------\n\n"); + fprintf(fp, "Packet Version : %i\n", CDEV_PACKET_VERSION); + fprintf(fp, "Binary Stream Size : %i\n", binaryLen); + fprintf(fp, "Client Identifier : %s\n", clientID==-1?"(not specified)":ltoa(clientID)); + fprintf(fp, "Transaction Index : %s\n", transIndex==0?"(not specified)":ultoa(transIndex)); + fprintf(fp, "Cancel Transaction : %s\n", cancelTransIndex==0?"(not specified)":ultoa(cancelTransIndex)); + fprintf(fp, "Local Data Index : %s\n", localDataIndex==0?"(not specified)":ultoa(localDataIndex)); + fprintf(fp, "Foreign Data Index : %s\n", foreignDataIndex==0?"(not specified)":ultoa(foreignDataIndex)); + fprintf(fp, "Operation Code : %s\n", operationCode==0?"(not specified)":ultoa(operationCode)); + fprintf(fp, "Completion Code : %i\n", completionCode); + fprintf(fp, "Number of Devices : %s\n", deviceCount==0?"(not specified)":ultoa(deviceCount)); + fprintf(fp, "List of Devices : "); + + if(deviceCount==0) fprintf(fp, "(not specified)\n"); + else fprintf(fp, "%s\n", deviceList[0]); + + for(int i=1; i GOTO_CLIENTID) + { + if(map.value.clientIDSet!=0) + result=!xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+XDR_Sizeof((short)1)); + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the clientID. + // ************************************************************* + else if(flag==GOTO_CLIENTID && !map.value.clientIDSet) result=-1; + + + // ************************************************************* + // * If the selected element is beyond the transIndex, then + // * advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_TRANSINDEX) + { + if(!result && map.value.transIndexSet!=0) + result=!xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+XDR_Sizeof((unsigned)1)); + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the transIndex. + // ************************************************************* + else if(flag==GOTO_TRANSINDEX && !map.value.transIndexSet) result=-1; + + + + // ************************************************************* + // * If the selected element is beyond the cancelTransIndex, + // * then advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_CANCELTRANSINDEX) + { + if(!result && map.value.cancelTransIndexSet!=0) + result=!xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+XDR_Sizeof((unsigned)1)); + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the cancelTransIndex. + // ************************************************************* + else if(flag==GOTO_CANCELTRANSINDEX && !map.value.cancelTransIndexSet) result=-1; + + + + // ************************************************************* + // * If the selected element is beyond the localDataIndex, then + // * advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_LOCALDATAINDEX) + { + if(!result && map.value.localDataIndexSet!=0) + result=!xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+XDR_Sizeof((unsigned)1)); + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the localDataIndex. + // ************************************************************* + else if(flag==GOTO_LOCALDATAINDEX && !map.value.localDataIndexSet) result=-1; + + + + // ************************************************************* + // * If the selected element is beyond the foreignDataIndex, then + // * advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_FOREIGNDATAINDEX) + { + if(!result && map.value.foreignDataIndexSet!=0) + result=!xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+XDR_Sizeof((unsigned)1)); + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the foreignDataIndex. + // ************************************************************* + else if(flag==GOTO_FOREIGNDATAINDEX && !map.value.foreignDataIndexSet) result=-1; + + + + // ************************************************************* + // * If the selected element is beyond the operationCode, + // * then advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_OPERATIONCODE) + { + if(!result && map.value.operationCodeSet!=0) + result=!xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+XDR_Sizeof((unsigned)1)); + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the operationCode. + // ************************************************************* + else if(flag==GOTO_OPERATIONCODE && !map.value.operationCodeSet) result=-1; + + + + // ************************************************************* + // * If the selected element is beyond the operationCode, + // * then advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_COMPLETIONCODE) + { + if(!result && map.value.completionCodeSet!=0) + result=!xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+XDR_Sizeof((int)1)); + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the operationCode. + // ************************************************************* + else if(flag==GOTO_COMPLETIONCODE && !map.value.completionCodeSet) result=-1; + + + // ************************************************************* + // * If the selected element is beyond the deviceList, then + // * advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_DEVICELIST) + { + if(!result && map.value.deviceListSet!=0) + { + int deviceCount; + if((result = !Reader.get(deviceCount))==0) + { + // ************************************* + // * Step over each string in the array. + // ************************************* + for(int i=0; i GOTO_MESSAGE) + { + if(!result && map.value.messageSet!=0) + { + slen = Reader.get_string_len(); + slen = XDR_Sizeof((char *)NULL, slen); + result = !xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+slen); + } + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the message. + // ************************************************************* + else if(flag==GOTO_MESSAGE && !map.value.messageSet) result=-1; + + + + // ************************************************************* + // * If the selected element is beyond the data, then + // * advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_DATA) + { + if(!result && map.value.dataSet!=0) + { + slen = Reader.get_string_len(); + slen = XDR_Sizeof((void *)NULL, slen); + result = !xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+slen); + } + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the data. + // ************************************************************* + else if(flag==GOTO_DATA && !map.value.dataSet) result=-1; + + + + // ************************************************************* + // * If the selected element is beyond the context, then it + // * contains an invalid value and should be cleared. + // ************************************************************* + if(flag > GOTO_CONTEXT) + { + if(!result && map.value.contextSet!=0) + { + slen = Reader.get_string_len(); + slen = XDR_Sizeof((void *)NULL, slen); + result = !xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+slen); + } + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the context. + // ************************************************************* + else if(flag==GOTO_CONTEXT && !map.value.contextSet) result=-1; + + + // ************************************************************* + // * If the selected element is beyond the context, then it + // * contains an invalid value and should be cleared. + // ************************************************************* + if(flag > GOTO_TAGMAP) result = -1; + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the context. + // ************************************************************* + else if(flag==GOTO_TAGMAP && !map.value.tagMapSet) result=-1; + } + + return result; + } + + +// ***************************************************************************** +// * cdevMessageBinary::set : +// * This method will convert the user provided data into the binary stream. +// ***************************************************************************** +void cdevMessageBinary::set ( short clientID, + unsigned transIndex, + unsigned cancelTransIndex, + unsigned localDataIndex, + unsigned foreignDataIndex, + unsigned operationCode, + int completionCode, + unsigned deviceCount, + char ** deviceList, + char * message, + cdevData * data, + cdevData * context, + cdevData * tagMap) + { + unsigned packetMap = 0; + size_t dataLen = 0, dataCnt = 0; + size_t contextLen = 0, contextCnt = 0; + size_t tagMapLen = 0, tagMapCnt = 0; + + if(binary!=NULL) + { + delete binary; + binary = NULL; + } + binaryLen = 0; + + // ********************************************************************* + // * Construct the packet map to indicate which components will be + // * transmitted. + // ********************************************************************* + map.rawData = 0; + map.value.version = CDEV_PACKET_VERSION; + + // ********************************************************************* + // * Because the cdevPacketBinary relies on the ordered existance of the + // * client identifier... this entry will automatically be tagged as + // * present, even though it may contain a default value... + // ********************************************************************* + map.value.clientIDSet = 1; + + // ********************************************************************* + // * All other components will only be marked as present if they have + // * actually been specified. + // ********************************************************************* + if(transIndex > 0) map.value.transIndexSet = 1; + if(cancelTransIndex > 0) map.value.cancelTransIndexSet = 1; + if(localDataIndex > 0) map.value.localDataIndexSet = 1; + if(foreignDataIndex > 0) map.value.foreignDataIndexSet = 1; + if(operationCode > 0) map.value.operationCodeSet = 1; + if(completionCode != 0) map.value.completionCodeSet = 1; + if(deviceCount>0 && deviceList!=NULL) map.value.deviceListSet = 1; + if(message!=NULL) map.value.messageSet = 1; + + if(data!=NULL) data->xdrSize (&dataLen, &dataCnt); + if(context!=NULL) context->xdrSize(&contextLen, &contextCnt); + if(tagMap!=NULL) tagMap->xdrSize (&tagMapLen, &tagMapCnt); + + if(dataCnt > 0) map.value.dataSet = 1; + if(contextCnt > 0) map.value.contextSet = 1; + if(tagMapCnt > 0) map.value.tagMapSet = 1; + + // ********************************************************************* + // * Calculate the total size of the packet. + // ********************************************************************* + binaryLen = XDR_Sizeof( map2int(map, packetMap) ); + if(map.value.clientIDSet!=0) binaryLen += XDR_Sizeof(clientID); + if(map.value.transIndexSet!=0) binaryLen += XDR_Sizeof(transIndex); + if(map.value.cancelTransIndexSet!=0) binaryLen += XDR_Sizeof(cancelTransIndex); + if(map.value.localDataIndexSet!=0) binaryLen += XDR_Sizeof(localDataIndex); + if(map.value.foreignDataIndexSet!=0) binaryLen += XDR_Sizeof(foreignDataIndex); + if(map.value.operationCodeSet!=0) binaryLen += XDR_Sizeof(operationCode); + if(map.value.completionCodeSet!=0) binaryLen += XDR_Sizeof(completionCode); + if(map.value.deviceListSet!=0) + { + binaryLen += XDR_Sizeof(deviceCount); + for(int i=0; ixdrExport(tbuf, dataLen, dataCnt); + xdr_setpos(writer.xdr(), tpos+XDR_Sizeof((void *)NULL, dataLen)); + } + if(map.value.contextSet!=0) + { + tpos = xdr_getpos(writer.xdr()); + writer.put(contextLen); + tbuf = writer.buffer()+xdr_getpos(writer.xdr()); + context->xdrExport(tbuf, contextLen, contextCnt); + xdr_setpos(writer.xdr(), tpos+XDR_Sizeof((void *)NULL, contextLen)); + } + if(map.value.tagMapSet!=0) + { + tpos = xdr_getpos(writer.xdr()); + writer.put(tagMapLen); + tbuf = writer.buffer()+xdr_getpos(writer.xdr()); + tagMap->xdrExport(tbuf, tagMapLen, tagMapCnt); + xdr_setpos(writer.xdr(), tpos+XDR_Sizeof((void *)NULL, tagMapLen)); + } + + writer.detachData(); + } + + +// ***************************************************************************** +// * cdevMessageBinary::getVersion : +// * This method is used to obtain the version number of the packet. +// ***************************************************************************** +int cdevMessageBinary::getVersion ( short & version ) + { + version = CDEV_PACKET_VERSION; + return 0; + } + + +// ***************************************************************************** +// * cdevMessageBinary::getClientID : +// * This method is used to obtain the client identifier for the packet. +// * This method returns 0 on success, or -1 if the clientID was not +// * specified. +// ***************************************************************************** +int cdevMessageBinary::getClientID ( short & clientID ) + { + int result = -1; + clientID = -1; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_CLIENTID))==0) + { + if(map.value.clientIDSet!=0) result=!reader.get(clientID); + } + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + + +// ***************************************************************************** +// * cdevMessageBinary::getTransIndex : +// * This method is used to obtain the transaction object index. This +// * object is used on the client side to obtain a pointer to the transaction +// * object. +// * This method returns 0 on success, or -1 if the transIndex could not +// * be read. +// ***************************************************************************** +int cdevMessageBinary::getTransIndex ( unsigned & transIndex ) + { + int result = -1; + transIndex = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_TRANSINDEX))==0) + { + result = !reader.get(transIndex); + } + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + +// ***************************************************************************** +// * cdevMessageBinary::getCancelTransIndex : +// * This method is used to obtain the identifier of a transaction object +// * that is to be canceled. +// * +// * This method returns 0 on success, or -1 if the cancelCancelTransIndex could not +// * be read. +// ***************************************************************************** +int cdevMessageBinary::getCancelTransIndex ( unsigned & cancelTransIndex ) + { + int result = -1; + cancelTransIndex = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_CANCELTRANSINDEX))==0) + { + result = !reader.get(cancelTransIndex); + } + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + +// ***************************************************************************** +// * cdevMessageBinary::getLocalDataIndex : +// * This method is used to obtain an index to any data that may be +// * maintained on the senders side of the connection. +// * This method returns 0 on success, or -1 if the localDataIndex could +// * not be read. +// ***************************************************************************** +int cdevMessageBinary::getLocalDataIndex ( unsigned & localDataIndex ) + { + int result = -1; + localDataIndex = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_LOCALDATAINDEX))==0) + { + result = !reader.get(localDataIndex); + } + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + +// ***************************************************************************** +// * cdevMessageBinary::getForeignDataIndex : +// * This method is used to obtain an index to any data that may be +// * maintained on the senders side of the connection. +// * This method returns 0 on success, or -1 if the foreignDataIndex could +// * not be read. +// ***************************************************************************** +int cdevMessageBinary::getForeignDataIndex ( unsigned & foreignDataIndex ) + { + int result = -1; + foreignDataIndex = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_FOREIGNDATAINDEX))==0) + { + result = !reader.get(foreignDataIndex); + } + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + +// ***************************************************************************** +// * cdevMessageBinary::getOperationCode : +// * This method is used to obtain the operation code. An operation code may +// * be used by the developer to define a particular message. This is faster +// * to manipulate than the supported string messages. +// ***************************************************************************** +int cdevMessageBinary::getOperationCode ( unsigned & operationCode ) + { + int result = -1; + operationCode = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_OPERATIONCODE))==0) + { + result = !reader.get(operationCode); + } + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + +// ***************************************************************************** +// * cdevMessageBinary::getCompletionCode : +// * This method is used to obtain the completion code. The completion code +// * is returned by the server to indicate the result code from an operation. +// ***************************************************************************** +int cdevMessageBinary::getCompletionCode ( int & completionCode ) + { + int result = -1; + completionCode = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_COMPLETIONCODE))==0) + { + result = !reader.get(completionCode); + } + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + +// ***************************************************************************** +// * cdevMessageBinary::getDeviceList : +// * This method is used to obtains an array of device names that are +// * associated with the request. It is the responsibility of the caller +// * to delete each element of the array, and the array itself when they +// * are no longer needed. +// * This method returns 0 on success, or -1 if the deviceList could +// * not be read. +// ***************************************************************************** +int cdevMessageBinary::getDeviceList ( char ** & deviceList, unsigned & deviceCount) + { + int result = -1; + + deviceList = NULL; + deviceCount = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_DEVICELIST))==0) + { + if((result = !reader.get(deviceCount))==0) + { + // ********************************************* + // * Allocate and initialize an array sufficient + // * to hold the contents of the stream. + // ********************************************* + deviceList = new char * [deviceCount]; + memset(deviceList, 0, sizeof(char *)*deviceCount); + + // ********************************************* + // * Read the individual strings into the array. + // * Note that the XDR_Reader will automatically + // * allocate data if the pointers are set to + // * NULL. + // ********************************************* + for(int i=0; i + +// ***************************************************************************** +// * OperationCode Definitions : +// * CDEV_NORMAL_OP = 0 : This is a message that is to be processed by the +// * developer's server interface. +// * CDEV_SERVER_OP = 1 : This is a message that is to be processed by the +// * Generic Server Interface. +// ***************************************************************************** +enum { + CDEV_NORMAL_OP = 0, + CDEV_SERVER_OP = 1 + }; + +// ***************************************************************************** +// * struct cdevMessageBinaryMap : +// * This is the first 32 bit integer that is passed through the socket. It +// * contains a bitmap that identifies the version of the packet, as well as +// * a bit field that indicates the contents of the packet. This bitfield +// * simplifies the process of decoding the packet and results in a smaller +// * transmission size. +// ***************************************************************************** +typedef union + { + unsigned rawData; + struct { + unsigned version : 16; + unsigned clientIDSet : 1; + unsigned transIndexSet : 1; + unsigned cancelTransIndexSet : 1; + unsigned localDataIndexSet : 1; + unsigned foreignDataIndexSet : 1; + unsigned operationCodeSet : 1; + unsigned completionCodeSet : 1; + unsigned deviceListSet : 1; + unsigned messageSet : 1; + unsigned dataSet : 1; + unsigned contextSet : 1; + unsigned tagMapSet : 1; + unsigned pad : 4; + } value; + } cdevMessageBinaryMap; + + +// ***************************************************************************** +// * The following elements are contained within a cdevMessageBinary binary +// * object. +// * +// * short version : This is the version of the cdevPacketBinary +// * that is being constructed. The format and +// * structure of the remainder of the data is +// * based on version 1. +// * +// * short clientID : **** REQUIRED **** +// * This is the clientID that the server will use +// * to uniquely identify this client. +// * +// * unsigned transIndex : **** REQUIRED **** +// * This is the index that will be used on the +// * client side to locate the transaction object +// * associated with this request. +// * +// * +// * unsigned cancelTransIndex : This is the transaction index of a transaction +// * that should be canceled. This field is +// * typically used to terminate a monitor. +// * +// * unsigned localDataIndex : This is the index that will be used on the +// * ~packet senders~ side to identify a list +// * of devices. +// * +// * unsigned foreignDataIndex : This is the index that will be used on the +// * ~packet receivers~ side to identify a list +// * of devices. +// * +// * +// * unsigned operationCode : This is a user defined operation code that +// * may be used to reduce the size of the data +// * that is transmitted between the client and +// * the server by using integer operation codes +// * rather than character strings. +// * +// * int completionCode : This is the result of the operation on the +// * server side. +// * +// * unsigned deviceCount : This is the number of device names that will +// * be contained in the following list. +// * +// * char ** deviceList : This is a list of character strings that +// * identify cdevDevices. +// * +// * char * message : This is the message text. +// * +// * cdevData data : This is a cdevData object containing the +// * data associated with the request or +// * the result of the request if this packet +// * is a response from a server. +// * +// * cdevData context : This is a cdevData object specifying the +// * context of the request. +// * +// * cdevData tagMap : This is a cdevData object that contains the +// * mapping of the cdevData tag table for the +// * client. By virtue of the fact that this table +// * cannot rely on any of the known tags to exist +// * of be the same... the following integer values +// * will be used. +// * +// * 1) An array of integers that identify the +// * tag numbers. +// * +// * 2) An array of strings that identify the +// * tag names. +// * +// ***************************************************************************** +class GENERIC_SERVER_API cdevMessageBinary : public cdevPacketBinary +{ +private: + cdevMessageBinaryMap map; + XDR_Reader reader; + + +protected: + typedef enum + { + GOTO_CLIENTID=1, + GOTO_TRANSINDEX, + GOTO_CANCELTRANSINDEX, + GOTO_LOCALDATAINDEX, + GOTO_FOREIGNDATAINDEX, + GOTO_OPERATIONCODE, + GOTO_COMPLETIONCODE, + GOTO_DEVICELIST, + GOTO_MESSAGE, + GOTO_DATA, + GOTO_CONTEXT, + GOTO_TAGMAP} POSITION_FLAG; + + // ********************************************************************* + // * cdevMessageBinary::setBinaryPosition : + // * This method will set the position of the binary stream within an + // * XDR_Reader to the specified data object. + // * This method returns 0 on success, or -1 if the data object could + // * not be selected. + // ********************************************************************* + int setBinaryPosition (XDR_Reader & reader, POSITION_FLAG flag ); + +public: + enum { CDEV_PACKET_VERSION = 2 }; + + cdevMessageBinary ( cdevMessageBinary &packet ); + cdevMessageBinary ( short clientID = -1, + unsigned transIndex = 0, + unsigned cancelTransIndex = 0, + unsigned localDataIndex = 0, + unsigned foreignDataIndex = 0, + unsigned operationCode = 0, + int completionCode = 0, + unsigned deviceCount = 0, + char ** deviceList = NULL, + char * message = NULL, + cdevData * data = NULL, + cdevData * context = NULL, + cdevData * tagMap = NULL ); + + virtual ~cdevMessageBinary ( void ); + + // ********************************************************************* + // * map2int ( void ) + // * This method will convert the cdevMessageBinaryMap to an unsigned + // ********************************************************************* + unsigned map2int ( cdevMessageBinaryMap map, unsigned & value); + + // ********************************************************************* + // * int2map ( void ) + // * This method will convert an unsigned to a cdevMessageBinaryMap. + // ********************************************************************* + cdevMessageBinaryMap int2map ( cdevMessageBinaryMap &map, unsigned value); + + // ********************************************************************* + // * The streamIn function will populate the cdevMessageBinary using the + // * data that is specified in the stream. The stream remains the + // * property of the caller, who must delete it when it is no longer + // * needed. + // ********************************************************************* + virtual int streamIn ( char * stream, size_t len ); + + // ********************************************************************* + // * attachData : + // * This method allows the caller to assign a preallocated binary + // * buffer to this object. This prevents the cdevMessageBinary class + // * from having to allocate the data. + // ********************************************************************* + int attachData ( char * stream, size_t len ); + + // ********************************************************************* + // * Performs a diagnostic dump of the object. + // ********************************************************************* + virtual void asciiDump ( FILE * fp = stdout ); + + // ********************************************************************* + // * The set mechanism: + // * Allows the caller to dynamically change the contents of the + // * binary structure. + // ********************************************************************* + void set ( short clientID = -1, + unsigned transIndex = 0, + unsigned cancelTransIndex = 0, + unsigned localDataIndex = 0, + unsigned foreignDataIndex = 0, + unsigned operationCode = 0, + int completionCode = 0, + unsigned deviceCount = 0, + char ** deviceList = NULL, + char * message = NULL, + cdevData * data = NULL, + cdevData * context = NULL, + cdevData * tagMap = NULL ); + + // ********************************************************************* + // * The get mechanisms: + // * The pointers that are retrieved by these functions are the + // * actual pointers that are used within the class. They should not + // * be altered by the caller. The caller may alter the contents of + // * these objects by using the set mechanisms. + // ********************************************************************* + virtual int getVersion ( short & version ); + virtual int getClientID ( short & clientID ); + int getTransIndex ( unsigned & transIndex ); + int getCancelTransIndex ( unsigned & cancelTransIndex ); + int getLocalDataIndex ( unsigned & localDataIndex ); + int getForeignDataIndex ( unsigned & foreignDataIndex ); + int getOperationCode ( unsigned & operationCode ); + int getCompletionCode ( int & completionCode ); + int getDeviceList ( char ** & deviceList, unsigned & deviceCount ); + int getMessage ( char * & message ); + int getData ( cdevData & data ); + int getContext ( cdevData & context ); + int getTagMap ( cdevData & tagMap ); + int get ( short & clientID, + unsigned & transIndex, + unsigned & cancelTransIndex, + unsigned & localDataIndex, + unsigned & foreignDataIndex, + unsigned & operationCode, + int & completionCode, + unsigned & deviceCount, + char ** & deviceList, + char * & message, + cdevData & data, + cdevData & context, + cdevData & tagMap); + + // ********************************************************************* + // * The has mechanisms: + // * This collection of functions allows the caller to determine if + // * certain components of the packet are present. + // ********************************************************************* + int hasClientID ( void ) { return map.value.clientIDSet; } + int hasTransIndex ( void ) { return map.value.transIndexSet; } + int hasCancelTransIndex ( void ) { return map.value.cancelTransIndexSet; } + int hasLocalDataIndex ( void ) { return map.value.localDataIndexSet; } + int hasForeignDataIndex ( void ) { return map.value.foreignDataIndexSet; } + int hasOperationCode ( void ) { return map.value.operationCodeSet; } + int hasCompletionCode ( void ) { return map.value.completionCodeSet; } + int hasDeviceList ( void ) { return map.value.deviceListSet; } + int hasMessage ( void ) { return map.value.messageSet; } + int hasData ( void ) { return map.value.dataSet; } + int hasContext ( void ) { return map.value.contextSet; } + int hasTagMap ( void ) { return map.value.tagMapSet; } +}; + + +#endif /* CDEV_PACKET_BINARY_H_ */ diff --git a/extensions/cdevGenericServer/cdevPacket/cdevPacket.cc b/extensions/cdevGenericServer/cdevPacket/cdevPacket.cc new file mode 100755 index 0000000..6adcd6e --- /dev/null +++ b/extensions/cdevGenericServer/cdevPacket/cdevPacket.cc @@ -0,0 +1,76 @@ +#include + +cdevPacket::ImportTable * cdevPacket::importTables = NULL; +int cdevPacket::maxTables = 0; + + +// ***************************************************************************** +// * cdevPacket::import : +// * The import mechanism will walk through the importTables and attempt to +// * locate an entry that has the same packet version as the cdevPacketBinary +// * parameter. If a matching netry is found, then it will be used to decode +// * the binary and create a cdevPacket object from it, otherwise NULL will +// * be returned. +// * +// * Note: Subclasses of the cdevPacket class that wish to employ this +// * functionality must register their import methods and their packet +// * versions using the registerImportMethod mechanism. +// ***************************************************************************** +cdevPacket * cdevPacket::import ( cdevPacketBinary & packet ) + { + short packetVersion = 0; + int idx = 0; + int found = 0; + cdevPacket * result = NULL; + + packet.getVersion(packetVersion); + + while(idx + +class GENERIC_SERVER_API cdevPacket +{ +public: + typedef cdevPacket * (*ImportMethod)(cdevPacketBinary &); + + typedef struct + { + short packetVersion; + ImportMethod importMethod; + } ImportTable; + + static cdevPacket * import ( cdevPacketBinary & ); + static void registerImportMethod ( short, ImportMethod ); + + cdevPacket ( void ) {} + virtual ~cdevPacket ( void ) {} + + virtual int streamIn ( char * binary, size_t binaryLen ) = 0; + virtual int streamOut ( char ** binary, size_t * binaryLen ) = 0; + virtual void asciiDump ( FILE * fp = stdout ) = 0; + + virtual short getVersion ( void ) = 0; + virtual short getClientID ( void ) = 0; + virtual void setClientID ( short ClientID ) = 0; + +private: + static ImportTable * importTables; + static int maxTables; +}; +#endif diff --git a/extensions/cdevGenericServer/cdevPacket/cdevPacketBinary.h b/extensions/cdevGenericServer/cdevPacket/cdevPacketBinary.h new file mode 100755 index 0000000..db13ffe --- /dev/null +++ b/extensions/cdevGenericServer/cdevPacket/cdevPacketBinary.h @@ -0,0 +1,322 @@ +#ifndef _CDEV_PACKET_H_ +#define _CDEV_PACKET_H_ + +#include +#include +#include + +// ***************************************************************************** +// * struct cdevPacketBinaryMap : +// * This is the first 32 bit integer that is passed through the socket. It +// * contains a bitmap that identifies the version of the packet, as well as +// * a bit field that indicates the contents of the packet. This bitfield +// * simplifies the process of decoding the packet and results in a smaller +// * transmission size. +// ***************************************************************************** +typedef union + { + unsigned rawData; + struct { + unsigned version : 16; + unsigned pad : 16; + } value; + } cdevPacketBinaryMap; + +// ***************************************************************************** +// * class cdevPacketBinary : +// * This is the base class for all cdevPacketBinary classes. It is a pure +// * virtual class that defines the mechanisms necessary for identifying +// * the version of a class as well as reading or generating a binary +// * stream. +// * +// * Enforced structural contraints... +// * +// * 1) Every packet that inherits from the cdevPacketBinary must have an +// * XDR encoded 4 byte integer at the beginning... +// * +// * a) The first two bytes of that 4 byte integer is the packet version. +// * +// * b) The second two bytes of that 4 byte integer is user defined data. +// * +// * 2) The next four bytes of the packet contains a XDR encoded short +// * integer that contains a 16 bit client identifier. +// ***************************************************************************** +class GENERIC_SERVER_API cdevPacketBinary +{ +protected: + // ********************************************************************* + // * These are the data storage variables. + // ********************************************************************* + char * binary; + size_t binaryLen; + +public: + cdevPacketBinary ( void ); + cdevPacketBinary ( cdevPacketBinary & packet ); + virtual ~cdevPacketBinary ( void ); + + unsigned map2int ( cdevPacketBinaryMap map, unsigned & value); + cdevPacketBinaryMap int2map ( cdevPacketBinaryMap &map, unsigned value); + + virtual int getVersion ( short & version ); + virtual int getPad ( short & pad ); + virtual int getClientID ( short & clientID ); + virtual int setClientID ( short clientID ); + virtual int streamOut ( char ** stream, size_t * len ); + virtual int streamIn ( char * stream, size_t len ); + virtual void detachData ( void ); + virtual int attachData ( char * stream, size_t len ); +}; + +// ***************************************************************************** +// * cdevPacketBinary::map2int ( void ) +// * This method will convert the cdevPacketBinaryMap to a long integer. +// ***************************************************************************** +inline unsigned cdevPacketBinary::map2int ( cdevPacketBinaryMap map, unsigned & value) + { + value = (map.value.version << 16); + value |= (map.value.pad & 0xFFFF); + + return value; + } + +// ***************************************************************************** +// * cdevPacketBinary::int2map ( void ) +// * This method will convert a long integer to a cdevPacketBinaryMap. +// ***************************************************************************** +inline cdevPacketBinaryMap cdevPacketBinary::int2map ( cdevPacketBinaryMap &map, unsigned value) + { + map.rawData = 0; + map.value.version = (value >> 16); + map.value.pad = (value & 0xFFFF); + return map; + } + + +// ***************************************************************************** +// * cdevPacketBinary::getVersion : +// * This method is used to obtain the version number of the packet. +// * +// * Returns 0 on Success or -1 on Error +// ***************************************************************************** +inline int cdevPacketBinary::getVersion ( short & version ) + { + int result=-1; + XDR_Reader reader; + cdevPacketBinaryMap map; + + version = -1; + + if(binary!=NULL && binaryLen>0) + { + unsigned packetMap = 0; + reader.attachData(binary, binaryLen); + map.rawData = 0; + if((result = !reader.get(packetMap))==0) + { + int2map(map, packetMap); + version = map.value.version; + } + reader.detachData(); + } + return result; + } + +// ***************************************************************************** +// * cdevPacketBinary::getPad : +// * This method is used to obtain the 16 bit integer that follows the +// * packet version. +// ***************************************************************************** +inline int cdevPacketBinary::getPad ( short & pad ) + { + int result=-1; + XDR_Reader reader; + cdevPacketBinaryMap map; + + pad = -1; + + if(binary!=NULL && binaryLen>0) + { + unsigned packetMap = 0; + reader.attachData(binary, binaryLen); + map.rawData = 0; + if((result = !reader.get(packetMap))==0) + { + int2map(map, packetMap); + pad = map.value.pad; + } + reader.detachData(); + } + return result; + } + + +// ***************************************************************************** +// * cdevPacketBinary::getClientID : +// * This method is used to obtain the 16 bit integer that contains the +// * client identifier. +// ***************************************************************************** +inline int cdevPacketBinary::getClientID ( short & clientID ) + { + int result = -1; + XDR_Reader reader; + + clientID = -1; + + if(binary!=NULL && binaryLen>0) + { + reader.attachData(binary, binaryLen); + if((result = !xdr_setpos(reader.xdr(), XDR_Sizeof((unsigned)1)))==0) + { + result = !reader.get(clientID); + } + reader.detachData(); + } + return result; + } + + +// ***************************************************************************** +// * cdevPacketBinary::getClientID : +// * This method is used to insert the 16 bit integer that contains the +// * client identifier. +// ***************************************************************************** +inline int cdevPacketBinary::setClientID ( short clientID ) + { + int result = -1; + XDR_Writer writer; + + if(binary!=NULL && binaryLen>0) + { + writer.attachData(binary, binaryLen); + if((result = !xdr_setpos(writer.xdr(), XDR_Sizeof((unsigned)1)))==0) + { + result = !writer.put(clientID); + } + writer.detachData(); + } + return result; + } + + +// ***************************************************************************** +// * cdevPacketBinary::streamIn : +// * The streamIn function will read a memory buffer provided by the caller +// * and then populate the class with these values. This stream remains the +// * property of the caller and he is responsible for deleting it. +// * +// * Returns 0 on Success +// ***************************************************************************** +inline int cdevPacketBinary::streamIn ( char * stream, size_t len ) + { + if(binary!=NULL) + { + delete binary; + binary = NULL; + } + binaryLen = 0; + + if(len>0 && stream!=NULL) + { + binary = new char[len]; + binaryLen = len; + memcpy(binary, stream, binaryLen); + } + return 0; + } + +// ***************************************************************************** +// * cdevPacketBinary::streamOut : +// * The streamOut and streamIn functions are the bread and butter of the +// * cdevPacketBinary classes. They allow the class to convert itself into a +// * binary stream for transmission and then be reconstructed into a class +// * when they are received on the other side. +// * +// * The streamOut function will allocate a memory buffer to the stream +// * variable that is sufficient to store the binary representation of +// * the data that is to be transmitted. This stream remains the +// * property of the cdevPacketBinary class and should not be deleted by the +// * caller. +// * +// * Returns 0 on Success +// ***************************************************************************** +inline int cdevPacketBinary::streamOut ( char ** stream, size_t * len ) + { + *stream = binary; + *len = binaryLen; + return 0; + } + +// ********************************************************************* +// * cdevPacketBinary::detachData : +// * This method allows the caller to obtain a copy of the binary +// * image that is stored in the cdevPacketBinary object (using +// * streamOut), and then force the cdevPacket object to detach it +// * (preventing it from being deleted when the object is destroyed.) +// * +// * Returns nothing. +// ********************************************************************* +inline void cdevPacketBinary::detachData ( void ) + { + binary = NULL; + binaryLen = 0; + } + +// ********************************************************************* +// * cdevPacketBinary::attachData : +// * This method allows the caller to assign a preallocated binary +// * buffer to this object. This prevents the cdevPacketBinary class +// * from having to allocate the data. +// * +// * Returns 0 on Success +// ********************************************************************* +inline int cdevPacketBinary::attachData ( char * stream, size_t len ) + { + if(binary!=NULL) + { + delete binary; + binary = NULL; + } + binaryLen = 0; + + if(stream!=NULL && len>0) + { + binary = stream; + binaryLen = len; + } + return 0; + } + +// ***************************************************************************** +// * cdevPacketBinary::cdevPacketBinary : +// * This is the default constructor for the class. +// ***************************************************************************** +inline cdevPacketBinary::cdevPacketBinary ( void ) + : binary(NULL), binaryLen(0) + {} + +// ***************************************************************************** +// * cdevPacketBinary::cdevPacketBinary : +// * This is the copy constructor for the class. +// ***************************************************************************** +inline cdevPacketBinary::cdevPacketBinary ( cdevPacketBinary & packet ) + : binary(NULL), binaryLen(0) + { + streamIn(packet.binary, packet.binaryLen); + } + +// ***************************************************************************** +// * cdevPacketBinary::~cdevPacketBinary : +// * This is the destructor for the object. +// ***************************************************************************** +inline cdevPacketBinary::~cdevPacketBinary ( void ) + { + if(binary!=NULL) + { + delete binary; + binary = NULL; + } + binaryLen = 0; + } + +#endif /* _CDEV_PACKET_H_ */ diff --git a/extensions/cdevGenericServer/cdevPacket/sparsePacketTest.cc b/extensions/cdevGenericServer/cdevPacket/sparsePacketTest.cc new file mode 100755 index 0000000..860b1da --- /dev/null +++ b/extensions/cdevGenericServer/cdevPacket/sparsePacketTest.cc @@ -0,0 +1,103 @@ +#include +#include + +char * myDevices[10] = + { + "Device 0", + "Device 1", + "Device 2", + "Device 3", + "Device 4", + "Device 5", + "Device 6", + "Device 7", + "Device 8", + "Device 9" + }; + +int myTags[] = + { + 1,2,3,4,5,6,7,8,9 + }; + +char * myTagNames[] = + { + "My Tag 1", + "My Tag 2", + "My Tag 3", + "My Tag 4", + "My tag 5", + "My Tag 6", + "My Tag 7", + "My Tag 8", + "My Tag 9" + }; + +char * valueTag[2] = {"This is a test1", "This is a test2"}; +int statusTag[2] = {1, 2}; +double severityTag[2] = {2.0, 3.0}; + +int main() + { + short clientID; + unsigned transIndex, cancelTransIndex; + unsigned localDataIndex; + unsigned foreignDataIndex; + unsigned operationCode; + int completionCode; + unsigned deviceCount; + char ** deviceList; + char * message; + cdevData data, context, tagMap; + + data.insert("value", valueTag, 2, 1); + data.insert("status", statusTag, 2, 1); + data.insert("severity", severityTag, 2, 1); + + context.insert("value", valueTag, 1, 1); + context.insert("status", statusTag, 1, 1); + context.insert("severity", severityTag, 1, 1); + + tagMap.insert (1, myTags, 9); + tagMap.insert (2, myTagNames, 9); + + cdevMessageBinary packet11(1, 2, 500, 3, 4, 5, 6, 10, myDevices, "set VAL", &data, &context, &tagMap); + packet11.asciiDump(); + + cdevMessageBinary packet22; + packet11.get(clientID, transIndex, cancelTransIndex, localDataIndex, foreignDataIndex, operationCode, completionCode, deviceCount, deviceList, message, data, context, tagMap); + packet22.set(clientID, transIndex, cancelTransIndex, localDataIndex, foreignDataIndex, operationCode, completionCode, deviceCount, deviceList, message, &data, &context, &tagMap); + packet22.asciiDump(); + + for(int i=0; iasciiDump(); + delete message2; + + return 0; + } + diff --git a/extensions/cdevGenericServer/cdevPacket/test.cc b/extensions/cdevGenericServer/cdevPacket/test.cc new file mode 100755 index 0000000..826feda --- /dev/null +++ b/extensions/cdevGenericServer/cdevPacket/test.cc @@ -0,0 +1,154 @@ +#include +#include + +char * myDevices[10] = + { + "Device 0", + "Device 1", + "Device 2", + "Device 3", + "Device 4", + "Device 5", + "Device 6", + "Device 7", + "Device 8", + "Device 9" + }; + +int myTags[] = + { + 1,2,3,4,5,6,7,8,9 + }; + +char * myTagNames[] = + { + "My Tag 1", + "My Tag 2", + "My Tag 3", + "My Tag 4", + "My tag 5", + "My Tag 6", + "My Tag 7", + "My Tag 8", + "My Tag 9" + }; + +int main() + { + short clientID; + unsigned transIndex, cancelTransIndex; + unsigned localDataIndex; + unsigned foreignDataIndex; + unsigned operationCode; + int completionCode; + unsigned deviceCount; + char ** deviceList; + char * message; + cdevData data, context, tagMap; + + data.insert("value", "This is a test value"); + data.insert("status", "This is a test status"); + data.insert("displayLow", 1); + data.insert("displayHigh", 2); + data.insert("controlLow", 3); + data.insert("controlHigh", 4); + + context.insert("value", "This is a context test value"); + context.insert("status", "This is a context test status"); + context.insert("displayLow", 5); + context.insert("displayHigh", 6); + context.insert("controlLow", 7); + context.insert("controlHigh", 8); + + tagMap.insert (1, myTags, 9); + tagMap.insert (2, myTagNames, 9); + + cdevMessageBinary packet1; + cdevMessageBinary packet2 (1); + cdevMessageBinary packet3 (1, 2); + cdevMessageBinary packet3a(1, 2, 500); + cdevMessageBinary packet4 (1, 2, 500, 3); + cdevMessageBinary packet5 (1, 2, 500, 3, 4); + cdevMessageBinary packet5a(1, 2, 500, 3, 4, 5); + cdevMessageBinary packet6 (1, 2, 500, 3, 4, 5, 6, 10); + cdevMessageBinary packet7 (1, 2, 500, 3, 4, 5, 6, 10, myDevices); + cdevMessageBinary packet8 (1, 2, 500, 3, 4, 5, 6, 10, myDevices, "set VAL"); + cdevMessageBinary packet9 (1, 2, 500, 3, 4, 5, 6, 10, myDevices, "set VAL", &data); + cdevMessageBinary packet10(1, 2, 500, 3, 4, 5, 6, 10, myDevices, "set VAL", &data, &context); + cdevMessageBinary packet11(1, 2, 500, 3, 4, 5, 6, 10, myDevices, "set VAL", &data, &context, &tagMap); + cdevMessageBinary packet12(-1, 2, 500, 3, 4, 5, 6, 10, myDevices, "set VAL", &data, &context, &tagMap); + cdevMessageBinary packet13(-1, 0, 500, 3, 4, 5, 6, 10, myDevices, "set VAL", &data, &context, &tagMap); + cdevMessageBinary packet14(-1, 0, 0, 3, 4, 5, 6, 10, myDevices, "set VAL", &data, &context, &tagMap); + cdevMessageBinary packet14a(-1, 0, 0, 0, 4, 5, 6, 10, myDevices, "set VAL", &data, &context, &tagMap); + cdevMessageBinary packet15(-1, 0, 0, 0, 0, 5, 6, 10, myDevices, "set VAL", &data, &context, &tagMap); + cdevMessageBinary packet16(-1, 0, 0, 0, 0, 0, 0, 10, myDevices, "set VAL", &data, &context, &tagMap); + cdevMessageBinary packet16a(-1, 0, 0, 0, 0, 0, 0, 0, myDevices, "set VAL", &data, &context, &tagMap); + cdevMessageBinary packet17(-1, 0, 0, 0, 0, 0, 0, 0, NULL, "set VAL", &data, &context, &tagMap); + cdevMessageBinary packet18(-1, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, &data, &context, &tagMap); + cdevMessageBinary packet19(-1, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, &context, &tagMap); + cdevMessageBinary packet20(-1, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, &tagMap); + cdevMessageBinary packet21(-1, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL); + + packet1.asciiDump(); + packet2.asciiDump(); + packet3.asciiDump(); + packet3a.asciiDump(); + packet4.asciiDump(); + packet5.asciiDump(); + packet5a.asciiDump(); + packet6.asciiDump(); + packet7.asciiDump(); + packet8.asciiDump(); + packet9.asciiDump(); + packet10.asciiDump(); + packet11.asciiDump(); + packet12.asciiDump(); + packet13.asciiDump(); + packet14.asciiDump(); + packet14a.asciiDump(); + packet15.asciiDump(); + packet16.asciiDump(); + packet16a.asciiDump(); + packet17.asciiDump(); + packet18.asciiDump(); + packet19.asciiDump(); + packet20.asciiDump(); + packet21.asciiDump(); + + cdevMessageBinary packet22; + packet11.get(clientID, transIndex, cancelTransIndex, localDataIndex, foreignDataIndex, operationCode, completionCode, deviceCount, deviceList, message, data, context, tagMap); + packet22.set(clientID, transIndex, cancelTransIndex, localDataIndex, foreignDataIndex, operationCode, completionCode, deviceCount, deviceList, message, &data, &context, &tagMap); + packet22.asciiDump(); + + for(int i=0; iasciiDump(); + delete message2; + + return 0; + } + diff --git a/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevAddr.o b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevAddr.o new file mode 100644 index 0000000..fd07978 Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevAddr.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevEventHandler.o b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevEventHandler.o new file mode 100644 index 0000000..5277b62 Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevEventHandler.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevHandleSet.o b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevHandleSet.o new file mode 100644 index 0000000..4bb048f Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevHandleSet.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevReactor.o b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevReactor.o new file mode 100644 index 0000000..486c837 Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevReactor.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocket.o b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocket.o new file mode 100644 index 0000000..0b7bf50 Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocket.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocketAcceptor.o b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocketAcceptor.o new file mode 100644 index 0000000..ebdecb6 Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocketAcceptor.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocketConnector.o b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocketConnector.o new file mode 100644 index 0000000..b95362f Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocketConnector.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocketDatagram.o b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocketDatagram.o new file mode 100644 index 0000000..fadc3d1 Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocketDatagram.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocketStream.o b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocketStream.o new file mode 100644 index 0000000..fd67049 Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocketStream.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevStreamNode.o b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevStreamNode.o new file mode 100644 index 0000000..8fc5fef Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevStreamNode.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevStreamQueue.o b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevStreamQueue.o new file mode 100644 index 0000000..ce3d5fe Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevStreamQueue.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevTime.o b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevTime.o new file mode 100644 index 0000000..8f94149 Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevTime.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevAddr.o b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevAddr.o new file mode 100644 index 0000000..3685551 Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevAddr.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevEventHandler.o b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevEventHandler.o new file mode 100644 index 0000000..8e0f594 Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevEventHandler.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevHandleSet.o b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevHandleSet.o new file mode 100644 index 0000000..d25aac2 Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevHandleSet.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevReactor.o b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevReactor.o new file mode 100644 index 0000000..f47d089 Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevReactor.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevSocket.o b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevSocket.o new file mode 100644 index 0000000..2259c3d Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevSocket.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevSocketAcceptor.o b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevSocketAcceptor.o new file mode 100644 index 0000000..4b917ea Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevSocketAcceptor.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevSocketConnector.o b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevSocketConnector.o new file mode 100644 index 0000000..280fc5a Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevSocketConnector.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevSocketDatagram.o b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevSocketDatagram.o new file mode 100644 index 0000000..fc5f39b Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevSocketDatagram.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevSocketStream.o b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevSocketStream.o new file mode 100644 index 0000000..05daec5 Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevSocketStream.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevStreamNode.o b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevStreamNode.o new file mode 100644 index 0000000..20e651c Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevStreamNode.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevStreamQueue.o b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevStreamQueue.o new file mode 100644 index 0000000..ccdd043 Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevStreamQueue.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevTime.o b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevTime.o new file mode 100644 index 0000000..305ae8b Binary files /dev/null and b/extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevTime.o differ diff --git a/extensions/cdevGenericServer/cdevReactor/Makefile b/extensions/cdevGenericServer/cdevReactor/Makefile new file mode 100755 index 0000000..a035419 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/Makefile @@ -0,0 +1,49 @@ +ARCH = OS +SHOBJ = YES + +#include ../include/makeinclude/Makefile.$(ARCH) +include ../include/makeinclude/Makefile.linux + +APPNAME = CDEV Reactor Library +OBJS = $(OBJDIR)/cdevAddr.o\ + $(OBJDIR)/cdevEventHandler.o\ + $(OBJDIR)/cdevHandleSet.o\ + $(OBJDIR)/cdevReactor.o\ + $(OBJDIR)/cdevSocket.o\ + $(OBJDIR)/cdevSocketAcceptor.o\ + $(OBJDIR)/cdevSocketConnector.o\ + $(OBJDIR)/cdevSocketDatagram.o\ + $(OBJDIR)/cdevSocketStream.o\ + $(OBJDIR)/cdevStreamNode.o\ + $(OBJDIR)/cdevStreamQueue.o\ + $(OBJDIR)/cdevTime.o + +# ****************************************************************************** +# * The BINARIES definition names all of the binary files that should be deleted +# * whenever "make clean" is executed. +# ****************************************************************************** +BINARIES = $(BASELIB)/libcdevReactor.$(SHARED_EXT) \ + $(BASELIB)/libcdevReactor.a + +# ****************************************************************************** +# * The TARGETS variable is used to specify the name of the library to build. +# ****************************************************************************** +ifeq ($(SHOBJ),YES) + TARGETS = $(BASELIB)/libcdevReactor.$(SHARED_EXT) +else + TARGETS = $(BASELIB)/libcdevReactor.a +endif + +targets : $(TARGETS) + +$(BASELIB)/libcdevReactor.a : $(OBJS) + $(LINK.a) $@ $^ + @$(RANLIB) $@ > /dev/null + @mkdir -p $(CDEVLIB) + @cp $@ $(CDEVLIB) + +$(BASELIB)/libcdevReactor.$(SHARED_EXT) : $(OBJS) + $(LINK.so) -o $@ $^ $(NETLIBS) + @mkdir -p $(CDEVLIB) + @cp $@ $(CDEVLIB) + diff --git a/extensions/cdevGenericServer/cdevReactor/NMakefile.mak b/extensions/cdevGenericServer/cdevReactor/NMakefile.mak new file mode 100644 index 0000000..36116ff --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/NMakefile.mak @@ -0,0 +1,54 @@ +.SUFFIXES: .cc .obj + +ARCH = WINNT-4.0 +SHOBJ = YES +APPNAME = CDEV Reactor Library + +include ..\include\makeinclude\Makefile.WINNT-4.0 + +OBJS = $(OBJDIR)/cdevAddr.obj\ + $(OBJDIR)/cdevEventHandler.obj\ + $(OBJDIR)/cdevHandleSet.obj\ + $(OBJDIR)/cdevReactor.obj\ + $(OBJDIR)/cdevSocket.obj\ + $(OBJDIR)/cdevSocketAcceptor.obj\ + $(OBJDIR)/cdevSocketConnector.obj\ + $(OBJDIR)/cdevSocketDatagram.obj\ + $(OBJDIR)/cdevSocketStream.obj\ + $(OBJDIR)/cdevStreamNode.obj\ + $(OBJDIR)/cdevStreamQueue.obj\ + $(OBJDIR)/cdevTime.obj + +CXXEXTRA = /D "_CDEV_REACTOR_EXPORTS_=1" + +# ****************************************************************************** +# * The BINARIES definition names all of the binary files that should be deleted +# * whenever "make clean" is executed. +# ****************************************************************************** +BINARIES = $(BASELIB)\cdevReactor.dll \ + $(BASELIB)\cdevReactor.lib + +# ****************************************************************************** +# * The TARGETS variable is used to specify the name of the library to build. +# ****************************************************************************** +!IF "$(SHOBJ)" == "YES" +TARGETS = $(CDEVLIB)\cdevReactor.dll +!ELSE +TARGETS = $(CDEVLIB)\cdevReactor.lib +!ENDIF + +targets : $(TARGETS) + +$(CDEVLIB)\cdevReactor.lib : $(OBJS) + @echo =^> Building $(@F) + @echo =^> Objects: $(?F) + -@if exist $@ erase $@ + $(LIB32) $(LINK_LIB_FLAGS) /out:$@ $(OBJS) + @echo ^<= Done... + +$(CDEVLIB)\cdevReactor.dll : $(OBJS) + @echo =^> Building $(@F) + @echo =^> Objects: $(?F) + -@if exist $@ erase $@ + $(LIB32) $(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $(OBJS) + @echo ^<= Done... diff --git a/extensions/cdevGenericServer/cdevReactor/ServerTest/ClientTest1.cc b/extensions/cdevGenericServer/cdevReactor/ServerTest/ClientTest1.cc new file mode 100755 index 0000000..2a876b2 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/ServerTest/ClientTest1.cc @@ -0,0 +1,129 @@ +#include +#include +#include +#include "TestNode.h" + +TestNode * TestNode::freeList = NULL; + +#ifndef TRUE + #define TRUE 1 + #define FALSE 0 +#endif + +cdevReactor GlobalReactor; + +class ServerHandler : public cdevEventHandler, public cdevNodeFactory +{ +private: + cdevBufferedSocket stream; + int count; + int inboundCount; + +public: + ServerHandler ( const cdevAddr &addr ) + : count(0), inboundCount(0), stream(0, 1, this) + { + open(addr); + } + + int open ( const cdevAddr & addr ) + { + int retval = -1; + + if((retval = stream.connect(addr))==0) + { + retval = GlobalReactor.registerHandler(this, WRITE_MASK); + } + return retval; + } + + int getHandle ( void ) const + { + return stream.getHandle(); + } + + void setHandle ( int handle ) + { + stream.setHandle(handle); + } + + cdevStreamNode * newNode ( ssize_t size ) + { + TestNode * node = new TestNode; + node->setLen(size); + return node; + } + + int handleInput ( void ) + { + int retval = 0; + cdevStreamNode * node = NULL; + + if((retval = stream.receive())>0) + { + while((node=stream.dequeueInbound())!=NULL) + { + if(((inboundCount++)%1000)==0) fprintf(stdout, "CLIENT: I received \"%s\"\n", node->getBuf()); + delete node; + } + } + + if(retval<0) setMask(DONT_CALL); + else if(!stream.inboundReady()) setMask(WRITE_MASK); + + return retval>=0?0:-1; + } + + int handleOutput ( void ) + { + int retval = 0; + + if(!stream.outboundReady()) + { + for(int i=0; i<1000; i++) + { + TestNode * node = new TestNode; + node->setLen(sprintf(node->getBuf(), "Client Packet %i", count++)+1); + stream.enqueueOutbound(node); + } + setMask(WRITE_MASK); + } + + retval=stream.transmit(); + if(retval<0) setMask(DONT_CALL); + else if(!stream.outboundReady()) setMask(READ_MASK); + + return retval>=0?0:-1; + } + + int handleClose ( void ) + { + stream.close(); + return 0; + } +}; + +int main ( int argc, char * argv[], char * envp [] ) + { + if(argc<3) + { + fprintf(stderr, "%s [host] [port]\n", "ClientTest1"); + return -1; + } + + char * host = argv[1]; + short port = atoi(argv[2]); + + + + cdevInetAddr serverAddr( port, host); + printf("Connecting to %s:%i\n", serverAddr.getHostName(),serverAddr.getPortNum()); + ServerHandler * client = new ServerHandler(serverAddr); + + for(int i=0; i<100; i++) + { + if(i%10==0) fprintf(stdout, "====> Have reached iteration %i\n", i); + GlobalReactor.handleEvents(1.0); + } + return 0; + } diff --git a/extensions/cdevGenericServer/cdevReactor/ServerTest/Makefile b/extensions/cdevGenericServer/cdevReactor/ServerTest/Makefile new file mode 100755 index 0000000..4d2d865 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/ServerTest/Makefile @@ -0,0 +1,17 @@ +SHOBJ=NO +ARCH =OS + +include ../../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "cdevReactor Client/Server Test" +CXXEXTRA = -I../ +TARGETS = ServerTest1 ClientTest1 + +targets : $(TARGETS) + +ServerTest1 : $(OBJDIR)/ServerTest1.o + $(LINK.cc) -o $@ $^ -L$(CDEVLIB) -lcdevReactor -lm + +ClientTest1 : $(OBJDIR)/ClientTest1.o + $(LINK.cc) -o $@ $^ -L$(CDEVLIB) -lcdevReactor -lm + diff --git a/extensions/cdevGenericServer/cdevReactor/ServerTest/NMakefile.mak b/extensions/cdevGenericServer/cdevReactor/ServerTest/NMakefile.mak new file mode 100644 index 0000000..a1411f4 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/ServerTest/NMakefile.mak @@ -0,0 +1,32 @@ +.SUFFIXES: .cc .obj + +ARCH = WINNT-4.0 + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +BASEBIN = . +OBJDIR = .exec\WINNT-4.0 +CXXINCLUDES = /I ..\ + +TARGETS = $(BASEBIN)\ServerTest1.exe $(BASEBIN)\ClientTest1.exe + +targets : $(TARGETS) + + +$(BASEBIN)\ServerTest1.exe : .exec\$(TARGETDIR)\ServerTest1.obj + $(LINK) \ + $(CDEVLIB)\cdevReactor.lib $(LINK_EXE_FLAGS) /out:$@ \ + .exec\$(TARGETDIR)\ServerTest1.obj + +$(BASEBIN)\ClientTest1.exe : .exec\$(TARGETDIR)\ClientTest1.obj + $(LINK) \ + $(CDEVLIB)\cdevReactor.lib $(LINK_EXE_FLAGS) /out:$@ \ + .exec\$(TARGETDIR)\ClientTest1.obj + +purgeworkspace : + -@del *.dsp + -@del *.plg + -@del *.dsw + -@del *.ncb + -@del *.opt + diff --git a/extensions/cdevGenericServer/cdevReactor/ServerTest/ServerTest1.cc b/extensions/cdevGenericServer/cdevReactor/ServerTest/ServerTest1.cc new file mode 100755 index 0000000..95dcf30 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/ServerTest/ServerTest1.cc @@ -0,0 +1,176 @@ +#include +#include +#include +#include "TestNode.h" + +TestNode * TestNode::freeList = NULL; + +#ifndef TRUE + #define TRUE 1 + #define FALSE 0 +#endif + +cdevReactor GlobalReactor; + +class ClientHandler : public cdevEventHandler, public cdevNodeFactory +{ +friend class Acceptor; + +private: + cdevBufferedSocket stream; + int inboundCount; + int count; + +public: + ClientHandler ( void ) : count(0), inboundCount(0), stream(0, 1, this) {} + + int open ( void ) + { + return GlobalReactor.registerHandler(this, READ_MASK); + } + + int getHandle ( void ) const + { + return stream.getHandle(); + } + + void setHandle ( int handle ) + { + stream.setHandle(handle); + } + + cdevStreamNode * newNode ( ssize_t size ) + { + TestNode * node = new TestNode; + node->setLen(size); + return node; + } + + int handleInput ( void ) + { + int retval = 0; + cdevStreamNode * node = NULL; + + if((retval = stream.receive())>0) + { + while((node=stream.dequeueInbound())!=NULL) + { + if(((inboundCount++)%1000)==0) fprintf(stdout, "SERVER: I received \"%s\"\n", node->getBuf()); + delete node; + } + } + + if(!stream.inboundReady()) + { + for(int i=0; i<1000; i++) + { + TestNode * node = new TestNode; + node->setLen(sprintf(node->getBuf(), "Server Packet %i", count++)+1); + stream.enqueueOutbound(node); + } + setMask(READ_MASK|WRITE_MASK); + } + + if(retval<0) setMask(DONT_CALL); + + return retval>=0?0:-1; + } + + int handleOutput ( void ) + { + int retval = 0; + + retval=stream.transmit(); + if(retval<0) setMask(DONT_CALL); + else if(!stream.outboundReady()) setMask(READ_MASK); + + return retval>=0?0:-1; + } + + int handleClose ( void ) + { + fprintf(stdout, "Closing connection to host\n"); + stream.close(); + return 0; + } +}; + + +class Acceptor : public cdevEventHandler +{ +public: + Acceptor ( const cdevAddr &addr ) + { + open(addr); + GlobalReactor.registerHandler(this, READ_MASK); + } + + int open ( const cdevAddr &addr ) + { + int result = -1; + if (acceptor.open (addr, TRUE) == -1) + { + fprintf(stdout, "Acceptor [ERROR]: Failed to open listening port"); + } + else if (acceptor.setFlags (O_NONBLOCK) == -1) + { + fprintf(stdout, "Acceptor [ERROR]: Could not enable non-blocking I/O"); + } + else result = 0; + return result; + } + + int getHandle ( void ) const + { + return acceptor.getHandle(); + } + + void setHandle ( int handle ) + { + acceptor.setHandle(handle); + } + + int handleInput ( void ) + { + cdevInetAddr addr; + ClientHandler * handler = new ClientHandler; + if(acceptor.accept(handler->stream, &addr)!=-1) + { + fprintf(stdout, "Received connection from host %s\n", addr.getHostName()); + handler->open(); + } + return 0; + } + + int handleClose ( void ) + { + acceptor.close(); + return 0; + } + +private: + cdevSocketAcceptor acceptor; + }; + + + +int main (int argc, char * argv[], char * envp[]) + { + if(argc<2) + { + fprintf(stderr, "%s [port]\n", argv[0]); + return -1; + } + + short port = atoi(argv[1]); + cdevInetAddr acceptAddr(port, (long)INADDR_ANY); + Acceptor * acceptor = new Acceptor(acceptAddr); + + for(int i=0; i<100; i++) + { + if(i%10==0) fprintf(stdout, "====> Have reached iteration %i\n", i); + GlobalReactor.handleEvents(1.0); + } + + return 0; + } diff --git a/extensions/cdevGenericServer/cdevReactor/ServerTest/TestNode.h b/extensions/cdevGenericServer/cdevReactor/ServerTest/TestNode.h new file mode 100755 index 0000000..3820307 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/ServerTest/TestNode.h @@ -0,0 +1,48 @@ +#include + +class TestNode : public cdevStreamNode +{ +private: + static TestNode * freeList; + TestNode * freeListNext; + + char buf[75]; + size_t len; + +public: + TestNode ( void ) + : len(0), freeListNext(NULL) + { + } + size_t getLen ( void ) const { return len; } + void setLen ( size_t size ) { len = size; } + char * getBuf ( void ) const { return (char *)buf; } + void setBuf ( char * buffer, size_t size) + { + strcpy(buf, buffer); + len = size; + } + + void * operator new ( size_t ) + { + TestNode * node; + if(freeList==NULL) + { + freeList = ::new TestNode[1000]; + for(int i=0; i<999; i++) + { + freeList[i].freeListNext = &freeList[i+1]; + } + } + node = freeList; + freeList = node->freeListNext; + return node; + } + + void operator delete ( void * ptr ) + { + TestNode * node = (TestNode *)ptr; + node->freeListNext = freeList; + freeList = node; + } +}; diff --git a/extensions/cdevGenericServer/cdevReactor/TimerTest/Makefile b/extensions/cdevGenericServer/cdevReactor/TimerTest/Makefile new file mode 100755 index 0000000..a3987bc --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/TimerTest/Makefile @@ -0,0 +1,17 @@ +SHOBJ=NO +ARCH =OS + +include ../../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "cdevReactor Timer Test" +TARGETS = TimerTest1 TimerTest2 +CXXEXTRA = -I../ + +targets : $(TARGETS) + +TimerTest1 : $(OBJDIR)/TimerTest1.o + $(LINK.cc) -o $@ $^ -L$(CDEVLIB) -lcdevReactor -lm + +TimerTest2 : $(OBJDIR)/TimerTest2.o + $(LINK.cc) -o $@ $^ -L$(CDEVLIB) -lcdevReactor -lm + diff --git a/extensions/cdevGenericServer/cdevReactor/TimerTest/NMakefile.mak b/extensions/cdevGenericServer/cdevReactor/TimerTest/NMakefile.mak new file mode 100644 index 0000000..c199738 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/TimerTest/NMakefile.mak @@ -0,0 +1,24 @@ +.SUFFIXES: .cc .obj + +ARCH = WINNT-4.0 + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +BASEBIN = . +OBJDIR = .exec\WINNT-4.0 +CXXINCLUDES = /I ..\ + +TARGETS = $(BASEBIN)\TimerTest1.exe $(BASEBIN)\TimerTest2.exe + +targets : $(TARGETS) + +$(BASEBIN)\TimerTest1.exe : .exec\$(TARGETDIR)\TimerTest1.obj + $(LINK) \ + $(CDEVLIB)\cdevReactor.lib $(LINK_EXE_FLAGS) /out:$@ \ + .exec\$(TARGETDIR)\TimerTest1.obj + + +$(BASEBIN)\TimerTest2.exe : .exec\$(TARGETDIR)\TimerTest2.obj + $(LINK) \ + $(CDEVLIB)\cdevReactor.lib $(LINK_EXE_FLAGS) /out:$@ \ + .exec\$(TARGETDIR)\TimerTest2.obj diff --git a/extensions/cdevGenericServer/cdevReactor/TimerTest/SocketTest1.cc b/extensions/cdevGenericServer/cdevReactor/TimerTest/SocketTest1.cc new file mode 100755 index 0000000..c9e2c41 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/TimerTest/SocketTest1.cc @@ -0,0 +1,28 @@ +#include +#include + +class simpleAcceptor : public cdevEventHandler +{ + +} +class simpleServer : public cdevEventHandler +{ +public: + int handleOpen ( void ) + { + } + + int handleInput ( void ) + { + char block[1024]; + + } +}; + +int main () + { + cdevReactor reactor; + simpleTimer timer; + reactor.registerTimer(&timer); + for(int i=0; i<10; i++) reactor.handleEvents(); + } diff --git a/extensions/cdevGenericServer/cdevReactor/TimerTest/TimerTest1.cc b/extensions/cdevGenericServer/cdevReactor/TimerTest/TimerTest1.cc new file mode 100755 index 0000000..4187a10 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/TimerTest/TimerTest1.cc @@ -0,0 +1,27 @@ +#include +#include + +class simpleTimer : public cdevEventHandler +{ +public: + simpleTimer ( void ) + { + setTimeoutRate(1.0); + } + + int handleTimeout ( void ) + { + fprintf(stdout, "."); + fflush(stdout); + return 0; + } +}; + +int main () + { + cdevReactor reactor; + simpleTimer timer; + reactor.registerTimer(&timer); + for(int i=0; i<10; i++) reactor.handleEvents(); + return 0; + } diff --git a/extensions/cdevGenericServer/cdevReactor/TimerTest/TimerTest2.cc b/extensions/cdevGenericServer/cdevReactor/TimerTest/TimerTest2.cc new file mode 100755 index 0000000..c81b7ab --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/TimerTest/TimerTest2.cc @@ -0,0 +1,48 @@ +#include +#include +#include + +class simpleTimer : public cdevEventHandler +{ +private: + char c; + +public: + simpleTimer ( char outputChar='.', double timeout=1.0 ) + : c(outputChar) + { + setTimeoutRate(timeout); + } + + int handleTimeout ( void ) + { + fprintf(stdout, "%c", c); + fflush(stdout); + return 0; + } +}; + +int main (int argc, char ** argv) + { + int iterations = 100; + cdevReactor reactor; + simpleTimer timer1('.', 1.0); + simpleTimer timer2('-', 0.5); + simpleTimer timer3(',', 10.0); + simpleTimer timer4('+', 0.25); + simpleTimer timer5('-', 0.05); + + if(argc>1) iterations = atoi(argv[1]); + if(iterations<=0) iterations=100; + + fprintf(stdout, "Processing for %i iterations\n", iterations); + + reactor.registerTimer(&timer1); + reactor.registerTimer(&timer2); + reactor.registerTimer(&timer3); + reactor.registerTimer(&timer4); + reactor.registerTimer(&timer5); + + for(int i=0; ih_addr, server_info->h_length); + retval = set(portnum, addr); + } + else retval = -1; + + return retval; + } + + +// ***************************************************************************** +// * cdevInetAddr::set : +// * Allows the caller to set the address using a sockaddr_in structure +// * and its length. +// ***************************************************************************** +int cdevInetAddr::set (const sockaddr_in *addr, int len) + { + setType(AF_INET); + setSize(len); + memcpy((void *)&inet_addr, (void *)addr, len); + return 0; + } + + +// ***************************************************************************** +// * cdevInetAddr::cdevInetAddr : +// * This constructor creates an empty address object. +// ***************************************************************************** +cdevInetAddr::cdevInetAddr ( void ) + : cdevAddr(AF_INET, sizeof(sockaddr_in)) + { + ::memset((void *)&inet_addr, 0, sizeof(inet_addr)); + } + + +// ***************************************************************************** +// * cdevInetAddr::cdevInetAddr : +// * This constructor copies the contents of one cdevInetAddr object to +// * the new cdevInetAddr object. +// ***************************************************************************** +cdevInetAddr::cdevInetAddr ( const cdevInetAddr & addr ) + : cdevAddr(AF_INET, sizeof(inet_addr)) + { + memcpy((void *)&inet_addr, (void *)&addr.inet_addr, sizeof(inet_addr)); + } + + +// ***************************************************************************** +// * cdevInetAddr::cdevInetAddr : +// * This constructor creates a new cdevInetAddr object that contains the +// * address provided in the sockaddr_in object. +// ***************************************************************************** +cdevInetAddr::cdevInetAddr (const sockaddr_in *addr, int len) + { + set(addr, len); + } + + +// ***************************************************************************** +// * cdevInetAddr::cdevInetAddr : +// * This constructor initializes the new cdevInetAddr object using the +// * specified port number and host name. +// ***************************************************************************** +cdevInetAddr::cdevInetAddr (unsigned short portnum, char hostname[]) + { + set(portnum, hostname); + } + + +// ***************************************************************************** +// * cdevInetAddr::cdevInetAddr : +// * This constructor initializes the new cdevInetAddr object with the +// * specified port number and ip address. +// ***************************************************************************** +cdevInetAddr::cdevInetAddr (unsigned short portnum, long ip_addr) + { + set(portnum, ip_addr); + } + + +// ***************************************************************************** +// * cdevInetAddr::getHostName : +// * This method allows the caller to return the name of the host that +// * the cdevInetAddr structure identifies. +// ***************************************************************************** +const char * cdevInetAddr::getHostName ( void ) const + { + char * retval; + hostent * hp; + int len = sizeof(inet_addr.sin_addr.s_addr); + + if((hp = ::gethostbyaddr((char *)&inet_addr.sin_addr, len, addr_type))==0) + { + retval = NULL; + } + else retval = hp->h_name; + + return retval; + } + + +// ***************************************************************************** +// * cdevInetAddr::getHostAddr : +// * This method allows the caller to retrieve the internet address (in +// * string format) of the host that the cdevInetAddr object identifies. +// ***************************************************************************** +const char * cdevInetAddr::getHostAddr ( void ) const + { + return ::inet_ntoa(inet_addr.sin_addr); + } + + +// ***************************************************************************** +// * cdevInetAddr::getInetAddr : +// * This method allows the caller to obtain the internet address of the +// * host that the cdevInetAddr object identifies. +// ***************************************************************************** +unsigned long cdevInetAddr::getInetAddr ( void ) const + { + return ntohl((unsigned long)inet_addr.sin_addr.s_addr); + } + + +// ***************************************************************************** +// * cdevInetAddr::getPortNum : +// * This method allows the caller to retrieve the port number that is +// * associated with this cdevInetAddr. +// ***************************************************************************** +unsigned short cdevInetAddr::getPortNum ( void ) const + { + return ntohs (inet_addr.sin_port); + } + + +// ***************************************************************************** +// * cdevInetAddr::getAddress : +// * Returns the address of the sockaddr_in structure. +// ***************************************************************************** +void * cdevInetAddr::getAddress ( void ) const + { + return (void *)&inet_addr; + } + diff --git a/extensions/cdevGenericServer/cdevReactor/cdevAddr.h b/extensions/cdevGenericServer/cdevReactor/cdevAddr.h new file mode 100755 index 0000000..89233e8 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevAddr.h @@ -0,0 +1,48 @@ +#ifndef _CDEV_ADDR_H_ +#define _CDEV_ADDR_H_ + +#include "cdevPlatforms.h" + +class CDEV_REACTOR_API cdevAddr +{ +protected: + int addr_type; + int addr_size; + +public: + cdevAddr ( void ) : addr_type(0), addr_size(0) {} + cdevAddr ( int type, int size ) : addr_type(type), addr_size(size) {} + int getSize ( void ) const { return addr_size; } + void setSize ( int size ) { addr_size = size; } + int getType ( void ) const { return addr_type; } + void setType ( int type ) { addr_type = type; } + + virtual void * getAddress ( void ) const { return NULL; } + +}; + + +class CDEV_REACTOR_API cdevInetAddr : public cdevAddr +{ +protected: + sockaddr_in inet_addr; + +public: + cdevInetAddr (void); + cdevInetAddr (const cdevInetAddr & addr); + cdevInetAddr (const sockaddr_in *, int len); + cdevInetAddr (unsigned short portnum, char hostname[]); + cdevInetAddr (unsigned short portnum, long ip_addr=INADDR_ANY); + + int set (unsigned short portnum, const char hostname[]); + int set (unsigned short portnum, long ip_addr=INADDR_ANY); + int set (const sockaddr_in *, int len); + + const char * getHostName ( void ) const; + const char * getHostAddr ( void ) const; + unsigned long getInetAddr ( void ) const; + unsigned short getPortNum ( void ) const; + void * getAddress ( void ) const; +}; + +#endif diff --git a/extensions/cdevGenericServer/cdevReactor/cdevBufferedSocket.cc b/extensions/cdevGenericServer/cdevReactor/cdevBufferedSocket.cc new file mode 100755 index 0000000..f8a4515 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevBufferedSocket.cc @@ -0,0 +1,256 @@ +#include "cdevBufferedSocket.h" + +// ***************************************************************************** +// * cdevBufferedSocket::sigPipeHandler : +// * This is a default signal pipe handler. +// ***************************************************************************** +void cdevBufferedSocket::sigPipeHandler ( int ) + { + } + + +// ***************************************************************************** +// * cdevBufferedSocket::newNode : +// * This method will return a pointer to a cdevSimpleStreamNode. This +// * node will then be populated with data that is read from the socket. +// ***************************************************************************** +cdevStreamNode * cdevBufferedSocket::newNode ( ssize_t size ) + { + cdevSimpleStreamNode * ptr = NULL; + if(size>0) ptr = new cdevSimpleStreamNode(new char[size], size); + return ptr; + } + + +// ***************************************************************************** +// * cdevBufferedSocket::transmit : +// * This method will attempt to transmit as many packets as immediately +// * possible from the activeOut cdevStreamQueue. The function will cease +// * transmitting when the queue is empty or when the receiver is fails +// * to accept data after a pre-specified number of retries. +// ***************************************************************************** +ssize_t cdevBufferedSocket::transmit ( void ) + { + int totalSent = 0; + int parm = 0; + int retval = 0; + int retries = 0; + + #ifndef WIN32 + void (*oldSig)(int) = signal(SIGPIPE, sigPipeHandler); + #endif + + setOption(IPPROTO_TCP, TCP_NODELAY, &parm, sizeof(parm)); + + if(activeOut.isEmpty()) + { + if(!waitingOut.isEmpty()) + { + activeOut.enqueue(waitingOut); + headerXfrLen = 0; + dataXfrLen = 0; + outboundHeader[0] = htonl(magicNumber); + outboundHeader[1] = htonl(activeOut.getSize()+sizeof(size_t)); + outboundHeader[2] = htonl(activeOut.getCount()); + } + else return 0; + } + + while(headerXfrLen<12 && retries=0) + { + retval = send(((char *)outboundHeader)+headerXfrLen, 12-headerXfrLen); + if(retval>=0) + { + retries = retval?0:retries+1; + headerXfrLen += retval; + totalSent += retval; + } + } + + while(headerXfrLen>=12 && retries=0 && !activeOut.isEmpty()) + { + cdevStreamNode * node = activeOut.dequeue(); + + while(dataXfrLen<4 && retries=0) + { + parm = htonl(node->getLen()); + retval = send(((char *)&parm)+dataXfrLen, 4-dataXfrLen); + if(retval>=0) + { + retries = retval?0:retries+1; + dataXfrLen += retval; + totalSent += retval; + } + } + + while(dataXfrLen>=4 && dataXfrLengetLen()+4 && retries=0) + { + retval = send(node->getBuf()+(dataXfrLen-4), node->getLen()-(dataXfrLen-4)); + if(retval>=0) + { + retries = retval?0:retries+1; + dataXfrLen += retval; + totalSent += retval; + } + } + + if(dataXfrLengetLen()+4) activeOut.poke(node); + else { + if(deleteFlag) delete node; + dataXfrLen = 0; + } + } + + parm = 1; + setOption(IPPROTO_TCP, TCP_NODELAY, &parm, sizeof(parm)); + + #ifndef WIN32 + signal(SIGPIPE, oldSig); + #endif + + return retval>=0?totalSent:-1; + } + + +// ***************************************************************************** +// * cdevBufferedSocket::receive : +// * This method will attempt to receive as many packets as immediately +// * possible from the socket into the waitingIn cdevStreamQueue. The +// * function will cease receiving when a complete transmission block +// * (multiple packets) have been received or when the sender has failed +// * to transmit data after a pre-specified number of retries. +// ***************************************************************************** +ssize_t cdevBufferedSocket::receive ( void ) + { + int totalRecv = 0; + int parm = 0; + int retval = 0; + int retries = 0; + size_t packetCnt = 0; + + while(headerRcvLen<12 && retries=0) + { + if((retval = recv(((char *)inboundHeader)+headerRcvLen, 12-headerRcvLen))==0) + { + int errCode = GetSocketErrno(); + + if(errCode!=EWOULDBLOCK && errCode!=EAGAIN) retval = -1; + else retries++; + } + else if(retval>=0) + { + retries = retval?0:retries+1; + headerRcvLen += retval; + totalRecv += retval; + } + if(headerRcvLen>=12) + { + inboundHeader[0] = ntohl(inboundHeader[0]); + inboundHeader[1] = ntohl(inboundHeader[1]); + inboundHeader[2] = ntohl(inboundHeader[2]); + + if(inboundHeader[0]!=magicNumber) retval=-1; + } + } + + while(headerRcvLen>=12 && retries=0 && + inboundHeader[1]>0 && inboundHeader[2]>0) + { + while(dataRcvLen<4 && retries=0) + { + if((retval = recv(((char *)&subPacketLen)+dataRcvLen, 4-dataRcvLen))==0) + { + int errCode = GetSocketErrno(); + + if(errCode!=EWOULDBLOCK && errCode!=EAGAIN) retval = -1; + else retries++; + } + else if(retval>0) + { + retries = 0; + dataRcvLen += retval; + totalRecv += retval; + inboundHeader[1]-=retval; + } + if(dataRcvLen>=4) + { + subPacketLen = ntohl(subPacketLen); + rcvNode = nodeFactory->newNode(subPacketLen); + memset(rcvNode->getBuf(), rcvNode->getLen(), 0); + } + } + + while(dataRcvLen>=4 && dataRcvLengetLen()+4 && retries=0) + { + if((retval = recv(rcvNode->getBuf()+(dataRcvLen-4), rcvNode->getLen()-(dataRcvLen-4)))==0) + { + int errCode = GetSocketErrno(); + + if(errCode!=EWOULDBLOCK && errCode!=EAGAIN) retval = -1; + else retries++; + } + else if(retval>=0) + { + retries = 0; + dataRcvLen += retval; + totalRecv += retval; + inboundHeader[1]-=retval; + } + if(dataRcvLen>=(rcvNode->getLen()+4)) + { + waitingIn.enqueue(rcvNode); + rcvNode = NULL; + dataRcvLen = 0; + subPacketLen = 0; + inboundHeader[2]--; + } + } + if(inboundHeader[1]<=0 || inboundHeader[2]<=0) + { + if(rcvNode) // Only received a partial packet on final entry + { + delete rcvNode; + rcvNode = NULL; + retval = -1; + } + headerRcvLen = 0; + dataRcvLen = 0; + inboundHeader[0]=(inboundHeader[1]=(inboundHeader[2]=0)); + } + } + return retval>=0?totalRecv:-1; + } + +// ***************************************************************************** +// * cdevBufferedSocket::getBlockingSemantics : +// * Identifies the cdevBufferedSocket object as a NON-BLOCKING entity. +// ***************************************************************************** +int cdevBufferedSocket::getBlockingSemantics ( void ) const + { + return O_NONBLOCK; + } + +// ***************************************************************************** +// * cdevBufferedSocket::getRcvBufferSize : +// * This method is called during the configureHandle method to obtain the +// * size of the receive buffer that will be used by the socket. This class +// * returns the value 56000 - telling the cdevSocketStream to set the +// * receive buffer size to 56 kilobytes. +// ***************************************************************************** +int cdevBufferedSocket::getRcvBufferSize ( void ) const + { + return 56000; + } + + +// ***************************************************************************** +// * cdevBufferedSocket::getSndBufferSize : +// * This method is called during the configureHandle method to obtain the +// * size of the send buffer that will be used by the socket. This class +// * returns the value 56000 - telling the cdevSocketStream to set the +// * send buffer size to 56 kilobytes. +// ***************************************************************************** +int cdevBufferedSocket::getSndBufferSize ( void ) const + { + return 56000; + } diff --git a/extensions/cdevGenericServer/cdevReactor/cdevBufferedSocket.h b/extensions/cdevGenericServer/cdevReactor/cdevBufferedSocket.h new file mode 100755 index 0000000..3cc34b3 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevBufferedSocket.h @@ -0,0 +1,114 @@ +#ifndef _CDEV_BUFFERED_SOCKET_H_ +#define _CDEV_BUFFERED_SOCKET_H_ + +#include "cdevSocketConnector.h" +#include "cdevStreamQueue.h" + +class cdevBufferedSocket : public cdevSocketConnector, public cdevNodeFactory +{ +private: + cdevNodeFactory * nodeFactory; + + int magicNumber; + int deleteFlag; + + cdevStreamQueue activeOut; + cdevStreamQueue waitingOut; + int outboundHeader[3]; + size_t headerXfrLen; + size_t dataXfrLen; + + cdevStreamQueue waitingIn; + cdevStreamNode * rcvNode; + int inboundHeader[3]; + size_t headerRcvLen; + size_t dataRcvLen; + size_t subPacketLen; + + static void sigPipeHandler (int); + +public: + enum {RETRYCNT = 1000 }; + + inline cdevBufferedSocket ( int MagicNumber=0, int deleteNodes = 1, cdevNodeFactory * factory=NULL ); + + inline int outboundReady ( void ); + inline int inboundReady ( void ); + inline void enqueueOutbound ( cdevStreamNode * node ); + inline cdevStreamNode * dequeueInbound ( void ); + + cdevStreamNode * newNode ( ssize_t size ); + ssize_t transmit ( void ); + ssize_t receive ( void ); + + int getBlockingSemantics ( void ) const; + int getRcvBufferSize ( void ) const; + int getSndBufferSize ( void ) const; +}; + + +// ***************************************************************************** +// * cdevBufferedSocket::cdevBufferedSocket : +// * This is the constructor for the cdevBufferedSocket, it will initialize +// * all internal variables and sub-classes. +// ***************************************************************************** +inline cdevBufferedSocket::cdevBufferedSocket ( int MagicNumber, int deleteNodes, cdevNodeFactory * factory ) + : nodeFactory(factory), + magicNumber(MagicNumber), + deleteFlag (deleteNodes), + activeOut(deleteNodes), + waitingOut(deleteNodes), + headerXfrLen(0), + dataXfrLen(0), + waitingIn(), + rcvNode(NULL), + headerRcvLen(0), + dataRcvLen(0), + subPacketLen(0) + { + if(nodeFactory==NULL) nodeFactory=this; + } + + +// ***************************************************************************** +// * cdevBufferedSocket::outboundReady : +// * This method returns an integer value indicating that outbound data is +// * ready for transmission. +// ***************************************************************************** +inline int cdevBufferedSocket::outboundReady ( void ) + { + return !(activeOut.isEmpty() && waitingOut.isEmpty()); + } + +// ***************************************************************************** +// * cdevBufferedSocket::inboundReady : +// * This method returns a flag indicating that inbound data is ready to be +// * dequeued and processed. +// ***************************************************************************** +inline int cdevBufferedSocket::inboundReady ( void ) + { + return !(waitingIn.isEmpty() && headerRcvLen==0); + } + +// ***************************************************************************** +// * cdevBufferedSocket::enqueueOutbound : +// * This method places the user defined cdevStreamNode pointer into the +// * waitingOut object. +// ***************************************************************************** +inline void cdevBufferedSocket::enqueueOutbound ( cdevStreamNode * node ) + { + waitingOut.enqueue(node); + } + +// ***************************************************************************** +// * cdevBufferedSocket::dequeueInbound : +// * This method dequeues the next available cdevStreamNode object from the +// * waitingIn object. +// ***************************************************************************** +inline cdevStreamNode * cdevBufferedSocket::dequeueInbound ( void ) + { + return waitingIn.dequeue(); + } + + +#endif /* _CDEV_BUFFERED_SOCKET_H_ */ diff --git a/extensions/cdevGenericServer/cdevReactor/cdevEventHandler.cc b/extensions/cdevGenericServer/cdevReactor/cdevEventHandler.cc new file mode 100755 index 0000000..08f1251 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevEventHandler.cc @@ -0,0 +1,96 @@ +#include "cdevReactor.h" +#include "cdevEventHandler.h" +#include + +cdevEventHandler::cdevEventHandler ( void ) + : mask(0), + next(NULL), + timeoutRate(0, 0), + nextTimeout(0, 0), + reactor(NULL) + { + } + + +cdevEventHandler::~cdevEventHandler ( void ) + { + if(reactor!=NULL) reactor->extractHandler(this); + handleClose(); + } + +void cdevEventHandler::setHandle ( int ) + { + } + +int cdevEventHandler::getHandle ( void ) const + { + return -1; + } + +void cdevEventHandler::setReactor (cdevReactor * r) + { + reactor = r; + } + + +cdevEventHandler * cdevEventHandler::getNext (void ) + { + return next; + } + + +void cdevEventHandler::setNext (cdevEventHandler * n) + { + next = n; + } + + +int cdevEventHandler::getMask ( void ) + { + return mask; + } + + +cdevReactor * cdevEventHandler::getReactor ( void ) + { + return reactor; + } + + +cdevTime & cdevEventHandler::getTimeoutRate ( void ) + { + return timeoutRate; + } + +cdevTime & cdevEventHandler::getNextTimeout ( void ) + { + return nextTimeout; + } + + +void cdevEventHandler::setMask ( unsigned Mask ) + { + mask = (Mask&(READ_MASK|WRITE_MASK|EXCEPT_MASK|DONT_CALL)); + } + + +void cdevEventHandler::setTimeoutRate ( cdevTime time ) + { + timeoutRate = time; + resetTimer(); + } + + +void cdevEventHandler::resetTimer ( void ) + { + nextTimeout.setTime(); + nextTimeout = nextTimeout+getTimeoutRate(); + } + +int cdevEventHandler::handleInput ( void ) { return 0; } +int cdevEventHandler::handleOutput ( void ) { return 0; } +int cdevEventHandler::handleExcept ( void ) { return 0; } +int cdevEventHandler::handleTimeout ( void ) { return 0; } +int cdevEventHandler::handleSignal ( void ) { return -1; } +int cdevEventHandler::handleClose ( void ) { return 0; } + diff --git a/extensions/cdevGenericServer/cdevReactor/cdevEventHandler.h b/extensions/cdevGenericServer/cdevReactor/cdevEventHandler.h new file mode 100755 index 0000000..7f4f05c --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevEventHandler.h @@ -0,0 +1,54 @@ +#ifndef _CDEV_EVENT_HANDLER_H_ +#define _CDEV_EVENT_HANDLER_H_ 1 + +#include "cdevTime.h" + +class CDEV_REACTOR_API cdevEventHandler +{ +friend class cdevReactor; + +public: + enum { + READ_MASK = 0x01, + EXCEPT_MASK = 0x02, + WRITE_MASK = 0x04, + DONT_CALL = 0x100 + } REACTOR_MASK; + +private: + void setReactor (cdevReactor * r); + cdevEventHandler * getNext (void ); + void setNext (cdevEventHandler * n); + cdevTime & getNextTimeout (void); + +protected: + cdevEventHandler * next; + cdevTime nextTimeout; + cdevReactor * reactor; + cdevTime timeoutRate; + int mask; + +public: + cdevEventHandler ( void ); + virtual ~cdevEventHandler ( void ); + + virtual void setMask ( unsigned Mask ); + virtual void setHandle ( int handle ); + virtual int getHandle ( void ) const; + virtual int getMask ( void ); + virtual cdevReactor * getReactor ( void ); + + virtual cdevTime & getTimeoutRate ( void ); + virtual void setTimeoutRate ( cdevTime time ); + virtual void resetTimer ( void ); + + virtual int handleInput ( void ); + virtual int handleOutput ( void ); + virtual int handleExcept ( void ); + virtual int handleTimeout ( void ); + virtual int handleSignal ( void ); + virtual int handleClose ( void ); + +}; + +#endif diff --git a/extensions/cdevGenericServer/cdevReactor/cdevHandleSet.cc b/extensions/cdevGenericServer/cdevReactor/cdevHandleSet.cc new file mode 100644 index 0000000..69c0e40 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevHandleSet.cc @@ -0,0 +1,304 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// FD_Set Wrapper Based on ACE +// + +#include "cdevHandleSet.h" + +#ifndef __VMS + #ifndef __linux + extern "C" bzero (char *, int); + #endif +#else + extern "C" bzero (char *, unsigned int); +#endif + +#if defined(__VMS) && defined(_TGV_MULTINET) + // ********************************************************************* + // * Unfortunately when you use TGV Multinet, the bit offsets in the + // * file * descriptor bitmasks used by select() cannot be found by + // * simply using the value of the file descriptor. Fortunately, there + // * is a simple relationship between the file descriptor value and the + // * desired bit offset. + // * (These macros are required because this file accesses the file + // * descriptor bitmasks directly, without using the FD_SET(), FD_CLR(), + // * FD_ISSSET() macros). + // ********************************************************************* + #define FD_TO_BIT_OFFSET( fd ) ((fd)/CHANNELSIZE) + #define FD_FROM_BIT_OFFSET( ibit ) ((ibit)*CHANNELSIZE) +#else + // ********************************************************************* + // * Under most operating systems the file descriptor value and the + // * associated bit offset are one and the same. + // ********************************************************************* + #define FD_TO_BIT_OFFSET( fd ) (fd) + #define FD_FROM_BIT_OFFSET( ibit ) (ibit) +#endif + +#ifdef CDEV_HAS_UNDERSCORE_FDBITS +#define fds_bits __fds_bits +#endif + +inline int BIT_ENABLED (unsigned long word, int bit = 1) { return (word & bit) != 0; } +inline int BIT_DISABLED (unsigned long word, int bit = 1) { return (word & bit) == 0; } +inline void SET_BIT (unsigned long &word, int bit) { word |= bit; } +inline void CLR_BIT (unsigned long &word, int bit) { word &= ~bit; } + +const char cdevHandleSet::nbits_[256] = + { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, + }; + +// ***************************************************************************** +// * Counts the number of bits enabled in N. Uses a table lookup to speed up +// * the count. +// ***************************************************************************** + +int cdevHandleSet::count_bits (unsigned long n) const + { + return (cdevHandleSet::nbits_[n & 0xff] + cdevHandleSet::nbits_[(n >> 8) & 0xff] + + cdevHandleSet::nbits_[(n >> 16) & 0xff] + cdevHandleSet::nbits_[n >> 24]); + } + +void cdevHandleSetIterator::operator++ (void) + { + #ifdef _WIN32 + this->index_++; + #else + this->val_ = (this->val_ >> 1) & cdevHandleSet::MSB_MASK; + this->num_++; + + if (this->val_ == 0) + { + for (this->index_++; + this->index_ < cdevHandleSet::NUM_WORDS && fds_.mask_.fds_bits[this->index_] == 0; + this->index_++); + + if (this->index_ == cdevHandleSet::NUM_WORDS) + { + this->num_ = fds_.max_handle_ + 1; + return; + } + else + { + this->val_ = fds_.mask_.fds_bits[this->index_]; + this->num_ = this->index_ * cdevHandleSet::WORD_SIZE; + } + } + + for (; BIT_DISABLED (this->val_); this->num_++) + this->val_ = (this->val_ >> 1) & cdevHandleSet::MSB_MASK; + #endif + } + +cdevHandleSetIterator::cdevHandleSetIterator (cdevHandleSet &f) + : fds_ (f), index_ (0), num_ (f.size_ == 0 ? f.max_handle_ + 1 : 0) + { + #ifndef _WIN32 + for (; fds_.mask_.fds_bits[this->index_] == 0; this->index_++) + this->num_ += cdevHandleSet::WORD_SIZE; + + for (this->val_ = this->fds_.mask_.fds_bits[this->index_]; + (BIT_DISABLED (this->val_)) && this->num_ < cdevHandleSet::MAX_SIZE; + this->num_++) + this->val_ = (this->val_ >> 1) & cdevHandleSet::MSB_MASK; + #endif + } + +// ***************************************************************************** +// * Synchronize the underlying FD_SET with the MAX_FD and the SIZE. +// ***************************************************************************** +void cdevHandleSet::sync (int max) + { + #ifndef _WIN32 + this->size_ = 0; + + for (int i = max / cdevHandleSet::WORD_SIZE; i >= 0; i--) + this->size_ += count_bits (this->mask_.fds_bits[i]); + + this->set_max (max); + #endif + } + +// ***************************************************************************** +// * Resets the MAX_FD after a clear of the original MAX_FD. +// ***************************************************************************** +void cdevHandleSet::set_max (int current_max) + { + #ifndef _WIN32 + int i = 0; + + if (this->size_ == 0) + this->max_handle_ = -1; + else + { + for (i = current_max / cdevHandleSet::WORD_SIZE; + this->mask_.fds_bits[i] == 0; + i--) + ; + + this->max_handle_ = i * cdevHandleSet::WORD_SIZE; + for (fd_mask val = this->mask_.fds_bits[i]; + (val & ~1) != 0; + val = (val >> 1) & cdevHandleSet::MSB_MASK) + this->max_handle_++; + } + #endif + } + +// ***************************************************************************** +// * Debugging method that prints out the underlying mask. +// ***************************************************************************** +int cdevHandleSet::asciiDump (FILE * fp) + { + fprintf(fp, "[ "); + for (int i = 0; i < this->max_handle_ + 1; i++) + if (this->is_set (i)) + fprintf(fp," %d ", i); + + fprintf(fp, " ]"); + return this->size_; + } + +void cdevHandleSet::reset (void) + { + this->max_handle_ = -1; + this->size_ = 0; + FD_ZERO (&this->mask_); + } + +// ***************************************************************************** +// * Constructor, initializes the bitmask to all 0s. +// ***************************************************************************** +cdevHandleSet::cdevHandleSet (void) + { + this->reset (); + } + +cdevHandleSet::cdevHandleSet (const fd_set &fd_mask): size_ (0) + { + memcpy ((void *) &this->mask_, (void *) &fd_mask, sizeof this->mask_); + // sync is empty for WIN32 + this->sync (FD_SETSIZE); + } + +// ***************************************************************************** +// * Returns the number of the large bit. +// ***************************************************************************** +int cdevHandleSet::max_set (void) const + { + return this->max_handle_; + } + +// ***************************************************************************** +// * Checks whether FD is enabled. +// ***************************************************************************** +int cdevHandleSet::is_set (int fd) const + { + #ifdef _WIN32 + return FD_ISSET ((SOCKET)fd, &this->mask_); + #else + return FD_ISSET (fd, &this->mask_); + #endif + } + +// ***************************************************************************** +// * Enables the FD. +// ***************************************************************************** +void cdevHandleSet::set_bit (int fd) + { + if (!this->is_set (fd)) + { + #ifdef _WIN32 + FD_SET ((SOCKET)fd, &this->mask_); + #else + FD_SET (fd, &this->mask_); + this->size_++; + // ***************************************************** + // * again VMS system has different idea + // ***************************************************** + #if defined(__VMS) && defined(_TGV_MULTINET) + if (FD_TO_BIT_OFFSET(fd) > this->max_handle_) + this->max_handle_ = FD_TO_BIT_OFFSET(fd); + #else + if (fd > this->max_handle_) + this->max_handle_ = fd; + #endif + #endif + } + } + +// ***************************************************************************** +// * Disables the FD. +// ***************************************************************************** +void cdevHandleSet::clr_bit (int fd) + { + if (this->is_set (fd)) + { + #ifdef _WIN32 + FD_CLR ((SOCKET)fd, &this->mask_); + #else + FD_CLR (fd, &this->mask_); + this->size_--; + + #if defined(__VMS) && defined(_TGV_MULTINET) + if (FD_TO_BIT_OFFSET(fd) == this->max_handle_) + this->set_max (this->max_handle_); + #else + if (fd == this->max_handle_) + this->set_max (this->max_handle_); + #endif + #endif + } + } + +// ***************************************************************************** +// * Returns a count of the number of enabled bits. +// ***************************************************************************** +int cdevHandleSet::num_set (void) const + { + #ifdef _WIN32 + return this->mask_.fd_count; + #else + return this->size_; + #endif + } + +int cdevHandleSetIterator::operator () (void) + { + #ifdef _WIN32 + return this->index_ < this->fds_.mask_.fd_count + ? fds_.mask_.fd_array[this->index_] : -1; + #else + #if defined(__VMS) && defined(_TGV_MULTINET) + return FD_FROM_BIT_OFFSET(this->num_ <= this->fds_.max_handle_ + ? this->num_ :-1); + #else + return this->num_ <= this->fds_.max_handle_ + ? this->num_ : -1; + #endif + #endif + } diff --git a/extensions/cdevGenericServer/cdevReactor/cdevHandleSet.h b/extensions/cdevGenericServer/cdevReactor/cdevHandleSet.h new file mode 100644 index 0000000..3f493da --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevHandleSet.h @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// File Descriptor Mask Class (Based On ACE Handler_Set) + +#ifndef _CDEV_HANDLE_SET_H_ +#define _CDEV_HANDLE_SET_H_ + +#include +#include +#include "cdevPlatforms.h" + +class CDEV_REACTOR_API cdevHandleSet +{ +friend class cdevHandleSetIterator; +friend class cdevReactor; + +public: + cdevHandleSet (void); + cdevHandleSet (const fd_set &mask); + + void reset (void); + int is_set (int) const; + void set_bit (int); + void clr_bit (int); + int num_set (void) const; + int max_set (void) const; + int asciiDump (FILE * fp = stdout); + void sync (int max = FD_SETSIZE); + + operator fd_set *( void ) { return &mask_; } + +private: + int size_; + int max_handle_; + fd_set mask_; + + enum { + #ifdef _WIN32 + MAX_SIZE = FD_SETSIZE, + #else + MAX_SIZE = NOFILE, + WORD_SIZE = NFDBITS, + NUM_WORDS = howmany (NOFILE, NFDBITS), + #ifdef __DECCXX + MSB_MASK = ~(1U << (NFDBITS - 1)) + #elif defined(CDEV_HAS_64BIT_LONGS) + MSB_MASK = ~(1UL << (NFDBITS - 1)) + #else + MSB_MASK = ~(1 << (NFDBITS - 1)) + #endif + #endif + }; + + int count_bits (unsigned long n) const; + void set_max (int max); + + static const char nbits_[256]; +}; + +class CDEV_REACTOR_API cdevHandleSetIterator +{ +public: + cdevHandleSetIterator (cdevHandleSet &); + int operator ()(void); + void operator++ (void); + +private: + cdevHandleSet &fds_; + int num_; + + #ifdef _WIN32 + unsigned int index_; + #else + int index_; + fd_mask val_; + #endif +}; + +#endif /* _CDEV_HANDLE_SET_H_ */ diff --git a/extensions/cdevGenericServer/cdevReactor/cdevReactor.cc b/extensions/cdevGenericServer/cdevReactor/cdevReactor.cc new file mode 100755 index 0000000..c69f55f --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevReactor.cc @@ -0,0 +1,585 @@ +#include +#include +#include "cdevReactor.h" + +// ***************************************************************************** +// * This is the number of times that InitializeNetwork was called to perform +// * network initialization. The InitializeNetwork and corresponding +// * TerminateNetwork methods are wrappers to provide support for WIN32 +// * WSAStartup and WSACleanup methods. They perform no actiual function on +// * UNIX platforms. +// ***************************************************************************** +int cdevReactor::netInitCount = 0; + +// ***************************************************************************** +// * cdevReactor::cdevReactor : +// * This is the constructor for the cdevReactor class. It takes no +// * arguments. It will set maxEntries to the value of the MAX_SIZE +// * variable and the size variable (the highest fd installed) will be set +// * to zero. +// * +// * The method will allocate space in the handlers array for the +// * cdevEventHandlers that will be installed during operation. The +// * read_set, write_set and except_set masks will be cleared. These masks +// * will be populated later as file descriptors are added to the +// * cdevReactor. +// ***************************************************************************** +cdevReactor::cdevReactor ( void ) + : maxEntries(cdevHandleSet::MAX_SIZE), + size (0), + handlers (NULL), + timers (NULL) + { + if(!netInitCount) + { + if(InitializeNetwork()==0) netInitCount++; + } + else netInitCount++; + + handlers = (cdevEventHandler **)malloc((maxEntries+1)*sizeof(cdevEventHandler *)); + memset(handlers, 0, sizeof(cdevEventHandler *)*(maxEntries+1)); + read_set.reset(); + write_set.reset(); + except_set.reset(); + } + + +// ***************************************************************************** +// * cdevReactor::~cdevReactor : +// * This is the destructor for the cdevReactor class. It wil first remove +// * all of the timer cdevEventHandlers from the timer array, it will then +// * remove all of the file-descriptor based cdevEventHandlers from the +// * handlers array. It will finish by deleteing the handlers array that +// * was allocated in the constructor. +// ***************************************************************************** +cdevReactor::~cdevReactor ( void ) + { + if(netInitCount && (-netInitCount)==0) TerminateNetwork(); + + while(timers!=NULL) removeHandler(timers); + for(int i=0; i<=maxEntries; i++) + { + if(handlers[i]!=NULL) removeHandler(handlers[i]); + } + delete handlers; + } + + +// ***************************************************************************** +// * cdevReactor::calculateMask : +// * This method will walk through the handlers array and setup the read_set, +// * write_set and except_set masks. +// ***************************************************************************** +void cdevReactor::calculateMask ( void ) + { + int i; + read_set.reset(); + write_set.reset(); + except_set.reset(); + size = 0; + + for(i=0; i<=maxEntries; i++) + { + unsigned mask; + if(handlers[i]!=NULL) + { + mask = handlers[i]->getMask(); + if(!(mask&cdevEventHandler::DONT_CALL)) + { + if(mask&cdevEventHandler::READ_MASK) + { + read_set.set_bit(i); + size = i+1; + } + if(mask&cdevEventHandler::WRITE_MASK) + { + write_set.set_bit(i); + size = i+1; + } + if(mask&cdevEventHandler::EXCEPT_MASK) + { + except_set.set_bit(i); + size = i+1; + } + } + } + } + } + + + +// ***************************************************************************** +// * cdevReactor::calculateTimeout : +// * This method will walk through the timers and determine the duration of +// * time that the cdevReactor should wait for events on the file +// * descriptors before automatically terminating. +// ***************************************************************************** +int cdevReactor::calculateTimeout ( cdevTime defaultPeriod, struct timeval &timeout ) + { + if(defaultPeriod==cdevTime(0,0)) timeout.tv_sec=(timeout.tv_usec=0); + else { + cdevTime now; + cdevTime target; + cdevEventHandler * timer; + + if(defaultPeriodnow; timer=timer->getNext()) + { + cdevTime nextTimeout = timer->getNextTimeout(); + + if(!(timer->getMask()&cdevEventHandler::DONT_CALL) && + (double)nextTimeout > 0.0) + { + if(nextTimeouthandleSignal()<0) + { + removeHandler(handlers[i]); + eventCnt++; + } + } + read_set.clr_bit(i); + } + } + } + return eventCnt; + } + +// ***************************************************************************** +// * cdevReactor::registerHandler : +// * This method is called to register a file-descriptor based +// * cdevEventHandler with the reactor. It will first check the validity +// * of the handler and its file descriptor. It will then determine if +// * another handler already occupies the position associated with the +// * specified handle. +// * +// * If the handler is valid, it will install it in the handlers array and +// * will add it to the read_set, write_set and except_set masks as +// * required. The size variable will be incremented if the new handler +// * has the highest file-descriptor in the array. +// ***************************************************************************** +int cdevReactor::registerHandler ( cdevEventHandler * handler, unsigned mask ) + { + int fd = -1; + REACTOR_RESULT result = SUCCESS; + + if(handler == NULL) + { + result = INVALID_HANDLER; + } + else if(handler->getReactor()!=NULL && handler->getReactor()!=this) + { + result = UNKNOWN_HANDLER; + } + else if((fd = handler->getHandle())<=0) + { + result = INVALID_HANDLE; + } + else if(fdgetHandle()]!=NULL) + { + result = HANDLE_EXISTS; + } + else { + if(fd>=maxEntries) + { + int oldMaxEntries = maxEntries; + maxEntries = fd+1; + handlers = (cdevEventHandler **)realloc(handlers, (maxEntries+1) * sizeof(cdevEventHandler *)); + memset(&handlers[oldMaxEntries], 0, sizeof(cdevEventHandler *)*((maxEntries+1)-oldMaxEntries)); + } + handler->setReactor(this); + handler->setMask (mask); + handlers[fd] = handler; + } + + return (int)result; + } + + +// ***************************************************************************** +// * cdevReactor::removeHandler : +// * This method allows the caller to remove an cdevEventHandler from the +// * cdevReactor and delete it. The method will call the extractHandler +// * method to remove the cdevEventHandler from the cdevReactor after which +// * the handler will be deleted. +// ***************************************************************************** +int cdevReactor::removeHandler ( cdevEventHandler * handler ) + { + REACTOR_RESULT result = INVALID_HANDLER; + if(handler!=NULL) + { + extractHandler(handler); + delete handler; + result = SUCCESS; + } + return (int)result; + } + +// ***************************************************************************** +// * cdevReactor::removeHandler : +// * This method will remove the specified handler using the file descriptor +// * provided by the caller. +// ***************************************************************************** +int cdevReactor::removeHandler ( int fd ) + { + REACTOR_RESULT result = SUCCESS; + + if(fd>0 && fd<=maxEntries) + { + result = (REACTOR_RESULT)removeHandler(handlers[fd]); + } + else result = INVALID_HANDLE; + + return (int) result; + } + +// ***************************************************************************** +// * cdevReactor::extractHandler : +// * This method will remove the specified cdevEventHandler from the +// * cdevReactor, however, it will not delete the cdevEventHandler when +// * finished. +// ***************************************************************************** +int cdevReactor::extractHandler ( cdevEventHandler * handler ) + { + int fd = -1; + REACTOR_RESULT result = UNKNOWN_HANDLER; + + if(handler == NULL) result = INVALID_HANDLER; + else { + cdevEventHandler * currTimer = timers; + cdevEventHandler * prevTimer = NULL; + + while(currTimer!=NULL && currTimer!=handler) + { + prevTimer = currTimer; + currTimer = prevTimer->getNext(); + } + + if(currTimer) + { + if(prevTimer) prevTimer->setNext(currTimer->getNext()); + else timers = currTimer->getNext(); + result = SUCCESS; + } + + if((fd = handler->getHandle())>=0 && + fd<=maxEntries && + handlers[fd]==handler) + { + handlers[fd] = NULL; + result = SUCCESS; + } + else for(fd=0; fd<=maxEntries; fd++) + { + if(handlers[fd]==handler) + { + handlers[fd] = NULL; + result = SUCCESS; + } + } + + if(result==SUCCESS) + { + handler->setMask(0); + handler->setReactor(NULL); + } + } + + return (int)result; + } + + +// ***************************************************************************** +// * cdevReactor::getHandler : +// * This method allows the caller to retrieve the cdevEventHandler +// * associated with a specific file descriptor. +// ***************************************************************************** +int cdevReactor::getHandler ( int fd, cdevEventHandler * & handler ) + { + REACTOR_RESULT result = SUCCESS; + + handler = NULL; + + if(fd<=0 || fd>maxEntries) result = INVALID_HANDLE; + else if((handler = handlers[fd])==NULL) result = INVALID_HANDLE; + + return (int) result; + } + +// ***************************************************************************** +// * cdevReactor::registerTimer : +// * This method will install a timer cdevEventHandler in the timers array. +// * The handleTimeout method of this class will be called each time the +// * timer expires. The timer's handleTimeout method will be called +// * immediately, and then the timer will be set to expire at the next +// * time period. +// ***************************************************************************** +int cdevReactor::registerTimer ( cdevEventHandler * timer ) + { + REACTOR_RESULT result = SUCCESS; + + if(timer==NULL) + { + result = INVALID_HANDLER; + } + else if(timer->getReactor()!=NULL && timer->getReactor()!=this) + { + result = UNKNOWN_HANDLER; + } + else if((double)timer->getTimeoutRate()<=0.0) + { + result = INVALID_TIMEOUT; + } + else { + timer->setReactor(this); + timer->resetTimer(); + timer->setNext(timers); + timers = timer; + } + + return (int)result; + } + +// ***************************************************************************** +// * cdevReactor::cancelTimer : +// * This method will remove the timer from the array of timers that are +// * being serviced by the reactor, however, it will NOT delete the +// * cdevEventHandler. Additionally, if the handler is also being used +// * for file-descriptor based operations - it will be not be removed from +// * that array. +// * +// * The user is responsible for deleteing the cdevEventHandler if it will +// * no longer be needed. +// ***************************************************************************** +int cdevReactor::cancelTimer ( cdevEventHandler * timer ) + { + REACTOR_RESULT result = SUCCESS; + + if(timer==NULL) result = INVALID_HANDLER; + else + { + cdevEventHandler * currTimer = timers; + cdevEventHandler * prevTimer = NULL; + + while(currTimer!=NULL && currTimer!=timer) + { + prevTimer = currTimer; + currTimer = prevTimer->getNext(); + } + + if(currTimer) + { + if(prevTimer) prevTimer->setNext(currTimer->getNext()); + else timers = currTimer->getNext(); + currTimer->setNext(NULL); + } + else result = UNKNOWN_HANDLER; + } + + return (int)result; + } + + +// ***************************************************************************** +// * cdevReactor::handleFileEvent : +// * This method will process the events that have occurred on a single +// * file descriptor. The caller must provide two arguments... +// * +// * fd_set * fds : The fd_set to be checked +// * REACTOR_EVENT event : The type of event being processed... +// * INPUT, OUTPUT, EXCEPTION, or SIGNAL. +// * +// * This method will return the number of events that have been processed +// * to completion. Note that if a cdevEventHandler returns a value greater +// * than 0, it will be called again after all other ready file descriptors +// * have been called - therefore, its occurance will not be included in the +// * number of events returned by this method. +// ***************************************************************************** +int cdevReactor::handleFileEvent ( cdevHandleSet * fds, REACTOR_EVENT event) + { + int result = 0; + int eventCnt = 0; + int i; + + for(i=0; i<=size; i++) + { + if(fds->is_set(i)) + { + if(handlers[i]) + { + if(event==INPUT) result = handlers[i]->handleInput(); + else if(event==OUTPUT) result = handlers[i]->handleOutput(); + else if(event==EXCEPTION) result = handlers[i]->handleExcept(); + else if(event==SIGNAL) result = handlers[i]->handleSignal(); + + if(result<=0) + { + if(result<0) removeHandler(handlers[i]); + eventCnt++; + fds->clr_bit(i); + } + } + else eventCnt++; + } + } + + return eventCnt; + } + +// ***************************************************************************** +// * cdevReactor::handleEvents : +// * This method is called to allow the cdevReactor to wait for events to +// * occur on the cdevEventHandler objects. This method will process events +// * until the specified time period has expired - if a negative time period +// * (or no time period) has been specified, then it will process messages +// * until the next event occurs. +// * +// * The flags parameter was added to allow the caller to specify either +// * UNTIL_TIMEOUT or UNTIL_EVENT. If the caller specifies UNTIL_TIMEOUT, +// * the cdevReactor will continue to handle events until the time period +// * has expired. If the caller specifies UNTIL_EVENT, the cdevReactor will +// * return after the first SOCKET-BASED EVENT occurs or after the time +// * expires, whichever comes first. +// * +// * Note: If the cdevEventHandler may return a -1, 0, or 1. These return +// * codes will have the following effect. +// * +// * -1 : The cdevEventHandler will be removed from the cdevReactor +// * and deleted. +// * 0 : The bit associated with the cdevEventHandler will be +// * cleared and processing will continue. +// * 1 : The bit associated with the cdevEventHandler will not be +// * cleared and it will be called to process more data after +// * after all of the subsequent cdevEventHandlers have been +// * called - this allows the cdevEventHandler in a lengthy +// * process to yeild time back for processing other events. +// ***************************************************************************** +int cdevReactor::handleEvents ( cdevTime period, int flags ) + { + int result = 0; + int finished = 0; + cdevTime startTime, currTime; + struct timeval timeout; + + startTime.setTime(); + + do + { + int i; + + calculateMask (); + calculateTimeout(period, timeout); + + result=cdevSelect(size, read_set, write_set, except_set, &timeout); + + if(result<0) + { + finished = 1; + checkHandlers(); + } + else { + if(result>0) + { + int cnt = 0; + + while(cnt0) finished = 1; + } + + if(timers!=NULL) + { + cdevEventHandler * timer=timers; + + currTime.setTime(); + + while(timer!=NULL) + { + cdevTime nextTimeout = timer->getNextTimeout(); + + if((timer->getMask()&cdevEventHandler::DONT_CALL)==0 && + (double)nextTimeout>0.0 && nextTimeout<=currTime) + { + if(timer->handleTimeout()<0) + { + cdevEventHandler *temp = timer->getNext(); + removeHandler(timer); + timer = temp; + } + else + { + timer->resetTimer(); + timer = timer->getNext(); + } + currTime.setTime(); + } + else timer = timer->getNext(); + } + } + } + + currTime.setTime(); + period = period-(currTime-startTime); + } while(!finished && period>cdevTime(0,0)); + + return result; + } diff --git a/extensions/cdevGenericServer/cdevReactor/cdevReactor.h b/extensions/cdevGenericServer/cdevReactor/cdevReactor.h new file mode 100755 index 0000000..ffe8dd5 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevReactor.h @@ -0,0 +1,65 @@ +#ifndef _CDEV_REACTOR_H_ +#define _CDEV_REACTOR_H_ 1 + +#include "cdevTime.h" +#include "cdevHandleSet.h" +#include "cdevEventHandler.h" + +class CDEV_REACTOR_API cdevReactor +{ +public: +typedef enum { + INPUT = 0, + OUTPUT = 1, + EXCEPTION = 2, + SIGNAL = 3 + } REACTOR_EVENT; + +typedef enum { + REACTOR_ERROR = -1, + SUCCESS = 0, + INVALID_HANDLE = 1, + INVALID_HANDLER = 2, + HANDLE_EXISTS = 3, + UNKNOWN_HANDLER = 4, + INVALID_TIMEOUT = 5 + } REACTOR_RESULT; + +typedef enum { + UNTIL_TIMEOUT = 0, + UNTIL_EVENT = 1 + } HANDLE_EVENT_FLAG; + +protected: + static int netInitCount; + + int maxEntries; + int size; + cdevHandleSet read_set; + cdevHandleSet write_set; + cdevHandleSet except_set; + cdevEventHandler ** handlers; + cdevEventHandler * timers; + +private: + void calculateMask ( void ); + int calculateTimeout ( cdevTime defaultPeriod, struct timeval &timeout ); + int handleFileEvent ( cdevHandleSet * fds, REACTOR_EVENT event); +public: + cdevReactor ( void ); + virtual ~cdevReactor ( void ); + + virtual int checkHandlers ( void ); + virtual int registerHandler ( cdevEventHandler * handler, unsigned mask ); + virtual int removeHandler ( cdevEventHandler * handler ); + virtual int removeHandler ( int fd ); + virtual int extractHandler ( cdevEventHandler * handler ); + virtual int getHandler ( int fd, cdevEventHandler * &handler ); + + virtual int registerTimer ( cdevEventHandler * timer ); + virtual int cancelTimer ( cdevEventHandler * timer ); + + virtual int handleEvents ( cdevTime period = -1.0, int flags = UNTIL_TIMEOUT ); +}; + +#endif diff --git a/extensions/cdevGenericServer/cdevReactor/cdevSocket.cc b/extensions/cdevGenericServer/cdevReactor/cdevSocket.cc new file mode 100644 index 0000000..5d5b057 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevSocket.cc @@ -0,0 +1,157 @@ +#include "cdevSocket.h" + +void cdevSocket::setHandle ( int fd ) + { + handle = fd; + } + + +int cdevSocket::getHandle ( void ) const + { + return handle; + } + + +int cdevSocket::open (int type, int protocol_family, int protocol) + { + setHandle(::socket(protocol_family, type, protocol)); + return getHandle(); + } + + +int cdevSocket::close (void) + { + int result = ::close(getHandle()); + setHandle(INVALID_HANDLE); + return result; + } + + +int cdevSocket::unsetFlags ( int flags ) + { + int retval = -1; + int fd = getHandle(); + + if(fd!=cdevSocket::INVALID_HANDLE) + { + #ifdef WIN32 + if(flags==O_NONBLOCK) + { + unsigned long val = 0; + retval = ::ioctlsocket(fd, FIONBIO, &val); + } + #else + int val; + if((val=::fcntl(fd, F_GETFL, 0)) != -1) + { + val &= ~flags; + retval = (::fcntl(fd, F_SETFL, val)!=-1)?0:1; + } + #endif + } + + return retval; + } + + +int cdevSocket::setFlags ( int flags ) + { + int retval = -1; + int fd = getHandle(); + + if(fd!=cdevSocket::INVALID_HANDLE) + { + #ifdef WIN32 + if(flags==O_NONBLOCK) + { + unsigned long val = 1; + retval = ::ioctlsocket(fd, FIONBIO, &val); + } + #else + int val; + if ((val=::fcntl(fd, F_GETFL, 0)) != -1) + { + val |= flags; + if(::fcntl(fd, F_SETFL, val) != -1) retval = 0; + } + #endif + } + + return retval; + } + + +int cdevSocket::getFlags ( void ) + { + int retval = -1; + int fd = getHandle(); + + #ifdef WIN32 + retval = 0; + #else + if(fd!=cdevSocket::INVALID_HANDLE) + { + retval=::fcntl(fd, F_GETFL, 0); + } + #endif + + return retval; + } + +int cdevSocket::setOption (int level, int option, void *optval, int optlen) const + { + return ::setsockopt(getHandle(), level, option, (char *)optval, (SOCKOPT_SIZE_PARM)optlen); + } + + +int cdevSocket::getOption (int level, int option, void *optval, int *optlen) const + { + return ::getsockopt(getHandle(), level, option, (char *)optval, (SOCKOPT_SIZE_PARM *)optlen); + } + + +int cdevSocket::getLocalAddress (cdevAddr & addr) + { + int retval; + int len=addr.getSize(); + + if(::getsockname(getHandle(), (sockaddr *)addr.getAddress(), (SOCKOPT_SIZE_PARM *)&len)==INVALID_HANDLE) + { + retval = INVALID_HANDLE; + } + else { + addr.setSize(len); + retval = 0; + } + return retval; + } + + +int cdevSocket::getRemoteAddress (cdevAddr & addr) + { + int retval; + int len = addr.getSize(); + if(::getpeername(getHandle(), (sockaddr *)addr.getAddress(), (SOCKOPT_SIZE_PARM *)&len)==INVALID_HANDLE) + { + retval = INVALID_HANDLE; + } + else { + addr.setSize(len); + retval = 0; + } + return retval; + } + + +cdevSocket::cdevSocket ( void ) + : handle(INVALID_HANDLE) + { + } + + +cdevSocket::cdevSocket(int type, int protocol_family, int protocol) + : handle(INVALID_HANDLE) + { + setHandle(open(type, protocol_family, protocol)); + } + diff --git a/extensions/cdevGenericServer/cdevReactor/cdevSocket.h b/extensions/cdevGenericServer/cdevReactor/cdevSocket.h new file mode 100755 index 0000000..f93fe2e --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevSocket.h @@ -0,0 +1,34 @@ +#ifndef _CDEV_SOCKET_H_ +#define _CDEV_SOCKET_H_ + +#include +#include +#include "cdevAddr.h" + +class CDEV_REACTOR_API cdevSocket +{ +protected: + int handle; + sockaddr_in sa; + + cdevSocket(void); + cdevSocket(int type, int protocol_family, int protocol=0); + +public: + enum {INVALID_HANDLE=-1}; + + void setHandle (int fd); + int getHandle (void) const; + int open (int type, int protocol_family, int protocol); + int close (void); + int unsetFlags (int flags); + int setFlags (int flags); + int getFlags (void); + int setOption (int level, int option, void *optval, int optlen) const; + int getOption (int level, int option, void *optval, int *optlen) const; + int getLocalAddress (cdevAddr & address); + int getRemoteAddress (cdevAddr & address); +}; + + +#endif diff --git a/extensions/cdevGenericServer/cdevReactor/cdevSocketAcceptor.cc b/extensions/cdevGenericServer/cdevReactor/cdevSocketAcceptor.cc new file mode 100644 index 0000000..1004b3a --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevSocketAcceptor.cc @@ -0,0 +1,93 @@ +#include "cdevSocketAcceptor.h" + +// ***************************************************************************** +// * cdevSocketAcceptor::cdevSocketAcceptor : +// * Do nothing routine for constructor. +// ***************************************************************************** +cdevSocketAcceptor::cdevSocketAcceptor(void) + { + } + +// ***************************************************************************** +// * cdevSocketAcceptor::open : +// * General purpose routine for performing server cdevSocket creation. +// ***************************************************************************** +int cdevSocketAcceptor::open + ( + const cdevAddr &addr, + int reuse_addr, + int protocol_family, + int backlog, + int protocol, + int reopen) + { + int one = 1; + int retval; + + if(reopen) cdevSocket::open(SOCK_STREAM, protocol_family, protocol); + + if(this->getHandle() == cdevSocket::INVALID_HANDLE) + { + retval = cdevSocket::INVALID_HANDLE; + close(); + } + else { + if(reuse_addr && setOption(SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == cdevSocket::INVALID_HANDLE) + { + close(); + } + else if(::bind(getHandle(), (sockaddr *)addr.getAddress(), + addr.getSize()) == cdevSocket::INVALID_HANDLE || + ::listen(getHandle(), backlog) == cdevSocket::INVALID_HANDLE) + { + close(); + } + retval = getHandle(); + } + return retval; + } + +// ***************************************************************************** +// * cdevSocketAcceptor::cdevSocketAcceptor : +// * General purpose routine for performing server cdevSocket creation. +// ***************************************************************************** +cdevSocketAcceptor::cdevSocketAcceptor ( + const cdevAddr &addr, + int reuse_addr, + int protocol_family, + int backlog, + int protocol) + : cdevSocket(SOCK_STREAM, protocol_family, protocol) + { + open(addr, reuse_addr, protocol_family, backlog, protocol, 0); + } + +// ***************************************************************************** +// * cdevSocketAcceptor::accept : +// * General purpose routine for accepting new connections. +// ***************************************************************************** +int cdevSocketAcceptor::accept(cdevSocketStream &new_stream, cdevAddr *addr) const + { + sockaddr *sock_addr=0; + int *len_ptr=0; + int len; + int new_handle; + + if(addr != 0) + { + len=addr->getSize(); + len_ptr= &len; + sock_addr=(sockaddr *) addr->getAddress(); + } + + do { + new_handle=::accept(this->getHandle(), sock_addr, (SOCKOPT_SIZE_PARM *)len_ptr); + } while(new_handle==cdevSocket::INVALID_HANDLE && errno==EINTR); + + if(addr != 0) addr->setSize(*len_ptr); + + new_stream.setHandle(new_handle); + new_stream.configureHandle(); + + return new_handle; + } diff --git a/extensions/cdevGenericServer/cdevReactor/cdevSocketAcceptor.h b/extensions/cdevGenericServer/cdevReactor/cdevSocketAcceptor.h new file mode 100755 index 0000000..dbefb46 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevSocketAcceptor.h @@ -0,0 +1,32 @@ +#ifndef _CDEV_SOCKET_ACCEPTOR_H_ +#define _CDEV_SOCKET_ACCEPTOR_H_ + +#include "cdevSocketStream.h" + +class CDEV_REACTOR_API cdevSocketAcceptor : public cdevSocket +{ +public: + cdevSocketAcceptor(void); + cdevSocketAcceptor( + const cdevAddr &addr, + int reuse_addr = 0, + int protocol_family = PF_INET, + int backlog = 5, + int protocol = 0); + + int open(const cdevAddr &addr, + int reuse_addr = 0, + int protocol_family = PF_INET, + int backlog = 5, + int protocol = 0, + int reopen = 1); + + int accept( + cdevSocketStream &new_stream, + cdevAddr *remote_addr=0) const; + +private: + int getRemoteAddress(cdevAddr &) const; +}; + +#endif /* _CDEV_SOCKET_ACCEPTOR_H */ diff --git a/extensions/cdevGenericServer/cdevReactor/cdevSocketConnector.cc b/extensions/cdevGenericServer/cdevReactor/cdevSocketConnector.cc new file mode 100644 index 0000000..880a5db --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevSocketConnector.cc @@ -0,0 +1,65 @@ +#include "cdevSocketConnector.h" +#include "cdevHandleSet.h" + +// ***************************************************************************** +// * cdevSocketConnector::connect : +// * Actively connect and produce a new cdevSocketStream if things go well... +// ***************************************************************************** +int cdevSocketConnector::connect ( const cdevAddr & remote_addr ) + { + int retval = 0; + + if(getHandle() == cdevSocket::INVALID_HANDLE && + cdevSocket::open(SOCK_STREAM, PF_INET, 0) == cdevSocket::INVALID_HANDLE) + { + retval = -1; + } + else + { + double secondsWaited = 0.0; + sockaddr *addr=(sockaddr *) remote_addr.getAddress(); + size_t size=remote_addr.getSize(); + + if(configureHandle()<0) + { + retval = -1; + } + else if(::connect(getHandle(), addr, size) == cdevSocket::INVALID_HANDLE) + { + int errCode = GetSocketErrno(); + + if(getBlockingSemantics()==O_NONBLOCK && errCode==EINPROGRESS) + { + errCode=EWOULDBLOCK; + } + + if(errCode == EISCONN) + { + retval = 0; + } + else if(errCode != EWOULDBLOCK) + { + close(); + setHandle(cdevSocket::INVALID_HANDLE); + retval = -1; + } + else { + cdevHandleSet ws; + cdevHandleSet es; + struct timeval tv; + int fd = getHandle(); + + ws.set_bit(fd); + es.set_bit(fd); + tv.tv_sec = 3; + tv.tv_usec = 0; + + if(cdevSelect(fd+1, NULL, ws, es, &tv)>0 && ws.is_set(fd)) retval = 0; + else retval = -1; + } + } + } + + return retval; + } + diff --git a/extensions/cdevGenericServer/cdevReactor/cdevSocketConnector.h b/extensions/cdevGenericServer/cdevReactor/cdevSocketConnector.h new file mode 100755 index 0000000..8dc1d72 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevSocketConnector.h @@ -0,0 +1,12 @@ +#ifndef _CDEV_SOCKET_CONNECTOR_H_ +#define _CDEV_SOCKET_CONNECTOR_H_ + +#include "cdevSocketStream.h" + +class CDEV_REACTOR_API cdevSocketConnector : public cdevSocketStream +{ +public: + int connect (const cdevAddr & remote_addr ); +}; + +#endif /* _CDEV_SOCK_CONNECTOR_H */ diff --git a/extensions/cdevGenericServer/cdevReactor/cdevSocketDatagram.cc b/extensions/cdevGenericServer/cdevReactor/cdevSocketDatagram.cc new file mode 100644 index 0000000..58bd240 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevSocketDatagram.cc @@ -0,0 +1,44 @@ +#include "cdevSocketDatagram.h" + +int cdevSocketDatagram::open ( const cdevAddr &addr, int protocol_family, int protocol ) + { + int result = 0; + + if((result = cdevSocket::open(SOCK_DGRAM, protocol_family, protocol))!=-1) + { + result = bind(getHandle(), (sockaddr *)addr.getAddress(), addr.getSize()); + } + if(result!=0) close(); + + return result; + } + + +ssize_t cdevSocketDatagram::send (const void *buf, size_t n, const cdevAddr &addr, int flags) const + { + sockaddr *saddr = (sockaddr *) addr.getAddress (); + size_t len = addr.getSize (); + return sendto (this->getHandle (), (const char *) buf, n, flags, (struct sockaddr *) saddr, len); + } + + +ssize_t cdevSocketDatagram::recv (void *buf, size_t n, cdevAddr &addr, int flags) const + { + sockaddr *saddr = (sockaddr *) addr.getAddress(); + int len = addr.getSize(); + ssize_t status = recvfrom (this->getHandle(), (char *)buf, n, flags, (sockaddr *) saddr, (SOCKOPT_SIZE_PARM *)&len); + addr.setSize (len); + return status; + } + + +cdevSocketDatagram::cdevSocketDatagram ( void ) + { + } + + +cdevSocketDatagram::cdevSocketDatagram ( const cdevAddr &addr, int protocol_family, int protocol ) + { + open(addr, protocol_family, protocol); + } + diff --git a/extensions/cdevGenericServer/cdevReactor/cdevSocketDatagram.h b/extensions/cdevGenericServer/cdevReactor/cdevSocketDatagram.h new file mode 100755 index 0000000..f2a1056 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevSocketDatagram.h @@ -0,0 +1,18 @@ +#if !defined (_CDEV_SOCKET_DATAGRAM_H_) +#define _CDEV_SOCKET_DATAGRAM_H + +#include "cdevSocket.h" +#include "cdevAddr.h" + +class CDEV_REACTOR_API cdevSocketDatagram : public cdevSocket +{ +public: + cdevSocketDatagram (void); + cdevSocketDatagram (const cdevAddr &addr, int protocol_family = PF_INET, int protocol = 0); + int open (const cdevAddr &addr, int protocol_family = PF_INET, int protocol = 0); + ssize_t send (const void *buf, size_t n, const cdevAddr &addr, int flags = 0) const; + ssize_t recv (void *buf, size_t n, cdevAddr &addr, int flags = 0) const; + +}; + +#endif /* _CDEV_SOCKET_DATAGRAM_H_ */ diff --git a/extensions/cdevGenericServer/cdevReactor/cdevSocketStream.cc b/extensions/cdevGenericServer/cdevReactor/cdevSocketStream.cc new file mode 100755 index 0000000..325b1e5 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevSocketStream.cc @@ -0,0 +1,177 @@ +#include "cdevSocketStream.h" + +// ***************************************************************************** +// * cdevSocketStream::cdevSocketStream : +// * Constructor for the cdevSocketStream class. Only serves to initialize +// * the readRetryCount variable. +// ***************************************************************************** +cdevSocketStream::cdevSocketStream ( void ) + { + } + +// ***************************************************************************** +// * cdevSocketStream::send : +// * Send an n byte message to the connected socket. +// ***************************************************************************** +ssize_t cdevSocketStream::send(const void *buf, size_t n, int flags) const + { + int retval; + if((retval = ::send(getHandle(), (const char *) buf, n, flags))<=0) + { + int errCode = GetSocketErrno(); + + if(errCode==EAGAIN || errCode==EWOULDBLOCK) retval = 0; + } + return retval; + } + +// ***************************************************************************** +// * cdevSocketStream::send_n : +// * This method will transmit an n byte message to a connected socket, +// * waiting until all data has been transmitted or an error occurs. +// ***************************************************************************** +ssize_t cdevSocketStream::send_n(const void *buf, size_t n, int flags) const + { + ssize_t amntsent = 0; + int result = 0; + + while(amntsent<(ssize_t)n && result>=0) + { + if((result = ::send(getHandle(), (const char *)buf+amntsent, n-amntsent, flags))<=0) + { + int errCode = GetSocketErrno(); + + if(errCode==EAGAIN || errCode==EWOULDBLOCK) result = 0; + else result = -1; + } + else amntsent+=result; + } + return (amntsent>=(ssize_t)n)?amntsent:-1; + } + + +// ***************************************************************************** +// * cdevSocketStream::recv : +// * Recv an n byte message from the connected socket. +// ***************************************************************************** +ssize_t cdevSocketStream::recv(void *buf, size_t n, int flags) + { + int retval = 0; + + if((retval = ::recv(getHandle(), (char *)buf, n, flags))<=0) + { + int errCode = GetSocketErrno(); + + if(errCode==EAGAIN || errCode==EWOULDBLOCK) retval = 0; + } + return retval; + } + + +// ***************************************************************************** +// * cdevSocketStream::recv_n : +// * This method will receive an n byte message from a connected socket, +// * waiting until all data has been received or an error occurs. +// ***************************************************************************** +ssize_t cdevSocketStream::recv_n(void *buf, size_t n, int flags) + { + ssize_t amntrecv = 0; + int result = 0; + + while(amntrecv < (ssize_t)n) + { + if((result = ::recv(getHandle(), (char *)buf+amntrecv, n-amntrecv, flags)) < 0) + { + return -1; + } + else if (result == 0) + break; + else amntrecv+=result; + } + return amntrecv; + } + + +// ***************************************************************************** +// * cdevSocketStream::closeReader : +// * Shut down just the reading end of a cdevSocket. +// ***************************************************************************** +int cdevSocketStream::closeReader(void) + { + return ::shutdown(getHandle(), 0); + } + + +// ***************************************************************************** +// * cdevSocketStream::closeWriter : +// * Shut down just the writing end of a cdevSocket. +// ***************************************************************************** +int cdevSocketStream::closeWriter(void) + { + return ::shutdown(getHandle(), 1); + } + + +int cdevSocketStream::getBlockingSemantics ( void ) const + { + return O_NONBLOCK; + } + +int cdevSocketStream::getRcvLowWaterMark ( void ) const + { + return 0; + } + +int cdevSocketStream::getRcvBufferSize ( void ) const + { + return 56000; + } + +int cdevSocketStream::getSndLowWaterMark ( void ) const + { + return 16000; + } + +int cdevSocketStream::getSndBufferSize ( void ) const + { + return 56000; + } + +int cdevSocketStream::configureHandle ( void ) + { + int retval = 0; + int parm = 1; + + + if(getBlockingSemantics()==O_NONBLOCK && setFlags(O_NONBLOCK)==-1) + { + retval = -1; + } + + setOption(IPPROTO_TCP, TCP_NODELAY, &parm, sizeof(parm)); + + if((parm = getRcvBufferSize())>0) + { + setOption(SOL_SOCKET, SO_RCVBUF, &parm, sizeof(parm)); + } +#ifndef __linux + if((parm = getRcvLowWaterMark())>0) + { + setOption(SOL_SOCKET, SO_RCVLOWAT, &parm, sizeof(parm)); + } +#endif + + if((parm = getSndBufferSize())>0) + { + setOption(SOL_SOCKET, SO_SNDBUF, &parm, sizeof(parm)); + } + +#ifndef __linux + if((parm = getSndLowWaterMark())>0) + { + setOption(SOL_SOCKET, SO_SNDLOWAT, &parm, sizeof(parm)); + } +#endif + + return retval; + } diff --git a/extensions/cdevGenericServer/cdevReactor/cdevSocketStream.h b/extensions/cdevGenericServer/cdevReactor/cdevSocketStream.h new file mode 100755 index 0000000..765922c --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevSocketStream.h @@ -0,0 +1,29 @@ +#if !defined (_CDEV_SOCKET_STREAM_H) +#define _CDEV_SOCKET_STREAM_H + +#include "cdevSocket.h" +#include + + +class CDEV_REACTOR_API cdevSocketStream : public cdevSocket +{ +public: + cdevSocketStream (void); + ssize_t send (const void *buf, size_t n, int flags=0) const; + ssize_t recv (void *buf, size_t n, int flags=0); + ssize_t send_n (const void *buf, size_t n, int flags=0) const; + ssize_t recv_n (void * buf, size_t n, int flags=0); + + int closeReader (void); + int closeWriter (void); + + virtual int getBlockingSemantics ( void ) const; + virtual int getRcvLowWaterMark ( void ) const; + virtual int getSndLowWaterMark ( void ) const; + virtual int getRcvBufferSize ( void ) const; + virtual int getSndBufferSize ( void ) const; + virtual int configureHandle ( void ); +}; + +#endif /* _CDEV_SOCKET_STREAM_H_ */ + diff --git a/extensions/cdevGenericServer/cdevReactor/cdevStreamNode.cc b/extensions/cdevGenericServer/cdevReactor/cdevStreamNode.cc new file mode 100644 index 0000000..350c437 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevStreamNode.cc @@ -0,0 +1,20 @@ +#include "cdevStreamNode.h" + +cdevStreamNode::cdevStreamNode ( void ) + : nextStreamNode(NULL) + { + } + +cdevStreamNode::~cdevStreamNode ( void ) + { + } + +cdevStreamNode * cdevStreamNode::getNext( void ) const + { + return nextStreamNode; + } + +void cdevStreamNode::setNext (cdevStreamNode * node) + { + nextStreamNode = node; + } diff --git a/extensions/cdevGenericServer/cdevReactor/cdevStreamNode.h b/extensions/cdevGenericServer/cdevReactor/cdevStreamNode.h new file mode 100755 index 0000000..fb7f9af --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevStreamNode.h @@ -0,0 +1,33 @@ +#ifndef _CDEV_STREAM_NODE_H_ +#define _CDEV_STREAM_NODE_H_ + +#include "cdevPlatforms.h" + +// ***************************************************************************** +// * class cdevStreamNode : +// * This is a virtual base class that defines the functionality that will +// * be required for data nodes that are inserted into the +// * cdevBufferedSocket. +// ***************************************************************************** +class CDEV_REACTOR_API cdevStreamNode +{ +friend class cdevStreamQueue; + +public: + virtual ~cdevStreamNode ( void ); + + virtual size_t getLen(void) const = 0; + virtual void setLen(size_t size) = 0; + virtual char * getBuf(void) const = 0; + virtual void setBuf(char * buf, size_t len) = 0; + +protected: + cdevStreamNode * nextStreamNode; + + cdevStreamNode ( void ); + + cdevStreamNode * getNext( void ) const; + void setNext(cdevStreamNode * node); +}; + +#endif /* _CDEV_STREAM_NODE_H_ */ diff --git a/extensions/cdevGenericServer/cdevReactor/cdevStreamQueue.cc b/extensions/cdevGenericServer/cdevReactor/cdevStreamQueue.cc new file mode 100644 index 0000000..81ea4ce --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevStreamQueue.cc @@ -0,0 +1,35 @@ +#include "cdevStreamQueue.h" + +cdevSimpleStreamNode::cdevSimpleStreamNode( char * buffer, size_t size) + : cdevStreamNode(), buf(buffer), len(size) + { + } + +cdevSimpleStreamNode::~cdevSimpleStreamNode ( void ) + { + if(buf) delete buf; + } + +size_t cdevSimpleStreamNode::getLen (void) const + { + return len; + } + +void cdevSimpleStreamNode:: setLen (size_t size) + { + len=size; + } + +char * cdevSimpleStreamNode::getBuf (void) const + { + return buf; + } + +void cdevSimpleStreamNode::setBuf (char * buffer, size_t size) + { + buf=buffer; len=size; + } + +cdevNodeFactory::~cdevNodeFactory ( void ) + { + } diff --git a/extensions/cdevGenericServer/cdevReactor/cdevStreamQueue.h b/extensions/cdevGenericServer/cdevReactor/cdevStreamQueue.h new file mode 100755 index 0000000..d58fa5d --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevStreamQueue.h @@ -0,0 +1,126 @@ +#ifndef _CDEV_STREAM_QUEUE_H_ +#define _CDEV_STREAM_QUEUE_H_ + +#include "cdevStreamNode.h" + +// ***************************************************************************** +// * class cdevSimpleStreamNode : +// * This is a simple implementation class of the cdevStreamNode. It will +// * be used if the developer does not provide his own implementation class. +// ***************************************************************************** +class CDEV_REACTOR_API cdevSimpleStreamNode : public cdevStreamNode +{ +protected: + char * buf; + size_t len; + +public: + cdevSimpleStreamNode ( char * buffer=NULL, size_t size=0); + ~cdevSimpleStreamNode ( void ); + + size_t getLen (void) const; + void setLen (size_t size); + char * getBuf (void) const; + void setBuf (char * buffer, size_t size); +}; + + +// ***************************************************************************** +// * class cdevNodeFactory : +// * This class will generate a user defined instance of a cdevStreamNode +// * sub-class. This class is used within the cdevBufferedSocket to +// * convert incoming binary packets into a user defined structure. +// ***************************************************************************** +class CDEV_REACTOR_API cdevNodeFactory +{ +public: + virtual ~cdevNodeFactory ( void ); + + virtual cdevStreamNode * newNode ( ssize_t size ) = 0; +}; + + + +// ***************************************************************************** +// * class cdevStreamQueue : +// * This is a class that will store the data items that are being enqueued +// * by the cdevBufferedSocket. +// ***************************************************************************** +class CDEV_REACTOR_API cdevStreamQueue +{ +private: + cdevStreamNode * head; + cdevStreamNode * tail; + int deleteFlag; + size_t nEntries; + size_t totalLen; + +public: + cdevStreamQueue ( int deleteNodesFlag = 1 ) + : head(NULL), tail(NULL), deleteFlag(deleteNodesFlag), + nEntries(0), totalLen(0) + { + } + + ~cdevStreamQueue ( void ) + { + if(deleteFlag) while(!isEmpty()) delete dequeue(); + } + + void enqueue( cdevStreamQueue & queue ) + { + head = queue.head; + tail = queue.tail; + nEntries = queue.nEntries; + totalLen = queue.totalLen; + queue.head = NULL; + queue.tail = NULL; + queue.nEntries = 0; + queue.totalLen = 0; + } + + void enqueue ( cdevStreamNode * node ) + { + if(node) + { + if(tail!=NULL) tail->setNext(node); + else head = node; + tail = node; + totalLen+=(node->getLen()+sizeof(node->getLen())); + nEntries++; + } + } + + cdevStreamNode * dequeue ( void ) + { + cdevStreamNode * node = NULL; + if(head!=NULL) + { + node = head; + head = node->getNext(); + node->setNext(NULL); + if(head==NULL) tail = NULL; + totalLen-=(node->getLen()+sizeof(node->getLen())); + nEntries--; + } + return node; + } + + cdevStreamNode * peek ( void ) + { + return head; + } + + void poke ( cdevStreamNode * node ) + { + node->setNext(head); + head = node; + if(tail==NULL) tail = head; + } + + int isEmpty ( void ) const { return head==NULL?1:0; } + size_t getCount ( void ) const { return nEntries; } + size_t getSize ( void ) const { return totalLen; } +}; + +#endif /* _CDEV_STREAM_QUEUE_H */ diff --git a/extensions/cdevGenericServer/cdevReactor/cdevTime.cc b/extensions/cdevGenericServer/cdevReactor/cdevTime.cc new file mode 100644 index 0000000..64f9735 --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevTime.cc @@ -0,0 +1,210 @@ +#include "cdevTime.h" + +cdevTime::cdevTime ( long sec, long usec ) + { + setTime(sec, usec); + } + + +cdevTime::cdevTime ( double t ) + { + setTime(t); + } + + +cdevTime::cdevTime ( timeval & t ) + { + setTime(t); + } + + +cdevTime::cdevTime ( const cdevTime & t ) + { + setTime(t); + } + + +void cdevTime::getTime ( double * t ) const + { + if(t) *t = (double)tv_sec+(double)tv_usec/(double)ONE_SECOND; + } + + +void cdevTime::getTime ( long * sec, long * usec) const + { + if(sec && usec) + { + *sec = tv_sec; + *usec = tv_usec; + } + } + + +void cdevTime::getTime ( timeval * t ) const + { + if(t) { + t->tv_sec = tv_sec; + t->tv_usec = tv_usec; + } + } + + +void cdevTime::setTime ( void ) + { + struct timeval tv_time; + + gettimeofday(&tv_time); + + tv_sec = tv_time.tv_sec; + tv_usec = tv_time.tv_usec; + } + + +void cdevTime::setTime ( double t ) + { + tv_sec = (long)t; + tv_usec = (long)((double)fmod(t, 1.0)*(double)ONE_SECOND); + normalize(); + } + + +void cdevTime::setTime ( long sec, long usec ) + { + tv_sec = sec; + tv_usec = usec; + normalize(); + } + + +void cdevTime::setTime ( timeval & t ) + { + tv_sec = t.tv_sec; + tv_usec = t.tv_usec; + normalize(); + } + + +void cdevTime::setTime ( const cdevTime & t ) + { + t.getTime(&tv_sec, &tv_usec); + normalize(); + } + + +void cdevTime::clear ( void ) + { + tv_sec = 0; + tv_usec = 0; + } + + +int cdevTime::isSet ( void ) const + { + return (tv_sec||tv_usec)?1:0; + } + + +int cdevTime::normalize ( void ) + { + while ((this->tv_usec >= ONE_SECOND) + || (this->tv_sec < 0 && this->tv_usec > 0 )) + { + this->tv_usec -= ONE_SECOND; + this->tv_sec++; + } + + while ((this->tv_usec <= -ONE_SECOND) + || (this->tv_sec > 0 && this->tv_usec < 0)) + { + this->tv_usec += ONE_SECOND; + this->tv_sec--; + } + + return isSet(); + } + + +cdevTime & cdevTime::operator = ( const cdevTime & t ) + { + if (this != &t) + { + tv_sec = t.tv_sec; + tv_usec = t.tv_usec; + } + return *this; + } + + +cdevTime::operator double ( void ) + { + return (double)tv_sec+(double)tv_usec/(double)ONE_SECOND; + } + + +cdevTime::operator timeval ( void ) + { + timeval tv_time; + + tv_time.tv_sec = tv_sec; + tv_time.tv_usec = tv_usec; + + return tv_time; + } + + +cdevTime operator + (cdevTime t1, cdevTime t2) + { + cdevTime sum (t1.tv_sec + t2.tv_sec, t1.tv_usec + t2.tv_usec); + + sum.normalize (); + return sum; + } + + +cdevTime operator - (cdevTime t1, cdevTime t2) + { + cdevTime delta (t1.tv_sec - t2.tv_sec, t1.tv_usec - t2.tv_usec); + + delta.normalize (); + return delta; + } + + +int operator > (cdevTime t1, cdevTime t2) + { + if (t1.tv_sec > t2.tv_sec) return 1; + else if (t1.tv_sec == t2.tv_sec && t1.tv_usec > t2.tv_usec) return 1; + else return 0; + } + + +int operator >= (cdevTime t1, cdevTime t2) + { + if (t1.tv_sec > t2.tv_sec) return 1; + else if (t1.tv_sec == t2.tv_sec && t1.tv_usec >= t2.tv_usec) return 1; + else return 0; + } + + +int operator < (cdevTime t1, cdevTime t2) + { + return t2 > t1; + } + + +int operator <= (cdevTime t1, cdevTime t2) + { + return t2 >= t1; + } + + +int operator == (cdevTime t1, cdevTime t2) + { + return t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec; + } + + +int operator != (cdevTime t1, cdevTime t2) + { + return !(t1 == t2); + } diff --git a/extensions/cdevGenericServer/cdevReactor/cdevTime.h b/extensions/cdevGenericServer/cdevReactor/cdevTime.h new file mode 100755 index 0000000..6ee8bad --- /dev/null +++ b/extensions/cdevGenericServer/cdevReactor/cdevTime.h @@ -0,0 +1,51 @@ +#ifndef _CDEV_TIME_H_ +#define _CDEV_TIME_H_ 1 + +#include "cdevPlatforms.h" + +#define ONE_SECOND 1000000 + +typedef struct timeval timeval; + +class CDEV_REACTOR_API cdevTime +{ +private: + long tv_sec; + long tv_usec; + +public: + cdevTime ( long sec=0, long usec=0 ); + cdevTime ( double t ); + cdevTime ( timeval &t ); + cdevTime ( const cdevTime &t ); + + void getTime ( double * t ) const; + void getTime ( long *sec, long *usec) const; + void getTime ( timeval * t ) const; + + void setTime ( void ); + void setTime ( double t ); + void setTime ( long sec, long usec); + void setTime ( timeval &t ); + void setTime ( const cdevTime &t ); + + void clear ( void ); + int isSet ( void ) const; + int normalize ( void ); + + operator double ( void ); + operator timeval ( void ); + + cdevTime & operator = (const cdevTime& t); + + friend cdevTime operator + (cdevTime t1, cdevTime t2); + friend cdevTime operator - (cdevTime t1, cdevTime t2); + friend int operator < (cdevTime t1, cdevTime t2); + friend int operator > (cdevTime t1, cdevTime t2); + friend int operator <= (cdevTime t1, cdevTime t2); + friend int operator >= (cdevTime t1, cdevTime t2); + friend int operator == (cdevTime t1, cdevTime t2); + friend int operator != (cdevTime t1, cdevTime t2); +}; + +#endif diff --git a/extensions/cdevGenericServer/cdevServer/ClientAcceptor.cc b/extensions/cdevGenericServer/cdevServer/ClientAcceptor.cc new file mode 100755 index 0000000..b858e90 --- /dev/null +++ b/extensions/cdevGenericServer/cdevServer/ClientAcceptor.cc @@ -0,0 +1,87 @@ +#include "ClientAcceptor.h" +#include "ClientHandler.h" + +// ***************************************************************************** +// * ClientAcceptor: +// * Default constructor for the ClientAcceptor class +// ***************************************************************************** +ClientAcceptor::ClientAcceptor (cdevSessionManager & s) + : server(s) + { + } + + +// ***************************************************************************** +// * ClientAcceptor::~ClientAcceptor: +// * Destructor for the ClientAcceptor class +// ***************************************************************************** +ClientAcceptor::~ClientAcceptor (void) + { + if(reactor) reactor->extractHandler(this); + handleClose(); + } + +// ***************************************************************************** +// * open: +// * Initializes the listening socket +// ***************************************************************************** +int ClientAcceptor::open (const cdevInetAddr &addr) + { + int result = -1; + if (this->acceptor.open (addr, TRUE) == -1) + { + outputError(CDEV_SEVERITY_SEVERE, (char *)getName(), + "Failed to open listening port"); + } + else if (acceptor.setFlags (O_NONBLOCK) == -1) + { + outputError(CDEV_SEVERITY_ERROR, (char *)getName(), + "Could not enable non-blocking I/O"); + } + else result = 0; + return result; + } + +// ***************************************************************************** +// * getHandle: +// * Returns the device descriptor of the listening socket +// ***************************************************************************** +int ClientAcceptor::getHandle (void) const + { + return acceptor.getHandle (); + } + +// ***************************************************************************** +// * handleInput: +// * Accepts a connection on a listening socket and then creates a +// * ClientHandler class to manage the connection. +// ***************************************************************************** +int ClientAcceptor::handleInput (void) + { + cdevInetAddr addr; + ClientHandler *svc_handler = new ClientHandler(server); + if (acceptor.accept (*svc_handler, &addr) != -1) + { + svc_handler->open(this); + } + else + { + outputError(CDEV_SEVERITY_ERROR, (char *)getName(), + "Failed to accept connection"); + } + // ********************************************************************* + // * Always return 0... Otherwise, the accepting socket will + // * be destroyed and a crippled server is all that will remain. + // ********************************************************************* + return 0; + } + +// ***************************************************************************** +// * handleClose: +// * Closes the listening socket +// ***************************************************************************** +int ClientAcceptor::handleClose (void) + { + acceptor.close (); + return 0; + } diff --git a/extensions/cdevGenericServer/cdevServer/ClientAcceptor.h b/extensions/cdevGenericServer/cdevServer/ClientAcceptor.h new file mode 100755 index 0000000..c99bfae --- /dev/null +++ b/extensions/cdevGenericServer/cdevServer/ClientAcceptor.h @@ -0,0 +1,34 @@ +#if !defined (_CLIENT_ACCEPTOR_H) +#define _CLIENT_ACCEPTOR_H + +#include "cdevSessionManager.h" + +#include "cdevSocketAcceptor.h" + +// ***************************************************************************** +// * class ClientAcceptor: +// * This class provdies the cdevEventHandler that accepts connections through +// * the reactor on the listening port. Once accepted, these new connections +// * are serviced by the ClientHandler. +// ***************************************************************************** +class GENERIC_SERVER_API ClientAcceptor : public cdevEventHandler, public ErrorReporter +{ +friend class ClientHandler; +public: + ClientAcceptor (cdevSessionManager &s); + ~ClientAcceptor (void); + + const char *getName (void) { return "ClientAcceptor"; } + int getLocalAddress (cdevAddr &addr) { return acceptor.getLocalAddress(addr); } + int open (const cdevInetAddr &addr); + + virtual int getHandle (void) const; + virtual int handleInput (void); + virtual int handleClose (void); + +private: + cdevSocketAcceptor acceptor; + cdevSessionManager & server; +}; + +#endif diff --git a/extensions/cdevGenericServer/cdevServer/ClientHandler.cc b/extensions/cdevGenericServer/cdevServer/ClientHandler.cc new file mode 100755 index 0000000..cbb6607 --- /dev/null +++ b/extensions/cdevGenericServer/cdevServer/ClientHandler.cc @@ -0,0 +1,268 @@ +#include "ClientHandler.h" +#include "ClientAcceptor.h" +#include + +// ***************************************************************************** +// * ClientHandler: +// * Default constructor for the ClientHandler class +// ***************************************************************************** +ClientHandler::ClientHandler (cdevSessionManager & s) + : server(s), queue(NULL), clientQuitFlag(0), + SocketReader(CLIP_MAGIC_NUMBER), SocketWriter(CLIP_MAGIC_NUMBER), + packetsSent(0), packetsRecv(0) + { + hostName[0] = 0; + } + +// ***************************************************************************** +// * ClientHandler::getHostName: +// * This function returns the name of the remote host. +// ***************************************************************************** +char * ClientHandler::getHostName( void ) + { + if(*hostName==0) + { + cdevInetAddr addr; + if(stream.getRemoteAddress (addr)==0) + { + const char * ptr=addr.getHostName(); + if(ptr) strncpy (hostName, ptr, MAXHOSTNAMELEN+1); + } + } + return hostName; + } + +// ***************************************************************************** +// * open: +// * Initializes the new socket and adds this ClientHandler class to +// * the reactor +// ***************************************************************************** +int ClientHandler::open (class ClientAcceptor * ) + { + cdevInetAddr addr; + int result = 0; + + if (stream.getRemoteAddress (addr) == -1) + { + outputError(CDEV_SEVERITY_SEVERE, (char *)getName(), + "Couldn't get local address"); + result = -1; + } + else + { + if (server.Reactor.registerHandler (this, READ_MASK|WRITE_MASK|EXCEPT_MASK)!=0) + { + outputError(CDEV_SEVERITY_SEVERE, (char *)getName(), + "Cannot register handler with reactor"); + result = -1; + } + else { + // ***************************************************** + // * Get the socket number and use it to identify the + // * socket within the cdevSessionManager. + // ***************************************************** + int handle = getHandle(); + if((queue = server.findSocket(handle))!=NULL) + { + server.removeSocket(handle); + } + queue = server.addSocket(handle); + + outputError(CDEV_SEVERITY_INFO, (char *)getName(), + "Establishing connection to %s on socket %i", + getHostName(), handle); + } + } + return result; + } + +// ***************************************************************************** +// * getHandle: +// * Returns the device descriptor for the underlying socket +// ***************************************************************************** +int ClientHandler::getHandle (void) const + { + return stream.getHandle (); + } + +// ***************************************************************************** +// * ~ClientHandler: +// * Destructor for the ClientHandler object +// ***************************************************************************** +ClientHandler::~ClientHandler (void) + { + if(stream.getHandle()>0 && clientQuitFlag==0) writeGoodbye(); + if(reactor) reactor->extractHandler(this); + handleClose(); + } + +// ***************************************************************************** +// * handleClose: +// * Removes the object from the reactor class and then deletes it. +// ***************************************************************************** +int ClientHandler::handleClose (void) + { + outputError(CDEV_SEVERITY_INFO, (char *)getName(), + "Terminating connection to %s on socket %i", + getHostName(), queue?queue->getSocketID():0); + + stream.close(); + if(queue) + { + server.removeSocket(queue->getSocketID()); + queue = NULL; + } + return 0; + } + + +// ***************************************************************************** +// # handleInput : +// # This function is called when data is ready to be read from a connected +// # socket. This function will read the data from the socket, and will then +// # submit the buffer to the processIncomingPacket function for processing. +// ***************************************************************************** +int ClientHandler::handleInput (void) +{ +int retval = 0; +char * buf = NULL; +size_t len = 0; +int result = 1; + +// ***************************************************************************** +// * Record oriented semantics dictate that the length of the transmission +// * always preceeds the actual data. Therefore, read the length of the +// * transmission into the len variable. +// ***************************************************************************** +while(result>0) + { + if(buf==NULL) result = read(&buf, (int *)&len); + else result = readNextPacket(&buf, (int *)&len); + switch(result) + { + // ************************************************************* + // * A return value of SHUTDOWN_CODE indicates that a negative + // * one was provided as the packet length - indicating a + // * shutdown... + // ************************************************************* + case SHUTDOWN_CODE: + outputError(CDEV_SEVERITY_INFO, (char *)getName(), + "Connection to %s terminated by client", getHostName()); + retval = -1; + break; + + // ************************************************************* + // * A return value of -1 indicates an error occured while + // * reading from the socket. A value of -1 is returned to + // * shutdown the socket and remove it from the reactor. + // ************************************************************* + case -1: + outputError(CDEV_SEVERITY_WARN, (char *)getName(), + "Error reading from connection to client %s", getHostName()); + retval = -1; + break; + + // ************************************************************* + // * A return value of 0 means that no data was ready to be + // * retrieved from the socket. + // ************************************************************* + case 0: + break; + + // ************************************************************* + // * Any other value returned from the socket represents the + // * number of bytes actually read into the local buffer object. + // ************************************************************* + default: + server.enqueue(getHandle(), buf, len); + packetsSent++; + break; + } + } + +// ***************************************************************************** +// * Return the value specified by retval. +// ***************************************************************************** +return retval; +} + + +// ***************************************************************************** +// # handleOutput : +// # This function is called when data is ready to be transmitted to a +// # connected socket. This function will read the data from the queue, +// # translate it to XDR, and then transmit it to the client. +// ***************************************************************************** +int ClientHandler::handleOutput (void) +{ +int retval = 0; +char * buf = NULL; +size_t len = 0; + +// ***************************************************************************** +// * Attempt to transmit or continue transmitting the data. Note, the peek +// * method is used to attempt to writeEnqueue a data item without actually +// * removing it from the outbound queue. If the item can be writeEnqueued, +// * then the dequeue method is called to remove it from the queue... +// * This method is repeated until the output buffer is fully populated. +// ***************************************************************************** +if(!writing() && queue!=NULL && queue->peek(&buf, &len)==0) + { + int full = 0; + while(!full) + { + full = writeEnqueue(buf, len); + if(!full) + { + queue->dequeue(&buf, &len); + delete buf; + buf = NULL; + len = 0; + if(queue->peek(&buf, &len)!=0) full=-1; + packetsRecv++; + } + } + if(writeContinue()<0) retval = -1; + } +else if(writing()) + { + if(writeContinue()<0) retval = -1; + } + +// ***************************************************************************** +// * Display an error message if the transmission failed. +// ***************************************************************************** +if(retval!=0) + { + outputError(CDEV_SEVERITY_WARN, (char *)getName(), + "Error transmitting to %s", getHostName()); + } + +// ***************************************************************************** +// * If there are no further messages in the outbound queue and the +// * ACE_Event_Handler has finished servicing the current message, turn off the +// * WRITE_MASK for this ACE_Event_Handler. +// ***************************************************************************** +if(retval!=0 || ((queue==NULL || queue->empty()) && !writing())) + { + setMask(READ_MASK|EXCEPT_MASK); + } + +// ***************************************************************************** +// * Return the value specified by retval. +// ***************************************************************************** +return retval; +} + + +// ***************************************************************************** +// * ClientHandler::handleExcept : +// * This function is called when out of band data is ready to be received +// * from the socket. +// ***************************************************************************** +int ClientHandler::handleExcept(void) + { + clientQuitFlag=1; + return -1; + } + diff --git a/extensions/cdevGenericServer/cdevServer/ClientHandler.h b/extensions/cdevGenericServer/cdevServer/ClientHandler.h new file mode 100755 index 0000000..5096797 --- /dev/null +++ b/extensions/cdevGenericServer/cdevServer/ClientHandler.h @@ -0,0 +1,43 @@ +#if !defined (_CLIENT_HANDLER_H) +#define _CLIENT_HANDLER_H + +#include +#include +#include + +#include "cdevSessionManager.h" +#include "SocketUtil.h" + +#include "cdevSocketStream.h" + +class GENERIC_SERVER_API ClientHandler : public cdevEventHandler, public SocketReader, public SocketWriter +{ +public: + ClientHandler (cdevSessionManager & s); + ~ClientHandler (void); + + char * getHostName (void); + const char * getName (void) { return "ClientHandler"; } + virtual int open (class ClientAcceptor * acc); + virtual int getHandle (void) const; + operator cdevSocketStream & (void) { return stream; } + + virtual int handleClose (void); + virtual int handleInput (void); + virtual int handleOutput (void); + virtual int handleExcept (void); + + size_t getPacketsSent (void) { return packetsSent; } + size_t getPacketsRecv (void) { return packetsRecv; } + +protected: + char hostName[MAXHOSTNAMELEN + 1]; + cdevSocketStream stream; + cdevSessionManager & server; + SocketSession * queue; + int clientQuitFlag; + size_t packetsSent; + size_t packetsRecv; +}; + +#endif /* _CLIENT_HANDLER_H */ diff --git a/extensions/cdevGenericServer/cdevServer/Makefile b/extensions/cdevGenericServer/cdevServer/Makefile new file mode 100755 index 0000000..b86cb91 --- /dev/null +++ b/extensions/cdevGenericServer/cdevServer/Makefile @@ -0,0 +1,106 @@ +ARCH = OS +SHOBJ = YES + +include ../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "CDEV Generic Server Engine" +CXXINCLUDES = -I../include/ace $(ACEINCLUDES) +TEMPLINKS = cdevPacket.cc\ + cdevMessageBinary.cc\ + cdevMessage.cc\ + cdevContextMap.cc\ + cdevTagMap.cc\ + cdevMonitorTable.cc\ + SignalManager.cc\ + cdevAddr.cc\ + cdevEventHandler.cc\ + cdevHandleSet.cc\ + cdevReactor.cc\ + cdevSocket.cc\ + cdevSocketAcceptor.cc\ + cdevSocketConnector.cc\ + cdevSocketDatagram.cc\ + cdevSocketStream.cc\ + cdevStreamNode.cc\ + cdevStreamQueue.cc\ + cdevTime.cc\ + fifo.cc\ + IntHash.cc + +SERVER_OBJS = $(OBJDIR)/cdevServer.o\ + $(OBJDIR)/cdevServerTools.o\ + $(OBJDIR)/cdevSessionManager.o\ + $(OBJDIR)/ClientHandler.o\ + $(OBJDIR)/ClientAcceptor.o\ + $(OBJDIR)/cdevTagMap.o\ + $(OBJDIR)/cdevMonitorTable.o + +COMMON_OBJS = $(OBJDIR)/cdevPacket.o\ + $(OBJDIR)/cdevMessageBinary.o\ + $(OBJDIR)/cdevMessage.o\ + $(OBJDIR)/cdevContextMap.o\ + $(OBJDIR)/SignalManager.o\ + $(OBJDIR)/fifo.o\ + $(OBJDIR)/IntHash.cc + +ACE_OBJS = $(OBJDIR)/cdevAddr.o\ + $(OBJDIR)/cdevEventHandler.o\ + $(OBJDIR)/cdevHandleSet.o\ + $(OBJDIR)/cdevReactor.o\ + $(OBJDIR)/cdevSocket.o\ + $(OBJDIR)/cdevSocketAcceptor.o\ + $(OBJDIR)/cdevSocketConnector.o\ + $(OBJDIR)/cdevSocketDatagram.o\ + $(OBJDIR)/cdevSocketStream.o\ + $(OBJDIR)/cdevStreamNode.o\ + $(OBJDIR)/cdevStreamQueue.o\ + $(OBJDIR)/cdevTime.o + +# ****************************************************************************** +# * The BINARIES definition names all of the binary files that should be deleted +# * whenever "make clean" is executed. +# ****************************************************************************** +BINARIES = $(BASELIB)/libcdevServer.$(SHARED_EXT) \ + $(BASELIB)/libcdevServer.a + +ifeq ($(SHOBJ),YES) + TARGETS = $(TEMPLINKS) $(BASELIB)/libcdevServer.$(SHARED_EXT) +else + TARGETS = $(TEMPLINKS) $(BASELIB)/libcdevServer.a +endif + +targets : $(TARGETS) + +$(TEMPLINKS) : + @cp $^ $@ + +$(BASELIB)/libcdevServer.a : $(SERVER_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + $(LINK.a) $@ $^ + @$(RANLIB) $@ > /dev/null + @cp $@ $(CDEVLIB) + +$(BASELIB)/libcdevServer.$(SHARED_EXT) : $(SERVER_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + $(LINK.so) -o $@ $^ $(NETLIBS) + @cp $@ $(CDEVLIB) + +cdevPacket.cc : ../cdevPacket/cdevPacket.cc +cdevMessageBinary.cc : ../cdevPacket/cdevMessageBinary.cc +cdevMessage.cc : ../cdevPacket/cdevMessage.cc +cdevContextMap.cc : ../cdevContextMap/cdevContextMap.cc +cdevTagMap.cc : ../cdevTagMap/cdevTagMap.cc +cdevMonitorTable.cc : ../cdevMonitorTable/cdevMonitorTable.cc +SignalManager.cc : ../common/SignalManager.cc +cdevAddr.cc : ../cdevReactor/cdevAddr.cc +cdevEventHandler.cc : ../cdevReactor/cdevEventHandler.cc +cdevHandleSet.cc : ../cdevReactor/cdevHandleSet.cc +cdevReactor.cc : ../cdevReactor/cdevReactor.cc +cdevSocket.cc : ../cdevReactor/cdevSocket.cc +cdevSocketAcceptor.cc : ../cdevReactor/cdevSocketAcceptor.cc +cdevSocketConnector.cc : ../cdevReactor/cdevSocketConnector.cc +cdevSocketDatagram.cc : ../cdevReactor/cdevSocketDatagram.cc +cdevSocketStream.cc : ../cdevReactor/cdevSocketStream.cc +cdevStreamNode.cc : ../cdevReactor/cdevStreamNode.cc +cdevStreamQueue.cc : ../cdevReactor/cdevStreamQueue.cc +cdevTime.cc : ../cdevReactor/cdevTime.cc +fifo.cc : ../common/fifo.cc +IntHash.cc : ../common/IntHash.cc diff --git a/extensions/cdevGenericServer/cdevServer/NMakefile.mak b/extensions/cdevGenericServer/cdevServer/NMakefile.mak new file mode 100644 index 0000000..e8fbfa7 --- /dev/null +++ b/extensions/cdevGenericServer/cdevServer/NMakefile.mak @@ -0,0 +1,149 @@ +.SUFFIXES: .cc .obj + +APPNAME = CDEV Generic Server Engine +ARCH = WINNT-4.0 + +TEMPLINKS = cdevPacket.cc\ + cdevMessageBinary.cc\ + cdevMessage.cc\ + cdevContextMap.cc\ + cdevTagMap.cc\ + cdevMonitorTable.cc\ + SignalManager.cc\ + cdevAddr.cc\ + cdevEventHandler.cc\ + cdevHandleSet.cc\ + cdevReactor.cc\ + cdevSocket.cc\ + cdevSocketAcceptor.cc\ + cdevSocketConnector.cc\ + cdevSocketDatagram.cc\ + cdevSocketStream.cc\ + cdevStreamNode.cc\ + cdevStreamQueue.cc\ + cdevTime.cc\ + fifo.cc + +BINARIES = $(CDEVLIB)\cdevServer.dll \ + $(CDEVLIB)\cdevServer.lib \ + $(TEMPLINKS) + +include ..\include\makeinclude\Makefile.WINNT-4.0 + +SERVER_OBJS = $(OBJDIR)\cdevServer.obj\ + $(OBJDIR)\cdevServerTools.obj\ + $(OBJDIR)\cdevSessionManager.obj\ + $(OBJDIR)\ClientHandler.obj\ + $(OBJDIR)\ClientAcceptor.obj\ + $(OBJDIR)\cdevTagMap.obj\ + $(OBJDIR)\cdevMonitorTable.obj + +COMMON_OBJS = $(OBJDIR)\cdevPacket.obj\ + $(OBJDIR)\cdevMessageBinary.obj\ + $(OBJDIR)\cdevMessage.obj\ + $(OBJDIR)\cdevContextMap.obj\ + $(OBJDIR)\SignalManager.obj\ + $(OBJDIR)\fifo.obj + +ACE_OBJS = $(OBJDIR)\cdevAddr.obj\ + $(OBJDIR)\cdevEventHandler.obj\ + $(OBJDIR)\cdevHandleSet.obj\ + $(OBJDIR)\cdevReactor.obj\ + $(OBJDIR)\cdevSocket.obj\ + $(OBJDIR)\cdevSocketAcceptor.obj\ + $(OBJDIR)\cdevSocketConnector.obj\ + $(OBJDIR)\cdevSocketDatagram.obj\ + $(OBJDIR)\cdevSocketStream.obj\ + $(OBJDIR)\cdevStreamNode.obj\ + $(OBJDIR)\cdevStreamQueue.obj\ + $(OBJDIR)\cdevTime.obj +OBJS = $(SERVER_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + +CXXEXTRA = /D "_CDEV_REACTOR_EXPORTS_=1" /D "_GENERIC_SERVER_EXPORTS_=1" + +!IF "$(SHOBJ)" == "YES" +TARGETS = $(TEMPLINKS) $(CDEVLIB)\cdevServer.dll +!ELSE +TARGETS = $(TEMPLINKS) $(CDEVLIB)\cdevServer.lib +!ENDIF + +targets : $(TARGETS) + @erase $(TEMPLINKS) + +$(CDEVLIB)\cdevServer.lib : $(OBJS) + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\rsvc.lib\ + $(LINK_LIB_FLAGS) /out:$@ $(OBJS) + @echo ^ ^ ^ ^ ^ ^ Done... + +$(CDEVLIB)\cdevServer.dll : $(OBJS) + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\rsvc.lib\ + $(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $(OBJS) + @echo ^ ^ ^ ^ ^ ^ Done... + +cdevMessage.cc : ..\cdevPacket\cdevMessage.cc + -@$(CREATE_LINK) + +cdevMessageBinary.cc : ..\cdevPacket\cdevMessageBinary.cc + -@$(CREATE_LINK) + +cdevPacket.cc : ..\cdevPacket\cdevPacket.cc + -@$(CREATE_LINK) + +cdevContextMap.cc : ..\cdevContextMap\cdevContextMap.cc + -@$(CREATE_LINK) + +SignalManager.cc : ..\common\SignalManager.cc + -@$(CREATE_LINK) + +cdevAddr.cc : ..\cdevReactor\cdevAddr.cc + -@$(CREATE_LINK) + +cdevEventHandler.cc : ..\cdevReactor\cdevEventHandler.cc + -@$(CREATE_LINK) + +cdevHandleSet.cc : ..\cdevReactor\cdevHandleSet.cc + -@$(CREATE_LINK) + +cdevReactor.cc : ..\cdevReactor\cdevReactor.cc + -@$(CREATE_LINK) + +cdevSocket.cc : ..\cdevReactor\cdevSocket.cc + -@$(CREATE_LINK) + +cdevSocketAcceptor.cc : ..\cdevReactor\cdevSocketAcceptor.cc + -@$(CREATE_LINK) + +cdevSocketConnector.cc : ..\cdevReactor\cdevSocketConnector.cc + -@$(CREATE_LINK) + +cdevSocketDatagram.cc : ..\cdevReactor\cdevSocketDatagram.cc + -@$(CREATE_LINK) + +cdevSocketStream.cc : ..\cdevReactor\cdevSocketStream.cc + -@$(CREATE_LINK) + +cdevStreamNode.cc : ..\cdevReactor\cdevStreamNode.cc + -@$(CREATE_LINK) + +cdevStreamQueue.cc : ..\cdevReactor\cdevStreamQueue.cc + -@$(CREATE_LINK) + +cdevTime.cc : ..\cdevReactor\cdevTime.cc + -@$(CREATE_LINK) + +fifo.cc : ..\common\fifo.cc + -@$(CREATE_LINK) + +cdevTagMap.cc : ..\cdevTagMap\cdevTagMap.cc + -@$(CREATE_LINK) + +cdevMonitorTable.cc : ..\cdevMonitorTable\cdevMonitorTable.cc + -@$(CREATE_LINK) + + diff --git a/extensions/cdevGenericServer/cdevServer/cdevServer.cc b/extensions/cdevGenericServer/cdevServer/cdevServer.cc new file mode 100755 index 0000000..06ec51a --- /dev/null +++ b/extensions/cdevGenericServer/cdevServer/cdevServer.cc @@ -0,0 +1,692 @@ +#include "cdevServer.h" +#include "ClientAcceptor.h" +#include "ClientHandler.h" + +sig_atomic_t cdevServer::Finished = 0; +SignalManager cdevServer::SigManager; +cdevGenericServerTagDef cdevServer::tags; + +// ***************************************************************************** +// * This function is an interrupt handler that will be executed whenever the +// * program receives a SIGINT. When called it will set the finished flag to 1 +// * and trigger the termination of the program. +// ***************************************************************************** +static void SIGINT_handler (int signo) + { + cdevServer::Finished = 1; + signal(signo, SIGINT_handler); + } + + +// ***************************************************************************** +// * cdevServer::cdevServer : +// * This is the constructor for the class. It will post the listening +// * socket, establish registration with the name server and record all +// * other pertinent information. +// ***************************************************************************** +cdevServer::cdevServer (char * DomainName, char * ServerName, unsigned short Port, double Rate) + : cdevSessionManager(), + serverName (NULL), + acceptor (NULL), + timer (NULL), + status (UNINITIALIZED), + serverInfo (NULL) + { + // ********************************************************************* + // * Register the import method for the cdevMessage class with the + // * cdevPacket class. + // ********************************************************************* + cdevPacket::registerImportMethod(cdevMessage::CDEV_PACKET_VERSION, + cdevMessage::import); + + startServer(DomainName, ServerName, Port, Rate, 0); + } + +// ***************************************************************************** +// * cdevServer::cdevServer : +// * This is the do nothing constructor for the class. +// ***************************************************************************** +cdevServer::cdevServer ( void ) + : cdevSessionManager (), + serverName (NULL), + acceptor (NULL), + timer (NULL), + status (UNINITIALIZED), + serverInfo (NULL) + { + // ********************************************************************* + // * Register the import method for the cdevMessage class with the + // * cdevPacket class. + // ********************************************************************* + cdevPacket::registerImportMethod(cdevMessage::CDEV_PACKET_VERSION, + cdevMessage::import); + + } + +// ***************************************************************************** +// * cdevServer::~cdevServer : +// * This is the destructor for the object. It will close all listening +// * sockets and will delete all allocated items. +// ***************************************************************************** +cdevServer::~cdevServer ( void ) + { + outputError ( CDEV_SEVERITY_INFO, "CDEV Server", + "Server %s is Terminating...", + serverName); + + Reactor.extractHandler(this); + + if(timer!=NULL) delete timer; + if(serverName!=NULL) delete serverName; + if(acceptor!=NULL) delete acceptor; + } + + +// ***************************************************************************** +// * cdevServer::startServer : +// * This method will initialize a cdevServer within a given name, will +// * register it within the CDEV Name Server and will commence listening +// * for connections on the specified port. +// ***************************************************************************** +int cdevServer::startServer (char * DomainName, char * ServerName, unsigned short Port, double Rate, int searchForPort) + { + if(acceptor!=NULL) + { + delete acceptor; + acceptor=NULL; + } + if(timer) + { + delete timer; + timer=NULL; + } + if(serverName) + { + delete serverName; + serverName = NULL; + } + if(serverInfo) + { + delete serverInfo; + serverInfo = NULL; + } + + Reactor.extractHandler(this); + + setTimeoutRate(Rate); + serverName = strdup(ServerName); + status = UNINITIALIZED; + acceptor = new ClientAcceptor(*this); + + // ********************************************************************* + // * Attempt to open the acceptor to receive new connections. + // ********************************************************************* + if(searchForPort) Port = 0; + cdevInetAddr addr(Port); + int initialized=!(acceptor->open(addr)); + + // ********************************************************************* + // * Call getLocalAddress to retrieve the actual port number that was + // * opened. This value will differ from the specified port if... + // * 1) the user specified 0 for the port number -or- + // * 2) the user set the searchForPort flag to non-zero. + // ********************************************************************* + if(acceptor->getLocalAddress(addr)==0) Port = addr.getPortNum(); + else Port = (unsigned short)-1; + + // ********************************************************************* + // * ServerInfo must be created after the port has been searched for + // * and found. Otherwise, the server will report the original port + // * number rather than the actual port number. + // ********************************************************************* + serverInfo = new ServerInfo(DomainName, ServerName, Port); + + if(initialized) + { + // ************************************************************* + // * Register the acceptor with the Reactor. + // ************************************************************* + if(Reactor.registerHandler(acceptor, READ_MASK)!=-1) + { + // ***************************************************** + // * Register this event handler with the Reactor. + // ***************************************************** + if(Reactor.registerHandler(this, READ_MASK)!=-1) + { + // ********************************************* + // * Schedule the periodic timer if it is + // * greater than 0. + // ********************************************* + if(Rate <= 0.0 || + Reactor.registerTimer(this)!=-1) + { + // ************************************* + // * Install a name server timer to + // * continuously register this server + // * with the Name Server. + // ************************************* + timer = new cdevNameServerManager(Reactor, DomainName, ServerName, Port); + outputError (CDEV_SEVERITY_INFO, "CDEV Server", + "Server %s is operational and servicing requests...", + serverName); + } + else + { + outputError ( CDEV_SEVERITY_SEVERE, "CDEV Server", + "Server %s - Unable to register server timer with cdevReactor", + serverName); + status = CANT_REGISTER_TIMER; + } + } + else + { + outputError ( CDEV_SEVERITY_SEVERE, "CDEV Server", + "Server %s - Unable to register server handler with cdevReactor", + serverName); + status = CANT_REGISTER_SERVER; + } + } + else + { + outputError (CDEV_SEVERITY_SEVERE, "CDEV Server", + "Server %s - Unable to register listening service with cdevReactor", + serverName); + status = CANT_REGISTER_LISTENER; + } + } + else + { + outputError ( CDEV_SEVERITY_SEVERE, "CDEV Server", + "Server %s - Unable to open listening socket", + serverName); + status = CANT_OPEN_SOCKET; + } + + switch (status) + { + case CANT_REGISTER_TIMER: + Reactor.extractHandler(this); + + case CANT_REGISTER_SERVER: + Reactor.extractHandler(acceptor); + + case CANT_REGISTER_LISTENER: + case CANT_OPEN_SOCKET: + delete acceptor; + acceptor = NULL; + break; + + case SUCCESS: + default: + status = SUCCESS; + break; + } + + return status; + } + + +// *************************************************************************** +// * cdevServer::runServer : +// * This method is called to simultaneously execute all servers that +// * reside in the system. +// *************************************************************************** +void cdevServer::runServer ( void ) + { + SigManager.installDefaults(); + SigManager.installHandler (SIGINT, SIGINT_handler); + while (!Finished) Reactor.handleEvents (); + } + + +// ***************************************************************************** +// * cdevServer::registerClient : +// * This is the cdevMessage specific method that is used to send a +// * "register" message to the server. +// ***************************************************************************** +void cdevServer::registerClient ( short localID ) + { + cdevMessage message(localID,0,0,0,0,0,0,0,NULL,"register"); + cdevPacketBinary * packet = new cdevPacketBinary; + char * binary; + size_t binaryLen; + + message.streamOut (&binary, &binaryLen); + packet->attachData(binary, binaryLen); + inbound.enqueue (packet); + } + + +// ***************************************************************************** +// * cdevServer::unregisterClient : +// * This is the cdevMessage specific method that is used to send an +// * "unregister" message to the server. +// ***************************************************************************** +void cdevServer::unregisterClient ( short localID ) + { + cdevMessage message(localID,0,0,0,0,0,0,0,NULL,"unregister"); + cdevPacketBinary * packet = new cdevPacketBinary; + char * binary; + size_t binaryLen; + + message.streamOut (&binary, &binaryLen); + packet->attachData(binary, binaryLen); + inbound.enqueue (packet); + trigger.insertEvent(); + } + + +// ***************************************************************************** +// * cdevServer::newClientSession : +// * This method allows the caller to create a new ClientSession object. The +// * ClientSession object functions primarily as a pointer to the queue that +// * holds packets destined for a specific client, however, the developer +// * can create a subclass of the ClientSession that may be used to associate +// * additional, client specific information to the structure. +// * +// * The CLIPClientSession class allows the developer to associate a context +// * with the clientID. +// ***************************************************************************** +ClientSession * cdevServer::newClientSession ( int SocketID, int ClientID, int LocalID ) + { + return new CLIPClientSession (SocketID, ClientID, LocalID); + } + + +// ***************************************************************************** +// * cdevServer::newSocketSession : +// * This method allows the caller to create a new SocketSession object. The +// * SocketSession object functions primarily as a pointer to the queue that +// * holds packets destined for a specific socket, however, the developer +// * can create a subclass of the SocketSession that may be used to associate +// * additional, socket specific information to the structure. +// * +// * The CLIPSocketSession class allows the developer to associate a +// * context map and a tag table with the socket number. +// ***************************************************************************** +SocketSession * cdevServer::newSocketSession ( int SocketID ) + { + if(serverInfo) serverInfo->clientCnt++; + + return new CLIPSocketSession (SocketID); + } + +// ***************************************************************************** +// * cdevServer::deleteSocketSession : +// * This method is called to delete an existing socket session. +// ***************************************************************************** +void cdevServer::deleteSocketSession ( SocketSession *socket ) + { + if(socket) + { + if(serverInfo) + { + if(serverInfo->clientCnt>0) serverInfo->clientCnt--; + else serverInfo->clientCnt=0; + } + + sockets.remove(socket->getSocketID()); + delete socket; + } + } + +// ***************************************************************************** +// * cdevServer::dequeue : +// * This method provides a mechanism for the cdevServer object to only +// * dequeue packets that are of the type cdevMessage. +// ***************************************************************************** +int cdevServer::dequeue ( cdevMessage * &message ) + { + cdevPacket * packet = NULL; + + while(packet==NULL && cdevSessionManager::dequeue(packet)==0) + { + if(packet->getVersion()!=cdevMessage::CDEV_PACKET_VERSION) + { + delete packet; + packet = NULL; + } + else if(((cdevMessage *)packet)->getOperationCode()==CDEV_SERVER_OP) + { + processLocal((cdevMessage * &)packet); + delete packet; + packet = NULL; + } + } + + message = (cdevMessage *)packet; + return message==NULL?-1:0; + } + +// ***************************************************************************** +// * cdevServer::processLocal : +// * This method is called to process requests that are being transmitted +// * directly to the cdev Generic Server Engine to set or retrieve statistics +// * about the operation of the server or its clients. +// ***************************************************************************** +void cdevServer::processLocal ( cdevMessage * & message ) + { + CLIPClientSession * client = NULL; + CLIPSocketSession * socket = NULL; + + if((client = (CLIPClientSession *)findLocalClient(message->getClientID()))!=NULL) + { + socket = (CLIPSocketSession *)findSocket(client->getSocketID()); + } + if(!strcmp(message->getMessage(), "set ClientInfo")) + { + cdevData * data = message->getData(); + if(data && socket) socket->updateClientInfo(*data); + } + else if(!strcmp(message->getMessage(), "get ServerInfo")) + { + if(serverInfo) + { + message->setOperationCode(CDEV_NORMAL_OP); + message->setData(&serverInfo->getServerData(), 1); + } + else { + message->setOperationCode(CDEV_NORMAL_OP); + message->setCompletionCode(-1); + } + enqueue(message); + } + else if(!strcmp(message->getMessage(), "get ClientInfo")) + { + IntHashIterator iter(&sockets); + ClientHandler * handler = NULL; + int socketCnt = 0; + int index = 0; + cdevData result; + + iter.first(); + while(iter.data()!=NULL) + { + iter++; + socketCnt++; + } + if(socketCnt) + { + char ** username = new char *[socketCnt]; + char ** group = new char *[socketCnt]; + unsigned * uid = new unsigned [socketCnt]; + unsigned * gid = new unsigned [socketCnt]; + unsigned * pid = new unsigned [socketCnt]; + char ** program = new char *[socketCnt]; + char ** commandline = new char *[socketCnt]; + unsigned * starttime = new unsigned [socketCnt]; + unsigned * connecttime = new unsigned [socketCnt]; + char ** host = new char *[socketCnt]; + char ** os = new char *[socketCnt]; + char ** osrelease = new char *[socketCnt]; + char ** osversion = new char *[socketCnt]; + char ** machine = new char *[socketCnt]; + char ** shell = new char *[socketCnt]; + unsigned * socketNum = new unsigned[socketCnt]; + unsigned * sendPktCnt = new unsigned[socketCnt]; + unsigned * recvPktCnt = new unsigned[socketCnt]; + + iter.first(); + while(indexgetUsername(); + group[index] = socket->getGroup(); + uid[index] = socket->getUid(); + gid[index] = socket->getGid(); + pid[index] = socket->getPid(); + program[index] = socket->getProgram(); + commandline[index] = socket->getCommandLine(); + starttime[index] = (unsigned)socket->getStartTime(); + connecttime[index] = (unsigned)socket->getConnectTime(); + host[index] = socket->getHost(); + os[index] = socket->getOs(); + osrelease[index] = socket->getOsRelease(); + osversion[index] = socket->getOsVersion(); + machine[index] = socket->getMachine(); + shell[index] = socket->getShell(); + socketNum[index] = socket->getSocketID(); + if(Reactor.getHandler(socketNum[index], (cdevEventHandler *&)handler)==0) + { + sendPktCnt[index] = handler->getPacketsSent(); + recvPktCnt[index] = handler->getPacketsRecv(); + } + else { + sendPktCnt[index] = 0; + recvPktCnt[index] = 0; + } + index++; + iter++; + } + + result.insert("username", username, socketCnt); delete username; + result.insert("group", group, socketCnt); delete group; + result.insert("uid", uid, socketCnt); delete uid; + result.insert("gid", gid, socketCnt); delete gid; + result.insert("pid", pid, socketCnt); delete pid; + result.insert("program", program, socketCnt); delete program; + result.insert("commandline", commandline, socketCnt); delete commandline; + result.insert("starttime", starttime, socketCnt); delete starttime; + result.insert("connecttime", connecttime, socketCnt); delete connecttime; + result.insert("host", host, socketCnt); delete host; + result.insert("os", os, socketCnt); delete os; + result.insert("osrelease", osrelease, socketCnt); delete osrelease; + result.insert("osversion", osversion, socketCnt); delete osversion; + result.insert("machine", machine, socketCnt); delete machine; + result.insert("shell", shell, socketCnt); delete shell; + result.insert("socket", socketNum, socketCnt); delete socketNum; + result.insert("sendPktCnt", sendPktCnt, socketCnt); delete sendPktCnt; + result.insert("recvPktCnt", recvPktCnt, socketCnt); delete recvPktCnt; + } + message->setOperationCode(CDEV_NORMAL_OP); + message->setData(&result, 1); + enqueue(message); + } + } + +// ***************************************************************************** +// * cdevServer::decodePacket : +// * This method is used to perform preprocessing on a newly dequeued binary +// * packet before it is provided to the caller. This method allows the +// * developer to perform special preparations on the packet before providing +// * it to the caller. +// ***************************************************************************** +cdevPacket * cdevServer::decodePacket( cdevPacketBinary * input ) + { + cdevPacket * packet = NULL; + + if(input!=NULL) + { + short version; + input->getVersion(version); + switch (version) + { + // ***************************************************** + // * If it is a cdevMessage object, I want to call the + // * cdevMessage specific decodePacket method. + // ***************************************************** + case cdevMessage::CDEV_PACKET_VERSION: + packet = decodePacket ((cdevMessage *)cdevPacket::import(*input)); + break; + + // ***************************************************** + // * Use the cdevSessionManager::decodePacket method + // * to handle any other type of packet. + // ***************************************************** + default: + packet = cdevSessionManager::decodePacket(input); + break; + } + if(serverInfo) serverInfo->recvPktCnt++; + } + return packet; + } + +// ***************************************************************************** +// * cdevServer::decodePacket : +// * This decodePacket method is designed specifically to preprocess the +// * data associated with a cdevMessage object. +// ***************************************************************************** +cdevPacket * cdevServer::decodePacket (cdevMessage * message ) + { + CLIPClientSession * client = NULL; + CLIPSocketSession * socket = NULL; + + if(message!=NULL && + (client = (CLIPClientSession *)findLocalClient(message->getClientID()))!=NULL && + (socket = (CLIPSocketSession *)findSocket(client->getSocketID()))!=NULL) + { + // ************************************************************* + // * If a tagMap has been provided... use it to update + // * the tagMap stored in the SocketSession object. + // ************************************************************* + if(message->getTagMap()!=NULL) + { + socket->TagMap().updateTagMap(*message->getTagMap()); + message->setTagMap(NULL); + } + + // ************************************************************* + // * Pass the data and context objects through the tag map to + // * convert their tags from the remote integers to the local + // * integers. + // ************************************************************* + if(message->getData()!=NULL) + socket->TagMap().remoteToLocal(*message->getData()); + if(message->getContext()!=NULL) + socket->TagMap().remoteToLocal(*message->getContext()); + + // ************************************************************* + // * If a context has been provided by the client side + // * of the connection - perform the following steps... + // * + // * 1) Add the context to the cdevContextMap for this + // * socketID if it does not already exist, and + // * obtain the index that identifies the new + // * context. + // * + // * 2) Delete the context from within the message. + // * + // * 3) Set the context within the message to the + // * current context that is specified in the + // * ClientSession object. + // * + // * 4) Set the saveContext flag in the message to + // * prevent its inadvertant destruction when the + // * message is deleted. + // ************************************************************* + if(message->getContext()!=NULL) + { + cdevData * lastContext = client->getContext(); + if(lastContext==NULL || *lastContext!=*message->getContext()) + { + int contextID = socket->ContextMap().insert(*message->getContext()); + client->setContext(socket->ContextMap().find(contextID)); + } + } + message->setContext(client->getContext(), 1); + + // ************************************************************* + // * Toggle the local and foreign data indices. + // ************************************************************* + unsigned int index = message->getForeignDataIndex(); + message->setForeignDataIndex(message->getLocalDataIndex()); + message->setLocalDataIndex (index); + } + + return message; + } + + +// ***************************************************************************** +// * cdevSessionManager::encodePacket : +// * This method is used to perform postprocessing on a packet that has been +// * enqueued to be sent to a client. This method allows the developer to +// * perform special preparations on the packet before providing it to the +// * client. +// ***************************************************************************** +cdevPacketBinary * cdevServer::encodePacket ( cdevPacket * input ) + { + cdevPacketBinary * packet = NULL; + + if(input!=NULL) + { + switch(input->getVersion()) + { + case cdevMessage::CDEV_PACKET_VERSION: + packet = encodePacket ((cdevMessage *)input); + break; + + default: + packet = cdevSessionManager::encodePacket(input); + break; + } + if(serverInfo) serverInfo->sendPktCnt++; + } + return packet; + } + + +// ***************************************************************************** +// * cdevServer::encodePacket : +// * This encodePacket method is designed specifically to postprocess the +// * data associated with a cdevMessage object. +// ***************************************************************************** +cdevPacketBinary * cdevServer::encodePacket (cdevMessage * message ) + { + cdevPacketBinary * result = NULL; + CLIPClientSession * client = NULL; + CLIPSocketSession * socket = NULL; + + if(message!=NULL && + message->getClientID()>0 && + message->getTransIndex()>0 && + (client = (CLIPClientSession *)findLocalClient(message->getClientID()))!=NULL && + (socket = (CLIPSocketSession *)findSocket(client->getSocketID()))!=NULL) + { + char * binary = NULL; + size_t binaryLen = 0; + static cdevMessage outBound; + + // ************************************************************* + // * Remap the data to its foreign design. + // ************************************************************* + if(message->getData()!=NULL) + socket->TagMap().localToRemote(*message->getData()); + + // ************************************************************* + // * Transfer the critical data items into the class. Note that + // * we are not returning the deviceList, message, context, + // * cancelTransIndex, or operationCode with the return packet. + // * + // * Also note that the cdevData object is marked as permanent + // * and is using a pointer to the same cdevData object that is + // * in the message object. + // ************************************************************* + outBound.clear(); + outBound.setClientID (client->getClientID()&0xFFFF); + outBound.setTransIndex (message->getTransIndex()); + outBound.setLocalDataIndex (message->getForeignDataIndex()); + outBound.setForeignDataIndex (message->getLocalDataIndex()); + outBound.setOperationCode (message->getOperationCode()); + outBound.setCompletionCode (message->getCompletionCode()); + outBound.setData (message->getData(), 1); + + // ************************************************************* + // * Create a binary stream from the cdevMessage object and then + // * place it into the outbound queue system. + // ************************************************************* + outBound.streamOut(&binary, &binaryLen); + outBound.clear (); + + result = new cdevPacketBinary; + result->attachData(binary, binaryLen); + + // ************************************************************* + // * Remap the data to its local design. + // ************************************************************* + if(message->getData()!=NULL) + socket->TagMap().remoteToLocal(*message->getData()); + } + return result; + } + diff --git a/extensions/cdevGenericServer/cdevServer/cdevServer.h b/extensions/cdevGenericServer/cdevServer/cdevServer.h new file mode 100755 index 0000000..ec53261 --- /dev/null +++ b/extensions/cdevGenericServer/cdevServer/cdevServer.h @@ -0,0 +1,120 @@ +#if !defined (_CDEV_SERVER_H_) +#define _CDEV_SERVER_H_ + +#include "SignalManager.h" +#include "cdevServerTools.h" +#include "cdevMessage.h" +#include "cdevContextMap.h" +#include "cdevTagMap.h" +#include "ClientInfo.h" +#include "ServerInfo.h" +#include "cdevGenericServerTags.h" + +// ***************************************************************************** +// * class CLIPClientSession : +// * +// * This class also allows the server to associate certain data with a +// * specific client... +// * +// * context: This is a pointer to the most recently used context from the +// * cdevContextMap. +// ***************************************************************************** +class GENERIC_SERVER_API CLIPClientSession : public ClientSession +{ +private: + cdevData *context; + +public: + CLIPClientSession ( int SocketID, int ClientID, int LocalID ) + : ClientSession(SocketID, ClientID, LocalID), + context(NULL) + { + } + virtual ~CLIPClientSession ( void ) { } + cdevData * getContext ( void ) { return context; } + void setContext ( cdevData * cxt ) { context = cxt; } +}; + + +// ***************************************************************************** +// * class CLIPSocketSession : +// * +// * This class allows the developer to associate additional information with +// * a particular socket... +// * +// * contextMap : a table of cdevData contexts that can be retrieved by index +// * +// * tagMap : the table for mapping cdevData tags from the remote system +// * to the tag table associated with this system. +// ***************************************************************************** +class GENERIC_SERVER_API CLIPSocketSession : public SocketSession, public ClientInfoStruct +{ +private: + cdevContextMap contextMap; + cdevTagMap tagMap; + +public: + CLIPSocketSession ( int SocketID ) + : SocketSession ( SocketID ) + { + } + virtual ~CLIPSocketSession ( void ) { } + cdevContextMap & ContextMap ( void ) { return contextMap; } + cdevTagMap & TagMap ( void ) { return tagMap; } +}; + + +// ***************************************************************************** +// * cdevServer : +// * This is the cdevServer class. It is responsible for establishing a +// * listening socket, and then responding to all incoming and outgoing +// * messages. +// ***************************************************************************** +class GENERIC_SERVER_API cdevServer : public cdevSessionManager +{ +public: + typedef enum { SUCCESS = 0, + UNINITIALIZED, + CANT_OPEN_SOCKET, + CANT_REGISTER_LISTENER, + CANT_REGISTER_SERVER, + CANT_REGISTER_TIMER + } ServerInitStatus; + +protected: + char * serverName; + class ClientAcceptor * acceptor; + cdevNameServerManager * timer; + ServerInitStatus status; + ServerInfo * serverInfo; + +public: + static cdevGenericServerTagDef tags; + static SignalManager SigManager; + static sig_atomic_t Finished; + + static void runServer (void); + + cdevServer (char * DomainName, char * ServerName, unsigned short Port, double Rate); + cdevServer (void); + virtual ~cdevServer (void); + int startServer (char * DomainName, char * ServerName, unsigned short Port, double Rate, int searchForPort=0); + + virtual void registerClient ( short localID ); + virtual void unregisterClient ( short localID ); + + virtual ClientSession * newClientSession ( int SocketID, int ClientID, int LocalID ); + virtual SocketSession * newSocketSession ( int SocketID ); + virtual void deleteSocketSession ( SocketSession *socket ); + + virtual int dequeue (cdevMessage * &message); + void processLocal (cdevMessage * &message); + virtual cdevPacket * decodePacket (cdevPacketBinary * input); + virtual cdevPacket * decodePacket (cdevMessage * message); + virtual cdevPacketBinary * encodePacket (cdevPacket * input); + virtual cdevPacketBinary * encodePacket (cdevMessage * message); + virtual int operational (void) { return (status==0)?1:0; } + virtual ServerInitStatus getInitStatus(void) { return status; } +}; + +#endif /* _CDEV_SERVER_H_ */ diff --git a/extensions/cdevGenericServer/cdevServer/cdevServerTools.cc b/extensions/cdevGenericServer/cdevServer/cdevServerTools.cc new file mode 100755 index 0000000..e418f02 --- /dev/null +++ b/extensions/cdevGenericServer/cdevServer/cdevServerTools.cc @@ -0,0 +1,403 @@ +#include "cdevServerTools.h" + + +// **************************************************************************** +// cdevSimpleTimer::cdevSimpleTimer : +// Constructor. +// **************************************************************************** +cdevSimpleTimer::cdevSimpleTimer ( cdevReactor & Reactor, double Rate) + { + setTimeoutRate(Rate); + if(Reactor.registerTimer (this) == -1) + { + outputError ( CDEV_SEVERITY_SEVERE, "cdevSimpleTimer", + "Unable to register timer with cdevReactor"); + } + } + +// **************************************************************************** +// cdevSimpleTimer::~cdevSimpleTimer : +// Destructor. +// **************************************************************************** +cdevSimpleTimer::~cdevSimpleTimer ( void ) + { + if(reactor) reactor->extractHandler(this); + handleClose(); + } + +// **************************************************************************** +// cdevSimpleTimer::handle_timeout : +// Called when the timer expires. +// **************************************************************************** +int cdevSimpleTimer::handleTimeout(void) + { + return execute(); + } + + +// ***************************************************************************** +// * cdevNameServerManager::cdevNameServerManager : +// * This method will read the CDEV_NAME_SERVER environment variable to +// * obtain a list of one or more cdev name servers that should be notified +// * that this server is operational. The class will create a +// * cdevNameServerHandler event handler to manage the connection to each of +// * the specified name servers. If a connection is lost to one of the +// * name servers, the cdevNameServerManager will attempt periodically to +// * reconnect to the specific name server. +// ***************************************************************************** +cdevNameServerManager::cdevNameServerManager ( cdevReactor & Reactor, + char * DomainName, + char * ServerName, + unsigned short ServerPort ) + : domainName(strdup(DomainName)), + serverName(strdup(ServerName)), + serverPort(ServerPort), + nameServerList(NULL), + nameServerHandlers(NULL), + nameServerCnt(0) + { + // ********************************************************************* + // * Prior to establishing any connections, the class must first install + // * all of the necessary data into the serverInfo and updateInfo + // * objects. + // ********************************************************************* + char * userName = getenv("USER"); + char hostname[255]; + struct hostent * hostPtr; + struct timeval tv; + + gettimeofday (&tv); + gethostname(hostname, 255); + hostPtr = gethostbyname(hostname); + + serverInfo.insert ("name", serverName); + serverInfo.insert ("domain", domainName); + serverInfo.insert ("host", (char *)hostPtr->h_name); + serverInfo.insert ("owner", userName?userName:(char *)"UNKNOWN"); + serverInfo.insert ("time", (long)tv.tv_sec); + serverInfo.insert ("port", (long)serverPort); + serverInfo.insert ("pid", getpid ()); + updateInfo.insert ("name", serverName); + updateInfo.insert ("domain", domainName); + + // ********************************************************************* + // * First obtain a list of name servers from the CDEV_NAME_SERVER + // * environment variable. If this list is empty, then report an + // * error once and then never call the handler again. + // ********************************************************************* + char * nsList = getenv("CDEV_NAME_SERVER"); + int idx; + int length; + + if(nsList!=NULL) + { + char * nsPtr = nsList; + char * endPtr = nsList; + + // ************************************************************* + // * Determine the number of name servers that have been + // * defined in the CDEV_NAME_SERVER environment variable. + // ************************************************************* + while(*nsPtr==':' && *nsPtr!=0) nsPtr++; + if(*nsPtr!=0) + { + nameServerCnt = 1; + while(nsPtr!=NULL && *nsPtr!=0) + { + if((nsPtr = strchr(nsPtr, ':'))!=NULL) + { + while(*(++nsPtr)==':' && *nsPtr!=0); + if(*nsPtr!=0) nameServerCnt++; + } + } + } + + // ************************************************************* + // * Copy each of the defined cdev name server host names into + // * the nameServerList. + // ************************************************************* + if(nameServerCnt>0) + { + nameServerList = new char *[nameServerCnt]; + nameServerHandlers = new cdevNameServerHandler *[nameServerCnt]; + + for(nsPtr = nsList, idx=0; idx No name servers have been specified in the CDEV_NAME_SERVER", + " => environment variable.", + " => This server WILL NOT be registered with any name servers..."); + } + // ********************************************************************* + // * Otherwise, set all of the cdevNameServerHandler pointers to NULL + // * so that they will be connected when the execute timeout method + // * is called. + // ********************************************************************* + else { + for(idx=0; idxconnect(nameServerList[idx], RSVC_SERVER_PORT, 2.0)!=RSVC_SUCCESS) + { + outputError ( CDEV_SEVERITY_ERROR, "CDEV Name Server Manager", + "Failed to connect to name server on host %s", + nameServerList[idx]); + error = -1; + } + else if(udpClient->connect(nameServerList[idx], RSVC_SERVER_PORT+1024)!=RSVC_SUCCESS) + { + outputError ( CDEV_SEVERITY_ERROR, "CDEV Name Server Manager", + "Failed to open UDP port to name server on host %s", + nameServerList[idx]); + error = -1; + } + else if(client->insertValue ("cdevServers", serverInfo, rsvcCallback, nameServerList[idx], 1)!=RSVC_SUCCESS) + { + outputError ( CDEV_SEVERITY_ERROR, "CDEV Name Server Manager", + "Error transmitting to name server on host %s", + nameServerList[idx]); + error = -1; + } + + if(!error) nameServerHandlers[idx] = new cdevNameServerHandler(*this, *reactor, idx, client, udpClient); + else { + client->disconnect(); + udpClient->disconnect(); + delete client; + delete udpClient; + } + } + } + return 0; + } + +// ***************************************************************************** +// * cdevNameServerManager::unregisterHandler: +// * This method is called whenever a cdevNameServerHandler needs to +// * unregister itself from the cdevNameServerManager. The handlers index +// * will be set to 0 and the connection will be reestablished the next time +// * the handleTimeout method is called. +// ***************************************************************************** +void cdevNameServerManager::unregisterHandler ( size_t index ) + { + if(index < nameServerCnt) nameServerHandlers[index] = NULL; + } + + +// ***************************************************************************** +// * cdevNameServerManager::rsvcCallback : +// * This is the method that is called when the register server method +// * is executed. +// ***************************************************************************** +void cdevNameServerManager::rsvcCallback (int status, void* arg, rsvcData* /* data */) + { + char * nameServer = (char *)arg; + + if (status != RSVC_SUCCESS) + { + #ifndef _WIN32 + fprintf(stderr, "CDEV Name Server Manager Error: %s %s\n", + "Failed to register with name server on host", + nameServer?nameServer:"UNKNOWN"); + #endif + } + } + + +// ***************************************************************************** +// * cdevNameServerHandler::cdevNameServerHandler : +// * This is the constructor for the cdevNameServerHandler class. It is +// * called by the cdevNameServerManager when a new cdevNameServerHandler +// * must be created to communicate with a name server. The connected +// * rsvcClient and rsvcUdpClient objects are provided to the class. +// ****************************************************************************** +cdevNameServerHandler::cdevNameServerHandler ( cdevNameServerManager & Manager, + cdevReactor & Reactor, + int index, + rsvcClient * tcpClient, + rsvcUdpClient * udpClient ) + : nameServerTCP(tcpClient), nameServerUDP(udpClient), + nameServerIndex(index), nameServerManager(Manager) + { + setTimeoutRate(5.0); + setMask(WRITE_MASK); + Reactor.registerHandler(this, WRITE_MASK); + Reactor.registerTimer (this); + } + +// ***************************************************************************** +// * cdevNameServerHandler::~cdevNameServerHandler : +// * This is the destructor for the class. this method is responsible for +// * disconnecting and closing the tcp and udp client connections and +// * sending notification to the cdevNameServerManager that it is +// * terminating. +// ***************************************************************************** +cdevNameServerHandler::~cdevNameServerHandler ( void ) + { + nameServerTCP->disconnect(); + nameServerUDP->disconnect(); + delete nameServerTCP; + delete nameServerUDP; + if(reactor) reactor->extractHandler(this); + nameServerManager.unregisterHandler(nameServerIndex); + } + +// ***************************************************************************** +// * cdevNameServerHandler::handleInput : +// * This method is called whenever data is ready to be read from the +// * nameServerTCP rsvcClient connection. +// ***************************************************************************** +int cdevNameServerHandler::handleInput ( void ) + { + return (nameServerTCP->pendIO()==RSVC_IOERROR)?-1:0; + } + +// ***************************************************************************** +// * cdevNameServerHandler::handleOutput : +// * This method is called whenever data is ready to be written to the +// * nameServerTCP rsvcClient connection. +// ***************************************************************************** +int cdevNameServerHandler::handleOutput ( void ) + { + setMask(READ_MASK); + return (nameServerTCP->pendIO()==RSVC_IOERROR)?-1:0; + } + +// ***************************************************************************** +// * cdevNameServerHandler::handleTimeout : +// * This method is called every five seconds to allow the object to emit +// * a UDP packet to the name server to notify it that the server is alive. +// ***************************************************************************** +int cdevNameServerHandler::handleTimeout ( void ) + { + if(nameServerUDP->update(*nameServerManager.getUpdateInfo())!=RSVC_SUCCESS) + { + outputError(CDEV_SEVERITY_ERROR, "CDEV Name Server Handler", + "Failed to update name server on host %s", + nameServerManager.getHostName(nameServerIndex)); + } + return 0; + } + +// ***************************************************************************** +// * cdevNameServerHandler::getHandle : +// * This method allows the caller to obtain the file handle that is being +// * used by the nameServerTCP rsvcClient connection. This handle is used +// * by the cdevReactor to detect when an event has occured. +// ***************************************************************************** +int cdevNameServerHandler::getHandle ( void ) const + { + return nameServerTCP->getFd(); + } + + +#ifndef DONT_SUPPORT_CDEV_CALLS + // ********************************************************************* + // * cdevSystemHandler::cdevSystemHandler : + // * This is the constructor for the cdevSystemHandler object. + // ********************************************************************* + cdevSystemHandler::cdevSystemHandler (cdevReactor & Reactor, + double pollRate, + cdevSystem & System) + : cdevSimpleTimer(Reactor, pollRate), system(System) + { + execute(); + } +#endif + +#ifndef DONT_SUPPORT_CDEV_CALLS + // ********************************************************************* + // * cdevSystemHandler::~cdevSystemHandler : + // * This is the destructor for the cdevSystemHandler object. + // ********************************************************************* + cdevSystemHandler::~cdevSystemHandler (void) + { + } +#endif + +#ifndef DONT_SUPPORT_CDEV_CALLS + // ********************************************************************* + // * cdevSystemHandler::execute : + // * This is the method that is executed when the specified timer + // * expires. + // ********************************************************************* + int cdevSystemHandler::execute (void) + { + system.poll(); + return 0; + } +#endif diff --git a/extensions/cdevGenericServer/cdevServer/cdevServerTools.h b/extensions/cdevGenericServer/cdevServer/cdevServerTools.h new file mode 100755 index 0000000..8703e8b --- /dev/null +++ b/extensions/cdevGenericServer/cdevServer/cdevServerTools.h @@ -0,0 +1,113 @@ +#if !defined (_CDEV_SERVER_TOOLS_H_) +#define _CDEV_SERVER_TOOLS_H_ + +#ifndef DONT_SUPPORT_CDEV_CALLS + #include "cdevSystemEventHandler.h" +#endif + +#include "cdevSessionManager.h" +#include "cdevMessage.h" +#include "rsvcClient.h" +#include "rsvcUdpClient.h" + +// ***************************************************************************** +// * This is the cdevSimpleTimer class. The user specifies a function, a rate +// * and a void * data pointer. The ACE_Reactor will then call the function +// * each time the period of time expires. +// ***************************************************************************** +class GENERIC_SERVER_API cdevSimpleTimer : public cdevEventHandler, public ErrorReporter +{ +public: + cdevSimpleTimer ( cdevReactor & Reactor, double Rate = 1.0 ); + ~cdevSimpleTimer ( void ); + virtual int handleTimeout (void); + virtual int execute (void) = 0; +}; + + +// ***************************************************************************** +// * class cdevNameServerManager: +// * This class will extract the list of cdev Name Servers from the +// * CDEV_NAME_SERVER environment variable and will create a collection +// * of cdevNameServerHandler objects that will manage the connections +// * to them. These cdevNameServerHandler objects will register the +// * server with the name server and will send updates every five seconds. +// * If the connection to the specific name server is lost, the +// * cdevNameServer handler will call the unregisterHandler method to +// * terminate the connection and before being deleted. This object +// * will then attempt to reestablish the connection periodically. +// ***************************************************************************** +class GENERIC_SERVER_API cdevNameServerManager : public cdevEventHandler, public ErrorReporter +{ +protected: + char ** nameServerList; + class cdevNameServerHandler ** nameServerHandlers; + size_t nameServerCnt; + rsvcData serverInfo; + rsvcData updateInfo; + char * serverName; + char * domainName; + unsigned short serverPort; + +public: + cdevNameServerManager ( cdevReactor & Reactor, char * DomainName, char * ServerName, unsigned short port); + ~cdevNameServerManager ( void ); + + static void rsvcCallback (int status, void* arg, rsvcData* data); + + virtual int handleTimeout ( void ); + void unregisterHandler ( size_t index ); + rsvcData * getServerInfo ( void ) { return &serverInfo; } + rsvcData * getUpdateInfo ( void ) { return &updateInfo; } + char * getHostName ( size_t index ) { return (index + +cdevReactor cdevSessionManager::Reactor; +IntHash cdevSessionManager::localIdx; + +// ***************************************************************************** +// * ClientSession::ClientSession : +// * This method serves only to initialize the internals of the class. +// ***************************************************************************** +ClientSession::ClientSession ( int SocketID, int ClientID, int LocalID ) + : socketID(SocketID), clientID(ClientID), localID(LocalID) + { + } + +// ***************************************************************************** +// * ClientSession::~ClientSession : +// * This method deletes all unprocessed binary packets that are stored +// * within the queue. +// ***************************************************************************** +ClientSession::~ClientSession ( void ) + { + } + +// ***************************************************************************** +// * SocketSession::SocketSession : +// * This is the constructor for the SocketSession object, it serves only +// * to initialize internal variables. +// ***************************************************************************** +SocketSession::SocketSession( int SocketID ) + : FifoQueue(), socketID(SocketID) + { + } + + +// ***************************************************************************** +// * SocketSession::~SocketSession : +// * This method deletes all unprocessed binary packets that are stored +// * within the queue. +// ***************************************************************************** +SocketSession::~SocketSession ( void ) + { + char * binary; + size_t binaryLen; + + while(dequeue(&binary, &binaryLen)==0) delete binary; + } + + +// ***************************************************************************** +// * cdevSessionManager::~cdevSessionManager : +// * This method deletes all entries from the client and socket queues +// * and then deletes all queue objects... +// ***************************************************************************** +cdevSessionManager::~cdevSessionManager ( void ) + { + int socketID; + int clientID; + IntHashIterator clientIter(&clients); + IntHashIterator socketIter(&sockets); + ClientSession * clientPtr; + SocketSession * socketPtr; + cdevPacketBinary * packet; + + while((packet = (cdevPacketBinary *)inbound.dequeue())!=NULL) + { + delete packet; + } + + clientIter.first(); + while((clientPtr=(ClientSession *)clientIter.data())!=NULL) + { + clientID = clientPtr->getClientID(); + clientIter++; + removeClient(clientID, 0); + } + + socketIter.first(); + while((socketPtr=(SocketSession *)socketIter.data())!=NULL) + { + socketID = socketIter.key(); + socketIter++; + removeSocket(socketID); + } + } + + +// ***************************************************************************** +// * cdevSessionManager::newClientSession : +// * This method allows the caller to create a new ClientSession object. The +// * ClientSession object functions primarily as a pointer to the queue that +// * holds packets destined for a specific client, however, the developer +// * can create a subclass of the ClientSession that may be used to associate +// * additional, client specific information to the structure. +// ***************************************************************************** +ClientSession * cdevSessionManager::newClientSession ( int SocketID, int ClientID, int LocalID ) + { + return new ClientSession (SocketID, ClientID, LocalID); + } + + +// ***************************************************************************** +// * cdevSessionManager::newSocketSession : +// * This method allows the caller to create a new SocketSession object. The +// * SocketSession object functions primarily as a pointer to the queue that +// * holds packets destined for a specific socket, however, the developer +// * can create a subclass of the SocketSession that may be used to associate +// * additional, socket specific information to the structure. +// ***************************************************************************** +SocketSession * cdevSessionManager::newSocketSession ( int SocketID ) + { + return new SocketSession (SocketID); + } + +// ***************************************************************************** +// * cdevSessionManager::deleteSocketSession : +// * This method is called to delete a SocketSession object. +// ***************************************************************************** +void cdevSessionManager::deleteSocketSession ( SocketSession *socket ) + { + if(socket) + { + sockets.remove(socket->getSocketID()); + delete socket; + } + } + +// ***************************************************************************** +// * cdevSessionManager::findLocalClient : +// * This method allows the caller to locate a ClientSession using the local +// * client identifier that is assigned by the cdevSessionManager class. +// ***************************************************************************** +ClientSession * cdevSessionManager::findLocalClient( short localID ) + { + return (ClientSession *)localIdx.find(localID); + } + +// ***************************************************************************** +// * cdevSessionManager::findClient : +// * This method allows the caller to locate a ClientSession using its +// * clientID. +// ***************************************************************************** +ClientSession * cdevSessionManager::findClient( int clientID ) + { + return (ClientSession *)clients.find(clientID); + } + +// ***************************************************************************** +// * cdevSessionManager::findSocket : +// * This method allows the caller to locate a SocketSession using its +// * socketID. +// ***************************************************************************** +SocketSession * cdevSessionManager::findSocket( int socketID ) + { + return (SocketSession *)sockets.find(socketID); + } + +// ***************************************************************************** +// * cdevSessionManager::addClient : +// * This method allows the caller to add a new clientID and construct a +// * ClientSession object for it. +// * +// * The socketID must have already been registered using the addSocket +// * method. If the clientID already exists or if an error occurs NULL will +// * be returned. +// ***************************************************************************** +ClientSession * cdevSessionManager::addClient( int socketID, int clientID ) + { + ClientSession * session = NULL; + + if(findSocket(socketID)!=NULL && findClient(clientID)==NULL) + { + short localID = getNextLocalID(); + if(localID>0 && + (session = newClientSession(socketID, clientID, localID))!=NULL) + { + clients.insert (clientID, session); + localIdx.insert((int)localID, session); + } + } + return session; + } + +// ***************************************************************************** +// * cdevSessionManager::addSocket : +// * This method allows the caller to add a new socketID and construct a +// * SocketSession object to service it. +// * +// * This function will fail if the socketID has already been registered... +// * On failure this method will return NULL. +// ***************************************************************************** +SocketSession * cdevSessionManager::addSocket ( int socketID ) + { + SocketSession * session = NULL; + if(findSocket(socketID)==NULL && + (session = newSocketSession(socketID))!=NULL) + { + sockets.insert(socketID, session); + } + return session; + } + +// ***************************************************************************** +// * cdevSessionManager::removeClient : +// * This method will remove the specified clientID from the clients list +// * and will delete the associated ClientSession object. +// ***************************************************************************** +void cdevSessionManager::removeClient ( int clientID, int unregisterFlag) + { + ClientSession * session; + + if((session = (ClientSession *)clients.find(clientID))!=NULL) + { + // ***************************************************** + // * Submit an unregister command to notify the server + // ***************************************************** + if(unregisterFlag) unregisterClient(session->getLocalID()); + + localIdx.remove((int)session->getLocalID()); + clients.remove (clientID); + delete session; + } + } + + +// ***************************************************************************** +// * cdevSessionManager::removeSocket : +// * This method will remove the specified socketID from the sockets list +// * and will delete the associated SocketSession object. It will then +// * ascend the clients list and will remove all ClientSessions that are +// * associated with the socketID. +// ***************************************************************************** +void cdevSessionManager::removeSocket ( int socketID ) + { + cdevEventHandler * handler = NULL; + SocketSession * socket; + ClientSession * client; + int clientID; + + if(Reactor.getHandler(socketID, handler)==0 && handler!=NULL) + { + delete handler; + } + + if((socket = (SocketSession *)sockets.find(socketID))!=NULL) + { + IntHashIterator clientIter(&clients); + clientIter.first(); + while((client=(ClientSession *)clientIter.data())!=NULL) + { + if(client->getSocketID()==socketID) + { + clientID = client->getClientID(); + clientIter++; + removeClient(clientID); + } + else clientIter++; + } + + deleteSocketSession(socket); + } + } + +// ***************************************************************************** +// * cdevSessionManager::getNextLocalID : +// * This method allows the caller to retrieve a unique localID to be +// * assigned to a client. The nextLocalID value is automatically +// * incremented. +// ***************************************************************************** +short cdevSessionManager::getNextLocalID ( void ) + { + static short nextLocalID = 0; + short startingPoint = nextLocalID; + ClientSession *session = NULL; + + if(nextLocalID>=32767) nextLocalID = 1; + else nextLocalID++; + + startingPoint = nextLocalID; + + do { + session=(ClientSession *)localIdx.find((int)nextLocalID); + if(session!=NULL) + { + if(nextLocalID>=32767) nextLocalID = 1; + else nextLocalID++; + } + } while(session!=NULL && nextLocalID!=startingPoint); + + return session==NULL?nextLocalID:-1; + } + +// ***************************************************************************** +// * cdevSessionManager::enqueue : +// * This method is used to enqueue a binary packet into the inbound +// * fifoQueue. This method is called by the client handler objects. +// * +// * The binary data item becomes the property of the queue and should not +// * be accessed later by the caller. +// ***************************************************************************** +int cdevSessionManager::enqueue( int socketID, char * binary, unsigned binaryLen ) + { + int result = -1; + SocketSession * socket = NULL; + ClientSession * client = NULL; + cdevPacketBinary * packet = new cdevPacketBinary; + + // ********************************************************************* + // * Make sure its a valid packet. + // ********************************************************************* + if(packet->streamIn(binary, binaryLen)==0) + { + // ************************************************************* + // * Add the socketID if it does not already exist. + // ************************************************************* + if((socket = findSocket(socketID))==NULL) + { + socket = addSocket(socketID); + } + + // ************************************************************* + // * Combine the (short)clientID and the (short)socketID to + // * create a unique identifier for this client. + // * + // * < HIGH WORD > < LOW WORD > + // * SSSSSSSS CCCCCCCCC + // ************************************************************* + short packetClientID; + int clientID; + + packet->getClientID(packetClientID); + clientID = ((socketID<<16)|packetClientID); + + // ************************************************************* + // * Add a clientID if it does not already exist. + // ************************************************************* + if((client = findClient(clientID))==NULL && + (client = addClient(socketID, clientID))!=NULL) + { + registerClient ( client->getLocalID() ); + } + + // ************************************************************* + // * This would only fail if the clientID had already been used + // * by another socket. + // ************************************************************* + if(client!=NULL && client->getSocketID()==socketID) + { + result = 0; + + // ***************************************************** + // * At this point everything necessary is known to + // * submit the packet for processing... + // ***************************************************** + + // ***************************************************** + // * Set the clientID to the localClientID to be used + // * by the server side of the connection. + // ***************************************************** + packet->setClientID(client->getLocalID()); + + // ***************************************************** + // * Enqueue the packet and set the pointer to NULL to + // * prevent its later deletion. + // ***************************************************** + inbound.enqueue((void *)packet); + packet = NULL; + } + } + if(packet!=NULL) delete packet; + + // ********************************************************************* + // * If a packet was successfully added to the inbound queue and the + // * queue is not empty , then add an event to the FDTrigger to cause + // * the handle_input mechanism to be called. + // ********************************************************************* + if(result==0 && !inbound.empty()) trigger.insertEvent(); + + // ********************************************************************* + // * Due to the new design of the SocketUtil class, the binary should + // * never be deleted. + // ********************************************************************* + return result; + } + + +// ***************************************************************************** +// * cdevSessionManager::enqueue : +// * This method is used to enqueue a cdevPacket packet into an outbound +// * queue. The method will first identify the target client and place the +// * packet into its queue... then it will identify the socket and place the +// * packet into its queue. +// * +// * This method will return -1 if either the socket or the client is +// * undefined. +// * +// * The packet remains the property of the caller who must delete it. +// ***************************************************************************** +int cdevSessionManager::enqueue ( cdevPacket * input ) + { + cdevPacketBinary * packet = encodePacket(input); + ClientSession * client = NULL; + SocketSession * socket = NULL; + int result = -1; + + // ********************************************************************* + // * Note that this condition makes sure that a queue exists for both + // * the client ID and the socketID. If both of these conditions are + // * met, then it checks to ensure that the socket has not been overrun + // * with data (500 or more packets). + // ********************************************************************* + if(packet!=NULL && + input->getClientID()>0 && + (client = findLocalClient(input->getClientID()))!=NULL && + (socket = findSocket(client->getSocketID()))!=NULL) + { + cdevEventHandler * handler = NULL; + Reactor.getHandler(client->getSocketID(), handler); + + // ************************************************************* + // * Attempt to flush the handler if more than 500 packets + // * have already been inserted. + // ************************************************************* + if(handler && socket->getCount()>=500) + { + outputError(CDEV_SEVERITY_WARN, "CDEV Server", + "Forcing flush of socket %i to prevent overflow...", + client->getSocketID()); + + // ***************************************************** + // * Call handleOutput to cause the handler to attempt + // * to write its contents. + // ***************************************************** + if(handler->handleOutput()<0) + { + Reactor.removeHandler(handler); + handler = NULL; + } + } + + if(handler && socket->getCount()<500) + { + char * binary = NULL; + size_t binaryLen = 0; + + // ***************************************************** + // * Create a binary stream from the cdevPacketBinary + // * object and then use the detachData method to + // * prevent the buffer from being deleted when the + // * cdevPacketBinary is destroyed. + // ***************************************************** + packet->streamOut(&binary, &binaryLen); + packet->detachData(); + + // ***************************************************** + // * Populate the cdevServerBinary object with the data + // * that was extracted from the cdevPacketBinary object + // ***************************************************** + socket->enqueue(binary, binaryLen); + + // ***************************************************** + // * Set the event mask for the outbound socket to read/ + // * write to force it to attempt to write to the socket + // * until data is transmitted. + // ***************************************************** + if(handler) handler->setMask(READ_MASK|WRITE_MASK); + + result = 0; + } + else if(handler) + { + outputError ( CDEV_SEVERITY_ERROR, "CDEV Server", + "Dropping packet to socket %i : queue is full...", + client->getSocketID()); + } + } + + // ********************************************************************* + // * Delete the cdevPacketBinary if it was generated. + // ********************************************************************* + if(packet) delete packet; + + return result; + } + + +// ***************************************************************************** +// * cdevSessionManager::dequeue : +// * This method is used to by the server engine to extract a message from +// * the inbound queue. Once the packet has been enqueue it will be sent to +// * the decodePacket method which will perform any preprocessing that the +// * developer may deem necessary before returning the packet to the caller. +// * +// * The cdevPacket object becomes the property of the caller and must +// * be deleted when it is no longer needed. +// ***************************************************************************** +int cdevSessionManager::dequeue ( cdevPacket * &packet ) + { + cdevPacketBinary * binary = NULL; + packet = NULL; + + // ********************************************************************* + // * Conitnue this loop unitl a valid packet has been extracted, or + // * until there are no more binary packets left in the queue. + // ********************************************************************* + do { + // ************************************************************* + // * Attempt to dequeue the cdevPacketBinary from the queue... + // * If it is not NULL, then begin processing. + // ************************************************************* + if((binary = (cdevPacketBinary *)inbound.dequeue())!=NULL) + { + // ***************************************************** + // * Call the decodePacket mechanism... This will use + // * the factory mechanisms of the cdevPacket class to + // * import the data and then will complete any required + // * preprocessing... + // ***************************************************** + packet = decodePacket(binary); + + // ***************************************************** + // * Delete the binary as it is no longer needed. + // ***************************************************** + delete binary; + } + } while(binary!=NULL && packet==NULL); + + // ********************************************************************* + // * Return 0 if a cdevPacket was successfully dequeued, otherwise, + // * return -1. + // ********************************************************************* + return packet?0:-1; + } + +// ***************************************************************************** +// * cdevServer::decodePacket : +// * This method is used to perform preprocessing on a newly dequeued binary +// * packet before it is provided to the caller. This method allows the +// * developer to perform special preparations on the packet before providing +// * it to the caller. +// ***************************************************************************** +cdevPacket * cdevSessionManager::decodePacket (cdevPacketBinary * input) + { + return input?cdevPacket::import(*input):(cdevPacket *)NULL; + } + + +// ***************************************************************************** +// * cdevSessionManager::encodePacket : +// * This method is used to perform postprocessing on a packet that has been +// * enqueued to be sent to a client. This method allows the developer to +// * perform special preparations on the packet before providing it to the +// * client. +// ***************************************************************************** +cdevPacketBinary * cdevSessionManager::encodePacket ( cdevPacket * input ) + { + cdevPacketBinary *result; + + if(input) + { + char * binary; + size_t binaryLen; + input->streamOut(&binary, &binaryLen); + if(binary && binaryLen) + { + result = new cdevPacketBinary; + result->attachData(binary, binaryLen); + } + } + return result; + } + +// ***************************************************************************** +// * cdevSessionManager::getHandle : +// * This method is used to obtain a copy of the file handle that is used +// * to poll for events. In this case it will be the read file descriptor +// * of the FD_Trigger object. +// ***************************************************************************** +int cdevSessionManager::getHandle ( void ) const + { + return trigger.readfd(); + } + +// ***************************************************************************** +// * cdevSessionManager::handleInput : +// * This method is called whenever there is a read event pending on the +// * FD_Trigger object. +// ***************************************************************************** +int cdevSessionManager::handleInput ( void ) + { + processMessages(); + if(inbound.empty()) trigger.purge(); + return 0; + } + +// **************************************************************************** +// cdevSessionManager::handleClose : +// Shuts down the timer - this will result in the destruction of the +// * cdevSessionManager object. +// **************************************************************************** +int cdevSessionManager::handleClose(void) + { + return -1; + } + + +// **************************************************************************** +// * cdevSessionManager::handleTimeout : +// * Called when the timer expires... This method serves only to call the +// * processMessages function. +// **************************************************************************** +int cdevSessionManager::handleTimeout(void) + { + processMessages(); + if(inbound.empty()) trigger.purge(); + return 0; + } + + +// *************************************************************************** +// * cdevServer::processMessages : +// * This is a simple stand-in function that retrieves a message from the +// * queue and then immediately returns it to the outbound queue. This +// * function should be overloaded by the developers mechanism for +// * processing messages. +// *************************************************************************** +void cdevSessionManager::processMessages ( void ) + { + cdevPacket * packet; + + while(dequeue(packet)==0) + { + enqueue(packet); + delete packet; + } + } diff --git a/extensions/cdevGenericServer/cdevServer/cdevSessionManager.h b/extensions/cdevGenericServer/cdevServer/cdevSessionManager.h new file mode 100755 index 0000000..edb0b97 --- /dev/null +++ b/extensions/cdevGenericServer/cdevServer/cdevSessionManager.h @@ -0,0 +1,222 @@ +#if !defined (_CDEV_SESSION_MANAGER_H_) +#define _CDEV_SESSION_MANAGER_H_ + +#include "cdevReactor.h" +#include "cdevEventHandler.h" +#include "cdevAddr.h" +#include "cdevSocketStream.h" + +#include "ErrorReporter.h" +#include "FD_Trigger.h" +#include "fifo.h" +#include "IntHash.h" +#include "cdevPacket.h" + +// ***************************************************************************** +// * class ClientSession : +// * +// * The ClientSession allows the server to associate certain data +// * with a specific client... +// * +// * The ClientSession object may be sub-classed later in order to allow the +// * developer to attach additional information to a particular client id. +// * +// * localID : This is the short integer that uniquely identifies the +// * client on the server side of the connection. +// * +// * clientID : This is an integer that uniquely identifies the client +// * within the context of the socket... That is to say... +// * +// * The high-order short integer is the socketID - AND - +// * the low-order short integer is a clientID that uniquely +// * identifies the client on the client side of the connection. +// * +// * Even though both the clientID and the localID uniquely +// * identify the client... both are maintained in order to +// * perform bi-directional routing of packets between multiple +// * repeaters. +// * +// * socketID : This is the socket number that the client is attached on. +// * +// * context: This is a pointer to the most recently used context from the +// * cdevContextMap. +// ***************************************************************************** +class GENERIC_SERVER_API ClientSession +{ +private: + short localID; + int clientID; + int socketID; + +public: + ClientSession ( int SocketID, int ClientID, int LocalID ); + virtual ~ClientSession ( void ); + int getSocketID ( void ) { return socketID; } + void setSocketID ( int SocketID ) { socketID = SocketID; } + int getClientID ( void ) { return clientID; } + void setClientID ( int ClientID ) { clientID = ClientID; } + short getLocalID ( void ) { return localID; } + void setLocalID ( short LocalID ) { localID = LocalID; } +}; + + +// ***************************************************************************** +// * class SocketSession : +// * This class is a queue that will feed to a specific socket in that is +// * connected to a remote client. The class contains the following variables. +// * +// * The SocketSession object may be sub-classed later in order to allow the +// * developer to attach additional information to a particular socket. +// * +// * socketID : the integer identifier of the socket +// * +// * contextMap : a table of cdevData contexts that can be retrieved by index +// * +// * tagMap : the table for mapping cdevData tags from the remote system +// * to the tag table associated with this system. +// ***************************************************************************** +class GENERIC_SERVER_API SocketSession : public FifoQueue +{ +private: + int socketID; + +public: + SocketSession ( int SocketID ); + virtual ~SocketSession ( void ); + int getSocketID ( void ) { return socketID; } + void setSocketID ( int SocketID ) { socketID = SocketID; } +}; + + + +// ***************************************************************************** +// * class cdevSessionManager: +// * The cdevSessionManager class is used to manage the queues that are +// * associated with the operation of a server. It maintains the following +// * variables. +// * +// * Reactor : This is the cdevReactor that will be used to manage the client +// * connections. +// * +// * localIdx : This is the next available local index. This value will be +// * used to populate the localID variable in each ClientSession. +// * +// * +// * trigger : This is the file descriptor mechanism that is used to +// * notify the cdevEventHandler mechanisms when a packet +// * is available to be dequeued. +// * +// * rate : This is the rate at which the handleTimeout mechanism will +// * be periodically called in order to process time oriented +// * events. +// * +// * inbound : This is the inbound message queue. Since all messages will +// * go to the same method to be processed, they can be enqueued +// * in the same queue for storage. +// * +// * clients : This is a hash table that contains the queues for each +// * client that is attached to the server. Since multiple +// * clients can be routed through the same socket, these +// * classes are used to determine which socket to send the +// * outbound message to. +// * +// * sockets : This is the hash table that contains the queues for each +// * socket. After the cdevSessionManager determines the clientID +// * associated with an outbound message, that value will be used +// * to locate the SocketSession - where the outbound message will +// * be enqueued. +// ***************************************************************************** +class GENERIC_SERVER_API cdevSessionManager : public ErrorReporter, public cdevEventHandler +{ +public: + static cdevReactor Reactor; + +protected: + static IntHash localIdx; + + FD_Trigger trigger; + FifoQueue inbound; + IntHash clients; + IntHash sockets; + +public: + cdevSessionManager ( void ) {} + virtual ~cdevSessionManager ( void ); + + static short getNextLocalID ( void ); + + // ********************************************************************* + // * These mechanisms are used to obtain new ClientSession and + // * SocketSession objects. This design allows the developer to affix + // * addition socket specific or client specific components to his + // * classes later in order to have an easily accessable data point. + // ********************************************************************* + virtual ClientSession * newClientSession ( int SocketID, int ClientID, int LocalID ); + virtual SocketSession * newSocketSession ( int SocketID ); + virtual void deleteSocketSession ( SocketSession * session ); + // ********************************************************************* + // * These mechanisms are used to add, locate and remove client and + // * socket sessions. + // ********************************************************************* + virtual ClientSession * findLocalClient ( short localID ); + virtual ClientSession * findClient ( int clientID ); + virtual SocketSession * findSocket ( int socketID ); + virtual ClientSession * addClient ( int socketID, int clientID ); + virtual SocketSession * addSocket ( int socketID ); + virtual void removeClient ( int clientID, int unregisterFlag=1); + virtual void removeSocket ( int socketID ); + + // ********************************************************************* + // * This mechanism is used by the ClientHandler class to enqueue binary + // * information incoming from the socket. + // ********************************************************************* + virtual int enqueue ( int socketID, char * binary, unsigned binaryLen ); + + // ********************************************************************* + // * This method is used by the developer to send a packet to a specific + // * client. The client is specified by the clientID in the cdevPacket. + // ********************************************************************* + virtual int enqueue ( cdevPacket * packet ); + + // ********************************************************************* + // * This method is used by the developer to extract a packet from the + // * inbound queue for processing. + // ********************************************************************* + int dequeue ( cdevPacket * &packet ); + + // ********************************************************************* + // * This method is used by the developer to dequeue, process and then + // * enqueue messages to a client. + // ********************************************************************* + virtual void processMessages ( void ); + + // ********************************************************************* + // * This method formats packets when they are being enqueued or + // * dequeued. + // ********************************************************************* + virtual cdevPacket * decodePacket (cdevPacketBinary * input); + virtual cdevPacketBinary * encodePacket (cdevPacket * input); + + // ********************************************************************* + // * These are the ACE_Event_Handler methods that are called whenever + // * a timeout, input or output event occur. + // ********************************************************************* + virtual int getHandle (void) const; + virtual int handleInput (void); + virtual int handleClose (void); + virtual int handleTimeout (void); + + // ********************************************************************* + // * These are developer defined functions which are used to announce + // * the creation of a new client or the destruction of an existing + // * client to the main processing loop. + // * + // * Typically, they will only enqueue a message in the server specific + // * packet format that specifies either "register" or "unregister" and + // * the local client identifier. + // ********************************************************************* + virtual void registerClient ( short localID ) = 0; + virtual void unregisterClient ( short localID ) = 0; +}; + +#endif /* _CDEV_SESSION_MANAGER_H_ */ diff --git a/extensions/cdevGenericServer/cdevServer/cdevSystemEventHandler.h b/extensions/cdevGenericServer/cdevServer/cdevSystemEventHandler.h new file mode 100755 index 0000000..cdcd876 --- /dev/null +++ b/extensions/cdevGenericServer/cdevServer/cdevSystemEventHandler.h @@ -0,0 +1,90 @@ +#include "cdevSystem.h" +#include "cdevSessionManager.h" + +class GENERIC_SERVER_API cdevSystemEventHandler : public cdevEventHandler +{ +private: + int cdevfd; + +public: + cdevSystemEventHandler ( cdevReactor & Reactor, int fd ) + : cdevfd(fd) + { + Reactor.registerHandler(this, READ_MASK|WRITE_MASK|EXCEPT_MASK); + } + + ~cdevSystemEventHandler ( void ) + { + if(reactor) reactor->extractHandler(this); + handleClose(); + } + + int handleInput ( void ) + { + cdevSystem::defaultSystem().poll(); + return 0; + } + + int handleOutput ( void ) + { + cdevSystem::defaultSystem().flush(); + return 0; + } + + int handleExcept ( void ) + { + cdevSystem::defaultSystem().poll(); + return 0; + } + + int getHandle ( void ) const + { + return cdevfd; + } +}; + + + +class GENERIC_SERVER_API cdevSystemEventManager : public cdevEventHandler +{ +public: + cdevSystemEventManager ( cdevReactor &Reactor=cdevSessionManager::Reactor, double Rate = 30.0 ) + { + setTimeoutRate(Rate); + Reactor.registerTimer(this); + cdevSystem::defaultSystem().addFdChangedCallback + (cdevSystemEventManager::fdChangedCallback, this); + } + + ~cdevSystemEventManager ( void ) + { + if(reactor) reactor->extractHandler(this); + handleClose(); + } + + int handleTimeout ( void ) + { + cdevSystem::defaultSystem().pend(0.0001); + return 0; + } + + static void fdChangedCallback ( int fd, int opened, void * arg ) + { + cdevSystemEventManager *manager = (cdevSystemEventManager *)arg; + cdevEventHandler *handler; + cdevReactor *reactor = manager->reactor; + + if(reactor) + { + if(opened && reactor->getHandler(fd, handler)!=0) + { + handler = new cdevSystemEventHandler(*reactor, fd); + } + else if(!opened && reactor->getHandler(fd, handler)==0) + { + delete handler; + } + } + } +}; + diff --git a/extensions/cdevGenericServer/cdevTagMap/Makefile b/extensions/cdevGenericServer/cdevTagMap/Makefile new file mode 100755 index 0000000..475d9f2 --- /dev/null +++ b/extensions/cdevGenericServer/cdevTagMap/Makefile @@ -0,0 +1,15 @@ +ARCH = OS +SHOBJ = NO + +include ../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Tag Map Source" +CXXINCLUDES = -I./ +LIBS = $(CDEVLIBS) $(OSLIBS) +TARGETS = $(BASEBIN)/cdevTagMapTest + +targets: $(TARGETS) + +$(BASEBIN)/cdevTagMapTest: $(OBJDIR)/cdevTagMap.o $(OBJDIR)/cdevTagMapTest.o + $(LINK.cc) $^ -o $@ $(LIBS) + diff --git a/extensions/cdevGenericServer/cdevTagMap/NMakefile.mak b/extensions/cdevGenericServer/cdevTagMap/NMakefile.mak new file mode 100644 index 0000000..354ad4e --- /dev/null +++ b/extensions/cdevGenericServer/cdevTagMap/NMakefile.mak @@ -0,0 +1,21 @@ +.SUFFIXES: .cc .obj + +APPNAME = Tag Map Source +ARCH = WINNT-4.0 +BINARIES = $(BASEBIN)\cdevTagMapTest.exe + +include ..\include\makeinclude\Makefile.WINNT-4.0 + +CXXEXTRA = /D "GENERIC_SERVER_API= " +CXXINCLUDES = /I .\\ +TARGETS = $(BASEBIN)\cdevTagMapTest.exe + +targets : $(TARGETS) + +$(BASEBIN)\cdevTagMapTest.exe : .exec\$(TARGETDIR)\cdevTagMap.obj .exec\$(TARGETDIR)\cdevTagMapTest.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib\ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + diff --git a/extensions/cdevGenericServer/cdevTagMap/cdevTagMap.cc b/extensions/cdevGenericServer/cdevTagMap/cdevTagMap.cc new file mode 100755 index 0000000..e1a11e0 --- /dev/null +++ b/extensions/cdevGenericServer/cdevTagMap/cdevTagMap.cc @@ -0,0 +1,221 @@ +#include + +// ***************************************************************************** +// * cdevTagMap::cdevTagMap : +// * This is the constructor for the cdevTagMap class. +// ***************************************************************************** +cdevTagMap::cdevTagMap ( void ) + : cnt(0), + maximum(0), + local(NULL), + remote(NULL) + { + } + + +// ***************************************************************************** +// * cdevTagMap::cdevTagMap : +// * This is the destructor for the cdevTagMap class. +// ***************************************************************************** +cdevTagMap::~cdevTagMap ( void ) + { + if(local !=NULL) free(local); + if(remote!=NULL) free(remote); + } + +// ***************************************************************************** +// * cdevTagMap::updateTagMap : +// * This method will read the names and integers from a cdevData object and +// * will then pass these values to the updateTagMap method for processing. +// * +// * For standardization the tag integers are placed in tag 1, and the +// * tag strings are placed in tag 2... +// ***************************************************************************** +void cdevTagMap::updateTagMap ( cdevData & data ) + { + char ** names; + int * tags; + size_t nameCnt=0, tagCnt=0; + + if(data.getElems(1, &tagCnt)==CDEV_SUCCESS && + data.getElems(2, &nameCnt)==CDEV_SUCCESS && + tagCnt>0 && tagCnt==nameCnt) + { + names = new char *[nameCnt]; + tags = new int [tagCnt]; + memset(names, 0, sizeof(char *)*nameCnt); + data.get(1, tags); + data.get(2, names); + updateTagMap(names, tags, nameCnt); + while(nameCnt>0) + { + --nameCnt; + delete names[nameCnt]; + } + delete names; + delete tags; + } + } + +// ***************************************************************************** +// * cdevTagMap::updateTagMap : +// * This method will create a mapping of the differences between the tags +// * specified in the user provided array and the tags that are stored +// * within cdevData. +// ***************************************************************************** +void cdevTagMap::updateTagMap ( char ** names, int * tags, int count ) + { + // ********************************************************************* + // * Process each item in the names array from last to first. + // ********************************************************************* + while((--count)>=0) + { + int localTag = -1; + + // ************************************************************* + // * Determine if a tag that is identified by the names[count] + // * string exists in the cdevData Global Tag Table. If it + // * does, copy its integer representation into the localTag + // * variable. + // ************************************************************* + if(cdevData::tagC2I(names[count], &localTag)!=CDEV_SUCCESS) + { + // ***************************************************** + // * If the string does not already exist in the + // * cdevData Global Tag Table, then attempt to add it. + // * + // * If the specified integer is in use locally by + // * another cdevData tag - then the value will be + // * incremented until an open slot is found. + // ***************************************************** + char * s; + localTag = tags[count]; + while(cdevData::tagI2C(localTag, s)==CDEV_SUCCESS) + { + localTag++; + } + cdevData::insertTag(localTag, names[count]); + } + + // ************************************************************* + // * If the local integer tag value differs from the remote + // * integer tag value, then this tag must be added to the + // * list. + // ************************************************************* + if(localTag != tags[count]) + { + int idx; + + // ***************************************************** + // * Walk through the list and determine if the tag + // * has already been added to the list... + // ***************************************************** + for(idx=0; idx=cnt) + { + // ********************************************* + // * If the internal arrays have not yet been + // * allocated, then allocate a default number + // * of entries (64). + // ********************************************* + if(maximum==0) + { + maximum=64; + local = (int *)malloc(maximum*sizeof(int)); + remote = (int *)malloc(maximum*sizeof(int)); + } + // ********************************************* + // * If the internal arrays are already filled + // * by the existing entries, then double the + // * size of the arrays. + // ********************************************* + else if(idx>=maximum) + { + maximum*=2; + local = (int *)realloc(local, maximum*sizeof(int)); + remote = (int *)realloc(remote, maximum*sizeof(int)); + } + + // ********************************************* + // * Populate the new entry with the mismatch + // * data and increment the total number of + // * mismatches. + // ********************************************* + local [idx] = localTag; + remote[idx] = tags[count]; + cnt = idx+1; + } + } + } + } + + +// ***************************************************************************** +// * cdevTagMap::swapTags : +// * This method is used to swap between two sets of tags... If a tag +// * listed in the outTags array is used in the cdevData item, its tag will +// * be converted to the corresponding value in the inTags array. +// ***************************************************************************** +void cdevTagMap::swapTags ( cdevData & data, int *inTags, int *outTags, int count) + { + int tag; + int changeCount = 0; + cdevDataIterator iter(&data); + + iter.init(); + do { + int idx; + for(idx=0, tag=iter.tag(); idx +#include + + +// ***************************************************************************** +// * class cdevTagMap: +// * The purpose of the cdevTagMap is to allow rapid translation between +// * the cdev tag tables that within different processes. +// * +// * This class provides the capability to switch back and forth from the +// * local tag values to the remote tag values. +// ***************************************************************************** +class GENERIC_SERVER_API cdevTagMap +{ +private: + int cnt; + int maximum; + int * local; + int * remote; + +public: + cdevTagMap ( void ); + ~cdevTagMap ( void ); + void updateTagMap ( cdevData & data ); + void updateTagMap ( char ** names, int * tags, int count ); + void swapTags ( cdevData & data, int *inTags, int *outTags, int count); + void localToRemote ( cdevData & data ) { if(cnt) swapTags(data, remote, local, cnt); } + void remoteToLocal ( cdevData & data ) { if(cnt) swapTags(data, local, remote, cnt); } + void asciiDump ( FILE * fp = stdout ); +}; + diff --git a/extensions/cdevGenericServer/cdevTagMap/cdevTagMapTest.cc b/extensions/cdevGenericServer/cdevTagMap/cdevTagMapTest.cc new file mode 100755 index 0000000..e4c9312 --- /dev/null +++ b/extensions/cdevGenericServer/cdevTagMap/cdevTagMapTest.cc @@ -0,0 +1,58 @@ +#include + +char * version1Names[] = + { + "Version 1 Tag 100", + "Version 1 Tag 101", + "Version 1 Tag 102", + "Version 1 Tag 103" + }; + +int version1Tags[] = + { + 100, 101, 102, 103 + }; + +char * version2Names[] = + { + "Version 2 Tag 100", + "Version 2 Tag 101", + "Version 2 Tag 102", + "Version 2 Tag 103" + }; + +int version2Tags[] = + { + 103, 102, 101, 100 + }; + +int main() +{ +cdevTagMap map; +cdevData version1Data; +cdevData version2Data; +version1Data.insert(1, version1Tags, 4); +version1Data.insert(2, version1Names, 4); +version2Data.insert(1, version2Tags, 4); +version2Data.insert(2, version2Names, 4); + +// map.updateTagMap (version1Names, version1Tags, 4); +// map.updateTagMap (version2Names, version2Tags, 4); +map.updateTagMap(version1Data); +map.updateTagMap(version2Data); + +map.asciiDump(stdout); + +cdevData data; + +data.insert(103, "Version 2 Tag 100"); +data.insert(102, "Version 2 Tag 101"); +data.insert(101, "Version 2 Tag 102"); +data.insert(100, "Version 2 Tag 103"); +map.remoteToLocal(data); +data.asciiDump(); +map.localToRemote(data); +data.asciiDump(); + +return 0; +} diff --git a/extensions/cdevGenericServer/common/AddressIndex.h b/extensions/cdevGenericServer/common/AddressIndex.h new file mode 100755 index 0000000..fb4eb91 --- /dev/null +++ b/extensions/cdevGenericServer/common/AddressIndex.h @@ -0,0 +1,417 @@ +#ifndef ADDRESS_INDEX_H_ +#define ADDRESS_INDEX_H_ + +#include +#include +#include + +// ***************************************************************************** +// * union AddressReference : +// * This union contains all of the components that are necessary to locate +// * and validate a memory address from within an AddressIndex object. +// * +// * The index entry contains the location of the pointer within the address +// * array. +// * +// * The checksum entry contains the checksum value that should be located +// * at the specified index within the checksum array. +// * +// ***************************************************************************** +typedef union + { + unsigned rawData; + struct { + unsigned index : 24; + unsigned checksum : 8; + } value; + } AddressReference; + + +// ***************************************************************************** +// * class AddressIndex: +// * This class is used to allow an array to be dereferenced using an integer +// * code that contains an array index and a checksum value. Both of these +// * values are validated before the user is allowed to access the data. +// ***************************************************************************** +class AddressIndex +{ +friend class AddressIndexIterator; + +private: + enum {START_ARRAY_SIZE=1024}; + + // ********************************************************************* + // * population : this integer identifies the exact number of data items + // * that currently exist in the list. + // ********************************************************************* + int population; + + // ********************************************************************* + // * maxEntries : this integer identifies the maximum number of entries + // * that this object can contain. + // ********************************************************************* + int maxEntries; + + // ********************************************************************* + // * curEntry : this integer identifies the currently selected entry. + // ********************************************************************* + int curEntry; + + // ********************************************************************* + // * checksum : this is an array of bytes that are used to identify the + // * checksum for a specific address. This checksum is used to validate + // * that the address has not been changed externally. + // ********************************************************************* + unsigned char * checksum; + + // ********************************************************************* + // * address : this is the array of addresses that will be stored and + // * retrieved using this object. + // ********************************************************************* + void ** address; + + +public: + inline AddressIndex ( void ); + inline ~AddressIndex ( void ); + + inline unsigned insert( void * ptr ); + + inline void remove( void * ptr ); + inline void remove( unsigned idx ); + + inline unsigned find ( void * ptr ); + inline void * find ( unsigned idx ); +}; + + +class AddressIndexIterator +{ +private: + AddressIndex * index; + int current; + +public: + inline AddressIndexIterator (AddressIndex * Index); + inline ~AddressIndexIterator( void ); + + inline void * first ( void ); + inline void * operator ++ ( void ); + inline void * operator ++ ( int x ); + inline unsigned key ( void ); + inline void * data ( void ); +}; + + + +// ***************************************************************************** +// * AddressIndex::AddressIndex : +// * This is the constructor for the AddressIndex class. It is allocates a +// * default number of entries in the checksum and address arrays and then +// * initializes the data values to 0. +// * +// * Note that these arrays must be allocated using malloc because we will +// * use realloc later to expand there size if necessary. +// ***************************************************************************** +inline AddressIndex::AddressIndex ( void ) + : population(0),maxEntries(0),curEntry(0),checksum(NULL),address(NULL) + { + maxEntries = START_ARRAY_SIZE; + checksum = (unsigned char *)malloc(sizeof(unsigned char)*maxEntries); + address = (void **) malloc(sizeof(void *) *maxEntries); + memset(checksum, 1, sizeof(unsigned char)*maxEntries); + memset(address, 0, sizeof(void *) *maxEntries); + } + + +// ***************************************************************************** +// * AddressIndex::~AddressIndex : +// * This is the destructor for the object. It will deallocate any memory +// * that has been assigned to the checksum or address objects. +// * +// * Note that these arrays must be deallocated using the free library call +// * because they were allocated using either malloc or realloc. +// ***************************************************************************** +inline AddressIndex::~AddressIndex ( void ) + { + if(checksum!=NULL) free(checksum); + if(address!=NULL) free(address); + } + + +// ***************************************************************************** +// * AddressIndex::insert : +// * This method is used to insert a void * pointer into the AddressIndex +// * object. It returns an unsigned integer result which is the rawData +// * component of an AddressReference object. +// ***************************************************************************** +inline unsigned AddressIndex::insert ( void * ptr ) + { + AddressReference result; + + // ********************************************************************* + // * Initial all entries within the AddressReference object before + // * starting. + // ********************************************************************* + result.rawData = 0U; + + // ********************************************************************* + // * If the pointer provided by the user is NULL, then it cannot be + // * inserted into the list... Otherwise, + // * + // * From the current position in the array, we are going to walk + // * forward until we find an empty slot. An empty slot is indicated + // * by the value NULL in its address. + // * + // * If the end of the list is reached before an empty slot can be found + // * then special considerations will be made as described below. + // ********************************************************************* + if(ptr!=NULL) + { + while(curEntry=maxEntries then an empty slot was not located. + // * The following options should be considered... + // ************************************************************* + + // ************************************************************* + // * 1) If the population of the table is less than half of the + // * maximum number of entries... go back to the beginning + // * and search the table for an empty slot. + // ************************************************************* + if(curEntry>=maxEntries && population<(maxEntries/2)) + { + curEntry = 0; + while(curEntry=maxEntries) + { + curEntry = maxEntries; + maxEntries*=2; + checksum = (unsigned char *)realloc(checksum, sizeof(char *)*maxEntries); + address = (void **) realloc(address, sizeof(void *)*maxEntries); + memset(&checksum[curEntry], 0, sizeof(char *)*curEntry); + memset(&address [curEntry], 0, sizeof(void *)*curEntry); + } + + // ************************************************************* + // * At this time the curEntry index points to the insertion + // * point that should be used. Place the index and checksum + // * information into the result object and update the + // * population count. + // ************************************************************* + checksum[curEntry] = (checksum[curEntry]==255?1:(checksum[curEntry]+1)); + address [curEntry] = ptr; + + result.value.index = curEntry; + result.value.checksum = checksum[curEntry]; + + population++; + } + + // ********************************************************************* + // * Return the rawData portion of the AddressReference to the caller + // * as an unsigned integer. + // ********************************************************************* + return result.rawData; + } + + +// ***************************************************************************** +// * AddressIndex::remove : +// * This function will locate an entry by searching the array for a +// * specific pointer. If the entry is found it will be deleted. Direct +// * searching is one of the most time consuming approaches to locating +// * data, therefore the remove function that uses an unsigned integer +// * identifier should be used whenever possible. +// ***************************************************************************** +inline void AddressIndex::remove ( void * ptr) + { + if(ptr!=NULL) + { + for(int idx=0; idxpopulation && + currentmaxEntries && + index->address[current]==NULL) + { + current++; + } + return (index->population && currentmaxEntries)?index->address[current]:NULL; + } + + +// ***************************************************************************** +// * AddressIndexIterator::operator ++ : +// * Repositions to the next entry in the AddressIndex. +// ***************************************************************************** +inline void * AddressIndexIterator::operator ++ ( void ) + { + current++; + + while(index->population && + currentmaxEntries && + index->address[current]==NULL) + { + current++; + } + return (index->population && currentmaxEntries)?index->address[current]:NULL; + } + + +// ***************************************************************************** +// * AddressIndexIterator::operator ++ : +// * Repositions to the next entry in the AddressIndex. +// ***************************************************************************** +inline void * AddressIndexIterator::operator ++ ( int x ) + { + current++; + + while(x==0 && + index->population && + currentmaxEntries && + index->address[current]==NULL) + { + current++; + } + return (x==0 && index->population && currentmaxEntries)?index->address[current]:NULL; + } + +// ***************************************************************************** +// * AddressIndexIterator::key : +// * This method will return the AddressIndex key value of the current entry. +// ***************************************************************************** +inline unsigned AddressIndexIterator::key ( void ) + { + AddressReference result; + + result.rawData = 0; + if(currentmaxEntries && index->address[current]!=NULL) + { + result.value.index = current; + result.value.checksum = index->checksum[current]; + } + return result.rawData; + } + + +// ***************************************************************************** +// * AddressIndexIterator::data : +// * This method will return the data value of the current entry. +// ***************************************************************************** +inline void * AddressIndexIterator::data ( void ) + { + return(currentmaxEntries)?index->address[current]:NULL; + } + + +#endif /* ADDRESS_INDEX_H_ */ diff --git a/extensions/cdevGenericServer/common/ClientInfo.h b/extensions/cdevGenericServer/common/ClientInfo.h new file mode 100755 index 0000000..edc4415 --- /dev/null +++ b/extensions/cdevGenericServer/common/ClientInfo.h @@ -0,0 +1,355 @@ +#include +#include +#include + +class ClientInfoStruct +{ +private: + char unknown[8]; + char * username; + char * group; + unsigned uid; + unsigned gid; + unsigned pid; + char * program; + char * commandline; + time_t starttime; + time_t connecttime; + char * host; + char * os; + char * osrelease; + char * osversion; + char * machine; + char * shell; + +private: + void updateDataString ( cdevData & data, char * tag, char * &item ) + { + size_t nelems = 0; + + if(data.getElems(tag, &nelems)==CDEV_SUCCESS && + nelems==1 && data.getType(tag)==CDEV_STRING) + { + if(item!=NULL) delete item; + item = NULL; + data.get(tag, &item); + } + } + + void updateDataInt ( cdevData & data, char * tag, unsigned &item ) + { + size_t nelems = 0; + if(data.getElems(tag, &nelems)==CDEV_SUCCESS && nelems==1) + { + data.get(tag, &item); + } + } + +public: + ClientInfoStruct ( void ) + : username(NULL), group(NULL), uid(0), gid(0), pid(0), + program(NULL), commandline(NULL), starttime(0), + connecttime(0), host(NULL), os(NULL), osrelease(NULL), + osversion(NULL), machine(NULL), shell(NULL) + { + strcpy(unknown, "UNKNOWN"); + } + + ~ClientInfoStruct ( void ) + { + if(username) delete username; + if(group) delete group; + if(program) delete program; + if(commandline) delete commandline; + if(host) delete host; + if(os) delete os; + if(osrelease) delete osrelease; + if(osversion) delete osversion; + if(machine) delete machine; + if(shell) delete shell; + } + + void updateClientInfo ( cdevData & data ) + { + updateDataString(data, "username", username); + updateDataString(data, "group", group); + updateDataInt (data, "uid", uid); + updateDataInt (data, "gid", gid); + updateDataInt (data, "pid", pid); + updateDataString(data, "program", program); + updateDataString(data, "commandline", commandline); + updateDataInt (data, "starttime", (unsigned &)starttime); + updateDataInt (data, "connecttime", (unsigned &)connecttime); + updateDataString(data, "host", host); + updateDataString(data, "os", os); + updateDataString(data, "osrelease", osrelease); + updateDataString(data, "osversion", osversion); + updateDataString(data, "machine", machine); + updateDataString(data, "shell", shell); + connecttime = time(NULL); + } + + char * getUsername ( void ) { return username?username:unknown; } + char * getGroup ( void ) { return group?group:unknown; } + unsigned getUid ( void ) { return uid; } + unsigned getGid ( void ) { return gid; } + unsigned getPid ( void ) { return pid; } + char * getProgram ( void ) { return program?program:unknown; } + char * getCommandLine ( void ) { return commandline?commandline:unknown; } + time_t getStartTime ( void ) { return starttime; } + time_t getConnectTime ( void ) { return connecttime; } + char * getHost ( void ) { return host?host:unknown; } + char * getOs ( void ) { return os?os:unknown; } + char * getOsRelease ( void ) { return osrelease?osrelease:unknown; } + char * getOsVersion ( void ) { return osversion?osversion:unknown; } + char * getMachine ( void ) { return machine?machine:unknown; } + char * getShell ( void ) { return shell?shell:unknown; } + + void asciiDump ( FILE * fp = stdout ) + { + fprintf(fp, "--------------------------------------------------------\n"); + fprintf(fp, " Printing Client Information\n"); + fprintf(fp, "--------------------------------------------------------\n"); + fprintf(fp, "=> USERNAME : %s\n", username?username:"UNDEFINED"); + fprintf(fp, "=> GROUP : %s\n", group?group:"UNDEFINED"); + fprintf(fp, "=> USER ID : %s\n", uid?ltoa(uid):"UNDEFINED"); + fprintf(fp, "=> GROUP ID : %s\n", gid?ltoa(gid):"UNDEFINED"); + fprintf(fp, "=> PROCESS ID : %s\n", pid?ltoa(pid):"UNDEFINED"); + fprintf(fp, "=> APPLICATION : %s\n", program?program:"UNDEFINED"); + fprintf(fp, "=> COMMAND LINE : %s\n", commandline?commandline:"UNDEFINED"); + fprintf(fp, "=> START TIME : %s", starttime?ctime(&starttime):"UNKNOWN\n"); + fprintf(fp, "=> CONNECT TIME : %s", connecttime?ctime(&connecttime):"UNKNOWN\n"); + fprintf(fp, "=> HOST NAME : %s\n", host?host:"UNKNOWN"); + fprintf(fp, "=> OS : %s\n", os?os:"UNKNOWN"); + fprintf(fp, "=> OS VERSION : %s\n", osversion?osversion:"UNKNOWN"); + fprintf(fp, "=> OS RELEASE : %s\n", osrelease?osrelease:"UNKNOWN"); + fprintf(fp, "=> HARDWARE ID : %s\n", machine?machine:"UNKNOWN"); + fprintf(fp, "--------------------------------------------------------\n"); + } +}; + + +class ClientInfo +{ +private: + cdevData data; + +public: + ClientInfo ( void ) + { + cdevData::addTag("username"); + cdevData::addTag("group"); + cdevData::addTag("uid"); + cdevData::addTag("gid"); + cdevData::addTag("pid"); + cdevData::addTag("program"); + cdevData::addTag("commandline"); + cdevData::addTag("starttime"); + cdevData::addTag("connecttime"); + cdevData::addTag("host"); + cdevData::addTag("os"); + cdevData::addTag("osrelease"); + cdevData::addTag("osversion"); + cdevData::addTag("machine"); + cdevData::addTag("shell"); + cdevData::addTag("sendPktCnt"); + cdevData::addTag("recvPktCnt"); + cdevData::addTag("socket"); + + #ifndef _WIN32 + struct utsname hostinfo; + struct group * grp; + char * shell = getenv("SHELL"); + + uname(&hostinfo); + grp = getgrgid(getgid()); + + data.insert("username", getlogin()); + data.insert("group", grp?grp->gr_name:(char *)"UNDEFINED"); + data.insert("uid", (unsigned)getuid()); + data.insert("gid", (unsigned)getgid()); + data.insert("pid", (unsigned)getpid()); + data.insert("host", hostinfo.nodename); + data.insert("os", hostinfo.sysname); + data.insert("osrelease", hostinfo.release); + data.insert("osversion", hostinfo.version); + data.insert("machine", hostinfo.machine); + data.insert("shell", shell?shell:(char *)"UNDEFINED"); + + #if defined(__hpux) + struct pst_status pstatData; + pstat_getproc(&pstatData, sizeof(pstatData), 0, (int)getpid()); + data.insert("program", pstatData.pst_ucomm); + data.insert("commandline", pstatData.pst_cmd); + data.insert("starttime", pstatData.pst_start); + #endif + #else + char userNameBuf[UNLEN+1]; + unsigned long userNameLen = UNLEN; + char hostNameBuf[MAXHOSTNAMELEN+1]; + unsigned long hostNameLen = MAXHOSTNAMELEN; + + *userNameBuf = 0; + *hostNameBuf = 0; + + data.insert("pid", GetCurrentProcessId()); + if(GetUserName (userNameBuf, &userNameLen)) data.insert("username", userNameBuf); + if(GetComputerName(hostNameBuf, &hostNameLen)) data.insert("host", hostNameBuf); + + if(userNameBuf && hostNameBuf) + { + char grpNameBuf[GNLEN+1]; + unsigned long grpNameLen = GNLEN; + char sidBuf[256]; + unsigned long sidLen = 256; + SID_NAME_USE sidType; + + *grpNameBuf = 0; + if(LookupAccountName(hostNameBuf, userNameBuf, + sidBuf, &sidLen, grpNameBuf, + &grpNameLen, &sidType)) + { + data.insert("group", grpNameBuf); + } + } + + OSVERSIONINFO osv; + osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if(GetVersionEx (&osv)) + { + char osVersionBuf[64]; + switch(osv.dwPlatformId) + { + case VER_PLATFORM_WIN32s: + data.insert("os", "WINDOWS"); + break; + + case VER_PLATFORM_WIN32_WINDOWS: + if(osv.dwMinorVersion == 0) + data.insert("os", "WINDOWS 95"); + else data.insert("os", "WINDOWS 98"); + break; + + case VER_PLATFORM_WIN32_NT: + data.insert("os", "WINDOWS NT"); + break; + + default: + data.insert("os", "WIN32"); + break; + } + sprintf(osVersionBuf, "%d.%d", osv.dwMajorVersion, osv.dwMinorVersion); + data.insert("osversion", osVersionBuf); + data.insert("osrelease", ltoa(osv.dwBuildNumber)); + } + + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + switch(sysinfo.wProcessorArchitecture) + { + case PROCESSOR_ARCHITECTURE_INTEL: + data.insert("machine", "PROCESSOR_ARCHITECTURE_INTEL"); + break; + + case PROCESSOR_ARCHITECTURE_MIPS: + data.insert("machine", "PROCESSOR_ARCHITECTURE_MIPS"); + break; + + case PROCESSOR_ARCHITECTURE_ALPHA: + data.insert("machine", "PROCESSOR_ARCHITECTURE_ALPHA"); + break; + + case PROCESSOR_ARCHITECTURE_PPC: + data.insert("machine", "PROCESSOR_ARCHITECTURE_PPC"); + break; + + case PROCESSOR_ARCHITECTURE_UNKNOWN: + default: + data.insert("machine", "PROCESSOR_ARCHITECTURE_UNKNOWN"); + break; + } + + if(__argc>0) + { + int i; + char * cmdLine = NULL; + size_t cmdLineLen = 0; + + data.insert("program", __argv[0]); + for(i=0; i<__argc; i++) cmdLineLen+=strlen(__argv[i])+1; + cmdLine = new char [cmdLineLen]; + *cmdLine = 0; + for(i=0; i<__argc; i++) + { + strcat(cmdLine, __argv[i]); + if(i+1<__argc) strcat(cmdLine, " "); + } + data.insert("commandline", cmdLine); + } + FILETIME startTime; + FILETIME exitTime; + FILETIME kernelTime; + FILETIME userTime; + if(GetProcessTimes(GetCurrentProcess(), &startTime, &exitTime, &kernelTime, &userTime)) + { + struct timeval tv; + FileTimeToTimeVal(&startTime, &tv); + data.insert("starttime", tv.tv_sec); + } + #endif + } + + cdevData & getClientData ( void ) { return data; } + + void asciiDump ( FILE * fp = stdout ) + { + fprintf(fp, "--------------------------------------------------------\n"); + fprintf(fp, " Printing Client Information\n"); + fprintf(fp, "--------------------------------------------------------\n"); + + char * username; + char * group; + unsigned pid; + unsigned gid; + unsigned uid; + char * host; + char * os; + char * osrelease; + char * osversion; + char * machine; + char * shell; + char * program; + char * commandline; + long starttime; + + if(data.find("username", (void * &)username)!=CDEV_SUCCESS) username = NULL; + if(data.find("group", (void * &)group)!=CDEV_SUCCESS) group = NULL; + if(data.find("host", (void * &)host)!=CDEV_SUCCESS) host = NULL; + if(data.find("os", (void * &)os)!=CDEV_SUCCESS) os = NULL; + if(data.find("osrelease", (void * &)osrelease)!=CDEV_SUCCESS) osrelease = NULL; + if(data.find("osversion", (void * &)osversion)!=CDEV_SUCCESS) osversion = NULL; + if(data.find("machine", (void * &)machine)!=CDEV_SUCCESS) machine = NULL; + if(data.find("shell", (void * &)shell)!=CDEV_SUCCESS) shell=NULL; + if(data.find("program", (void * &)program)!=CDEV_SUCCESS) program=NULL; + if(data.find("commandline", (void * &)commandline)!=CDEV_SUCCESS) commandline=NULL; + if(data.get("starttime", &starttime)!=CDEV_SUCCESS) starttime = 0; + if(data.get("pid", &pid)!=CDEV_SUCCESS) pid = 0; + if(data.get("gid", &gid)!=CDEV_SUCCESS) gid = 0; + if(data.get("uid", &uid)!=CDEV_SUCCESS) uid = 0; + + fprintf(fp, "=> USERNAME : %s\n", username?username:"UNDEFINED"); + fprintf(fp, "=> GROUP : %s\n", group?group:"UNDEFINED"); + fprintf(fp, "=> USER ID : %s\n", uid?ltoa(uid):"UNDEFINED"); + fprintf(fp, "=> GROUP ID : %s\n", gid?ltoa(gid):"UNDEFINED"); + fprintf(fp, "=> PROCESS ID : %s\n", pid?ltoa(pid):"UNDEFINED"); + fprintf(fp, "=> APPLICATION : %s\n", program?program:"UNDEFINED"); + fprintf(fp, "=> COMMAND LINE : %s\n", commandline?commandline:"UNDEFINED"); + fprintf(fp, "=> START TIME : %s", starttime?ctime(&starttime):"UNKNOWN\n"); + fprintf(fp, "=> HOST NAME : %s\n", host?host:"UNKNOWN"); + fprintf(fp, "=> OS : %s\n", os?os:"UNKNOWN"); + fprintf(fp, "=> OS VERSION : %s\n", osversion?osversion:"UNKNOWN"); + fprintf(fp, "=> OS RELEASE : %s\n", osrelease?osrelease:"UNKNOWN"); + fprintf(fp, "=> HARDWARE ID : %s\n", machine?machine:"UNKNOWN"); + fprintf(fp, "--------------------------------------------------------\n"); + } +}; diff --git a/extensions/cdevGenericServer/common/ClientInfoTest.cc b/extensions/cdevGenericServer/common/ClientInfoTest.cc new file mode 100755 index 0000000..43c1823 --- /dev/null +++ b/extensions/cdevGenericServer/common/ClientInfoTest.cc @@ -0,0 +1,19 @@ +#include +#include + +ClientInfo info; +ServerInfo sInfo("MODEL", "MODEL1", 32526); + +ClientInfoStruct infoStruct; + +int main() + { + sInfo.asciiDump(); + info.asciiDump(); + infoStruct.updateClientInfo(info.getClientData()); + infoStruct.updateClientInfo(info.getClientData()); + infoStruct.updateClientInfo(info.getClientData()); + infoStruct.updateClientInfo(info.getClientData()); + infoStruct.asciiDump(); + return 0; + } diff --git a/extensions/cdevGenericServer/common/ErrorReporter.h b/extensions/cdevGenericServer/common/ErrorReporter.h new file mode 100755 index 0000000..ea00704 --- /dev/null +++ b/extensions/cdevGenericServer/common/ErrorReporter.h @@ -0,0 +1,49 @@ +#ifndef _ERROR_REPORTER_H_ +#define _ERROR_REPORTER_H_ 1 + +#include + +#ifndef _NO_CDEV_SYSTEM_ + #include + #include +#else + #include + #ifndef CDEV_SEVERITY_INFO /* cdevError class severity codes */ + #define CDEV_SEVERITY_INFO 0 /* informative message */ + #define CDEV_SEVERITY_WARN 1 /* warning message */ + #define CDEV_SEVERITY_ERROR 2 /* error message */ + #define CDEV_SEVERITY_SEVERE 3 /* severe or fatal error message */ + #endif +#endif + +class GENERIC_SERVER_API ErrorReporter +{ +public: + ErrorReporter ( void ) {} + virtual ~ErrorReporter ( void ) {} + virtual int outputError ( int severity, char *name, char *formatString, ... ) + { + int result = 0; + + va_list argp; + va_start (argp, formatString); + + #ifndef _NO_CDEV_SYSTEM_ + result = cdevSystem::defaultSystem().vreportError(severity, name, NULL, formatString, argp); + #else + fprintf(stdout,"%s %s: ", + name, + (severity==CDEV_SEVERITY_INFO?"Information": + (severity==CDEV_SEVERITY_WARN?"Warning": + (severity==CDEV_SEVERITY_ERROR?"Error": + (severity==CDEV_SEVERITY_SEVERE?"Severe Error": + "Event"))))); + vfprintf(stdout, formatString, argp); + fprintf (stdout, "\n"); + #endif + va_end(argp); + return result; + } +}; + +#endif /* _ERROR_REPORTER_H_ */ diff --git a/extensions/cdevGenericServer/common/FD_Trigger.h b/extensions/cdevGenericServer/common/FD_Trigger.h new file mode 100755 index 0000000..b19eccc --- /dev/null +++ b/extensions/cdevGenericServer/common/FD_Trigger.h @@ -0,0 +1,192 @@ +#ifndef _FD_TRIGGER_H_ +#define _FD_TRIGGER_H_ 1 + +#include + +// ***************************************************************************** +// * FD_Trigger : +// * This class provides a method for triggering events based on file +// * descriptor activity. +// ***************************************************************************** +class FD_Trigger +{ +private: + enum {READ=0, WRITE=1}; + int sockPair[2]; + +#ifndef _WIN32 + char cbuf[100]; +#endif + +public: + FD_Trigger ( void ); + ~FD_Trigger ( void ); + int insertEvent ( int numEvents = 1 ); + int removeEvent ( int numEvents = 1 ); + void purge ( void ); + int writefd ( void ) const; + int readfd ( void ) const; +}; + + +// ***************************************************************************** +// * FD_Trigger::FD_Trigger : +// * Constructor for the FD_Trigger class. +// ***************************************************************************** +inline FD_Trigger::FD_Trigger ( void ) + { + if(pipe(sockPair)!=0) + { + sockPair[READ] = -1; + sockPair[WRITE] = -1; + } + #ifndef _WIN32 + else + { + int val; + + val = ::fcntl(sockPair[READ], F_GETFL, 0); + if(val>0) ::fcntl(sockPair[READ], F_SETFL, val|O_NONBLOCK); + + val = ::fcntl(sockPair[WRITE], F_GETFL, 0); + if(val>0) ::fcntl(sockPair[WRITE], F_SETFL, val|O_NONBLOCK); + + memset(cbuf, '1', 100); + } + #endif + } + + + +// ***************************************************************************** +// * FD_Trigger::~FD_Trigger : +// * Destructor for the FD_Trigger class. +// ***************************************************************************** +inline FD_Trigger::~FD_Trigger ( void ) + { + if(sockPair[READ] != -1) close(sockPair[READ]); + if(sockPair[WRITE] != -1) close(sockPair[WRITE]); + } + + + +// ***************************************************************************** +// * FD_Trigger::insertEvent : +// * Adds one or more bytes (indicating events) to the pipe +// ***************************************************************************** +inline int FD_Trigger::insertEvent ( int numEvents ) + { + if(sockPair[WRITE]>0) + { + int count = 0; + + #ifdef _WIN32 + char cptr = 1; + + while(count++0) + { + write(sockPair[WRITE], cbuf, min(100, count)); + count-=100; + } + #endif + } + return (sockPair[WRITE]>0)?0:-1; + } + + + +// ***************************************************************************** +// * FD_Trigger::removeEvent : +// * Removes one or more bytes (indicating events) from the pipe. +// ***************************************************************************** +inline int FD_Trigger::removeEvent ( int numEvents ) + { + int retval = 0; + + if(sockPair[READ]>0) + { + int count = 0; + + #ifdef _WIN32 + char cptr = 0; + + while(count0 || + WSAGetLastError()==WSAEMSGSIZE)) + { + count++; + } + if(count==0) retval = -1; + + #else + if(ioctl(sockPair[READ], FIONREAD, &count)<0 || count==0) + { + retval = -1; + } + else + { + if(numEvents>count) numEvents = count; + while(numEvents>0) + { + read(sockPair[READ], cbuf, min(100, numEvents)); + numEvents-=100; + } + } + #endif + } + else retval = -1; + + return retval; + } + + + +// ***************************************************************************** +// * FD_Trigger::purge : +// * This function removes all bytes from the pipe. +// ***************************************************************************** +inline void FD_Trigger::purge ( void ) + { + if(sockPair[READ]>0) + { + #ifdef _WIN32 + char cptr = 0; + while(recv(sockPair[READ], &cptr, 1, 0)>0 || WSAGetLastError()==WSAEMSGSIZE); + #else + int count = 0; + ioctl(sockPair[READ], FIONREAD, &count); + while(count>0) + { + read(sockPair[READ], cbuf, min(100, count)); + count-=100; + } + #endif + } + } + + + +// ***************************************************************************** +// * FD_Trigger::writefd +// * Returns the write file descriptor associated with the pipe. +// ***************************************************************************** +inline int FD_Trigger::writefd ( void ) const + { + return sockPair[WRITE]; + } + + + +// ***************************************************************************** +// * FD_Trigger::readfd +// * Returns the read file descriptor associated with the pipe. +// ***************************************************************************** +inline int FD_Trigger::readfd ( void ) const + { + return sockPair[READ]; + } + +#endif /* _FD_TRIGGER_H_ */ diff --git a/extensions/cdevGenericServer/common/FD_TriggerTest.cc b/extensions/cdevGenericServer/common/FD_TriggerTest.cc new file mode 100644 index 0000000..6239335 --- /dev/null +++ b/extensions/cdevGenericServer/common/FD_TriggerTest.cc @@ -0,0 +1,104 @@ +#include + +char * resultString[] = + { + "SUCCEEDED", + "FAILED" + }; + +int main () + { + #ifdef _WIN32 + InitializeNetwork(); + #endif + + FD_Trigger trigger; + int i; + int cnt; + int singleInsertResult = 0; + int multiInsertResult = 0; + int singleExtractResult = 0; + int multiExtractResult = 0; + int purgeResult = 0; + + fprintf(stdout, "Inserting Twenty Single Events\n"); + for(i=0, cnt=0; i<20; i++) + { + if(trigger.insertEvent()!=0) + { + fprintf(stdout, "Error inserting event %i\n", i); + singleInsertResult = 1; + } + else cnt++; + } + fprintf(stdout, "%i Events Successfully Inserted - %i Failed\n", cnt, 20-cnt); + + fprintf(stdout, "Extracting Each Event\n"); + for(cnt=0; trigger.removeEvent()==0 && cnt<500; cnt++); + if(cnt!=20) singleExtractResult = 1; + fprintf(stdout, "Extracted %i Events\n", cnt); + + fprintf(stdout, "Inserting Twenty Quad Events\n"); + for(i=0, cnt=0; i<20; i++) + { + if(trigger.insertEvent(4)!=0) + { + fprintf(stdout, "Error inserting event %i\n", i); + multiInsertResult = 1; + } + else cnt++; + } + fprintf(stdout, "%i Quad Events Successfully Inserted - %i Failed\n", cnt, 20-cnt); + + fprintf(stdout, "Extracting Each Event\n"); + for(cnt=0; trigger.removeEvent()==0 && cnt<500; cnt++); + if(cnt!=80) singleExtractResult = 1; + fprintf(stdout, "Extracted %i Events\n", cnt); + + fprintf(stdout, "Inserting Twenty Single Events\n"); + for(i=0, cnt=0; i<20; i++) + { + if(trigger.insertEvent()!=0) + { + fprintf(stdout, "Error inserting event %i\n", i); + singleInsertResult = 1; + } + else cnt++; + } + fprintf(stdout, "%i Events Successfully Inserted - %i Failed\n", cnt, 20-cnt); + + fprintf(stdout, "Extracting Each Quad Event\n"); + for(cnt=0; trigger.removeEvent(4)==0 && cnt<500; cnt++); + if(cnt!=5) multiExtractResult = 1; + fprintf(stdout, "Extracted %i Quad Events\n", cnt); + + fprintf(stdout, "Inserting Twenty Single Events\n"); + for(i=0, cnt=0; i<20; i++) + { + if(trigger.insertEvent()!=0) + { + fprintf(stdout, "Error inserting event %i\n", i); + } + else cnt++; + } + fprintf(stdout, "%i Events Successfully Inserted - %i Failed\n", cnt, 20-cnt); + + fprintf(stdout, "Purging Trigger\n"); + trigger.purge(); + fprintf(stdout, "Extracting Each Remaining Event\n"); + for(cnt=0; trigger.removeEvent()==0 && cnt<500; cnt++); + if(cnt!=0) purgeResult = 1; + fprintf(stdout, "Extracted %i Events\n\n", cnt); + + fprintf(stdout, "RESULTS: \n"); + fprintf(stdout, "\tInsertion of single events %s\n", resultString[singleInsertResult]); + fprintf(stdout, "\tInsertion of multiple events %s\n", resultString[multiInsertResult]); + fprintf(stdout, "\tExtraction of single events %s\n", resultString[singleExtractResult]); + fprintf(stdout, "\tExtraction of multiple events %s\n", resultString[multiExtractResult]); + fprintf(stdout, "\tPurging of multiple events %s\n", resultString[purgeResult]); + + #ifdef _WIN32 + TerminateNetwork(); + #endif + return 0; + } diff --git a/extensions/cdevGenericServer/common/IntHash.cc b/extensions/cdevGenericServer/common/IntHash.cc new file mode 100644 index 0000000..d81e314 --- /dev/null +++ b/extensions/cdevGenericServer/common/IntHash.cc @@ -0,0 +1,13 @@ +#include + +IntHashNode::IntHashNode ( int HashInt, void * HashData) + : next(NULL) + { + hashInt = HashInt; + hashData = HashData; + } + +IntHashNode::~IntHashNode ( void ) + { + } + diff --git a/extensions/cdevGenericServer/common/IntHash.h b/extensions/cdevGenericServer/common/IntHash.h new file mode 100755 index 0000000..8ccdbb0 --- /dev/null +++ b/extensions/cdevGenericServer/common/IntHash.h @@ -0,0 +1,204 @@ +#ifndef _INT_HASH_H_ +#define _INT_HASH_H_ 1 + +#include + +class GENERIC_SERVER_API IntHashNode +{ +friend class IntHash; +friend class IntHashIterator; + +private: + int hashInt; + void * hashData; + IntHashNode * next; + + IntHashNode ( int HashInt, void * HashData); + ~IntHashNode ( void ); +}; + + +class GENERIC_SERVER_API IntHash +{ +friend class IntHashIterator; + +private: + enum { HASH_CNT=256, HASH_NO=256 }; + + IntHashNode * nodes[HASH_CNT]; + +public: + IntHash ( void ); + ~IntHash ( void ); + + inline unsigned char hash ( int hashInt ); + + inline void insert ( int hashInt, void * hashData ); + inline void remove ( int hashInt ); + inline void * find ( int hashInt ); +}; + + +class GENERIC_SERVER_API IntHashIterator +{ +private: + IntHash * hashTbl; + IntHashNode * node; + int idx; + +public: + IntHashIterator( IntHash * HashTbl ); + ~IntHashIterator( void ); + + inline void * first ( void ); + inline void * operator ++ ( void ); + inline void * operator ++ ( int x ); + inline int key ( void ); + inline void * data ( void ); +}; + + + +inline IntHash::IntHash ( void ) + { + memset(nodes, 0, sizeof(nodes)); + } + + +inline IntHash::~IntHash ( void ) + { + for(int i=0; inext; + delete node; + } + } + } + +inline unsigned char IntHash::hash ( int hashInt ) + { + return (hashInt%HASH_NO); + } + +inline void IntHash::insert (int hashInt, void * hashData ) + { + unsigned char idx = hash(hashInt); + IntHashNode * prev = NULL, * node = nodes[idx]; + IntHashNode * newNode = new IntHashNode(hashInt, hashData); + + while(node!=NULL && node->hashInt!=hashInt) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + newNode->next = node->next; + delete node; + } + if(prev!=NULL) prev->next = newNode; + else nodes[idx] = newNode; + } + +inline void IntHash::remove ( int hashInt ) + { + unsigned char idx = hash(hashInt); + IntHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && node->hashInt!=hashInt) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + if(prev!=NULL) prev->next = node->next; + else nodes[idx] = node->next; + delete node; + } + } + +inline void * IntHash::find ( int hashInt ) + { + unsigned char idx = hash(hashInt); + IntHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && node->hashInt!=hashInt) + { + prev = node; + node = prev->next; + } + return node!=NULL?node->hashData:NULL; + } + + +inline IntHashIterator::IntHashIterator(IntHash * HashTbl) + : hashTbl(HashTbl), idx(0), node(NULL) + { + } + +inline IntHashIterator::~IntHashIterator( void ) + { + } + +inline void * IntHashIterator::first ( void ) + { + if(hashTbl!=NULL) + { + for(idx = 0; idxnodes[idx])==NULL; idx++); + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * IntHashIterator::operator ++ ( void ) + { + if(hashTbl!=NULL) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxnodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * IntHashIterator::operator ++ ( int x ) + { + if(hashTbl!=NULL && x==0) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxnodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline int IntHashIterator::key ( void ) + { + return (node!=NULL)?node->hashInt:0; + } + +inline void * IntHashIterator::data ( void ) + { + return (node!=NULL)?node->hashData:NULL; + } + +#endif /* _INT_HASH_H_ */ diff --git a/extensions/cdevGenericServer/common/LinkList.h b/extensions/cdevGenericServer/common/LinkList.h new file mode 100755 index 0000000..5d94f73 --- /dev/null +++ b/extensions/cdevGenericServer/common/LinkList.h @@ -0,0 +1,1091 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: General purpose linked list class with smart iterator. +// +// Author: Walt Akers +// +//----------------------------------------------------------------------------- + +#if !defined (_LINKED_LIST_H_) +#define _LINKED_LIST_H_ + +#include + +// ***************************************************************************** +// * class LinkedListDataDestructor : +// * This is a pure virtual base class that can be used to create a +// * destructor class for the data that is stored in the LinkedList class. +// * If a destructor class is specified, it can be called by the LinkedList +// * to delete the user defined data whenever it is removed from the list. +// ***************************************************************************** +class LinkedListDataDestructor +{ +public: + virtual void destroy ( void * data ) = 0; +}; + + +// ***************************************************************************** +// * class LinkedListDataConstructor : +// * This is a pure virtual class that can be used to create a constructor +// * class for data that is being stored in the LinkedList class. If this +// * constructor class is specified, then it will be called each time data +// * is added to the list in order to perform any user defined pre-processing +// * that is necessary. +// ***************************************************************************** +class LinkedListDataConstructor +{ +public: + virtual void * construct ( void * data ) = 0; +}; + + +// ***************************************************************************** +// * class LinkedList : +// * This is the storage class for the linked list, it will maintain a list +// * of data nodes and provide iterator objects to the developer upon +// * request. +// ***************************************************************************** +class LinkedList +{ +friend class LinkedListIterator; + +private: + // ********************************************************************* + // * class LinkedList::Node : + // * An embedded class that defines the storage structure for each + // * entity in the doubly-linked list. + // ********************************************************************* + class Node + { + public: + Node * prev; + Node * next; + void * data; + + Node ( void * Data = NULL ) + : prev(NULL), + next(NULL), + data(Data) + { + } + }; + + // ********************************************************************* + // * LinkedListDataDestructor * destructor: + // * This is a class that may be specified by the linked list user. + // * If specified, this method will be called by the linked list + // * any remove is called in order to delete the user data. If the + // * destructor is not specified, then the user provided data will + // * not be deleted. + // ********************************************************************* + LinkedListDataDestructor * destructor; + + // ********************************************************************* + // * LinkedListDataConstructor * constructor : + // * This is a class that contains a virtual construct method that + // * is called whenever new data is added to the linked list. This + // * construct method can do any preprocessing that of the data that + // * is desired by the user. + // ********************************************************************* + LinkedListDataConstructor * constructor; + + // ********************************************************************* + // * Node * head: + // * This item points to the first node in the list. It is NULL when + // * the class is created and is initialized when the first data item + // * is added to the list. + // ********************************************************************* + Node * head; + + // ********************************************************************* + // * Node * tail: + // * This item points to the last node in the list. It is NULL when + // * the class is created and is initailized and updated each time a + // * data item is added to the list. + // ********************************************************************* + Node * tail; + + // ********************************************************************* + // * LinkedListIterator * iterList; + // * This is a list of iterators that have been created to access + // * this list. + // ********************************************************************* + LinkedListIterator * iterList; + + // ********************************************************************* + // * size_t count + // * This is the total number of entries that are currently stored + // * in the linked list. + // ********************************************************************* + size_t count; + + // ********************************************************************* + // * LinkedList::remove : + // * This method is called by the LinkedListIterator in order to + // * remove an entry from the linked list. It will locate all + // * iterators that might be impacted by this change and will update + // * them appropriately. + // ********************************************************************* + inline int remove ( LinkedListIterator & iter ); + + // ********************************************************************* + // * LinkedList::append : + // * This method is called by the LinkedListIterator in order to + // * append a new entry to the linked list. + // * + // * Note that the newly appended entry will become the current entry + // * for this iterator. + // ********************************************************************* + inline int append ( LinkedListIterator & iter, LinkedList::Node & node ); + + // ********************************************************************* + // * LinkedList::insert : + // * This method is called by the LinkedListIterator to insert a + // * new entry above or below the current entry. It will locate all + // * iterators that might be impacted by this change and will update + // * them appropriately. + // * + // * Note that the iterator must be pointing to a valid entry or the + // * list must be empty in order for this to work. The newly + // * inserted entry will become the current entry for this iterator. + // ********************************************************************* + inline int insert ( LinkedListIterator & iter, LinkedList::Node & node, int above=1 ); + + // ********************************************************************* + // * LinkedList::reindex : + // * This is an emergency fall-back that should never be called. + // * This method will be executed if the indexing/count in the list + // * or any of its iterators becomes invalid... It will recount all + // * of the items in the list and then walk through each of the + // * iterators and update their internal indices. + // ********************************************************************* + inline void reindex ( void ); + +public: + // ********************************************************************* + // * LinkedList::LinkedList : + // * This is the constructor for the class, it initializes all + // * internal variables to there default values. + // ********************************************************************* + inline LinkedList ( void ); + + // ********************************************************************* + // * LinkedList::~LinkedList : + // * This is the destructor for the class, it deletes all nodes that + // * may have been created to store data. It will also invalidate + // * the listPtr for any existing iterators. This destructor will NOT + // * delete the data that is stored in the Nodes. + // ********************************************************************* + inline ~LinkedList ( void ); + + // ********************************************************************* + // * LinkedList::iterator : + // * This method will return a new linked list iterator that can + // * be used to traverse this list. + // ********************************************************************* + inline LinkedListIterator * iterator ( void ); + + // ********************************************************************* + // * LinkedList::setDestructor : + // * This inline method allows the caller to set the destructor that + // * will be used by the class to delete data. + // ********************************************************************* + inline void setDestructor ( LinkedListDataDestructor * Destructor = NULL ); + + // ********************************************************************* + // * LinkedList::setConstructor : + // * This method allows the caller to set the constructor that will + // * be used by the class to initialize inbound data. + // ********************************************************************* + inline void setConstructor ( LinkedListDataConstructor * Constructor = NULL ); +}; + + +// ***************************************************************************** +// * class LinkedListIterator : +// * This class is used to allow the caller to traverse the data in the +// * linked list class. +// ***************************************************************************** +class LinkedListIterator +{ +friend class LinkedList; + +private: + // ********************************************************************* + // * LinkedListIterator * next : + // * This entry allows the linked list to maintain a list of all + // * iterators that are in use. This list is used to update indices + // * when entries are deleted. + // ********************************************************************* + LinkedListIterator * nextIter; + + // ********************************************************************* + // * LinkedList * list : + // * This is the linked list that owns the iterator. + // ********************************************************************* + LinkedList * list; + + // ********************************************************************* + // * LinkedList::Node * node : + // * This is the current entry in the linked list. + // ********************************************************************* + LinkedList::Node * node; + + // ********************************************************************* + // * int index : + // * This is the index of the current entry in the list. Indexes + // * start at 0. + // ********************************************************************* + int index; + + // ********************************************************************* + // * LinkedListIterator::LinkedListIterator : + // * This is the constructor for the iterator. It is private to + // * prevent it from being instanciated directly. In order to obtain + // * a LinkedListIterator the developer must call the iterator method + // * of the LinkedList. + // * + // * This method will automatically position the developer at the + // * top of the linked list. + // ********************************************************************* + inline LinkedListIterator ( LinkedList * listPtr ); + +public: + // ********************************************************************* + // * LinkedListIterator::~LinkedListIterator : + // * This is the destructor for the iterator. The user must call + // * this method when the iterator is no longer needed. It will + // * remove itself from teh table of iterators registered with the + // * LinkedList prior to being deleted. + // ********************************************************************* + inline ~LinkedListIterator ( void ); + + // ********************************************************************* + // * LinkedListIterator::first : + // * This method will position the iterator to the top of the list + // * of entries in the linked list and set the index to 0. If the + // * linked list is empty, then the index will be set to -1 and the + // * node willbe set to NULL. + // ********************************************************************* + inline void first ( void ); + + // ********************************************************************* + // * LinkedListIterator::last : + // * This method will position the iterator to the bottom of the + // * list of entries and set the index to the appropriate + // * value (count-1). If the list is empty the index will be set to + // * -1 and the node will be set to NULL. + // ********************************************************************* + inline void last ( void ); + + // ********************************************************************* + // * LinkedListIterator::prev : + // * This method will position the iterator to the previous entry + // * in the list. + // * + // * If the iterator is already at the top of the list or the list is + // * empty, then a -1 will be returned and the current entry will be + // * marked as invalid. + // * + // * If the iterator is passed the bottom of the list, this method + // * will reposition to the tail. + // * + // * On success a value of 0 is returned. + // ********************************************************************* + inline int prev ( void ); + + // ********************************************************************* + // * LinkedListIterator::next : + // * This method will position the iterator to the next entry in the + // * list. + // * + // * If the iterator is already at the bottom of the list or the list + // * is empty, then a -1 will be returned and the current entry will + // * be marked as invalid. + // * + // * If the iterator is above the top of the list, this method + // * will reposition to the head. + // * + // * On success a value of 0 is returned. + // ********************************************************************* + inline int next ( void ); + + // ********************************************************************* + // * LinkedListIterator::remove : + // * This method is called to remove the current entry from the + // * linked list. It will return 0 if the entry is successful + // * removed, or -1 if an error occurs. + // ********************************************************************* + inline int remove ( void ); + + // ********************************************************************* + // * LinkedListIterator::append : + // * This method is called to append an entry to the bottom of the + // * list. It will return 0 if the entry is successfully added, or + // * -1 if an error occurs. + // ********************************************************************* + inline int append ( void * data ); + + // ********************************************************************* + // * LinkedListIterator::insert : + // * This method is called to insert a new entry at the current + // * position in the linked list. It will return 0 on success, or + // * -1 if an error occurs. + // * + // * The above flag (TRUE by default) indicates that the new entry + // * should be inserted above or below the current entry. + // ********************************************************************* + inline int insert ( void * data, int above = 1 ); + + // ********************************************************************* + // * LinkedListIterator::replace : + // * This method will replace the data in the current node with the + // * user provided data. It is the responsibility of the user to + // * delete the old data if necessary. this method will return 0 + // * on success, or -1 if there is no current entry. + // ********************************************************************* + inline int replace ( void * data ); + + // ********************************************************************* + // * LinkedListIterator::isvalid : + // * This method allows the developer to determine if the iterator + // * is currently pointing at a valid entry. This method returns + // * 1 if the entry is valid or 0 if the entry is bogus. + // ********************************************************************* + inline int isvalid ( void ); + + // ********************************************************************* + // * LinkedListIterator::get_index : + // * This method returns the index of the current data item. If the + // * data item is invalid, then an index of -1 is returned. + // ********************************************************************* + inline int get_index ( void ); + + // ********************************************************************* + // * LinkedListIterator::get_count : + // * This method will return the total number of entries in the list. + // ********************************************************************* + inline int get_count ( void ); + + // ********************************************************************* + // * LinkedListIterator::get_value : + // * This method returns the value of the current entry in the list. + // * If the current entry is invalid, a value of NULL is returned. + // ********************************************************************* + inline void * get_value ( void ); + + // ********************************************************************* + // * LinkedListIterator::operator []; + // * This method returns the value of the entry in the list at the + // * specified index. If the index is out of range, then a value + // * of NULL will be returned. + // * + // * Note that the index operator cannot be used to replace the + // * pointer used by the list. Use the replace method to install + // * a new pointer. + // ********************************************************************* + inline void * operator [] ( size_t idx ); +}; + + +// ***************************************************************************** +// * LinkedList::remove : +// * This method is called by the LinkedListIterator in order to +// * remove an entry from the linked list. It will locate all +// * iterators that might be impacted by this change and will update +// * them appropriately. +// ***************************************************************************** +inline int LinkedList::remove ( LinkedListIterator & iter ) + { + int result; + + // ********************************************************************* + // * Check to make sure that the node contained in the iterator + // * is valid, that the iterator points to this list, and that + // * the iterator's index is in a valid range. + // ********************************************************************* + if(iter.node!=NULL && iter.list==this && + iter.index=0) + { + LinkedListIterator * iters; + Node * deadNode = iter.node; + Node * node = NULL; + int index = iter.index; + + // ************************************************************* + // * Identify the node that will take the place of the + // * deleted node and determine what its index will be. + // * By default, the replacement node will be the + // * previous node when possible or the next node if + // * the head node is deleted. + // ************************************************************* + if(deadNode->prev!=NULL) + { + node = deadNode->prev; + index--; + } + else node = deadNode->next; + + // ************************************************************* + // * Ensure that the head and tail are correct. + // ************************************************************* + if(deadNode->prev==NULL) head = deadNode->next; + if(deadNode->next==NULL) tail = deadNode->prev; + + // ************************************************************* + // * Update the pointers on the nodes surrounding the node to + // * be removed... + // ************************************************************* + if(deadNode->next) deadNode->next->prev = deadNode->prev; + if(deadNode->prev) deadNode->prev->next = deadNode->next; + + // ************************************************************* + // * Walk through the list of all iterators and update + // * them. If an iterator points to the deleted node, + // * then it will be updated with the replacement node + // * and index as determined above. If a iterator has + // * a node that occurs later in the list, then its + // * index will be decremented to indicate its new + // * position. + // ************************************************************* + for(iters=iterList; iters!=NULL; iters=iters->nextIter) + { + if(iters->node==NULL) + { + continue; + } + else if (head==NULL) + { + iters->node = NULL; + iters->index = -1; + } + else if(iters->node==deadNode) + { + iters->node = node; + iters->index = index; + } + else if(iters->index > index) + { + iters->index--; + } + } + + // ************************************************************* + // * Delete the old node and decrement the count. Note, + // * this approach WILL NOT delete the data that is + // * associated with the entry... the developer is + // * responsible for deleting the data. + // ************************************************************* + if(destructor) destructor->destroy(deadNode->data); + delete deadNode; + count--; + result = 0; + } + else result = -1; + + return result; + } + +// ***************************************************************************** +// * LinkedList::append : +// * This method is called by the LinkedListIterator in order to +// * append a new entry to the linked list. +// * +// * Note that the newly appended entry will become the current entry +// * for this iterator. +// ***************************************************************************** +inline int LinkedList::append ( LinkedListIterator & iter, LinkedList::Node & node ) + { + int result; + + // ********************************************************************* + // * If a constructor class has been specified, use the construct method + // * to pre-process the data. + // ********************************************************************* + if(constructor!=NULL) node.data = constructor->construct(node.data); + + // ********************************************************************* + // * Ensure that the iterator points to the current list and + // * then append the entry to the end of the list and increment + // * the count. + // ********************************************************************* + if(iter.list == this) + { + int index = count++; + + node.prev = tail; + node.next = NULL; + if(tail!=NULL) tail->next = &node; + if(head==NULL) head = &node; + tail = &node; + + iter.node = &node; + iter.index = index; + + result = 0; + } + else result = -1; + + return result; + } + +// ***************************************************************************** +// * LinkedList::insert : +// * This method is called by the LinkedListIterator to insert a +// * new entry above or below the current entry. It will locate all +// * iterators that might be impacted by this change and will update +// * them appropriately. +// * +// * Note that the iterator must be pointing to a valid entry or the +// * list must be empty in order for this to work. The newly +// * inserted entry will become the current entry for this iterator. +// ***************************************************************************** +inline int LinkedList::insert ( LinkedListIterator & iter, LinkedList::Node & node, int above ) + { + int result; + + // ********************************************************************* + // * If a constructor class has been specified, use the construct method + // * to pre-process the data. + // ********************************************************************* + if(constructor!=NULL) node.data = constructor->construct(node.data); + + // ********************************************************************* + // * If there are no entries in the list, then use the append + // * method to add the new entry to the head of the list. + // ********************************************************************* + if(iter.list == this && count==0) + { + result = append(iter, node); + } + // ********************************************************************* + // * If the iterator points to this list and the insertion point + // * is not NULL, then attempt to insert the entry. + // ********************************************************************* + else if(iter.list == this && iter.node!=NULL) + { + LinkedListIterator * iters; + int index = iter.index; + + // ************************************************************* + // * Insert the entry above or below the current entry. + // * If the new node is inserted below the current + // * entry, then the index must be incremented to + // * reflect its new position. + // ************************************************************* + if(above) + { + if((node.prev = iter.node->prev)!=NULL) + node.prev->next = &node; + if((node.next = iter.node)!=NULL) + node.next->prev = &node; + } + else { + if((node.next = iter.node->next)!=NULL) + node.next->prev = &node; + if((node.prev = iter.node)!=NULL) + node.prev->next = &node; + index++; + } + + // ************************************************************* + // * If the new entry occupies the head or tail position + // * in the list, then update these variables to reflect + // * its position. + // ************************************************************* + if(node.prev==NULL) head = &node; + if(node.next==NULL) tail = &node; + + // ************************************************************* + // * Walk through the list and increment the indexes of + // * any iterator that contains a node that occurs later + // * in the list than the new node. + // ************************************************************* + for(iters=iterList; iters!=NULL; iters=iters->nextIter) + { + if(iters->node==NULL) + { + continue; + } + else if(iters->index >= index) + { + iters->index++; + } + } + + // ************************************************************* + // * Update the user provided iterator to point to the + // * newly inserted node and its correct index and + // * increment the count. + // ************************************************************* + iter.node = &node; + iter.index = index; + count++; + result = 0; + } + else result = -1; + + return result; + } + +// ***************************************************************************** +// * LinkedList::reindex : +// * This is an emergency fall-back that should never be called. +// * This method will be executed if the indexing/count in the list +// * or any of its iterators becomes invalid... It will recount all +// * of the items in the list and then walk through each of the +// * iterators and update their internal indices. +// ***************************************************************************** +inline void LinkedList::reindex ( void ) + { + LinkedListIterator * iters; + Node * node = head; + + for(count = 0; node!=NULL; node=node->next) count++; + for(iters=iterList; iters!=NULL; iters = iters->nextIter) + { + if(iters->node!=NULL) + { + for(iters->index=0, node=head; + node!=NULL && node!=iters->node; + node=node->next) + { + iters->index++; + } + if(node==NULL) + { + iters->node = NULL; + iters->index = 0; + } + } + } + } + +// ***************************************************************************** +// * LinkedList::LinkedList : +// * This is the constructor for the class, it initializes all +// * internal variables to there default values. +// ***************************************************************************** +inline LinkedList::LinkedList ( void ) + : head(NULL), tail(NULL), iterList(NULL), count(0), + constructor(NULL), destructor(NULL) + { + } + + +// ***************************************************************************** +// * LinkedList::~LinkedList : +// * This is the destructor for the class, it deletes all nodes that +// * may have been created to store data. It will also invalidate +// * the listPtr for any existing iterators. This destructor will NOT +// * delete the data that is stored in the Nodes. +// ***************************************************************************** +inline LinkedList::~LinkedList ( void ) + { + Node * curr; + while(head!=NULL) + { + curr = head; + head = curr->next; + if(destructor) destructor->destroy(curr->data); + delete curr; + } + + while(iterList!=NULL) + { + iterList->list = NULL; + iterList->node = NULL; + iterList = iterList->nextIter; + } + } + +// ***************************************************************************** +// * LinkedList::iterator : +// * This method will return a new linked list iterator that can +// * be used to traverse this list. +// ***************************************************************************** +inline LinkedListIterator * LinkedList::iterator ( void ) + { + LinkedListIterator * iter = new LinkedListIterator(this); + iter->nextIter = iterList; + iterList = iter; + return iter; + } + +// ***************************************************************************** +// * LinkedList::setDestructor : +// * This inline method allows the caller to set the destructor that +// * will be used by the class to delete data. +// ***************************************************************************** +inline void LinkedList::setDestructor ( LinkedListDataDestructor * Destructor) + { + destructor = Destructor; + } + +// ***************************************************************************** +// * LinkedList::setConstructor : +// * This method allows the caller to set the constructor that will +// * be used by the class to initialize inbound data. +// ***************************************************************************** +inline void LinkedList::setConstructor ( LinkedListDataConstructor * Constructor) + { + constructor = Constructor; + } + +// ***************************************************************************** +// * LinkedListIterator::LinkedListIterator : +// * This is the constructor for the iterator. It is private to +// * prevent it from being instanciated directly. In order to obtain +// * a LinkedListIterator the developer must call the iterator method +// * of the LinkedList. +// * +// * This method will automatically position the developer at the +// * top of the linked list. +// ***************************************************************************** +inline LinkedListIterator::LinkedListIterator ( LinkedList * listPtr ) + : nextIter(NULL), list(listPtr), node(NULL), index(-1) + { + first(); + } + +// ***************************************************************************** +// * LinkedListIterator::~LinkedListIterator : +// * This is the destructor for the iterator. The user must call +// * this method when the iterator is no longer needed. It will +// * remove itself from teh table of iterators registered with the +// * LinkedList prior to being deleted. +// ***************************************************************************** +inline LinkedListIterator::~LinkedListIterator ( void ) + { + LinkedListIterator * curr, * prev = NULL; + + for(curr=list->iterList; curr!=this; curr=curr->nextIter) prev = curr; + if(curr!=NULL) + { + if(prev) prev->nextIter = curr->nextIter; + else list->iterList = curr->nextIter; + } + } + +// ***************************************************************************** +// * LinkedListIterator::first : +// * This method will position the iterator to the top of the list +// * of entries in the linked list and set the index to 0. If the +// * linked list is empty, then the index will be set to -1 and the +// * node willbe set to NULL. +// ***************************************************************************** +inline void LinkedListIterator::first ( void ) + { + node = list->head; + index = node?0:-1; + } + +// ***************************************************************************** +// * LinkedListIterator::last : +// * This method will position the iterator to the bottom of the +// * list of entries and set the index to the appropriate +// * value (count-1). If the list is empty the index will be set to +// * -1 and the node will be set to NULL. +// ***************************************************************************** +inline void LinkedListIterator::last ( void ) + { + node = list->tail; + index = node?list->count-1:-1; + } + +// ***************************************************************************** +// * LinkedListIterator::prev : +// * This method will position the iterator to the previous entry +// * in the list. +// * +// * If the iterator is already at the top of the list or the list is +// * empty, then a -1 will be returned and the current entry will be +// * marked as invalid. +// * +// * If the iterator is passed the bottom of the list, this method +// * will reposition to the tail. +// * +// * On success a value of 0 is returned. +// ***************************************************************************** +inline int LinkedListIterator::prev ( void ) + { + int result; + + if(node!=NULL && node->prev!=NULL) + { + node = node->prev; + index--; + result = 0; + } + else if (node==NULL && index==INT_MAX) + { + last(); + result = isvalid()?0:-1; + } + else { + node = NULL; + index = -1; + result = -1; + } + + return result; + } + +// ***************************************************************************** +// * LinkedListIterator::next : +// * This method will position the iterator to the next entry in the +// * list. +// * +// * If the iterator is already at the bottom of the list or the list +// * is empty, then a -1 will be returned and the current entry will +// * be marked as invalid. +// * +// * If the iterator is above the top of the list, this method +// * will reposition to the head. +// * +// * On success a value of 0 is returned. +// ***************************************************************************** +inline int LinkedListIterator::next ( void ) + { + int result; + + if(node!=NULL && node->next!=NULL) + { + node = node->next; + index++; + result = 0; + } + else if (node==NULL && index<0) + { + first(); + result = isvalid()?0:-1; + } + else { + node = NULL; + index = INT_MAX; + result = -1; + } + + return result; + } + +// ***************************************************************************** +// * LinkedListIterator::remove : +// * This method is called to remove the current entry from the +// * linked list. It will return 0 if the entry is successful +// * removed, or -1 if an error occurs. +// ***************************************************************************** +inline int LinkedListIterator::remove ( void ) + { + return list->remove(*this); + } + + +// ***************************************************************************** +// * LinkedListIterator::append : +// * This method is called to append an entry to the bottom of the +// * list. It will return 0 if the entry is successfully added, or +// * -1 if an error occurs. +// ***************************************************************************** +inline int LinkedListIterator::append ( void * data ) + { + int result; + + LinkedList::Node * newNode = new LinkedList::Node(data); + + if((result = list->append(*this, *newNode))!=0) + { + delete newNode; + } + return result; + } + +// ***************************************************************************** +// * LinkedListIterator::insert : +// * This method is called to insert a new entry at the current +// * position in the linked list. It will return 0 on success, or +// * -1 if an error occurs. +// * +// * The above flag (TRUE by default) indicates that the new entry +// * should be inserted above or below the current entry. +// ***************************************************************************** +inline int LinkedListIterator::insert ( void * data, int above ) + { + int result; + + LinkedList::Node * newNode = new LinkedList::Node(data); + + if((result = list->insert(*this, *newNode, above))!=0) + { + delete newNode; + } + return result; + } + +// ***************************************************************************** +// * LinkedListIterator::replace : +// * This method will replace the data in the current node with the +// * user provided data. It is the responsibility of the user to +// * delete the old data if necessary. this method will return 0 +// * on success, or -1 if there is no current entry. +// ***************************************************************************** +inline int LinkedListIterator::replace ( void * data ) + { + int result; + + if(node!=NULL) + { + if(list->destructor) list->destructor->destroy(node->data); + + if(list->constructor==NULL) node->data = data; + else node->data = list->constructor->construct(data); + + result = 0; + } + else result = -1; + + return result; + } + +// ***************************************************************************** +// * LinkedListIterator::isvalid : +// * This method allows the developer to determine if the iterator +// * is currently pointing at a valid entry. This method returns +// * 1 if the entry is valid or 0 if the entry is bogus. +// ***************************************************************************** +inline int LinkedListIterator::isvalid ( void ) + { + return node==NULL?0:1; + } + +// ***************************************************************************** +// * LinkedListIterator::get_index : +// * This method returns the index of the current data item. If the +// * data item is invalid, then an index of -1 is returned. +// ***************************************************************************** +inline int LinkedListIterator::get_index ( void ) + { + return (node && index>=0 && indexcount; + } + +// ***************************************************************************** +// * LinkedListIterator::get_value : +// * This method returns the value of the current entry in the list. +// * If the current entry is invalid, a value of NULL is returned. +// ***************************************************************************** +inline void * LinkedListIterator::get_value ( void ) + { + return node?node->data:NULL; + + } + +// ***************************************************************************** +// * LinkedList::operator []; +// * This method returns the value of the entry in the list at the +// * specified index. If the index is out of range, then a value +// * of NULL will be returned. +// * +// * Note that the index operator cannot be used to replace the +// * pointer used by the list. Use the replace method to install +// * a new pointer. +// ***************************************************************************** +inline void * LinkedListIterator::operator [] ( size_t idx ) + { + // ********************************************************************* + // * Ensure that the index is within range. + // ********************************************************************* + if(idxcount) + { + // ************************************************************* + // * If the desired position is above the current entry + // * reposition to it by going down from the top or + // * up from the current - whichever is a shorter trip. + // ************************************************************* + if(idxhead; + index = 0; + + while(index!=idx && node!=NULL) + { + node = node->next; + index++; + } + } + else { + while(index!=idx && node!=NULL) + { + node = node->prev; + index--; + } + } + } + // ************************************************************* + // * If the desired position is below the current entry + // * reposition to it by going up from the bottom or + // * down from the current - whichever is a shorter trip. + // ************************************************************* + else { + if(idx > list->count-idx-1) + { + node = list->tail; + index = list->count-1; + + while(index!=idx && node!=NULL) + { + node = node->prev; + index--; + } + } + else { + while(index!=idx && node!=NULL) + { + node = node->next; + index++; + } + } + } + + // ************************************************************* + // * If an error occurs, then it means that the indexing + // * has somehow become invalid. Set the node to NULL + // * and the index to -1 and recount the items in the + // * linked list... Logically, this should never + // * happen. + // ************************************************************* + if(node==NULL) + { + index = -1; + list->reindex(); + } + } + else { + node = NULL; + index = -1; + } + + return node?node->data:NULL; + } + + + +#endif /* _LINKED_LIST_H_ */ diff --git a/extensions/cdevGenericServer/common/Makefile b/extensions/cdevGenericServer/common/Makefile new file mode 100755 index 0000000..fab2f5f --- /dev/null +++ b/extensions/cdevGenericServer/common/Makefile @@ -0,0 +1,15 @@ +ARCH = OS +SHOBJ = YES + +include ../include/makeinclude/Makefile.$(ARCH) + +APPNAME = Signal Manager Source +CXXINCLUDES = -I./ +LIBS = $(CDEVLIBS) $(OSLIBS) +TARGETS = $(BASEBIN)/SignalManagerTest + +targets: $(TARGETS) + +$(BASEBIN)/SignalManagerTest: $(OBJDIR)/SignalManager.o $(OBJDIR)/SignalManagerTest.o $(OBJDIR)/ErrorReporter.obj + $(LINK.cc) $^ -o $@ $(LIBS) + diff --git a/extensions/cdevGenericServer/common/MultiQueue.h b/extensions/cdevGenericServer/common/MultiQueue.h new file mode 100755 index 0000000..6a93d75 --- /dev/null +++ b/extensions/cdevGenericServer/common/MultiQueue.h @@ -0,0 +1,192 @@ +#ifndef __MULTIQUEUE_H_ +#define __MULTIQUEUE_H_ 1 + +#include +#include + +class MultiQueueBase +{ +private: + int nodeCount; + +public: + MultiQueueBase ( void ) { nodeCount = 0; } + + virtual void setTail ( void *tail ) = 0; + virtual int getCount ( void ) { return nodeCount; } + virtual int setCount ( int cnt ) { return (nodeCount = (cnt>=0?cnt:0)); } + virtual int incCount ( void ) { return (++nodeCount); } + virtual int decCount ( void ) { return (nodeCount=(nodeCount>0?nodeCount-1:0)); } +}; + + +template class MultiQueueNode +{ +private: + char * binary; + unsigned binaryLen; + +public: + class MultiQueueBase *queue[queueCount]; + class MultiQueueNode *prev [queueCount]; + class MultiQueueNode *next [queueCount]; + + MultiQueueNode(char * Binary=NULL, size_t BinaryLen=0) + : binary(Binary), binaryLen(BinaryLen) + { + memset(queue, 0, sizeof(class MultiQueueBase *)*queueCount); + memset(prev, 0, sizeof(class MultiQueueNode *)*queueCount); + memset(next, 0, sizeof(class MultiQueueNode *)*queueCount); + } + + virtual ~MultiQueueNode(void) + { + binary = NULL; + binaryLen = 0; + clear(); + } + + virtual void set ( char * Binary, size_t BinaryLen ) + { + binary = Binary; + binaryLen = BinaryLen; + } + + virtual void get ( char ** Binary, size_t * BinaryLen ) + { + *Binary = binary; + *BinaryLen = binaryLen; + } + + virtual void clear ( void ) + { + for(int i=0; inext[i] = next[i]; + if(next[i]) next [i]->prev[i] = prev[i]; + else if(queue[i]) queue[i]->setTail(prev[i]); + + if(queue[i]) queue[i]->decCount(); + + queue[i]=NULL; + prev[i] =NULL; + next[i] =NULL; + } + } +}; + + + +template class MultiQueue + : public MultiQueueBase +{ +private: + MultiQueueNode head; + MultiQueueNode * tail; + +public: + MultiQueue ( void ) + { + tail = NULL; + } + + virtual ~MultiQueue ( void ) + { + MultiQueueNode * node; + while((node=dequeue())!=NULL) delete node; + } + + virtual void setTail ( void * Tail ) + { + tail = (MultiQueueNode *)Tail; + } + + virtual int empty ( void ) { return (head.next[queueIndex]==NULL?1:0); } + + virtual void enqueue ( MultiQueueNode * node ) + { + if(node!=NULL) + { + if(head.next[queueIndex]==NULL) + { + head.next[queueIndex] = node; + node->prev[queueIndex] = &head; + } + else + { + tail->next[queueIndex] = node; + node->prev[queueIndex] = tail; + } + tail = node; + node->queue[queueIndex] = this; + node->queue[queueIndex]->incCount(); + } + } + + + virtual MultiQueueNode * peek ( void ) + { + return head.next[queueIndex]; + } + + virtual MultiQueueNode * dequeue ( void ) + { + MultiQueueNode * node = head.next[queueIndex]; + if(node!=NULL) node->clear(); + return node; + } + + virtual int peek ( char ** binary, size_t * binaryLen ) + { + int result = -1; + MultiQueueNode * node; + + if((node = peek())!=NULL) + { + node->get(binary, binaryLen); + if(*binary!=NULL && *binaryLen!=0) result = 0; + } + return result; + } + + virtual int dequeue ( char ** binary, size_t * binaryLen ) + { + int result = -1; + MultiQueueNode * node; + + *binary = NULL; + *binaryLen = 0; + + if((node = dequeue())!=NULL) + { + node->get(binary, binaryLen); + if(*binary!=NULL && *binaryLen!=0) result = 0; + delete node; + } + return result; + } + + virtual MultiQueueNode * localDequeue ( void ) + { + MultiQueueNode * node = head.next[queueIndex]; + if(node!=NULL) + { + if(node->prev[queueIndex]!=NULL) + node->prev[queueIndex]->next[queueIndex] = node->next[queueIndex]; + if(node->next[queueIndex]!=NULL) + node->next[queueIndex]->prev[queueIndex] = node->prev[queueIndex]; + else if(node->queue[queueIndex]!=NULL) + { + node->queue[queueIndex]->setTail(node->prev); + node->queue[queueIndex]->decCount(); + } + node->queue[queueIndex]=NULL; + node->next [queueIndex]=NULL; + node->prev [queueIndex]=NULL; + } + return node; + } +}; + +#endif /* __MULTIQUEUE_H_ */ + diff --git a/extensions/cdevGenericServer/common/NMakefile.mak b/extensions/cdevGenericServer/common/NMakefile.mak new file mode 100644 index 0000000..73a6417 --- /dev/null +++ b/extensions/cdevGenericServer/common/NMakefile.mak @@ -0,0 +1,42 @@ +.SUFFIXES: .cc .obj + +APPNAME = Common Source +ARCH = WINNT-4.0 +BINARIES = $(BASEBIN)\SignalManagerTest.exe $(BASEBIN)\ClientInfoTest.exe $(BASEBIN)\FD_TriggerTest.exe $(BASEBIN)\includeAllTest.exe + +include ..\include\makeinclude\Makefile.WINNT-4.0 + +CXXEXTRA = /D "GENERIC_SERVER_API= " +CXXINCLUDES = /I .\\ +TARGETS = $(BASEBIN)\SignalManagerTest.exe $(BASEBIN)\ClientInfoTest.exe $(BASEBIN)\FD_TriggerTest.exe $(BASEBIN)\includeAllTest.exe + +targets : $(TARGETS) + +$(BASEBIN)\SignalManagerTest.exe : .exec\$(TARGETDIR)\SignalManager.obj .exec\$(TARGETDIR)\SignalManagerTest.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib\ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\ClientInfoTest.exe : .exec\$(TARGETDIR)\ClientInfoTest.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib\ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + + +$(BASEBIN)\FD_TriggerTest.exe : .exec\$(TARGETDIR)\FD_TriggerTest.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib\ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\includeAllTest.exe : .exec\$(TARGETDIR)\includeAll.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib\ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... diff --git a/extensions/cdevGenericServer/common/ServerInfo.h b/extensions/cdevGenericServer/common/ServerInfo.h new file mode 100755 index 0000000..8d50e5f --- /dev/null +++ b/extensions/cdevGenericServer/common/ServerInfo.h @@ -0,0 +1,280 @@ +#include +#include + +class ServerInfo +{ +friend class cdevServer; + +private: + cdevData data; + size_t sendPktCnt; + size_t recvPktCnt; + size_t clientCnt; + long pageSize; + +public: + ServerInfo ( char * domain, char * server, unsigned short port ) + : sendPktCnt(0), recvPktCnt(0), clientCnt(0), pageSize(0) + { + cdevData::addTag("username"); + cdevData::addTag("group"); + cdevData::addTag("uid"); + cdevData::addTag("gid"); + cdevData::addTag("pid"); + cdevData::addTag("program"); + cdevData::addTag("commandline"); + cdevData::addTag("starttime"); + cdevData::addTag("host"); + cdevData::addTag("server"); + cdevData::addTag("domain"); + cdevData::addTag("port"); + cdevData::addTag("os"); + cdevData::addTag("osrelease"); + cdevData::addTag("osversion"); + cdevData::addTag("machine"); + cdevData::addTag("shell"); + cdevData::addTag("sendPktCnt"); + cdevData::addTag("recvPktCnt"); + cdevData::addTag("clientCnt"); + cdevData::addTag("pctcpu"); + cdevData::addTag("datasize"); + cdevData::addTag("socket"); + + data.insert("server", server); + data.insert("domain", domain); + data.insert("port", port); + + #ifndef _WIN32 + struct utsname hostinfo; + struct group * grp; + char * shell = getenv("SHELL"); + + uname(&hostinfo); + grp = getgrgid(getgid()); + + data.insert("username", getlogin()); + data.insert("group", grp?grp->gr_name:(char *)"UNDEFINED"); + data.insert("uid", (unsigned)getuid()); + data.insert("gid", (unsigned)getgid()); + data.insert("pid", (unsigned)getpid()); + data.insert("host", hostinfo.nodename); + data.insert("os", hostinfo.sysname); + data.insert("osrelease", hostinfo.release); + data.insert("osversion", hostinfo.version); + data.insert("machine", hostinfo.machine); + data.insert("shell", shell?shell:(char *)"UNDEFINED"); + + #if defined(__hpux) + struct pst_status pstatData; + pstat_getproc(&pstatData, sizeof(pstatData), 0, (int)getpid()); + data.insert("program", pstatData.pst_ucomm); + data.insert("commandline", pstatData.pst_cmd); + data.insert("starttime", pstatData.pst_start); + + struct pst_static pstatStatic; + pstat_getstatic(&pstatStatic, sizeof(pstatStatic), 1, 0); + pageSize = pstatStatic.page_size; + #endif + #else + char userNameBuf[UNLEN+1]; + unsigned long userNameLen = UNLEN; + char hostNameBuf[MAXHOSTNAMELEN+1]; + unsigned long hostNameLen = MAXHOSTNAMELEN; + + *userNameBuf = 0; + *hostNameBuf = 0; + + data.insert("pid", getpid()); + if(GetUserName (userNameBuf, &userNameLen)) data.insert("username", userNameBuf); + if(GetComputerName(hostNameBuf, &hostNameLen)) data.insert("host", hostNameBuf); + + if(userNameBuf && hostNameBuf) + { + char grpNameBuf[GNLEN+1]; + unsigned long grpNameLen = GNLEN; + char sidBuf[256]; + unsigned long sidLen = 256; + SID_NAME_USE sidType; + + *grpNameBuf = 0; + if(LookupAccountName(hostNameBuf, userNameBuf, + sidBuf, &sidLen, grpNameBuf, + &grpNameLen, &sidType)) + { + data.insert("group", grpNameBuf); + } + } + + OSVERSIONINFO osv; + osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if(GetVersionEx (&osv)) + { + char osVersionBuf[64]; + switch(osv.dwPlatformId) + { + case VER_PLATFORM_WIN32s: + data.insert("os", "WINDOWS"); + break; + + case VER_PLATFORM_WIN32_WINDOWS: + if(osv.dwMinorVersion == 0) + data.insert("os", "WINDOWS 95"); + else data.insert("os", "WINDOWS 98"); + break; + + case VER_PLATFORM_WIN32_NT: + data.insert("os", "WINDOWS NT"); + break; + + default: + data.insert("os", "WIN32"); + break; + } + sprintf(osVersionBuf, "%d.%d", osv.dwMajorVersion, osv.dwMinorVersion); + data.insert("osversion", osVersionBuf); + data.insert("osrelease", ltoa(osv.dwBuildNumber)); + } + + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + switch(sysinfo.wProcessorArchitecture) + { + case PROCESSOR_ARCHITECTURE_INTEL: + data.insert("machine", "PROCESSOR_ARCHITECTURE_INTEL"); + break; + + case PROCESSOR_ARCHITECTURE_MIPS: + data.insert("machine", "PROCESSOR_ARCHITECTURE_MIPS"); + break; + + case PROCESSOR_ARCHITECTURE_ALPHA: + data.insert("machine", "PROCESSOR_ARCHITECTURE_ALPHA"); + break; + + case PROCESSOR_ARCHITECTURE_PPC: + data.insert("machine", "PROCESSOR_ARCHITECTURE_PPC"); + break; + + case PROCESSOR_ARCHITECTURE_UNKNOWN: + default: + data.insert("machine", "PROCESSOR_ARCHITECTURE_UNKNOWN"); + break; + } + + if(__argc>0) + { + int i; + char * cmdLine = NULL; + size_t cmdLineLen = 0; + + data.insert("program", __argv[0]); + for(i=0; i<__argc; i++) cmdLineLen+=strlen(__argv[i])+1; + cmdLine = new char [cmdLineLen]; + *cmdLine = 0; + for(i=0; i<__argc; i++) + { + strcat(cmdLine, __argv[i]); + if(i+1<__argc) strcat(cmdLine, " "); + } + data.insert("commandline", cmdLine); + } + + FILETIME startTime; + FILETIME exitTime; + FILETIME kernelTime; + FILETIME userTime; + if(GetProcessTimes(GetCurrentProcess(), &startTime, &exitTime, &kernelTime, &userTime)) + { + struct timeval tv; + FileTimeToTimeVal(&startTime, &tv); + data.insert("starttime", tv.tv_sec); + } + #endif + } + + cdevData & getServerData ( void ) + { + #if defined(__hpux) + struct pst_status pstatData; + pstat_getproc(&pstatData, sizeof(pstatData), 0, (int)getpid()); + data.insert("pctcpu", pstatData.pst_pctcpu); + data.insert("datasize", pageSize*(pstatData.pst_dsize+pstatData.pst_tsize+pstatData.pst_ssize)); + data.insert("sendPktCnt", sendPktCnt); + data.insert("recvPktCnt", recvPktCnt); + #endif + + return data; + } + + void asciiDump ( FILE * fp = stdout ) + { + fprintf(fp, "--------------------------------------------------------\n"); + fprintf(fp, " Printing Server Information\n"); + fprintf(fp, "--------------------------------------------------------\n"); + + char * server; + char * domain; + unsigned short port; + char * username; + char * group; + unsigned pid; + unsigned gid; + unsigned uid; + char * host; + char * os; + char * osrelease; + char * osversion; + char * machine; + char * shell; + char * program; + char * commandline; + long starttime; + size_t datasize; + float pctcpu; + + getServerData(); + + if(data.find("domain", (void *&)domain)!=CDEV_SUCCESS) host = NULL; + if(data.find("server", (void *&)server)!=CDEV_SUCCESS) server = NULL; + if(data.find("username", (void * &)username)!=CDEV_SUCCESS) username = NULL; + if(data.find("group", (void * &)group)!=CDEV_SUCCESS) group = NULL; + if(data.find("host", (void * &)host)!=CDEV_SUCCESS) host = NULL; + if(data.find("os", (void * &)os)!=CDEV_SUCCESS) os = NULL; + if(data.find("osrelease", (void * &)osrelease)!=CDEV_SUCCESS) osrelease = NULL; + if(data.find("osversion", (void * &)osversion)!=CDEV_SUCCESS) osversion = NULL; + if(data.find("machine", (void * &)machine)!=CDEV_SUCCESS) machine = NULL; + if(data.find("shell", (void * &)shell)!=CDEV_SUCCESS) shell=NULL; + if(data.find("program", (void * &)program)!=CDEV_SUCCESS) program=NULL; + if(data.find("commandline", (void * &)commandline)!=CDEV_SUCCESS) commandline=NULL; + if(data.get("port", &port)!=CDEV_SUCCESS) port = 0; + if(data.get("starttime", &starttime)!=CDEV_SUCCESS) starttime = 0; + if(data.get("pid", &pid)!=CDEV_SUCCESS) pid = 0; + if(data.get("gid", &gid)!=CDEV_SUCCESS) gid = 0; + if(data.get("uid", &uid)!=CDEV_SUCCESS) uid = 0; + if(data.get("datasize", &datasize)!=CDEV_SUCCESS) datasize = 0; + if(data.get("pctcpu", &pctcpu)!=CDEV_SUCCESS) pctcpu = (float)0.0; + + fprintf(fp, "=> DOMAIN : %s\n", domain?domain:"UNDEFINED"); + fprintf(fp, "=> SERVER : %s\n", server?server:"UNDEFINED"); + fprintf(fp, "=> LISTENING PORT : %s\n", port?ltoa(port):"UNDEFINED"); + fprintf(fp, "=> USERNAME : %s\n", username?username:"UNDEFINED"); + fprintf(fp, "=> GROUP : %s\n", group?group:"UNDEFINED"); + fprintf(fp, "=> USER ID : %s\n", uid?ltoa(uid):"UNDEFINED"); + fprintf(fp, "=> GROUP ID : %s\n", gid?ltoa(gid):"UNDEFINED"); + fprintf(fp, "=> PROCESS ID : %s\n", pid?ltoa(pid):"UNDEFINED"); + fprintf(fp, "=> APPLICATION : %s\n", program?program:"UNDEFINED"); + fprintf(fp, "=> COMMAND LINE : %s\n", commandline?commandline:"UNDEFINED"); + fprintf(fp, "=> START TIME : %s", starttime?ctime(&starttime):"UNKNOWN\n"); + fprintf(fp, "=> HOST NAME : %s\n", host?host:"UNKNOWN"); + fprintf(fp, "=> OS : %s\n", os?os:"UNKNOWN"); + fprintf(fp, "=> OS VERSION : %s\n", osversion?osversion:"UNKNOWN"); + fprintf(fp, "=> OS RELEASE : %s\n", osrelease?osrelease:"UNKNOWN"); + fprintf(fp, "=> HARDWARE ID : %s\n", machine?machine:"UNKNOWN"); + fprintf(fp, "=> PERCENT CPU : %f\n", pctcpu); + fprintf(fp, "=> RESIDENT SIZE : %i\n", datasize); + fprintf(fp, "=> PACKETS SENT : %i\n", sendPktCnt); + fprintf(fp, "=> PACKETS RECV : %i\n", recvPktCnt); + fprintf(fp, "=> ACTIVE CLIENTS : %i\n", clientCnt); + fprintf(fp, "--------------------------------------------------------\n"); + } +}; diff --git a/extensions/cdevGenericServer/common/SignalManager.cc b/extensions/cdevGenericServer/common/SignalManager.cc new file mode 100755 index 0000000..1c68328 --- /dev/null +++ b/extensions/cdevGenericServer/common/SignalManager.cc @@ -0,0 +1,257 @@ +#include + +#ifdef __linux + +#ifndef SIGSYS +#define SIGSYS SIGUNUSED +#endif + +#endif + +// ***************************************************************************** +// * SignalManager::reporter : +// * This is the declaration for the error reporter. +// ***************************************************************************** +ErrorReporter SignalManager::reporter; + +// ***************************************************************************** +// * SignalHandler::SignalHandler : +// * This is the initializer for a SignalHandler class. It holds the +// * information needed to handle a single signal number. +// ***************************************************************************** +_SignalHandler_::_SignalHandler_ ( void ) + : signo(0), handler(NULL), oldHandler(NULL) + { + } + +// ***************************************************************************** +// * SignalHandler::~SignalHandler : +// * This is the destructor for the SignlaHandler class. It will call the +// * uninstall method to remove the handler that was imposed for the signal. +// ***************************************************************************** +_SignalHandler_::~_SignalHandler_ ( void ) + { + uninstall (); + } + +// ***************************************************************************** +// * SignalHandler::install : +// * This method will install the specified signal handler function on the +// * signal number specified by signo. The old handler will be preserved +// * for later restoration. +// ***************************************************************************** +void _SignalHandler_::install ( int newSigno, SignalHandlerFunc newHandler ) + { + // ********************************************************************* + // * If a local signal handler has already been installed on the + // * specified signal number, uninstall it before proceeding. + // ********************************************************************* + if(handler!=NULL && signo==newSigno) uninstall(); + + // ********************************************************************* + // * Setup the control variables. + // ********************************************************************* + signo = newSigno; + handler = newHandler; + + // ********************************************************************* + // * Install the new signal handler, preserving the old handler in the + // * oact sigaction structure. + // ********************************************************************* + oldHandler = signal(signo, handler); + } + +// ***************************************************************************** +// * SignalHandler::uninstall : +// * This method will remove a user specified signal handler and will restore +// * the previously installed handler. +// ***************************************************************************** +void _SignalHandler_::uninstall ( void ) + { + // ********************************************************************* + // * Check to see if the signal handler has been installed. If so, + // * call sigaction to confirm that the current signal handler is the + // * one that was installed. + // ********************************************************************* + if(signo!=0 && handler!=NULL) + { + SignalHandlerFunc current = signal(signo, SIG_DFL); + if(current==handler) signal(signo, oldHandler); + else signal(signo, current); + } + + signo = 0; + handler = NULL; + } + +// ***************************************************************************** +// * SignalManager::installHandler : +// * This method will install the specified signal handler. +// ***************************************************************************** +void SignalManager::installHandler (int signo, SignalHandlerFunc handler ) + { + if(signo>0 && signo<=MAXSIGNAL) signals[signo-1].install(signo, handler); + } + +// ***************************************************************************** +// * SignalManager::uninstallHandler : +// * This method will remove a signal handler that was previously installed. +// ***************************************************************************** +void SignalManager::uninstallHandler ( int signo ) + { + if(signo>0 && signo<=MAXSIGNAL) signals[signo-1].uninstall(); + } + +// ***************************************************************************** +// * SignalManager::installDefaults : +// * This method will install a default collection of signal handlers. +// ***************************************************************************** +void SignalManager::installDefaults ( void ) + { + static int sigList[] = + { + #if !defined (_WIN32) + SIGFPE, // Erroneous arithmetic operation. + SIGHUP, // Hangup. + SIGILL, // Illegal instruction. + SIGINT, // Terminal interrupt signal. + SIGPIPE, // Write on a socket with no one to read + SIGQUIT, // Terminal quit signal. + SIGSEGV, // Invalid memory reference. + SIGTERM, // Termination signal. + SIGBUS, // Bus error. + SIGSYS, // Bad system call. + #else + SIGABRT, // Process abort signal. + SIGFPE, // Erroneous arithmetic operation. + SIGILL, // Illegal instruction. + SIGINT, // Terminal interrupt signal. + SIGSEGV, // Invalid memory reference. + SIGTERM, // Termination signal. + #endif + 0 + }; + + for(int i=0; sigList[i]!=0; i++) installHandler(sigList[i], defaultHandler); + } + +// ***************************************************************************** +// * SignalManager::defaultHandler : +// * This is the default signal handler method. +// ***************************************************************************** +void SignalManager::defaultHandler( int signo ) + { + switch(signo) + { + // ************************************************************* + // * Process the interrupt signal by reporting it and exiting. + // ************************************************************* + case SIGINT: + reporter.outputError ( + CDEV_SEVERITY_INFO, + "Signal Manager", + "[SIGINT] Terminating at user's request"); + exit(0); + + // ************************************************************* + // * Process the terminate signal by reporting it and exiting. + // ************************************************************* + case SIGTERM: + reporter.outputError ( + CDEV_SEVERITY_INFO, + "Signal Manager", + "[SIGTERM] Terminating normally"); + exit(0); + + // ************************************************************* + // * Process abort signal by reporting the error and exiting. + // ************************************************************* + case SIGABRT: + reporter.outputError ( + CDEV_SEVERITY_SEVERE, + "Signal Manager", + "[SIGABRT] Application terminating due to abort signal"); + abort(); + + + // ************************************************************* + // * Process erroneous arithmetic operations by reporting them + // * and exiting. + // ************************************************************* + case SIGFPE: + reporter.outputError ( + CDEV_SEVERITY_SEVERE, + "Signal Manager", + "[SIGFPE] Floating point error - terminating\n"); + abort(); + + + // ************************************************************* + // * Process illegal instructions by reporting them and exiting. + // ************************************************************* + case SIGILL: + reporter.outputError ( + CDEV_SEVERITY_SEVERE, + "Signal Manager", + "[SIGILL] Illegal instruction"); + abort(); + + // ************************************************************* + // * Process the segmentation fault signal by reporting the + // * error and terminating. + // ************************************************************* + case SIGSEGV: + reporter.outputError ( + CDEV_SEVERITY_SEVERE, + "Signal Manager", + "[SIGSEGV] Segmentation fault"); + abort(); + +#if !defined(_WIN32) + // ************************************************************* + // * Report pipe errors, however, do not terminate. + // ************************************************************* + case SIGPIPE: + reporter.outputError ( + CDEV_SEVERITY_ERROR, + "Signal Manager", + "[SIGPIPE] Write on a pipe with no one to read it"); + errno = SIGPIPE; + break; + + // ************************************************************* + // * Process a bus error by reporting it and exiting. + // ************************************************************* + case SIGBUS: + reporter.outputError ( + CDEV_SEVERITY_SEVERE, + "Signal Manager", + "[SIGBUS] Bus error"); + abort(); + + // ************************************************************* + // * Process a bad system call by reporting it and exiting. + // ************************************************************* + case SIGSYS: + reporter.outputError ( + CDEV_SEVERITY_SEVERE, + "Signal Manager", + "[SIGSYS] Bad system call"); + abort(); + + // ************************************************************* + // * Ignore the following signals: + // * SIGHUP: hangup signal. + // * SIGQUIT: terminal quit signal + // * default: All other signals + // ************************************************************* + case SIGHUP: + case SIGQUIT: +#endif + + default: + break; + } + signal(signo, SignalManager::defaultHandler); + } + diff --git a/extensions/cdevGenericServer/common/SignalManager.h b/extensions/cdevGenericServer/common/SignalManager.h new file mode 100755 index 0000000..afcabe7 --- /dev/null +++ b/extensions/cdevGenericServer/common/SignalManager.h @@ -0,0 +1,41 @@ +#ifndef _SIGNAL_MANAGER_H_ +#define _SIGNAL_MANAGER_H_ + +#include +#include +#include +#include + +typedef void (*SignalHandlerFunc)( int ); + +class GENERIC_SERVER_API _SignalHandler_ +{ +public: + _SignalHandler_ ( void ); + ~_SignalHandler_ ( void ); + void install ( int, SignalHandlerFunc); + void uninstall ( void ); + +private: + int signo; + SignalHandlerFunc handler; + SignalHandlerFunc oldHandler; +}; + +class GENERIC_SERVER_API SignalManager +{ +public: + static ErrorReporter reporter; + + void installHandler ( int, SignalHandlerFunc ); + void uninstallHandler ( int ); + void installDefaults ( void ); + + static void defaultHandler ( int ); + +private: + enum { MAXSIGNAL = 34 }; + _SignalHandler_ signals[MAXSIGNAL]; +}; + +#endif /* _SIGNAL_MANAGER_H_ */ diff --git a/extensions/cdevGenericServer/common/SignalManagerTest.cc b/extensions/cdevGenericServer/common/SignalManagerTest.cc new file mode 100755 index 0000000..c36e138 --- /dev/null +++ b/extensions/cdevGenericServer/common/SignalManagerTest.cc @@ -0,0 +1,25 @@ +#include + + +int x = 1; +void SIGINT_Handler ( int signo ) + { + SignalManager::reporter.outputError ( + CDEV_SEVERITY_INFO, + "Signal Manager", + "[SIGINT] Ignoring interrupt signal"); + signal(signo, SIGINT_Handler); + x++; + } + +int main () + { + SignalManager manager; + manager.installDefaults(); + manager.installHandler (SIGINT, SIGINT_Handler); + while(1) + { + if(x%5==0) raise(SIGABRT); + } + return 0; + } diff --git a/extensions/cdevGenericServer/common/SocketUtil.h b/extensions/cdevGenericServer/common/SocketUtil.h new file mode 100755 index 0000000..e207388 --- /dev/null +++ b/extensions/cdevGenericServer/common/SocketUtil.h @@ -0,0 +1,545 @@ +#if !defined (_SOCKET_UTIL_H) +#define _SOCKET_UTIL_H + +#include +#include +#include + +class SocketReader : virtual public ErrorReporter +{ +public: + enum { SHUTDOWN_CODE = -128}; + enum { MAX_RETRIES = 1000 }; + enum { READBUF_INITIAL_SIZE = 56000 }; + + virtual int getHandle ( void ) const = 0; + + SocketReader ( long MagicNumber = 0L ); + ~SocketReader ( void ); + + int read ( char ** buf, int * len ); + virtual int readNextPacket ( char ** buf, int * len ); + virtual int reading ( void ); + virtual int readReset ( void ); + +private: + char * readBuf; + char * readNextPktPtr; + int readBufMax; + int readPktCnt; + int readPktXfrCnt; + + int readBufLen; + int readXfrLen; + int readPktXfrLen; + int readRetries; + + // *************************** + // * This section added to + // * optionally support magic + // * number for buffer + // * validation. + // *************************** + const long readMagicNumber; + int readMagicLen; + long readMagicVal; +}; + + +class SocketWriter : virtual public ErrorReporter +{ +public: + enum { WRITEBUF_INITIAL_SIZE = 56000 }; + enum { WRITEBUF_PAD_SIZE = 32 }; + + virtual int getHandle ( void ) const = 0; + + SocketWriter ( long MagicNumber = 0L ); + ~SocketWriter ( void ); + + int write ( char * buf, int buflen); + int writeEnqueue ( char * buf, int buflen); + virtual int writing ( void ); + virtual int writeContinue ( void ); + virtual int writeReset ( void ); + virtual int writeGoodbye ( void ); + +private: + char * writeBuf; + char * writeNextPktPtr; + int writeBufMax; + int writePktCnt; + + int writeBufLen; + int writeXfrLen; + int writePktXfrLen; + + // *************************** + // * This section added to + // * optionally support magic + // * number for buffer + // * validation. + // *************************** + const long writeMagicNumber; + int writeMagicLen; +}; + + +inline SocketReader::SocketReader ( long MagicNumber ) + : readBuf(NULL), readNextPktPtr(NULL), readBufMax(READBUF_INITIAL_SIZE), + readPktCnt(0), readPktXfrCnt(0), readBufLen(0), readXfrLen(0), + readPktXfrLen(0), readRetries(0), + // ************************* + // * Magic number support. + // ************************* + readMagicNumber(MagicNumber), readMagicLen(0), readMagicVal(0L) + { + readBuf = (char *)malloc(readBufMax); + readNextPktPtr = readBuf+RNDUP(sizeof(long)); + } + +inline SocketReader::~SocketReader ( void ) + { + if(readBuf!=NULL) free(readBuf); + } + +inline int SocketReader::reading ( void ) + { + return (readPktCnt>readPktXfrCnt)?1:0; + } + +inline int SocketReader::readReset ( void ) + { + readNextPktPtr = readBuf+RNDUP(sizeof(long)); + readBufLen = 0; + readXfrLen = 0; + readPktCnt = 0; + readPktXfrCnt = 0; + readPktXfrLen = 0; + readMagicLen = 0; + readMagicVal = 0L; + return 0; + } + +// ***************************************************************************** +// * This method causes the next available packet to be dequeued from the +// * already read buffer. +// ***************************************************************************** +inline int SocketReader::readNextPacket (char ** buf, int *buflen) + { + if(readPktCnt>readPktXfrCnt) + { + *buflen = (int)ntohl(*(long *)readNextPktPtr); + readNextPktPtr+=RNDUP(sizeof(long)); + *buf = readNextPktPtr; + readNextPktPtr+=RNDUP(*buflen); + readPktXfrCnt++; + } + else { + *buf = NULL; + *buflen = 0; + } + if(readPktXfrCnt>=readPktCnt) readReset(); + return *buflen; + } + + +// ***************************************************************************** +// * This method will get the next available packet from the socket. The caller +// * is responsible for transfering this data to a new location immediately. +// * The caller should not delete the pointer provided by this method, or rely +// * on it to remain valid between calls. +// ***************************************************************************** +inline int SocketReader::read(char ** buf, int * buflen) + { + int handle = getHandle(); + int result = 0; + int shutdown = 0; + int error = 0; + *buf = NULL; + *buflen = 0; + + // ********************************************************************* + // * First test to ensure that the socket is allocated and that the + // * device descriptor is valid. + // ********************************************************************* + if(handle<=0) result = -1; + // ********************************************************************* + // * If the handle is valid attempt to read the next packet of a + // * multi-packet set from an already existing buffer. + // ********************************************************************* + else if(reading()) result = readNextPacket(buf, buflen); + // ********************************************************************* + // * If all packets in the most recent multi-packet set have already + // * been read... Then attempt to read a new block from the socket. + // ********************************************************************* + else { + int amntread = 0; + char *readPtr = NULL; + + // ************************************************************* + // * Optionally read the magic number from the socket. + // ************************************************************* + readPtr = (char *)&readMagicVal; + while(readMagicNumber && readMagicLen0) + { + // ***************************************************** + // * Anytime a read is successful, set the readRetries + // * variable to 0. + // ***************************************************** + readRetries = 0; + // ***************************************************** + // * Once an entire long integer is read from the socket + // * validate that against the Magic Number that is + // * expected. + // ***************************************************** + if((readMagicLen += amntread)>=sizeof(long)) + { + readMagicVal = ntohl(readMagicVal); + + // ********************************************* + // * If the Magic Number received is not the + // * same as the Magic Number expected, set the + // * shutdown flag and kill the connection. + // ********************************************* + if(readMagicVal!=readMagicNumber) + { + outputError (CDEV_SEVERITY_ERROR, "SocketReader", + "Invalid magic number read from socket\n\t=> Expected %lX - received %lX", + readMagicNumber, readMagicVal); + shutdown = 1; + } + } + } + + // ************************************************************* + // * Read the size of the packet from the socket... note, this + // * code will not be executed until the Magic Number has been + // * successfully read. + // ************************************************************* + readPtr = (char *)&readBufLen; + while(!shutdown && readPktXfrLen=sizeof(long)) && + (amntread = recv(handle, + readPtr+readPktXfrLen, + sizeof(long)-readPktXfrLen, 0))>0) + { + // ***************************************************** + // * Anytime a read is successful, set the readRetries + // * variable to 0. + // ***************************************************** + readRetries = 0; + // ***************************************************** + // * Once an entire long integer is read from the socket + // * use that variable as the expected packet length, + // * and allocate a buffer of sufficient size to hold + // * the incoming packet. + // ***************************************************** + if((readPktXfrLen += amntread)>=sizeof(long)) + { + readBufLen = ntohl(readBufLen); + // ********************************************* + // * A length of -1 indicates that the socket + // * should be shutdown. + // ********************************************* + if(readBufLen == -1) shutdown = 1; + if(readBufLen <= 0) readReset(); + else { + if(readBufLen>readBufMax) + { + readBufMax = readBufLen; + readBuf = (char *)realloc(readBuf, readBufMax); + readNextPktPtr = readBuf+RNDUP(sizeof(long)); + } + readXfrLen = 0; + } + } + } + + // ************************************************************* + // * Continue reading from the socket into the new buffer until + // * the amount of data specified by the readBufLen variable + // * has been obtained, or no further data is available. + // ************************************************************* + while(!shutdown && + readPktXfrLen>=sizeof(long) && + readXfrLen < readBufLen && + (amntread = recv(handle, readBuf+readXfrLen, readBufLen-readXfrLen, 0))>0) + { + // ***************************************************** + // * Anytime a read is successful, set the readRetries + // * variable to 0. + // ***************************************************** + readRetries = 0; + + // ***************************************************** + // * Once a complete buffer of data has been read from + // * the socket, use the readNextPacket method to set + // * the user pointer to the appropriate position within + // * the data buffer. + // ***************************************************** + if((readXfrLen+=amntread)>=readBufLen) + { + readPktCnt = (int)ntohl(*(long *)readBuf); + result = readNextPacket(buf, buflen); + } + } + + // ************************************************************* + // * If an error occurred, or the function failed to read + // * data from the socket, then this section of code will be + // * executed. + // ************************************************************* + if(!shutdown && amntread<=0) + { + int errCode = GetSocketErrno(); + + // ***************************************************** + // * Increment the readRetries to count the number of + // * empty receives. Once this variable reaches the + // * MAX_RETRIES value, a -1 will be returned to delete + // * the socket. + // ***************************************************** + readRetries++; + + // ***************************************************** + // * If the amntread is 0 or -1 (and any error was + // * caused by blocking), and the maximum number of + // * retries has not been reached, do the following + // ***************************************************** + if(readRetries < MAX_RETRIES && + ((amntread==0 && readPktXfrLen>0) || + (amntread==-1 && (errCode == EWOULDBLOCK || errCode == EAGAIN)))) + { + result = 0; + } + // ***************************************************** + // * Otherwise, if the maximum number of retries have + // * been reached, do the following + // ***************************************************** + else if(readRetries >= MAX_RETRIES) + { + outputError (CDEV_SEVERITY_WARN, "SocketReader", + "Have exceeded maximum retries on socket"); + result = -1; + } + // ***************************************************** + // * Otherwise, if the error was not due to blocking, + // * do the following + // ****************************************************** + else if(amntread==-1) + { + outputError (CDEV_SEVERITY_ERROR, "SocketReader", + "Error number %i while reading from socket", + errCode); + result = -1; + } + } + } + + if(shutdown) result = SHUTDOWN_CODE; + if(result==-1) readReset(); + return result; + } + + +inline SocketWriter::SocketWriter ( long MagicNumber ) + : writeBuf(NULL), writeNextPktPtr(NULL), writeBufMax(WRITEBUF_INITIAL_SIZE), + writePktCnt(0), writeBufLen(RNDUP(sizeof(long))), writeXfrLen(0), writePktXfrLen(0), + // ************************* + // * Magic number support. + // ************************* + writeMagicNumber(MagicNumber), writeMagicLen(0) + { + writeBuf = (char *)malloc(writeBufMax); + writeNextPktPtr = writeBuf+writeBufLen; + } + +inline SocketWriter::~SocketWriter ( void ) + { + if(writeBuf!=NULL) free(writeBuf); + } + +inline int SocketWriter::writing ( void ) + { + return (writePktCnt>0)?1:0; + } + +inline int SocketWriter::writeReset ( void ) + { + writeBufLen = RNDUP(sizeof(long)); + writeNextPktPtr = writeBuf+writeBufLen; + writePktCnt = 0; + writeXfrLen = 0; + writePktXfrLen = 0; + + // ************************* + // * Magic number support. + // ************************* + writeMagicLen = 0; + return 0; + } + +inline int SocketWriter::writeContinue ( void ) + { + int handle = getHandle(); + int result = 0; + + // ********************************************************************* + // * The following variable has been added to allow the SocketWriter + // * to poll the file descriptor for validity prior to writing to it. + // ********************************************************************* +#ifdef SYSV + struct pollfd fds; + fds.fd = handle; + fds.events = POLLERR|POLLNVAL|POLLHUP; + fds.revents = 0; + + // ********************************************************************* + // * First test to ensure that the socket is allocated and that the + // * device descriptor is valid. + // ********************************************************************* + if( handle<=0 ) result = -1; + // ********************************************************************* + // * Execute poll to ensure that the handle is still valid and writable. + // ********************************************************************* + else if(poll(&fds, 1, 0)>0 && (fds.revents&(POLLERR|POLLNVAL|POLLHUP))!=0) + { + result = -1; + } +#else + cdevHandleSet readfd; + struct timeval tv; + + readfd.set_bit(handle); + tv.tv_sec = 0; + tv.tv_usec = 0; + + if (handle<=0) result = -1; + else if (cdevSelect (handle+1,readfd,0,0,&tv)<0) result = -1; +#endif + // ********************************************************************* + // * If all is well, continue writing data. + // ********************************************************************* + else if( writing() ) + { + int amntsent = 0; + char *sendPtr = NULL; + long magicNumber = htonl(writeMagicNumber); + long packetSize = htonl(writeBufLen); + + sendPtr = (char *)&magicNumber; + while(writeMagicNumber && writeMagicLen0) + { + writeMagicLen += amntsent; + } + + sendPtr = (char *)&packetSize; + while((!writeMagicNumber || writeMagicLen>=sizeof(long)) && writePktXfrLen0) + { + writePktXfrLen += amntsent; + } + + while(writePktXfrLen>=sizeof(long) && + writeXfrLen < writeBufLen && + (amntsent = send(handle, writeBuf+writeXfrLen, writeBufLen-writeXfrLen, 0))>0) + { + if((writeXfrLen+=amntsent)>=writeBufLen) + { + result = writeBufLen; + writeReset(); + } + } + + if(amntsent<=0) + { + int errCode = GetSocketErrno(); + + if((amntsent==0 && writePktXfrLen>0) || + (amntsent==-1 && (errCode == EWOULDBLOCK || errCode == EAGAIN))) + { + // ********************************************* + // * Do Nothing + // ********************************************* + } + else if(amntsent==-1) + { + outputError (CDEV_SEVERITY_ERROR, "SocketWriter", + "Error number %i while writing to socket", + errCode); + result = -1; + } + } + } + + if(result==-1) writeReset(); + return result; + } + +inline int SocketWriter::writeGoodbye ( void ) + { + int handle = getHandle(); + int result = 0; + + if( handle<=0 ) result = -1; + else + { + char val = -1; + result=(send(handle, &val, 1, MSG_OOB)==1)?0:-1; + } + + if(result==-1) writeReset(); + return result; + } + +inline int SocketWriter::writeEnqueue ( char * buf, int buflen ) + { + int result = 0; + + // ********************************************************************* + // * If data has already been transmitted, then it is impossible to + // * add more data to the outbound buffer because it would invalidate + // * the packet length and packet count variables. + // ********************************************************************* + if(writePktXfrLen>0) result = -1; + else + { + if(writePktCnt==0 && + (RNDUP(sizeof(long))+RNDUP(buflen)+RNDUP(sizeof(long))) > writeBufMax) + { + writeBufMax = (RNDUP(sizeof(long))+RNDUP(buflen)+RNDUP(sizeof(long))+WRITEBUF_PAD_SIZE); + writeBuf = (char *)realloc(writeBuf, writeBufMax); + writeBufLen = RNDUP(sizeof(long)); + writeNextPktPtr = writeBuf+writeBufLen; + } + if(writeBufLen+RNDUP(buflen)+RNDUP(sizeof(long)) < writeBufMax) + { + writePktCnt++; + long tpktCnt = htonl(writePktCnt); + memcpy(writeBuf, &tpktCnt, sizeof(long)); + + long tbuflen = htonl(buflen); + memcpy(writeNextPktPtr, &tbuflen, sizeof(long)); + writeNextPktPtr+=RNDUP(sizeof(long)); + memcpy(writeNextPktPtr, buf, buflen); + writeNextPktPtr+=RNDUP(buflen); + writeBufLen = (int)(writeNextPktPtr-writeBuf); + result = 0; + } + else result = -1; + } + return result; + } + +inline int SocketWriter::write(char * buf, int buflen) + { + writeEnqueue(buf, buflen); + return writeContinue(); + } + +#endif /* _SOCKET_UTIL_H */ diff --git a/extensions/cdevGenericServer/common/StringHash.h b/extensions/cdevGenericServer/common/StringHash.h new file mode 100755 index 0000000..afdfb40 --- /dev/null +++ b/extensions/cdevGenericServer/common/StringHash.h @@ -0,0 +1,235 @@ +#ifndef _VAR_STRING_HASH_H_ +#define _VAR_STRING_HASH_H_ 1 + +#include +#include +#include + +class StringHashNode +{ +friend class StringHash; +friend class StringHashIterator; + +private: + int copyKeyFlag; + char * hashString; + void * hashData; + StringHashNode * next; + + StringHashNode ( char * HashString, void * HashData, int copyKey=1); + ~StringHashNode ( void ); +}; + + +class StringHash +{ +friend class StringHashIterator; + +private: + int tableSize; + int copyKeyFlag; + StringHashNode ** nodes; + +public: + StringHash (int copyKey = 1, int TableSize = 255 ); + ~StringHash ( void ); + + inline unsigned int stringHash ( char * hashString ); + + inline void insert ( char * hashString, void * hashData ); + inline void remove ( char * hashString ); + inline void * find ( char * hashString ); +}; + + +class StringHashIterator +{ +private: + StringHash * hashTbl; + StringHashNode * node; + int idx; + +public: + StringHashIterator( StringHash * HashTbl ); + ~StringHashIterator( void ); + + inline void * first ( void ); + inline void * operator ++ ( void ); + inline void * operator ++ ( int x ); + inline char * key ( void ); + inline void * data ( void ); +}; + + +inline StringHashNode::StringHashNode ( char * HashString, void * HashData, int copyKey ) + : next(NULL), copyKeyFlag(copyKey) + { + if(copyKeyFlag) hashString = strdup(HashString); + else hashString = HashString; + hashData = HashData; + } + + +inline StringHashNode::~StringHashNode ( void ) + { + if(copyKeyFlag) delete hashString; + } + + +inline StringHash::StringHash ( int copyKey, int TableSize ) + : copyKeyFlag(copyKey), tableSize (TableSize) + { + nodes = new StringHashNode * [tableSize]; + memset(nodes, 0, sizeof(StringHashNode *) * tableSize ); + } + + +inline StringHash::~StringHash ( void ) + { + for(int i=0; inext; + delete node; + } + } + delete nodes; + } + +inline unsigned int StringHash::stringHash ( char * hashString ) + { + unsigned int hash = 0, g; + + for (int i = 0; hashString[i] != '\0'; i++) + { + hash = (hash << 4) + hashString[i]; + if (g = hash & 0xf0000000) + { + hash ^= g >> 24; + hash ^= g; + } + } + return (hash % tableSize); + } + +inline void StringHash::insert (char * hashString, void * hashData ) + { + unsigned int idx = stringHash(hashString); + StringHashNode * prev = NULL, * node = nodes[idx]; + StringHashNode * newNode = new StringHashNode(hashString, hashData, copyKeyFlag); + + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + newNode->next = node->next; + delete node; + } + if(prev!=NULL) prev->next = newNode; + else nodes[idx] = newNode; + } + +inline void StringHash::remove ( char * hashString ) + { + unsigned int idx = stringHash(hashString); + StringHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + if(prev!=NULL) prev->next = node->next; + else nodes[idx] = node->next; + delete node; + } + } + +inline void * StringHash::find ( char * hashString ) + { + unsigned int idx = stringHash(hashString); + StringHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + return node!=NULL?node->hashData:NULL; + } + + +inline StringHashIterator::StringHashIterator(StringHash * HashTbl) + : hashTbl(HashTbl), idx(0), node(NULL) + { + } + +inline StringHashIterator::~StringHashIterator( void ) + { + } + +inline void * StringHashIterator::first ( void ) + { + if(hashTbl!=NULL) + { + for(idx = 0; idxtableSize && + (node = hashTbl->nodes[idx])==NULL; idx++); + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * StringHashIterator::operator ++ ( void ) + { + if(hashTbl!=NULL) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxtableSize && + (node = hashTbl->nodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * StringHashIterator::operator ++ ( int x ) + { + if(hashTbl!=NULL && x==0) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxtableSize && + (node = hashTbl->nodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline char * StringHashIterator::key ( void ) + { + return (node!=NULL)?node->hashString:(char *)NULL; + } + +inline void * StringHashIterator::data ( void ) + { + return (node!=NULL)?node->hashData:NULL; + } + +#endif /* _VAR_STRING_HASH_H_ */ diff --git a/extensions/cdevGenericServer/common/VarStrHash.h b/extensions/cdevGenericServer/common/VarStrHash.h new file mode 100755 index 0000000..ccb93d0 --- /dev/null +++ b/extensions/cdevGenericServer/common/VarStrHash.h @@ -0,0 +1,235 @@ +#ifndef _VAR_STRING_HASH_H_ +#define _VAR_STRING_HASH_H_ 1 + +#include +#include +#include + +class VarStrHashNode +{ +friend class VarStrHash; +friend class VarStrHashIterator; + +private: + int copyKeyFlag; + char * hashString; + void * hashData; + VarStrHashNode * next; + + VarStrHashNode ( char * HashString, void * HashData, int copyKey=1); + ~VarStrHashNode ( void ); +}; + + +class VarStrHash +{ +friend class VarStrHashIterator; + +private: + int tableSize; + int copyKeyFlag; + VarStrHashNode ** nodes; + +public: + VarStrHash (int copyKey = 1, int TableSize = 255 ); + ~VarStrHash ( void ); + + inline unsigned char stringHash ( char * hashString ); + + inline void insert ( char * hashString, void * hashData ); + inline void remove ( char * hashString ); + inline void * find ( char * hashString ); +}; + + +class VarStrHashIterator +{ +private: + VarStrHash * hashTbl; + VarStrHashNode * node; + int idx; + +public: + VarStrHashIterator( VarStrHash * HashTbl ); + ~VarStrHashIterator( void ); + + inline void * first ( void ); + inline void * operator ++ ( void ); + inline void * operator ++ ( int x ); + inline char * key ( void ); + inline void * data ( void ); +}; + + +inline VarStrHashNode::VarStrHashNode ( char * HashString, void * HashData, int copyKey ) + : next(NULL), copyKeyFlag(copyKey) + { + if(copyKeyFlag) hashString = strdup(HashString); + else hashString = HashString; + hashData = HashData; + } + + +inline VarStrHashNode::~VarStrHashNode ( void ) + { + if(copyKeyFlag) delete hashString; + } + + +inline VarStrHash::VarStrHash ( int copyKey, int TableSize ) + : copyKeyFlag(copyKey), tableSize (TableSize) + { + nodes = new VarStrHashNode * [tableSize]; + memset(nodes, 0, sizeof(VarStrHashNode *) * tableSize ); + } + + +inline VarStrHash::~VarStrHash ( void ) + { + for(int i=0; inext; + delete node; + } + } + } + +inline unsigned char VarStrHash::stringHash ( char * hashString ) + { + unsigned char idx=0; + unsigned int hash = 0, g; + + for (int i = 0; hashString[i] != '\0'; i++) + { + hash = (hash << 4) + hashString[i]; + if (g = hash & 0xf0000000) + { + hash ^= g >> 24; + hash ^= g; + } + } + return (hash % tableSize); + } + +inline void VarStrHash::insert (char * hashString, void * hashData ) + { + unsigned char idx = stringHash(hashString); + VarStrHashNode * prev = NULL, * node = nodes[idx]; + VarStrHashNode * newNode = new VarStrHashNode(hashString, hashData, copyKeyFlag); + + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + newNode->next = node->next; + delete node; + } + if(prev!=NULL) prev->next = newNode; + else nodes[idx] = newNode; + } + +inline void VarStrHash::remove ( char * hashString ) + { + unsigned char idx = stringHash(hashString); + VarStrHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + if(prev!=NULL) prev->next = node->next; + else nodes[idx] = node->next; + delete node; + } + } + +inline void * VarStrHash::find ( char * hashString ) + { + unsigned char idx = stringHash(hashString); + VarStrHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + return node!=NULL?node->hashData:NULL; + } + + +inline VarStrHashIterator::VarStrHashIterator(VarStrHash * HashTbl) + : hashTbl(HashTbl), idx(0), node(NULL) + { + } + +inline VarStrHashIterator::~VarStrHashIterator( void ) + { + } + +inline void * VarStrHashIterator::first ( void ) + { + if(hashTbl!=NULL) + { + for(idx = 0; idxtableSize && + (node = hashTbl->nodes[idx])==NULL; idx++); + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * VarStrHashIterator::operator ++ ( void ) + { + if(hashTbl!=NULL) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxtableSize && + (node = hashTbl->nodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * VarStrHashIterator::operator ++ ( int x ) + { + if(hashTbl!=NULL && x==0) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxtableSize && + (node = hashTbl->nodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline char * VarStrHashIterator::key ( void ) + { + return (node!=NULL)?node->hashString:NULL; + } + +inline void * VarStrHashIterator::data ( void ) + { + return (node!=NULL)?node->hashData:NULL; + } + +#endif /* _VAR_STRING_HASH_H_ */ diff --git a/extensions/cdevGenericServer/common/cdevGenericServerTags.h b/extensions/cdevGenericServer/common/cdevGenericServerTags.h new file mode 100755 index 0000000..04852b9 --- /dev/null +++ b/extensions/cdevGenericServer/common/cdevGenericServerTags.h @@ -0,0 +1,66 @@ +static char * cdevGenericServerTags[] = + { + "client", + "clientCnt", + "commandline", + "connecttime", + "datasize", + "domain", + "gid", + "group", + "host", + "key", + "keyExp", + "keyType", + "machine", + "name", + "os", + "osrelease", + "osversion", + "owner", + "pctcpu", + "pid", + "ping", + "port", + "program", + "queryMsg", + "recvPktCnt", + "resultCode", + "sendPktCnt", + "server", + "shell", + "socket", + "starttime", + "table", + "time", + "uid", + "username", + NULL + }; + +class cdevGenericServerTagDef +{ +public: + enum {GENERIC_BASE_TAG=900}; + + cdevGenericServerTagDef ( void ) + { + installTags(); + } + + void installTags ( void ) + { + + for(int i=0; cdevGenericServerTags[i]!=NULL; i++) + { + int tagVal; + + cdevData::insertTag(GENERIC_BASE_TAG+i, cdevGenericServerTags[i]); + if(cdevData::tagC2I(cdevGenericServerTags[i], &tagVal)!=CDEV_SUCCESS) + { + cdevData::addTag(cdevGenericServerTags[i]); + } + } + } +}; + diff --git a/extensions/cdevGenericServer/common/cdevPlatforms.h b/extensions/cdevGenericServer/common/cdevPlatforms.h new file mode 100755 index 0000000..f0d95d3 --- /dev/null +++ b/extensions/cdevGenericServer/common/cdevPlatforms.h @@ -0,0 +1,334 @@ +#ifndef _CDEV_PLATFORMS_H_ +#define _CDEV_PLATFORMS_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 + #include + + #ifndef CDEV_REACTOR_API + // ********************************************************************* + // * _CDEV_REACTOR_EXPORTS : + // * This definition allows cdevReactor DLL components to be imported + // * and exported by other applications and libraries. + // ********************************************************************* + #ifdef _CDEV_REACTOR_EXPORTS_ + #define CDEV_REACTOR_API __declspec(dllexport) + #else + #define CDEV_REACTOR_API __declspec(dllimport) + #endif + #endif + + #ifndef GENERIC_SERVER_API + // ********************************************************************* + // * _GENERIC_SERVER_EXPORTS : + // * This definition allows Generic Server DLL components to be imported + // * and exported by other applications and libraries. + // ********************************************************************* + #ifdef _GENERIC_SERVER_EXPORTS_ + #define GENERIC_SERVER_API __declspec(dllexport) + #else + #define GENERIC_SERVER_API __declspec(dllimport) + #endif + #endif + + #include + #include + #include + #include + #include + #include + #include + #include + + typedef signed long ssize_t; + + #define MAXHOSTNAMELEN 128 + #define EWOULDBLOCK WSAEWOULDBLOCK + #define EINPROGRESS WSAEINPROGRESS + #define EISCONN WSAEISCONN + #define SELECT_PARM fd_set * + + #ifndef O_NONBLOCK + #define O_NONBLOCK 1 + #endif + + // ********************************************************************* + // * SOCKOPT_SIZE_PARM : + // * This is the datatype of the parameter that is sent to getsockopt, + // * setsockopt, and getsockname. + // ********************************************************************* + typedef int SOCKOPT_SIZE_PARM; + + inline int GetSocketErrno ( void ) + { + return WSAGetLastError(); + } + + inline int GetSelectErrno ( void ) + { + return WSAGetLastError(); + } + + inline int InitializeNetwork ( void ) + { + WORD version_requested = MAKEWORD (2, 0); + WSADATA wsa_data; + return WSAStartup(version_requested, &wsa_data); + } + + inline int TerminateNetwork ( void ) + { + return WSACleanup(); + } + + inline char * ultoa ( unsigned long val ) + { + static char buf[64]; + return _ultoa(val, buf, 10); + } + + inline char * ltoa ( long val ) + { + static char buf[64]; + return _ltoa(val, buf, 10); + } + + inline int usleep ( unsigned int useconds ) + { + int retval = 0; + if(useconds<100000) Sleep(useconds/1000); + else retval = -1; + return retval; + } + + inline unsigned int sleep ( unsigned int seconds ) + { + Sleep(seconds*1000); + return seconds; + } + + // ********************************************************************* + // * This version of pipe is provided because the file descriptors + // * generated by the Windows NT version of pipe cannot be used with the + // * select system call. + // ********************************************************************* + inline int pipe ( int fd[2] ) + { + int retval = 0; + sockaddr_in addr[2]; + hostent * hostptr; + char hostname[MAXHOSTNAMELEN]; + unsigned long ipAddr; + unsigned long blockFlag = 1; + + gethostname(hostname, MAXHOSTNAMELEN); + hostptr = ::gethostbyname(hostname); + ipAddr = *(unsigned long *)hostptr->h_addr; + + for(int i=0; i<2; i++) + { + addr[i].sin_family = AF_INET; + addr[i].sin_port = htons(0); + *(unsigned long *)&addr[i].sin_addr = ipAddr; + if((fd[i] = socket(PF_INET, SOCK_DGRAM,0))>0 && + bind(fd[i], (sockaddr *)&addr[i], sizeof(addr[i]))==0) + { + int addrLen = sizeof(addr[i]); + getsockname(fd[i], (sockaddr *)&addr[i], &addrLen); + ioctlsocket(fd[i], FIONBIO, &blockFlag); + } + else fd[i] = -1; + } + if(fd[0]>0 && fd[1]>0) + { + ::connect(fd[0], (sockaddr *)&addr[1], sizeof(addr[1])); + ::connect(fd[1], (sockaddr *)&addr[0], sizeof(addr[0])); + } + else + { + if(fd[0]>0) close(fd[0]); + if(fd[1]>0) close(fd[1]); + fd[0] = (fd[1] = (retval = -1)); + } + return retval; + } + + inline int FileTimeToTimeVal ( FILETIME * tfile, struct timeval * tv ) + { + if(tfile && tv) + { + ULARGE_INTEGER _100ns = {tfile->dwLowDateTime, + tfile->dwHighDateTime}; + + _100ns.QuadPart -= 0x19db1ded53e8000i64; + + tv->tv_sec = long (_100ns.QuadPart / (10000 * 1000)); + tv->tv_usec = long ((_100ns.QuadPart % (10000 * 1000)) / 10); + + return 0; + } + return -1; + } + + inline int gettimeofday (struct timeval *tv) + { + FILETIME tfile; + + GetSystemTimeAsFileTime(&tfile); + + return FileTimeToTimeVal(&tfile, tv); + } + + inline int cdevSelect ( + int size, + fd_set * read_set, + fd_set * write_set, + fd_set * except_set, + struct timeval * timeout ) + { + int result = select(size, read_set, write_set, except_set, timeout); + + if(result<0 && GetSelectErrno()==WSAEINVAL) + { + if(timeout) + { + unsigned long millisec = timeout->tv_sec*1000+timeout->tv_usec/1000; + Sleep(millisec); + } + result = 0; + } + else if (result<0 && GetSelectErrno()==WSAEINPROGRESS) + { + result = 0; + } + return result; + } +#else + #include + + #define CDEV_REACTOR_API + #define GENERIC_SERVER_API + + #ifdef __VMS + #ifdef _TGV_MULTINET + // ***************************************************** + // * Under TGV multinet and VMS, if you want sys/types.h + // * you need to have types.h already pulled in because + // * sys/types.h makes it look like types.h is loaded. + // * Then when types.h does get loaded, it is ignored + // * because it looks like it is already loaded -- + // * Mr. Danial Van Olst + // ***************************************************** + #include + + // ***************************************************** + // * Under TGV Multinet and VMS, the file sys/param.h + // * does not define NOFILE (max number of open files + // * per process). FD_SETSIZE seems to be the correct + // * value for NOFILE. + // * See Multinet's sys/types.h file for more info on + // * FD_SETSIZE. - Daniel Van Olst + // ***************************************************** + #ifndef NOFILE + #define NOFILE FD_SETSIZE + #endif + #endif + #endif + + #ifdef SYSV + #include + #endif + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + + #if defined (__hpux) + #include + #endif + + #if defined (AIX) + #include + #endif + + #if defined(solaris) || defined(SunOS) + #include + extern "C" { int gethostname(char *name, int namelen); } + #endif + + #ifdef _SELECT_USES_INT_ + #define SELECT_PARM int * + #else + #define SELECT_PARM fd_set * + #endif + + #ifndef min + #define min(a,b) ((ab)?a:b) + #endif + + // ********************************************************************* + // * SOCKOPT_SIZE_PARM : + // * This is the datatype of the parameter that is sent to getsockopt, + // * setsockopt, and getsockname. + // ********************************************************************* + #if defined(AIX) || defined(__linux) + typedef unsigned int SOCKOPT_SIZE_PARM; + #else + typedef int SOCKOPT_SIZE_PARM; + #endif + + inline int GetSocketErrno ( void ) + { + return errno; + } + + inline int GetSelectErrno ( void ) + { + return errno; + } + + inline int InitializeNetwork ( void ) + { + return 0; + } + + inline int TerminateNetwork ( void ) + { + return 0; + } + + inline int gettimeofday (struct timeval * tv) + { + struct timezone tz; + + return ::gettimeofday(tv, &tz); + } + + inline int cdevSelect (int nfds, fd_set *r, fd_set *w, fd_set *e, struct timeval *t) + { + return ::select(nfds, (SELECT_PARM)r, (SELECT_PARM)w, (SELECT_PARM)e, t); + } +#endif + +#endif /* _CDEV_PLATFORMS_H_ */ diff --git a/extensions/cdevGenericServer/common/clipMagicNumber.h b/extensions/cdevGenericServer/common/clipMagicNumber.h new file mode 100755 index 0000000..5f4de2d --- /dev/null +++ b/extensions/cdevGenericServer/common/clipMagicNumber.h @@ -0,0 +1,8 @@ +// ***************************************************************************** +// * CLIP_MAGIC_NUMBER : +// * The magic number was added to the CLIP Protocol beginning with version +// * 1.6 of CDEV. This magic number will preceed the buffer length in +// * a clip buffer and will be used to validate that the client is using the +// * same protocol as the server. +// ***************************************************************************** +#define CLIP_MAGIC_NUMBER 0x434C4950 diff --git a/extensions/cdevGenericServer/common/fifo.cc b/extensions/cdevGenericServer/common/fifo.cc new file mode 100644 index 0000000..794ef71 --- /dev/null +++ b/extensions/cdevGenericServer/common/fifo.cc @@ -0,0 +1,2 @@ +#define _FIFO_QUEUE_MASTER_ 1 +#include diff --git a/extensions/cdevGenericServer/common/fifo.h b/extensions/cdevGenericServer/common/fifo.h new file mode 100755 index 0000000..ccecc22 --- /dev/null +++ b/extensions/cdevGenericServer/common/fifo.h @@ -0,0 +1,315 @@ +/*----------------------------------------------------------------------------- + * Copyright (c) 1991,1992 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + *----------------------------------------------------------------------------- + * + * Description: + * + * Author: Walt Akers + * + * Revision History: + * fifo.h,v + * Revision 1.4 1997/12/22 15:15:45 akers + * Ongoing development with new cdevReactor + * + * Revision 1.3 1996/09/13 18:47:18 akers + * Installed free list for node objects + * + * Revision 1.2 1996/07/16 15:48:55 akers + * Ongoing Modifications + * + *----------------------------------------------------------------------------- + */ + +#ifndef __FIFO_H_ +#define __FIFO_H_ 1 + +#include + +class GENERIC_SERVER_API QueueBase +{ +public: + class node + { + friend class QueueBase; + private: + node ( void ) : binary(NULL), binaryLen(0), next(NULL) { } + ~node ( void ) { } + public: + void * binary; + size_t binaryLen; + class node * next; + }; + +protected: + node * head; + node * tail; + +private: + enum { NEWCNT = 32 }; + static node * freeList_; + +public: + QueueBase ( void ) + : head(NULL), tail(NULL) + { + } + + virtual ~QueueBase ( void ) + { + } + + static node * newNode ( void ) + { + node * result; + if(freeList_==NULL) + { + freeList_ = new node[NEWCNT]; + for(int i=0; inext; + result->binary = NULL; + result->binaryLen = 0; + result->next = NULL; + return result; + } + + static void deleteNode ( node * ptr) + { + if(ptr->next!=NULL) deleteNode(ptr->next); + ptr->next = freeList_; + freeList_ = ptr; + } +}; + +class GENERIC_SERVER_API FifoQueue : public QueueBase + { + private: + int nodeCnt; + + public: + FifoQueue ( void ) : QueueBase(), nodeCnt(0) {} + + virtual ~FifoQueue ( void ) + { + while(dequeue()!=NULL); + } + + int empty ( void ) + { + return head==NULL?1:0; + } + + void enqueue ( void * ptr ) + { + if(ptr != NULL) + { + if(tail==NULL) tail = newNode(); + else + { + tail->next = newNode(); + tail = tail->next; + } + tail->binary = ptr; + if(head==NULL) head = tail; + nodeCnt++; + } + } + + void enqueue ( char * ptr, size_t len ) + { + if(ptr != NULL && len > 0 ) + { + if(tail==NULL) tail = newNode(); + else { + tail->next = newNode(); + tail = tail->next; + } + tail->binary = ptr; + tail->binaryLen = len; + if(head==NULL) head = tail; + nodeCnt++; + } + } + + void * dequeue ( void ) + { + void * result = NULL; + if(head!=NULL) + { + node * next = head->next; + result = head->binary; + head->next = NULL; + deleteNode(head); + head = next; + if(head==NULL) tail = NULL; + nodeCnt--; + } + return result; + } + + + int dequeue ( char ** ptr, size_t * len ) + { + int result = -1; + *ptr = NULL; + *len = 0; + if(head!=NULL) + { + node * next = head->next; + result = 0; + *ptr = (char *)head->binary; + *len = head->binaryLen; + head->next = NULL; + deleteNode(head); + head = next; + if(head==NULL) tail = NULL; + nodeCnt--; + } + return result; + } + + int peek ( char ** ptr, size_t *len ) + { + int result = -1; + if(head!=NULL) + { + *ptr = (char *)head->binary; + *len = head->binaryLen; + result = 0; + } + return result; + } + + void undequeue ( void * ptr ) + { + if(ptr != NULL) + { + if(tail==NULL) enqueue(ptr); + else { + node * headnode = newNode(); + headnode->binary = ptr; + headnode->next = head; + head = headnode; + nodeCnt++; + } + } + } + + void undequeue ( char *ptr, size_t len) + { + if(ptr != NULL && len > 0) + { + if(tail==NULL) enqueue(ptr, len); + else { + node * headnode = newNode(); + headnode->binary = ptr; + headnode->binaryLen = len; + headnode->next = head; + head = headnode; + nodeCnt++; + } + } + } + + int getCount ( void ) { return nodeCnt; } + }; + + +class GENERIC_SERVER_API ListQueue : public QueueBase + { + protected: + node * prev; + node * bookmark; + + public: + ListQueue ( void ) : QueueBase () + { + prev = NULL; + bookmark = NULL; + } + virtual ~ListQueue ( void ) + { + while(first()==0) remove(); + } + int first ( void ) + { + prev = NULL; + bookmark = head; + return (bookmark==NULL?-1:0); + } + int next ( void ) + { + if(bookmark!=NULL) + { + prev = bookmark; + bookmark = bookmark->next; + } + return (bookmark==NULL?-1:0); + } + void * dequeue ( void ) + { + return (bookmark==NULL?NULL:bookmark->binary); + } + void enqueue ( void * ptr ) + { + if(ptr != NULL) + { + prev = tail; + if(tail==NULL) tail = newNode(); + else + { + tail->next = newNode(); + tail = tail->next; + } + tail->binary = ptr; + bookmark = tail; + if(head==NULL) head = tail; + } + } + int remove ( void ) + { + int retval = -1; + if(bookmark != NULL) + { + if(prev!=NULL) prev->next = bookmark->next; + else head = bookmark->next; + + bookmark->next = NULL; + deleteNode(bookmark); + + if(prev!=NULL) { + bookmark = prev->next; + } + else if(head!=NULL && head->next!=NULL) { + bookmark = head->next; + } + else bookmark = head; + + for( tail=head; + tail!=NULL && tail->next!=NULL; + tail=tail->next); + retval = 0; + } + else if(head!=NULL) first(); + else tail = NULL; + return retval; + } + }; + +#ifdef _FIFO_QUEUE_MASTER_ + QueueBase::node * QueueBase::freeList_ = NULL; +#endif + +#endif // __FIFO_H_ + diff --git a/extensions/cdevGenericServer/common/includeAll.cc b/extensions/cdevGenericServer/common/includeAll.cc new file mode 100644 index 0000000..3d0c4fa --- /dev/null +++ b/extensions/cdevGenericServer/common/includeAll.cc @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int main() +{ +return 0; +} diff --git a/extensions/cdevGenericServer/doc/Makefile b/extensions/cdevGenericServer/doc/Makefile new file mode 100755 index 0000000..bc8d339 --- /dev/null +++ b/extensions/cdevGenericServer/doc/Makefile @@ -0,0 +1,15 @@ +APPNAME = CDEV Generic Server Documentation + +all: + @echo "=> $(APPNAME)" + @echo "<= Nothing to be done..." + +clean: + @echo " => Cleaning $(APPNAME)" + @rm -rf */*.backup */*.recover + @echo " Done..." + +purge: + @echo " => Purging $(APPNAME)" + @rm -rf */*.backup */*.recover + @echo " Done..." diff --git a/extensions/cdevGenericServer/doc/NMakefile.mak b/extensions/cdevGenericServer/doc/NMakefile.mak new file mode 100755 index 0000000..9ea20e6 --- /dev/null +++ b/extensions/cdevGenericServer/doc/NMakefile.mak @@ -0,0 +1,13 @@ +APPNAME = CDEV Generic Server Documentation + +all: + @echo =^> $(APPNAME) + @echo ^ ^ ^ ^ ^ ^ Done... + +clean: + @echo ^ ^ ^ =^> Cleaning $(APPNAME) + @echo ^ ^ ^ ^ ^ ^ Done... + +purge: + @echo ^ ^ ^ =^> Purging $(APPNAME) + @echo ^ ^ ^ ^ ^ ^ Done... diff --git a/extensions/cdevGenericServer/doc/frame/ClientOverview.doc b/extensions/cdevGenericServer/doc/frame/ClientOverview.doc new file mode 100755 index 0000000..edb1569 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/ClientOverview.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/LinkList.book b/extensions/cdevGenericServer/doc/frame/LinkList.book new file mode 100755 index 0000000..a96c862 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/LinkList.book differ diff --git a/extensions/cdevGenericServer/doc/frame/LinkList.doc b/extensions/cdevGenericServer/doc/frame/LinkList.doc new file mode 100755 index 0000000..279a3b7 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/LinkList.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/LinkListLOF.doc b/extensions/cdevGenericServer/doc/frame/LinkListLOF.doc new file mode 100755 index 0000000..72bb33b Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/LinkListLOF.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/LinkListTITLE.doc b/extensions/cdevGenericServer/doc/frame/LinkListTITLE.doc new file mode 100755 index 0000000..e79d48a Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/LinkListTITLE.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/LinkListTOC.doc b/extensions/cdevGenericServer/doc/frame/LinkListTOC.doc new file mode 100755 index 0000000..df96267 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/LinkListTOC.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/MultiQueue.doc b/extensions/cdevGenericServer/doc/frame/MultiQueue.doc new file mode 100755 index 0000000..d037385 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/MultiQueue.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/cdevClient.doc b/extensions/cdevGenericServer/doc/frame/cdevClient.doc new file mode 100755 index 0000000..3304449 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/cdevClient.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/cdevGenericServer.book b/extensions/cdevGenericServer/doc/frame/cdevGenericServer.book new file mode 100755 index 0000000..6ff8e29 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/cdevGenericServer.book differ diff --git a/extensions/cdevGenericServer/doc/frame/cdevGenericServer.doc b/extensions/cdevGenericServer/doc/frame/cdevGenericServer.doc new file mode 100755 index 0000000..5a16380 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/cdevGenericServer.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/cdevGenericServerExample.doc b/extensions/cdevGenericServer/doc/frame/cdevGenericServerExample.doc new file mode 100755 index 0000000..985de44 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/cdevGenericServerExample.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/cdevGenericServerLOF.doc b/extensions/cdevGenericServer/doc/frame/cdevGenericServerLOF.doc new file mode 100755 index 0000000..b30a5f3 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/cdevGenericServerLOF.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/cdevGenericServerTITLE.doc b/extensions/cdevGenericServer/doc/frame/cdevGenericServerTITLE.doc new file mode 100755 index 0000000..8736715 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/cdevGenericServerTITLE.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/cdevGenericServerTOC.doc b/extensions/cdevGenericServer/doc/frame/cdevGenericServerTOC.doc new file mode 100755 index 0000000..597ad70 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/cdevGenericServerTOC.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/cdevPacket.doc b/extensions/cdevGenericServer/doc/frame/cdevPacket.doc new file mode 100755 index 0000000..1907041 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/cdevPacket.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/cdevProtocol.book b/extensions/cdevGenericServer/doc/frame/cdevProtocol.book new file mode 100755 index 0000000..746ad3d Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/cdevProtocol.book differ diff --git a/extensions/cdevGenericServer/doc/frame/cdevProtocol.doc b/extensions/cdevGenericServer/doc/frame/cdevProtocol.doc new file mode 100755 index 0000000..0b82f43 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/cdevProtocol.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/cdevProtocolLOF.doc b/extensions/cdevGenericServer/doc/frame/cdevProtocolLOF.doc new file mode 100755 index 0000000..0716b64 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/cdevProtocolLOF.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/cdevProtocolTITLE.doc b/extensions/cdevGenericServer/doc/frame/cdevProtocolTITLE.doc new file mode 100755 index 0000000..c885319 Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/cdevProtocolTITLE.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/cdevProtocolTOC.doc b/extensions/cdevGenericServer/doc/frame/cdevProtocolTOC.doc new file mode 100755 index 0000000..4aca0df Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/cdevProtocolTOC.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/cdevServerPoster.doc b/extensions/cdevGenericServer/doc/frame/cdevServerPoster.doc new file mode 100755 index 0000000..d55d7fe Binary files /dev/null and b/extensions/cdevGenericServer/doc/frame/cdevServerPoster.doc differ diff --git a/extensions/cdevGenericServer/doc/frame/makehtml b/extensions/cdevGenericServer/doc/frame/makehtml new file mode 100755 index 0000000..e51bd6b --- /dev/null +++ b/extensions/cdevGenericServer/doc/frame/makehtml @@ -0,0 +1,18 @@ +#! /bin/csh + +if( -f fmbatch.dat) rm fmbatch.dat +mkdir -p ../html +cp $CDEV/doc/bullet.jpg ../html + +foreach x (cdevGenericServer.doc cdevGenericServerTITLE.doc cdevGenericServerExample.doc) + echo "Open $x" >> fmbatch.dat + echo "SaveAs ma $x ../html/`basename $x .doc`.mif" >> fmbatch.dat + end + +fmbatch fmbatch.dat + +rm fmbatch.dat + +cd ../html +mif2html -t 'CDEV Generic Server' -o cdevGenericServer.html cdevGenericServerTITLE.mif -TOC -LOF cdevGenericServer.mif cdevGenericServerExample.mif +rm *.mif diff --git a/extensions/cdevGenericServer/doc/html/BlueMarbleLine.gif b/extensions/cdevGenericServer/doc/html/BlueMarbleLine.gif new file mode 100755 index 0000000..6e7c0c7 Binary files /dev/null and b/extensions/cdevGenericServer/doc/html/BlueMarbleLine.gif differ diff --git a/extensions/cdevGenericServer/doc/html/bullet.jpg b/extensions/cdevGenericServer/doc/html/bullet.jpg new file mode 100755 index 0000000..a79a191 Binary files /dev/null and b/extensions/cdevGenericServer/doc/html/bullet.jpg differ diff --git a/extensions/cdevGenericServer/doc/html/cdevGenericServer.html b/extensions/cdevGenericServer/doc/html/cdevGenericServer.html new file mode 100755 index 0000000..ae47e62 --- /dev/null +++ b/extensions/cdevGenericServer/doc/html/cdevGenericServer.html @@ -0,0 +1,7540 @@ + + +CDEV Generic Server + + + + + + +


        + + + +
        + + + + The CDEV Generic Server +

        + + A CDEV Extension Library for Building Client/Server Systems +

        + + +

        + Version 1.5 December 9, 1996 +

        + +

        + Walt Akers, Chip Watson, Jie Chen +

        + +

        + TJNAF - Thomas Jefferson National Accelerator Facility +

        + +

        +
        + +


        + + + + + +
        + + + + Table of Contents +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +
        +
        + + Overview of the CDEV Generic Server Engine +
        +
        + + +
        +
        + + Purpose of This Document +
        +
        + + +
        +
        + + Intended Audience +
        +
        + + +
        +
        + + What is the CDEV Generic Server Engine +
        +
        + + +
        +
        + + Why Use the CDEV Generic Server Engine +
        +
        + + +
        +
        + + Features +
        +
        + + 2. +
        +
        + + Building the CDEV Generic Server Engine +
        +
        + + +
        +
        + + Steps for Compiling and Testing the CDEV Generic Server Engine +
        +
        + + 3. +
        +
        + + The Reflector Server - A Simple Client/Server System +
        +
        + + +
        +
        + + Overview +
        +
        + + +
        +
        + + Reflector Server Source Code +
        +
        + + +
        +
        + + ReflectorServer Header Files +
        +
        + + +
        +
        + + The ReflectorServer Class +
        +
        + + +
        +
        + + The main Function +
        +
        + + +
        +
        + + The ReflectorService Source Code +
        +
        + + +
        +
        + + The ReflectorService.h Header File +
        +
        + + +
        +
        + + The newReflectorService Function +
        +
        + + +
        +
        + + The ReflectorService Class +
        +
        + + +
        +
        + + The CDEV DDL File +
        +
        + + +
        +
        + + Testing the Reflector Server +
        +
        + + 4. +
        +
        + + Server Class Hierarchy +
        +
        + + +
        +
        + + Server Classes +
        +
        + + +
        +
        + + FifoQueue Class +
        +
        + + +
        +
        + + MultiQueue Class +
        +
        + + +
        +
        + + ClientSession Class +
        +
        + + +
        +
        + + Attributes of the ClientSession Class +
        + + + + + + + +
        + + +
        +
        + + localID +
        +
        + + +
        +
        + + clientID +
        +
        + + +
        +
        + + socketID +
        +
        +
        + + +
        +
        + + SocketSession Class +
        +
        + + +
        +
        + + Attributes of the SocketSession Class +
        + + + +
        + + +
        +
        + + socketID +
        +
        +
        + + +
        +
        + + ClientAcceptor Class +
        +
        + + +
        +
        + + SocketReader Class +
        +
        + + +
        +
        + + SocketWriter Class +
        +
        + + +
        +
        + + ClientHandler Class +
        +
        + + +
        +
        + + cdevSessionManager Class +
        +
        + + +
        +
        + + cdevServer Class +
        +
        + + 5. +
        +
        + + Client Class Hierarchy +
        +
        + + +
        +
        + + Client Classes +
        +
        + + +
        +
        + + SocketReader Class +
        +
        + + +
        +
        + + SocketWriter Class +
        +
        + + +
        +
        + + ServerHandler Class +
        +
        + + +
        +
        + + ServerHandlerCallback Class +
        +
        + + +
        +
        + + ServerConnectionList Class +
        +
        + + +
        +
        + + cdevServerInterface Class +
        +
        + + +
        +
        + + cdevClientRequestObject Class +
        +
        + + +
        +
        + + cdevClientService Class +
        +
        + + 6. +
        +
        + + Properties of the cdevSessionManager Class +
        +
        + + +
        +
        + + Overview +
        +
        + + +
        +
        + + Attributes of the cdevSessionManager Class +
        + + + + + + + + + + + + + + + +
        + + +
        +
        + + Reactor +
        +
        + + +
        +
        + + trigger +
        +
        + + +
        +
        + + rate +
        +
        + + +
        +
        + + localIdx +
        +
        + + +
        +
        + + inbound +
        +
        + + +
        +
        + + clients +
        +
        + + +
        +
        + + sockets +
        +
        +
        + + +
        +
        + + Methods of the cdevSessionManager Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + getNextLocalID +
        +
        + + +
        +
        + + newClientSession +
        +
        + + +
        +
        + + newClientSession +
        +
        + + +
        +
        + + findLocalClient +
        +
        + + +
        +
        + + findClient +
        +
        + + +
        +
        + + findSocket +
        +
        + + +
        +
        + + addClient +
        +
        + + +
        +
        + + addSocket +
        +
        + + +
        +
        + + removeClient +
        +
        + + +
        +
        + + removeSocket +
        +
        + + +
        +
        + + enqueue +
        +
        + + +
        +
        + + enqueue +
        +
        + + +
        +
        + + dequeue +
        +
        + + +
        +
        + + decodePacket +
        +
        + + +
        +
        + + encodePacket +
        +
        + + +
        +
        + + get_handle +
        +
        + + +
        +
        + + handle_input +
        +
        + + +
        +
        + + handle_close +
        +
        + + +
        +
        + + handle_timeout +
        +
        + + +
        +
        + + set_rate +
        +
        + + +
        +
        + + get_rate +
        +
        + + +
        +
        + + processMessages +
        +
        +
        + + 7. +
        +
        + + Properties of the cdevServer Class +
        +
        + + +
        +
        + + Overview +
        +
        + + +
        +
        + + Attributes of the cdevServer Class +
        + + + + + + + + + + + +
        + + +
        +
        + + Finished +
        +
        + + +
        +
        + + serverName +
        +
        + + +
        +
        + + acceptor +
        +
        + + +
        +
        + + timer +
        +
        + + +
        +
        + + status +
        +
        +
        + + +
        +
        + + Methods of the cdevServer Class +
        + + + + + + + + + + + + + + + +
        + + +
        +
        + + cdevServer +
        +
        + + +
        +
        + + newClientSession +
        +
        + + +
        +
        + + newSocketSession +
        +
        + + +
        +
        + + dequeue +
        +
        + + +
        +
        + + decodePacket +
        +
        + + +
        +
        + + encodePacket +
        +
        + + +
        +
        + + operational +
        +
        +
        + + 8. +
        +
        + + Properties of the cdevServerInterface Class +
        +
        + + +
        +
        + + Overview +
        +
        + + +
        +
        + + Attributes of the cdevServer Interface Class +
        + + + + + + + + + + + + + + + +
        + + +
        +
        + + Reactor +
        +
        + + +
        +
        + + connections +
        +
        + + +
        +
        + + domain +
        +
        + + +
        +
        + + defaultServer +
        +
        + + +
        +
        + + defaultServerHandler +
        +
        + + +
        +
        + + maxFd +
        +
        + + +
        +
        + + fdList +
        +
        +
        + + +
        +
        + + Methods of the cdevServer Interface Class +
        + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + cdevServerInterface +
        +
        + + +
        +
        + + getDefault +
        +
        + + +
        +
        + + getDomain +
        +
        + + +
        +
        + + setDefault +
        +
        + + +
        +
        + + connect +
        +
        + + +
        +
        + + disconnect +
        +
        + + +
        +
        + + enqueue +
        +
        + + +
        +
        + + getFd +
        +
        + + +
        +
        + + flush +
        +
        + + +
        +
        + + pend +
        +
        +
        + + 9. +
        +
        + + Properties of the cdevClientService Class +
        +
        + + +
        +
        + + Overview +
        +
        + + +
        +
        + + Attributes of the cdevClientService Class +
        + + + + + + + + + +
        + + +
        +
        + + callback +
        +
        + + +
        +
        + + transactions +
        +
        + + +
        +
        + + contexts +
        +
        + + +
        +
        + + tagCallback +
        +
        +
        + + +
        +
        + + Methods of the cdevClientService Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + cdevClientService +
        +
        + + +
        +
        + + defaultCallback +
        +
        + + +
        +
        + + outputError +
        +
        + + +
        +
        + + flush +
        +
        + + +
        +
        + + pend +
        +
        + + +
        +
        + + poll +
        +
        + + +
        +
        + + pend +
        +
        + + +
        +
        + + getNameServer +
        +
        + + +
        +
        + + getRequestObject +
        +
        + + +
        +
        + + enqueue +
        +
        + + +
        +
        + + cancel +
        +
        + + +
        +
        + + enqueue +
        +
        + + +
        +
        + + fireCallback +
        +
        +
        + + 10. +
        +
        + + Properties of the cdevClientRequestObject Class +
        +
        + + +
        +
        + + Overview +
        +
        + + +
        +
        + + Attributes of the cdevClient RequestObject Class +
        + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + sendStatus +
        +
        + + +
        +
        + + server +
        +
        + + +
        +
        + + DDL_server +
        +
        + + +
        +
        + + syncCallback +
        +
        + + +
        +
        + + handler +
        +
        + + +
        +
        + + contextID +
        +
        + + +
        +
        + + commandCode +
        +
        + + +
        +
        + + messageCode +
        +
        +
        + + +
        +
        + + Methods of the cdevClient RequestObject Class +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +
        +
        + + constructor +
        +
        + + +
        +
        + + setContext +
        +
        + + +
        +
        + + send +
        +
        + + +
        +
        + + sendNoBlock +
        +
        + + +
        +
        + + sendCallback +
        +
        + + +
        +
        + + className +
        +
        + + +
        +
        + + defaultCallback +
        +
        + + +
        +
        + + executeServer HandlerCallback +
        +
        + + +
        +
        + + getServerHandler +
        +
        + + +
        +
        + + getContextID +
        +
        + + +
        +
        + + getCommandCode +
        +
        + + +
        +
        + + getMessageCode +
        +
        +
        + + 11. +
        +
        + + Implementing Monitoring on the cdevServer +
        +
        + + +
        +
        + + Overview +
        +
        + + +
        +
        + + Special Notes +
        +
        + + +
        +
        + + Attributes of the cdevMonitorTable Class +
        + + + +
        + + +
        +
        + + monitors +
        +
        +
        + + +
        +
        + + Methods of the cdevMonitorTable Class +
        + + + + + + + + + + + + + +
        + + +
        +
        + + insertMonitor +
        +
        + + +
        +
        + + removeMonitor +
        +
        + + +
        +
        + + remove ClientMonitors +
        +
        + + +
        +
        + + findMonitor +
        +
        + + +
        +
        + + fireMonitor +
        +
        + + +
        +
        + + fireCallback +
        +
        +
        + + +
        +
        + + Attributes of the cdevMonitorNodeClass +
        + + + + + + + +
        + + +
        +
        + + parent +
        +
        + + +
        +
        + + node +
        +
        + + +
        +
        + + hashString +
        +
        +
        + + +
        +
        + + Methods of the cdevMonitorNode Class +
        + + + + + +
        + + +
        +
        + + fireMonitor +
        +
        + + +
        +
        + + isMonitored +
        +
        +
        + + 12. +
        +
        + + VirtualService: A Complex Client/Server Implementation +
        +
        + + +
        +
        + + Overview +
        +
        + + +
        +
        + + Virtual Server Structure +
        +
        + + +
        +
        + + Virtual Service Structure +
        + + + + + + + + + + + + + + + +
        + + +
        +
        + + VirtualAttrib.h +
        +
        + + +
        +
        + + VirtualAttrib.cc +
        +
        + + +
        +
        + + VirtualServer.h +
        +
        + + +
        +
        + + VirtualServer.cc +
        +
        + + +
        +
        + + VirtualService.h +
        +
        + + +
        +
        + + VirtualService.cc +
        +
        + + +
        +
        + + Virtual.ddl +
        +
        +
        +
        + +


        + + + + + +
        + + + + List of Figures +

        +
        + + + + Figure 10: + ReflectorServer.cc - Source Code for the Reflector Server +
        + + Figure 11: + ReflectorService.h - Header File for the Reflector Service +
        + + Figure 12: + ReflectorService.cc - Source Code for the Reflector Service +
        + + Figure 13: + Reflector.ddl - A Simple CDEV DDL File +
        + + Figure 1: + Object Hierarchy of Server Classes +
        + + Figure 2: + Object Hierarchy of Client Classes +
        + + Figure 3: + General Structure of the cdevMonitorTable +
        + + Figure 4: + Components of the Virtual Server +
        + + Figure 5: + Components of the Virtual Service +
        +
        + +


        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. +

        +
        + + + Overview of the CDEV Generic Server Engine +

        +
        + + + Purpose of This + Document +

        +
        + + This document is designed to provide an overview and tutorial of how to implement + client/server applications by using the CDEV Generic Server Engine. Adherence to + the structure and syntax that is specified in this document will improve the likelihood + that the CDEV service/server developer's application will be compatible with other + similar applications using CDEV. +

        + The class library was designed to be as efficient as possible and still maintain the + flexibility to allow CDEV client/server developers to use it with minimal modification. In + addition to describing the conceptual behavior of the server, this document will also + discuss the C++ classes and how inheritance and overloading may be used to build + the best server for your application. +

        +
        + + + Intended Audience +

        +
        + + This document is intended for anyone who will be developing a CDEV server or will be + developing CDEV applications that will communicate with one another over a network. + This document will also be useful for software developers who wish to develop a non- + CDEV application that can communicate with an existing server that uses this class + library. +

        +
        + + + What is the CDEV + Generic Server + Engine +

        +
        + + The CDEV Generic Server Engine is a collection of C++ classes that may be used to + quickly develop a client/server application. The communications component of the + library is based on the Adaptive Communications Environment (ACE), a freeware + product developed by Douglas Schmidt that is provided with the CDEV distribution. +

        + CDEV servers use a global CDEV Name Server (provided with the source code + distribution) to register themselves. The client services can then use this Name Server + to locate servers by type, name or host. The Name Server insures that each server + name is unique within its type or domain. Servers that have not reregistered within a + specific time period (usually 60 seconds) are automatically removed from the Name + Server. +

        + Clients and servers that are developed using this library will use the CDEV Linear + Internet Protocol to communicate. The documentation for this protocol is provided with + the CDEV distribution and its use ensures that the developer's server will be + accessible by all CDEV compliant applications. +

        +
        + + + Why Use the CDEV + Generic Server + Engine +

        +
        + + The CDEV Generic Server Engine provides a robust and reliable mechanism for + quickly developing client/server applications. Because all of the network + communications intricacies are isolated by the C++ classes, the developer's server + can easily be modified and upgraded without significant modification to the network + internals. Additionally, by using CDEV, the client does not need to be 'network-aware', + the client C++ class library does all of the communications work. +

        + The CDEV Generic Server Engine also provides a myriad of features that would + require a significant investment in time to develop for each new server. These features + are described in detail below. +

        +
        + + + Features +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + +

        +
        + + The developer is only required to create a subclass of the cdevServer C++ class + and overload a single method in order to generate the communications + component of his server. +

        +
        + + +

        +
        + + The complete client communications portion of the application is accomplished by + inheriting a CDEV service class from the cdevClientService C++ class and writing + a boiler plate service loader. +

        +
        + + +

        +
        + + The engine uses the CDEV Linear Internet Protocol (CLIP) to communicate. This + protocol uses cdevData objects (a self-describing data structure) to transfer data + allowing unique, application specific data structures to be transferred without + modifying the protocol. +

        +
        + + +

        +
        + + The client and server side of the application use a global CDEV Name Server to + register and locate various servers by their type, name or host. +

        +
        + + +

        +
        + + The socket utility classes use embedded buffering to optimize asynchronous + communications and increase communications speed. +

        +
        + + +

        +
        + + The communications interface is completely abstracted from the client application. + Because the application has only a CDEV view of the world, the underlying + communications engine can be modified or upgraded without breaking the + program. +

        +
        + + +

        +
        + + Clients automatically reconnect to server following a disconnect or + communications error. +

        +
        + + +

        +
        + + Communications integrity is ensured by using TCP/IP and the Adaptive + Communications Environment (ACE) C++ library. +

        +
        + + +

        +
        + + The server supports multiple concurrent client connections. Because the inbound + data is read incrementally and buffered, a slow client will not cause the server to + block while waiting for a transmission to be completed. +

        +
        + + +

        +
        + + The server is completely event driven. It is activated whenever a client submits a + packet or packets, otherwise, it sleeps until it has inbound data to process. +

        +
        + + +

        +
        + + An individual tag map is maintained for each connection. When data is received + the server will map the contents of the clients cdevData objects to the server's + representation prior to processing. The cdevData objects are remapped to the + client's representation prior to returning results. +

        +
        + + +

        +
        + + The server has built-in mechanisms for storing, executing and removing client + specified monitors on server data objects. This monitoring capability easily allows + application developers to create event-driven client programs that respond to + changes in the server. +

        +
        + + +

        +
        + + A timer-based CDEV 'polling' class is provided that allows the server to attach to + other CDEV servers or services to obtain information. +

        +
        +
        + + 2. +

        +
        + + + Building the CDEV Generic Server Engine +

        +
        + + + Steps for + Compiling and + Testing the CDEV + Generic Server + Engine +

        +
        + + + + + + + + + + + +
        + + 1. +

        +
        + + Install and compile the CDEV source code distribution. See the CDEV + distribution for specific instructions for compiling these libraries. +

        +
        + + 2. +

        +
        + + Compile the Adaptive Communications Environment (ACE) Library. ACE is + located at the same level as the 'src' directory in the CDEV distribution tree. The + README file located in that directory will provide specific instructions on building + this library on your system. The ACE libraries should be automatically copied to + the CDEV library directory. +

        +
        + + 3. +

        +
        + + Setup the Makefile for your platform. In the directory include/makeinclude there + are a collection of makefiles that are followed by the name of the platform for + which they were developed. Link the makefile associated with your platform to the + file Makefile.OS by typing the following command: "ln -s Makefile.XXXX + Makefile.OS". +

        + + If a makefile for your platform does not already exist, you may have to create one + in that directory. +

        +
        + + 4. +

        +
        + + Compile the cdevGenericServer Library. The source code tree for this + distribution is located in the directory $CDEV/extensions/cdevGenericServer. +

        + + The makefile for this library requires the same environment variables that are + used by the main CDEV makefile. +

        + + + + + + + + + + + +
        + + CDEV +

        +
        + + This is the root directory of the CDEV distribution. +

        +
        + + CDEVVERSION +

        +
        + + This is the version number of the CDEV class library. +

        +
        + + CDEVSHOBJ +

        +
        + + This is the directory for the CDEV shared objects. +

        +
        + + CDEVLIB +

        +
        + + This is the directory where the CDEV libraries reside. +

        +
        + + CDEVINCLUDE +

        +
        + + This is the directory where the CDEV include files reside. +

        +
        + + To compile the libraries, go to the cdevGenericServer directory and type make. All + libraries and the associated test and example applications should be built. +

        +
        + + 5. +

        +
        + + Run the test applications to ensure that the code is working correctly. These + applications are located in the test sub-directory of the cdevGenericServer tree. + The test applications require that a special DDL file is specified and that the + CDEV Name Server is operating. Perform the following steps to test the library. +

        + + + + + + + + + + + + + + + + + + + +
        + + 5a. +

        +
        + + Start the Name Server. The NameServer application is located in the bin + directory of the cdevGenericServer distribution tree. The NameServer should + produce no output and can be executed in the background by typing: + "NameServer &". +

        +
        + + 5b. +

        +
        + + Specify the host name of the Name Server. Because all applications will + need to access the Name Server, the host where it is executing should be + specified in the CDEV_NAME_SERVER environment variable. This variable + must be specified in the environment of each shell that will need to access the + Name Server. If the Name Server is running on host foo.cebaf.gov, the Name + Server environment variable can be set by typing: "setenv + CDEV_NAME_SERVER foo.cebaf.gov". +

        +
        + + 5c. +

        +
        + + Specify the CDEV Device Definition Language file for the test programs. + The DDL file for the test programs is named TestService.ddl and is located in + the test sub-directory of the cdevGenericServer distribution tree. In order for + this DDL file to be used as the default, it should be specified in the CDEVDDL + environment variable. This can be accomplished by moving to the test + directory and typing the following command: "setenv CDEVDDL $PWD/ + TestService.ddl". +

        +
        + + 5d. +

        +
        + + Specify the CDEVSHOBJ directory. The CDEVSHOBJ directory is the + directory that contains the versioned subdirectories for the service shared + objects. By default the makefile will place the file TestService.so in the + directory $CDEV/lib/PLATFORM-OSVERSION.XX/1.5/TestService.so, where + PLATFORM is the name of your platform and OSVERSION is the major + operating system. The following example shows the location of the + TestService.so on a Solaris 5.5 system and the correct setting for the + CDEVSHOBJ variable. +

        + + +

        + Location: $CDEV/lib/solaris-5.XX/1.5/TestService.so +

        + CDEVSHOBJ: $CDEV/lib/solaris-5.XX +

        + +

        + The CDEVSHOBJ variable may point to the directory that actually contains + the service shared objects, however, CDEV will always attempt to locate the + files in the version subdirectory first in order to support multiple CDEV + versions. +

        +
        + + 5e. +

        +
        + + Start the Test Server. The environment is now correct to start the TestServer. + From the bin sub-directory type the command: "TestServer". The TestServer + should print a message indicating that it is ready to process user requests. +

        +
        + + 5f. +

        +
        + + Specify the Client Tag Map. In order to test all capabilities of the server, the + client should use a tag map that is different from the one that is in use on the + server side of the connection. A special tag map has been provided that can + be used to test this feature. The tag map is located in the test sub-directory + and can be specified by moving to the test subdirectory and typing: "setenv + CDEVTAGMAP $PWD/cdevTagMap.txt". +

        +
        + + 5g. +

        +
        + + Start the Test Client. In a new window, set the CDEV_NAME_SERVER and + the CDEVDDL environment variables as previously described. The test client + may then be started by typing the following command "TestProgram". +

        +
        + + 5h. +

        +
        + + Examine Test Server and Test Client output. The server and the client + should periodically print a line indicating that the packets that they are + exchanging are correctly matched. If a mismatch occurs, both sides of the + connection will print out a verbose description of what differences were + detected. +

        +
        + + 5i. +

        +
        + + Terminate the Test Server and the Test Client. The TestServer and + TestProgram applications are terminated using CTRL-C. When the + applications are terminated, they should display a disconnecting message + and exit gracefully. +

        +
        +
        +
        + + 3. +

        +
        + + + The Reflector Server - A Simple Client/Server System +

        +
        + + + Overview +

        +
        + + The Reflector client/server system is a simple CDEV service that returns the + cdevData object unmodified to the caller. The Reflector server can be used as a + skeleton for any other server that the developer may wish to create. The source code + that is provided in the following sections is available in text form in the examples sub- + directory of the cdevGenericServer directory tree. A more complex example is + provided in section 11 of this document. +

        +
        + + + Reflector Server + Source Code +

        +
        + + The server for the Reflector system is instituted as a single C++ file. The source code + for this application is listed below. +

        + + Figure 10: + + ReflectorServer.cc - Source Code for the Reflector Server +
        + + + +
        + + +
        
        +#include <cdevServer.h>
        + 
        +// ******************************************************************
        +// * class ReflectorServer:
        +// *   This is the server class for the reflector. It simply
        +// *   receives messages from a client and immediately returns them.
        +// *
        +// *   The constructor passes the domain, server, port and rate to the
        +// *   underlying cdevServer class to be processed. The cdevServer
        +// *   constructor will add this server to the Name Server and will 
        +// *   begin processing messages when the cdevServer::runServer() 
        +// *   method is executed.
        +// *
        +// *   The processMessages method is the servers interface to the 
        +// *   world... Each time a complete message is received or the time 
        +// *   specified in rate expires, that method will be called.
        +// ******************************************************************
        +class ReflectorServer : public cdevServer
        +{
        +public:
        +   ReflectorServer ( char *domain, char *server, 
        +                  unsigned int port, double rate )
        +      : cdevServer(domain, server, port, rate)
        +      {
        +      }
        + 
        +   virtual void processMessages ( void )
        +      {
        +      cdevMessage * message;
        +      while(dequeue(message)==0)
        +         {
        +         enqueue(message);
        +         delete message;
        +         }
        +      }
        +};
        + 
        +void main()
        +{
        +ReflectorServer server("REFLECTOR", "TestServerX", 9120, 60);
        +cdevServer::runServer();
        +}
        +			
        +
        +
        + +

        +
        + + + ReflectorServer + Header Files +

        +
        + + In the source code for the Reflector server, the only header file that must be included + is the one for the cdevServer class. This header contains all of the definition + information that is required for the Adaptive Communications Environment (ACE) and + the CDEV Linear Internet Protocol. +

        +
        + + + The + ReflectorServer + Class +

        +
        + + The ReflectorServer class inherits directly from the cdevServer class. Because + cdevServer defines all of the functionality necessary to establish a listening socket + and accept connections, the developers start-up is limited to initializing the + cdevServer class object with the domain name, server name, listening socket number + and the time-out rate. +

        + The developer is required to create a processMessages method which will perform + whatever message processing that is required of the server. In this case, the + processMessages method will merely remove an entry from the queue and then re- + enqueue it for return to the client. Note that the enqueue method does not delete the + cdevMessage object, so it is the responsibility of the developer to delete the + cdevMessage object when it is no longer needed. +

        +
        + + + The main Function +

        +
        + + The main function is responsible for starting the server when the application is started. + In order to perform this task, main must first create a new ReflectorServer object. The + ReflectorServer in this example has the Name Server domain "REFLECTOR" and the + server name "TestServerX". It will be listening for connections on socket 9120 and will + automatically process messages at least once every 60 seconds. +

        + When the ReflectorServer was created it automatically registered itself with the ACE + Reactor that is embedded in the cdevServer class. In order to begin accepting + connections and processing messages the main function must call the static + runServer method of the cdevServer class. This method will continue servicing + requests until the static Finished flag of the cdevServer class is set to non-zero. +

        +
        + + + The + ReflectorService + Source Code +

        +
        + + The ReflectorService is the CDEV interface to the ReflectorServer that is described + above. The source code for the ReflectorServer is implemented as a single source file + and its associated header file. The source code for the ReflectorService is as follows. +

        + + Figure 11: + + ReflectorService.h - Header File for the Reflector Service +
        + + + +
        + + +
        
        +#include <cdevClientService.h>
        + 
        +// ******************************************************************
        +// * Function called to create initial instance of ReflectorService
        +// ******************************************************************
        +extern "C" cdevService *newReflectorService ( char *, cdevSystem *);
        + 
        +// ******************************************************************
        +// * class ReflectorService :
        +// *   This class simply inherits from the cdevClientService and must 
        +// *   define only a constructor and destructor.
        +// ******************************************************************
        +class ReflectorService : public cdevClientService
        +{
        +public:
        +   ReflectorService (   char * name, cdevSystem & system =
        +      cdevSystem::defaultSystem());   
        +protected:
        +   virtual ~ReflectorService ( void ) {};
        +};
        +			
        +
        +
        + +

        + + Figure 12: + + ReflectorService.cc - Source Code for the Reflector Service +
        + + + +
        + + +
        
        +#include <ReflectorService.h>
        + 
        +// ******************************************************************
        +// * newReflectorService:
        +// *   This function will be called by the cdevSystem object to create 
        +// *   an initial instance of the ReflectorService.
        +// ******************************************************************
        +extern "C" cdevService * newReflectorService 
        +   (char * name, cdevSystem * system)
        +   {
        +   return new ReflectorService(name, *system);
        +   }
        + 
        +// ******************************************************************
        +// * ReflectorService::ReflectorService :
        +// *   This is the constructor for the ReflectorService.  It 
        +// *   initializes the underlying cdevClientService by specifying 
        +// *   that it is in the domain of REFLECTOR.
        +// ******************************************************************
        +ReflectorService::ReflectorService 
        +   ( char * name, cdevSystem & system)
        +   : cdevClientService("REFLECTOR", name, system) 
        +   {
        +   system.reportError(CDEV_SEVERITY_INFO, "ReflectorService", NULL, 
        +            "Constructing a new ReflectorService"); 
        +   }
        +			
        +
        +
        + +

        +
        + + + The + ReflectorService.h + Header File +

        +
        + + While the server is not required to have a specific header file, a CDEV service must + have a header file that may be used to create a loader for the archive version of the + library. This file is always named xxxxxService.h, where xxxxx is the name of the + service as it will be specified in the CDEV DDL file. This file must contain the complete + class definition for the service class. +

        +
        + + + The newReflector + Service Function +

        +
        + + Each service in CDEV must have a function that the cdevSystem object can call to + create the initial instance of the object. In the case of the ReflectorService, this + method will create a new instance of the ReflectorService using the provided name + and cdevSystem object. This new object will then be returned as a pointer to a + cdevService object. +

        +
        + + + The + ReflectorService + Class +

        +
        + + Because of the simplicity of the ReflectorService, all of the functionality of this class is + inherited from the cdevClientService class. The ReflectorService class is only + required to initialize its parent classes to be fully operational. +

        +
        + + + The CDEV DDL + File +

        +
        + + After compiling this source code into a server application and a CDEV shared library + using the makefile that is provided in the examples sub-directory, the developer is + ready to generate a CDEV DDL file that will map certain device/message + combinations to the Reflector service. The following simple CDEV DDL file can be + used to map device "device1" and message "get attrib1" to the Reflector Service. Note + that by entering the server tag in the service data section, the default server name that + the message will be sent to may be specified. In this case all messages associated + with the "attrib1" attribute will be sent to "TestServerX". +

        + + Figure 13: + + Reflector.ddl - A Simple CDEV DDL File +
        + + + +
        + + +
        
        +service Reflector 
        +   {
        +   tags {server}
        +   }
        + 
        +class Reflectors 
        +   {
        +       verbs {get}
        +   attributes 
        +      {
        +      attrib1     Reflector {server=TestServerX};
        +      }
        +   }
        + 
        +Reflectors :
        +   device1,
        +;
        +			
        +
        +
        + +

        +
        + + + Testing the + Reflector Server +

        +
        + + After compiling the server and the service components of the Reflector system, the + developer can test the functionality of the client/server application by performing the + following steps. +

        + + + + + + + + + + + + + +
        + + 1. +

        +
        + + Start the Name Server. +

        +
        + + 2. +

        +
        + + Set the CDEV_NAME_SERVER environment variable in the shell where you will + execute the server and the client to indicate the host where you started the Name + Server. For instance: setenv CDEV_NAME_SERVER cebaf1.cebaf.gov. +

        +
        + + 3. +

        +
        + + Set the CDEVSHOBJ environment variable in the shell where you will start the + client application to indicate the directory where the ReflectorService.so file is + stored. +

        +
        + + 4. +

        +
        + + Set the CDEVDDL environment variable in the shell where you will start the client + application to indicate the absolute path to the CDEV DDL file where the Reflector + definitions have been created. +

        +
        + + 5. +

        +
        + + Start the server. +

        +
        + + 6. +

        +
        + + Start the cdevUtil application that is provided with the CDEV distribution and send + messages to the server by typing: device1 get attrib1. You may want to enter + additional output code in the processMessages method of the server to report + each time a message is received. +

        +
        +
        + + 4. +

        +
        + + + Server Class Hierarchy +

        +
        + + + Server Classes +

        +
        + + The server side of the CDEV Generic Server Engine library is composed of a series of + classes that are used in conjunction with the ACE Reactor class to provide event + driven socket management. The following diagram shows an object diagram of the + classes that are used on the server side of the connection. +

        + + Figure 1: + + Object Hierarchy of Server Classes + +

        +
        + + + FifoQueue Class +

        +
        + + This class is a simple queue that is used to enqueue inbound messages that are + received from a socket. Because all messages will be processed by the same method, + there is only one FifoQueue object that is used by all client sockets. This object + resides in the cdevSessionManager class. +

        +
        + + + MultiQueue Class +

        +
        + + A MultiQueue object is a special type of FifoQueue that allows the caller to create an + object that is to be placed into the queue and then place it into several queues at + once. If the message is removed from any queue, it will automatically be removed + from all other queues where it exists. This mechanism is used to provide the capability + of removing all of a specific client's outbound packets without stepping through all of + the packets in the associated socket's queue. +

        +
        + + + ClientSession + Class +

        +
        + + The ClientSession class inherits its queue functionality from the MultiQueue class. It is + used to hold all outbound packets that are associated with a specific client identifier. + The ClientSession object also holds supplemental data that the cdevSessionManager + will need to manage the client. This class be subclassed by the developer in order to + associate more data with the client identifier. The following information is stored in the + ClientSession object: +

        +
        + + + Attributes of the + ClientSession + Class +

        +
        + + + + + + + +
        + + + localID +

        +
        + + short localID; +

        + + This is the client identifier that will be used on the server to + uniquely identify the client. +

        +
        + + + clientID +

        +
        + + int clientID; +

        + + This is the client identifier that was provided by the client + combined with the socket identifier. +

        +
        + + + socketID +

        +
        + + int socketID; +

        + + This is the socket identifier (file descriptor) to which the client is + connected. +

        +
        +
        + + + SocketSession + Class +

        +
        + + The SocketSession class inherits its functionality from the MultiQueue class. It is used + to hold all packets that are destined for a specific socket. The SocketSession object is + also used to store supplemental data that the cdevSessionManager will need to + maintain the connection. This class be subclassed by the developer in order to + associate more data with the socket identifier. The following information is stored in + the SocketSession object: +

        +
        + + + Attributes of the + SocketSession + Class +

        +
        + + + +
        + + + socketID +

        +
        + + int socketID; +

        + + This is the socket identifier (file descriptor) to which the remote + client is attached. +

        +
        +
        + + + ClientAcceptor + Class +

        +
        + + The ClientAcceptor class is used by the ACE Reactor to listen to the server socket and + accept each inbound client connection. When a connection is accepted, this class will + create a ClientHandler object that will manage the connection throughout its lifetime. +

        +
        + + + SocketReader + Class +

        +
        + + The SocketReader class has the embedded mechanisms to read buffered packets + from a socket. The ClientHandler inherits the functionality of this class to read data + that is received on its associated socket. +

        +
        + + + SocketWriter + Class +

        +
        + + The SocketWriter class has the embedded mechanisms to write buffered packets to a + socket. The class maintains a 56 kilobyte buffer that it uses to enqueue as many + outbound messages as possible before executing a network write. The ClientHandler + inherits the functionality of this class to write data to its associated socket. +

        +
        + + + ClientHandler + Class +

        +
        + + A ClientHandler object is created each time a new connection is accepted by the + server. This class is used by the ACE Reactor to manage the input and output events + on the specific socket. When data is received from the socket by the handle_input + method, the ClientHandler object will enqueue the inbound packet in the FifoQueue + provided by the cdevSessionManager class. When the cdevSessionManager class + enqueues outbound packets, the handle_output method of the ClientHandler class will + write them to the socket using as many write operations as required to transmit all + data. +

        + When the ClientHandler object is destroyed it will notify the cdevSessionManager + object which will remove its associated queues and will remove it from the ACE + Reactor. +

        +
        + + + cdevSessionMan + ager Class +

        +
        + + The cdevSessionManager class maintains all of the queues, ClientSession and + SocketSession objects that are used to operate a server. This class also defines the + enqueue and dequeue methods that are used by the cdevServer to obtain inbound + packets and to submit outbound packets. +

        +
        + + + cdevServer Class +

        +
        + + The cdevServer class inherits the queue management functionality that is provided by + the cdevSessionManager class and then implements the ClientAcceptor and + ClientHandler classes to accept and process connections. The cdevServer class also + introduces the concept of timed execution of the server function and automatic + registration of the server with the CDEV Name Server. +

        + In order to construct a new CDEV Server application, the developer only needs to + inherit his server class from the cdevServer class and then define the + processMessages method. This method will be called whenever the server timer + expires or when data is ready to be processed in the inbound queue. Once called the + processMessages method should use the dequeue method to remove the inbound + cdevMessage object, process the message, and then use the enqueue method to + return the processed cdevMessage object to the client. +

        + The encodePacket and decodePacket methods of this class are responsible for + coordinating the tables of context objects, performing tag mapping and converting + between the local client identifier and the foreign client identifier. +

        + +

        +
        + + 5. +

        +
        + + + Client Class Hierarchy +

        +
        + + + Client Classes +

        +
        + + The client side of the CDEV Generic Server Engine consists of a collection of classes + that are used in conjunction with the CDEV service architecture and the ACE Reactor + to provide pollable event driven behavior. The following diagram shows the object + structure of the classes used by the client. +

        + + Figure 2: + + Object Hierarchy of Client Classes + +

        +
        + + + SocketReader + Class +

        +
        + + The SocketReader class has the embedded mechanisms to read buffered packets + from a socket. The ServerHandler inherits the functionality of this class to read data + that is received on its associated socket. +

        +
        + + + SocketWriter + Class +

        +
        + + The SocketWriter class has the embedded mechanisms to write buffered packets to a + socket. The class maintains a 56 kilobyte buffer that it uses to enqueue as many + outbound messages as possible before executing a network write. The ServerHandler + inherits the functionality of this class to write data to its associated socket. +

        +
        + + + ServerHandler + Class +

        +
        + + A ServerHandler object is created for each server that the cdevServerInterface wishes + to communicate with. This object has an embedded FifoQueue object that is used to + store the outbound packets until the ServerHandler's data is flushed. If the + ServerHandler receives a sufficient number of packets or volume of data it will + automatically flush its buffer to the socket. The ServerHandler inherits much of its + communications functionality from the SocketReader and SocketWriter classes which + provide buffered communications methods. +

        + The cdevClientRequestObject may obtain a pointer to the ServerHandler that is + associated with the server that it is communicating with. By referencing this pointer + when enqueueing messages to the server through the cdevService, the request + object can increase its performance significantly because it does not have to locate + the associated ServerHandler on each transmission. +

        + A cdevClientRequestObject that is utilizing a ServerHandler will register itself in a list + of ServerHandlerCallback objects that are maintained in the ServerHandler object. + When the ServerHandler is destroyed it will notify each ServerHandlerCallback object + in the list to allow them to clear their pointers to it, avoiding the inadvertent use of an + invalid object. +

        +
        + + + ServerHandler + Callback Class +

        +
        + + The ServerHandlerCallback class is a virtual base class that any class that uses a + ServerHandler object may use to detect when the object is destroyed. When an object + that is inherited from this class is registered with the ServerHandler, it will be called + prior to deleting the ServerHandler object. The inherited object should then set the + associated ServerHandler pointer to NULL to prevent inadvertent access to a deleted + object. The cdevClientRequestObject inherits from this class in order to support this + functionality. +

        +
        + + + ServerConnection + List Class +

        +
        + + The ServerConnectionList is a table of all ServerHandler objects that are currently + connected to servers. The cdevServerInterface uses this table to locate a + ServerHandler by the name of its associated server. This table prevents multiple + connections from inadvertently being established to the same server. +

        +
        + + + cdevServerInter + face Class +

        +
        + + This class has a ServerConnectionList that references all ServerHandlers that are + connected to servers for the specific service. This object provides the mechanisms + that are used to enqueue, dequeue, flush, poll and pend on the outbound connections. +

        + The cdevServerInterface class contains an ACE Reactor that is used to respond to + input/output events that occur on the sockets within the ServerHandlers. Because this + Reactor is static within the cdevServerInterface class, it will handle events for all of the + server connections in all of the services that are inherited from it when it is called. +

        +
        + + + cdevClientRe + questObject Class +

        +
        + + This class inherits the majority of its functionality from, the cdevRequestObject class + and is used to associate a device with a specific message. The identity of the server + that supports the specific device/message combination may be specified in several + ways: through the server tag in the context, through the CDEV DDL file, or by the + server specified by a prior call to set default. If a specific server has been named, the + cdevClientRequestObject will obtain a pointer to the associated ServerHandler object + and will use that as a reference when submitting enqueue messages to the + cdevClientService object. If no server has been specified, then the + cdevClientRequestObject will set the ServerHandler pointer to NULL and will rely on + the cdevClientService to use the default server. If no default server has been specified + then the transmission will fail. +

        +
        + + + cdevClientService + Class +

        +
        + + This class inherits its functionality from the cdevServerInterface class. While the + cdevServerInterface class deals exclusively with binary streams and their associated + lengths, this class is called to enqueue information in the form of device, message, + data and context. The class will encode this information into the appropriate binary + format and submit it to the cdevServerInterface for enqueueing. When data is received + from the server, the cdevServerInterface will provide it to the cdevClientService in the + form of a binary stream, and the service will decompose it into its CDEV components + and dispatch the caller specified callback. +

        + Messages are enqueued in the service in the form of cdevTranObjs. The + cdevClientService manages these messages by maintaining a list of numbered + transactions. The transaction number associated with a message is embedded in the + outbound binary packet. When a server responds the same transaction number is + embedded in the response packet. This transaction number is then used to locate and + dispatch the associated callback. Once the callback has been executed, the + transaction object is removed from the list and deleted. +

        + In the event that a message indicates a monitoring operation, the transaction object is + marked as permanent until a monitorOff operation is executed. +

        +
        + + 6. +

        +
        + + + Properties of the cdevSessionManager Class +

        +
        + + + Overview +

        +
        + + As described earlier the cdevSessionManager class is responsible for managing the + queues that are used to read and write data to a collection of sockets that are + communicating with the server. The public interface to the cdevSessionManager class + is described below. +

        +
        + + + Attributes of the + cdevSessionMan + ager Class +

        +
        + + + + + + + + + + + + + + + +
        + + + Reactor +

        +
        + + static ACE_Reactor Reactor; +

        + + This is the ACE Reactor object that is used to respond to input/ + output events on the individual sockets and to respond to time + triggered events that are specified by the developer. +

        +
        + + + trigger +

        +
        + + FD_Trigger trigger; +

        + + This class contains an embedded pipe that is used to trigger + events in the object's ACE_Event_Handler. Each time a new + packet is enqueued in the cdevSessionManager, a byte is + written to the pipe within the trigger object, this causes the + Reactor to call the processMessages method of the + cdevSessionManager object to handle its input. +

        +
        + + + rate +

        +
        + + ACE_Time_Value rate; +

        + + Because the cdevSessionManager's processMessages + method may be called on a periodic basis rather than just when + a new message has arrived, the rate variable contains the + period in seconds between each subsequent execution. +

        +
        + + + localIdx +

        +
        + + static IntHash localIdx; +

        + + This is a table of ClientSession objects that are hashed based + on the local client index. The local client index is short integer + that is unique within the server and is used to identify a specific + client that is communicating through a socket. The + ClientSession object is the queue that is used to store + outbound packets that are destined for a specific client. + Additional client specific information is also stored in the + ClientSession object. +

        +
        + + + inbound +

        +
        + + FifoQueue inbound; +

        + + This is the queue into which all inbound messages that are + destined for a specific server are placed. A message is + enqueued as a binary stream and its associated length. +

        +
        + + + clients +

        +
        + + IntHash clients; +

        + + This is the table of ClientSession objects that are indexed by + the client specified client identifier. While the localIdx table is + global in scope, this table is specific to this instance of the + cdevSessionManager class. The ClientSession object that is + referenced by a specific client identifier is used to enqueue + messages that are destined for that client ID. +

        +
        + + + sockets +

        +
        + + IntHash sockets; +

        + + This is the table of SocketSession objects that are currently in + use by this instance of the cdevSessionManager class. The + SocketSession that is referenced by the socket identifier is + used to enqueue messages that are destined for that client. + The ClientHandler object dequeues messages from the queue + and writes them to the socket using multiple writes if necessary. +

        +
        +
        + + + Methods of the + cdevSessionMan + ager Class +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + getNextLocalID +

        +
        + + static short getNextLocalID (void); +

        + + Because local indexes are short integers that monotonically + increase, this method is used to obtain the next local index from + the list. +

        +
        + + + newClientSession +

        +
        + + ClientSession * newClientSession ( int SocketID, +

        + int ClientID, +

        + int LocalD); +

        + + This method is used by the cdevSessionManager whenever it + needs to create a new ClientSession object. By overriding this + method the developer may return subclassed ClientSession + objects that contain additional, server-specific information that + is associated with the client identifier. +

        +
        + + + newClientSession +

        +
        + + SocketSession * newSocketSession (int SocketID); +

        + + This method is used by the cdevSessionManager whenever it + needs to create a new SocketSession object. By overriding this + method the developer may return subclassed SocketSession + objects that contain additional, server-specific information that + is associated with the socket. +

        +
        + + + findLocalClient +

        +
        + + virtual ClientSession * findLocalClient (short localID); +

        + + This method is used to obtain a pointer to the ClientSession + object that is associated with a local client identifier. Because + the cdevServer object deals exclusively with the local client + identifier, this method allows it to obtain the ClientSession + without converting between the local and foreign client ID. +

        +
        + + + findClient +

        +
        + + virtual ClientSession * findClient (int clientID); +

        + + This method allows the caller to obtain a pointer to the + ClientSession associated with a specific client identifier. This + method uses the remotely specified client ID to locate the + ClientSession object. +

        +
        + + + findSocket +

        +
        + + virtual SocketSession * findSocket (int socketID); +

        + + This method allows the caller to locate the SocketSession + associated with a specific socket identifier. The socket identifier + is the same as the file descriptor for a specific socket. The + SocketSession object is the queue that is used by the + ServerHandler object to dequeue messages that are destined + for the client. +

        +
        + + + addClient +

        +
        + + virtual ClientSession * addClient (int socketID, int clientID); +

        + + This method is used to add a new ClientSession object to the + clients list and obtain a pointer to the new object. If a + ClientSession object already exists for the socketID/clientID + combination, then a pointer to the existing ClientSession object + will be returned. If a new ClientSession object is created, then + this method will cause a "register" message to be generated + and enqueued in the inbound queue for the cdevServer object. +

        +
        + + + addSocket +

        +
        + + virtual SocketSession * addSocket (int socketID); +

        + + This method is used to add a new SocketSession object to the + sockets list and obtain a pointer to the new object. If a + SocketSession object already exists for the specific socketID, + then the existing SocketSession object will be returned. +

        +
        + + + removeClient +

        +
        + + virtual void removeClient (int clientID, int unregisterFlag=1); +

        + + This method removes the ClientSession object associated with + a specific client identifier. If the unregister flag is non-zero, then + this method will compose and send an "unregister" message to + the inbound queue to alert the cdevServer object that the client + (local client identifier) is being removed. The server should then + remove any monitors that are associated with the local client + identifier. +

        + This method will remove and delete any outbound messages + that are destined for the specified client identifier from the + outbound queues. +

        +
        + + + removeSocket +

        +
        + + virtual void removeSocket (int socketID); +

        + + This method removes the SocketSession object associated + with the specified socket identifier from the sockets list. When a + socket is removed the ClientHandler associated with the socket + identifier will be disconnected and deleted and then all + ClientSession objects that are associated with the socket will + also be deleted. This message will delete all outbound + messages that are in the SocketSession queue or in any of its + associated ClientSession queues. +

        +
        + + + enqueue +

        +
        + + virtual int enqueue (int socketID, char * binary, unsigned len); +

        + + This method is used by the ClientHandler object to enqueue + messages that are destined for the processMessages method. + The method will create a SocketSession for the ClientHandler if + one does not already exist and will place the message into the + inbound queue. +

        + If the message is from a new client identifier, then a new + ClientSession object is created. +

        +
        + + + enqueue +

        +
        + + virtual int enqueue (cdevPacket * packet); +

        + + This method is used to enqueue a packet that is to be returned + to a client. The cdevPacket structure as described in the CLIP + literature contains a client identifier that is used to determine to + which socket the packet should be enqueued. +

        + The enqueue method will call the encodePacket method in + order to convert the packet into a cdevPacketBinary object to + be enqueued. The developer may overload that method in + order to perform any post-processing that may be necessary + before converting the packet to binary format. +

        + Note, this cdevPacket object remains the property of the caller + and must be deleted when it is no longer needed. +

        +
        + + + dequeue +

        +
        + + virtual int dequeue (cdevPacket * &packet); +

        + + This method is used to dequeue messages that have been + placed in the inbound queue. The processMessages method + will then process the message and return the result using the + enqueue method. Note that the inbound message contains a + client identifier and other components that must be returned to + the client unmodified. +

        + The dequeue method will call the decodePacket in order to + convert the binary cdevPacketBinary object into a cdevPacket + object. The developer may override that method in order to + perform any pre-processing that may be necessary before + returning the packet. +

        + Note, this cdevPacket object becomes the property of the caller + and must be deleted when it is no longer needed. +

        +
        + + + decodePacket +

        +
        + + virtual cdevPacket * dequeue (cdevPacketBinary * binary); +

        + + This method converts a cdevPacketBinary object (as stored in + the inbound queue) into a cdevPacket object. The developer + may override this method in order to perform any special pre- + processing that may be necessary prior to returning the + cdevPacket object via the dequeue method. +

        +
        + + + encodePacket +

        +
        + + virtual cdevPacketBinary * enqueue (cdevPacket * packet); +

        + + This method converts a cdevPacket object into a + cdevPacketBinary object (for submission to the client/socket + queue). The developer may override this method in order to + perform any special post-processing that may be necessary. +

        +
        + + + get_handle +

        +
        + + virtual int get_handle (void) const; +

        + + This method returns the file descriptor that is used by the + FD_Trigger object. This method is called by the ACE Reactor in + order to obtain a file descriptor for polling. +

        +
        + + + handle_input +

        +
        + + virtual int handle_input (ACE_HANDLE); +

        + + This method is called by the ACE Reactor whenever the file + descriptor in the FD_Trigger object has a read event ready. This + method will, inturn, call the processMessages method to + dequeue the message from the inbound queue and process it. +

        +
        + + + handle_close +

        +
        + + virtual int handle_close (int, ACE_Reactor_Mask); +

        + + This method is called by the ACE Reactor to close the + connections associated with this object. +

        +
        + + + handle_timeout +

        +
        + + virtual int handle_timeout ( const ACE_Time_Value&, +

        + const void *); +

        + + This method is called by the ACE Reactor when the period + specified by the Rate parameter has expired. This method will, + inturn, call the processMessages method to handle events. +

        +
        + + + set_rate +

        +
        + + virtual void set_rate (double d); +

        + + This method is used to alter the rate at which the + cdevSessionManager is periodically triggered. +

        +
        + + + get_rate +

        +
        + + virtual ACE_Time_Value& get_rate (void); +

        + + This method will return the rate at which the + cdevSessionManager object is periodically triggered. +

        +
        + + + processMessages +

        +
        + + virtual void processMessages (void); +

        + + This is a user defined method that dequeues messages, + processes them and then enqueues the result. +

        + +

        +
        +
        + + 7. +

        +
        + + + Properties of the cdevServer Class +

        +
        + + + Overview +

        +
        + + The cdevServer class is the developer's primary interface to the server side of the + CDEV Generic Server Engine. In most cases the developer will only be required to + overload the processMessages method with his own method that dequeues a + message, processes it, and then enqueues the result. The cdevServer class has the + following properties. +

        +
        + + + Attributes of the + cdevServer Class +

        +
        + + + + + + + + + + + +
        + + + Finished +

        +
        + + static sig_atomic_t Finished; +

        + + This flag is used to indicate that the server should shutdown all + connections and exit. This is a public flag that may be set by + signal handlers or by the developer. +

        +
        + + + serverName +

        +
        + + char * serverName; +

        + + This is the name of the server that was specified when the + cdevServer object was created. This name will be used to + identify the server when reporting errors or events. +

        +
        + + + acceptor +

        +
        + + class ClientAcceptor * acceptor; +

        + + This is the ClientAcceptor class that will be used to listen for + incoming connections on the specified listening socket. +

        +
        + + + timer +

        +
        + + cdevNameServerTimer * timer; +

        + + This is a timer object that will be registered with the ACE + Reactor and will reregister the service with the Name Server + periodically. If a server does not update its registration with the + Name Server at least once per minute, the Name Server will + remove its name from its list of available servers. +

        +
        + + + status +

        +
        + + int status; +

        + + The status variable is set to 0 if the ClientAcceptor was + successfully opened to listen for incoming connections, or -1 if + an error occurred while posting the listening socket. +

        +
        +
        + + + Methods of the + cdevServer Class +

        +
        + + + + + + + + + + + + + + + +
        + + + cdevServer +

        +
        + + cdevServer ( char * Domain, char * Server, +

        + unsigned short Port, double Rate); +

        + + This method is the constructor for the cdevServer class. It will + register the server with the CDEV Name Server using the + specified Domain and Server names. It will then post a listening + socket using a ClientAcceptor object on the specified Port. The + ACE Reactor will use the rate parameter to establish the + frequency in seconds in which the processMessages method + should be called. +

        +
        + + + newClientSession +

        +
        + + ClientSession * newClientSession ( int SocketID, +

        + int ClientID, +

        + int LocalD); +

        + + This method overrides the cdevSessionManager's + newClientSession method and returns a CLIPClientSession + object. The CLIPClientSession allows the cdevServer object to + associate the most recent CDEV context received with an + individual client identifier. +

        +
        + + + newSocketSession +

        +
        + + SocketSession * newSocketSession (int SocketID); +

        + + This method overrides the cdevSessionManager's + newSocketSession method and returns a CLIPSocketSession + object. The CLIPSocketSession object allows the cdevServer + object to associate a cdevTagMap object and a + cdevContextMap object with each socket identifier. +

        +
        + + + dequeue +

        +
        + + int dequeue (cdevMessage * &message); +

        + + Because the cdevServer deals only with the cdevMessage type + cdevPackets, this method will dispose of any other packet type + that is received and will return the next available cdevMessage + object from the inbound queue. +

        +
        + + + decodePacket +

        +
        + + cdevPacket * decodePacket (cdevPacketBinary * input); +

        + cdevPacket * decodePacket(cdevMessage * message); +

        + + These methods allow the cdevServer class to perform special + processing whenever a cdevMessage object is dequeued. +

        +
        + + + encodePacket +

        +
        + + cdevPacketBinary * encodePacket (cdevPacket * input); +

        + cdevPacketBinary * encodePacket(cdevMessage * message); +

        + + These methods allow the cdevServer class to perform special + processing whenever a cdevMessage object is enqueued. +

        +
        + + + operational +

        +
        + + virtual int operational (void); +

        + + This method returns a boolean integer indicating whether or not + the listening socket has been posted. If the return value is zero, + then the cdevServer cannot receive new connections. +

        +
        +
        + + 8. +

        +
        + + + Properties of the cdevServerInterface Class +

        +
        + + + Overview +

        +
        + + The cdevServerInterface class is responsible for managing all server connections for + a specific service on the client side of the connection. In most cases the developer will + not need to modify any of the code associated with this class. The properties of the + cdevServerInterface class are described below. +

        +
        + + + Attributes of the + cdevServer + Interface Class +

        +
        + + + + + + + + + + + + + + + +
        + + + Reactor +

        +
        + + static ACE_Reactor Reactor; +

        + + This is the ACE Reactor object that is used to respond to input/ + output events on the individual sockets. The developer is + responsible for calling the poll or pend method periodically in + order to force events to be handled. +

        +
        + + + connections +

        +
        + + ServerConnectionList connections; +

        + + This is a list of ServerHandler objects that are used to handle + input/output events on all currently connected servers. +

        +
        + + + domain +

        +
        + + char * domain; +

        + + This is the name of the domain in which this + cdevServerInterface class is operating. When a server name is + specified, the cdevServerInterface object will poll the Name + Server for the location of the specified server name within this + domain. +

        +
        + + + defaultServer +

        +
        + + char * defaultServer; +

        + + This is the name of the defaultServer to which messages will be + sent if no other server has been specified. The caller must + specify the name of the default server by using the "set default" + message with the server name in the "value" tag of the + outbound cdevData object. +

        +
        + + + defaultServerHandler +

        +
        + + ServerHandler * defaultServerHandler; +

        + + This is the ServerHandler object for the default server. It is + maintained separately from the ServerConnectionList in order + to reduce lookup times when the default server is accessed. +

        +
        + + + maxFd +

        +
        + + int maxFd; +

        + + This is the allocated size of the fdList array. +

        +
        + + + fdList +

        +
        + + int * fdList; +

        + + This is a an array of integers that contains the file descriptors + that are in use in the ServerHandler objects. The cdevSystem + object will request this list of integers in order to execute the + select system call to determine which file descriptors have + waiting input events. +

        +
        +
        + + + Methods of the + cdevServer + Interface Class +

        +
        + + + + + + + + + + + + + + + + + + + + + +
        + + + cdevServerInterface +

        +
        + + cdevServerInterface (char * Domain); +

        + + This is the constructor for the cdevServerInterface class. The + Domain is the name of the domain that all servers must be + registered with in the CDEV Name Server. +

        +
        + + + getDefault +

        +
        + + virtual char * getDefault (void); +

        + + This method returns the name of the default server. +

        +
        + + + getDomain +

        +
        + + virtual char * getDomain (void); +

        + + This method returns the name of the default Name Server + domain. +

        +
        + + + setDefault +

        +
        + + virtual void setDefault (char * Default); +

        + + This method allows the caller to set the name of the default + server. This method will cause the cdevServerInterface to + attach to the specified server name within the default Name + Server domain. +

        +
        + + + connect +

        +
        + + virtual ServerHandler * connect (char * server); +

        + + This method allows the caller to connect to a specified server + within the default Name Server domain. Once connected, the + ServerHandler associated with the connection will be returned + to the caller. If the server is already connected, its current + ServerHandler will be returned. +

        +
        + + + disconnect +

        +
        + + virtual ServerHandler * disconnect (char * server); +

        + + This method allows the caller to terminate a connection to the + specified server within the default Name Server domain. +

        +
        + + + enqueue +

        +
        + + int enqueue (ServerHandler *handler, char *binary, size_t len); +

        + + This method enqueues a binary data stream in the outbound + queue for the specified ServerHandler. When the + ServerHandler has reached a high-water mark (or when the + flush method is called), the data in the outbound queue will be + written to the socket. +

        +
        + + + getFd +

        +
        + + virtual int getFd (int * &fd, int &numFd); +

        + + This method allows the cdevSystem object to get the file + descriptors that are in use by the cdevServerInterface in order + to poll for read events using the select system call. +

        +
        + + + flush +

        +
        + + virtual int flush (void); +

        + int flush (int fd); +

        + + This method forces the data in the outbound queues for all + ServerHandlers (or the specified ServerHandler if the fd + parameter contains a file descriptor) to be flushed to their + associated sockets. The system will wait for up to five seconds + for all outbound data to be written. +

        +
        + + + pend +

        +
        + + virtual int pend (double seconds, int fd = -1); +

        + + This method calls the handle_events method of the ACE + Reactor to poll for inbound events. If data is ready on any of the + supported sockets, then the ServerHandler objects will be + called to handle the input. +

        +
        +
        + + 9. +

        +
        + + + Properties of the cdevClientService Class +

        +
        + + + Overview +

        +
        + + The cdevClientService class is the class that the developer will directly inherit from in + order to create his new service. This class inherits most of its functionality from the + cdevServerInterface class and either inherits or contains all of the methods necessary + for a CDEV Service. The properties of the cdevClientService class are described + below. +

        +
        + + + Attributes of the + cdevClientService + Class +

        +
        + + + + + + + + + +
        + + + callback +

        +
        + + cdevCallback callback; +

        + + This is the callback object that is used to support sendNoBlock + requests because the service implements all operations as + sendCallback operations. In situations where no callback object + has been specified, this one is used by default. +

        +
        + + + transactions +

        +
        + + AddressIndex transactions; +

        + + This is a table that contains a list of all active transaction + objects. When a transaction is returned from the server, its + associated transaction object is removed from this list and + deleted. +

        +
        + + + contexts +

        +
        + + cdevContextMap contexts; +

        + + This is a table that contains a copy of all contexts that have + been used by the service. This table is used to allow the + cdevRequestObjects to maintain an integer identifier for their + current context and to simplify detection of context changes to + a specific socket. +

        +
        + + + tagCallback +

        +
        + + cdevClientTagCallback tagCallback; +

        + + This is a callback object that will be called each time a new tag + is placed in the cdevGlobalTagTable. This callback causes a + new copy of the cdevTagMap to be submitted to each server. +

        +
        +
        + + + Methods of the + cdevClientService + Class +

        +
        + + + + + + + + + + + + + + + + + + + +
        + + + cdevClientService +

        +
        + + cdevClientService ( char * domain, char * name, +

        + cdevSystem & system = +

        + cdevSystem::defaultSystem()); +

        + + This is the constructor for the cdevClientService object. The + domain parameter specifies the name of the Name Server + domain where its servers will be found. The name parameter is + the name of the service and the system parameter is a + reference to the cdevSystem object that it will use. +

        +
        + + + defaultCallback +

        +
        + + static void defaultCallback ( int, void *, +

        + cdevRequestObject &, +

        + cdevData &); +

        + + This is the default callback function that is used by the callback + attribute for processing sendNoBlock messages. +

        +
        + + + outputError +

        +
        + + virtual int outputError ( int severity, char *name, +

        + char *formatString,...); +

        + + This method is used by the class to display error and warning + messages. This method calls the reportError method of the + cdevSystem object. +

        +
        + + + flush +

        +
        + + int flush (void); +

        + + This method causes all messages that are waiting in the + outbound queues to be flushed to their associated sockets. +

        +
        + + + pend +

        +
        + + int pend (double seconds, int fd = -1); +

        + + This method causes the service to pend for a specified number + of seconds and wait for read events on its file descriptors. +

        +
        + + + poll +

        +
        + + int poll (void); +

        + + This method causes the service to pend for a very short period + of time and wait for read events on its file descriptors. +

        +
        + + + pend +

        +
        + + int pend (int fd = -1); +

        + + This method causes the service to pend until the next read + event occurs on one of its file descriptors. +

        +
        + + + getNameServer +

        +
        + + int getNameServer (cdevDevice * &ns); +

        + + This method is typically used to return a pointer to a service + specific local Name Server device. Because this option is not + currently supported by this service, the ns parameters is set to + NULL and 0 is returned. +

        +
        + + + getRequestObject +

        +
        + + int getRequestObject ( char * device, char * message, +

        + cdevRequestObject * &req); +

        + + This method is used by the cdevSystem object to obtain a + specific cdevRequestObject associated with the specified + device and message. +

        +
        + + +

        + + + + + + + + + +
        + + + enqueue +

        +
        + + int enqueue ( char * server, cdevData * in, +

        + cdevTranObj & xobj); +

        + int enqueue ( ServerHandler * handler, +

        + cdevData * in, cdevTranObj & xobj); +

        + + These methods are called by the cdevClientRequestObject to + enqueue messages to be sent to a specific server. The server + may be specified either by the server name or by the + associated ServerHandler object. +

        +
        + + + cancel +

        +
        + + int cancel (cdevTranObj & xobj); +

        + + This message is used to cancel a transaction that has already + been sent. Since a transaction cannot be canceled once sent to + the server, this method simply removes its transaction number + from the list of transactions and deletes its transaction object. +

        +
        + + + enqueue +

        +
        + + int enqueue ( int status, ServerHandler * handler, +

        + char * binary, size_t binaryLen); +

        + + This method is called by the cdevServerInterface to enqueue + an inbound packet that has been received from a server. The + status indicates whether the message was successfully sent + and the ServerHandler indicates the server that the message + was destined for. This method will call the fireCallback method + to dispatch the message. +

        +
        + + + fireCallback +

        +
        + + void fireCallback ( int status, cdevTranObj &xobj, +

        + cdevData *resultData, +

        + int partialTransaction = 0); +

        + + This method will execute the callback method associated with + the specified transaction object. If non-zero, the + partialTransaction flag indicates that the request that is being + serviced will generate multiple responses. +

        + +

        +
        +
        + + 10. +

        +
        + + + Properties of the cdevClientRequestObject Class +

        +
        + + + Overview +

        +
        + + The cdevClientRequestObject is a cdevRequestObject class that has been optimized + to operate with the cdevClientService class. The cdevClientRequestObject class has + the following properties. +

        +
        + + + Attributes of the + cdevClient + RequestObject + Class +

        +
        + + + + + + + + + + + + + + + + + +
        + + + sendStatus +

        +
        + + SendStatus sendStatus; +

        + + This is a structure that is used as the user argument to the + default callback for the cdevClientRequestObject. Whenever a + send method is executed, the request object can detect that the + operation has completed by polling this value. +

        +
        + + + server +

        +
        + + char server [256]; +

        + + This is the name of the server that the + cdevClientRequestObject is currently connected to. This value + is maintained in order to reestablish the connection if a + communication error occurs. +

        +
        + + + DDL_server +

        +
        + + char DDL_server[256]; +

        + + This is the server name that is specified in the CDEV DDL file + as the default server for this device/message combination. +

        +
        + + + syncCallback +

        +
        + + cdevCallback syncCallback; +

        + + This is the callback object that is used to receive the callback + when the send method is executed. The callback used by this + method expects to receive a SendStatus structure as its user + argument. +

        +
        + + + handler +

        +
        + + ServerHandler * handler; +

        + + This is the ServerHandler object for the server to which the + cdevClientRequestObject is currently attached. +

        +
        + + + contextID +

        +
        + + int contextID; +

        + + This is the index of the current context from the + cdevContextMap that is maintained in the service. This + identifier is used during transmission to determine if the context + has changed since the last transmission. +

        +
        + + + commandCode +

        +
        + + int commandCode; +

        + + This is an integer that holds an enumerated type identifying the + command or verb that the cdevClientRequestObject supports. + The standard verbs are "get", "set", "monitorOn", and + "monitorOff". +

        +
        + + + messageCode +

        +
        + + int messageCode; +

        + + This is an integer that holds an enumerated type identifying the + message that the cdevClientRequestObject supports. Typically + only messages that are intrinisic to the service layer will be + enumerated here. The following messages are currently + supported: "get servers", "get default", "set default", and + "disconnect". +

        +
        +
        + + + Methods of the + cdevClient + RequestObject + Class +

        +
        + + + +
        + + + +

        + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + constructor +

        +
        + + cdevClientRequestObject ( char * device, char * message, +

        + cdevSystem & system = +

        + cdevSystem::defaultSystem()); +

        + + This is the constructor for the cdevClientRequestObject. It will + check the CDEV DDL file to determine if a default server has + been established for this device/message combination. +

        +
        + + + setContext +

        +
        + + virtual int setContext (cdevData & ctx); +

        + + This method is used to set the context for the + cdevClientRequestObject. The context may be used to + establish the default server that the request object will + communicate with if the server tag has been set. If the server + tag is unspecified, then the server specified in the CDEV DDL + file will be used. If no server has been specified in the CDEV + DDL file, then the request object will rely on the + cdevClientService to use the default server. +

        +
        + + + send +

        +
        + + virtual int send (cdevData & in, cdevData & out); +

        + virtual int send (cdevData * in, cdevData & out); +

        + virtual int send (cdevData & in, cdevData * out); +

        + virtual int send (cdevData * in, cdevData * out); +

        + + This method will synchronously transmit the device/message + combination to the server. See the setContext method for + details on how the target server is selected. +

        +
        + + + sendNoBlock +

        +
        + + virtual int sendNoBlock (cdevData & in, cdevData & out); +

        + virtual int sendNoBlock (cdevData * in, cdevData & out); +

        + virtual int sendNoBlock (cdevData & in, cdevData * out); +

        + virtual int sendNoBlock (cdevData * in, cdevData * out); +

        + + This method will asynchronously transmit the device/message + combination to the server. The caller is required to poll the + system in order to allow the transmission to be processed. See + the setContext method for information on how the target server + is selected. +

        +
        + + + sendCallback +

        +
        + + virtual int sendCallback (cdevData & in, cdevCallback &); +

        + virtual int sendCallback (cdevData * in, cdevCallback &); +

        + + This method will asynchronously transmit the device/message + combination to the server and will call a developer specified + callback function when the message has been processed. The + caller is required to poll the system in order to provide time for + the transmission to be processed. See the setContext method + for information on how the target server is selected. +

        +
        + + + className +

        +
        + + virtual const char * className (void) const; +

        + + This method returns the name of the class. +

        +
        + + + defaultCallback +

        +
        + + static void defaultCallback ( int status, void * user, +

        + cdevRequestObject &, +

        + cdevData &); +

        + + This is the callback function that will be executed when the + synchronous send method has been used. It will set the value + of the SendStatus structure that was passed as its user + argument to indicate completion and the status of the call. +

        +
        + + + executeServer HandlerCallback +

        +
        + + +

        + virtual void executeServerHandlerCallback (ServerHandler*); +

        + + This method is inherited from the ServerHandlerCallback + method and will be called by the ServerHandler that is currently + in use by this request object prior to its destruction. This allows + the request object to set the pointer to NULL to avoid accessing + an invalid or deleted data item later. +

        +
        + + + getServerHandler +

        +
        + + virtual int getServerHandler (ServerHandler ** Handler); +

        + + This method allows the caller to get a pointer to the + ServerHandler that is in use by the cdevClientRequestObject. + When called, this method will check the class parameters and + attach or reattach to a server if necessary before returning the + ServerHandler object. +

        +
        + + + getContextID +

        +
        + + int getContextID (void); +

        + + This method returns the context index that uniquely identifies + the context that is in use within this cdevClientRequestObject. + This value is used by the service to determine if the context + data needs to be retransmitted to the server. +

        +
        + + + getCommandCode +

        +
        + + int getCommandCode (void); +

        + + This method returns the command code that identifies the verb + portion of the message used by this request object. This code + is used by the service to avoid having to perform string + comparisons to identify the message content. +

        +
        + + + getMessageCode +

        +
        + + int getMessageCode (void); +

        + + This method returns the message code that identifies the + message in use by this request object. This code is used by the + service to identify messages that may be processed locally + rather than being transmitted to the server. +

        +
        +
        +
        + + 11. +

        +
        + + + Implementing Monitoring on the cdevServer +

        +
        + + + Overview +

        +
        + + Monitoring is implemented on the cdevServer by the use of a cdevMonitorTable + class. This class stores a collection of cdevMonitorNode objects that are represented + by a device name and its associated attribute name. Within each of the + cdevMonitorNode objects there is a list of cdevMonitorEntry objects that contain + information regarding an individual monitor request - this information is stored in the + form of the cdevMessage object that was used to place the request. +

        + The cdevMonitorTable provides the methods to insert and remove monitors and to + retrieve the cdevMonitorNode objects that are used by individual device/attribute + pairs. By using the node directly to trigger monitors, the application can greatly speed + the delivery of messages when a monitored value changes. +

        + The following object model describes the general structure of the cdevMonitorTable. +

        + + Figure 3: + + General Structure of the cdevMonitorTable + +

        + + +

        +
        + + + Special Notes +

        +
        + + Because a monitor generates many responses from the request, the service has to be + able to differentiate it from the transaction that generate a single response. To + accomodate this, the cdevMonitorTable uses the operationCode member of the + cdevMessage structure to indicate that the result is one message of many messages + that may be generated. If the first bit of the operationCode is non-zero, then the + response is one of many. If the first bit of the operationCode is zero, then this is the + last response that will be generated by the monitorOn request. +

        +
        + + + Attributes of the + cdevMonitorTable + Class +

        +
        + + + +
        + + + monitors +

        +
        + + StringHash monitors; +

        + + This is a hash table that is hashed on a string representation of + the device/attribute combination. Each hash entry points to the + cdevMonitorNode for that specific hash string combination. +

        +
        +
        + + + Methods of the + cdevMonitorTable + Class +

        +
        + + + + + + + + + + + + + +
        + + + insertMonitor +

        +
        + + int insertMonitor ( cdevMessage * request, +

        + cdevData * data); +

        + int insertMonitor ( cdevMessage * request, +

        + cdevData ** data, size_t dataCnt); +

        + + This method allows the caller to insert a new monitor for the + device and attribute that are specified in the cdevMessage + object. The data that is provided with the call contains the + current settings for all properties of the device/attribute + combination and will be used to dispatch the initial callback. If + the cdevMessage object contains a list of multiple devices, then + the second insertMonitor method is used to provide an array of + cdevData objects containing the settings for each device. +

        + The cdevMessage object that is provided to this method + becomes the property of the cdevMonitorTable and should not + be accessed again by the caller. +

        +
        + + + removeMonitor +

        +
        + + int removeMonitor (cdevMessage * request); +

        + + This method allows the caller to remove a monitor that was + previously installed using the insertMonitor method. +

        + +

        +
        + + + remove ClientMonitors +

        +
        + + int removeClientMonitors(short clientID); +

        + + This method will remove all monitors that are associated with a + specific client identifier. This method is typically employed to + remove all of a client's monitors when it is disconnected. +

        +
        + + + findMonitor +

        +
        + + cdevMonitorNode * findMonitor ( char * device, +

        + char * attrib); +

        + + This method is used to locate the collection of monitors that is + associated with one device/attribute pair. An object that + manages the values of that device/attribute pair may use this + cdevMonitorNode to directly trigger monitors when one or more + its properties are changed. +

        +
        + + + fireMonitor +

        +
        + + int fireMonitor ( char * device, char * attrib, +

        + char * property, cdevData * data); +

        + int fireMonitor ( char * device, char * attrib, +

        + int property, cdevData * data); +

        + + This method is used to trigger the callbacks for the monitors + that are associated with the specified device/attribute pair. The + property that has been changed is provided in the property + parameter and a list of the current values of all properties + should be provided in the data parameter. When this method is + called it will locate all monitors that are triggered by the + specified property and will use the context associated with the + monitor to load the desired property values into the outbound + data object. +

        +
        + + + fireCallback +

        +
        + + int fireCallback (cdevMessage * message); +

        + + This is a pure virtual method that the developer must provide. + This method is called when the cdevMonitorTable has a + monitor that needs to be dispatched. The data is provided to + the method in the form of a cdevMessage object which must be + dispatched to the client using the user provided mechanisms. +

        +
        +
        + + + Attributes of the + cdevMonitorNode + Class +

        +
        + + + + + + + +
        + + + parent +

        +
        + + class cdevMonitorTable * parent; +

        + + This is a pointer to the cdevMonitorTable that contains this + cdevMonitorNode. This pointer will be used to access the user + defined fireCallback method when a monitor must be + dispatched. +

        +
        + + + node +

        +
        + + cdevMonitorEntry * nodes; +

        + + This is a list of all of the monitors that are associated with this + cdevMonitorNode. +

        +
        + + + hashString +

        +
        + + char * hashString; +

        + + This is a unique string that is composed of the device name + and attribute that is used to identify this cdevMonitorNode + within the list of all cdevMonitorNodes that a cdevMonitorTable + may be managing. +

        +
        +
        + + + Methods of the + cdevMonitorNode + Class +

        +
        + + + + + +
        + + + fireMonitor +

        +
        + + int fireMonitor (char * property, cdevData * data); +

        + int fireMonitor (int property, cdevData * data); +

        + + This method is called in order to trigger all monitors that are + associated with the specified property. When the method is + called it will walk through the cdevMonitorEntry objects and + locate each one that is associated with the specified property. It + will then evaluate the context for that entry and populate the + outbound data with the appropriate properties before calling + the fireCallback method of its parent cdevMonitorTable object. +

        +
        + + + isMonitored +

        +
        + + int isMonitored (void); +

        + + This method returns a boolean value that indicates if there are + any active monitors that have been placed on this + cdevMonitorNode object. +

        + +

        +
        +
        + + 12. +

        +
        + + + VirtualService: A Complex Client/Server Implementation +

        +
        + + + Overview +

        +
        + + The VirtualService example gives the developer a complex illustration of how to create + a client/server system that provides for getting, setting and monitoring specific + properties of a virtual device/attribute pair. By examining the source code, the + developer can also get an understanding of the different approaches used to return + message completion codes to the client and how to establish and trigger monitors + using the components that are provided with the distribution. +

        +
        + + + Virtual Server + Structure +

        +
        + + The server side of the VirtualService example is structured as described in the object + model below. +

        + + Figure 4: + + Components of the Virtual Server + +

        +
        + + + Virtual Service + Structure +

        +
        + + The client side of the VirtualService example is much less complex and inherits + almost all of its functionality from the cdevClientService class and declares no + specialized request object class. +

        + + Figure 5: + + Components of the Virtual Service + +

        + + +

        +
        + +


        + + + +
        + + + VirtualAttrib.h +

        +
        + + The following header file defines the structure of the VirtualAttrib class. A VirtualAttrib object is used to represent a single + entity within the VirtualServer. Each VirtualAttrib is represented by a device name and an associated attribute. This device/ + attribute pair has a collection of properties that may be read, written to, or monitored. All of these properties are set using + methods in order to allow the class to ensure that they are set within the specified range and to allow the monitor callbacks to + be fired when a value changes. +

        + Additionally, helper functions have been added that allow the caller to populate the properties of the VirtualAttrib using a + cdevData object that contains tagged data items that specify the new values. Other methods allow the caller to read selected + properties into an outbound cdevData object using a caller specified context. +

        +
        +


        + + + +
        + + + + + +

        +
        
        +#ifndef _VIRTUAL_ATTRIB_H_
        +#define _VIRTUAL_ATTRIB_H_ 1
        + 
        +#include <cdevData.h>
        +#include <VirtualServer.h>   
        +   
        +// *****************************************************************************
        +// * class VirtualAttrib:
        +// *   This class maintains a list of items that make-up a Virtual Attrib. And
        +// *   access mechanisms.
        +// *****************************************************************************
        +class VirtualAttrib
        +{
        +private:
        +   char             * device;
        +
        +   char             * attrib;
        +   cdevMonitorNode * monitors;
        +      
        +   double   value;
        +
        +   char   status  [255];
        +    char   severity[255];
        +   char   units   [255];
        +   double   alarmHigh;
        +   double   alarmLow;
        +   double   warningHigh;
        +   double   warningLow;
        +   double   controlHigh;
        +   double   controlLow;
        +   int   resultCode;
        + 
        +public:
        +   VirtualAttrib      (char * Device, char * Attrib);
        +   ~VirtualAttrib      ( void );
        +   
        +   int   setFromData   ( cdevData * data );
        +
        +   void   getToData   ( cdevData * data, cdevData * context = NULL );
        +   void   getAllToData   ( cdevData * data );
        +   
        +   int   setValue   ( double Value );
        +
        +   int   setStatus   ( char * Status );
        +   int   setSeverity   ( char * Severity );
        +   int   setUnits   ( char * Units );
        +   int   setAlarmHigh   ( double AlarmHigh );
        +   int   setAlarmLow   ( double AlarmLow );  
        +   int   setWarningHigh   ( double WarningHigh );
        +   int   setWarningLow   ( double WarningLow );
        +   int   setControlHigh   ( double ControlHigh );
        +   int   setControlLow   ( double ControlLow );
        +   void   checkAlarms   ( void );
        +   
        +   double   getValue   ( void ) { return value; }
        +
        +   char *   getStatus   ( void ) { return status; }
        +   char *   getSeverity   ( void ) { return severity; }
        +   char *   getUnits   ( void ) { return units; }
        +   double   getAlarmHigh   ( void ) { return alarmHigh; }
        +   double   getAlarmLow   ( void ) { return alarmLow; }
        +   double   getWarningHigh   ( void ) { return warningHigh; }
        +   double   getWarningLow   ( void ) { return warningLow; }
        +   double   getControlHigh   ( void ) { return controlHigh; }
        +   double   getControlLow   ( void ) { return controlLow; }
        +   int   getResultCode   ( void ) { return resultCode; }
        +   
        +   void   insertMonitor   ( cdevMonitorTable * table, cdevMessage * message );
        +
        +   void   removeMonitor   ( cdevMonitorTable * table, cdevMessage * message );
        +};
        + 
        +#endif
        + 
        +
        +	
        + + + +
        + + + VirtualAttrib.cc +

        +
        + + This is the source file that defines the implementation details of the VirtualDevice class. The methods below are used to + insert and retrieve properties associated with the device/attribute pairs that are represented by each VirtualDevice object. +

        +
        + + + +

        +
        
        +#include <VirtualAttrib.h>
        + 
        +static int VALUE_TAG   = -1;
        +	
        + + + +
        + + + + These static integers will be populated with the associated tag identifiers + that are used in the cdevData object. By using the tag identifier integer + rather than the associated character string, performance is greatly + improved when accessing properties stored in the cdevData object. +

        +
        +
        + +static int STATUS_TAG = -1; +static int SEVERITY_TAG = -1; +static int UNITS_TAG = -1; +static int ALARMHIGH_TAG = -1; +static int ALARMLOW_TAG = -1; +static int WARNINGHIGH_TAG = -1; +static int WARNINGLOW_TAG = -1; +static int CONTROLHIGH_TAG = -1; +static int CONTROLLOW_TAG = -1; + + +// ***************************************************************************** +// * VirtualAttrib::VirtualAttrib : +// * This is the constructor for the VirtualAttrib class. It initializes the +// * internal mechanisms to 0. +// ***************************************************************************** +VirtualAttrib::VirtualAttrib ( char * Device, char * Attrib ) + : device(strdup(Device)), +
        + + + +
        + + + + The constructor for the VirtualAttrib object makes a copy of the name of + the device and attribute and then initializes all of its internal properties. + Note that if the 'high' and 'low' values for a range specification (such as + alarm) are equal, then that range specification is disabled. +

        +
        +
        + + attrib(strdup(Attrib)), + monitors(NULL), + value(0.0), + alarmHigh(0.0), + alarmLow(0.0), + warningHigh(0.0), + warningLow(0.0), + controlHigh(0.0), + controlLow(0.0) + { + *severity = 0; + *units = 0; + strcpy(status, "NORMAL"); + } + +// ***************************************************************************** +// * VirtualAttrib::~VirtualAttrib : +// * This is the destructor for the VirtualAttrib class. It must free the +// * memory associated with the device and attribute names. +// ***************************************************************************** +VirtualAttrib::~VirtualAttrib ( void +) +
        + + + +
        + + + + The destructor for a VirtualAttrib object only needs to delete the device + and attrib strings that were duplicated when the object was created. +

        +
        +
        + + { + delete device; + delete attrib; + } + +// ***************************************************************************** +// * VirtualAttrib::setFromData : +// * This method will populate the VirtualAttrib object with the data contained in +// * the cdevData object. +// ***************************************************************************** +int VirtualAttrib::setFromData ( cdevData * data ) +
        + + + +
        + + + + When a "set" cdevMessage + object is received in the + processMessages method of + the VirtualServer, it contains a + cdevData object that has a list + of properties and values. For + each property that is specified + this method will call the set + method with the new value. If + the value is different than the + previous value and the + property is monitored, then the + callback will be fired at that + time. +

        + + +

        + + The result of this operation is + indicated by success in setting + the value property. +

        +
        +
        + + { + double val; + int result; + if(data!=NULL) + { + result = CDEV_SUCCESS; + data->get(UNITS_TAG, units, 255); + if(data->get(CONTROLLOW_TAG, &val)==CDEV_SUCCESS) setControlLow(val); + if(data->get(CONTROLHIGH_TAG, &val)==CDEV_SUCCESS) setControlHigh(val); + if(data->get(ALARMLOW_TAG, &val)==CDEV_SUCCESS) setAlarmLow(val); + if(data->get(ALARMHIGH_TAG, &val)==CDEV_SUCCESS) setAlarmHigh(val); + if(data->get(WARNINGLOW_TAG, &val)==CDEV_SUCCESS) setWarningLow(val); + if(data->get(WARNINGHIGH_TAG, &val)==CDEV_SUCCESS) setWarningHigh(val); + if(data->get(VALUE_TAG, &val)==CDEV_SUCCESS) + { + result=setValue(val); + } + } + else result = CDEV_ERROR; + checkAlarms(); + return result; + } + + +// ***************************************************************************** +// * VirtualAttrib::getToData : +// * This method will populate the VirtualAttrib object with the data contained in +// * the cdevData object. +// ***************************************************************************** +void VirtualAttrib::getToData ( cdevData * data, cdevData * context ) +
        + + + +
        + + + + When a "get" cdevMessage object is received in the + processMessages method of the VirtualServer, it + contains a context that indicates the properties that the + caller desires to be returned. This method walks through + the context object and copies each property that is + specified in the context into the cdevData object pointed + to by the data parameter. Once populated, this object will + be returned to the caller. +

        + +

        + If the context is empty, then the "value", "status", and + "severity" properties are returned by default. +

        +
        +
        + + { + if(data!=NULL) + { + data->remove(); + if(context!=NULL) + { + if(context->getType(VALUE_TAG)!=CDEV_INVALID) + data->insert(VALUE_TAG, getValue()); + if(context->getType(STATUS_TAG)!=CDEV_INVALID) + data->insert(STATUS_TAG, getStatus()); + if(context->getType(SEVERITY_TAG)!=CDEV_INVALID) + data->insert(SEVERITY_TAG, getSeverity()); + if(context->getType(UNITS_TAG)!=CDEV_INVALID) + data->insert(UNITS_TAG, getUnits()); + if(context->getType(CONTROLLOW_TAG)!=CDEV_INVALID) + data->insert(CONTROLLOW_TAG, getControlLow()); + if(context->getType(CONTROLHIGH_TAG)!=CDEV_INVALID) + data->insert(CONTROLHIGH_TAG, getControlHigh()); + if(context->getType(ALARMLOW_TAG)!=CDEV_INVALID) + data->insert(ALARMLOW_TAG, getAlarmLow()); + if(context->getType(ALARMHIGH_TAG)!=CDEV_INVALID) + data->insert(ALARMHIGH_TAG, getAlarmHigh()); + if(context->getType(WARNINGLOW_TAG)!=CDEV_INVALID) + data->insert(WARNINGLOW_TAG, getWarningLow()); + if(context->getType(WARNINGHIGH_TAG)!=CDEV_INVALID) + data->insert(WARNINGHIGH_TAG, getWarningHigh()); + } + else + { + data->insert(VALUE_TAG, getValue()); + data->insert(STATUS_TAG, getStatus()); + data->insert(SEVERITY_TAG, getSeverity()); + } + } + } + + +// ***************************************************************************** +// * VirtualAttrib::getAllToData : +// * This method will populate the VirtualAttrib object with the data contained in +// * the cdevData object. +// ***************************************************************************** +void VirtualAttrib::getAllToData ( cdevData * data ) +
        + + + +
        + + + + Unlike the getToData method, this method will populate + the cdevData object will all properties that are currently + contained in the VirtualAttrib object. +

        +
        +
        + + { + if(data!=NULL) + { + data->remove(); + data->insert(VALUE_TAG, getValue()); + data->insert(STATUS_TAG, getStatus()); + data->insert(SEVERITY_TAG, getSeverity()); + data->insert(UNITS_TAG, getUnits()); + data->insert(CONTROLLOW_TAG, getControlLow()); + data->insert(CONTROLHIGH_TAG, getControlHigh()); + data->insert(ALARMLOW_TAG, getAlarmLow()); + data->insert(ALARMHIGH_TAG, getAlarmHigh()); + data->insert(WARNINGLOW_TAG, getWarningLow()); + data->insert(WARNINGHIGH_TAG, getWarningHigh()); + } + } + +// ***************************************************************************** +// * VirtualAttrib::setValue : +// * This method allows the caller to set the value of the Virtual Attrib. +// * This call will fail if the specified value is outside of the legal +// * range. +// ***************************************************************************** +int VirtualAttrib::setValue ( double Value ) +
        + + + +
        + + + + The setValue method is used to set the value property within the VirtualAttrib + object. Since the overall range may be specified using the controlHigh and + controlLow properties, this method will ensure that the new value conforms to the + range (if specified) and will fail if the value is too high or too low. +

        +
        +
        + + { + resultCode = CDEV_SUCCESS; + + if(controlHigh>controlLow && + (Value<controlLow || Value>controlHigh)) + { + resultCode = CDEV_OUTOFRANGE; + } + else if(value != Value) + { + value = Value; + checkAlarms(); +
        + + + +
        + + + + The checkAlarms method is called after the value has been set. The + checkAlarms method determines if the new value places the VirtualAttrib + in a warning or alarm state based on the confines that are specified in the + alarmHigh/Low and warningHigh/Low properties. +

        + If the VirtualAttrib is monitored, then all properties will be copied into a + cdevData object and the list of monitors for the value property will be fired. +

        +
        +
        + + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(VALUE_TAG, &data); + } + } + return resultCode; + } + +// ***************************************************************************** +// * VirtualAttrib::setStatus : +// * This method allows the caller to set the status of the device. +// ***************************************************************************** +int VirtualAttrib::setStatus ( char * Status ) +
        + + + +
        + + + + Sets the status property and fires any monitors that may be associated + with that value. +

        +
        +
        + + { + if(strcmp(status, Status)) + { + strncpy(status, Status, 255); + status[254] = 0; + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(STATUS_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setSeverity : +// * This method allows the caller to set the severity flag for the device. +// ***************************************************************************** +int VirtualAttrib::setSeverity ( char * Severity ) +
        + + + +
        + + + + Sets the severity property and fires any monitors that may be associated + with that value. +

        +
        +
        + + { + if(strcmp(severity, Severity)) + { + strncpy(severity, Severity, 255); + severity[254] = 0; + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(SEVERITY_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setUnits : +// * This method allows the caller to set the units for the device. +// ***************************************************************************** +int VirtualAttrib::setUnits ( char * Units ) +
        + + + +
        + + + + Sets the units property and fires any monitors that may be associated with + that value. +

        +
        +
        + + { + if(strcmp(units, Units)) + { + strncpy(units, Units, 255); + units[254] = 0; + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(UNITS_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setAlarmHigh : +// * This method allows the caller to set the high alarm value of the device. +// ***************************************************************************** +int VirtualAttrib::setAlarmHigh ( double AlarmHigh ) +
        + + + +
        + + + + Sets the alarmHigh property and calls checkAlarms to determine if a + change in this value will trigger a change in the device alarm status. + Dispatches any monitors that are associated with the property. +

        +
        +
        + + { + if(alarmHigh!=AlarmHigh) + { + alarmHigh = AlarmHigh; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(ALARMHIGH_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setAlarmLow : +// * This method allows the caller to set the low alarm value of the device. +// ***************************************************************************** +int VirtualAttrib::setAlarmLow ( double AlarmLow ) +
        + + + +
        + + + + Sets the alarmLow property and calls checkAlarms to determine if a + change in this value will trigger a change in the device alarm status. + Dispatches any monitors that are associated with the property. +

        +
        +
        + + { + if(alarmLow!=AlarmLow) + { + alarmLow = AlarmLow; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(ALARMLOW_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setWarningHigh : +// * This method allows the caller to set the high warning value of a device. +// ***************************************************************************** +int VirtualAttrib::setWarningHigh ( double WarningHigh +) +
        + + + +
        + + + + Sets the warningHigh property and calls checkAlarms to determine if a + change in this value will trigger a change in the device warning status. + Dispatches any monitors that are associated with the property. +

        +
        +
        + + { + if(warningHigh!=WarningHigh) + { + warningHigh = WarningHigh; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(WARNINGHIGH_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setWarningLow : +// * This method allows the caller to set the low warning value of a device. +// ***************************************************************************** +int VirtualAttrib::setWarningLow ( double WarningLow ) +
        + + + +
        + + + + Sets the warningLow property and calls checkAlarms to determine if a + change in this value will trigger a change in the device warning status. + Dispatches any monitors that are associated with the property. +

        +
        +
        + + { + if(warningLow != WarningLow) + { + warningLow = WarningLow; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(WARNINGLOW_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setControlHigh : +// * This method allows the caller to set the maximum value for a device. +// ***************************************************************************** +int VirtualAttrib::setControlHigh ( double ControlHigh ) +
        + + + +
        + + + + Sets the controlHigh property and calls checkAlarms to determine if a + change in this value will trigger a change in the device status. + Dispatches any monitors that are associated with the property. +

        +
        +
        + + { + if(controlHigh != ControlHigh) + { + controlHigh = ControlHigh; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(CONTROLHIGH_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setControlLow : +// * This method allows the caller to set the minimum value of a device. +// ***************************************************************************** +int VirtualAttrib::setControlLow ( double ControlLow ) +
        + + + +
        + + + + Sets the controlLow property and calls checkAlarms to determine if a + change in this value will trigger a change in the device status. + Dispatches any monitors that are associated with the property. +

        +
        +
        + + { + if(controlLow != ControlLow) + { + controlLow = ControlLow; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(CONTROLLOW_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::checkAlarms : +// * This method allows the caller to read the value in comparison with all +// * of its limits and set the status and severity tag appropriately. +// ***************************************************************************** +void VirtualAttrib::checkAlarms ( void ) +
        + + + +
        + + + + This method tests the value property against the ranges that may be + specified in the warningHigh/Low, alarmHigh/Low and controlHigh/Low + properties. If the value is outside of any of these ranges, then the status + and severity variables will be set to a corresponding value: "WARNING", + "ALARM", or "ERROR" +

        +
        +
        + + { + int done = 0; + if(controlHigh>controlLow) + { + { + setStatus("OUT OF RANGE LOW"); + setSeverity("ERROR"); + done = 1; + } + else if (value>controlHigh) + { + setStatus("OUT OF RANGE HIGH"); + setSeverity("ERROR"); + done = 1; + } + } + if(!done && alarmHigh>alarmLow) + { + { + setStatus("ALARM LOW"); + setSeverity("ALARM"); + done = 1; + } + else if (value>alarmHigh) + { + setStatus("ALARM HIGH"); + setSeverity("ALARM"); + done = 1; + } + } + if(!done && warningHigh>warningLow) + { + { + setStatus("WARNING LOW"); + setSeverity("WARNING"); + done = 1; + } + else if (value>warningHigh) + { + setStatus("WARNING HIGH"); + setSeverity("WARNING"); + done = 1; + } + } + if(!done) + { + setStatus("NORMAL"); + setSeverity("\\0"); + } + } + +// ***************************************************************************** +// * VirtualAttrib::insertMonitor : +// * This message adds a monitor to the cdevMonitorTable for this device/ +// * attribute pair. The message parameter becomes the property of the +// * monitorTable and should not be accessed again by the caller. +// ***************************************************************************** +void VirtualAttrib::insertMonitor ( cdevMonitorTable * table, cdevMessage * message ) + { +
        + + + +
        + + + + The processMessages method of the VirtualServer class + calls this method when it receives a "monitorOn" message. + This method collects all of the current property values into a + cdevData object and then submits the cdevMessage object + and the data to the insertMonitor method of the + cdevMonitorTable object. The method will then call + findMonitor to locate its node in the cdevMonitorTable for later + access. +

        + Note that the cdevMessage object becomes the property of + the cdevMonitorTable object and should not be accessed + again. +

        +
        +
        + + if(table!=NULL && message!=NULL) + { + cdevData data; + getAllToData(&data); + table->insertMonitor(message, &data); + monitors = table->findMonitor(device, attrib); + if(monitors && !monitors->isMonitored()) monitors = NULL; + } + else if(message!=NULL) delete message; + } + + + + +// ***************************************************************************** +// * VirtualAttrib::removeMonitor: +// * This method uses the cancelTransIdx to locate and delete a monitor +// * that was previously posted using that transaction index. +// ***************************************************************************** +void VirtualAttrib::removeMonitor (cdevMonitorTable * table, cdevMessage * message ) + { +
        + + + +
        + + + + The processMessages method of the VirtualServer class + calls this method when it receives a "monitorOff" message. + The method will call the removeMonitor method of the + cdevMonitorTable to remove the monitor. +

        + If all monitors have been removed that are associated with + this VirtualAttrib object, then the monitors pointer will be set + to NULL. +

        +
        +
        + + if(table!=NULL && message!=NULL) + { + table->removeMonitor(message); + if(monitors && !monitors->isMonitored()) monitors = NULL; + } + } + + + + +
        + + + +
        + + + VirtualServer.h +

        +
        + + The following header file defines the structure of the VirtualServer class. The VirtualServer class inherits its functionality from + the cdevServer object and consequently has to do very little initialization. When created it calls the populateTable method to + generate a list of VirtualAttrib objects that it will support, the service may then manipulate any of the devices that the server + has created using the commands "get", "set", "monitorOn", and "monitorOff". +

        +
        + + + +

        +
        
        +#include <cdevServer.h>
        +#include <StringHash.h>
        +#include <cdevMonitorTable.h>
        +// *****************************************************************************
        +// * class VirtualServer :
        +// *   This is the server class for the VirtualDevice.  It simply receives 
        +// *   messages from a client and immediately returns them.
        +// *
        +// *   The constructor passes the domain, server, port and rate to the
        +// *   underlying cdevServer class to be processed.  The cdevServer constructor
        +// *   will add this server to the Name Server and will begin processing 
        +// *   messages when the cdevServer::runServer() method is executed.
        +// *
        +// *   The processMessages method is the servers interface to the world... Each
        +// *   time a complete message is received or the time specified in rate
        +// *   expires, that method will be called.
        +// *****************************************************************************
        +class VirtualServer : public cdevServer, public cdevMonitorTable
        +{
        +private:
        +   StringHash attribHash;
        +public:
        +   VirtualServer ( char * domain, char * server, unsigned int port, double rate )
        +      : cdevServer(domain, server, port, rate), attribHash()
        +      {
        +      populateTable();
        +      }
        +   virtual   ~VirtualServer   ( void );
        +   virtual void   processMessages   ( void );   
        +   void   populateTable   ( void );
        +   virtual int   fireCallback   ( cdevMessage * message );
        +};
        + 
        +
        +	
        + + + +
        + + + VirtualServer.cc +

        +
        + + This source file implements the classes that are defined in the VirtualServer.h header file. The methods that are contained in + this file define the functionality for the VirtualServer that is different from what is provided by default by the cdevServer class. +

        +
        + + + +

        +
        
        +#include <VirtualServer.h>
        +#include <VirtualAttrib.h>
        + 
        +VirtualServer::~VirtualServer ( void )
        +	
        + + + +
        + + + + This is the destructor for the VirtualServer object. It is responsible for + walking through the list of VirtualAttrib objects that were created and + deleting each of them from the list prior to terminating. +

        +
        +
        + + { + StringHashIterator iter(&attribHash); + VirtualAttrib * attrib = NULL; + char * key = NULL; + + iter.first(); + while((key=iter.key())!=NULL) + { + attrib = (VirtualAttrib *)iter.data(); + iter++; + attribHash.remove(key); + if(attrib!=NULL) delete attrib; + } + } + + +void VirtualServer::populateTable ( void ) +
        + + + +
        + + + + The populateTable method is used to generate a collection of device + names and their associated attributes that will be used to create a hash + table of VirtualAttrib objects. The device names are "device0" through + "device9", and each device has attributes "attrib0" through "attrib9". +

        + The client may use the "get", "set", "monitorOn" or "monitorOff" methods + to manipulate the properties associated with any of these VirtualAttrib + objects. +

        +
        +
        + + { + char device[10]; + char attrib[10]; + char key[20]; + { + { + sprintf(device, "device%i", i); + sprintf(attrib, "attrib%i", j); + sprintf(key, "device%i attrib%i", i, j); + attribHash.insert(key, new VirtualAttrib(device, attrib)); + } + } + } + +void VirtualServer::processMessages ( void ) +
        + + + +
        + + + + The processMessages method will be called whenever data is waiting to + be processed in the inbound queue. When called, this method should + process all of the messages that it has available and then return 0. +

        + To process a cdevMessage the method must dequeue it, process it, + enqueue the result and then delete the original cdevMessage object. +

        +
        +
        + + { + char key[255]; + int saveMessageFlag; + int sendMessageFlag; + cdevMessage * message; + VirtualAttrib * attrib; + cdevData output; + + while(dequeue(message)==0) + { + // ************************************************************* + // * Note at this point a cdevTagMap has already been received + // * from the client. This tag map will have initialized all + // * of the tags that are required by the service. + // ************************************************************* + if(!strcmp(message->getMessage(), "unregister")) + { + sendMessageFlag = 0; + removeClientMonitors(message->getClientID()); + } + if(!strncmp(message->getMessage(), "get ", 4)) + { + output.remove(); + saveMessageFlag = 0; + sendMessageFlag = 1; + + sprintf(key, "%s %s", + message->getDeviceList()[0], + &message->getMessage()[4]); + + if((attrib = (VirtualAttrib *)attribHash.find(key))!=NULL) + { + attrib->getToData(&output, message->getContext()); + output.insert("resultCode", CDEV_SUCCESS); +
        + + + +
        + + + + The resultCode property is set to CDEV_SUCCESS + to indicate that the call completed successfully. +

        +
        +
        + + } + else output.insert("resultCode", CDEV_NOTFOUND); + } + else if(!strncmp(message->getMessage(), "set ", 4)) + { + output.remove(); + saveMessageFlag = 0; + sendMessageFlag = 1; + + sprintf(key, "%s %s", + message->getDeviceList()[0], + &message->getMessage()[4]); + + + if((attrib = (VirtualAttrib *)attribHash.find(key))!=NULL) + { + output.insert("resultCode", + attrib->setFromData(message->getData())); + } + else output.insert("resultCode", CDEV_NOTFOUND); + } + else if(!strncmp(message->getMessage(), "monitorOn ", 10)) + { + saveMessageFlag = 1; + sendMessageFlag = 0; + + sprintf(key, "%s %s", + message->getDeviceList()[0], + &message->getMessage()[10]); + + if((attrib = (VirtualAttrib *)attribHash.find(key))!=NULL) + { + attrib->insertMonitor(this, message); + } + } + else if(!strncmp(message->getMessage(), "monitorOff ", 11)) + { + saveMessageFlag = 0; + sendMessageFlag = 1; + + sprintf(key, "%s %s", + message->getDeviceList()[0], + &message->getMessage()[11]); + + if((attrib = (VirtualAttrib *)attribHash.find(key))!=NULL) + { + attrib->removeMonitor(this, message); + } + } + else + { + saveMessageFlag = 0; + sendMessageFlag = 1; + output.insert("resultCode", CDEV_NOTFOUND); + } + + if(sendMessageFlag) +
        + + + +
        + + + + The sendMessageFlag indicates whether a return message should be provided to the + caller. If the message was a monitorOn request, then the return message has already + been automatically dispatched by the cdevMonitorTable object. +

        +
        +
        + + { + message->setData(&output, 1); + enqueue(message); + } + if(!saveMessageFlag) delete message; +
        + + + +
        + + + + If the cdevMessage object was not provided to the cdevMonitorTable to install a monitor, + then it should be deleted. +

        +
        +
        + + } + } + + +int VirtualServer::fireCallback ( cdevMessage * message ) +
        + + + +
        + + + + This method is called by the cdevMonitorTable portion of the class + whenever a monitored value has changed. It is only required to enqueue + the cdevMessage object so that it can be returned to the client with the + new value. +

        +
        +
        + + { + int result = CDEV_SUCCESS; + cdevData * data = NULL; + + if(message && (data = message->getData())!=NULL) + { + data->insert("resultCode", CDEV_SUCCESS); + result = enqueue(message); + } + return result; + } + +void main() +
        + + + +
        + + + + The main function creates an instance of the VirtualServer class named + "TestServerX", which will have the Name Server domain "VIRTUAL" and + will listen for incoming requests on port 9120. The processMessages + method will be called automatically at least every 60 seconds. +

        +
        +
        + +{ +VirtualServer server("VIRTUAL", "TestServerX", 9120, 60); +cdevServer::runServer(); +} + + + +
        + + + +
        + + + VirtualService.h +

        +
        + + The VirtualService.h header file describes the structure of the VirtualService that will be loaded by the cdevSystem in order + to accomodate requests made to the VirtualServer. +

        +
        + + + +

        +
        
        +#include <cdevClientService.h>
        + 
        +// *****************************************************************************
        +// * newVirtualService :
        +// *   This function will be called by the cdevSystem object to create an 
        +// *   initial instance of the VirtualService.
        +// *****************************************************************************
        +extern "C" cdevService * newVirtualService ( char * name, cdevSystem * system );
        +	
        + + + +
        + + + + The newVirtualService function will + create the initial instance of the + VirtualService class. +

        +
        +
        + + +// ***************************************************************************** +// * class VirtualService : +// * This class simply inherits from the cdevClientService and must define +// * only a constructor and destructor. +// ***************************************************************************** +class VirtualService : public cdevClientService +
        + + + +
        + + + + The VirtualService class inherits + almost all of its functionality from the + cdevClientService class. +

        +
        +
        + +{ +public: + VirtualService ( char * name, cdevSystem & system = +cdevSystem::defaultSystem()); + +protected: + int RESULT_CODE_TAG; + + virtual ~VirtualService ( void ) {}; + virtual void fireCallback ( int status, cdevTranObj &xobj, cdevData *resultData ); +
        + + + +
        + + + + The fireCallback method has been + overloaded in order to allow the + service to copy the resultCode + property from the returned + cdevData object into the + completion status for the + cdevCallback function. +

        +
        +
        + +}; + + + + + + + +
        + +
        + + + +
        + + + VirtualService.cc +

        +
        + + This source file implements the classes that are defined in the VirtualService.h header file. The methods that are contained + in this file define the functionality for the VirtualService that is different from what is provided by default by the + cdevClientService class. +

        +
        + + + +

        +
        
        +#include <VirtualService.h>
        + 
        +// *****************************************************************************
        +// * newVirtualService:
        +// *   This function will be called by the cdevSystem object to create an 
        +// *   initial instance of the VirtualService.
        +// *****************************************************************************
        +extern "C" cdevService * newVirtualService (char * name, cdevSystem * system)
        +	
        + + + +
        + + + + The newVirtualService is called by the + cdevSystem to create an instance of + the VirtualService object. +

        +
        +
        + + { + return new VirtualService(name, *system); + } + +// ***************************************************************************** +// * VirtualService::VirtualService : +// * This is teh constructor for the VirtualService. It initializes the +// * underlying cdevClientService by specifying that it is in the domain of +// * VIRTUAL. +// ***************************************************************************** +VirtualService::VirtualService ( char * name, cdevSystem & system) +
        + + + +
        + + + + The constructor for the class will + initialize the underlying + cdevClientService object with the + name of the Name Server domain and + the service name and cdevSystem + parameters. +

        + Additionally the constructor must + declare any tags that it will be using for + communications. +

        +
        +
        + + : cdevClientService("VIRTUAL", name, system) + { + // ********************************************************************* + // * Install the RESULT_CODE_TAG at a location of 30 or higher if it + // * does not already exist. + // ********************************************************************* + RESULT_CODE_TAG = 0; + cdevData::tagC2I("resultCode", &RESULT_CODE_TAG); + + { + cdevData::insertTag(i, "resultCode"); + cdevData::tagC2I("resultCode", &RESULT_CODE_TAG); + } + + system.reportError(CDEV_SEVERITY_INFO, "VirtualService", NULL, +
        + + + +
        + + + + Once initialized the VirtualService will + declare its presence using the + reportError mechanism. +

        +
        +
        + + "Constructing a new VirtualService"); + + } + +// ***************************************************************************** +// * VirtualService::fireCallback : +// * This is the method that will be called to dispatch the callback methods +// * that are associated with the calls to the Virtual Server. If the +// * message has been processed successfully, then the method will remove +// * the resultCode from the outbound data and use that as the status. +// ***************************************************************************** +void VirtualService::fireCallback ( int status, cdevTranObj &xobj, cdevData *resultData ) + { + // ********************************************************************* + // * If the message was transmitted successfully, get the result code + // * from the data that was returned and use that as the status. + // ********************************************************************* + if(status==CDEV_SUCCESS && resultData!=NULL) +
        + + + +
        + + + + Before calling the user defined + callback, this method will copy the + resultCode property of the returned + cdevData object into the status integer + that is provided to the callback + function. +

        +
        +
        + + { + resultData->get(RESULT_CODE_TAG, &status); + resultData->remove(RESULT_CODE_TAG); + } + + cdevClientService::fireCallback(status, xobj, resultData); + } + + +
        + + + +
        + + + Virtual.ddl +

        +
        + + This is the device definition file that is used to map the CDEV requests to the VirtualService for transmission to the + VirtualServer. +

        +
        + + + +

        +
        
        +service Virtual 
        +   {
        +   tags {server}
        +   }
        + 
        +class Virtuals 
        +   {
        +       verbs {get, set, monitorOn, monitorOff}
        +   attributes 
        +      {
        +      default      Virtual;
        +      servers      Virtual;
        +      attrib0      Virtual {server=TestServerX};
        +      attrib1      Virtual {server=TestServerX};
        +      attrib2      Virtual {server=TestServerX};
        +      attrib3      Virtual {server=TestServerX};
        +      attrib4      Virtual {server=TestServerX};
        +      attrib5      Virtual {server=TestServerX};
        +      attrib6      Virtual {server=TestServerX};
        +      attrib7      Virtual {server=TestServerX};
        +      attrib8      Virtual {server=TestServerX};
        +      attrib9      Virtual {server=TestServerX};
        +      }
        +   messages 
        +      {
        +      disconnect   Virtual;
        +      }
        +   }
        + 
        + 
        +Virtuals :
        +   device0, device1, device2, device3, device4, 
        +   device5, device6, device7, device8, device9;
        +
        +
        +	
        +
        + diff --git a/extensions/cdevGenericServer/doc/html/cdevProtocol-fig1.gif b/extensions/cdevGenericServer/doc/html/cdevProtocol-fig1.gif new file mode 100755 index 0000000..78ce71a Binary files /dev/null and b/extensions/cdevGenericServer/doc/html/cdevProtocol-fig1.gif differ diff --git a/extensions/cdevGenericServer/doc/html/cdevProtocol-fig2.gif b/extensions/cdevGenericServer/doc/html/cdevProtocol-fig2.gif new file mode 100755 index 0000000..5481dcb Binary files /dev/null and b/extensions/cdevGenericServer/doc/html/cdevProtocol-fig2.gif differ diff --git a/extensions/cdevGenericServer/doc/html/cdevProtocol-fig3.gif b/extensions/cdevGenericServer/doc/html/cdevProtocol-fig3.gif new file mode 100755 index 0000000..68cd588 Binary files /dev/null and b/extensions/cdevGenericServer/doc/html/cdevProtocol-fig3.gif differ diff --git a/extensions/cdevGenericServer/doc/html/cdevProtocol-fig4.gif b/extensions/cdevGenericServer/doc/html/cdevProtocol-fig4.gif new file mode 100755 index 0000000..5e1dea1 Binary files /dev/null and b/extensions/cdevGenericServer/doc/html/cdevProtocol-fig4.gif differ diff --git a/extensions/cdevGenericServer/doc/html/cdevProtocol-fig5.gif b/extensions/cdevGenericServer/doc/html/cdevProtocol-fig5.gif new file mode 100755 index 0000000..75fb41f Binary files /dev/null and b/extensions/cdevGenericServer/doc/html/cdevProtocol-fig5.gif differ diff --git a/extensions/cdevGenericServer/doc/html/cdevProtocol-fig6.gif b/extensions/cdevGenericServer/doc/html/cdevProtocol-fig6.gif new file mode 100755 index 0000000..51e6da5 Binary files /dev/null and b/extensions/cdevGenericServer/doc/html/cdevProtocol-fig6.gif differ diff --git a/extensions/cdevGenericServer/doc/html/cdevProtocol.html b/extensions/cdevGenericServer/doc/html/cdevProtocol.html new file mode 100755 index 0000000..94e0112 --- /dev/null +++ b/extensions/cdevGenericServer/doc/html/cdevProtocol.html @@ -0,0 +1,1156 @@ + + + +The CDEV Linear Internet Protocol Definition + + + + + + +
        +



        +

        + The CDEV Linear Internet Protocol Definition +

        +

        + Structure and Syntax of CDEV Client/Server Network Transmissions +

        +


        + +

        + Prepared for +
        + South Eastern Universities Research Association /
        + Thomas Jefferson National Accelerator Facility +

        + by +

        + Walt Akers, Chip Watson, and Jie Chen +

        + September 19, 1996 +

        + +




        +


        + + + + + + + + + + + +
        + DOCUMENT DATE: + + September 19, 1996 +




        +
        + TRADEMARKS: + + UNIX is a registered trademark of AT&T in the USA and other countries.
        + VxWorks is a register trademark of Wind River Systems.
        + The X Window System is a trademark of Massachusetts Institute of Technology.
        + OSF/Motif and Motif are trademarks of Open Software Foundation, Inc.
        + Ultrix and DEC are registered trademarks of Digital Equipment Corporation.
        + HPUX is a registered trademark of Hewlett Packard.
        +



        +
        + SURA/TJNAF: + + The Southeastern Universities Research Association (SURA) operates the + Thomas Jefferson National Accelerator Facility (CEBAF) for the United States + Department of Energy under contract DE-AC05-84ER40150. +




        +
        + DISCLAIMER: + + This report was prepared as an account of work sponsored by the + United States government. Neither the United States nor the + United States Department of Energy, nor any of their employees, + makes any warranty, express or implied, or assumes any legal + liability or responsibility for the accuracy, completeness, or + usefulness of any information, apparatus, product or process + disclosed, or represents that its use would not infringe + privately owned rights. Reference herein to any specific + commercial product, process, or service by trade name, mark, + manufacturer, or otherwise, does not necessarily constitute or + imply its endorsement, recommendation, or favoring by the + United States government or any agency thereof. The view and + opinions of the authors expressed herein do not necessarily + state or reflect those of the United States government or any + agency thereof. +
        + +




        +

        ii

        +


        + + +

        + CONTENTS +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + List of Illustrations + + ....................................... + + iv +
        + 1. Overview of the CDEV Protocol + + ....................................... + + 1 +
        + 2. The CDEV Multi-Packet Architecture + + ....................................... + + 2 +
        + 3. Binary Structure of the CDEV Packet (Version 1) + + ....................................... + + 3 +
        + 4. The cdevPacket Class + + ....................................... + + 4 +
        + 5. The cdevPacket1 Class + + ....................................... + + 5 +
        + 4. The cdevMessage Class + + ....................................... + + 6 +
        + +




        +

        iii

        +


        + + +

        + + LIST OF ILLUSTRATIONS +

        +
        + + + + + + + + + + + + + + + + + + + + + + + + + +
        + Figure 1: Structure of a Multi-Packet Transmission + + ....................................... + + 2 +
        + Figure 2: Structure of the CDEV Packet Binary Stream (Version 1) + + ....................................... + + 3 +
        + Figure 3: The CDEV Packet Map + + ....................................... + + 3 +
        + Figure 4: Object Model of the cdevPacket Class + + ....................................... + + 4 +
        + Figure 5: Object Model of the cdevPacket1 Class + + ....................................... + + 5 +
        + Figure 6: Object Model of the cdevMessage Class + + ....................................... + + 6 +
        +




        +

        iv

        +


        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + 1. + + Overview of the CDEV Linear Internet Protocol +
        + Purpose of This Document + + This document is designed to provide a clear description of the communications protocol that should be used to pass information between CDEV compliant applications. Adherence to the structure and syntax that is specified by this document will improve the likelihood that the CDEV service/server developer's application will be compatible with other similar applications using CDEV.

        + This protocol was designed to be as lightweight as possible and still maintain the flexibility to allow CDEV service/server developers to use it without modification. In addition to describing the physical structure of the data packets, this document will also discuss the C++ classes that are provided to allow the developer to rapidly generate packets for transmission and decompose them upon receipt.

        +
        + Intended Audience + + This document is intended for anyone who will be developing a CDEV server or will be developing CDEV applications that will communicate with one another over a network. This document will also be useful for software developers who wish to develop a non-CDEV application that can communicate with an existing server that uses this protocol.

        +
        + Layout of Document + + This document will begin by discussing the multi-packet architecture that was used to design the data flow for this protocol. The internal structure of the binary stream will be described.

        + The document will then describe the structure of the individual cdevPacket binary streams that comprise the multi-packet stream. This section will describe the internal structure of the binary stream, as well as the classes that are used to manipulate the component data items and generate and decompose the binary stream.

        + Next the individual components of the cdevPacket binary stream will be dissected and analyzed. This will include the format of the cdevData binary stream and the intended usage of each element within the cdevPacket binary stream.

        +
        +



        +

        1

        +


        +
        + + 2. + + The Multi-Packet Architecture +
        + Multi-Packet Architecture Overview + + When transmitting data using TCP/IP, performance may normally be improved substantially by placing outbound data into a single buffer and then transmitting many packets simultaneously using a single write call. The CDEV Linear Internet Protocol is designed to support this concept. By buffering small binary packets into a single, larger buffer we are able to substantially improve performance for high-volume, asynchronous transmissions.

        + To encode individual binary packets using this design required the addition of two 32 bit integers at the beginning of the data stream; the length and the packet count. While this method adds an additional 8 bytes to each synchronous transmission of single CDEV packets, this was considered inconsequential because even with the added size the average CDEV packet would still need to be padded to fulfill the minimum TCP/IP packet size.

        +
        + Multi-Packet Data Structure + + + Figure 1: Structure of a Multi-Packet Transmission
        +
        +

        + The following components are contained within a CDEV multi-packet transmission.

        + + + + + + + + + + + + +
        + Overall Length: + + This field is a 32 bit integer that identifies the amount of binary data that will be transmitted following the overall length integer.

        +
        + Packet Count: + + This field is a 32 bit integer that identifies the number of data packets that will comprise the transmission. While this data item is not required to decode the packet, it is provided to allow verification that the packet was received intact.

        +
        + Packet Length: + + This field is a 32 bit integer that identifies the size of the binary packet data following the packet length. It is important to note that this variable represents the length of the data that follows, however, because the next packet length must begin on a four byte boundary the binary data may be followed by up to three bytes of padding.

        +
        + Binary Data: + + This field is a variable length binary stream that contains a binary encoded cdevPacket object.

        +
        +
        +



        +

        2

        +


        +
        + + 3. + + Binary Structure of the CDEV Packet (Version 1) +
        + CDEV Packet Overview + + The CDEV packet is a binary stream that contains all of the data items that are required to submit a request or receive a reply from a CDEV server. All of the data elements within the CDEV packet are encoded for network transport using SUN's External Data Representation (XDR) and are aligned on four byte boundaries. The following diagram shows the structure of the CDEV packet binary stream.

        + + Figure 2: Structure of the CDEV Packet Binary Stream (Version 1) + +

        +
        + CDEV Packet Map + + + + +
        + The CDEV packet map is the only component of the binary stream that is required by the protocol. This 32 bit integer is implemented as two 16 bit integers. The first 16 bits contains the version number of the packet (this will be true regardless of the packet version that is being transferred.) In version1, the next 16 bits contains a bit mask that identifies which optional elements of the packet will be included in this transmission. The following diagram shows the structure of the CDEV packet map. This 32 bit integer is encoded using XDR prior to placing it in the stream.

        + The meaning of the individual components of the CDEV packet map is described below.

        +
        + + Figure 3: CDEV Packet Map
        +
        +

        +
        +
        + Components of the CDEV Packet Map + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + Version + + This short integer identifies the version number of the packet. Because the rest of the CDEV packet map is version specific, the first 16 bits of all CDEV packets will identify the version of the packet.

        +
        + Client ID Flag + + This is a boolean bit that is used to specify the presence (1) or absence (0) of the client identifier in the packet. The definition and intended usage of the client identifier is explained later. +
        + Trans Index Flag + + This is a boolean bit that is used to specify the presence (1) or absence (0) of the transaction index in the packet. The definition and intended usage of the transaction index is explained later.

        +
        + Cancel Trans Index Flag + + This is a boolean bit that is used to specify the presence (1) or absence (0) of the cancel transaction index in the packet. The definition and intended usage of the cancel transaction index is explained later. +
        + Local Data Index Flag + + This is a boolean bit that is used to specify the presence (1) or absence (0) of the local data index in the packet. The definition and intended usage of the local data index is explained later.

        +
        + Foreign Data Index Flag + + This is a boolean bit that is used to specify the presence (1) or absence (0) of the foreign data index in the packet. The definition and intended usage of the foreign data index is explained later.

        +
        + Operation Code Flag + + This is a boolean bit that is used to specify the presence (1) or absence (0) of the operation code in the packet. The definition and intended usage of the operation code is explained later.

        +
        + Device List Flag + + This is a boolean bit that is used to specify the presence (1) or absence (0) of the device count and the corresponding device list in the packet. The definition and intended usage of the device list is explained later.

        +
        + Message Flag + + This is a boolean bit that is used to specify the presence (1) or absence (0) of the message string in the packet. The definition and intended usage of the message string is explained later.

        +
        + Data Flag + + This is a boolean bit that is used to specify the presence (1) or absence (0) of the request data in the packet. The definition and intended usage of the request data is explained later.

        +
        + Context Flag + + This is a boolean bit that is used to specify the presence (1) or absence (0) of the context data in the packet. The definition and intended usage of the context data is explained later.

        +
        + Tag Map Flag + + This is a boolean bit that is used to specify the presence (1) or absence (0) of the tag map data in the packet. The definition and intended usage of the tag map data is explained later.

        +
        +
        + Client Identifier + + The client identifier is a short integer that is used by the client to identify different program elements that may be communicating with the server using a single socket. While the value is passed using four bytes in order to preserve data alignment, the value should be a short integer. The value of the client identifier is selected by the client and should be included with each message that is sent to a CDEV server. The server will always include the client identifier in its reply packets.

        + When the server receives the client identifier, it will merge it with the socket identifier in order to generate an identification number that will be unique within the server. In the design that is currently being implemented the 16 bit socket handle is placed in the high order word of an unsigned long integer and the 16 bit client identifier is placed in the low order word.

        + This 32 bit integer is encoded using XDR before placing it in the stream.

        +
        + Transaction Index + + The transaction index is a 32 bit integer that is an index into a table of transaction objects that is stored on the client side. A transaction object is used to maintain information about a specific request that was submitted to a server. The information that is stored includes the device name, the message, the callback function to be executed upon reply and a void pointer to be sent as a parameter to the callback. The server should always return this value as part of its reply.

        + It should be noted that the transaction index is not merely a pointer to an object in memory on the client side. It is an index that has an embedded checksum that allows the client to verify that the specified transaction object has not been deleted. This functionality is described in detail in the documentation for the CDEV Generic Server Engine.

        + This 32 bit integer is encoded using XDR before placing it in the stream.

        +
        + Cancel Transaction Index + + This is a transaction index that the client now wishes to cancel. This technique is typically used to cancel a monitor that was previously installed on a specific server attribute. The cancel transaction index should be a transaction index that was submitted as part of a prior request.

        + This 32 bit integer is encoded using XDR before placing it in the stream.

        +
        + Local Data Index and Foreign Data Index + + These elements are a pair of developer usable 32 bit indexes. The original design consideration that led to the introduction of these indexes was to allow the client to define a memory structure in his local memory (such as a list of device names) and assign an integer identifier to the structure. The client would then pass the list to the server once and, at that time the server would create a similar structure and assign its own integer identifier to it. The client could then refer to the large data structure using one or both of the 32 bit integer identifiers.

        + This functionality is only implemented in the CDEV Generic Server Engine in so much as, the server will swap the local data index and the foreign data index when it receives a packet and will swap them back when it sends a reply. The client will always receive the packet with the data in the correct order.

        + These 32 bit integers are encoded using XDR before placing them in the stream.

        +
        + Operation Code + + The operation code is a 32 bit integer that was added to the protocol in order to provide a server that supports very few message types with a mechanism to pre-parse the message at the client and then simply send an integer code. This implementation is not currently used in the CDEV Generic Server Engine.

        + This 32 bit integer is encoded using XDR before placing it in the stream.

        +
        + Device Count + + The device count is a 32 bit integer that identifies the number of character strings that are included in the device list.

        + This 32 bit integer is encoded using XDR before placing it in the stream.

        +
        + Device List + + This is the list of device names to which the message will be sent. The server is responsible for descending this list and submitting the message and any associated data and context to each of them.

        + Each string is placed in the binary stream using xdr_string function of SUN's External Data Representation. For each string XDR will write the length of the string as a four byte integer followed by the string itself. If the string length is not evenly divisible by four, then XDR will insert pad characters at the end of the string to force it to end on a four byte boundary.

        +
        + Message + + The message string is the command that is to be sent to each device in the device list. In this version of the CDEV packet this is a single string, however, in future versions this may be expanded to be a list of message strings.

        + This string is inserted into the binary stream using the xdr_string function. XDR will write the length of the string as a four byte integer, followed by the string itself. If the length of the string is not evenly divisible by four, then XDR will insert pad characters at the end of the string to force it to end on a four byte boundary.

        +
        + Request/Reply Data + + The request data element is a binary stream that represents the contents of a cdevData object. When a message is transmitted from a CDEV client to a CDEV server this element contains the contents of the outbound cdevData object that the caller provided as a parameter to the send call. When a reply is returned from the server this element contains the resultant data from the call.

        + The binary representation of the cdevData object is placed in the stream in two parts; the first is a four byte integer that specifies the length of the binary stream and the second part is the binary stream itself.

        + This length and binary representation of any cdevData object can be obtained by using the xdrExport method of the cdevData class. The xdrImport method is used to read this binary stream back into a cdevData object.

        +
        + Request Context + + The context data element is a binary stream that represents the contents of a cdevData object that contains the context of the device/message combination at the time the message was transmitted. The CDEV Generic Server Engine is designed to only resubmit the context element when it is differs from the previous context that was transmitted through the socket. The server is responsible for using the most recent context cdevData object until a new one is received. The context associated with each transaction is currently not returned to the client when a reply is sent from the server.

        + Refer to the Request Data section for a description of how cdevData objects are stored and retrieved from a binary stream.

        +
        + Tag Map + + The tag map data element is a binary stream that represents the contents of a cdevData object. This object is populated with current tag table integers and tag table strings that are in use in the client process. This data is used to construct a tag conversion table on the server that can be used to convert between client tags and server tags (and vice-versa).

        + Because tag names cannot be used to specify where data is inserted in this object, tag number 1 is used to store an array of integer tag numbers that are in use on the client. Tag number 2 will contain an array of corresponding tag strings.

        + The client should only submit this table to the server when it initially creates the connection, or when new tags are added to the client's global tag table.

        + Refer to the Request Data section for a description of how cdevData objects are stored and retrieved from a binary stream.

        +
        +



        +

        3

        +


        +
        + + 4. + + The cdevPacket Class +
        + cdevPacket Class Overview + + The cdevPacket class is the base class from which all other versioned cdevPacket classes will be inherited. It defines the functionality that should be inherent in all versions of a cdevPacket object.

        + The cdevPacket class has the following structure.

        + + Figure 4: Object Model of the cdevPacket Class
        +
        +

        +
        + Attributes of the cdevPacket Class + + + + + + + +
        + binary + + This is a pointer to a character string buffer that will be used to store the address of the binary output stream. This stream is typically allocated by the class, however, an existing buffer may be attached using the attachData method. If the character string pointer has not been cleared using the detachData method, then the buffer will be deleted when the object is destroyed.

        +
        + binaryLen + + This is the length of the binary data that is stored in the character string pointed to by the binary attribute.

        +
        +
        + Methods of the cdevPacket Class + + + + + + + + + + + + + + + + + + + + + + + + + +
        + cdevPacket + + cdevPacket (void);

        + This is the default constructor for the class. In the absence of parameters, this constructor will initialize the binary attribute to NULL and the binaryLen attribute to 0.

        +
        + cdevPacket + + cdevPacket (cdevPacket & packet);

        + This is the copy constructor for the class. This method will call the virtual streamIn method to copy the binary and binaryLen attributes of the user specified packet into this object. +
        + ~cdevPacket + + ~cdevPacket (void);

        + This is the destructor for the class. If the binary attribute has not been set to NULL using the detachData method, this destructor will delete the binary buffer.

        +
        + getVersion + + int getVersion (short & version);

        + This method will read a short integer from the first 16 bits of the binary stream. The method will return 0 if the version was successfully read, otherwise -1 is returned.

        +
        + streamOut + + int streamOut (char ** stream, size_t * len);

        + This method is used to obtain a copy of the binary and binaryLen parameters. A pointer to the binary parameter will be placed in the stream pointer, and the binaryLen value will be placed in len. This method returns 0 to indicate success.

        +
        + streamIn + + int streamIn (char * stream, size_t len);

        + This method is used to copy a new stream into the object. If the binary attribute is not NULL, then it will be deleted before a new buffer is allocated. This method returns 0 to indicate success.

        +
        + attachData + + int attachData (char * stream, size_t len);

        + This method is used to assign a preallocated pointer to the internal binary attribute. If the binary attribute is not NULL, then it will be deleted before the new pointer is assigned. This method returns 0 on success.

        +
        + detachData + + void detachData (void);

        + This method sets the binary attribute to NULL and the binaryLen attribute to 0. This prevents the buffer from being deleted when the object is destroyed or a new buffer is attached to the object. Before using this method the user should call the streamOut method to obtain a copy of the binary address and the binary length.

        +
        +
        +



        +

        4

        +


        +
        + + 5. + + The cdevPacket1 Class +
        + cdevPacket1 Class Overview + + The cdevPacket1 class supports the data elements and structure for version 1 of the CDEV Linear Internet Protocol definition. This class provides the functionality to generate and read a binary packet that is CDEV compliant.

        + The cdevPacket1 class has the following structure.

        + + Figure 5: Object Model of the cdevPacket1 Class
        +
        +

        +
        + Methods of the cdevPacket1 Class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + cdevPacket1 + + cdevPacket1 (cdevPacket1 & packet);

        + This is the copy constructor for the class. This method will call the virtual streamIn method to copy the binary and binaryLen attributes of the user specified packet into this object.

        +
        + cdevPacket1 + + cdevPacket1 (
        + short clientID = -1,
        + unsigned transIndex = 0,
        + unsigned cancelTransIndex = 0,
        + unsigned localDataIndex = 0,
        + unsigned foreignDataIndex = 0,
        + unsigned operationCode = 0,
        + unsigned deviceCount = 0,
        + char ** deviceList = NULL,
        + char * message = NULL,
        + cdevData * data = NULL,
        + cdevData * context = NULL,
        + cdevData * tagMap = NULL);

        + This constructor will call the set method to initialize the object with the individual data items.

        +
        + ~cdevPacket1 + + ~cdevPacket1 (void);

        + This is the destructor for the class. If the binary attribute has not been set to NULL using the detachData method, this destructor will delete the binary buffer.

        +
        + asciiDump + + void asciiDump (FILE * fp = stdout);

        + This method is used to generate a diagnostic dump of the contents of the binary. The method will convert each of the data items to its ASCII text representation and then will print a report of the contents to the specified file pointer.

        +
        + streamIn + + int streamIn (char * stream, size_t len);

        + This method is used to copy a new stream into the object. If the binary attribute is not NULL, then it will be deleted before a new buffer is allocated. This method returns 0 to indicate success.

        +
        + attachData + + int attachData (char * stream, size_t len);

        + This method is used to assign a preallocated pointer to the internal binary attribute. If the binary attribute is not NULL, then it will be deleted before the new pointer is assigned. This method returns 0 on success.

        +
        + +
        + getVersion + + virtual int getVersion (short & version)

        + This method reads the version from the binary stream and places the value in the user specified parameter. This method returns 0 on success or -1 if the stream is empty or the version is not contained in the stream.

        +
        + getClientID + + int getClientID (short & clientID)

        + This method reads the clientID from the binary stream and places the value in the user specified parameter. This method returns 0 on success or -1 if the stream is empty or the clientID is not contained in the stream.

        +
        + getTransIndex + + int getTransIndex (unsigned & transIndex)

        + This method reads the transaction index from the binary stream and places the value in the user specified parameter. This method returns 0 on success or -1 if the stream is empty or the transaction index is not contained in the stream.

        +
        + getCancelTransIndex + + int getCancelTransIndex (unsigned & cancelTransIndex)

        + This method reads the cancel transaction index from the binary stream and places the value in the user specified parameter. This method returns 0 on success or -1 if the stream is empty or the cancel transaction index is not contained in the stream.

        +
        + getLocalDataIndex + + int getLocalDataIndex (unsigned & localDataIndex)

        + This method reads the local data index from the binary stream and places the value in the user specified parameter. This method returns 0 on success or -1 if the stream is empty or the local data index is not contained in the stream.

        +
        + getForeignDataIndex + + int getForeignDataIndex (unsigned & foreignDataIndex)

        + This method reads the foreign data index from the binary stream and places the value in the user specified parameter. This method returns 0 on success or -1 if the stream is empty or the foreign data index is not contained in the stream.

        +
        + getOperationCode + + int getOperationCode (unsigned & operationCode)

        + This method reads the operation code from the binary stream and places the value in the user specified parameter. This method returns 0 on success or -1 if the stream is empty or the operation code is not contained in the stream.

        +
        + getDeviceList + + int getDeviceList (char ** & deviceList, unsigned & deviceCount)

        + This method reads the device count and device list from the binary stream and places the values in the user specified parameter. This method returns 0 on success or -1 if the stream is empty or these items are not contained in the stream.

        +
        + getMessage + + int getMessage (char * & message)

        + This method reads the message string from the binary stream and places the value in the user specified parameter. This method returns 0 on success or -1 if the stream is empty or the message string is not contained in the stream.

        +
        + getData + + int getData (cdevData & data)

        + This method reads the request/reply data from the binary stream and places the value in the user specified parameter. This method returns 0 on success or -1 if the stream is empty or the data object is not contained in the stream.

        +
        + getContext + + int getContext (cdevData & context)

        + This method reads the context data from the binary stream and places the value in the user specified parameter. This method returns 0 on success or -1 if the stream is empty or the context data is not contained in the stream.

        +
        + getTagMap + + int getTagMap (cdevData & tagMap)

        + This method reads the tag map from the binary stream and places the value in the user specified parameter. This method returns 0 on success or -1 if the stream is empty or the tag map is not contained in the stream.

        +
        + get + + int get (
        + short & clientID,
        + unsigned & transIndex,
        + unsigned & cancelTransIndex,
        + unsigned & localDataIndex,
        + unsigned & foreignDataIndex,
        + unsigned & operationCode,
        + unsigned & deviceCount,
        + char ** & deviceList,
        + char * & message,
        + cdevData & data,
        + cdevData & context,
        + cdevData & tagMap);

        + This method will read the entire contents of the binary stream into the user specified parameters. If a data item is not included in the stream, then its associated parameter will be set to a default value. This method returns 0 on success or -1 if the stream is empty.

        +
        + set + + void set (
        + short clientID = -1,
        + unsigned transIndex = 0,
        + unsigned cancelTransIndex = 0,
        + unsigned localDataIndex = 0,
        + unsigned foreignDataIndex = 0,
        + unsigned operationCode = 0,
        + unsigned deviceCount = 0,
        + char ** deviceList = NULL,
        + char * message = NULL,
        + cdevData * data = NULL,
        + cdevData * context = NULL,
        + cdevData * tagMap = NULL);

        + This method is used to explicitly set the contents of the binary stream using the user specified parameters. If a binary buffer has already been allocated it will be deleted prior to allocating the new buffer. This new buffer will be sufficiently large to hold all of the data and the method will copy the binary representation of the data elements into the binary stream.

        +
        + has... + + int hasClientID (void);
        + int hasTransIndex (void);
        + int hasCancelTransIndex (void);
        + int hasLocalDataIndex (void);
        + int hasForeignDataIndex (void);
        + int hasOperationCode (void);
        + int hasDeviceList (void);
        + int hasMessage (void);
        + int hasData (void);
        + int hasContext (void);
        + int hasTagMap (void);

        + These methods are used to query the cdevpacket1 object for the presence of each data item. The methods will return a boolean result of (1) if the item exists in the stream, or (0) if the item does not exist or the stream is empty.

        +
        +
        +



        +

        5

        +


        +
        + + 6. + + The cdevMessage Class +
        + cdevMessage Class Overview + + The cdevMessage class is a simple contained class that provides a way of realizing the elements that are compressed within the binary stream used by the cdevPacket1 class. The cdevMessage class has a very lightweight interface and allows the developer to access its internals through the use of public data.

        + The cdevMessage class has the following structure.

        + + Figure 6: Object Model of the cdevMessage Class
        +
        +

        +
        + Attributes of the cdevMessage Class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + saveTbl + + This is a union that is used by the destructor when deleting the object. It contains an entry for each pointer that might be allocated within the class. If the save flag for the associated data is TRUE (non-zero), then that element will not be deleted when the cdevMessage object is destroyed.

        +
        + clientID + + This is the identifier of the client that generated the request or will receive the reply.

        +
        + transIndex + + This is the transaction index that is used on the client side to lookup the transaction object that corresponds to this message.

        +
        + cancelTransIndex + + This is a previously submitted transaction that the client now wishes to cancel.

        +
        + localDataIndex + + This is an index into a block of data in the local process that corresponds to the block of data in the remote process that is specified by the foreignDataIndex entry.

        +
        + foreignDataIndex + + This is an index into a block of data in the remote process that corresponds to the block of data in the local process that is specified by the localDataIndex entry.

        +
        + operationCode + + This is a developer specified operation code.

        +
        + deviceCount + + This is the number of device strings in the deviceList entry.

        +
        + deviceList + + This is a list of device names to which the specified message should be sent.

        +
        + message + + This is the message string or command that should be sent to each of the specified devices in the device list. In the absence of a deviceList, this may be a command that is intrinsic to the server.

        +
        + data + + This is the data that is associated with the request or reply.

        +
        + context + + This is the context that was in effect at the time that the call was made on the client side. The server does not guarantee that this value will be returned with its reply.

        +
        + tagMap + + This is a table of tag integers and tag strings that are in use on the client side of the connection. The array of tag integers is stored in tag 1, and the array of corresponding names is stored in tag 2.

        +
        +
        + Methods of the cdevMessage Class + + + + + + + + + + + + + + + + + + + + + + + + + +
        + cdevMessage + + cdevMessage (char * binary, size_t binaryLen);

        + This constructor uses the binary stream from a cdevPacket object to populate its data items.

        +
        + cdevMessage + + cdevMessage (cdevMessage & Message)

        + This is the copy constructor for the class. It will make a copy of each of the items that is stored in the caller specified Message and use these values to populate its data items.

        +
        + cdevMessage + + cdevMessage (
        + short ClientID = -1,
        + unsigned TransIndex = 0,
        + unsigned CancelTransIndex = 0,
        + unsigned LocalDataIndex = 0,
        + unsigned ForeignDataIndex = 0,
        + unsigned OperationCode = 0,
        + unsigned DeviceCount = 0,
        + char ** DeviceList = NULL,
        + char * Message = NULL,
        + cdevData * Data = NULL,
        + cdevData * Context = NULL,
        + cdevData * TagMap = NULL);

        + This constructor will use the user specified parameters to populate its internal data items. note that new items will be allocated and the user specified items will be duplicated.

        +
        + ~cdevMessage + + ~cdevMessage (void)

        + This is the destructor for the object. When the object is deleted this method will consult the saveTbl and will delete any data item that does not have its corresponding saveTbl entry set to non-zero.

        +
        + clear + + void clear (void)

        + This method consults the saveTbl and then deletes any allocated data item that does not have its corresponding saveTbl entry set to non-zero. The method will then set all of the data items and pointers to their default values.

        +
        + streamIn + + int streamIn (char * stream, size_t len)

        + This method is used to repopulate the cdevMessage object with new data from a cdevPacket1 object. This method will call clear to remove any existing data before loading the data specified in the binary stream. This method will return 0 on success or -1 if an error occurred.

        +
        + streamOut + + int streamOut (char ** stream, size_t * len)

        + This method is used to obtain a copy of a binary stream of the data that is stored in the cdevMessage object. It is the callers responsibility to delete this data buffer when it is no longer needed. This method will return 0 on success or -1 if an error occurred.

        +
        + asciiDump + + void asciiDump (FILE * fp = stdout)

        + This method is used to generate a diagnostic dump of the contents of the cdevMessage object. The method will convert each of the data items to its ASCII text representation and then will print a report of the contents to the specified file pointer.

        +
        +
        +



        +

        6

        +


        +
        + + diff --git a/extensions/cdevGenericServer/example/Makefile b/extensions/cdevGenericServer/example/Makefile new file mode 100755 index 0000000..f5e4971 --- /dev/null +++ b/extensions/cdevGenericServer/example/Makefile @@ -0,0 +1,19 @@ +DIRS = Reflector VirtualService + +all: + @for dir in $(DIRS); \ + do \ + $(MAKE) -C $$dir; \ + done + +clean: + @for dir in $(DIRS); \ + do \ + $(MAKE) -C $$dir clean; \ + done + +purge: + @for dir in $(DIRS); \ + do \ + $(MAKE) -C $$dir purge; \ + done diff --git a/extensions/cdevGenericServer/example/NMakefile.mak b/extensions/cdevGenericServer/example/NMakefile.mak new file mode 100755 index 0000000..c3d7163 --- /dev/null +++ b/extensions/cdevGenericServer/example/NMakefile.mak @@ -0,0 +1,8 @@ +BASEDIR = $(MAKEDIR) +DIRS = $(BASEDIR)\Reflector\ + $(BASEDIR)\VirtualService + +notarget: all + +all clean purge: + @for %d in ($(DIRS)) do @if exist %d cd %d & $(MAKE) /NOLOGO $@ /f NMakefile.mak diff --git a/extensions/cdevGenericServer/example/Reflector/Makefile b/extensions/cdevGenericServer/example/Reflector/Makefile new file mode 100755 index 0000000..76b4fb1 --- /dev/null +++ b/extensions/cdevGenericServer/example/Reflector/Makefile @@ -0,0 +1,32 @@ +ARCH = OS +SHOBJ = YES + +include ../../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Reflector Client/Server Example" +CXXINCLUDES = -I./ +SO_SRCS = ReflectorService.cc +SO_LIBS = -L$(CDEVLIB) -lcdevGenericServer $(OSLIBS) +LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(ACELIBS) $(OSLIBS) + +ifeq ($(SHOBJ), YES) + TARGETS = $(BASELIB)/ReflectorService.so $(BASEBIN)/ReflectorServer +else + TARGETS = $(BASELIB)/libReflectorService.a $(BASEBIN)/ReflectorServer +endif + +targets : $(TARGETS) + +$(BASEBIN)/ReflectorServer : $(OBJDIR)/ReflectorServer.o + $(LINK.cc) $^ $(LIBS) -o $@ + +$(BASELIB)/ReflectorService.so : $(OBJDIR)/ReflectorService.o + $(LINK.so) -o $@ $^ -L$(CDEVLIB) -lcdevGenericServer $(OSLIBS) + @mkdir -p $(CDEVSHOBJ)/$(CDEVVERSION) + @cp $@ $(CDEVSHOBJ)/$(CDEVVERSION)/$(@F) + + +$(BASELIB)/libReflectorService.a : $(OBJDIR)/ReflectorService.o + $(LINK.a) $@ $(OBJDIR)/ReflectorService.o + @$(RANLIB) $@ > /dev/null + diff --git a/extensions/cdevGenericServer/example/Reflector/NMakefile.mak b/extensions/cdevGenericServer/example/Reflector/NMakefile.mak new file mode 100755 index 0000000..f027465 --- /dev/null +++ b/extensions/cdevGenericServer/example/Reflector/NMakefile.mak @@ -0,0 +1,51 @@ +.SUFFIXES: .cc .obj + +APPNAME = Reflector Client/Server Example +ARCH = WINNT-4.0 +SHOBJ = YES + +BINARIES = $(BASEBIN)\ReflectorServer.exe \ + $(CDEVLIB)\ReflectorService.dll \ + $(CDEVLIB)\ReflectorService.lib + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +CXXINCLUDES = /I .\\ +CXXEXTRA_DLL = /D "REFLECTOR_SERVICE_API=__declspec(dllexport)" +CXXEXTRA_LIB = /D "REFLECTOR_SERVICE_API=" + +!IF "$(SHOBJ)" == "YES" +TARGETS = $(BASEBIN)\ReflectorServer.exe \ + $(CDEVLIB)\ReflectorService.dll +!ELSE +TARGETS = $(BASEBIN)\ReflectorServer.exe \ + $(CDEVLIB)\ReflectorService.lib +!ENDIF + +targets : $(TARGETS) + +$(CDEVLIB)\ReflectorService.dll : $(OBJDIR)\ReflectorService.obj + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib\ + $(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $? + -@copy $@ $(CDEVSHOBJ)\$(CDEVVERSION)\$(@F) > nul + @echo ^ ^ ^ ^ ^ ^ Done... + +$(CDEVLIB)\ReflectorService.lib : $(OBJDIR)\ReflectorService.obj + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib\ + $(LINK_LIB_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\ReflectorServer.exe : .exec\$(TARGETDIR)\ReflectorServer.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + + diff --git a/extensions/cdevGenericServer/example/Reflector/Reflector.ddl b/extensions/cdevGenericServer/example/Reflector/Reflector.ddl new file mode 100755 index 0000000..8b4e820 --- /dev/null +++ b/extensions/cdevGenericServer/example/Reflector/Reflector.ddl @@ -0,0 +1,33 @@ +service Reflector + { + tags {server} + } + +class Reflectors + { + verbs {get, set} + attributes + { + default Reflector; + clientID Reflector; + servers Reflector; + connections Reflector; + attrib1 Reflector {server=TestServerX}; + attrib2 Reflector {server=TestServerX}; + attrib3 Reflector {server=TestServerX}; + attrib4 Reflector {server=TestServerX}; + attrib5 Reflector {server=TestServerX}; + attrib6 Reflector {server=TestServerX}; + } + messages + { + shutdown Reflector; + } + } + + +Reflectors : + device1, + device2, + device3 +; diff --git a/extensions/cdevGenericServer/example/Reflector/ReflectorServer.cc b/extensions/cdevGenericServer/example/Reflector/ReflectorServer.cc new file mode 100755 index 0000000..7c30d4b --- /dev/null +++ b/extensions/cdevGenericServer/example/Reflector/ReflectorServer.cc @@ -0,0 +1,45 @@ +#include + + +// ***************************************************************************** +// * class ReflectorServer : +// * This is the server class for the reflector. It simply receives messages +// * from a client and immediately returns them. +// * +// * The constructor passes the domain, server, port and rate to the +// * underlying cdevServer class to be processed. The cdevServer constructor +// * will add this server to the Name Server and will begin processing +// * messages when the cdevServer::runServer() method is executed. +// * +// * The processMessages method is the servers interface to the world... Each +// * time a complete message is received or the time specified in rate +// * expires, that method will be called. +// ***************************************************************************** +class ReflectorServer : public cdevServer +{ +public: + ReflectorServer ( char * domain, char * server, unsigned int port, double pulse ) + : cdevServer(domain, server, port, pulse) + { + } + + virtual void processMessages ( void ) + { + cdevMessage * message; + while(dequeue(message)==0) + { + // message->asciiDump(); + enqueue(message); + delete message; + } + } +}; + + +int main() +{ +ReflectorServer server("REFLECTOR", "TestServerX", 0, 60); +cdevServer::runServer(); + +return 0; +} diff --git a/extensions/cdevGenericServer/example/Reflector/ReflectorService.cc b/extensions/cdevGenericServer/example/Reflector/ReflectorService.cc new file mode 100755 index 0000000..113dd05 --- /dev/null +++ b/extensions/cdevGenericServer/example/Reflector/ReflectorService.cc @@ -0,0 +1,24 @@ +#include + +// ***************************************************************************** +// * newReflectorService: +// * This function will be called by the cdevSystem object to create an +// * initial instance of the ReflectorService. +// ***************************************************************************** +extern "C" cdevService * newReflectorService (char * name, cdevSystem * system) + { + return new ReflectorService(name, *system); + } + +// ***************************************************************************** +// * ReflectorService::ReflectorService : +// * This is teh constructor for the ReflectorService. It initializes the +// * underlying cdevClientService by specifying that it is in the domain of +// * REFLECTOR. +// ***************************************************************************** +ReflectorService::ReflectorService ( char * name, cdevSystem & system) + : cdevClientService("REFLECTOR", name, system) + { + system.reportError(CDEV_SEVERITY_INFO, "ReflectorService", NULL, + "Constructing a new ReflectorService"); + } diff --git a/extensions/cdevGenericServer/example/Reflector/ReflectorService.h b/extensions/cdevGenericServer/example/Reflector/ReflectorService.h new file mode 100755 index 0000000..afabcbd --- /dev/null +++ b/extensions/cdevGenericServer/example/Reflector/ReflectorService.h @@ -0,0 +1,26 @@ +#include + +#ifndef REFLECTOR_SERVICE_API + #define REFLECTOR_SERVICE_API +#endif + +// ***************************************************************************** +// * newReflectorService : +// * This function will be called by the cdevSystem object to create an +// * initial instance of the ReflectorService. +// ***************************************************************************** +extern "C" REFLECTOR_SERVICE_API cdevService * newReflectorService ( char * name, cdevSystem * system ); + +// ***************************************************************************** +// * class ReflectorService : +// * This class simply inherits from the cdevClientService and must define +// * only a constructor and destructor. +// ***************************************************************************** +class ReflectorService : public cdevClientService +{ +public: + ReflectorService ( char * name, cdevSystem & system = cdevSystem::defaultSystem()); + +protected: + virtual ~ReflectorService ( void ) {}; +}; diff --git a/extensions/cdevGenericServer/example/Reflector/ReflectorTest.csh b/extensions/cdevGenericServer/example/Reflector/ReflectorTest.csh new file mode 100755 index 0000000..df47494 --- /dev/null +++ b/extensions/cdevGenericServer/example/Reflector/ReflectorTest.csh @@ -0,0 +1,46 @@ +#! /bin/csh + +if ( $?CDEV == 0 ) then + echo "CDEV Environment Variable is NOT Defined" + exit 0 +endif + +if ( $?CDEVDDL ) then + setenv OLDCDEVDDL $CDEVDDL +endif + +setenv CDEVDDL `pwd`/Reflector.ddl + +echo "-------------------------------------------------------------------------" +echo " This test will send a collection of packets to the Reflector Server... " +echo " The Server should return the same data to the client unmodified. " +echo "-------------------------------------------------------------------------" + +cdevUtil "debug on" \ + "device1 get attrib1 value=0 status=1 controlHigh=2 controlLow=3 alarmHigh=4 alarmLow=5" \ + "device1 get attrib2 value=10 status=11 controlHigh=12 controlLow=13 alarmHigh=14 alarmLow=15" \ + "device1 get attrib3 value=20 status=21 controlHigh=22 controlLow=23 alarmHigh=24 alarmLow=25" \ + "device1 get attrib4 value=30 status=31 controlHigh=32 controlLow=33 alarmHigh=34 alarmLow=35" \ + "device1 get attrib5 value=40 status=41 controlHigh=42 controlLow=43 alarmHigh=44 alarmLow=45" \ + "device1 get attrib6 value=50 status=51 controlHigh=52 controlLow=53 alarmHigh=54 alarmLow=55" \ + "device2 get attrib1 value=0 status=1 controlHigh=2 controlLow=3 alarmHigh=4 alarmLow=5" \ + "device2 get attrib2 value=10 status=11 controlHigh=12 controlLow=13 alarmHigh=14 alarmLow=15" \ + "device2 get attrib3 value=20 status=21 controlHigh=22 controlLow=23 alarmHigh=24 alarmLow=25" \ + "device2 get attrib4 value=30 status=31 controlHigh=32 controlLow=33 alarmHigh=34 alarmLow=35" \ + "device2 get attrib5 value=40 status=41 controlHigh=42 controlLow=43 alarmHigh=44 alarmLow=45" \ + "device2 get attrib6 value=50 status=51 controlHigh=52 controlLow=53 alarmHigh=54 alarmLow=55" \ + "device3 get attrib1 value=0 status=1 controlHigh=2 controlLow=3 alarmHigh=4 alarmLow=5" \ + "device3 get attrib2 value=10 status=11 controlHigh=12 controlLow=13 alarmHigh=14 alarmLow=15" \ + "device3 get attrib3 value=20 status=21 controlHigh=22 controlLow=23 alarmHigh=24 alarmLow=25" \ + "device3 get attrib4 value=30 status=31 controlHigh=32 controlLow=33 alarmHigh=34 alarmLow=35" \ + "device3 get attrib5 value=40 status=41 controlHigh=42 controlLow=43 alarmHigh=44 alarmLow=45" \ + "device3 get attrib6 value=50 status=51 controlHigh=52 controlLow=53 alarmHigh=54 alarmLow=55" \ + "quit" + +if ( $?OLDCDEVDDL ) then + setenv CDEVDDL $OLDCDEVDDL +endif + +echo "-------------------------------------------------------------------------" +echo " End of test..." +echo "-------------------------------------------------------------------------" diff --git a/extensions/cdevGenericServer/example/VirtualService/Makefile b/extensions/cdevGenericServer/example/VirtualService/Makefile new file mode 100755 index 0000000..66210c2 --- /dev/null +++ b/extensions/cdevGenericServer/example/VirtualService/Makefile @@ -0,0 +1,34 @@ +ARCH = OS +SHOBJ = YES + +include ../../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Virtual Client/Server Example" +CXXINCLUDES = -I./ +SERVER_LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(ACELIBS) $(OSLIBS) + +ifeq ($(SHOBJ), YES) + LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + TARGETS = $(BASELIB)/VirtualService.so $(BASEBIN)/VirtualServer $(BASEBIN)/monitorTest +else + LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(ACELIBS) $(OSLIBS) + TARGETS = $(BASELIB)/libVirtualService.a $(BASEBIN)/VirtualServer $(BASEBIN)/monitorTest +endif + + +targets : $(TARGETS) + +$(BASEBIN)/VirtualServer : $(OBJDIR)/VirtualServer.o $(OBJDIR)/VirtualAttrib.o + $(LINK.cc) $^ $(SERVER_LIBS) -o $@ + +$(BASELIB)/VirtualService.so : $(OBJDIR)/VirtualService.o + $(LINK.so) -o $@ $^ -L$(CDEVLIB) -lcdevGenericServer $(OSLIBS) + @mkdir -p $(CDEVSHOBJ)/$(CDEVVERSION) + @cp $@ $(CDEVSHOBJ)/$(CDEVVERSION)/$(@F) + +$(BASELIB)/libVirtualService.a : $(OBJDIR)/VirtualService.o + $(LINK.a) $@ $^ + @$(RANLIB) $@ > /dev/null + +$(BASEBIN)/monitorTest : $(OBJDIR)/monitorTest.o + $(LINK.cc) $^ -o $@ $(LIBS) diff --git a/extensions/cdevGenericServer/example/VirtualService/NMakefile.mak b/extensions/cdevGenericServer/example/VirtualService/NMakefile.mak new file mode 100755 index 0000000..ccd952e --- /dev/null +++ b/extensions/cdevGenericServer/example/VirtualService/NMakefile.mak @@ -0,0 +1,61 @@ +.SUFFIXES: .cc .obj + +APPNAME = Virtual Client/Server Example +ARCH = WINNT-4.0 +SHOBJ = YES + +BINARIES = $(BASEBIN)\VirtualServer.exe \ + $(CDEVLIB)\VirtualService.dll \ + $(CDEVLIB)\VirtualService.lib \ + $(BASEBIN)\monitorTest.exe + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +CXXINCLUDES = /I .\\ +CXXEXTRA_DLL = /D "VIRTUAL_SERVICE_API=__declspec(dllexport)" +CXXEXTRA_LIB = /D "VIRTUAL_SERVICE_API=" + +!IF "$(SHOBJ)" == "YES" +TARGETS = $(BASEBIN)\VirtualServer.exe \ + $(CDEVLIB)\VirtualService.dll \ + $(BASEBIN)\monitorTest.exe +!ELSE +TARGETS = $(BASEBIN)\VirtualServer.exe \ + $(CDEVLIB)\VirtualService.lib \ + $(BASEBIN)\monitorTest.exe +!ENDIF + +targets : $(TARGETS) + +$(CDEVLIB)\VirtualService.dll : $(OBJDIR)\VirtualService.obj + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib\ + $(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $? + -@copy $@ $(CDEVSHOBJ)\$(CDEVVERSION)\$(@F) > nul + @echo ^ ^ ^ ^ ^ ^ Done... + +$(CDEVLIB)\VirtualService.lib : $(OBJDIR)\VirtualService.obj + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib\ + $(LINK_LIB_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\VirtualServer.exe : .exec\$(TARGETDIR)\VirtualServer.obj .exec\$(TARGETDIR)\VirtualAttrib.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\monitorTest.exe : .exec\$(TARGETDIR)\monitorTest.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + + diff --git a/extensions/cdevGenericServer/example/VirtualService/Virtual.ddl b/extensions/cdevGenericServer/example/VirtualService/Virtual.ddl new file mode 100755 index 0000000..e3970da --- /dev/null +++ b/extensions/cdevGenericServer/example/VirtualService/Virtual.ddl @@ -0,0 +1,34 @@ +service Virtual + { + tags {server} + } + +class Virtuals + { + verbs {get, set, monitorOn, monitorOff} + attributes + { + default Virtual; + servers Virtual; + attrib0 Virtual {server=TestServerX}; + attrib1 Virtual {server=TestServerX}; + attrib2 Virtual {server=TestServerX}; + attrib3 Virtual {server=TestServerX}; + attrib4 Virtual {server=TestServerX}; + attrib5 Virtual {server=TestServerX}; + attrib6 Virtual {server=TestServerX}; + attrib7 Virtual {server=TestServerX}; + attrib8 Virtual {server=TestServerX}; + attrib9 Virtual {server=TestServerX}; + } + messages + { + disconnect Virtual; + } + } + + +Virtuals : + device0, device1, device2, device3, device4, + device5, device6, device7, device8, device9 +; diff --git a/extensions/cdevGenericServer/example/VirtualService/VirtualAttrib.cc b/extensions/cdevGenericServer/example/VirtualService/VirtualAttrib.cc new file mode 100755 index 0000000..1a458e1 --- /dev/null +++ b/extensions/cdevGenericServer/example/VirtualService/VirtualAttrib.cc @@ -0,0 +1,445 @@ +#include + +static int VALUE_TAG_ID = -1; +static int STATUS_TAG_ID = -1; +static int SEVERITY_TAG_ID = -1; +static int UNITS_TAG_ID = -1; +static int ALARMHIGH_TAG_ID = -1; +static int ALARMLOW_TAG_ID = -1; +static int WARNINGHIGH_TAG_ID = -1; +static int WARNINGLOW_TAG_ID = -1; +static int CONTROLHIGH_TAG_ID = -1; +static int CONTROLLOW_TAG_ID = -1; + +#define VALUE_TAG ((VALUE_TAG_ID<0 && cdevData::tagC2I("value", &VALUE_TAG_ID)!=CDEV_SUCCESS)?-1:VALUE_TAG_ID) +#define STATUS_TAG ((STATUS_TAG_ID<0 && cdevData::tagC2I("status", &STATUS_TAG_ID)!=CDEV_SUCCESS)?-1:STATUS_TAG_ID) +#define SEVERITY_TAG ((SEVERITY_TAG_ID<0 && cdevData::tagC2I("severity", &SEVERITY_TAG_ID)!=CDEV_SUCCESS)?-1:SEVERITY_TAG_ID) +#define UNITS_TAG ((UNITS_TAG_ID<0 && cdevData::tagC2I("units", &UNITS_TAG_ID)!=CDEV_SUCCESS)?-1:UNITS_TAG_ID) +#define ALARMHIGH_TAG ((ALARMHIGH_TAG_ID<0 && cdevData::tagC2I("alarmHigh", &ALARMHIGH_TAG_ID)!=CDEV_SUCCESS)?-1:ALARMHIGH_TAG_ID) +#define ALARMLOW_TAG ((ALARMLOW_TAG_ID<0 && cdevData::tagC2I("alarmLow", &ALARMLOW_TAG_ID)!=CDEV_SUCCESS)?-1:ALARMLOW_TAG_ID) +#define WARNINGHIGH_TAG ((WARNINGHIGH_TAG_ID<0 && cdevData::tagC2I("warningHigh", &WARNINGHIGH_TAG_ID)!=CDEV_SUCCESS)?-1:WARNINGHIGH_TAG_ID) +#define WARNINGLOW_TAG ((WARNINGLOW_TAG_ID<0 && cdevData::tagC2I("warningLow", &WARNINGLOW_TAG_ID)!=CDEV_SUCCESS)?-1:WARNINGLOW_TAG_ID) +#define CONTROLHIGH_TAG ((CONTROLHIGH_TAG_ID<0 && cdevData::tagC2I("controlHigh", &CONTROLHIGH_TAG_ID)!=CDEV_SUCCESS)?-1:CONTROLHIGH_TAG_ID) +#define CONTROLLOW_TAG ((CONTROLLOW_TAG_ID<0 && cdevData::tagC2I("controlLow", &CONTROLLOW_TAG_ID)!=CDEV_SUCCESS)?-1:CONTROLLOW_TAG_ID) + +// ***************************************************************************** +// * VirtualAttrib::VirtualAttrib : +// * This is the constructor for the VirtualAttrib class. It initializes the +// * internal mechanisms to 0. +// ***************************************************************************** +VirtualAttrib::VirtualAttrib ( char * Device, char * Attrib ) + : device(strdup(Device)), + attrib(strdup(Attrib)), + monitors(NULL), + value(0.0), + alarmHigh(0.0), + alarmLow(0.0), + warningHigh(0.0), + warningLow(0.0), + controlHigh(0.0), + controlLow(0.0) + { + *severity = 0; + *units = 0; + strcpy(status, "NORMAL"); + } + + +// ***************************************************************************** +// * VirtualAttrib::~VirtualAttrib : +// * This is the destructor for the VirtualAttrib class. It must free the +// * memory associated with the device and attribute names. +// ***************************************************************************** +VirtualAttrib::~VirtualAttrib ( void ) + { + delete device; + delete attrib; + } + +// ***************************************************************************** +// * VirtualAttrib::setFromData : +// * This method will populate the VirtualAttrib object with the data contained in +// * the cdevData object. +// ***************************************************************************** +int VirtualAttrib::setFromData ( cdevData * data ) + { + double val; + int result; + if(data!=NULL) + { + result = CDEV_SUCCESS; + data->get(UNITS_TAG, units, 255); + if(data->get(CONTROLLOW_TAG, &val)==CDEV_SUCCESS) setControlLow(val); + if(data->get(CONTROLHIGH_TAG, &val)==CDEV_SUCCESS) setControlHigh(val); + if(data->get(ALARMLOW_TAG, &val)==CDEV_SUCCESS) setAlarmLow(val); + if(data->get(ALARMHIGH_TAG, &val)==CDEV_SUCCESS) setAlarmHigh(val); + if(data->get(WARNINGLOW_TAG, &val)==CDEV_SUCCESS) setWarningLow(val); + if(data->get(WARNINGHIGH_TAG, &val)==CDEV_SUCCESS) setWarningHigh(val); + if(data->get(VALUE_TAG, &val)==CDEV_SUCCESS) + { + result=setValue(val); + } + } + else result = CDEV_ERROR; + checkAlarms(); + return result; + } + + +// ***************************************************************************** +// * VirtualAttrib::getToData : +// * This method will populate the VirtualAttrib object with the data contained in +// * the cdevData object. +// ***************************************************************************** +void VirtualAttrib::getToData ( cdevData * data, cdevData * context ) + { + if(data!=NULL) + { + data->remove(); + if(context!=NULL) + { + if(context->getType(VALUE_TAG)!=CDEV_INVALID) data->insert(VALUE_TAG, getValue()); + if(context->getType(STATUS_TAG)!=CDEV_INVALID) data->insert(STATUS_TAG, getStatus()); + if(context->getType(SEVERITY_TAG)!=CDEV_INVALID) data->insert(SEVERITY_TAG, getSeverity()); + if(context->getType(UNITS_TAG)!=CDEV_INVALID) data->insert(UNITS_TAG, getUnits()); + if(context->getType(CONTROLLOW_TAG)!=CDEV_INVALID) data->insert(CONTROLLOW_TAG, getControlLow()); + if(context->getType(CONTROLHIGH_TAG)!=CDEV_INVALID) data->insert(CONTROLHIGH_TAG, getControlHigh()); + if(context->getType(ALARMLOW_TAG)!=CDEV_INVALID) data->insert(ALARMLOW_TAG, getAlarmLow()); + if(context->getType(ALARMHIGH_TAG)!=CDEV_INVALID) data->insert(ALARMHIGH_TAG, getAlarmHigh()); + if(context->getType(WARNINGLOW_TAG)!=CDEV_INVALID) data->insert(WARNINGLOW_TAG, getWarningLow()); + if(context->getType(WARNINGHIGH_TAG)!=CDEV_INVALID) data->insert(WARNINGHIGH_TAG, getWarningHigh()); + } + else + { + data->insert(VALUE_TAG, getValue()); + data->insert(STATUS_TAG, getStatus()); + data->insert(SEVERITY_TAG, getSeverity()); + } + } + } + + +// ***************************************************************************** +// * VirtualAttrib::getAllToData : +// * This method will populate the VirtualAttrib object with the data contained in +// * the cdevData object. +// ***************************************************************************** +void VirtualAttrib::getAllToData ( cdevData * data ) + { + if(data!=NULL) + { + data->remove(); + data->insert(VALUE_TAG, getValue()); + data->insert(STATUS_TAG, getStatus()); + data->insert(SEVERITY_TAG, getSeverity()); + data->insert(UNITS_TAG, getUnits()); + data->insert(CONTROLLOW_TAG, getControlLow()); + data->insert(CONTROLHIGH_TAG, getControlHigh()); + data->insert(ALARMLOW_TAG, getAlarmLow()); + data->insert(ALARMHIGH_TAG, getAlarmHigh()); + data->insert(WARNINGLOW_TAG, getWarningLow()); + data->insert(WARNINGHIGH_TAG, getWarningHigh()); + } + } + +// ***************************************************************************** +// * VirtualAttrib::setValue : +// * This method allows the caller to set the value of the Virtual Attrib. +// * This call will fail if the specified value is outside of the legal +// * range. +// ***************************************************************************** +int VirtualAttrib::setValue ( double Value ) + { + resultCode = CDEV_SUCCESS; + + if(controlHigh>controlLow && + (ValuecontrolHigh)) + { + resultCode = CDEV_OUTOFRANGE; + } + else if(value != Value) + { + value = Value; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(VALUE_TAG, &data); + } + } + return resultCode; + } + +// ***************************************************************************** +// * VirtualAttrib::setStatus : +// * This method allows the caller to set the status of the device. +// ***************************************************************************** +int VirtualAttrib::setStatus ( char * Status ) + { + if(strcmp(status, Status)) + { + strncpy(status, Status, 255); + status[254] = 0; + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(STATUS_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setSeverity : +// * This method allows the caller to set the severity flag for the device. +// ***************************************************************************** +int VirtualAttrib::setSeverity ( char * Severity ) + { + if(strcmp(severity, Severity)) + { + strncpy(severity, Severity, 255); + severity[254] = 0; + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(SEVERITY_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setUnits : +// * This method allows the caller to set the units for the device. +// ***************************************************************************** +int VirtualAttrib::setUnits ( char * Units ) + { + if(strcmp(units, Units)) + { + strncpy(units, Units, 255); + units[254] = 0; + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(UNITS_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setAlarmHigh : +// * This method allows the caller to set the high alarm value of the device. +// ***************************************************************************** +int VirtualAttrib::setAlarmHigh ( double AlarmHigh ) + { + if(alarmHigh!=AlarmHigh) + { + alarmHigh = AlarmHigh; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(ALARMHIGH_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setAlarmLow : +// * This method allows the caller to set the low alarm value of the device. +// ***************************************************************************** +int VirtualAttrib::setAlarmLow ( double AlarmLow ) + { + if(alarmLow!=AlarmLow) + { + alarmLow = AlarmLow; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(ALARMLOW_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setWarningHigh : +// * This method allows the caller to set the high warning value of a device. +// ***************************************************************************** +int VirtualAttrib::setWarningHigh ( double WarningHigh ) + { + if(warningHigh!=WarningHigh) + { + warningHigh = WarningHigh; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(WARNINGHIGH_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setWarningLow : +// * This method allows the caller to set the low warning value of a device. +// ***************************************************************************** +int VirtualAttrib::setWarningLow ( double WarningLow ) + { + if(warningLow != WarningLow) + { + warningLow = WarningLow; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(WARNINGLOW_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setControlHigh : +// * This method allows the caller to set the maximum value for a device. +// ***************************************************************************** +int VirtualAttrib::setControlHigh ( double ControlHigh ) + { + if(controlHigh != ControlHigh) + { + controlHigh = ControlHigh; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(CONTROLHIGH_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::setControlLow : +// * This method allows the caller to set the minimum value of a device. +// ***************************************************************************** +int VirtualAttrib::setControlLow ( double ControlLow ) + { + if(controlLow != ControlLow) + { + controlLow = ControlLow; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(CONTROLLOW_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * VirtualAttrib::checkAlarms : +// * This method allows the caller to read the value in comparison with all +// * of its limits and set the status and severity tag appropriately. +// ***************************************************************************** +void VirtualAttrib::checkAlarms ( void ) + { + int done = 0; + if(controlHigh>controlLow) + { + if(valuecontrolHigh) + { + setStatus("OUT OF RANGE HIGH"); + setSeverity("ERROR"); + done = 1; + } + } + if(!done && alarmHigh>alarmLow) + { + if(valuealarmHigh) + { + setStatus("ALARM HIGH"); + setSeverity("ALARM"); + done = 1; + } + } + if(!done && warningHigh>warningLow) + { + if(valuewarningHigh) + { + setStatus("WARNING HIGH"); + setSeverity("WARNING"); + done = 1; + } + } + if(!done) + { + setStatus("NORMAL"); + setSeverity("\0"); + } + } + +// ***************************************************************************** +// * VirtualAttrib::insertMonitor : +// * This message adds a monitor to the cdevMonitorTable for this device/ +// * attribute pair. The message parameter becomes the property of the +// * monitorTable and should not be accessed again by the caller. +// ***************************************************************************** +void VirtualAttrib::insertMonitor ( cdevMonitorTable * table, cdevMessage * message ) + { + if(table!=NULL && message!=NULL) + { + cdevData data; + getAllToData(&data); + table->insertMonitor(message, &data); + monitors = table->findMonitor(device, attrib); + if(monitors && !monitors->isMonitored()) monitors = NULL; + } + else if(message!=NULL) delete message; + } + +// ***************************************************************************** +// * VirtualAttrib::removeMonitor: +// * This method uses the cancelTransIdx to locate and delete a monitor +// * that was previously posted using that transaction index. +// ***************************************************************************** +void VirtualAttrib::removeMonitor (cdevMonitorTable * table, cdevMessage * message ) + { + if(table!=NULL && message!=NULL) + { + table->removeMonitor(message); + if(monitors && !monitors->isMonitored()) monitors = NULL; + } + } diff --git a/extensions/cdevGenericServer/example/VirtualService/VirtualAttrib.h b/extensions/cdevGenericServer/example/VirtualService/VirtualAttrib.h new file mode 100755 index 0000000..18a79fe --- /dev/null +++ b/extensions/cdevGenericServer/example/VirtualService/VirtualAttrib.h @@ -0,0 +1,68 @@ +#ifndef _VIRTUAL_ATTRIB_H_ +#define _VIRTUAL_ATTRIB_H_ 1 + +#include +#include + + +// ***************************************************************************** +// * class VirtualAttrib: +// * This class maintains a list of items that make-up a Virtual Attrib. And +// * access mechanisms. +// ***************************************************************************** +class VirtualAttrib +{ +private: + char * device; + char * attrib; + cdevMonitorNode * monitors; + + double value; + char status [255]; + char severity[255]; + char units [255]; + double alarmHigh; + double alarmLow; + double warningHigh; + double warningLow; + double controlHigh; + double controlLow; + + int resultCode; +public: + VirtualAttrib (char * Device, char * Attrib); + ~VirtualAttrib ( void ); + + int setFromData ( cdevData * data ); + void getToData ( cdevData * data, cdevData * context = NULL ); + void getAllToData ( cdevData * data ); + + int setValue ( double Value ); + int setStatus ( char * Status ); + int setSeverity ( char * Severity ); + int setUnits ( char * Units ); + int setAlarmHigh ( double AlarmHigh ); + int setAlarmLow ( double AlarmLow ); + int setWarningHigh ( double WarningHigh ); + int setWarningLow ( double WarningLow ); + int setControlHigh ( double ControlHigh ); + int setControlLow ( double ControlLow ); + void checkAlarms ( void ); + + double getValue ( void ) { return value; } + char * getStatus ( void ) { return status; } + char * getSeverity ( void ) { return severity; } + char * getUnits ( void ) { return units; } + double getAlarmHigh ( void ) { return alarmHigh; } + double getAlarmLow ( void ) { return alarmLow; } + double getWarningHigh ( void ) { return warningHigh; } + double getWarningLow ( void ) { return warningLow; } + double getControlHigh ( void ) { return controlHigh; } + double getControlLow ( void ) { return controlLow; } + int getResultCode ( void ) { return resultCode; } + + void insertMonitor ( cdevMonitorTable * table, cdevMessage * message ); + void removeMonitor ( cdevMonitorTable * table, cdevMessage * message ); +}; + +#endif diff --git a/extensions/cdevGenericServer/example/VirtualService/VirtualServer.cc b/extensions/cdevGenericServer/example/VirtualService/VirtualServer.cc new file mode 100755 index 0000000..7e47dcd --- /dev/null +++ b/extensions/cdevGenericServer/example/VirtualService/VirtualServer.cc @@ -0,0 +1,158 @@ +#include +#include + +// ***************************************************************************** +// * This has to be added in order to support the CenterLine Compiler. +// ***************************************************************************** +VirtualServer::~VirtualServer ( void ) + { + StringHashIterator iter(&attribHash); + VirtualAttrib * attrib = NULL; + char * key = NULL; + + iter.first(); + while((key=iter.key())!=NULL) + { + attrib = (VirtualAttrib *)iter.data(); + iter++; + attribHash.remove(key); + if(attrib!=NULL) delete attrib; + } + } + +void VirtualServer::populateTable ( void ) + { + char device[10]; + char attrib[10]; + char key[20]; + for(int i=0; i<10; i++) + { + for(int j=0; j<10; j++) + { + sprintf(device, "device%i", i); + sprintf(attrib, "attrib%i", j); + sprintf(key, "device%i attrib%i", i, j); + attribHash.insert(key, new VirtualAttrib(device, attrib)); + } + } + } + +void VirtualServer::processMessages ( void ) + { + char key[255]; + int saveMessageFlag; + int sendMessageFlag; + cdevMessage * message; + VirtualAttrib * attrib; + cdevData output; + + while(dequeue(message)==0) + { + // ************************************************************* + // * Note at this point a cdevTagMap has already been received + // * from the client. This tag map will have initialized all + // * of the tags that are required by the service. + // ************************************************************* + if(!strcmp(message->getMessage(), "unregister")) + { + sendMessageFlag = 0; + removeClientMonitors(message->getClientID()); + } + if(!strncmp(message->getMessage(), "get ", 4)) + { + output.remove(); + saveMessageFlag = 0; + sendMessageFlag = 1; + + sprintf(key, "%s %s", + message->getDeviceList()[0], + &message->getMessage()[4]); + + if((attrib = (VirtualAttrib *)attribHash.find(key))!=NULL) + { + attrib->getToData(&output, message->getContext()); + output.insert("resultCode", CDEV_SUCCESS); + } + else output.insert("resultCode", CDEV_NOTFOUND); + } + else if(!strncmp(message->getMessage(), "set ", 4)) + { + output.remove(); + saveMessageFlag = 0; + sendMessageFlag = 1; + + sprintf(key, "%s %s", + message->getDeviceList()[0], + &message->getMessage()[4]); + + if((attrib = (VirtualAttrib *)attribHash.find(key))!=NULL) + { + output.insert("resultCode", + attrib->setFromData(message->getData())); + } + else output.insert("resultCode", CDEV_NOTFOUND); + } + else if(!strncmp(message->getMessage(), "monitorOn ", 10)) + { + saveMessageFlag = 1; + sendMessageFlag = 0; + + sprintf(key, "%s %s", + message->getDeviceList()[0], + &message->getMessage()[10]); + + if((attrib = (VirtualAttrib *)attribHash.find(key))!=NULL) + { + attrib->insertMonitor(this, message); + } + } + else if(!strncmp(message->getMessage(), "monitorOff ", 11)) + { + saveMessageFlag = 0; + sendMessageFlag = 1; + + sprintf(key, "%s %s", + message->getDeviceList()[0], + &message->getMessage()[11]); + + if((attrib = (VirtualAttrib *)attribHash.find(key))!=NULL) + { + attrib->removeMonitor(this, message); + } + } + else + { + saveMessageFlag = 0; + sendMessageFlag = 1; + output.insert("resultCode", CDEV_NOTFOUND); + } + + if(sendMessageFlag) + { + message->setData(&output, 1); + enqueue(message); + } + if(!saveMessageFlag) delete message; + } + } + +int VirtualServer::fireCallback ( cdevMessage * message ) + { + int result = CDEV_SUCCESS; + cdevData * data = NULL; + + if(message && (data = message->getData())!=NULL) + { + data->insert("resultCode", CDEV_SUCCESS); + result = enqueue(message); + } + return result; + } + +int main() +{ +VirtualServer server("VIRTUAL", "TestServerX", 0, 60); +cdevServer::runServer(); + +return 0; +} diff --git a/extensions/cdevGenericServer/example/VirtualService/VirtualServer.h b/extensions/cdevGenericServer/example/VirtualService/VirtualServer.h new file mode 100755 index 0000000..f264a7a --- /dev/null +++ b/extensions/cdevGenericServer/example/VirtualService/VirtualServer.h @@ -0,0 +1,40 @@ +#ifndef _VIRTUAL_SERVER_H_ +#define _VIRTUAL_SERVER_H_ 1 + +#include +#include +#include + +// ***************************************************************************** +// * class VirtualServer : +// * This is the server class for the VirtualDevice. It simply receives +// * messages from a client and immediately returns them. +// * +// * The constructor passes the domain, server, port and rate to the +// * underlying cdevServer class to be processed. The cdevServer constructor +// * will add this server to the Name Server and will begin processing +// * messages when the cdevServer::runServer() method is executed. +// * +// * The processMessages method is the servers interface to the world... Each +// * time a complete message is received or the time specified in rate +// * expires, that method will be called. +// ***************************************************************************** +class VirtualServer : public cdevServer, public cdevMonitorTable +{ +private: + StringHash attribHash; + +public: + VirtualServer ( char * domain, char * server, unsigned int port, double pulse ) + : cdevServer(domain, server, port, pulse), attribHash() + { + populateTable(); + } + + virtual ~VirtualServer ( void ); + virtual void processMessages ( void ); + void populateTable ( void ); + virtual int fireCallback ( cdevMessage * message ); +}; + +#endif diff --git a/extensions/cdevGenericServer/example/VirtualService/VirtualService.cc b/extensions/cdevGenericServer/example/VirtualService/VirtualService.cc new file mode 100755 index 0000000..76f53ed --- /dev/null +++ b/extensions/cdevGenericServer/example/VirtualService/VirtualService.cc @@ -0,0 +1,60 @@ +#include + +// ***************************************************************************** +// * newVirtualService: +// * This function will be called by the cdevSystem object to create an +// * initial instance of the VirtualService. +// ***************************************************************************** +extern "C" cdevService * newVirtualService (char * name, cdevSystem * system) + { + return new VirtualService(name, *system); + } + +// ***************************************************************************** +// * VirtualService::VirtualService : +// * This is teh constructor for the VirtualService. It initializes the +// * underlying cdevClientService by specifying that it is in the domain of +// * VIRTUAL. +// ***************************************************************************** +VirtualService::VirtualService ( char * name, cdevSystem & system) + : cdevClientService("VIRTUAL", name, system) + { + // ********************************************************************* + // * Install the RESULT_CODE_TAG at a location of 30 or higher if it + // * does not already exist. + // ********************************************************************* + RESULT_CODE_TAG = 0; + cdevData::tagC2I("resultCode", &RESULT_CODE_TAG); + + for(int i=30; RESULT_CODE_TAG==0 && i<65534; i++) + { + cdevData::insertTag(i, "resultCode"); + cdevData::tagC2I("resultCode", &RESULT_CODE_TAG); + } + + system.reportError(CDEV_SEVERITY_INFO, "VirtualService", NULL, + "Constructing a new VirtualService"); + + } + +// ***************************************************************************** +// * VirtualService::fireCallback : +// * This is the method that will be called to dispatch the callback methods +// * that are associated with the calls to the Virtual Server. If the +// * message has been processed successfully, then the method will remove +// * the resultCode from the outbound data and use that as the status. +// ***************************************************************************** +void VirtualService::fireCallback ( int status, cdevTranObj &xobj, cdevData *resultData ) + { + // ********************************************************************* + // * If the message was transmitted successfully, get the result code + // * from the data that was returned and use that as the status. + // ********************************************************************* + if(status==CDEV_SUCCESS && resultData!=NULL) + { + resultData->get(RESULT_CODE_TAG, &status); + resultData->remove(RESULT_CODE_TAG); + } + + cdevClientService::fireCallback(status, xobj, resultData); + } diff --git a/extensions/cdevGenericServer/example/VirtualService/VirtualService.h b/extensions/cdevGenericServer/example/VirtualService/VirtualService.h new file mode 100755 index 0000000..a6e7f76 --- /dev/null +++ b/extensions/cdevGenericServer/example/VirtualService/VirtualService.h @@ -0,0 +1,29 @@ +#include + +#ifndef VIRTUAL_SERVICE_API + #define VIRTUAL_SERVICE_API +#endif + +// ***************************************************************************** +// * newVirtualService : +// * This function will be called by the cdevSystem object to create an +// * initial instance of the VirtualService. +// ***************************************************************************** +extern "C" VIRTUAL_SERVICE_API cdevService * newVirtualService ( char * name, cdevSystem * system ); + +// ***************************************************************************** +// * class VirtualService : +// * This class simply inherits from the cdevClientService and must define +// * only a constructor and destructor. +// ***************************************************************************** +class VirtualService : public cdevClientService +{ +public: + VirtualService ( char * name, cdevSystem & system = cdevSystem::defaultSystem()); + +protected: + int RESULT_CODE_TAG; + + virtual ~VirtualService ( void ) {}; + virtual void fireCallback ( int status, cdevTranObj &xobj, cdevData *resultData ); +}; diff --git a/extensions/cdevGenericServer/example/VirtualService/monitorTest.cc b/extensions/cdevGenericServer/example/VirtualService/monitorTest.cc new file mode 100755 index 0000000..25a7003 --- /dev/null +++ b/extensions/cdevGenericServer/example/VirtualService/monitorTest.cc @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include +#include + +int lastHitReceived = 0; +int callbackCount = 0; +double totalPeriod = 0.0; + +void myCallback1 (int status, void *, cdevRequestObject &, cdevData &) + { + if(status==CDEV_SUCCESS) callbackCount++; + } + +void myCallback2 (int status, void *, cdevRequestObject &, cdevData &) + { + if(status==CDEV_SUCCESS) + { + callbackCount++; + lastHitReceived++; + } + } + +#define POSTCOUNT 1 +#define REPEATCOUNT 2 + +int main(void) +{ +struct timeval first, second, lapsed; +cdevCallback cb1(myCallback1, NULL); +cdevCallback cb2(myCallback2, NULL); + +cdevDevice * device[3]; + +device[0] = cdevDevice::attachPtr("device1"); +device[1] = cdevDevice::attachPtr("device2"); +device[2] = cdevDevice::attachPtr("device3"); +cdevData data; +cdevData context; +int i,j,k; +int done = -2; +double deviceValue[3][3]; +char message[255]; + +context.insert("value", 3); +for(i=0; i<3; i++) + { + for(j=0; j<3; j++) + { + sprintf(message, "get attrib%i", j+1); + device[i]->send(message, NULL, data); + deviceValue[i][j] = (double)data; + } + } + +while(done<0) + { + fprintf(stdout, "Posting %i monitors\n", POSTCOUNT*9); + for(i=0; i<3; i++) + { + device[i]->setContext(context); + for(j=0; j<3; j++) + { + sprintf(message, "monitorOn attrib%i", j+1); + for(k=0; ksendCallback(message, NULL, cb1); + } + device[i]->sendCallback(message, NULL, cb2); + } + } + + for(k=0; k second.tv_usec) + { + second.tv_usec += 1000000; + second.tv_sec--; + } + lapsed.tv_usec = second.tv_usec - first.tv_usec; + lapsed.tv_sec = second.tv_sec - first.tv_sec; + double period = (double)lapsed.tv_sec+(double)lapsed.tv_usec/1000000.00; + totalPeriod += period; + fprintf(stdout, "%i Callbacks in %f seconds (%i pkts/sec - %i pkts/sec cum)\n", + POSTCOUNT*9, period, (int)((double)POSTCOUNT*9.0/period), (int)((double)callbackCount/totalPeriod)); + + for(i=0; i<3; i++) + { + for(j=0; j<3; j++) + { + deviceValue[i][j]+=1.0; + data.insert("value", deviceValue[i][j]); + if(ksendNoBlock(message, data, NULL); + } + } + } + } + + fprintf(stdout, "Removing %i monitors\n", POSTCOUNT*9); + for(i=0; i<3; i++) + { + for(j=0; j<3; j++) + { + sprintf(message, "monitorOff attrib%i", j+1); + device[i]->sendCallback(message, NULL, cb1); + device[i]->sendCallback(message, NULL, cb2); + } + } + done++; + } +cdevSystem::defaultSystem().poll(); + +return 0; +} diff --git a/extensions/cdevGenericServer/include/AddressIndex.h b/extensions/cdevGenericServer/include/AddressIndex.h new file mode 100644 index 0000000..fb4eb91 --- /dev/null +++ b/extensions/cdevGenericServer/include/AddressIndex.h @@ -0,0 +1,417 @@ +#ifndef ADDRESS_INDEX_H_ +#define ADDRESS_INDEX_H_ + +#include +#include +#include + +// ***************************************************************************** +// * union AddressReference : +// * This union contains all of the components that are necessary to locate +// * and validate a memory address from within an AddressIndex object. +// * +// * The index entry contains the location of the pointer within the address +// * array. +// * +// * The checksum entry contains the checksum value that should be located +// * at the specified index within the checksum array. +// * +// ***************************************************************************** +typedef union + { + unsigned rawData; + struct { + unsigned index : 24; + unsigned checksum : 8; + } value; + } AddressReference; + + +// ***************************************************************************** +// * class AddressIndex: +// * This class is used to allow an array to be dereferenced using an integer +// * code that contains an array index and a checksum value. Both of these +// * values are validated before the user is allowed to access the data. +// ***************************************************************************** +class AddressIndex +{ +friend class AddressIndexIterator; + +private: + enum {START_ARRAY_SIZE=1024}; + + // ********************************************************************* + // * population : this integer identifies the exact number of data items + // * that currently exist in the list. + // ********************************************************************* + int population; + + // ********************************************************************* + // * maxEntries : this integer identifies the maximum number of entries + // * that this object can contain. + // ********************************************************************* + int maxEntries; + + // ********************************************************************* + // * curEntry : this integer identifies the currently selected entry. + // ********************************************************************* + int curEntry; + + // ********************************************************************* + // * checksum : this is an array of bytes that are used to identify the + // * checksum for a specific address. This checksum is used to validate + // * that the address has not been changed externally. + // ********************************************************************* + unsigned char * checksum; + + // ********************************************************************* + // * address : this is the array of addresses that will be stored and + // * retrieved using this object. + // ********************************************************************* + void ** address; + + +public: + inline AddressIndex ( void ); + inline ~AddressIndex ( void ); + + inline unsigned insert( void * ptr ); + + inline void remove( void * ptr ); + inline void remove( unsigned idx ); + + inline unsigned find ( void * ptr ); + inline void * find ( unsigned idx ); +}; + + +class AddressIndexIterator +{ +private: + AddressIndex * index; + int current; + +public: + inline AddressIndexIterator (AddressIndex * Index); + inline ~AddressIndexIterator( void ); + + inline void * first ( void ); + inline void * operator ++ ( void ); + inline void * operator ++ ( int x ); + inline unsigned key ( void ); + inline void * data ( void ); +}; + + + +// ***************************************************************************** +// * AddressIndex::AddressIndex : +// * This is the constructor for the AddressIndex class. It is allocates a +// * default number of entries in the checksum and address arrays and then +// * initializes the data values to 0. +// * +// * Note that these arrays must be allocated using malloc because we will +// * use realloc later to expand there size if necessary. +// ***************************************************************************** +inline AddressIndex::AddressIndex ( void ) + : population(0),maxEntries(0),curEntry(0),checksum(NULL),address(NULL) + { + maxEntries = START_ARRAY_SIZE; + checksum = (unsigned char *)malloc(sizeof(unsigned char)*maxEntries); + address = (void **) malloc(sizeof(void *) *maxEntries); + memset(checksum, 1, sizeof(unsigned char)*maxEntries); + memset(address, 0, sizeof(void *) *maxEntries); + } + + +// ***************************************************************************** +// * AddressIndex::~AddressIndex : +// * This is the destructor for the object. It will deallocate any memory +// * that has been assigned to the checksum or address objects. +// * +// * Note that these arrays must be deallocated using the free library call +// * because they were allocated using either malloc or realloc. +// ***************************************************************************** +inline AddressIndex::~AddressIndex ( void ) + { + if(checksum!=NULL) free(checksum); + if(address!=NULL) free(address); + } + + +// ***************************************************************************** +// * AddressIndex::insert : +// * This method is used to insert a void * pointer into the AddressIndex +// * object. It returns an unsigned integer result which is the rawData +// * component of an AddressReference object. +// ***************************************************************************** +inline unsigned AddressIndex::insert ( void * ptr ) + { + AddressReference result; + + // ********************************************************************* + // * Initial all entries within the AddressReference object before + // * starting. + // ********************************************************************* + result.rawData = 0U; + + // ********************************************************************* + // * If the pointer provided by the user is NULL, then it cannot be + // * inserted into the list... Otherwise, + // * + // * From the current position in the array, we are going to walk + // * forward until we find an empty slot. An empty slot is indicated + // * by the value NULL in its address. + // * + // * If the end of the list is reached before an empty slot can be found + // * then special considerations will be made as described below. + // ********************************************************************* + if(ptr!=NULL) + { + while(curEntry=maxEntries then an empty slot was not located. + // * The following options should be considered... + // ************************************************************* + + // ************************************************************* + // * 1) If the population of the table is less than half of the + // * maximum number of entries... go back to the beginning + // * and search the table for an empty slot. + // ************************************************************* + if(curEntry>=maxEntries && population<(maxEntries/2)) + { + curEntry = 0; + while(curEntry=maxEntries) + { + curEntry = maxEntries; + maxEntries*=2; + checksum = (unsigned char *)realloc(checksum, sizeof(char *)*maxEntries); + address = (void **) realloc(address, sizeof(void *)*maxEntries); + memset(&checksum[curEntry], 0, sizeof(char *)*curEntry); + memset(&address [curEntry], 0, sizeof(void *)*curEntry); + } + + // ************************************************************* + // * At this time the curEntry index points to the insertion + // * point that should be used. Place the index and checksum + // * information into the result object and update the + // * population count. + // ************************************************************* + checksum[curEntry] = (checksum[curEntry]==255?1:(checksum[curEntry]+1)); + address [curEntry] = ptr; + + result.value.index = curEntry; + result.value.checksum = checksum[curEntry]; + + population++; + } + + // ********************************************************************* + // * Return the rawData portion of the AddressReference to the caller + // * as an unsigned integer. + // ********************************************************************* + return result.rawData; + } + + +// ***************************************************************************** +// * AddressIndex::remove : +// * This function will locate an entry by searching the array for a +// * specific pointer. If the entry is found it will be deleted. Direct +// * searching is one of the most time consuming approaches to locating +// * data, therefore the remove function that uses an unsigned integer +// * identifier should be used whenever possible. +// ***************************************************************************** +inline void AddressIndex::remove ( void * ptr) + { + if(ptr!=NULL) + { + for(int idx=0; idxpopulation && + currentmaxEntries && + index->address[current]==NULL) + { + current++; + } + return (index->population && currentmaxEntries)?index->address[current]:NULL; + } + + +// ***************************************************************************** +// * AddressIndexIterator::operator ++ : +// * Repositions to the next entry in the AddressIndex. +// ***************************************************************************** +inline void * AddressIndexIterator::operator ++ ( void ) + { + current++; + + while(index->population && + currentmaxEntries && + index->address[current]==NULL) + { + current++; + } + return (index->population && currentmaxEntries)?index->address[current]:NULL; + } + + +// ***************************************************************************** +// * AddressIndexIterator::operator ++ : +// * Repositions to the next entry in the AddressIndex. +// ***************************************************************************** +inline void * AddressIndexIterator::operator ++ ( int x ) + { + current++; + + while(x==0 && + index->population && + currentmaxEntries && + index->address[current]==NULL) + { + current++; + } + return (x==0 && index->population && currentmaxEntries)?index->address[current]:NULL; + } + +// ***************************************************************************** +// * AddressIndexIterator::key : +// * This method will return the AddressIndex key value of the current entry. +// ***************************************************************************** +inline unsigned AddressIndexIterator::key ( void ) + { + AddressReference result; + + result.rawData = 0; + if(currentmaxEntries && index->address[current]!=NULL) + { + result.value.index = current; + result.value.checksum = index->checksum[current]; + } + return result.rawData; + } + + +// ***************************************************************************** +// * AddressIndexIterator::data : +// * This method will return the data value of the current entry. +// ***************************************************************************** +inline void * AddressIndexIterator::data ( void ) + { + return(currentmaxEntries)?index->address[current]:NULL; + } + + +#endif /* ADDRESS_INDEX_H_ */ diff --git a/extensions/cdevGenericServer/include/ClientAcceptor.h b/extensions/cdevGenericServer/include/ClientAcceptor.h new file mode 100644 index 0000000..c99bfae --- /dev/null +++ b/extensions/cdevGenericServer/include/ClientAcceptor.h @@ -0,0 +1,34 @@ +#if !defined (_CLIENT_ACCEPTOR_H) +#define _CLIENT_ACCEPTOR_H + +#include "cdevSessionManager.h" + +#include "cdevSocketAcceptor.h" + +// ***************************************************************************** +// * class ClientAcceptor: +// * This class provdies the cdevEventHandler that accepts connections through +// * the reactor on the listening port. Once accepted, these new connections +// * are serviced by the ClientHandler. +// ***************************************************************************** +class GENERIC_SERVER_API ClientAcceptor : public cdevEventHandler, public ErrorReporter +{ +friend class ClientHandler; +public: + ClientAcceptor (cdevSessionManager &s); + ~ClientAcceptor (void); + + const char *getName (void) { return "ClientAcceptor"; } + int getLocalAddress (cdevAddr &addr) { return acceptor.getLocalAddress(addr); } + int open (const cdevInetAddr &addr); + + virtual int getHandle (void) const; + virtual int handleInput (void); + virtual int handleClose (void); + +private: + cdevSocketAcceptor acceptor; + cdevSessionManager & server; +}; + +#endif diff --git a/extensions/cdevGenericServer/include/ClientHandler.h b/extensions/cdevGenericServer/include/ClientHandler.h new file mode 100644 index 0000000..5096797 --- /dev/null +++ b/extensions/cdevGenericServer/include/ClientHandler.h @@ -0,0 +1,43 @@ +#if !defined (_CLIENT_HANDLER_H) +#define _CLIENT_HANDLER_H + +#include +#include +#include + +#include "cdevSessionManager.h" +#include "SocketUtil.h" + +#include "cdevSocketStream.h" + +class GENERIC_SERVER_API ClientHandler : public cdevEventHandler, public SocketReader, public SocketWriter +{ +public: + ClientHandler (cdevSessionManager & s); + ~ClientHandler (void); + + char * getHostName (void); + const char * getName (void) { return "ClientHandler"; } + virtual int open (class ClientAcceptor * acc); + virtual int getHandle (void) const; + operator cdevSocketStream & (void) { return stream; } + + virtual int handleClose (void); + virtual int handleInput (void); + virtual int handleOutput (void); + virtual int handleExcept (void); + + size_t getPacketsSent (void) { return packetsSent; } + size_t getPacketsRecv (void) { return packetsRecv; } + +protected: + char hostName[MAXHOSTNAMELEN + 1]; + cdevSocketStream stream; + cdevSessionManager & server; + SocketSession * queue; + int clientQuitFlag; + size_t packetsSent; + size_t packetsRecv; +}; + +#endif /* _CLIENT_HANDLER_H */ diff --git a/extensions/cdevGenericServer/include/ClientInfo.h b/extensions/cdevGenericServer/include/ClientInfo.h new file mode 100644 index 0000000..edc4415 --- /dev/null +++ b/extensions/cdevGenericServer/include/ClientInfo.h @@ -0,0 +1,355 @@ +#include +#include +#include + +class ClientInfoStruct +{ +private: + char unknown[8]; + char * username; + char * group; + unsigned uid; + unsigned gid; + unsigned pid; + char * program; + char * commandline; + time_t starttime; + time_t connecttime; + char * host; + char * os; + char * osrelease; + char * osversion; + char * machine; + char * shell; + +private: + void updateDataString ( cdevData & data, char * tag, char * &item ) + { + size_t nelems = 0; + + if(data.getElems(tag, &nelems)==CDEV_SUCCESS && + nelems==1 && data.getType(tag)==CDEV_STRING) + { + if(item!=NULL) delete item; + item = NULL; + data.get(tag, &item); + } + } + + void updateDataInt ( cdevData & data, char * tag, unsigned &item ) + { + size_t nelems = 0; + if(data.getElems(tag, &nelems)==CDEV_SUCCESS && nelems==1) + { + data.get(tag, &item); + } + } + +public: + ClientInfoStruct ( void ) + : username(NULL), group(NULL), uid(0), gid(0), pid(0), + program(NULL), commandline(NULL), starttime(0), + connecttime(0), host(NULL), os(NULL), osrelease(NULL), + osversion(NULL), machine(NULL), shell(NULL) + { + strcpy(unknown, "UNKNOWN"); + } + + ~ClientInfoStruct ( void ) + { + if(username) delete username; + if(group) delete group; + if(program) delete program; + if(commandline) delete commandline; + if(host) delete host; + if(os) delete os; + if(osrelease) delete osrelease; + if(osversion) delete osversion; + if(machine) delete machine; + if(shell) delete shell; + } + + void updateClientInfo ( cdevData & data ) + { + updateDataString(data, "username", username); + updateDataString(data, "group", group); + updateDataInt (data, "uid", uid); + updateDataInt (data, "gid", gid); + updateDataInt (data, "pid", pid); + updateDataString(data, "program", program); + updateDataString(data, "commandline", commandline); + updateDataInt (data, "starttime", (unsigned &)starttime); + updateDataInt (data, "connecttime", (unsigned &)connecttime); + updateDataString(data, "host", host); + updateDataString(data, "os", os); + updateDataString(data, "osrelease", osrelease); + updateDataString(data, "osversion", osversion); + updateDataString(data, "machine", machine); + updateDataString(data, "shell", shell); + connecttime = time(NULL); + } + + char * getUsername ( void ) { return username?username:unknown; } + char * getGroup ( void ) { return group?group:unknown; } + unsigned getUid ( void ) { return uid; } + unsigned getGid ( void ) { return gid; } + unsigned getPid ( void ) { return pid; } + char * getProgram ( void ) { return program?program:unknown; } + char * getCommandLine ( void ) { return commandline?commandline:unknown; } + time_t getStartTime ( void ) { return starttime; } + time_t getConnectTime ( void ) { return connecttime; } + char * getHost ( void ) { return host?host:unknown; } + char * getOs ( void ) { return os?os:unknown; } + char * getOsRelease ( void ) { return osrelease?osrelease:unknown; } + char * getOsVersion ( void ) { return osversion?osversion:unknown; } + char * getMachine ( void ) { return machine?machine:unknown; } + char * getShell ( void ) { return shell?shell:unknown; } + + void asciiDump ( FILE * fp = stdout ) + { + fprintf(fp, "--------------------------------------------------------\n"); + fprintf(fp, " Printing Client Information\n"); + fprintf(fp, "--------------------------------------------------------\n"); + fprintf(fp, "=> USERNAME : %s\n", username?username:"UNDEFINED"); + fprintf(fp, "=> GROUP : %s\n", group?group:"UNDEFINED"); + fprintf(fp, "=> USER ID : %s\n", uid?ltoa(uid):"UNDEFINED"); + fprintf(fp, "=> GROUP ID : %s\n", gid?ltoa(gid):"UNDEFINED"); + fprintf(fp, "=> PROCESS ID : %s\n", pid?ltoa(pid):"UNDEFINED"); + fprintf(fp, "=> APPLICATION : %s\n", program?program:"UNDEFINED"); + fprintf(fp, "=> COMMAND LINE : %s\n", commandline?commandline:"UNDEFINED"); + fprintf(fp, "=> START TIME : %s", starttime?ctime(&starttime):"UNKNOWN\n"); + fprintf(fp, "=> CONNECT TIME : %s", connecttime?ctime(&connecttime):"UNKNOWN\n"); + fprintf(fp, "=> HOST NAME : %s\n", host?host:"UNKNOWN"); + fprintf(fp, "=> OS : %s\n", os?os:"UNKNOWN"); + fprintf(fp, "=> OS VERSION : %s\n", osversion?osversion:"UNKNOWN"); + fprintf(fp, "=> OS RELEASE : %s\n", osrelease?osrelease:"UNKNOWN"); + fprintf(fp, "=> HARDWARE ID : %s\n", machine?machine:"UNKNOWN"); + fprintf(fp, "--------------------------------------------------------\n"); + } +}; + + +class ClientInfo +{ +private: + cdevData data; + +public: + ClientInfo ( void ) + { + cdevData::addTag("username"); + cdevData::addTag("group"); + cdevData::addTag("uid"); + cdevData::addTag("gid"); + cdevData::addTag("pid"); + cdevData::addTag("program"); + cdevData::addTag("commandline"); + cdevData::addTag("starttime"); + cdevData::addTag("connecttime"); + cdevData::addTag("host"); + cdevData::addTag("os"); + cdevData::addTag("osrelease"); + cdevData::addTag("osversion"); + cdevData::addTag("machine"); + cdevData::addTag("shell"); + cdevData::addTag("sendPktCnt"); + cdevData::addTag("recvPktCnt"); + cdevData::addTag("socket"); + + #ifndef _WIN32 + struct utsname hostinfo; + struct group * grp; + char * shell = getenv("SHELL"); + + uname(&hostinfo); + grp = getgrgid(getgid()); + + data.insert("username", getlogin()); + data.insert("group", grp?grp->gr_name:(char *)"UNDEFINED"); + data.insert("uid", (unsigned)getuid()); + data.insert("gid", (unsigned)getgid()); + data.insert("pid", (unsigned)getpid()); + data.insert("host", hostinfo.nodename); + data.insert("os", hostinfo.sysname); + data.insert("osrelease", hostinfo.release); + data.insert("osversion", hostinfo.version); + data.insert("machine", hostinfo.machine); + data.insert("shell", shell?shell:(char *)"UNDEFINED"); + + #if defined(__hpux) + struct pst_status pstatData; + pstat_getproc(&pstatData, sizeof(pstatData), 0, (int)getpid()); + data.insert("program", pstatData.pst_ucomm); + data.insert("commandline", pstatData.pst_cmd); + data.insert("starttime", pstatData.pst_start); + #endif + #else + char userNameBuf[UNLEN+1]; + unsigned long userNameLen = UNLEN; + char hostNameBuf[MAXHOSTNAMELEN+1]; + unsigned long hostNameLen = MAXHOSTNAMELEN; + + *userNameBuf = 0; + *hostNameBuf = 0; + + data.insert("pid", GetCurrentProcessId()); + if(GetUserName (userNameBuf, &userNameLen)) data.insert("username", userNameBuf); + if(GetComputerName(hostNameBuf, &hostNameLen)) data.insert("host", hostNameBuf); + + if(userNameBuf && hostNameBuf) + { + char grpNameBuf[GNLEN+1]; + unsigned long grpNameLen = GNLEN; + char sidBuf[256]; + unsigned long sidLen = 256; + SID_NAME_USE sidType; + + *grpNameBuf = 0; + if(LookupAccountName(hostNameBuf, userNameBuf, + sidBuf, &sidLen, grpNameBuf, + &grpNameLen, &sidType)) + { + data.insert("group", grpNameBuf); + } + } + + OSVERSIONINFO osv; + osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if(GetVersionEx (&osv)) + { + char osVersionBuf[64]; + switch(osv.dwPlatformId) + { + case VER_PLATFORM_WIN32s: + data.insert("os", "WINDOWS"); + break; + + case VER_PLATFORM_WIN32_WINDOWS: + if(osv.dwMinorVersion == 0) + data.insert("os", "WINDOWS 95"); + else data.insert("os", "WINDOWS 98"); + break; + + case VER_PLATFORM_WIN32_NT: + data.insert("os", "WINDOWS NT"); + break; + + default: + data.insert("os", "WIN32"); + break; + } + sprintf(osVersionBuf, "%d.%d", osv.dwMajorVersion, osv.dwMinorVersion); + data.insert("osversion", osVersionBuf); + data.insert("osrelease", ltoa(osv.dwBuildNumber)); + } + + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + switch(sysinfo.wProcessorArchitecture) + { + case PROCESSOR_ARCHITECTURE_INTEL: + data.insert("machine", "PROCESSOR_ARCHITECTURE_INTEL"); + break; + + case PROCESSOR_ARCHITECTURE_MIPS: + data.insert("machine", "PROCESSOR_ARCHITECTURE_MIPS"); + break; + + case PROCESSOR_ARCHITECTURE_ALPHA: + data.insert("machine", "PROCESSOR_ARCHITECTURE_ALPHA"); + break; + + case PROCESSOR_ARCHITECTURE_PPC: + data.insert("machine", "PROCESSOR_ARCHITECTURE_PPC"); + break; + + case PROCESSOR_ARCHITECTURE_UNKNOWN: + default: + data.insert("machine", "PROCESSOR_ARCHITECTURE_UNKNOWN"); + break; + } + + if(__argc>0) + { + int i; + char * cmdLine = NULL; + size_t cmdLineLen = 0; + + data.insert("program", __argv[0]); + for(i=0; i<__argc; i++) cmdLineLen+=strlen(__argv[i])+1; + cmdLine = new char [cmdLineLen]; + *cmdLine = 0; + for(i=0; i<__argc; i++) + { + strcat(cmdLine, __argv[i]); + if(i+1<__argc) strcat(cmdLine, " "); + } + data.insert("commandline", cmdLine); + } + FILETIME startTime; + FILETIME exitTime; + FILETIME kernelTime; + FILETIME userTime; + if(GetProcessTimes(GetCurrentProcess(), &startTime, &exitTime, &kernelTime, &userTime)) + { + struct timeval tv; + FileTimeToTimeVal(&startTime, &tv); + data.insert("starttime", tv.tv_sec); + } + #endif + } + + cdevData & getClientData ( void ) { return data; } + + void asciiDump ( FILE * fp = stdout ) + { + fprintf(fp, "--------------------------------------------------------\n"); + fprintf(fp, " Printing Client Information\n"); + fprintf(fp, "--------------------------------------------------------\n"); + + char * username; + char * group; + unsigned pid; + unsigned gid; + unsigned uid; + char * host; + char * os; + char * osrelease; + char * osversion; + char * machine; + char * shell; + char * program; + char * commandline; + long starttime; + + if(data.find("username", (void * &)username)!=CDEV_SUCCESS) username = NULL; + if(data.find("group", (void * &)group)!=CDEV_SUCCESS) group = NULL; + if(data.find("host", (void * &)host)!=CDEV_SUCCESS) host = NULL; + if(data.find("os", (void * &)os)!=CDEV_SUCCESS) os = NULL; + if(data.find("osrelease", (void * &)osrelease)!=CDEV_SUCCESS) osrelease = NULL; + if(data.find("osversion", (void * &)osversion)!=CDEV_SUCCESS) osversion = NULL; + if(data.find("machine", (void * &)machine)!=CDEV_SUCCESS) machine = NULL; + if(data.find("shell", (void * &)shell)!=CDEV_SUCCESS) shell=NULL; + if(data.find("program", (void * &)program)!=CDEV_SUCCESS) program=NULL; + if(data.find("commandline", (void * &)commandline)!=CDEV_SUCCESS) commandline=NULL; + if(data.get("starttime", &starttime)!=CDEV_SUCCESS) starttime = 0; + if(data.get("pid", &pid)!=CDEV_SUCCESS) pid = 0; + if(data.get("gid", &gid)!=CDEV_SUCCESS) gid = 0; + if(data.get("uid", &uid)!=CDEV_SUCCESS) uid = 0; + + fprintf(fp, "=> USERNAME : %s\n", username?username:"UNDEFINED"); + fprintf(fp, "=> GROUP : %s\n", group?group:"UNDEFINED"); + fprintf(fp, "=> USER ID : %s\n", uid?ltoa(uid):"UNDEFINED"); + fprintf(fp, "=> GROUP ID : %s\n", gid?ltoa(gid):"UNDEFINED"); + fprintf(fp, "=> PROCESS ID : %s\n", pid?ltoa(pid):"UNDEFINED"); + fprintf(fp, "=> APPLICATION : %s\n", program?program:"UNDEFINED"); + fprintf(fp, "=> COMMAND LINE : %s\n", commandline?commandline:"UNDEFINED"); + fprintf(fp, "=> START TIME : %s", starttime?ctime(&starttime):"UNKNOWN\n"); + fprintf(fp, "=> HOST NAME : %s\n", host?host:"UNKNOWN"); + fprintf(fp, "=> OS : %s\n", os?os:"UNKNOWN"); + fprintf(fp, "=> OS VERSION : %s\n", osversion?osversion:"UNKNOWN"); + fprintf(fp, "=> OS RELEASE : %s\n", osrelease?osrelease:"UNKNOWN"); + fprintf(fp, "=> HARDWARE ID : %s\n", machine?machine:"UNKNOWN"); + fprintf(fp, "--------------------------------------------------------\n"); + } +}; diff --git a/extensions/cdevGenericServer/include/ErrorReporter.h b/extensions/cdevGenericServer/include/ErrorReporter.h new file mode 100644 index 0000000..ea00704 --- /dev/null +++ b/extensions/cdevGenericServer/include/ErrorReporter.h @@ -0,0 +1,49 @@ +#ifndef _ERROR_REPORTER_H_ +#define _ERROR_REPORTER_H_ 1 + +#include + +#ifndef _NO_CDEV_SYSTEM_ + #include + #include +#else + #include + #ifndef CDEV_SEVERITY_INFO /* cdevError class severity codes */ + #define CDEV_SEVERITY_INFO 0 /* informative message */ + #define CDEV_SEVERITY_WARN 1 /* warning message */ + #define CDEV_SEVERITY_ERROR 2 /* error message */ + #define CDEV_SEVERITY_SEVERE 3 /* severe or fatal error message */ + #endif +#endif + +class GENERIC_SERVER_API ErrorReporter +{ +public: + ErrorReporter ( void ) {} + virtual ~ErrorReporter ( void ) {} + virtual int outputError ( int severity, char *name, char *formatString, ... ) + { + int result = 0; + + va_list argp; + va_start (argp, formatString); + + #ifndef _NO_CDEV_SYSTEM_ + result = cdevSystem::defaultSystem().vreportError(severity, name, NULL, formatString, argp); + #else + fprintf(stdout,"%s %s: ", + name, + (severity==CDEV_SEVERITY_INFO?"Information": + (severity==CDEV_SEVERITY_WARN?"Warning": + (severity==CDEV_SEVERITY_ERROR?"Error": + (severity==CDEV_SEVERITY_SEVERE?"Severe Error": + "Event"))))); + vfprintf(stdout, formatString, argp); + fprintf (stdout, "\n"); + #endif + va_end(argp); + return result; + } +}; + +#endif /* _ERROR_REPORTER_H_ */ diff --git a/extensions/cdevGenericServer/include/FD_Trigger.h b/extensions/cdevGenericServer/include/FD_Trigger.h new file mode 100644 index 0000000..b19eccc --- /dev/null +++ b/extensions/cdevGenericServer/include/FD_Trigger.h @@ -0,0 +1,192 @@ +#ifndef _FD_TRIGGER_H_ +#define _FD_TRIGGER_H_ 1 + +#include + +// ***************************************************************************** +// * FD_Trigger : +// * This class provides a method for triggering events based on file +// * descriptor activity. +// ***************************************************************************** +class FD_Trigger +{ +private: + enum {READ=0, WRITE=1}; + int sockPair[2]; + +#ifndef _WIN32 + char cbuf[100]; +#endif + +public: + FD_Trigger ( void ); + ~FD_Trigger ( void ); + int insertEvent ( int numEvents = 1 ); + int removeEvent ( int numEvents = 1 ); + void purge ( void ); + int writefd ( void ) const; + int readfd ( void ) const; +}; + + +// ***************************************************************************** +// * FD_Trigger::FD_Trigger : +// * Constructor for the FD_Trigger class. +// ***************************************************************************** +inline FD_Trigger::FD_Trigger ( void ) + { + if(pipe(sockPair)!=0) + { + sockPair[READ] = -1; + sockPair[WRITE] = -1; + } + #ifndef _WIN32 + else + { + int val; + + val = ::fcntl(sockPair[READ], F_GETFL, 0); + if(val>0) ::fcntl(sockPair[READ], F_SETFL, val|O_NONBLOCK); + + val = ::fcntl(sockPair[WRITE], F_GETFL, 0); + if(val>0) ::fcntl(sockPair[WRITE], F_SETFL, val|O_NONBLOCK); + + memset(cbuf, '1', 100); + } + #endif + } + + + +// ***************************************************************************** +// * FD_Trigger::~FD_Trigger : +// * Destructor for the FD_Trigger class. +// ***************************************************************************** +inline FD_Trigger::~FD_Trigger ( void ) + { + if(sockPair[READ] != -1) close(sockPair[READ]); + if(sockPair[WRITE] != -1) close(sockPair[WRITE]); + } + + + +// ***************************************************************************** +// * FD_Trigger::insertEvent : +// * Adds one or more bytes (indicating events) to the pipe +// ***************************************************************************** +inline int FD_Trigger::insertEvent ( int numEvents ) + { + if(sockPair[WRITE]>0) + { + int count = 0; + + #ifdef _WIN32 + char cptr = 1; + + while(count++0) + { + write(sockPair[WRITE], cbuf, min(100, count)); + count-=100; + } + #endif + } + return (sockPair[WRITE]>0)?0:-1; + } + + + +// ***************************************************************************** +// * FD_Trigger::removeEvent : +// * Removes one or more bytes (indicating events) from the pipe. +// ***************************************************************************** +inline int FD_Trigger::removeEvent ( int numEvents ) + { + int retval = 0; + + if(sockPair[READ]>0) + { + int count = 0; + + #ifdef _WIN32 + char cptr = 0; + + while(count0 || + WSAGetLastError()==WSAEMSGSIZE)) + { + count++; + } + if(count==0) retval = -1; + + #else + if(ioctl(sockPair[READ], FIONREAD, &count)<0 || count==0) + { + retval = -1; + } + else + { + if(numEvents>count) numEvents = count; + while(numEvents>0) + { + read(sockPair[READ], cbuf, min(100, numEvents)); + numEvents-=100; + } + } + #endif + } + else retval = -1; + + return retval; + } + + + +// ***************************************************************************** +// * FD_Trigger::purge : +// * This function removes all bytes from the pipe. +// ***************************************************************************** +inline void FD_Trigger::purge ( void ) + { + if(sockPair[READ]>0) + { + #ifdef _WIN32 + char cptr = 0; + while(recv(sockPair[READ], &cptr, 1, 0)>0 || WSAGetLastError()==WSAEMSGSIZE); + #else + int count = 0; + ioctl(sockPair[READ], FIONREAD, &count); + while(count>0) + { + read(sockPair[READ], cbuf, min(100, count)); + count-=100; + } + #endif + } + } + + + +// ***************************************************************************** +// * FD_Trigger::writefd +// * Returns the write file descriptor associated with the pipe. +// ***************************************************************************** +inline int FD_Trigger::writefd ( void ) const + { + return sockPair[WRITE]; + } + + + +// ***************************************************************************** +// * FD_Trigger::readfd +// * Returns the read file descriptor associated with the pipe. +// ***************************************************************************** +inline int FD_Trigger::readfd ( void ) const + { + return sockPair[READ]; + } + +#endif /* _FD_TRIGGER_H_ */ diff --git a/extensions/cdevGenericServer/include/IntHash.h b/extensions/cdevGenericServer/include/IntHash.h new file mode 100644 index 0000000..8ccdbb0 --- /dev/null +++ b/extensions/cdevGenericServer/include/IntHash.h @@ -0,0 +1,204 @@ +#ifndef _INT_HASH_H_ +#define _INT_HASH_H_ 1 + +#include + +class GENERIC_SERVER_API IntHashNode +{ +friend class IntHash; +friend class IntHashIterator; + +private: + int hashInt; + void * hashData; + IntHashNode * next; + + IntHashNode ( int HashInt, void * HashData); + ~IntHashNode ( void ); +}; + + +class GENERIC_SERVER_API IntHash +{ +friend class IntHashIterator; + +private: + enum { HASH_CNT=256, HASH_NO=256 }; + + IntHashNode * nodes[HASH_CNT]; + +public: + IntHash ( void ); + ~IntHash ( void ); + + inline unsigned char hash ( int hashInt ); + + inline void insert ( int hashInt, void * hashData ); + inline void remove ( int hashInt ); + inline void * find ( int hashInt ); +}; + + +class GENERIC_SERVER_API IntHashIterator +{ +private: + IntHash * hashTbl; + IntHashNode * node; + int idx; + +public: + IntHashIterator( IntHash * HashTbl ); + ~IntHashIterator( void ); + + inline void * first ( void ); + inline void * operator ++ ( void ); + inline void * operator ++ ( int x ); + inline int key ( void ); + inline void * data ( void ); +}; + + + +inline IntHash::IntHash ( void ) + { + memset(nodes, 0, sizeof(nodes)); + } + + +inline IntHash::~IntHash ( void ) + { + for(int i=0; inext; + delete node; + } + } + } + +inline unsigned char IntHash::hash ( int hashInt ) + { + return (hashInt%HASH_NO); + } + +inline void IntHash::insert (int hashInt, void * hashData ) + { + unsigned char idx = hash(hashInt); + IntHashNode * prev = NULL, * node = nodes[idx]; + IntHashNode * newNode = new IntHashNode(hashInt, hashData); + + while(node!=NULL && node->hashInt!=hashInt) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + newNode->next = node->next; + delete node; + } + if(prev!=NULL) prev->next = newNode; + else nodes[idx] = newNode; + } + +inline void IntHash::remove ( int hashInt ) + { + unsigned char idx = hash(hashInt); + IntHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && node->hashInt!=hashInt) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + if(prev!=NULL) prev->next = node->next; + else nodes[idx] = node->next; + delete node; + } + } + +inline void * IntHash::find ( int hashInt ) + { + unsigned char idx = hash(hashInt); + IntHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && node->hashInt!=hashInt) + { + prev = node; + node = prev->next; + } + return node!=NULL?node->hashData:NULL; + } + + +inline IntHashIterator::IntHashIterator(IntHash * HashTbl) + : hashTbl(HashTbl), idx(0), node(NULL) + { + } + +inline IntHashIterator::~IntHashIterator( void ) + { + } + +inline void * IntHashIterator::first ( void ) + { + if(hashTbl!=NULL) + { + for(idx = 0; idxnodes[idx])==NULL; idx++); + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * IntHashIterator::operator ++ ( void ) + { + if(hashTbl!=NULL) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxnodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * IntHashIterator::operator ++ ( int x ) + { + if(hashTbl!=NULL && x==0) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxnodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline int IntHashIterator::key ( void ) + { + return (node!=NULL)?node->hashInt:0; + } + +inline void * IntHashIterator::data ( void ) + { + return (node!=NULL)?node->hashData:NULL; + } + +#endif /* _INT_HASH_H_ */ diff --git a/extensions/cdevGenericServer/include/LinkList.h b/extensions/cdevGenericServer/include/LinkList.h new file mode 100644 index 0000000..5d94f73 --- /dev/null +++ b/extensions/cdevGenericServer/include/LinkList.h @@ -0,0 +1,1091 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: General purpose linked list class with smart iterator. +// +// Author: Walt Akers +// +//----------------------------------------------------------------------------- + +#if !defined (_LINKED_LIST_H_) +#define _LINKED_LIST_H_ + +#include + +// ***************************************************************************** +// * class LinkedListDataDestructor : +// * This is a pure virtual base class that can be used to create a +// * destructor class for the data that is stored in the LinkedList class. +// * If a destructor class is specified, it can be called by the LinkedList +// * to delete the user defined data whenever it is removed from the list. +// ***************************************************************************** +class LinkedListDataDestructor +{ +public: + virtual void destroy ( void * data ) = 0; +}; + + +// ***************************************************************************** +// * class LinkedListDataConstructor : +// * This is a pure virtual class that can be used to create a constructor +// * class for data that is being stored in the LinkedList class. If this +// * constructor class is specified, then it will be called each time data +// * is added to the list in order to perform any user defined pre-processing +// * that is necessary. +// ***************************************************************************** +class LinkedListDataConstructor +{ +public: + virtual void * construct ( void * data ) = 0; +}; + + +// ***************************************************************************** +// * class LinkedList : +// * This is the storage class for the linked list, it will maintain a list +// * of data nodes and provide iterator objects to the developer upon +// * request. +// ***************************************************************************** +class LinkedList +{ +friend class LinkedListIterator; + +private: + // ********************************************************************* + // * class LinkedList::Node : + // * An embedded class that defines the storage structure for each + // * entity in the doubly-linked list. + // ********************************************************************* + class Node + { + public: + Node * prev; + Node * next; + void * data; + + Node ( void * Data = NULL ) + : prev(NULL), + next(NULL), + data(Data) + { + } + }; + + // ********************************************************************* + // * LinkedListDataDestructor * destructor: + // * This is a class that may be specified by the linked list user. + // * If specified, this method will be called by the linked list + // * any remove is called in order to delete the user data. If the + // * destructor is not specified, then the user provided data will + // * not be deleted. + // ********************************************************************* + LinkedListDataDestructor * destructor; + + // ********************************************************************* + // * LinkedListDataConstructor * constructor : + // * This is a class that contains a virtual construct method that + // * is called whenever new data is added to the linked list. This + // * construct method can do any preprocessing that of the data that + // * is desired by the user. + // ********************************************************************* + LinkedListDataConstructor * constructor; + + // ********************************************************************* + // * Node * head: + // * This item points to the first node in the list. It is NULL when + // * the class is created and is initialized when the first data item + // * is added to the list. + // ********************************************************************* + Node * head; + + // ********************************************************************* + // * Node * tail: + // * This item points to the last node in the list. It is NULL when + // * the class is created and is initailized and updated each time a + // * data item is added to the list. + // ********************************************************************* + Node * tail; + + // ********************************************************************* + // * LinkedListIterator * iterList; + // * This is a list of iterators that have been created to access + // * this list. + // ********************************************************************* + LinkedListIterator * iterList; + + // ********************************************************************* + // * size_t count + // * This is the total number of entries that are currently stored + // * in the linked list. + // ********************************************************************* + size_t count; + + // ********************************************************************* + // * LinkedList::remove : + // * This method is called by the LinkedListIterator in order to + // * remove an entry from the linked list. It will locate all + // * iterators that might be impacted by this change and will update + // * them appropriately. + // ********************************************************************* + inline int remove ( LinkedListIterator & iter ); + + // ********************************************************************* + // * LinkedList::append : + // * This method is called by the LinkedListIterator in order to + // * append a new entry to the linked list. + // * + // * Note that the newly appended entry will become the current entry + // * for this iterator. + // ********************************************************************* + inline int append ( LinkedListIterator & iter, LinkedList::Node & node ); + + // ********************************************************************* + // * LinkedList::insert : + // * This method is called by the LinkedListIterator to insert a + // * new entry above or below the current entry. It will locate all + // * iterators that might be impacted by this change and will update + // * them appropriately. + // * + // * Note that the iterator must be pointing to a valid entry or the + // * list must be empty in order for this to work. The newly + // * inserted entry will become the current entry for this iterator. + // ********************************************************************* + inline int insert ( LinkedListIterator & iter, LinkedList::Node & node, int above=1 ); + + // ********************************************************************* + // * LinkedList::reindex : + // * This is an emergency fall-back that should never be called. + // * This method will be executed if the indexing/count in the list + // * or any of its iterators becomes invalid... It will recount all + // * of the items in the list and then walk through each of the + // * iterators and update their internal indices. + // ********************************************************************* + inline void reindex ( void ); + +public: + // ********************************************************************* + // * LinkedList::LinkedList : + // * This is the constructor for the class, it initializes all + // * internal variables to there default values. + // ********************************************************************* + inline LinkedList ( void ); + + // ********************************************************************* + // * LinkedList::~LinkedList : + // * This is the destructor for the class, it deletes all nodes that + // * may have been created to store data. It will also invalidate + // * the listPtr for any existing iterators. This destructor will NOT + // * delete the data that is stored in the Nodes. + // ********************************************************************* + inline ~LinkedList ( void ); + + // ********************************************************************* + // * LinkedList::iterator : + // * This method will return a new linked list iterator that can + // * be used to traverse this list. + // ********************************************************************* + inline LinkedListIterator * iterator ( void ); + + // ********************************************************************* + // * LinkedList::setDestructor : + // * This inline method allows the caller to set the destructor that + // * will be used by the class to delete data. + // ********************************************************************* + inline void setDestructor ( LinkedListDataDestructor * Destructor = NULL ); + + // ********************************************************************* + // * LinkedList::setConstructor : + // * This method allows the caller to set the constructor that will + // * be used by the class to initialize inbound data. + // ********************************************************************* + inline void setConstructor ( LinkedListDataConstructor * Constructor = NULL ); +}; + + +// ***************************************************************************** +// * class LinkedListIterator : +// * This class is used to allow the caller to traverse the data in the +// * linked list class. +// ***************************************************************************** +class LinkedListIterator +{ +friend class LinkedList; + +private: + // ********************************************************************* + // * LinkedListIterator * next : + // * This entry allows the linked list to maintain a list of all + // * iterators that are in use. This list is used to update indices + // * when entries are deleted. + // ********************************************************************* + LinkedListIterator * nextIter; + + // ********************************************************************* + // * LinkedList * list : + // * This is the linked list that owns the iterator. + // ********************************************************************* + LinkedList * list; + + // ********************************************************************* + // * LinkedList::Node * node : + // * This is the current entry in the linked list. + // ********************************************************************* + LinkedList::Node * node; + + // ********************************************************************* + // * int index : + // * This is the index of the current entry in the list. Indexes + // * start at 0. + // ********************************************************************* + int index; + + // ********************************************************************* + // * LinkedListIterator::LinkedListIterator : + // * This is the constructor for the iterator. It is private to + // * prevent it from being instanciated directly. In order to obtain + // * a LinkedListIterator the developer must call the iterator method + // * of the LinkedList. + // * + // * This method will automatically position the developer at the + // * top of the linked list. + // ********************************************************************* + inline LinkedListIterator ( LinkedList * listPtr ); + +public: + // ********************************************************************* + // * LinkedListIterator::~LinkedListIterator : + // * This is the destructor for the iterator. The user must call + // * this method when the iterator is no longer needed. It will + // * remove itself from teh table of iterators registered with the + // * LinkedList prior to being deleted. + // ********************************************************************* + inline ~LinkedListIterator ( void ); + + // ********************************************************************* + // * LinkedListIterator::first : + // * This method will position the iterator to the top of the list + // * of entries in the linked list and set the index to 0. If the + // * linked list is empty, then the index will be set to -1 and the + // * node willbe set to NULL. + // ********************************************************************* + inline void first ( void ); + + // ********************************************************************* + // * LinkedListIterator::last : + // * This method will position the iterator to the bottom of the + // * list of entries and set the index to the appropriate + // * value (count-1). If the list is empty the index will be set to + // * -1 and the node will be set to NULL. + // ********************************************************************* + inline void last ( void ); + + // ********************************************************************* + // * LinkedListIterator::prev : + // * This method will position the iterator to the previous entry + // * in the list. + // * + // * If the iterator is already at the top of the list or the list is + // * empty, then a -1 will be returned and the current entry will be + // * marked as invalid. + // * + // * If the iterator is passed the bottom of the list, this method + // * will reposition to the tail. + // * + // * On success a value of 0 is returned. + // ********************************************************************* + inline int prev ( void ); + + // ********************************************************************* + // * LinkedListIterator::next : + // * This method will position the iterator to the next entry in the + // * list. + // * + // * If the iterator is already at the bottom of the list or the list + // * is empty, then a -1 will be returned and the current entry will + // * be marked as invalid. + // * + // * If the iterator is above the top of the list, this method + // * will reposition to the head. + // * + // * On success a value of 0 is returned. + // ********************************************************************* + inline int next ( void ); + + // ********************************************************************* + // * LinkedListIterator::remove : + // * This method is called to remove the current entry from the + // * linked list. It will return 0 if the entry is successful + // * removed, or -1 if an error occurs. + // ********************************************************************* + inline int remove ( void ); + + // ********************************************************************* + // * LinkedListIterator::append : + // * This method is called to append an entry to the bottom of the + // * list. It will return 0 if the entry is successfully added, or + // * -1 if an error occurs. + // ********************************************************************* + inline int append ( void * data ); + + // ********************************************************************* + // * LinkedListIterator::insert : + // * This method is called to insert a new entry at the current + // * position in the linked list. It will return 0 on success, or + // * -1 if an error occurs. + // * + // * The above flag (TRUE by default) indicates that the new entry + // * should be inserted above or below the current entry. + // ********************************************************************* + inline int insert ( void * data, int above = 1 ); + + // ********************************************************************* + // * LinkedListIterator::replace : + // * This method will replace the data in the current node with the + // * user provided data. It is the responsibility of the user to + // * delete the old data if necessary. this method will return 0 + // * on success, or -1 if there is no current entry. + // ********************************************************************* + inline int replace ( void * data ); + + // ********************************************************************* + // * LinkedListIterator::isvalid : + // * This method allows the developer to determine if the iterator + // * is currently pointing at a valid entry. This method returns + // * 1 if the entry is valid or 0 if the entry is bogus. + // ********************************************************************* + inline int isvalid ( void ); + + // ********************************************************************* + // * LinkedListIterator::get_index : + // * This method returns the index of the current data item. If the + // * data item is invalid, then an index of -1 is returned. + // ********************************************************************* + inline int get_index ( void ); + + // ********************************************************************* + // * LinkedListIterator::get_count : + // * This method will return the total number of entries in the list. + // ********************************************************************* + inline int get_count ( void ); + + // ********************************************************************* + // * LinkedListIterator::get_value : + // * This method returns the value of the current entry in the list. + // * If the current entry is invalid, a value of NULL is returned. + // ********************************************************************* + inline void * get_value ( void ); + + // ********************************************************************* + // * LinkedListIterator::operator []; + // * This method returns the value of the entry in the list at the + // * specified index. If the index is out of range, then a value + // * of NULL will be returned. + // * + // * Note that the index operator cannot be used to replace the + // * pointer used by the list. Use the replace method to install + // * a new pointer. + // ********************************************************************* + inline void * operator [] ( size_t idx ); +}; + + +// ***************************************************************************** +// * LinkedList::remove : +// * This method is called by the LinkedListIterator in order to +// * remove an entry from the linked list. It will locate all +// * iterators that might be impacted by this change and will update +// * them appropriately. +// ***************************************************************************** +inline int LinkedList::remove ( LinkedListIterator & iter ) + { + int result; + + // ********************************************************************* + // * Check to make sure that the node contained in the iterator + // * is valid, that the iterator points to this list, and that + // * the iterator's index is in a valid range. + // ********************************************************************* + if(iter.node!=NULL && iter.list==this && + iter.index=0) + { + LinkedListIterator * iters; + Node * deadNode = iter.node; + Node * node = NULL; + int index = iter.index; + + // ************************************************************* + // * Identify the node that will take the place of the + // * deleted node and determine what its index will be. + // * By default, the replacement node will be the + // * previous node when possible or the next node if + // * the head node is deleted. + // ************************************************************* + if(deadNode->prev!=NULL) + { + node = deadNode->prev; + index--; + } + else node = deadNode->next; + + // ************************************************************* + // * Ensure that the head and tail are correct. + // ************************************************************* + if(deadNode->prev==NULL) head = deadNode->next; + if(deadNode->next==NULL) tail = deadNode->prev; + + // ************************************************************* + // * Update the pointers on the nodes surrounding the node to + // * be removed... + // ************************************************************* + if(deadNode->next) deadNode->next->prev = deadNode->prev; + if(deadNode->prev) deadNode->prev->next = deadNode->next; + + // ************************************************************* + // * Walk through the list of all iterators and update + // * them. If an iterator points to the deleted node, + // * then it will be updated with the replacement node + // * and index as determined above. If a iterator has + // * a node that occurs later in the list, then its + // * index will be decremented to indicate its new + // * position. + // ************************************************************* + for(iters=iterList; iters!=NULL; iters=iters->nextIter) + { + if(iters->node==NULL) + { + continue; + } + else if (head==NULL) + { + iters->node = NULL; + iters->index = -1; + } + else if(iters->node==deadNode) + { + iters->node = node; + iters->index = index; + } + else if(iters->index > index) + { + iters->index--; + } + } + + // ************************************************************* + // * Delete the old node and decrement the count. Note, + // * this approach WILL NOT delete the data that is + // * associated with the entry... the developer is + // * responsible for deleting the data. + // ************************************************************* + if(destructor) destructor->destroy(deadNode->data); + delete deadNode; + count--; + result = 0; + } + else result = -1; + + return result; + } + +// ***************************************************************************** +// * LinkedList::append : +// * This method is called by the LinkedListIterator in order to +// * append a new entry to the linked list. +// * +// * Note that the newly appended entry will become the current entry +// * for this iterator. +// ***************************************************************************** +inline int LinkedList::append ( LinkedListIterator & iter, LinkedList::Node & node ) + { + int result; + + // ********************************************************************* + // * If a constructor class has been specified, use the construct method + // * to pre-process the data. + // ********************************************************************* + if(constructor!=NULL) node.data = constructor->construct(node.data); + + // ********************************************************************* + // * Ensure that the iterator points to the current list and + // * then append the entry to the end of the list and increment + // * the count. + // ********************************************************************* + if(iter.list == this) + { + int index = count++; + + node.prev = tail; + node.next = NULL; + if(tail!=NULL) tail->next = &node; + if(head==NULL) head = &node; + tail = &node; + + iter.node = &node; + iter.index = index; + + result = 0; + } + else result = -1; + + return result; + } + +// ***************************************************************************** +// * LinkedList::insert : +// * This method is called by the LinkedListIterator to insert a +// * new entry above or below the current entry. It will locate all +// * iterators that might be impacted by this change and will update +// * them appropriately. +// * +// * Note that the iterator must be pointing to a valid entry or the +// * list must be empty in order for this to work. The newly +// * inserted entry will become the current entry for this iterator. +// ***************************************************************************** +inline int LinkedList::insert ( LinkedListIterator & iter, LinkedList::Node & node, int above ) + { + int result; + + // ********************************************************************* + // * If a constructor class has been specified, use the construct method + // * to pre-process the data. + // ********************************************************************* + if(constructor!=NULL) node.data = constructor->construct(node.data); + + // ********************************************************************* + // * If there are no entries in the list, then use the append + // * method to add the new entry to the head of the list. + // ********************************************************************* + if(iter.list == this && count==0) + { + result = append(iter, node); + } + // ********************************************************************* + // * If the iterator points to this list and the insertion point + // * is not NULL, then attempt to insert the entry. + // ********************************************************************* + else if(iter.list == this && iter.node!=NULL) + { + LinkedListIterator * iters; + int index = iter.index; + + // ************************************************************* + // * Insert the entry above or below the current entry. + // * If the new node is inserted below the current + // * entry, then the index must be incremented to + // * reflect its new position. + // ************************************************************* + if(above) + { + if((node.prev = iter.node->prev)!=NULL) + node.prev->next = &node; + if((node.next = iter.node)!=NULL) + node.next->prev = &node; + } + else { + if((node.next = iter.node->next)!=NULL) + node.next->prev = &node; + if((node.prev = iter.node)!=NULL) + node.prev->next = &node; + index++; + } + + // ************************************************************* + // * If the new entry occupies the head or tail position + // * in the list, then update these variables to reflect + // * its position. + // ************************************************************* + if(node.prev==NULL) head = &node; + if(node.next==NULL) tail = &node; + + // ************************************************************* + // * Walk through the list and increment the indexes of + // * any iterator that contains a node that occurs later + // * in the list than the new node. + // ************************************************************* + for(iters=iterList; iters!=NULL; iters=iters->nextIter) + { + if(iters->node==NULL) + { + continue; + } + else if(iters->index >= index) + { + iters->index++; + } + } + + // ************************************************************* + // * Update the user provided iterator to point to the + // * newly inserted node and its correct index and + // * increment the count. + // ************************************************************* + iter.node = &node; + iter.index = index; + count++; + result = 0; + } + else result = -1; + + return result; + } + +// ***************************************************************************** +// * LinkedList::reindex : +// * This is an emergency fall-back that should never be called. +// * This method will be executed if the indexing/count in the list +// * or any of its iterators becomes invalid... It will recount all +// * of the items in the list and then walk through each of the +// * iterators and update their internal indices. +// ***************************************************************************** +inline void LinkedList::reindex ( void ) + { + LinkedListIterator * iters; + Node * node = head; + + for(count = 0; node!=NULL; node=node->next) count++; + for(iters=iterList; iters!=NULL; iters = iters->nextIter) + { + if(iters->node!=NULL) + { + for(iters->index=0, node=head; + node!=NULL && node!=iters->node; + node=node->next) + { + iters->index++; + } + if(node==NULL) + { + iters->node = NULL; + iters->index = 0; + } + } + } + } + +// ***************************************************************************** +// * LinkedList::LinkedList : +// * This is the constructor for the class, it initializes all +// * internal variables to there default values. +// ***************************************************************************** +inline LinkedList::LinkedList ( void ) + : head(NULL), tail(NULL), iterList(NULL), count(0), + constructor(NULL), destructor(NULL) + { + } + + +// ***************************************************************************** +// * LinkedList::~LinkedList : +// * This is the destructor for the class, it deletes all nodes that +// * may have been created to store data. It will also invalidate +// * the listPtr for any existing iterators. This destructor will NOT +// * delete the data that is stored in the Nodes. +// ***************************************************************************** +inline LinkedList::~LinkedList ( void ) + { + Node * curr; + while(head!=NULL) + { + curr = head; + head = curr->next; + if(destructor) destructor->destroy(curr->data); + delete curr; + } + + while(iterList!=NULL) + { + iterList->list = NULL; + iterList->node = NULL; + iterList = iterList->nextIter; + } + } + +// ***************************************************************************** +// * LinkedList::iterator : +// * This method will return a new linked list iterator that can +// * be used to traverse this list. +// ***************************************************************************** +inline LinkedListIterator * LinkedList::iterator ( void ) + { + LinkedListIterator * iter = new LinkedListIterator(this); + iter->nextIter = iterList; + iterList = iter; + return iter; + } + +// ***************************************************************************** +// * LinkedList::setDestructor : +// * This inline method allows the caller to set the destructor that +// * will be used by the class to delete data. +// ***************************************************************************** +inline void LinkedList::setDestructor ( LinkedListDataDestructor * Destructor) + { + destructor = Destructor; + } + +// ***************************************************************************** +// * LinkedList::setConstructor : +// * This method allows the caller to set the constructor that will +// * be used by the class to initialize inbound data. +// ***************************************************************************** +inline void LinkedList::setConstructor ( LinkedListDataConstructor * Constructor) + { + constructor = Constructor; + } + +// ***************************************************************************** +// * LinkedListIterator::LinkedListIterator : +// * This is the constructor for the iterator. It is private to +// * prevent it from being instanciated directly. In order to obtain +// * a LinkedListIterator the developer must call the iterator method +// * of the LinkedList. +// * +// * This method will automatically position the developer at the +// * top of the linked list. +// ***************************************************************************** +inline LinkedListIterator::LinkedListIterator ( LinkedList * listPtr ) + : nextIter(NULL), list(listPtr), node(NULL), index(-1) + { + first(); + } + +// ***************************************************************************** +// * LinkedListIterator::~LinkedListIterator : +// * This is the destructor for the iterator. The user must call +// * this method when the iterator is no longer needed. It will +// * remove itself from teh table of iterators registered with the +// * LinkedList prior to being deleted. +// ***************************************************************************** +inline LinkedListIterator::~LinkedListIterator ( void ) + { + LinkedListIterator * curr, * prev = NULL; + + for(curr=list->iterList; curr!=this; curr=curr->nextIter) prev = curr; + if(curr!=NULL) + { + if(prev) prev->nextIter = curr->nextIter; + else list->iterList = curr->nextIter; + } + } + +// ***************************************************************************** +// * LinkedListIterator::first : +// * This method will position the iterator to the top of the list +// * of entries in the linked list and set the index to 0. If the +// * linked list is empty, then the index will be set to -1 and the +// * node willbe set to NULL. +// ***************************************************************************** +inline void LinkedListIterator::first ( void ) + { + node = list->head; + index = node?0:-1; + } + +// ***************************************************************************** +// * LinkedListIterator::last : +// * This method will position the iterator to the bottom of the +// * list of entries and set the index to the appropriate +// * value (count-1). If the list is empty the index will be set to +// * -1 and the node will be set to NULL. +// ***************************************************************************** +inline void LinkedListIterator::last ( void ) + { + node = list->tail; + index = node?list->count-1:-1; + } + +// ***************************************************************************** +// * LinkedListIterator::prev : +// * This method will position the iterator to the previous entry +// * in the list. +// * +// * If the iterator is already at the top of the list or the list is +// * empty, then a -1 will be returned and the current entry will be +// * marked as invalid. +// * +// * If the iterator is passed the bottom of the list, this method +// * will reposition to the tail. +// * +// * On success a value of 0 is returned. +// ***************************************************************************** +inline int LinkedListIterator::prev ( void ) + { + int result; + + if(node!=NULL && node->prev!=NULL) + { + node = node->prev; + index--; + result = 0; + } + else if (node==NULL && index==INT_MAX) + { + last(); + result = isvalid()?0:-1; + } + else { + node = NULL; + index = -1; + result = -1; + } + + return result; + } + +// ***************************************************************************** +// * LinkedListIterator::next : +// * This method will position the iterator to the next entry in the +// * list. +// * +// * If the iterator is already at the bottom of the list or the list +// * is empty, then a -1 will be returned and the current entry will +// * be marked as invalid. +// * +// * If the iterator is above the top of the list, this method +// * will reposition to the head. +// * +// * On success a value of 0 is returned. +// ***************************************************************************** +inline int LinkedListIterator::next ( void ) + { + int result; + + if(node!=NULL && node->next!=NULL) + { + node = node->next; + index++; + result = 0; + } + else if (node==NULL && index<0) + { + first(); + result = isvalid()?0:-1; + } + else { + node = NULL; + index = INT_MAX; + result = -1; + } + + return result; + } + +// ***************************************************************************** +// * LinkedListIterator::remove : +// * This method is called to remove the current entry from the +// * linked list. It will return 0 if the entry is successful +// * removed, or -1 if an error occurs. +// ***************************************************************************** +inline int LinkedListIterator::remove ( void ) + { + return list->remove(*this); + } + + +// ***************************************************************************** +// * LinkedListIterator::append : +// * This method is called to append an entry to the bottom of the +// * list. It will return 0 if the entry is successfully added, or +// * -1 if an error occurs. +// ***************************************************************************** +inline int LinkedListIterator::append ( void * data ) + { + int result; + + LinkedList::Node * newNode = new LinkedList::Node(data); + + if((result = list->append(*this, *newNode))!=0) + { + delete newNode; + } + return result; + } + +// ***************************************************************************** +// * LinkedListIterator::insert : +// * This method is called to insert a new entry at the current +// * position in the linked list. It will return 0 on success, or +// * -1 if an error occurs. +// * +// * The above flag (TRUE by default) indicates that the new entry +// * should be inserted above or below the current entry. +// ***************************************************************************** +inline int LinkedListIterator::insert ( void * data, int above ) + { + int result; + + LinkedList::Node * newNode = new LinkedList::Node(data); + + if((result = list->insert(*this, *newNode, above))!=0) + { + delete newNode; + } + return result; + } + +// ***************************************************************************** +// * LinkedListIterator::replace : +// * This method will replace the data in the current node with the +// * user provided data. It is the responsibility of the user to +// * delete the old data if necessary. this method will return 0 +// * on success, or -1 if there is no current entry. +// ***************************************************************************** +inline int LinkedListIterator::replace ( void * data ) + { + int result; + + if(node!=NULL) + { + if(list->destructor) list->destructor->destroy(node->data); + + if(list->constructor==NULL) node->data = data; + else node->data = list->constructor->construct(data); + + result = 0; + } + else result = -1; + + return result; + } + +// ***************************************************************************** +// * LinkedListIterator::isvalid : +// * This method allows the developer to determine if the iterator +// * is currently pointing at a valid entry. This method returns +// * 1 if the entry is valid or 0 if the entry is bogus. +// ***************************************************************************** +inline int LinkedListIterator::isvalid ( void ) + { + return node==NULL?0:1; + } + +// ***************************************************************************** +// * LinkedListIterator::get_index : +// * This method returns the index of the current data item. If the +// * data item is invalid, then an index of -1 is returned. +// ***************************************************************************** +inline int LinkedListIterator::get_index ( void ) + { + return (node && index>=0 && indexcount; + } + +// ***************************************************************************** +// * LinkedListIterator::get_value : +// * This method returns the value of the current entry in the list. +// * If the current entry is invalid, a value of NULL is returned. +// ***************************************************************************** +inline void * LinkedListIterator::get_value ( void ) + { + return node?node->data:NULL; + + } + +// ***************************************************************************** +// * LinkedList::operator []; +// * This method returns the value of the entry in the list at the +// * specified index. If the index is out of range, then a value +// * of NULL will be returned. +// * +// * Note that the index operator cannot be used to replace the +// * pointer used by the list. Use the replace method to install +// * a new pointer. +// ***************************************************************************** +inline void * LinkedListIterator::operator [] ( size_t idx ) + { + // ********************************************************************* + // * Ensure that the index is within range. + // ********************************************************************* + if(idxcount) + { + // ************************************************************* + // * If the desired position is above the current entry + // * reposition to it by going down from the top or + // * up from the current - whichever is a shorter trip. + // ************************************************************* + if(idxhead; + index = 0; + + while(index!=idx && node!=NULL) + { + node = node->next; + index++; + } + } + else { + while(index!=idx && node!=NULL) + { + node = node->prev; + index--; + } + } + } + // ************************************************************* + // * If the desired position is below the current entry + // * reposition to it by going up from the bottom or + // * down from the current - whichever is a shorter trip. + // ************************************************************* + else { + if(idx > list->count-idx-1) + { + node = list->tail; + index = list->count-1; + + while(index!=idx && node!=NULL) + { + node = node->prev; + index--; + } + } + else { + while(index!=idx && node!=NULL) + { + node = node->next; + index++; + } + } + } + + // ************************************************************* + // * If an error occurs, then it means that the indexing + // * has somehow become invalid. Set the node to NULL + // * and the index to -1 and recount the items in the + // * linked list... Logically, this should never + // * happen. + // ************************************************************* + if(node==NULL) + { + index = -1; + list->reindex(); + } + } + else { + node = NULL; + index = -1; + } + + return node?node->data:NULL; + } + + + +#endif /* _LINKED_LIST_H_ */ diff --git a/extensions/cdevGenericServer/include/MultiQueue.h b/extensions/cdevGenericServer/include/MultiQueue.h new file mode 100644 index 0000000..6a93d75 --- /dev/null +++ b/extensions/cdevGenericServer/include/MultiQueue.h @@ -0,0 +1,192 @@ +#ifndef __MULTIQUEUE_H_ +#define __MULTIQUEUE_H_ 1 + +#include +#include + +class MultiQueueBase +{ +private: + int nodeCount; + +public: + MultiQueueBase ( void ) { nodeCount = 0; } + + virtual void setTail ( void *tail ) = 0; + virtual int getCount ( void ) { return nodeCount; } + virtual int setCount ( int cnt ) { return (nodeCount = (cnt>=0?cnt:0)); } + virtual int incCount ( void ) { return (++nodeCount); } + virtual int decCount ( void ) { return (nodeCount=(nodeCount>0?nodeCount-1:0)); } +}; + + +template class MultiQueueNode +{ +private: + char * binary; + unsigned binaryLen; + +public: + class MultiQueueBase *queue[queueCount]; + class MultiQueueNode *prev [queueCount]; + class MultiQueueNode *next [queueCount]; + + MultiQueueNode(char * Binary=NULL, size_t BinaryLen=0) + : binary(Binary), binaryLen(BinaryLen) + { + memset(queue, 0, sizeof(class MultiQueueBase *)*queueCount); + memset(prev, 0, sizeof(class MultiQueueNode *)*queueCount); + memset(next, 0, sizeof(class MultiQueueNode *)*queueCount); + } + + virtual ~MultiQueueNode(void) + { + binary = NULL; + binaryLen = 0; + clear(); + } + + virtual void set ( char * Binary, size_t BinaryLen ) + { + binary = Binary; + binaryLen = BinaryLen; + } + + virtual void get ( char ** Binary, size_t * BinaryLen ) + { + *Binary = binary; + *BinaryLen = binaryLen; + } + + virtual void clear ( void ) + { + for(int i=0; inext[i] = next[i]; + if(next[i]) next [i]->prev[i] = prev[i]; + else if(queue[i]) queue[i]->setTail(prev[i]); + + if(queue[i]) queue[i]->decCount(); + + queue[i]=NULL; + prev[i] =NULL; + next[i] =NULL; + } + } +}; + + + +template class MultiQueue + : public MultiQueueBase +{ +private: + MultiQueueNode head; + MultiQueueNode * tail; + +public: + MultiQueue ( void ) + { + tail = NULL; + } + + virtual ~MultiQueue ( void ) + { + MultiQueueNode * node; + while((node=dequeue())!=NULL) delete node; + } + + virtual void setTail ( void * Tail ) + { + tail = (MultiQueueNode *)Tail; + } + + virtual int empty ( void ) { return (head.next[queueIndex]==NULL?1:0); } + + virtual void enqueue ( MultiQueueNode * node ) + { + if(node!=NULL) + { + if(head.next[queueIndex]==NULL) + { + head.next[queueIndex] = node; + node->prev[queueIndex] = &head; + } + else + { + tail->next[queueIndex] = node; + node->prev[queueIndex] = tail; + } + tail = node; + node->queue[queueIndex] = this; + node->queue[queueIndex]->incCount(); + } + } + + + virtual MultiQueueNode * peek ( void ) + { + return head.next[queueIndex]; + } + + virtual MultiQueueNode * dequeue ( void ) + { + MultiQueueNode * node = head.next[queueIndex]; + if(node!=NULL) node->clear(); + return node; + } + + virtual int peek ( char ** binary, size_t * binaryLen ) + { + int result = -1; + MultiQueueNode * node; + + if((node = peek())!=NULL) + { + node->get(binary, binaryLen); + if(*binary!=NULL && *binaryLen!=0) result = 0; + } + return result; + } + + virtual int dequeue ( char ** binary, size_t * binaryLen ) + { + int result = -1; + MultiQueueNode * node; + + *binary = NULL; + *binaryLen = 0; + + if((node = dequeue())!=NULL) + { + node->get(binary, binaryLen); + if(*binary!=NULL && *binaryLen!=0) result = 0; + delete node; + } + return result; + } + + virtual MultiQueueNode * localDequeue ( void ) + { + MultiQueueNode * node = head.next[queueIndex]; + if(node!=NULL) + { + if(node->prev[queueIndex]!=NULL) + node->prev[queueIndex]->next[queueIndex] = node->next[queueIndex]; + if(node->next[queueIndex]!=NULL) + node->next[queueIndex]->prev[queueIndex] = node->prev[queueIndex]; + else if(node->queue[queueIndex]!=NULL) + { + node->queue[queueIndex]->setTail(node->prev); + node->queue[queueIndex]->decCount(); + } + node->queue[queueIndex]=NULL; + node->next [queueIndex]=NULL; + node->prev [queueIndex]=NULL; + } + return node; + } +}; + +#endif /* __MULTIQUEUE_H_ */ + diff --git a/extensions/cdevGenericServer/include/ServerHandler.h b/extensions/cdevGenericServer/include/ServerHandler.h new file mode 100644 index 0000000..2b9d9c3 --- /dev/null +++ b/extensions/cdevGenericServer/include/ServerHandler.h @@ -0,0 +1,97 @@ +#if !defined (_SERVER_HANDLER_H_) +#define _SERVER_HANDLER_H_ + +// ***************************************************************************** +// * SIG_PIPE_HANDLED: +// * This definition tells the SocketWriter class not to independently +// * handle the SIGPIPE signal. +// ***************************************************************************** +#define SIG_PIPE_HANDLED 1 + +#include "cdevEventHandler.h" +#include "cdevAddr.h" +#include "cdevSocketConnector.h" +#include "cdevReactor.h" + +#include "SocketUtil.h" +#include "fifo.h" + +class ServerInterface; +class ServerHandlerCallbackNode; +class SignalManager; + +// ***************************************************************************** +// * ServerHandlerCallback : +// * This class is used by other classes to register to be informed when the +// * ServerHandler is destroyed. +// ***************************************************************************** +class GENERIC_SERVER_API ServerHandlerCallback +{ +public: + ServerHandlerCallback ( void ) {} + virtual ~ServerHandlerCallback ( void ) {} + virtual void executeServerHandlerCallback (class ServerHandler * handler) = 0; +}; + + +// ***************************************************************************** +// * ServerHandler: +// * This class provides the mechanisms that will be used to service the +// * requests of a client. +// ***************************************************************************** +class GENERIC_SERVER_API ServerHandler : public cdevEventHandler, + public SocketReader, + public SocketWriter +{ +protected: + static SignalManager signalManager; + static int signalManagerInit; + + char hostName [MAXHOSTNAMELEN + 1]; + char server [256]; + FifoQueue & queue; + cdevSocketConnector stream; + ServerInterface * serverface; + ServerHandlerCallbackNode * callbacks; + size_t enqueuedPackets; + size_t enqueuedBytes; + short clientID; + int contextID; + int tagChanged; + int serverQuitFlag; + +public: + ServerHandler (char * Server, ServerInterface * Interface); + ~ServerHandler (void); + virtual int outputError (int severity, char *name, char *formatString, ...); + + virtual int open (const cdevAddr &addr); + + char * getHostName (void); + char * getName (void) const; + virtual int getHandle (void) const; + virtual char * getServer (void) const; + + virtual int handleClose (void); + virtual int handleInput (void); + virtual int handleOutput (void); + virtual int handleExcept (void); + + virtual void registerServerCallback (ServerHandlerCallback *); + virtual void unregisterServerCallback (ServerHandlerCallback *); + + void enqueue (char * buf, size_t len); + void undequeue (char * buf, size_t len) { queue.undequeue(buf, len); } + int dequeue (char **buf, size_t *len) { return queue.dequeue(buf, len); } + int empty (void) { return queue.empty(); } + + static short getNextClientID ( void ); + short getClientID ( void ) { return clientID; } + void setClientID ( short ClientID ) { clientID=ClientID; } + int getContextID ( void ) { return contextID; } + void setContextID ( int ContextID ) { contextID = ContextID; } + int getTagChangeFlag ( void ) { return tagChanged; } + void setTagChangeFlag ( int flag ) { tagChanged = flag; } +}; + +#endif /* _SERVER_HANDLER_H_ */ diff --git a/extensions/cdevGenericServer/include/ServerInfo.h b/extensions/cdevGenericServer/include/ServerInfo.h new file mode 100644 index 0000000..8d50e5f --- /dev/null +++ b/extensions/cdevGenericServer/include/ServerInfo.h @@ -0,0 +1,280 @@ +#include +#include + +class ServerInfo +{ +friend class cdevServer; + +private: + cdevData data; + size_t sendPktCnt; + size_t recvPktCnt; + size_t clientCnt; + long pageSize; + +public: + ServerInfo ( char * domain, char * server, unsigned short port ) + : sendPktCnt(0), recvPktCnt(0), clientCnt(0), pageSize(0) + { + cdevData::addTag("username"); + cdevData::addTag("group"); + cdevData::addTag("uid"); + cdevData::addTag("gid"); + cdevData::addTag("pid"); + cdevData::addTag("program"); + cdevData::addTag("commandline"); + cdevData::addTag("starttime"); + cdevData::addTag("host"); + cdevData::addTag("server"); + cdevData::addTag("domain"); + cdevData::addTag("port"); + cdevData::addTag("os"); + cdevData::addTag("osrelease"); + cdevData::addTag("osversion"); + cdevData::addTag("machine"); + cdevData::addTag("shell"); + cdevData::addTag("sendPktCnt"); + cdevData::addTag("recvPktCnt"); + cdevData::addTag("clientCnt"); + cdevData::addTag("pctcpu"); + cdevData::addTag("datasize"); + cdevData::addTag("socket"); + + data.insert("server", server); + data.insert("domain", domain); + data.insert("port", port); + + #ifndef _WIN32 + struct utsname hostinfo; + struct group * grp; + char * shell = getenv("SHELL"); + + uname(&hostinfo); + grp = getgrgid(getgid()); + + data.insert("username", getlogin()); + data.insert("group", grp?grp->gr_name:(char *)"UNDEFINED"); + data.insert("uid", (unsigned)getuid()); + data.insert("gid", (unsigned)getgid()); + data.insert("pid", (unsigned)getpid()); + data.insert("host", hostinfo.nodename); + data.insert("os", hostinfo.sysname); + data.insert("osrelease", hostinfo.release); + data.insert("osversion", hostinfo.version); + data.insert("machine", hostinfo.machine); + data.insert("shell", shell?shell:(char *)"UNDEFINED"); + + #if defined(__hpux) + struct pst_status pstatData; + pstat_getproc(&pstatData, sizeof(pstatData), 0, (int)getpid()); + data.insert("program", pstatData.pst_ucomm); + data.insert("commandline", pstatData.pst_cmd); + data.insert("starttime", pstatData.pst_start); + + struct pst_static pstatStatic; + pstat_getstatic(&pstatStatic, sizeof(pstatStatic), 1, 0); + pageSize = pstatStatic.page_size; + #endif + #else + char userNameBuf[UNLEN+1]; + unsigned long userNameLen = UNLEN; + char hostNameBuf[MAXHOSTNAMELEN+1]; + unsigned long hostNameLen = MAXHOSTNAMELEN; + + *userNameBuf = 0; + *hostNameBuf = 0; + + data.insert("pid", getpid()); + if(GetUserName (userNameBuf, &userNameLen)) data.insert("username", userNameBuf); + if(GetComputerName(hostNameBuf, &hostNameLen)) data.insert("host", hostNameBuf); + + if(userNameBuf && hostNameBuf) + { + char grpNameBuf[GNLEN+1]; + unsigned long grpNameLen = GNLEN; + char sidBuf[256]; + unsigned long sidLen = 256; + SID_NAME_USE sidType; + + *grpNameBuf = 0; + if(LookupAccountName(hostNameBuf, userNameBuf, + sidBuf, &sidLen, grpNameBuf, + &grpNameLen, &sidType)) + { + data.insert("group", grpNameBuf); + } + } + + OSVERSIONINFO osv; + osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if(GetVersionEx (&osv)) + { + char osVersionBuf[64]; + switch(osv.dwPlatformId) + { + case VER_PLATFORM_WIN32s: + data.insert("os", "WINDOWS"); + break; + + case VER_PLATFORM_WIN32_WINDOWS: + if(osv.dwMinorVersion == 0) + data.insert("os", "WINDOWS 95"); + else data.insert("os", "WINDOWS 98"); + break; + + case VER_PLATFORM_WIN32_NT: + data.insert("os", "WINDOWS NT"); + break; + + default: + data.insert("os", "WIN32"); + break; + } + sprintf(osVersionBuf, "%d.%d", osv.dwMajorVersion, osv.dwMinorVersion); + data.insert("osversion", osVersionBuf); + data.insert("osrelease", ltoa(osv.dwBuildNumber)); + } + + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + switch(sysinfo.wProcessorArchitecture) + { + case PROCESSOR_ARCHITECTURE_INTEL: + data.insert("machine", "PROCESSOR_ARCHITECTURE_INTEL"); + break; + + case PROCESSOR_ARCHITECTURE_MIPS: + data.insert("machine", "PROCESSOR_ARCHITECTURE_MIPS"); + break; + + case PROCESSOR_ARCHITECTURE_ALPHA: + data.insert("machine", "PROCESSOR_ARCHITECTURE_ALPHA"); + break; + + case PROCESSOR_ARCHITECTURE_PPC: + data.insert("machine", "PROCESSOR_ARCHITECTURE_PPC"); + break; + + case PROCESSOR_ARCHITECTURE_UNKNOWN: + default: + data.insert("machine", "PROCESSOR_ARCHITECTURE_UNKNOWN"); + break; + } + + if(__argc>0) + { + int i; + char * cmdLine = NULL; + size_t cmdLineLen = 0; + + data.insert("program", __argv[0]); + for(i=0; i<__argc; i++) cmdLineLen+=strlen(__argv[i])+1; + cmdLine = new char [cmdLineLen]; + *cmdLine = 0; + for(i=0; i<__argc; i++) + { + strcat(cmdLine, __argv[i]); + if(i+1<__argc) strcat(cmdLine, " "); + } + data.insert("commandline", cmdLine); + } + + FILETIME startTime; + FILETIME exitTime; + FILETIME kernelTime; + FILETIME userTime; + if(GetProcessTimes(GetCurrentProcess(), &startTime, &exitTime, &kernelTime, &userTime)) + { + struct timeval tv; + FileTimeToTimeVal(&startTime, &tv); + data.insert("starttime", tv.tv_sec); + } + #endif + } + + cdevData & getServerData ( void ) + { + #if defined(__hpux) + struct pst_status pstatData; + pstat_getproc(&pstatData, sizeof(pstatData), 0, (int)getpid()); + data.insert("pctcpu", pstatData.pst_pctcpu); + data.insert("datasize", pageSize*(pstatData.pst_dsize+pstatData.pst_tsize+pstatData.pst_ssize)); + data.insert("sendPktCnt", sendPktCnt); + data.insert("recvPktCnt", recvPktCnt); + #endif + + return data; + } + + void asciiDump ( FILE * fp = stdout ) + { + fprintf(fp, "--------------------------------------------------------\n"); + fprintf(fp, " Printing Server Information\n"); + fprintf(fp, "--------------------------------------------------------\n"); + + char * server; + char * domain; + unsigned short port; + char * username; + char * group; + unsigned pid; + unsigned gid; + unsigned uid; + char * host; + char * os; + char * osrelease; + char * osversion; + char * machine; + char * shell; + char * program; + char * commandline; + long starttime; + size_t datasize; + float pctcpu; + + getServerData(); + + if(data.find("domain", (void *&)domain)!=CDEV_SUCCESS) host = NULL; + if(data.find("server", (void *&)server)!=CDEV_SUCCESS) server = NULL; + if(data.find("username", (void * &)username)!=CDEV_SUCCESS) username = NULL; + if(data.find("group", (void * &)group)!=CDEV_SUCCESS) group = NULL; + if(data.find("host", (void * &)host)!=CDEV_SUCCESS) host = NULL; + if(data.find("os", (void * &)os)!=CDEV_SUCCESS) os = NULL; + if(data.find("osrelease", (void * &)osrelease)!=CDEV_SUCCESS) osrelease = NULL; + if(data.find("osversion", (void * &)osversion)!=CDEV_SUCCESS) osversion = NULL; + if(data.find("machine", (void * &)machine)!=CDEV_SUCCESS) machine = NULL; + if(data.find("shell", (void * &)shell)!=CDEV_SUCCESS) shell=NULL; + if(data.find("program", (void * &)program)!=CDEV_SUCCESS) program=NULL; + if(data.find("commandline", (void * &)commandline)!=CDEV_SUCCESS) commandline=NULL; + if(data.get("port", &port)!=CDEV_SUCCESS) port = 0; + if(data.get("starttime", &starttime)!=CDEV_SUCCESS) starttime = 0; + if(data.get("pid", &pid)!=CDEV_SUCCESS) pid = 0; + if(data.get("gid", &gid)!=CDEV_SUCCESS) gid = 0; + if(data.get("uid", &uid)!=CDEV_SUCCESS) uid = 0; + if(data.get("datasize", &datasize)!=CDEV_SUCCESS) datasize = 0; + if(data.get("pctcpu", &pctcpu)!=CDEV_SUCCESS) pctcpu = (float)0.0; + + fprintf(fp, "=> DOMAIN : %s\n", domain?domain:"UNDEFINED"); + fprintf(fp, "=> SERVER : %s\n", server?server:"UNDEFINED"); + fprintf(fp, "=> LISTENING PORT : %s\n", port?ltoa(port):"UNDEFINED"); + fprintf(fp, "=> USERNAME : %s\n", username?username:"UNDEFINED"); + fprintf(fp, "=> GROUP : %s\n", group?group:"UNDEFINED"); + fprintf(fp, "=> USER ID : %s\n", uid?ltoa(uid):"UNDEFINED"); + fprintf(fp, "=> GROUP ID : %s\n", gid?ltoa(gid):"UNDEFINED"); + fprintf(fp, "=> PROCESS ID : %s\n", pid?ltoa(pid):"UNDEFINED"); + fprintf(fp, "=> APPLICATION : %s\n", program?program:"UNDEFINED"); + fprintf(fp, "=> COMMAND LINE : %s\n", commandline?commandline:"UNDEFINED"); + fprintf(fp, "=> START TIME : %s", starttime?ctime(&starttime):"UNKNOWN\n"); + fprintf(fp, "=> HOST NAME : %s\n", host?host:"UNKNOWN"); + fprintf(fp, "=> OS : %s\n", os?os:"UNKNOWN"); + fprintf(fp, "=> OS VERSION : %s\n", osversion?osversion:"UNKNOWN"); + fprintf(fp, "=> OS RELEASE : %s\n", osrelease?osrelease:"UNKNOWN"); + fprintf(fp, "=> HARDWARE ID : %s\n", machine?machine:"UNKNOWN"); + fprintf(fp, "=> PERCENT CPU : %f\n", pctcpu); + fprintf(fp, "=> RESIDENT SIZE : %i\n", datasize); + fprintf(fp, "=> PACKETS SENT : %i\n", sendPktCnt); + fprintf(fp, "=> PACKETS RECV : %i\n", recvPktCnt); + fprintf(fp, "=> ACTIVE CLIENTS : %i\n", clientCnt); + fprintf(fp, "--------------------------------------------------------\n"); + } +}; diff --git a/extensions/cdevGenericServer/include/ServerInterface.h b/extensions/cdevGenericServer/include/ServerInterface.h new file mode 100644 index 0000000..9830043 --- /dev/null +++ b/extensions/cdevGenericServer/include/ServerInterface.h @@ -0,0 +1,71 @@ +#ifndef _SERVER_INTERFACE_H_ +#define _SERVER_INTERFACE_H_ + +#include "cdevErrCode.h" +#include "ServerHandler.h" +#include "ErrorReporter.h" +#include "StringHash.h" +#include "fifo.h" +#include "cdevReactor.h" +#include "cdevEventHandler.h" +#include "cdevAddr.h" + +class GENERIC_SERVER_API ServerConnectionList +{ +private: + enum { ALLOCATION_COUNT = 32 }; + ServerHandler ** items; + int maxItems; + +public: + ServerConnectionList ( void ); + virtual ~ServerConnectionList ( void ); + + ServerHandler * find ( char * server ); + int insert ( ServerHandler * handler ); + int remove ( ServerHandler * handler ); + ServerHandler * remove ( char * server ); + + ServerHandler * operator [] ( int idx ) + { return (idx +#include +#include +#include + +typedef void (*SignalHandlerFunc)( int ); + +class GENERIC_SERVER_API _SignalHandler_ +{ +public: + _SignalHandler_ ( void ); + ~_SignalHandler_ ( void ); + void install ( int, SignalHandlerFunc); + void uninstall ( void ); + +private: + int signo; + SignalHandlerFunc handler; + SignalHandlerFunc oldHandler; +}; + +class GENERIC_SERVER_API SignalManager +{ +public: + static ErrorReporter reporter; + + void installHandler ( int, SignalHandlerFunc ); + void uninstallHandler ( int ); + void installDefaults ( void ); + + static void defaultHandler ( int ); + +private: + enum { MAXSIGNAL = 34 }; + _SignalHandler_ signals[MAXSIGNAL]; +}; + +#endif /* _SIGNAL_MANAGER_H_ */ diff --git a/extensions/cdevGenericServer/include/SocketUtil.h b/extensions/cdevGenericServer/include/SocketUtil.h new file mode 100644 index 0000000..e207388 --- /dev/null +++ b/extensions/cdevGenericServer/include/SocketUtil.h @@ -0,0 +1,545 @@ +#if !defined (_SOCKET_UTIL_H) +#define _SOCKET_UTIL_H + +#include +#include +#include + +class SocketReader : virtual public ErrorReporter +{ +public: + enum { SHUTDOWN_CODE = -128}; + enum { MAX_RETRIES = 1000 }; + enum { READBUF_INITIAL_SIZE = 56000 }; + + virtual int getHandle ( void ) const = 0; + + SocketReader ( long MagicNumber = 0L ); + ~SocketReader ( void ); + + int read ( char ** buf, int * len ); + virtual int readNextPacket ( char ** buf, int * len ); + virtual int reading ( void ); + virtual int readReset ( void ); + +private: + char * readBuf; + char * readNextPktPtr; + int readBufMax; + int readPktCnt; + int readPktXfrCnt; + + int readBufLen; + int readXfrLen; + int readPktXfrLen; + int readRetries; + + // *************************** + // * This section added to + // * optionally support magic + // * number for buffer + // * validation. + // *************************** + const long readMagicNumber; + int readMagicLen; + long readMagicVal; +}; + + +class SocketWriter : virtual public ErrorReporter +{ +public: + enum { WRITEBUF_INITIAL_SIZE = 56000 }; + enum { WRITEBUF_PAD_SIZE = 32 }; + + virtual int getHandle ( void ) const = 0; + + SocketWriter ( long MagicNumber = 0L ); + ~SocketWriter ( void ); + + int write ( char * buf, int buflen); + int writeEnqueue ( char * buf, int buflen); + virtual int writing ( void ); + virtual int writeContinue ( void ); + virtual int writeReset ( void ); + virtual int writeGoodbye ( void ); + +private: + char * writeBuf; + char * writeNextPktPtr; + int writeBufMax; + int writePktCnt; + + int writeBufLen; + int writeXfrLen; + int writePktXfrLen; + + // *************************** + // * This section added to + // * optionally support magic + // * number for buffer + // * validation. + // *************************** + const long writeMagicNumber; + int writeMagicLen; +}; + + +inline SocketReader::SocketReader ( long MagicNumber ) + : readBuf(NULL), readNextPktPtr(NULL), readBufMax(READBUF_INITIAL_SIZE), + readPktCnt(0), readPktXfrCnt(0), readBufLen(0), readXfrLen(0), + readPktXfrLen(0), readRetries(0), + // ************************* + // * Magic number support. + // ************************* + readMagicNumber(MagicNumber), readMagicLen(0), readMagicVal(0L) + { + readBuf = (char *)malloc(readBufMax); + readNextPktPtr = readBuf+RNDUP(sizeof(long)); + } + +inline SocketReader::~SocketReader ( void ) + { + if(readBuf!=NULL) free(readBuf); + } + +inline int SocketReader::reading ( void ) + { + return (readPktCnt>readPktXfrCnt)?1:0; + } + +inline int SocketReader::readReset ( void ) + { + readNextPktPtr = readBuf+RNDUP(sizeof(long)); + readBufLen = 0; + readXfrLen = 0; + readPktCnt = 0; + readPktXfrCnt = 0; + readPktXfrLen = 0; + readMagicLen = 0; + readMagicVal = 0L; + return 0; + } + +// ***************************************************************************** +// * This method causes the next available packet to be dequeued from the +// * already read buffer. +// ***************************************************************************** +inline int SocketReader::readNextPacket (char ** buf, int *buflen) + { + if(readPktCnt>readPktXfrCnt) + { + *buflen = (int)ntohl(*(long *)readNextPktPtr); + readNextPktPtr+=RNDUP(sizeof(long)); + *buf = readNextPktPtr; + readNextPktPtr+=RNDUP(*buflen); + readPktXfrCnt++; + } + else { + *buf = NULL; + *buflen = 0; + } + if(readPktXfrCnt>=readPktCnt) readReset(); + return *buflen; + } + + +// ***************************************************************************** +// * This method will get the next available packet from the socket. The caller +// * is responsible for transfering this data to a new location immediately. +// * The caller should not delete the pointer provided by this method, or rely +// * on it to remain valid between calls. +// ***************************************************************************** +inline int SocketReader::read(char ** buf, int * buflen) + { + int handle = getHandle(); + int result = 0; + int shutdown = 0; + int error = 0; + *buf = NULL; + *buflen = 0; + + // ********************************************************************* + // * First test to ensure that the socket is allocated and that the + // * device descriptor is valid. + // ********************************************************************* + if(handle<=0) result = -1; + // ********************************************************************* + // * If the handle is valid attempt to read the next packet of a + // * multi-packet set from an already existing buffer. + // ********************************************************************* + else if(reading()) result = readNextPacket(buf, buflen); + // ********************************************************************* + // * If all packets in the most recent multi-packet set have already + // * been read... Then attempt to read a new block from the socket. + // ********************************************************************* + else { + int amntread = 0; + char *readPtr = NULL; + + // ************************************************************* + // * Optionally read the magic number from the socket. + // ************************************************************* + readPtr = (char *)&readMagicVal; + while(readMagicNumber && readMagicLen0) + { + // ***************************************************** + // * Anytime a read is successful, set the readRetries + // * variable to 0. + // ***************************************************** + readRetries = 0; + // ***************************************************** + // * Once an entire long integer is read from the socket + // * validate that against the Magic Number that is + // * expected. + // ***************************************************** + if((readMagicLen += amntread)>=sizeof(long)) + { + readMagicVal = ntohl(readMagicVal); + + // ********************************************* + // * If the Magic Number received is not the + // * same as the Magic Number expected, set the + // * shutdown flag and kill the connection. + // ********************************************* + if(readMagicVal!=readMagicNumber) + { + outputError (CDEV_SEVERITY_ERROR, "SocketReader", + "Invalid magic number read from socket\n\t=> Expected %lX - received %lX", + readMagicNumber, readMagicVal); + shutdown = 1; + } + } + } + + // ************************************************************* + // * Read the size of the packet from the socket... note, this + // * code will not be executed until the Magic Number has been + // * successfully read. + // ************************************************************* + readPtr = (char *)&readBufLen; + while(!shutdown && readPktXfrLen=sizeof(long)) && + (amntread = recv(handle, + readPtr+readPktXfrLen, + sizeof(long)-readPktXfrLen, 0))>0) + { + // ***************************************************** + // * Anytime a read is successful, set the readRetries + // * variable to 0. + // ***************************************************** + readRetries = 0; + // ***************************************************** + // * Once an entire long integer is read from the socket + // * use that variable as the expected packet length, + // * and allocate a buffer of sufficient size to hold + // * the incoming packet. + // ***************************************************** + if((readPktXfrLen += amntread)>=sizeof(long)) + { + readBufLen = ntohl(readBufLen); + // ********************************************* + // * A length of -1 indicates that the socket + // * should be shutdown. + // ********************************************* + if(readBufLen == -1) shutdown = 1; + if(readBufLen <= 0) readReset(); + else { + if(readBufLen>readBufMax) + { + readBufMax = readBufLen; + readBuf = (char *)realloc(readBuf, readBufMax); + readNextPktPtr = readBuf+RNDUP(sizeof(long)); + } + readXfrLen = 0; + } + } + } + + // ************************************************************* + // * Continue reading from the socket into the new buffer until + // * the amount of data specified by the readBufLen variable + // * has been obtained, or no further data is available. + // ************************************************************* + while(!shutdown && + readPktXfrLen>=sizeof(long) && + readXfrLen < readBufLen && + (amntread = recv(handle, readBuf+readXfrLen, readBufLen-readXfrLen, 0))>0) + { + // ***************************************************** + // * Anytime a read is successful, set the readRetries + // * variable to 0. + // ***************************************************** + readRetries = 0; + + // ***************************************************** + // * Once a complete buffer of data has been read from + // * the socket, use the readNextPacket method to set + // * the user pointer to the appropriate position within + // * the data buffer. + // ***************************************************** + if((readXfrLen+=amntread)>=readBufLen) + { + readPktCnt = (int)ntohl(*(long *)readBuf); + result = readNextPacket(buf, buflen); + } + } + + // ************************************************************* + // * If an error occurred, or the function failed to read + // * data from the socket, then this section of code will be + // * executed. + // ************************************************************* + if(!shutdown && amntread<=0) + { + int errCode = GetSocketErrno(); + + // ***************************************************** + // * Increment the readRetries to count the number of + // * empty receives. Once this variable reaches the + // * MAX_RETRIES value, a -1 will be returned to delete + // * the socket. + // ***************************************************** + readRetries++; + + // ***************************************************** + // * If the amntread is 0 or -1 (and any error was + // * caused by blocking), and the maximum number of + // * retries has not been reached, do the following + // ***************************************************** + if(readRetries < MAX_RETRIES && + ((amntread==0 && readPktXfrLen>0) || + (amntread==-1 && (errCode == EWOULDBLOCK || errCode == EAGAIN)))) + { + result = 0; + } + // ***************************************************** + // * Otherwise, if the maximum number of retries have + // * been reached, do the following + // ***************************************************** + else if(readRetries >= MAX_RETRIES) + { + outputError (CDEV_SEVERITY_WARN, "SocketReader", + "Have exceeded maximum retries on socket"); + result = -1; + } + // ***************************************************** + // * Otherwise, if the error was not due to blocking, + // * do the following + // ****************************************************** + else if(amntread==-1) + { + outputError (CDEV_SEVERITY_ERROR, "SocketReader", + "Error number %i while reading from socket", + errCode); + result = -1; + } + } + } + + if(shutdown) result = SHUTDOWN_CODE; + if(result==-1) readReset(); + return result; + } + + +inline SocketWriter::SocketWriter ( long MagicNumber ) + : writeBuf(NULL), writeNextPktPtr(NULL), writeBufMax(WRITEBUF_INITIAL_SIZE), + writePktCnt(0), writeBufLen(RNDUP(sizeof(long))), writeXfrLen(0), writePktXfrLen(0), + // ************************* + // * Magic number support. + // ************************* + writeMagicNumber(MagicNumber), writeMagicLen(0) + { + writeBuf = (char *)malloc(writeBufMax); + writeNextPktPtr = writeBuf+writeBufLen; + } + +inline SocketWriter::~SocketWriter ( void ) + { + if(writeBuf!=NULL) free(writeBuf); + } + +inline int SocketWriter::writing ( void ) + { + return (writePktCnt>0)?1:0; + } + +inline int SocketWriter::writeReset ( void ) + { + writeBufLen = RNDUP(sizeof(long)); + writeNextPktPtr = writeBuf+writeBufLen; + writePktCnt = 0; + writeXfrLen = 0; + writePktXfrLen = 0; + + // ************************* + // * Magic number support. + // ************************* + writeMagicLen = 0; + return 0; + } + +inline int SocketWriter::writeContinue ( void ) + { + int handle = getHandle(); + int result = 0; + + // ********************************************************************* + // * The following variable has been added to allow the SocketWriter + // * to poll the file descriptor for validity prior to writing to it. + // ********************************************************************* +#ifdef SYSV + struct pollfd fds; + fds.fd = handle; + fds.events = POLLERR|POLLNVAL|POLLHUP; + fds.revents = 0; + + // ********************************************************************* + // * First test to ensure that the socket is allocated and that the + // * device descriptor is valid. + // ********************************************************************* + if( handle<=0 ) result = -1; + // ********************************************************************* + // * Execute poll to ensure that the handle is still valid and writable. + // ********************************************************************* + else if(poll(&fds, 1, 0)>0 && (fds.revents&(POLLERR|POLLNVAL|POLLHUP))!=0) + { + result = -1; + } +#else + cdevHandleSet readfd; + struct timeval tv; + + readfd.set_bit(handle); + tv.tv_sec = 0; + tv.tv_usec = 0; + + if (handle<=0) result = -1; + else if (cdevSelect (handle+1,readfd,0,0,&tv)<0) result = -1; +#endif + // ********************************************************************* + // * If all is well, continue writing data. + // ********************************************************************* + else if( writing() ) + { + int amntsent = 0; + char *sendPtr = NULL; + long magicNumber = htonl(writeMagicNumber); + long packetSize = htonl(writeBufLen); + + sendPtr = (char *)&magicNumber; + while(writeMagicNumber && writeMagicLen0) + { + writeMagicLen += amntsent; + } + + sendPtr = (char *)&packetSize; + while((!writeMagicNumber || writeMagicLen>=sizeof(long)) && writePktXfrLen0) + { + writePktXfrLen += amntsent; + } + + while(writePktXfrLen>=sizeof(long) && + writeXfrLen < writeBufLen && + (amntsent = send(handle, writeBuf+writeXfrLen, writeBufLen-writeXfrLen, 0))>0) + { + if((writeXfrLen+=amntsent)>=writeBufLen) + { + result = writeBufLen; + writeReset(); + } + } + + if(amntsent<=0) + { + int errCode = GetSocketErrno(); + + if((amntsent==0 && writePktXfrLen>0) || + (amntsent==-1 && (errCode == EWOULDBLOCK || errCode == EAGAIN))) + { + // ********************************************* + // * Do Nothing + // ********************************************* + } + else if(amntsent==-1) + { + outputError (CDEV_SEVERITY_ERROR, "SocketWriter", + "Error number %i while writing to socket", + errCode); + result = -1; + } + } + } + + if(result==-1) writeReset(); + return result; + } + +inline int SocketWriter::writeGoodbye ( void ) + { + int handle = getHandle(); + int result = 0; + + if( handle<=0 ) result = -1; + else + { + char val = -1; + result=(send(handle, &val, 1, MSG_OOB)==1)?0:-1; + } + + if(result==-1) writeReset(); + return result; + } + +inline int SocketWriter::writeEnqueue ( char * buf, int buflen ) + { + int result = 0; + + // ********************************************************************* + // * If data has already been transmitted, then it is impossible to + // * add more data to the outbound buffer because it would invalidate + // * the packet length and packet count variables. + // ********************************************************************* + if(writePktXfrLen>0) result = -1; + else + { + if(writePktCnt==0 && + (RNDUP(sizeof(long))+RNDUP(buflen)+RNDUP(sizeof(long))) > writeBufMax) + { + writeBufMax = (RNDUP(sizeof(long))+RNDUP(buflen)+RNDUP(sizeof(long))+WRITEBUF_PAD_SIZE); + writeBuf = (char *)realloc(writeBuf, writeBufMax); + writeBufLen = RNDUP(sizeof(long)); + writeNextPktPtr = writeBuf+writeBufLen; + } + if(writeBufLen+RNDUP(buflen)+RNDUP(sizeof(long)) < writeBufMax) + { + writePktCnt++; + long tpktCnt = htonl(writePktCnt); + memcpy(writeBuf, &tpktCnt, sizeof(long)); + + long tbuflen = htonl(buflen); + memcpy(writeNextPktPtr, &tbuflen, sizeof(long)); + writeNextPktPtr+=RNDUP(sizeof(long)); + memcpy(writeNextPktPtr, buf, buflen); + writeNextPktPtr+=RNDUP(buflen); + writeBufLen = (int)(writeNextPktPtr-writeBuf); + result = 0; + } + else result = -1; + } + return result; + } + +inline int SocketWriter::write(char * buf, int buflen) + { + writeEnqueue(buf, buflen); + return writeContinue(); + } + +#endif /* _SOCKET_UTIL_H */ diff --git a/extensions/cdevGenericServer/include/StringHash.h b/extensions/cdevGenericServer/include/StringHash.h new file mode 100644 index 0000000..afdfb40 --- /dev/null +++ b/extensions/cdevGenericServer/include/StringHash.h @@ -0,0 +1,235 @@ +#ifndef _VAR_STRING_HASH_H_ +#define _VAR_STRING_HASH_H_ 1 + +#include +#include +#include + +class StringHashNode +{ +friend class StringHash; +friend class StringHashIterator; + +private: + int copyKeyFlag; + char * hashString; + void * hashData; + StringHashNode * next; + + StringHashNode ( char * HashString, void * HashData, int copyKey=1); + ~StringHashNode ( void ); +}; + + +class StringHash +{ +friend class StringHashIterator; + +private: + int tableSize; + int copyKeyFlag; + StringHashNode ** nodes; + +public: + StringHash (int copyKey = 1, int TableSize = 255 ); + ~StringHash ( void ); + + inline unsigned int stringHash ( char * hashString ); + + inline void insert ( char * hashString, void * hashData ); + inline void remove ( char * hashString ); + inline void * find ( char * hashString ); +}; + + +class StringHashIterator +{ +private: + StringHash * hashTbl; + StringHashNode * node; + int idx; + +public: + StringHashIterator( StringHash * HashTbl ); + ~StringHashIterator( void ); + + inline void * first ( void ); + inline void * operator ++ ( void ); + inline void * operator ++ ( int x ); + inline char * key ( void ); + inline void * data ( void ); +}; + + +inline StringHashNode::StringHashNode ( char * HashString, void * HashData, int copyKey ) + : next(NULL), copyKeyFlag(copyKey) + { + if(copyKeyFlag) hashString = strdup(HashString); + else hashString = HashString; + hashData = HashData; + } + + +inline StringHashNode::~StringHashNode ( void ) + { + if(copyKeyFlag) delete hashString; + } + + +inline StringHash::StringHash ( int copyKey, int TableSize ) + : copyKeyFlag(copyKey), tableSize (TableSize) + { + nodes = new StringHashNode * [tableSize]; + memset(nodes, 0, sizeof(StringHashNode *) * tableSize ); + } + + +inline StringHash::~StringHash ( void ) + { + for(int i=0; inext; + delete node; + } + } + delete nodes; + } + +inline unsigned int StringHash::stringHash ( char * hashString ) + { + unsigned int hash = 0, g; + + for (int i = 0; hashString[i] != '\0'; i++) + { + hash = (hash << 4) + hashString[i]; + if (g = hash & 0xf0000000) + { + hash ^= g >> 24; + hash ^= g; + } + } + return (hash % tableSize); + } + +inline void StringHash::insert (char * hashString, void * hashData ) + { + unsigned int idx = stringHash(hashString); + StringHashNode * prev = NULL, * node = nodes[idx]; + StringHashNode * newNode = new StringHashNode(hashString, hashData, copyKeyFlag); + + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + newNode->next = node->next; + delete node; + } + if(prev!=NULL) prev->next = newNode; + else nodes[idx] = newNode; + } + +inline void StringHash::remove ( char * hashString ) + { + unsigned int idx = stringHash(hashString); + StringHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + if(prev!=NULL) prev->next = node->next; + else nodes[idx] = node->next; + delete node; + } + } + +inline void * StringHash::find ( char * hashString ) + { + unsigned int idx = stringHash(hashString); + StringHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + return node!=NULL?node->hashData:NULL; + } + + +inline StringHashIterator::StringHashIterator(StringHash * HashTbl) + : hashTbl(HashTbl), idx(0), node(NULL) + { + } + +inline StringHashIterator::~StringHashIterator( void ) + { + } + +inline void * StringHashIterator::first ( void ) + { + if(hashTbl!=NULL) + { + for(idx = 0; idxtableSize && + (node = hashTbl->nodes[idx])==NULL; idx++); + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * StringHashIterator::operator ++ ( void ) + { + if(hashTbl!=NULL) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxtableSize && + (node = hashTbl->nodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * StringHashIterator::operator ++ ( int x ) + { + if(hashTbl!=NULL && x==0) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxtableSize && + (node = hashTbl->nodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline char * StringHashIterator::key ( void ) + { + return (node!=NULL)?node->hashString:(char *)NULL; + } + +inline void * StringHashIterator::data ( void ) + { + return (node!=NULL)?node->hashData:NULL; + } + +#endif /* _VAR_STRING_HASH_H_ */ diff --git a/extensions/cdevGenericServer/include/VarStrHash.h b/extensions/cdevGenericServer/include/VarStrHash.h new file mode 100644 index 0000000..ccb93d0 --- /dev/null +++ b/extensions/cdevGenericServer/include/VarStrHash.h @@ -0,0 +1,235 @@ +#ifndef _VAR_STRING_HASH_H_ +#define _VAR_STRING_HASH_H_ 1 + +#include +#include +#include + +class VarStrHashNode +{ +friend class VarStrHash; +friend class VarStrHashIterator; + +private: + int copyKeyFlag; + char * hashString; + void * hashData; + VarStrHashNode * next; + + VarStrHashNode ( char * HashString, void * HashData, int copyKey=1); + ~VarStrHashNode ( void ); +}; + + +class VarStrHash +{ +friend class VarStrHashIterator; + +private: + int tableSize; + int copyKeyFlag; + VarStrHashNode ** nodes; + +public: + VarStrHash (int copyKey = 1, int TableSize = 255 ); + ~VarStrHash ( void ); + + inline unsigned char stringHash ( char * hashString ); + + inline void insert ( char * hashString, void * hashData ); + inline void remove ( char * hashString ); + inline void * find ( char * hashString ); +}; + + +class VarStrHashIterator +{ +private: + VarStrHash * hashTbl; + VarStrHashNode * node; + int idx; + +public: + VarStrHashIterator( VarStrHash * HashTbl ); + ~VarStrHashIterator( void ); + + inline void * first ( void ); + inline void * operator ++ ( void ); + inline void * operator ++ ( int x ); + inline char * key ( void ); + inline void * data ( void ); +}; + + +inline VarStrHashNode::VarStrHashNode ( char * HashString, void * HashData, int copyKey ) + : next(NULL), copyKeyFlag(copyKey) + { + if(copyKeyFlag) hashString = strdup(HashString); + else hashString = HashString; + hashData = HashData; + } + + +inline VarStrHashNode::~VarStrHashNode ( void ) + { + if(copyKeyFlag) delete hashString; + } + + +inline VarStrHash::VarStrHash ( int copyKey, int TableSize ) + : copyKeyFlag(copyKey), tableSize (TableSize) + { + nodes = new VarStrHashNode * [tableSize]; + memset(nodes, 0, sizeof(VarStrHashNode *) * tableSize ); + } + + +inline VarStrHash::~VarStrHash ( void ) + { + for(int i=0; inext; + delete node; + } + } + } + +inline unsigned char VarStrHash::stringHash ( char * hashString ) + { + unsigned char idx=0; + unsigned int hash = 0, g; + + for (int i = 0; hashString[i] != '\0'; i++) + { + hash = (hash << 4) + hashString[i]; + if (g = hash & 0xf0000000) + { + hash ^= g >> 24; + hash ^= g; + } + } + return (hash % tableSize); + } + +inline void VarStrHash::insert (char * hashString, void * hashData ) + { + unsigned char idx = stringHash(hashString); + VarStrHashNode * prev = NULL, * node = nodes[idx]; + VarStrHashNode * newNode = new VarStrHashNode(hashString, hashData, copyKeyFlag); + + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + newNode->next = node->next; + delete node; + } + if(prev!=NULL) prev->next = newNode; + else nodes[idx] = newNode; + } + +inline void VarStrHash::remove ( char * hashString ) + { + unsigned char idx = stringHash(hashString); + VarStrHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + if(prev!=NULL) prev->next = node->next; + else nodes[idx] = node->next; + delete node; + } + } + +inline void * VarStrHash::find ( char * hashString ) + { + unsigned char idx = stringHash(hashString); + VarStrHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + return node!=NULL?node->hashData:NULL; + } + + +inline VarStrHashIterator::VarStrHashIterator(VarStrHash * HashTbl) + : hashTbl(HashTbl), idx(0), node(NULL) + { + } + +inline VarStrHashIterator::~VarStrHashIterator( void ) + { + } + +inline void * VarStrHashIterator::first ( void ) + { + if(hashTbl!=NULL) + { + for(idx = 0; idxtableSize && + (node = hashTbl->nodes[idx])==NULL; idx++); + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * VarStrHashIterator::operator ++ ( void ) + { + if(hashTbl!=NULL) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxtableSize && + (node = hashTbl->nodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * VarStrHashIterator::operator ++ ( int x ) + { + if(hashTbl!=NULL && x==0) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxtableSize && + (node = hashTbl->nodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline char * VarStrHashIterator::key ( void ) + { + return (node!=NULL)?node->hashString:NULL; + } + +inline void * VarStrHashIterator::data ( void ) + { + return (node!=NULL)?node->hashData:NULL; + } + +#endif /* _VAR_STRING_HASH_H_ */ diff --git a/extensions/cdevGenericServer/include/cdevAddr.h b/extensions/cdevGenericServer/include/cdevAddr.h new file mode 100644 index 0000000..89233e8 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevAddr.h @@ -0,0 +1,48 @@ +#ifndef _CDEV_ADDR_H_ +#define _CDEV_ADDR_H_ + +#include "cdevPlatforms.h" + +class CDEV_REACTOR_API cdevAddr +{ +protected: + int addr_type; + int addr_size; + +public: + cdevAddr ( void ) : addr_type(0), addr_size(0) {} + cdevAddr ( int type, int size ) : addr_type(type), addr_size(size) {} + int getSize ( void ) const { return addr_size; } + void setSize ( int size ) { addr_size = size; } + int getType ( void ) const { return addr_type; } + void setType ( int type ) { addr_type = type; } + + virtual void * getAddress ( void ) const { return NULL; } + +}; + + +class CDEV_REACTOR_API cdevInetAddr : public cdevAddr +{ +protected: + sockaddr_in inet_addr; + +public: + cdevInetAddr (void); + cdevInetAddr (const cdevInetAddr & addr); + cdevInetAddr (const sockaddr_in *, int len); + cdevInetAddr (unsigned short portnum, char hostname[]); + cdevInetAddr (unsigned short portnum, long ip_addr=INADDR_ANY); + + int set (unsigned short portnum, const char hostname[]); + int set (unsigned short portnum, long ip_addr=INADDR_ANY); + int set (const sockaddr_in *, int len); + + const char * getHostName ( void ) const; + const char * getHostAddr ( void ) const; + unsigned long getInetAddr ( void ) const; + unsigned short getPortNum ( void ) const; + void * getAddress ( void ) const; +}; + +#endif diff --git a/extensions/cdevGenericServer/include/cdevBufferedSocket.h b/extensions/cdevGenericServer/include/cdevBufferedSocket.h new file mode 100644 index 0000000..3cc34b3 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevBufferedSocket.h @@ -0,0 +1,114 @@ +#ifndef _CDEV_BUFFERED_SOCKET_H_ +#define _CDEV_BUFFERED_SOCKET_H_ + +#include "cdevSocketConnector.h" +#include "cdevStreamQueue.h" + +class cdevBufferedSocket : public cdevSocketConnector, public cdevNodeFactory +{ +private: + cdevNodeFactory * nodeFactory; + + int magicNumber; + int deleteFlag; + + cdevStreamQueue activeOut; + cdevStreamQueue waitingOut; + int outboundHeader[3]; + size_t headerXfrLen; + size_t dataXfrLen; + + cdevStreamQueue waitingIn; + cdevStreamNode * rcvNode; + int inboundHeader[3]; + size_t headerRcvLen; + size_t dataRcvLen; + size_t subPacketLen; + + static void sigPipeHandler (int); + +public: + enum {RETRYCNT = 1000 }; + + inline cdevBufferedSocket ( int MagicNumber=0, int deleteNodes = 1, cdevNodeFactory * factory=NULL ); + + inline int outboundReady ( void ); + inline int inboundReady ( void ); + inline void enqueueOutbound ( cdevStreamNode * node ); + inline cdevStreamNode * dequeueInbound ( void ); + + cdevStreamNode * newNode ( ssize_t size ); + ssize_t transmit ( void ); + ssize_t receive ( void ); + + int getBlockingSemantics ( void ) const; + int getRcvBufferSize ( void ) const; + int getSndBufferSize ( void ) const; +}; + + +// ***************************************************************************** +// * cdevBufferedSocket::cdevBufferedSocket : +// * This is the constructor for the cdevBufferedSocket, it will initialize +// * all internal variables and sub-classes. +// ***************************************************************************** +inline cdevBufferedSocket::cdevBufferedSocket ( int MagicNumber, int deleteNodes, cdevNodeFactory * factory ) + : nodeFactory(factory), + magicNumber(MagicNumber), + deleteFlag (deleteNodes), + activeOut(deleteNodes), + waitingOut(deleteNodes), + headerXfrLen(0), + dataXfrLen(0), + waitingIn(), + rcvNode(NULL), + headerRcvLen(0), + dataRcvLen(0), + subPacketLen(0) + { + if(nodeFactory==NULL) nodeFactory=this; + } + + +// ***************************************************************************** +// * cdevBufferedSocket::outboundReady : +// * This method returns an integer value indicating that outbound data is +// * ready for transmission. +// ***************************************************************************** +inline int cdevBufferedSocket::outboundReady ( void ) + { + return !(activeOut.isEmpty() && waitingOut.isEmpty()); + } + +// ***************************************************************************** +// * cdevBufferedSocket::inboundReady : +// * This method returns a flag indicating that inbound data is ready to be +// * dequeued and processed. +// ***************************************************************************** +inline int cdevBufferedSocket::inboundReady ( void ) + { + return !(waitingIn.isEmpty() && headerRcvLen==0); + } + +// ***************************************************************************** +// * cdevBufferedSocket::enqueueOutbound : +// * This method places the user defined cdevStreamNode pointer into the +// * waitingOut object. +// ***************************************************************************** +inline void cdevBufferedSocket::enqueueOutbound ( cdevStreamNode * node ) + { + waitingOut.enqueue(node); + } + +// ***************************************************************************** +// * cdevBufferedSocket::dequeueInbound : +// * This method dequeues the next available cdevStreamNode object from the +// * waitingIn object. +// ***************************************************************************** +inline cdevStreamNode * cdevBufferedSocket::dequeueInbound ( void ) + { + return waitingIn.dequeue(); + } + + +#endif /* _CDEV_BUFFERED_SOCKET_H_ */ diff --git a/extensions/cdevGenericServer/include/cdevClientRequestObject.h b/extensions/cdevGenericServer/include/cdevClientRequestObject.h new file mode 100644 index 0000000..fc71085 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevClientRequestObject.h @@ -0,0 +1,223 @@ +#if !defined (_CDEV_CLIENT_REQUEST_OBJECT_H_) +#define _CDEV_CLIENT_REQUEST_OBJECT_H_ + +#include +#include +#include + +// ***************************************************************************** +// * cdevClientRequestObject: +// * The cdevClientRequestObject class provides the interface for sending +// * messages to a server. All device/message commands are routed +// * through a cdevClientRequestObject either directly or indirectly. +// ***************************************************************************** +class GENERIC_SERVER_API cdevClientRequestObject : public cdevRequestObject, public ServerHandlerCallback +{ +protected: + typedef struct + { + int completionCode; + int finished; + } SendStatus; + + SendStatus sendStatus; + char server [256]; + char DDL_server[256]; + cdevCallback syncCallback; + ServerHandler * handler; + int contextID; + + int commandCode; + int messageCode; + +public: + // ********************************************************************* + // * These enumerated type are used to identify the basic four commands + // * that might be represented by a cdevClientRequestObject... By using + // * these identifiers the cdevService does not have to perform a + // * string compare in order to identify the nature of the request + // * object. + // * + // * At construction the cdevClientRequestObject will set the + // * commandCode to contain the correct value, the developer may + // * override this setting in the constructor for an inherited class. + // * + // * Enumerated list extensions created by developers should begin at + // * value cdevClientRequestObject::MONITOR_OFF_COMMAND+1. + // * + // * The current setting of the commandCode may be obtained by calling + // * the getCommandCode method of the class. + // ********************************************************************* + enum {OTHER_COMMAND = 0, + GET_COMMAND, + SET_COMMAND, + MONITOR_ON_COMMAND, + MONITOR_OFF_COMMAND}; + + // ********************************************************************* + // * These enumerated type are used to identify the messages that are + // * intrinisicly supported by the cdevService... By using + // * these identifiers the cdevService does not have to perform a + // * string compare in order to identify the nature of the request + // * object. + // * + // * At construction the cdevClientRequestObject will set the + // * messageCode to contain the correct value, the developer may + // * override this setting in the constructor for an inherited class. + // * + // * Enumerated list extensions created by developers should begin at + // * value cdevClientRequestObject::SET_DEFAULT_MESSAGE+1 + // * + // * The current setting of the commandCode may be obtained by calling + // * the getMessageCode method of the class. + // ********************************************************************* + enum {OTHER_MESSAGE = 0, + GET_SERVERS_MESSAGE, + GET_DEFAULT_MESSAGE, + SET_DEFAULT_MESSAGE, + DISCONNECT_MESSAGE, + GET_CLIENTINFO_MESSAGE, + GET_SERVERINFO_MESSAGE}; + + cdevClientRequestObject ( char * device, char * message, + cdevSystem & system = cdevSystem::defaultSystem()); + + virtual ~cdevClientRequestObject ( void ); + + // ********************************************************************* + // * cdevClientRequestObject::getState : + // * Returns the connection state of the cdevClientRequestObject. + // ********************************************************************* + virtual int getState ( void ); + + // ********************************************************************* + // * cdevClientRequestObject::setContext : + // * This mechanism is used to specify the default server that will + // * be used for the request. + // ********************************************************************* + virtual int setContext ( cdevData & ctx); + + // ********************************************************************* + // * cdevClientRequestObject::send : + // * The send interface is used to provide synchronous I/O with the + // * service. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int send ( cdevData & in, cdevData & out ); + virtual int send ( cdevData * in, cdevData & out ); + virtual int send ( cdevData & in, cdevData * out ); + virtual int send ( cdevData * in, cdevData * out ); + + // ********************************************************************* + // * cdevClientRequestObject::sendNoBlock : + // * The sendNoBlock interface is used in conjunction with cdevGroup + // * or cdevSystem to execute a series of operations. During the + // * early implementation of this product, these functions will be + // * linked directly to the send call. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int sendNoBlock (cdevData & in, cdevData & out); + virtual int sendNoBlock (cdevData * in, cdevData & out); + virtual int sendNoBlock (cdevData & in, cdevData * out); + virtual int sendNoBlock (cdevData * in, cdevData * out); + + // ********************************************************************* + // * cdevClientRequestObject::sendCallback : + // * The sendCallback interface provides asynchronous communications + // * with the server. During the early implementation of this + // * product, these functions will be linked directly to the send + // * call. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int sendCallback (cdevData & in, cdevCallback & callback); + virtual int sendCallback (cdevData * in, cdevCallback & callback); + + virtual const char * className ( void ) const; + + // ********************************************************************* + // * cdevClientRequestObject::deafultCallback : + // * This is the callback function that is used by the object to + // * receive callbacks for send operations. + // ********************************************************************* + static void defaultCallback (int status, void * user, cdevRequestObject &, cdevData &); + + // ********************************************************************* + // * The requestObject registers itself with the ServerHandler when it + // * attaches to it... If the Serverhandler is destroyed, it will + // * call this method on all of the registered request objects in order + // * to notify them that it is going away. This allows the request + // * object to clear the pointer to the ServerHandler. + // ********************************************************************* + virtual void executeServerHandlerCallback (ServerHandler * Handler); + + // ********************************************************************* + // * This method is used to obtain the ServerHandler for this request + // * object... + // * + // * The following rules will be followed: + // * 1) If a server has been specified in the context, then that + // * server will be used. + // * + // * - otherwise - + // * + // * 2) If a server has been specified in the service data of the + // * DDL file, then that server will be used. + // * + // * - otherwise - + // * + // * 3) The default server as specified at the cdevClientService will + // * be used. + // ********************************************************************* + virtual int getServerHandler (ServerHandler ** Handler); + + // ********************************************************************* + // * This method allows the caller to determine if the request object + // * is restartable. If a server goes down and then a new server comes + // * up in its place, this method will be called for each request object + // * that has an outstanding request that has not been serviced. + // * If the isRequestRestartable method returns 1, the request will be + // * sent to the new server - otherwise, the request will be terminated. + // ********************************************************************* + virtual int isRequestRestartable ( void ); + + // ********************************************************************* + // * getContextID : + // * This method will retrieve the identifier of the context that + // * is currently in use by this object. + // ********************************************************************* + int getContextID ( void ); + + // ********************************************************************* + // * getCommandCode : + // * This method will return the current value of the commandCode + // * variable. This variable is used to identify the VERB that is + // * utilized by this cdevRequestObject. The default set of verbs + // * are "get", "set", "monitorOn", and "monitorOff". + // ********************************************************************* + int getCommandCode ( void ); + + // ********************************************************************* + // * getMessageCode : + // * This method will return the current value of the messageCode + // * variable. This variable is used to identify the message that is + // * utilized by this cdevRequestObject. The default set of + // * supported messages are "get servers", "get default", + // * "set default", and "disconnect". + // ********************************************************************* + int getMessageCode ( void ); + + + // ********************************************************************* + // * waitPeriod : + // * This method returns a double that indicates the maximum amount + // * of time that the service should wait for a synchronous result to + // * be returned. + // ********************************************************************* + virtual double waitPeriod ( void ) { return 10.0; } +}; + + +#endif /* _CDEV_CLIENT_REQUEST_OBJECT_H_ */ diff --git a/extensions/cdevGenericServer/include/cdevClientService.h b/extensions/cdevGenericServer/include/cdevClientService.h new file mode 100644 index 0000000..4d34ab4 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevClientService.h @@ -0,0 +1,140 @@ +#if !defined (_CDEV_CLIENT_SERVICE_H_) +#define _CDEV_CLIENT_SERVICE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ***************************************************************************** +// * class NSCallbackArg : +// * This class is provided as a technique for allowing the name server +// * to differentiate when making monitorOn requests between two servers that +// * use the same service. +// ***************************************************************************** +class GENERIC_SERVER_API NSCallbackArg +{ +friend class cdevClientService; + +private: + char * server; + cdevClientService * service; + + NSCallbackArg ( char * Server, cdevClientService * Service ) + : server(strdup(Server)), service(Service) + { + } + + ~NSCallbackArg ( void ) + { + if(server) delete server; + } +}; + + +// ***************************************************************************** +// * cdevClientService: +// * This is class provides the mechanisms that the cdev system will use +// * to communicate with the model service. +// ***************************************************************************** +class GENERIC_SERVER_API cdevClientService : public cdevService, + public ServerInterface, + public cdevTagTableCallback +{ +friend class cdevClientRequestObject; +friend class cdevClientTransaction; + +public: + enum { ServiceTagBase=511 }; + + static int ServerTag; + static int HostTag; + static int PortTag; + + cdevClientService ( char * domain, char * name, cdevSystem & system = cdevSystem::defaultSystem()); + static void defaultCallback (int, void *, cdevRequestObject &, cdevData &); + static void nameServerCallback(int, void *, cdevRequestObject &, cdevData &); + virtual int outputError (int severity, char *name, char *formatString, ...); + ServerHandler * connect ( char * server, char * host=NULL, unsigned short port = 0); + ServerHandler * disconnect ( char * server ); + + int flush ( void ); + int pend ( double seconds, int fd = -1 ); + int getFd ( int * &fd, int & numFd ); + + int poll ( void ); + int pend ( int fd = -1 ); + int getNameServer ( cdevDevice * &ns ); + int getRequestObject ( char * device, char * message, cdevRequestObject * &req); + + int enqueue ( char * server, cdevData * in, cdevTranObj & xobj ); + int enqueue ( ServerHandler * handler, cdevData * in, cdevTranObj & xobj ); + int enqueue ( ServerHandler * handler, class cdevClientTransaction &, unsigned); + int cancel ( cdevTranObj & xobj ); + int enqueue ( int status, ServerHandler * handler, char * binary, size_t binaryLen ); + int isPacketValid ( char * binary, size_t binaryLen ); + void callback ( int newTag, char * newName ); + char * getDomain ( void ) const { return domain; } + +protected: + virtual ~cdevClientService ( void ); + virtual void fireCallback ( int status, cdevTranObj &xobj, cdevData *resultData, int partialTransaction = 0 ); + virtual int processLocal ( cdevData * in, cdevTranObj & xobj ); + + char * domain; + AddressIndex transactions; + cdevCallback syncCallback; + cdevContextMap contexts; + int quitFlag; + StringHash nsCallbackArgs; + static ClientInfo clientInfo; + static cdevGenericServerTagDef tags; + + NSCallbackArg * getCallbackArg ( char * server ); +}; + +class GENERIC_SERVER_API cdevClientTransaction +{ +private: + // ********************************************************************* + // * Free list data elements and private array constructor. + // ********************************************************************* + enum {ALLOCATION_COUNT = 16 }; + static cdevClientTransaction * freeList_; + cdevClientTransaction * freeListNext_; + cdevClientTransaction ( void ); + +public: + // ********************************************************************* + // * Public free list interface. + // ********************************************************************* + void * operator new ( size_t size ); + void operator delete ( void * ptr ); + + char server[256]; + cdevTranObj * xobj; + int permanent; + int statusCode; + + // ********************************************************************* + // * Data elements used for restartable transactions. + // ********************************************************************* + int restartable; + int contextID; + cdevData * userData; + + cdevClientTransaction ( cdevTranObj & XObj, ServerHandler &handler, + int Restartable=0, cdevData *data=NULL, + unsigned ContextID=0 ); + virtual ~cdevClientTransaction ( void ); + void reconnect (char * host=NULL, unsigned short port=0, unsigned key=0); + +}; + + +#endif /* _CDEV_CLIENT_SERVICE_H_ */ diff --git a/extensions/cdevGenericServer/include/cdevContextMap.h b/extensions/cdevGenericServer/include/cdevContextMap.h new file mode 100644 index 0000000..c39a7d3 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevContextMap.h @@ -0,0 +1,33 @@ +#ifndef _CDEV_CONTEXT_MAP_H_ +#define _CDEV_CONTEXT_MAP_H_ 1 +#include +#include + + +// ***************************************************************************** +// * class cdevContextMap : +// * The purpose of this class is to allow the user to store a list of +// * commonly used context cdevData items. This will allow the caller to +// * pass the context to maintain a list of contexts that are identifiable +// * by a unique integer identifier... +// ***************************************************************************** +class GENERIC_SERVER_API cdevContextMap +{ +protected: + cdevData ** entries; + size_t maximum; + size_t cnt; + + void resize ( void ); + +public: + cdevContextMap ( void ); + ~cdevContextMap ( void ); + int insert ( cdevData & context ); + int find ( cdevData & context ); + cdevData * find ( int idx ) { return (idx>cnt || idx<0)?(cdevData *)NULL:entries[idx]; } + void asciiDump ( FILE * fp = stdout ); +}; + +#endif /* _CDEV_CONTEXT_MAP_H_ */ + diff --git a/extensions/cdevGenericServer/include/cdevEventHandler.h b/extensions/cdevGenericServer/include/cdevEventHandler.h new file mode 100644 index 0000000..7f4f05c --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevEventHandler.h @@ -0,0 +1,54 @@ +#ifndef _CDEV_EVENT_HANDLER_H_ +#define _CDEV_EVENT_HANDLER_H_ 1 + +#include "cdevTime.h" + +class CDEV_REACTOR_API cdevEventHandler +{ +friend class cdevReactor; + +public: + enum { + READ_MASK = 0x01, + EXCEPT_MASK = 0x02, + WRITE_MASK = 0x04, + DONT_CALL = 0x100 + } REACTOR_MASK; + +private: + void setReactor (cdevReactor * r); + cdevEventHandler * getNext (void ); + void setNext (cdevEventHandler * n); + cdevTime & getNextTimeout (void); + +protected: + cdevEventHandler * next; + cdevTime nextTimeout; + cdevReactor * reactor; + cdevTime timeoutRate; + int mask; + +public: + cdevEventHandler ( void ); + virtual ~cdevEventHandler ( void ); + + virtual void setMask ( unsigned Mask ); + virtual void setHandle ( int handle ); + virtual int getHandle ( void ) const; + virtual int getMask ( void ); + virtual cdevReactor * getReactor ( void ); + + virtual cdevTime & getTimeoutRate ( void ); + virtual void setTimeoutRate ( cdevTime time ); + virtual void resetTimer ( void ); + + virtual int handleInput ( void ); + virtual int handleOutput ( void ); + virtual int handleExcept ( void ); + virtual int handleTimeout ( void ); + virtual int handleSignal ( void ); + virtual int handleClose ( void ); + +}; + +#endif diff --git a/extensions/cdevGenericServer/include/cdevGenericServerTags.h b/extensions/cdevGenericServer/include/cdevGenericServerTags.h new file mode 100644 index 0000000..04852b9 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevGenericServerTags.h @@ -0,0 +1,66 @@ +static char * cdevGenericServerTags[] = + { + "client", + "clientCnt", + "commandline", + "connecttime", + "datasize", + "domain", + "gid", + "group", + "host", + "key", + "keyExp", + "keyType", + "machine", + "name", + "os", + "osrelease", + "osversion", + "owner", + "pctcpu", + "pid", + "ping", + "port", + "program", + "queryMsg", + "recvPktCnt", + "resultCode", + "sendPktCnt", + "server", + "shell", + "socket", + "starttime", + "table", + "time", + "uid", + "username", + NULL + }; + +class cdevGenericServerTagDef +{ +public: + enum {GENERIC_BASE_TAG=900}; + + cdevGenericServerTagDef ( void ) + { + installTags(); + } + + void installTags ( void ) + { + + for(int i=0; cdevGenericServerTags[i]!=NULL; i++) + { + int tagVal; + + cdevData::insertTag(GENERIC_BASE_TAG+i, cdevGenericServerTags[i]); + if(cdevData::tagC2I(cdevGenericServerTags[i], &tagVal)!=CDEV_SUCCESS) + { + cdevData::addTag(cdevGenericServerTags[i]); + } + } + } +}; + diff --git a/extensions/cdevGenericServer/include/cdevHandleSet.h b/extensions/cdevGenericServer/include/cdevHandleSet.h new file mode 100644 index 0000000..3f493da --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevHandleSet.h @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// File Descriptor Mask Class (Based On ACE Handler_Set) + +#ifndef _CDEV_HANDLE_SET_H_ +#define _CDEV_HANDLE_SET_H_ + +#include +#include +#include "cdevPlatforms.h" + +class CDEV_REACTOR_API cdevHandleSet +{ +friend class cdevHandleSetIterator; +friend class cdevReactor; + +public: + cdevHandleSet (void); + cdevHandleSet (const fd_set &mask); + + void reset (void); + int is_set (int) const; + void set_bit (int); + void clr_bit (int); + int num_set (void) const; + int max_set (void) const; + int asciiDump (FILE * fp = stdout); + void sync (int max = FD_SETSIZE); + + operator fd_set *( void ) { return &mask_; } + +private: + int size_; + int max_handle_; + fd_set mask_; + + enum { + #ifdef _WIN32 + MAX_SIZE = FD_SETSIZE, + #else + MAX_SIZE = NOFILE, + WORD_SIZE = NFDBITS, + NUM_WORDS = howmany (NOFILE, NFDBITS), + #ifdef __DECCXX + MSB_MASK = ~(1U << (NFDBITS - 1)) + #elif defined(CDEV_HAS_64BIT_LONGS) + MSB_MASK = ~(1UL << (NFDBITS - 1)) + #else + MSB_MASK = ~(1 << (NFDBITS - 1)) + #endif + #endif + }; + + int count_bits (unsigned long n) const; + void set_max (int max); + + static const char nbits_[256]; +}; + +class CDEV_REACTOR_API cdevHandleSetIterator +{ +public: + cdevHandleSetIterator (cdevHandleSet &); + int operator ()(void); + void operator++ (void); + +private: + cdevHandleSet &fds_; + int num_; + + #ifdef _WIN32 + unsigned int index_; + #else + int index_; + fd_mask val_; + #endif +}; + +#endif /* _CDEV_HANDLE_SET_H_ */ diff --git a/extensions/cdevGenericServer/include/cdevMessage.h b/extensions/cdevGenericServer/include/cdevMessage.h new file mode 100644 index 0000000..fba12b3 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevMessage.h @@ -0,0 +1,129 @@ +#ifndef _CDEV_MESSAGE_H_ +#define _CDEV_MESSAGE_H_ 1 + +#include +#include +#include + +class GENERIC_SERVER_API cdevMessage : public cdevPacket +{ +private: + typedef union + { + unsigned char rawData; + struct { + unsigned char saveDeviceList : 1; + unsigned char saveMessage : 1; + unsigned char saveData : 1; + unsigned char saveContext : 1; + unsigned char saveTagMap : 1; + unsigned pad : 3; + } value; + } SaveTable; + + SaveTable saveTbl; + + short clientID; + unsigned transIndex; + unsigned cancelTransIndex; + unsigned localDataIndex; + unsigned foreignDataIndex; + unsigned operationCode; + int completionCode; + unsigned deviceCount; + char ** deviceList; + char * message; + cdevData * data; + cdevData * context; + cdevData * tagMap; + +public: + enum { CDEV_PACKET_VERSION = cdevMessageBinary::CDEV_PACKET_VERSION }; + + static cdevPacket *import( cdevPacketBinary & ); + + cdevMessage ( short ClientID = -1, + unsigned TransIndex = 0, + unsigned CancelTransIndex = 0, + unsigned LocalDataIndex = 0, + unsigned ForeignDataIndex = 0, + unsigned OperationCode = 0, + int CompletionCode = 0, + unsigned DeviceCount = 0, + char ** DeviceList = NULL, + char * Message = NULL, + cdevData * Data = NULL, + cdevData * Context = NULL, + cdevData * TagMap = NULL); + + cdevMessage ( char * binary, size_t binaryLen ); + cdevMessage ( class cdevMessage & message ); + virtual ~cdevMessage ( void ); + virtual void clear ( void ); + virtual int streamIn ( char * binary, size_t binaryLen ); + virtual int streamOut ( char ** binary, size_t * binaryLen ); + virtual void asciiDump ( FILE * fp = stdout ); + + virtual short getVersion ( void ) { return CDEV_PACKET_VERSION; } + virtual short getClientID ( void ) { return clientID; } + virtual unsigned getTransIndex ( void ) { return transIndex; } + + unsigned getCancelTransIndex ( void ) { return cancelTransIndex; } + unsigned getLocalDataIndex ( void ) { return localDataIndex; } + unsigned getForeignDataIndex ( void ) { return foreignDataIndex; } + unsigned getOperationCode ( void ) { return operationCode; } + int getCompletionCode ( void ) { return completionCode; } + unsigned getDeviceCount ( void ) { return deviceCount; } + char ** getDeviceList ( void ) { return deviceList; } + char * getMessage ( void ) { return message; } + cdevData * getData ( void ) { return data; } + cdevData * getContext ( void ) { return context; } + cdevData * getTagMap ( void ) { return tagMap; } + + virtual void setClientID ( short ClientID ) { clientID = ClientID; } + virtual void setTransIndex( unsigned TransIndex ) { transIndex = TransIndex; } + + void setCancelTransIndex ( unsigned CancelTransIndex ) { cancelTransIndex = CancelTransIndex; } + void setLocalDataIndex ( unsigned LocalDataIndex ) { localDataIndex = LocalDataIndex; } + void setForeignDataIndex ( unsigned ForeignDataIndex ) { foreignDataIndex = ForeignDataIndex; } + void setOperationCode ( unsigned OperationCode ) { operationCode = OperationCode; } + void setCompletionCode ( int CompletionCode ) { completionCode = CompletionCode; } + void setDeviceList ( char ** DeviceList, int DeviceCount, int permanent = 0 ) + { + if(deviceList!=NULL && !saveTbl.value.saveDeviceList) + { + for(int i=0; i + +// ***************************************************************************** +// * OperationCode Definitions : +// * CDEV_NORMAL_OP = 0 : This is a message that is to be processed by the +// * developer's server interface. +// * CDEV_SERVER_OP = 1 : This is a message that is to be processed by the +// * Generic Server Interface. +// ***************************************************************************** +enum { + CDEV_NORMAL_OP = 0, + CDEV_SERVER_OP = 1 + }; + +// ***************************************************************************** +// * struct cdevMessageBinaryMap : +// * This is the first 32 bit integer that is passed through the socket. It +// * contains a bitmap that identifies the version of the packet, as well as +// * a bit field that indicates the contents of the packet. This bitfield +// * simplifies the process of decoding the packet and results in a smaller +// * transmission size. +// ***************************************************************************** +typedef union + { + unsigned rawData; + struct { + unsigned version : 16; + unsigned clientIDSet : 1; + unsigned transIndexSet : 1; + unsigned cancelTransIndexSet : 1; + unsigned localDataIndexSet : 1; + unsigned foreignDataIndexSet : 1; + unsigned operationCodeSet : 1; + unsigned completionCodeSet : 1; + unsigned deviceListSet : 1; + unsigned messageSet : 1; + unsigned dataSet : 1; + unsigned contextSet : 1; + unsigned tagMapSet : 1; + unsigned pad : 4; + } value; + } cdevMessageBinaryMap; + + +// ***************************************************************************** +// * The following elements are contained within a cdevMessageBinary binary +// * object. +// * +// * short version : This is the version of the cdevPacketBinary +// * that is being constructed. The format and +// * structure of the remainder of the data is +// * based on version 1. +// * +// * short clientID : **** REQUIRED **** +// * This is the clientID that the server will use +// * to uniquely identify this client. +// * +// * unsigned transIndex : **** REQUIRED **** +// * This is the index that will be used on the +// * client side to locate the transaction object +// * associated with this request. +// * +// * +// * unsigned cancelTransIndex : This is the transaction index of a transaction +// * that should be canceled. This field is +// * typically used to terminate a monitor. +// * +// * unsigned localDataIndex : This is the index that will be used on the +// * ~packet senders~ side to identify a list +// * of devices. +// * +// * unsigned foreignDataIndex : This is the index that will be used on the +// * ~packet receivers~ side to identify a list +// * of devices. +// * +// * +// * unsigned operationCode : This is a user defined operation code that +// * may be used to reduce the size of the data +// * that is transmitted between the client and +// * the server by using integer operation codes +// * rather than character strings. +// * +// * int completionCode : This is the result of the operation on the +// * server side. +// * +// * unsigned deviceCount : This is the number of device names that will +// * be contained in the following list. +// * +// * char ** deviceList : This is a list of character strings that +// * identify cdevDevices. +// * +// * char * message : This is the message text. +// * +// * cdevData data : This is a cdevData object containing the +// * data associated with the request or +// * the result of the request if this packet +// * is a response from a server. +// * +// * cdevData context : This is a cdevData object specifying the +// * context of the request. +// * +// * cdevData tagMap : This is a cdevData object that contains the +// * mapping of the cdevData tag table for the +// * client. By virtue of the fact that this table +// * cannot rely on any of the known tags to exist +// * of be the same... the following integer values +// * will be used. +// * +// * 1) An array of integers that identify the +// * tag numbers. +// * +// * 2) An array of strings that identify the +// * tag names. +// * +// ***************************************************************************** +class GENERIC_SERVER_API cdevMessageBinary : public cdevPacketBinary +{ +private: + cdevMessageBinaryMap map; + XDR_Reader reader; + + +protected: + typedef enum + { + GOTO_CLIENTID=1, + GOTO_TRANSINDEX, + GOTO_CANCELTRANSINDEX, + GOTO_LOCALDATAINDEX, + GOTO_FOREIGNDATAINDEX, + GOTO_OPERATIONCODE, + GOTO_COMPLETIONCODE, + GOTO_DEVICELIST, + GOTO_MESSAGE, + GOTO_DATA, + GOTO_CONTEXT, + GOTO_TAGMAP} POSITION_FLAG; + + // ********************************************************************* + // * cdevMessageBinary::setBinaryPosition : + // * This method will set the position of the binary stream within an + // * XDR_Reader to the specified data object. + // * This method returns 0 on success, or -1 if the data object could + // * not be selected. + // ********************************************************************* + int setBinaryPosition (XDR_Reader & reader, POSITION_FLAG flag ); + +public: + enum { CDEV_PACKET_VERSION = 2 }; + + cdevMessageBinary ( cdevMessageBinary &packet ); + cdevMessageBinary ( short clientID = -1, + unsigned transIndex = 0, + unsigned cancelTransIndex = 0, + unsigned localDataIndex = 0, + unsigned foreignDataIndex = 0, + unsigned operationCode = 0, + int completionCode = 0, + unsigned deviceCount = 0, + char ** deviceList = NULL, + char * message = NULL, + cdevData * data = NULL, + cdevData * context = NULL, + cdevData * tagMap = NULL ); + + virtual ~cdevMessageBinary ( void ); + + // ********************************************************************* + // * map2int ( void ) + // * This method will convert the cdevMessageBinaryMap to an unsigned + // ********************************************************************* + unsigned map2int ( cdevMessageBinaryMap map, unsigned & value); + + // ********************************************************************* + // * int2map ( void ) + // * This method will convert an unsigned to a cdevMessageBinaryMap. + // ********************************************************************* + cdevMessageBinaryMap int2map ( cdevMessageBinaryMap &map, unsigned value); + + // ********************************************************************* + // * The streamIn function will populate the cdevMessageBinary using the + // * data that is specified in the stream. The stream remains the + // * property of the caller, who must delete it when it is no longer + // * needed. + // ********************************************************************* + virtual int streamIn ( char * stream, size_t len ); + + // ********************************************************************* + // * attachData : + // * This method allows the caller to assign a preallocated binary + // * buffer to this object. This prevents the cdevMessageBinary class + // * from having to allocate the data. + // ********************************************************************* + int attachData ( char * stream, size_t len ); + + // ********************************************************************* + // * Performs a diagnostic dump of the object. + // ********************************************************************* + virtual void asciiDump ( FILE * fp = stdout ); + + // ********************************************************************* + // * The set mechanism: + // * Allows the caller to dynamically change the contents of the + // * binary structure. + // ********************************************************************* + void set ( short clientID = -1, + unsigned transIndex = 0, + unsigned cancelTransIndex = 0, + unsigned localDataIndex = 0, + unsigned foreignDataIndex = 0, + unsigned operationCode = 0, + int completionCode = 0, + unsigned deviceCount = 0, + char ** deviceList = NULL, + char * message = NULL, + cdevData * data = NULL, + cdevData * context = NULL, + cdevData * tagMap = NULL ); + + // ********************************************************************* + // * The get mechanisms: + // * The pointers that are retrieved by these functions are the + // * actual pointers that are used within the class. They should not + // * be altered by the caller. The caller may alter the contents of + // * these objects by using the set mechanisms. + // ********************************************************************* + virtual int getVersion ( short & version ); + virtual int getClientID ( short & clientID ); + int getTransIndex ( unsigned & transIndex ); + int getCancelTransIndex ( unsigned & cancelTransIndex ); + int getLocalDataIndex ( unsigned & localDataIndex ); + int getForeignDataIndex ( unsigned & foreignDataIndex ); + int getOperationCode ( unsigned & operationCode ); + int getCompletionCode ( int & completionCode ); + int getDeviceList ( char ** & deviceList, unsigned & deviceCount ); + int getMessage ( char * & message ); + int getData ( cdevData & data ); + int getContext ( cdevData & context ); + int getTagMap ( cdevData & tagMap ); + int get ( short & clientID, + unsigned & transIndex, + unsigned & cancelTransIndex, + unsigned & localDataIndex, + unsigned & foreignDataIndex, + unsigned & operationCode, + int & completionCode, + unsigned & deviceCount, + char ** & deviceList, + char * & message, + cdevData & data, + cdevData & context, + cdevData & tagMap); + + // ********************************************************************* + // * The has mechanisms: + // * This collection of functions allows the caller to determine if + // * certain components of the packet are present. + // ********************************************************************* + int hasClientID ( void ) { return map.value.clientIDSet; } + int hasTransIndex ( void ) { return map.value.transIndexSet; } + int hasCancelTransIndex ( void ) { return map.value.cancelTransIndexSet; } + int hasLocalDataIndex ( void ) { return map.value.localDataIndexSet; } + int hasForeignDataIndex ( void ) { return map.value.foreignDataIndexSet; } + int hasOperationCode ( void ) { return map.value.operationCodeSet; } + int hasCompletionCode ( void ) { return map.value.completionCodeSet; } + int hasDeviceList ( void ) { return map.value.deviceListSet; } + int hasMessage ( void ) { return map.value.messageSet; } + int hasData ( void ) { return map.value.dataSet; } + int hasContext ( void ) { return map.value.contextSet; } + int hasTagMap ( void ) { return map.value.tagMapSet; } +}; + + +#endif /* CDEV_PACKET_BINARY_H_ */ diff --git a/extensions/cdevGenericServer/include/cdevMonitorTable.h b/extensions/cdevGenericServer/include/cdevMonitorTable.h new file mode 100644 index 0000000..88d0027 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevMonitorTable.h @@ -0,0 +1,136 @@ +#ifndef _CDEV_MONITOR_TABLE_H_ +#define _CDEV_MONITOR_TABLE_H_ 1 + +#include +#include +#include +#include + + +// ***************************************************************************** +// * class cdevMonitorData : +// * This class gives a cdevData object the capacity to selectively place +// * its tagged data items into an XDR stream. +// ***************************************************************************** +class GENERIC_SERVER_API cdevMonitorData : public cdevData +{ +protected: + int * criticalTags; + int criticalTagCnt; + + virtual int isTagCritical ( int tag ); + +public: + cdevMonitorData (void ); + cdevMonitorData (const cdevData & data); + cdevMonitorData (const cdevMonitorData & data); + + virtual void setCriticalTags ( int * tags, int tagCnt ); + virtual int changeTag ( int oldTag, int newTag ); + virtual int xdrExport ( char ** buf, size_t * bufLen ); + virtual int xdrExport ( char * buf, size_t bufLen, size_t count); + virtual int xdrSize ( size_t * bufLen, size_t * elementCount ); +}; + + +// ***************************************************************************** +// * class cdevMonitorNode : +// * This class is used to store the list of monitors associated with a +// * device / attribute pair. It maintains a back-pointer to the +// * cdevMonitorTable object to allow it to call the fireCallback method of +// * the parent in order to submit the reply. +// ***************************************************************************** +class GENERIC_SERVER_API cdevMonitorNode +{ +friend class cdevMonitorTable; + +protected: + // ********************************************************************** + // * class cdevMonitorEntry : + // * This is an individual monitor transaction that has been installed + // * in a cdevMonitorNode. + // ********************************************************************** + class cdevMonitorEntry + { + friend class cdevMonitorNode; + private: + static int VALUE_TAG; + static int STATUS_TAG; + static int TIME_TAG; + static int DEVICE_TAG; // *** Added for multi-device + + cdevMonitorEntry * next; + cdevMessage * message; + int * triggers; + int * trigType; + int trigCnt; + int * properties; + int propCnt; + + int deviceIdx; // *** Added for multi-device + + cdevMonitorEntry ( cdevMessage * Message, int deviceIdx ); + ~cdevMonitorEntry ( void ); + }; + + class cdevMonitorTable * parent; + cdevMonitorEntry * nodes; + cdevMonitorData mData; + char * hashString; + + virtual int fireMonitor ( cdevMonitorEntry *entry, + int property, + cdevMonitorData * data, + int endOfTransaction = 0); + + virtual int insertMonitor ( cdevMessage * request, + cdevData * data, + int deviceIdx ); + + virtual int removeMonitor ( cdevMessage * request ); + virtual int removeMonitor ( unsigned transIndex ); + virtual int removeClientMonitors ( short clientID, int fire = 1 ); + char * getHashString ( void ) { return hashString; } + +public: + cdevMonitorNode ( cdevMonitorTable * Parent, + char * Device, + char * Attrib ); + virtual ~cdevMonitorNode ( void ); + + virtual int fireMonitor ( char * property, cdevData * data ); + virtual int fireMonitor ( int property, cdevData * data ); + int isMonitored ( void ) { return nodes==NULL?0:1; } +}; + + + +// ***************************************************************************** +// * class cdevMonitorTable : +// * This class is used to store the list of all monitors for all device / +// * attribute pairs in the system. The developer must provide the +// * fireCallback method which will be used to submit the callback to the +// * client. +// ***************************************************************************** +class GENERIC_SERVER_API cdevMonitorTable +{ +protected: + StringHash monitors; + +public: + cdevMonitorTable ( void ); + virtual ~cdevMonitorTable ( void ); + + virtual int insertMonitor ( cdevMessage * request, cdevData * data ); + virtual int insertMonitor ( cdevMessage * request, cdevData ** data, size_t dataCnt ); + virtual int removeMonitor ( cdevMessage * request ); + virtual int removeClientMonitors( short clientID, int fire = 1 ); + virtual cdevMonitorNode * findMonitor ( char * device, char * attrib ); + virtual int fireMonitor ( char * device, char * attrib, + char * property, cdevData * data ); + virtual int fireMonitor ( char * device, char * attrib, + int property, cdevData * data ); + virtual int fireCallback ( cdevMessage * message ); +}; + +#endif diff --git a/extensions/cdevGenericServer/include/cdevPacket.h b/extensions/cdevGenericServer/include/cdevPacket.h new file mode 100644 index 0000000..819c6a9 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevPacket.h @@ -0,0 +1,35 @@ +#ifndef _CDEV_PACKET_ +#define _CDEV_PACKET_ + +#include + +class GENERIC_SERVER_API cdevPacket +{ +public: + typedef cdevPacket * (*ImportMethod)(cdevPacketBinary &); + + typedef struct + { + short packetVersion; + ImportMethod importMethod; + } ImportTable; + + static cdevPacket * import ( cdevPacketBinary & ); + static void registerImportMethod ( short, ImportMethod ); + + cdevPacket ( void ) {} + virtual ~cdevPacket ( void ) {} + + virtual int streamIn ( char * binary, size_t binaryLen ) = 0; + virtual int streamOut ( char ** binary, size_t * binaryLen ) = 0; + virtual void asciiDump ( FILE * fp = stdout ) = 0; + + virtual short getVersion ( void ) = 0; + virtual short getClientID ( void ) = 0; + virtual void setClientID ( short ClientID ) = 0; + +private: + static ImportTable * importTables; + static int maxTables; +}; +#endif diff --git a/extensions/cdevGenericServer/include/cdevPacketBinary.h b/extensions/cdevGenericServer/include/cdevPacketBinary.h new file mode 100644 index 0000000..db13ffe --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevPacketBinary.h @@ -0,0 +1,322 @@ +#ifndef _CDEV_PACKET_H_ +#define _CDEV_PACKET_H_ + +#include +#include +#include + +// ***************************************************************************** +// * struct cdevPacketBinaryMap : +// * This is the first 32 bit integer that is passed through the socket. It +// * contains a bitmap that identifies the version of the packet, as well as +// * a bit field that indicates the contents of the packet. This bitfield +// * simplifies the process of decoding the packet and results in a smaller +// * transmission size. +// ***************************************************************************** +typedef union + { + unsigned rawData; + struct { + unsigned version : 16; + unsigned pad : 16; + } value; + } cdevPacketBinaryMap; + +// ***************************************************************************** +// * class cdevPacketBinary : +// * This is the base class for all cdevPacketBinary classes. It is a pure +// * virtual class that defines the mechanisms necessary for identifying +// * the version of a class as well as reading or generating a binary +// * stream. +// * +// * Enforced structural contraints... +// * +// * 1) Every packet that inherits from the cdevPacketBinary must have an +// * XDR encoded 4 byte integer at the beginning... +// * +// * a) The first two bytes of that 4 byte integer is the packet version. +// * +// * b) The second two bytes of that 4 byte integer is user defined data. +// * +// * 2) The next four bytes of the packet contains a XDR encoded short +// * integer that contains a 16 bit client identifier. +// ***************************************************************************** +class GENERIC_SERVER_API cdevPacketBinary +{ +protected: + // ********************************************************************* + // * These are the data storage variables. + // ********************************************************************* + char * binary; + size_t binaryLen; + +public: + cdevPacketBinary ( void ); + cdevPacketBinary ( cdevPacketBinary & packet ); + virtual ~cdevPacketBinary ( void ); + + unsigned map2int ( cdevPacketBinaryMap map, unsigned & value); + cdevPacketBinaryMap int2map ( cdevPacketBinaryMap &map, unsigned value); + + virtual int getVersion ( short & version ); + virtual int getPad ( short & pad ); + virtual int getClientID ( short & clientID ); + virtual int setClientID ( short clientID ); + virtual int streamOut ( char ** stream, size_t * len ); + virtual int streamIn ( char * stream, size_t len ); + virtual void detachData ( void ); + virtual int attachData ( char * stream, size_t len ); +}; + +// ***************************************************************************** +// * cdevPacketBinary::map2int ( void ) +// * This method will convert the cdevPacketBinaryMap to a long integer. +// ***************************************************************************** +inline unsigned cdevPacketBinary::map2int ( cdevPacketBinaryMap map, unsigned & value) + { + value = (map.value.version << 16); + value |= (map.value.pad & 0xFFFF); + + return value; + } + +// ***************************************************************************** +// * cdevPacketBinary::int2map ( void ) +// * This method will convert a long integer to a cdevPacketBinaryMap. +// ***************************************************************************** +inline cdevPacketBinaryMap cdevPacketBinary::int2map ( cdevPacketBinaryMap &map, unsigned value) + { + map.rawData = 0; + map.value.version = (value >> 16); + map.value.pad = (value & 0xFFFF); + return map; + } + + +// ***************************************************************************** +// * cdevPacketBinary::getVersion : +// * This method is used to obtain the version number of the packet. +// * +// * Returns 0 on Success or -1 on Error +// ***************************************************************************** +inline int cdevPacketBinary::getVersion ( short & version ) + { + int result=-1; + XDR_Reader reader; + cdevPacketBinaryMap map; + + version = -1; + + if(binary!=NULL && binaryLen>0) + { + unsigned packetMap = 0; + reader.attachData(binary, binaryLen); + map.rawData = 0; + if((result = !reader.get(packetMap))==0) + { + int2map(map, packetMap); + version = map.value.version; + } + reader.detachData(); + } + return result; + } + +// ***************************************************************************** +// * cdevPacketBinary::getPad : +// * This method is used to obtain the 16 bit integer that follows the +// * packet version. +// ***************************************************************************** +inline int cdevPacketBinary::getPad ( short & pad ) + { + int result=-1; + XDR_Reader reader; + cdevPacketBinaryMap map; + + pad = -1; + + if(binary!=NULL && binaryLen>0) + { + unsigned packetMap = 0; + reader.attachData(binary, binaryLen); + map.rawData = 0; + if((result = !reader.get(packetMap))==0) + { + int2map(map, packetMap); + pad = map.value.pad; + } + reader.detachData(); + } + return result; + } + + +// ***************************************************************************** +// * cdevPacketBinary::getClientID : +// * This method is used to obtain the 16 bit integer that contains the +// * client identifier. +// ***************************************************************************** +inline int cdevPacketBinary::getClientID ( short & clientID ) + { + int result = -1; + XDR_Reader reader; + + clientID = -1; + + if(binary!=NULL && binaryLen>0) + { + reader.attachData(binary, binaryLen); + if((result = !xdr_setpos(reader.xdr(), XDR_Sizeof((unsigned)1)))==0) + { + result = !reader.get(clientID); + } + reader.detachData(); + } + return result; + } + + +// ***************************************************************************** +// * cdevPacketBinary::getClientID : +// * This method is used to insert the 16 bit integer that contains the +// * client identifier. +// ***************************************************************************** +inline int cdevPacketBinary::setClientID ( short clientID ) + { + int result = -1; + XDR_Writer writer; + + if(binary!=NULL && binaryLen>0) + { + writer.attachData(binary, binaryLen); + if((result = !xdr_setpos(writer.xdr(), XDR_Sizeof((unsigned)1)))==0) + { + result = !writer.put(clientID); + } + writer.detachData(); + } + return result; + } + + +// ***************************************************************************** +// * cdevPacketBinary::streamIn : +// * The streamIn function will read a memory buffer provided by the caller +// * and then populate the class with these values. This stream remains the +// * property of the caller and he is responsible for deleting it. +// * +// * Returns 0 on Success +// ***************************************************************************** +inline int cdevPacketBinary::streamIn ( char * stream, size_t len ) + { + if(binary!=NULL) + { + delete binary; + binary = NULL; + } + binaryLen = 0; + + if(len>0 && stream!=NULL) + { + binary = new char[len]; + binaryLen = len; + memcpy(binary, stream, binaryLen); + } + return 0; + } + +// ***************************************************************************** +// * cdevPacketBinary::streamOut : +// * The streamOut and streamIn functions are the bread and butter of the +// * cdevPacketBinary classes. They allow the class to convert itself into a +// * binary stream for transmission and then be reconstructed into a class +// * when they are received on the other side. +// * +// * The streamOut function will allocate a memory buffer to the stream +// * variable that is sufficient to store the binary representation of +// * the data that is to be transmitted. This stream remains the +// * property of the cdevPacketBinary class and should not be deleted by the +// * caller. +// * +// * Returns 0 on Success +// ***************************************************************************** +inline int cdevPacketBinary::streamOut ( char ** stream, size_t * len ) + { + *stream = binary; + *len = binaryLen; + return 0; + } + +// ********************************************************************* +// * cdevPacketBinary::detachData : +// * This method allows the caller to obtain a copy of the binary +// * image that is stored in the cdevPacketBinary object (using +// * streamOut), and then force the cdevPacket object to detach it +// * (preventing it from being deleted when the object is destroyed.) +// * +// * Returns nothing. +// ********************************************************************* +inline void cdevPacketBinary::detachData ( void ) + { + binary = NULL; + binaryLen = 0; + } + +// ********************************************************************* +// * cdevPacketBinary::attachData : +// * This method allows the caller to assign a preallocated binary +// * buffer to this object. This prevents the cdevPacketBinary class +// * from having to allocate the data. +// * +// * Returns 0 on Success +// ********************************************************************* +inline int cdevPacketBinary::attachData ( char * stream, size_t len ) + { + if(binary!=NULL) + { + delete binary; + binary = NULL; + } + binaryLen = 0; + + if(stream!=NULL && len>0) + { + binary = stream; + binaryLen = len; + } + return 0; + } + +// ***************************************************************************** +// * cdevPacketBinary::cdevPacketBinary : +// * This is the default constructor for the class. +// ***************************************************************************** +inline cdevPacketBinary::cdevPacketBinary ( void ) + : binary(NULL), binaryLen(0) + {} + +// ***************************************************************************** +// * cdevPacketBinary::cdevPacketBinary : +// * This is the copy constructor for the class. +// ***************************************************************************** +inline cdevPacketBinary::cdevPacketBinary ( cdevPacketBinary & packet ) + : binary(NULL), binaryLen(0) + { + streamIn(packet.binary, packet.binaryLen); + } + +// ***************************************************************************** +// * cdevPacketBinary::~cdevPacketBinary : +// * This is the destructor for the object. +// ***************************************************************************** +inline cdevPacketBinary::~cdevPacketBinary ( void ) + { + if(binary!=NULL) + { + delete binary; + binary = NULL; + } + binaryLen = 0; + } + +#endif /* _CDEV_PACKET_H_ */ diff --git a/extensions/cdevGenericServer/include/cdevPlatforms.h b/extensions/cdevGenericServer/include/cdevPlatforms.h new file mode 100644 index 0000000..f0d95d3 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevPlatforms.h @@ -0,0 +1,334 @@ +#ifndef _CDEV_PLATFORMS_H_ +#define _CDEV_PLATFORMS_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 + #include + + #ifndef CDEV_REACTOR_API + // ********************************************************************* + // * _CDEV_REACTOR_EXPORTS : + // * This definition allows cdevReactor DLL components to be imported + // * and exported by other applications and libraries. + // ********************************************************************* + #ifdef _CDEV_REACTOR_EXPORTS_ + #define CDEV_REACTOR_API __declspec(dllexport) + #else + #define CDEV_REACTOR_API __declspec(dllimport) + #endif + #endif + + #ifndef GENERIC_SERVER_API + // ********************************************************************* + // * _GENERIC_SERVER_EXPORTS : + // * This definition allows Generic Server DLL components to be imported + // * and exported by other applications and libraries. + // ********************************************************************* + #ifdef _GENERIC_SERVER_EXPORTS_ + #define GENERIC_SERVER_API __declspec(dllexport) + #else + #define GENERIC_SERVER_API __declspec(dllimport) + #endif + #endif + + #include + #include + #include + #include + #include + #include + #include + #include + + typedef signed long ssize_t; + + #define MAXHOSTNAMELEN 128 + #define EWOULDBLOCK WSAEWOULDBLOCK + #define EINPROGRESS WSAEINPROGRESS + #define EISCONN WSAEISCONN + #define SELECT_PARM fd_set * + + #ifndef O_NONBLOCK + #define O_NONBLOCK 1 + #endif + + // ********************************************************************* + // * SOCKOPT_SIZE_PARM : + // * This is the datatype of the parameter that is sent to getsockopt, + // * setsockopt, and getsockname. + // ********************************************************************* + typedef int SOCKOPT_SIZE_PARM; + + inline int GetSocketErrno ( void ) + { + return WSAGetLastError(); + } + + inline int GetSelectErrno ( void ) + { + return WSAGetLastError(); + } + + inline int InitializeNetwork ( void ) + { + WORD version_requested = MAKEWORD (2, 0); + WSADATA wsa_data; + return WSAStartup(version_requested, &wsa_data); + } + + inline int TerminateNetwork ( void ) + { + return WSACleanup(); + } + + inline char * ultoa ( unsigned long val ) + { + static char buf[64]; + return _ultoa(val, buf, 10); + } + + inline char * ltoa ( long val ) + { + static char buf[64]; + return _ltoa(val, buf, 10); + } + + inline int usleep ( unsigned int useconds ) + { + int retval = 0; + if(useconds<100000) Sleep(useconds/1000); + else retval = -1; + return retval; + } + + inline unsigned int sleep ( unsigned int seconds ) + { + Sleep(seconds*1000); + return seconds; + } + + // ********************************************************************* + // * This version of pipe is provided because the file descriptors + // * generated by the Windows NT version of pipe cannot be used with the + // * select system call. + // ********************************************************************* + inline int pipe ( int fd[2] ) + { + int retval = 0; + sockaddr_in addr[2]; + hostent * hostptr; + char hostname[MAXHOSTNAMELEN]; + unsigned long ipAddr; + unsigned long blockFlag = 1; + + gethostname(hostname, MAXHOSTNAMELEN); + hostptr = ::gethostbyname(hostname); + ipAddr = *(unsigned long *)hostptr->h_addr; + + for(int i=0; i<2; i++) + { + addr[i].sin_family = AF_INET; + addr[i].sin_port = htons(0); + *(unsigned long *)&addr[i].sin_addr = ipAddr; + if((fd[i] = socket(PF_INET, SOCK_DGRAM,0))>0 && + bind(fd[i], (sockaddr *)&addr[i], sizeof(addr[i]))==0) + { + int addrLen = sizeof(addr[i]); + getsockname(fd[i], (sockaddr *)&addr[i], &addrLen); + ioctlsocket(fd[i], FIONBIO, &blockFlag); + } + else fd[i] = -1; + } + if(fd[0]>0 && fd[1]>0) + { + ::connect(fd[0], (sockaddr *)&addr[1], sizeof(addr[1])); + ::connect(fd[1], (sockaddr *)&addr[0], sizeof(addr[0])); + } + else + { + if(fd[0]>0) close(fd[0]); + if(fd[1]>0) close(fd[1]); + fd[0] = (fd[1] = (retval = -1)); + } + return retval; + } + + inline int FileTimeToTimeVal ( FILETIME * tfile, struct timeval * tv ) + { + if(tfile && tv) + { + ULARGE_INTEGER _100ns = {tfile->dwLowDateTime, + tfile->dwHighDateTime}; + + _100ns.QuadPart -= 0x19db1ded53e8000i64; + + tv->tv_sec = long (_100ns.QuadPart / (10000 * 1000)); + tv->tv_usec = long ((_100ns.QuadPart % (10000 * 1000)) / 10); + + return 0; + } + return -1; + } + + inline int gettimeofday (struct timeval *tv) + { + FILETIME tfile; + + GetSystemTimeAsFileTime(&tfile); + + return FileTimeToTimeVal(&tfile, tv); + } + + inline int cdevSelect ( + int size, + fd_set * read_set, + fd_set * write_set, + fd_set * except_set, + struct timeval * timeout ) + { + int result = select(size, read_set, write_set, except_set, timeout); + + if(result<0 && GetSelectErrno()==WSAEINVAL) + { + if(timeout) + { + unsigned long millisec = timeout->tv_sec*1000+timeout->tv_usec/1000; + Sleep(millisec); + } + result = 0; + } + else if (result<0 && GetSelectErrno()==WSAEINPROGRESS) + { + result = 0; + } + return result; + } +#else + #include + + #define CDEV_REACTOR_API + #define GENERIC_SERVER_API + + #ifdef __VMS + #ifdef _TGV_MULTINET + // ***************************************************** + // * Under TGV multinet and VMS, if you want sys/types.h + // * you need to have types.h already pulled in because + // * sys/types.h makes it look like types.h is loaded. + // * Then when types.h does get loaded, it is ignored + // * because it looks like it is already loaded -- + // * Mr. Danial Van Olst + // ***************************************************** + #include + + // ***************************************************** + // * Under TGV Multinet and VMS, the file sys/param.h + // * does not define NOFILE (max number of open files + // * per process). FD_SETSIZE seems to be the correct + // * value for NOFILE. + // * See Multinet's sys/types.h file for more info on + // * FD_SETSIZE. - Daniel Van Olst + // ***************************************************** + #ifndef NOFILE + #define NOFILE FD_SETSIZE + #endif + #endif + #endif + + #ifdef SYSV + #include + #endif + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + + #if defined (__hpux) + #include + #endif + + #if defined (AIX) + #include + #endif + + #if defined(solaris) || defined(SunOS) + #include + extern "C" { int gethostname(char *name, int namelen); } + #endif + + #ifdef _SELECT_USES_INT_ + #define SELECT_PARM int * + #else + #define SELECT_PARM fd_set * + #endif + + #ifndef min + #define min(a,b) ((ab)?a:b) + #endif + + // ********************************************************************* + // * SOCKOPT_SIZE_PARM : + // * This is the datatype of the parameter that is sent to getsockopt, + // * setsockopt, and getsockname. + // ********************************************************************* + #if defined(AIX) || defined(__linux) + typedef unsigned int SOCKOPT_SIZE_PARM; + #else + typedef int SOCKOPT_SIZE_PARM; + #endif + + inline int GetSocketErrno ( void ) + { + return errno; + } + + inline int GetSelectErrno ( void ) + { + return errno; + } + + inline int InitializeNetwork ( void ) + { + return 0; + } + + inline int TerminateNetwork ( void ) + { + return 0; + } + + inline int gettimeofday (struct timeval * tv) + { + struct timezone tz; + + return ::gettimeofday(tv, &tz); + } + + inline int cdevSelect (int nfds, fd_set *r, fd_set *w, fd_set *e, struct timeval *t) + { + return ::select(nfds, (SELECT_PARM)r, (SELECT_PARM)w, (SELECT_PARM)e, t); + } +#endif + +#endif /* _CDEV_PLATFORMS_H_ */ diff --git a/extensions/cdevGenericServer/include/cdevReactor.h b/extensions/cdevGenericServer/include/cdevReactor.h new file mode 100644 index 0000000..ffe8dd5 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevReactor.h @@ -0,0 +1,65 @@ +#ifndef _CDEV_REACTOR_H_ +#define _CDEV_REACTOR_H_ 1 + +#include "cdevTime.h" +#include "cdevHandleSet.h" +#include "cdevEventHandler.h" + +class CDEV_REACTOR_API cdevReactor +{ +public: +typedef enum { + INPUT = 0, + OUTPUT = 1, + EXCEPTION = 2, + SIGNAL = 3 + } REACTOR_EVENT; + +typedef enum { + REACTOR_ERROR = -1, + SUCCESS = 0, + INVALID_HANDLE = 1, + INVALID_HANDLER = 2, + HANDLE_EXISTS = 3, + UNKNOWN_HANDLER = 4, + INVALID_TIMEOUT = 5 + } REACTOR_RESULT; + +typedef enum { + UNTIL_TIMEOUT = 0, + UNTIL_EVENT = 1 + } HANDLE_EVENT_FLAG; + +protected: + static int netInitCount; + + int maxEntries; + int size; + cdevHandleSet read_set; + cdevHandleSet write_set; + cdevHandleSet except_set; + cdevEventHandler ** handlers; + cdevEventHandler * timers; + +private: + void calculateMask ( void ); + int calculateTimeout ( cdevTime defaultPeriod, struct timeval &timeout ); + int handleFileEvent ( cdevHandleSet * fds, REACTOR_EVENT event); +public: + cdevReactor ( void ); + virtual ~cdevReactor ( void ); + + virtual int checkHandlers ( void ); + virtual int registerHandler ( cdevEventHandler * handler, unsigned mask ); + virtual int removeHandler ( cdevEventHandler * handler ); + virtual int removeHandler ( int fd ); + virtual int extractHandler ( cdevEventHandler * handler ); + virtual int getHandler ( int fd, cdevEventHandler * &handler ); + + virtual int registerTimer ( cdevEventHandler * timer ); + virtual int cancelTimer ( cdevEventHandler * timer ); + + virtual int handleEvents ( cdevTime period = -1.0, int flags = UNTIL_TIMEOUT ); +}; + +#endif diff --git a/extensions/cdevGenericServer/include/cdevServer.h b/extensions/cdevGenericServer/include/cdevServer.h new file mode 100644 index 0000000..ec53261 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevServer.h @@ -0,0 +1,120 @@ +#if !defined (_CDEV_SERVER_H_) +#define _CDEV_SERVER_H_ + +#include "SignalManager.h" +#include "cdevServerTools.h" +#include "cdevMessage.h" +#include "cdevContextMap.h" +#include "cdevTagMap.h" +#include "ClientInfo.h" +#include "ServerInfo.h" +#include "cdevGenericServerTags.h" + +// ***************************************************************************** +// * class CLIPClientSession : +// * +// * This class also allows the server to associate certain data with a +// * specific client... +// * +// * context: This is a pointer to the most recently used context from the +// * cdevContextMap. +// ***************************************************************************** +class GENERIC_SERVER_API CLIPClientSession : public ClientSession +{ +private: + cdevData *context; + +public: + CLIPClientSession ( int SocketID, int ClientID, int LocalID ) + : ClientSession(SocketID, ClientID, LocalID), + context(NULL) + { + } + virtual ~CLIPClientSession ( void ) { } + cdevData * getContext ( void ) { return context; } + void setContext ( cdevData * cxt ) { context = cxt; } +}; + + +// ***************************************************************************** +// * class CLIPSocketSession : +// * +// * This class allows the developer to associate additional information with +// * a particular socket... +// * +// * contextMap : a table of cdevData contexts that can be retrieved by index +// * +// * tagMap : the table for mapping cdevData tags from the remote system +// * to the tag table associated with this system. +// ***************************************************************************** +class GENERIC_SERVER_API CLIPSocketSession : public SocketSession, public ClientInfoStruct +{ +private: + cdevContextMap contextMap; + cdevTagMap tagMap; + +public: + CLIPSocketSession ( int SocketID ) + : SocketSession ( SocketID ) + { + } + virtual ~CLIPSocketSession ( void ) { } + cdevContextMap & ContextMap ( void ) { return contextMap; } + cdevTagMap & TagMap ( void ) { return tagMap; } +}; + + +// ***************************************************************************** +// * cdevServer : +// * This is the cdevServer class. It is responsible for establishing a +// * listening socket, and then responding to all incoming and outgoing +// * messages. +// ***************************************************************************** +class GENERIC_SERVER_API cdevServer : public cdevSessionManager +{ +public: + typedef enum { SUCCESS = 0, + UNINITIALIZED, + CANT_OPEN_SOCKET, + CANT_REGISTER_LISTENER, + CANT_REGISTER_SERVER, + CANT_REGISTER_TIMER + } ServerInitStatus; + +protected: + char * serverName; + class ClientAcceptor * acceptor; + cdevNameServerManager * timer; + ServerInitStatus status; + ServerInfo * serverInfo; + +public: + static cdevGenericServerTagDef tags; + static SignalManager SigManager; + static sig_atomic_t Finished; + + static void runServer (void); + + cdevServer (char * DomainName, char * ServerName, unsigned short Port, double Rate); + cdevServer (void); + virtual ~cdevServer (void); + int startServer (char * DomainName, char * ServerName, unsigned short Port, double Rate, int searchForPort=0); + + virtual void registerClient ( short localID ); + virtual void unregisterClient ( short localID ); + + virtual ClientSession * newClientSession ( int SocketID, int ClientID, int LocalID ); + virtual SocketSession * newSocketSession ( int SocketID ); + virtual void deleteSocketSession ( SocketSession *socket ); + + virtual int dequeue (cdevMessage * &message); + void processLocal (cdevMessage * &message); + virtual cdevPacket * decodePacket (cdevPacketBinary * input); + virtual cdevPacket * decodePacket (cdevMessage * message); + virtual cdevPacketBinary * encodePacket (cdevPacket * input); + virtual cdevPacketBinary * encodePacket (cdevMessage * message); + virtual int operational (void) { return (status==0)?1:0; } + virtual ServerInitStatus getInitStatus(void) { return status; } +}; + +#endif /* _CDEV_SERVER_H_ */ diff --git a/extensions/cdevGenericServer/include/cdevServerTools.h b/extensions/cdevGenericServer/include/cdevServerTools.h new file mode 100644 index 0000000..8703e8b --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevServerTools.h @@ -0,0 +1,113 @@ +#if !defined (_CDEV_SERVER_TOOLS_H_) +#define _CDEV_SERVER_TOOLS_H_ + +#ifndef DONT_SUPPORT_CDEV_CALLS + #include "cdevSystemEventHandler.h" +#endif + +#include "cdevSessionManager.h" +#include "cdevMessage.h" +#include "rsvcClient.h" +#include "rsvcUdpClient.h" + +// ***************************************************************************** +// * This is the cdevSimpleTimer class. The user specifies a function, a rate +// * and a void * data pointer. The ACE_Reactor will then call the function +// * each time the period of time expires. +// ***************************************************************************** +class GENERIC_SERVER_API cdevSimpleTimer : public cdevEventHandler, public ErrorReporter +{ +public: + cdevSimpleTimer ( cdevReactor & Reactor, double Rate = 1.0 ); + ~cdevSimpleTimer ( void ); + virtual int handleTimeout (void); + virtual int execute (void) = 0; +}; + + +// ***************************************************************************** +// * class cdevNameServerManager: +// * This class will extract the list of cdev Name Servers from the +// * CDEV_NAME_SERVER environment variable and will create a collection +// * of cdevNameServerHandler objects that will manage the connections +// * to them. These cdevNameServerHandler objects will register the +// * server with the name server and will send updates every five seconds. +// * If the connection to the specific name server is lost, the +// * cdevNameServer handler will call the unregisterHandler method to +// * terminate the connection and before being deleted. This object +// * will then attempt to reestablish the connection periodically. +// ***************************************************************************** +class GENERIC_SERVER_API cdevNameServerManager : public cdevEventHandler, public ErrorReporter +{ +protected: + char ** nameServerList; + class cdevNameServerHandler ** nameServerHandlers; + size_t nameServerCnt; + rsvcData serverInfo; + rsvcData updateInfo; + char * serverName; + char * domainName; + unsigned short serverPort; + +public: + cdevNameServerManager ( cdevReactor & Reactor, char * DomainName, char * ServerName, unsigned short port); + ~cdevNameServerManager ( void ); + + static void rsvcCallback (int status, void* arg, rsvcData* data); + + virtual int handleTimeout ( void ); + void unregisterHandler ( size_t index ); + rsvcData * getServerInfo ( void ) { return &serverInfo; } + rsvcData * getUpdateInfo ( void ) { return &updateInfo; } + char * getHostName ( size_t index ) { return (index +#include +#include "cdevAddr.h" + +class CDEV_REACTOR_API cdevSocket +{ +protected: + int handle; + sockaddr_in sa; + + cdevSocket(void); + cdevSocket(int type, int protocol_family, int protocol=0); + +public: + enum {INVALID_HANDLE=-1}; + + void setHandle (int fd); + int getHandle (void) const; + int open (int type, int protocol_family, int protocol); + int close (void); + int unsetFlags (int flags); + int setFlags (int flags); + int getFlags (void); + int setOption (int level, int option, void *optval, int optlen) const; + int getOption (int level, int option, void *optval, int *optlen) const; + int getLocalAddress (cdevAddr & address); + int getRemoteAddress (cdevAddr & address); +}; + + +#endif diff --git a/extensions/cdevGenericServer/include/cdevSocketAcceptor.h b/extensions/cdevGenericServer/include/cdevSocketAcceptor.h new file mode 100644 index 0000000..dbefb46 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevSocketAcceptor.h @@ -0,0 +1,32 @@ +#ifndef _CDEV_SOCKET_ACCEPTOR_H_ +#define _CDEV_SOCKET_ACCEPTOR_H_ + +#include "cdevSocketStream.h" + +class CDEV_REACTOR_API cdevSocketAcceptor : public cdevSocket +{ +public: + cdevSocketAcceptor(void); + cdevSocketAcceptor( + const cdevAddr &addr, + int reuse_addr = 0, + int protocol_family = PF_INET, + int backlog = 5, + int protocol = 0); + + int open(const cdevAddr &addr, + int reuse_addr = 0, + int protocol_family = PF_INET, + int backlog = 5, + int protocol = 0, + int reopen = 1); + + int accept( + cdevSocketStream &new_stream, + cdevAddr *remote_addr=0) const; + +private: + int getRemoteAddress(cdevAddr &) const; +}; + +#endif /* _CDEV_SOCKET_ACCEPTOR_H */ diff --git a/extensions/cdevGenericServer/include/cdevSocketConnector.h b/extensions/cdevGenericServer/include/cdevSocketConnector.h new file mode 100644 index 0000000..8dc1d72 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevSocketConnector.h @@ -0,0 +1,12 @@ +#ifndef _CDEV_SOCKET_CONNECTOR_H_ +#define _CDEV_SOCKET_CONNECTOR_H_ + +#include "cdevSocketStream.h" + +class CDEV_REACTOR_API cdevSocketConnector : public cdevSocketStream +{ +public: + int connect (const cdevAddr & remote_addr ); +}; + +#endif /* _CDEV_SOCK_CONNECTOR_H */ diff --git a/extensions/cdevGenericServer/include/cdevSocketDatagram.h b/extensions/cdevGenericServer/include/cdevSocketDatagram.h new file mode 100644 index 0000000..f2a1056 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevSocketDatagram.h @@ -0,0 +1,18 @@ +#if !defined (_CDEV_SOCKET_DATAGRAM_H_) +#define _CDEV_SOCKET_DATAGRAM_H + +#include "cdevSocket.h" +#include "cdevAddr.h" + +class CDEV_REACTOR_API cdevSocketDatagram : public cdevSocket +{ +public: + cdevSocketDatagram (void); + cdevSocketDatagram (const cdevAddr &addr, int protocol_family = PF_INET, int protocol = 0); + int open (const cdevAddr &addr, int protocol_family = PF_INET, int protocol = 0); + ssize_t send (const void *buf, size_t n, const cdevAddr &addr, int flags = 0) const; + ssize_t recv (void *buf, size_t n, cdevAddr &addr, int flags = 0) const; + +}; + +#endif /* _CDEV_SOCKET_DATAGRAM_H_ */ diff --git a/extensions/cdevGenericServer/include/cdevSocketStream.h b/extensions/cdevGenericServer/include/cdevSocketStream.h new file mode 100644 index 0000000..765922c --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevSocketStream.h @@ -0,0 +1,29 @@ +#if !defined (_CDEV_SOCKET_STREAM_H) +#define _CDEV_SOCKET_STREAM_H + +#include "cdevSocket.h" +#include + + +class CDEV_REACTOR_API cdevSocketStream : public cdevSocket +{ +public: + cdevSocketStream (void); + ssize_t send (const void *buf, size_t n, int flags=0) const; + ssize_t recv (void *buf, size_t n, int flags=0); + ssize_t send_n (const void *buf, size_t n, int flags=0) const; + ssize_t recv_n (void * buf, size_t n, int flags=0); + + int closeReader (void); + int closeWriter (void); + + virtual int getBlockingSemantics ( void ) const; + virtual int getRcvLowWaterMark ( void ) const; + virtual int getSndLowWaterMark ( void ) const; + virtual int getRcvBufferSize ( void ) const; + virtual int getSndBufferSize ( void ) const; + virtual int configureHandle ( void ); +}; + +#endif /* _CDEV_SOCKET_STREAM_H_ */ + diff --git a/extensions/cdevGenericServer/include/cdevStreamNode.h b/extensions/cdevGenericServer/include/cdevStreamNode.h new file mode 100644 index 0000000..fb7f9af --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevStreamNode.h @@ -0,0 +1,33 @@ +#ifndef _CDEV_STREAM_NODE_H_ +#define _CDEV_STREAM_NODE_H_ + +#include "cdevPlatforms.h" + +// ***************************************************************************** +// * class cdevStreamNode : +// * This is a virtual base class that defines the functionality that will +// * be required for data nodes that are inserted into the +// * cdevBufferedSocket. +// ***************************************************************************** +class CDEV_REACTOR_API cdevStreamNode +{ +friend class cdevStreamQueue; + +public: + virtual ~cdevStreamNode ( void ); + + virtual size_t getLen(void) const = 0; + virtual void setLen(size_t size) = 0; + virtual char * getBuf(void) const = 0; + virtual void setBuf(char * buf, size_t len) = 0; + +protected: + cdevStreamNode * nextStreamNode; + + cdevStreamNode ( void ); + + cdevStreamNode * getNext( void ) const; + void setNext(cdevStreamNode * node); +}; + +#endif /* _CDEV_STREAM_NODE_H_ */ diff --git a/extensions/cdevGenericServer/include/cdevStreamQueue.h b/extensions/cdevGenericServer/include/cdevStreamQueue.h new file mode 100644 index 0000000..d58fa5d --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevStreamQueue.h @@ -0,0 +1,126 @@ +#ifndef _CDEV_STREAM_QUEUE_H_ +#define _CDEV_STREAM_QUEUE_H_ + +#include "cdevStreamNode.h" + +// ***************************************************************************** +// * class cdevSimpleStreamNode : +// * This is a simple implementation class of the cdevStreamNode. It will +// * be used if the developer does not provide his own implementation class. +// ***************************************************************************** +class CDEV_REACTOR_API cdevSimpleStreamNode : public cdevStreamNode +{ +protected: + char * buf; + size_t len; + +public: + cdevSimpleStreamNode ( char * buffer=NULL, size_t size=0); + ~cdevSimpleStreamNode ( void ); + + size_t getLen (void) const; + void setLen (size_t size); + char * getBuf (void) const; + void setBuf (char * buffer, size_t size); +}; + + +// ***************************************************************************** +// * class cdevNodeFactory : +// * This class will generate a user defined instance of a cdevStreamNode +// * sub-class. This class is used within the cdevBufferedSocket to +// * convert incoming binary packets into a user defined structure. +// ***************************************************************************** +class CDEV_REACTOR_API cdevNodeFactory +{ +public: + virtual ~cdevNodeFactory ( void ); + + virtual cdevStreamNode * newNode ( ssize_t size ) = 0; +}; + + + +// ***************************************************************************** +// * class cdevStreamQueue : +// * This is a class that will store the data items that are being enqueued +// * by the cdevBufferedSocket. +// ***************************************************************************** +class CDEV_REACTOR_API cdevStreamQueue +{ +private: + cdevStreamNode * head; + cdevStreamNode * tail; + int deleteFlag; + size_t nEntries; + size_t totalLen; + +public: + cdevStreamQueue ( int deleteNodesFlag = 1 ) + : head(NULL), tail(NULL), deleteFlag(deleteNodesFlag), + nEntries(0), totalLen(0) + { + } + + ~cdevStreamQueue ( void ) + { + if(deleteFlag) while(!isEmpty()) delete dequeue(); + } + + void enqueue( cdevStreamQueue & queue ) + { + head = queue.head; + tail = queue.tail; + nEntries = queue.nEntries; + totalLen = queue.totalLen; + queue.head = NULL; + queue.tail = NULL; + queue.nEntries = 0; + queue.totalLen = 0; + } + + void enqueue ( cdevStreamNode * node ) + { + if(node) + { + if(tail!=NULL) tail->setNext(node); + else head = node; + tail = node; + totalLen+=(node->getLen()+sizeof(node->getLen())); + nEntries++; + } + } + + cdevStreamNode * dequeue ( void ) + { + cdevStreamNode * node = NULL; + if(head!=NULL) + { + node = head; + head = node->getNext(); + node->setNext(NULL); + if(head==NULL) tail = NULL; + totalLen-=(node->getLen()+sizeof(node->getLen())); + nEntries--; + } + return node; + } + + cdevStreamNode * peek ( void ) + { + return head; + } + + void poke ( cdevStreamNode * node ) + { + node->setNext(head); + head = node; + if(tail==NULL) tail = head; + } + + int isEmpty ( void ) const { return head==NULL?1:0; } + size_t getCount ( void ) const { return nEntries; } + size_t getSize ( void ) const { return totalLen; } +}; + +#endif /* _CDEV_STREAM_QUEUE_H */ diff --git a/extensions/cdevGenericServer/include/cdevSystemEventHandler.h b/extensions/cdevGenericServer/include/cdevSystemEventHandler.h new file mode 100644 index 0000000..cdcd876 --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevSystemEventHandler.h @@ -0,0 +1,90 @@ +#include "cdevSystem.h" +#include "cdevSessionManager.h" + +class GENERIC_SERVER_API cdevSystemEventHandler : public cdevEventHandler +{ +private: + int cdevfd; + +public: + cdevSystemEventHandler ( cdevReactor & Reactor, int fd ) + : cdevfd(fd) + { + Reactor.registerHandler(this, READ_MASK|WRITE_MASK|EXCEPT_MASK); + } + + ~cdevSystemEventHandler ( void ) + { + if(reactor) reactor->extractHandler(this); + handleClose(); + } + + int handleInput ( void ) + { + cdevSystem::defaultSystem().poll(); + return 0; + } + + int handleOutput ( void ) + { + cdevSystem::defaultSystem().flush(); + return 0; + } + + int handleExcept ( void ) + { + cdevSystem::defaultSystem().poll(); + return 0; + } + + int getHandle ( void ) const + { + return cdevfd; + } +}; + + + +class GENERIC_SERVER_API cdevSystemEventManager : public cdevEventHandler +{ +public: + cdevSystemEventManager ( cdevReactor &Reactor=cdevSessionManager::Reactor, double Rate = 30.0 ) + { + setTimeoutRate(Rate); + Reactor.registerTimer(this); + cdevSystem::defaultSystem().addFdChangedCallback + (cdevSystemEventManager::fdChangedCallback, this); + } + + ~cdevSystemEventManager ( void ) + { + if(reactor) reactor->extractHandler(this); + handleClose(); + } + + int handleTimeout ( void ) + { + cdevSystem::defaultSystem().pend(0.0001); + return 0; + } + + static void fdChangedCallback ( int fd, int opened, void * arg ) + { + cdevSystemEventManager *manager = (cdevSystemEventManager *)arg; + cdevEventHandler *handler; + cdevReactor *reactor = manager->reactor; + + if(reactor) + { + if(opened && reactor->getHandler(fd, handler)!=0) + { + handler = new cdevSystemEventHandler(*reactor, fd); + } + else if(!opened && reactor->getHandler(fd, handler)==0) + { + delete handler; + } + } + } +}; + diff --git a/extensions/cdevGenericServer/include/cdevTagMap.h b/extensions/cdevGenericServer/include/cdevTagMap.h new file mode 100644 index 0000000..e87d23b --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevTagMap.h @@ -0,0 +1,31 @@ +#include +#include + + +// ***************************************************************************** +// * class cdevTagMap: +// * The purpose of the cdevTagMap is to allow rapid translation between +// * the cdev tag tables that within different processes. +// * +// * This class provides the capability to switch back and forth from the +// * local tag values to the remote tag values. +// ***************************************************************************** +class GENERIC_SERVER_API cdevTagMap +{ +private: + int cnt; + int maximum; + int * local; + int * remote; + +public: + cdevTagMap ( void ); + ~cdevTagMap ( void ); + void updateTagMap ( cdevData & data ); + void updateTagMap ( char ** names, int * tags, int count ); + void swapTags ( cdevData & data, int *inTags, int *outTags, int count); + void localToRemote ( cdevData & data ) { if(cnt) swapTags(data, remote, local, cnt); } + void remoteToLocal ( cdevData & data ) { if(cnt) swapTags(data, local, remote, cnt); } + void asciiDump ( FILE * fp = stdout ); +}; + diff --git a/extensions/cdevGenericServer/include/cdevTime.h b/extensions/cdevGenericServer/include/cdevTime.h new file mode 100644 index 0000000..6ee8bad --- /dev/null +++ b/extensions/cdevGenericServer/include/cdevTime.h @@ -0,0 +1,51 @@ +#ifndef _CDEV_TIME_H_ +#define _CDEV_TIME_H_ 1 + +#include "cdevPlatforms.h" + +#define ONE_SECOND 1000000 + +typedef struct timeval timeval; + +class CDEV_REACTOR_API cdevTime +{ +private: + long tv_sec; + long tv_usec; + +public: + cdevTime ( long sec=0, long usec=0 ); + cdevTime ( double t ); + cdevTime ( timeval &t ); + cdevTime ( const cdevTime &t ); + + void getTime ( double * t ) const; + void getTime ( long *sec, long *usec) const; + void getTime ( timeval * t ) const; + + void setTime ( void ); + void setTime ( double t ); + void setTime ( long sec, long usec); + void setTime ( timeval &t ); + void setTime ( const cdevTime &t ); + + void clear ( void ); + int isSet ( void ) const; + int normalize ( void ); + + operator double ( void ); + operator timeval ( void ); + + cdevTime & operator = (const cdevTime& t); + + friend cdevTime operator + (cdevTime t1, cdevTime t2); + friend cdevTime operator - (cdevTime t1, cdevTime t2); + friend int operator < (cdevTime t1, cdevTime t2); + friend int operator > (cdevTime t1, cdevTime t2); + friend int operator <= (cdevTime t1, cdevTime t2); + friend int operator >= (cdevTime t1, cdevTime t2); + friend int operator == (cdevTime t1, cdevTime t2); + friend int operator != (cdevTime t1, cdevTime t2); +}; + +#endif diff --git a/extensions/cdevGenericServer/include/clipMagicNumber.h b/extensions/cdevGenericServer/include/clipMagicNumber.h new file mode 100644 index 0000000..5f4de2d --- /dev/null +++ b/extensions/cdevGenericServer/include/clipMagicNumber.h @@ -0,0 +1,8 @@ +// ***************************************************************************** +// * CLIP_MAGIC_NUMBER : +// * The magic number was added to the CLIP Protocol beginning with version +// * 1.6 of CDEV. This magic number will preceed the buffer length in +// * a clip buffer and will be used to validate that the client is using the +// * same protocol as the server. +// ***************************************************************************** +#define CLIP_MAGIC_NUMBER 0x434C4950 diff --git a/extensions/cdevGenericServer/include/fifo.h b/extensions/cdevGenericServer/include/fifo.h new file mode 100644 index 0000000..ccecc22 --- /dev/null +++ b/extensions/cdevGenericServer/include/fifo.h @@ -0,0 +1,315 @@ +/*----------------------------------------------------------------------------- + * Copyright (c) 1991,1992 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + *----------------------------------------------------------------------------- + * + * Description: + * + * Author: Walt Akers + * + * Revision History: + * fifo.h,v + * Revision 1.4 1997/12/22 15:15:45 akers + * Ongoing development with new cdevReactor + * + * Revision 1.3 1996/09/13 18:47:18 akers + * Installed free list for node objects + * + * Revision 1.2 1996/07/16 15:48:55 akers + * Ongoing Modifications + * + *----------------------------------------------------------------------------- + */ + +#ifndef __FIFO_H_ +#define __FIFO_H_ 1 + +#include + +class GENERIC_SERVER_API QueueBase +{ +public: + class node + { + friend class QueueBase; + private: + node ( void ) : binary(NULL), binaryLen(0), next(NULL) { } + ~node ( void ) { } + public: + void * binary; + size_t binaryLen; + class node * next; + }; + +protected: + node * head; + node * tail; + +private: + enum { NEWCNT = 32 }; + static node * freeList_; + +public: + QueueBase ( void ) + : head(NULL), tail(NULL) + { + } + + virtual ~QueueBase ( void ) + { + } + + static node * newNode ( void ) + { + node * result; + if(freeList_==NULL) + { + freeList_ = new node[NEWCNT]; + for(int i=0; inext; + result->binary = NULL; + result->binaryLen = 0; + result->next = NULL; + return result; + } + + static void deleteNode ( node * ptr) + { + if(ptr->next!=NULL) deleteNode(ptr->next); + ptr->next = freeList_; + freeList_ = ptr; + } +}; + +class GENERIC_SERVER_API FifoQueue : public QueueBase + { + private: + int nodeCnt; + + public: + FifoQueue ( void ) : QueueBase(), nodeCnt(0) {} + + virtual ~FifoQueue ( void ) + { + while(dequeue()!=NULL); + } + + int empty ( void ) + { + return head==NULL?1:0; + } + + void enqueue ( void * ptr ) + { + if(ptr != NULL) + { + if(tail==NULL) tail = newNode(); + else + { + tail->next = newNode(); + tail = tail->next; + } + tail->binary = ptr; + if(head==NULL) head = tail; + nodeCnt++; + } + } + + void enqueue ( char * ptr, size_t len ) + { + if(ptr != NULL && len > 0 ) + { + if(tail==NULL) tail = newNode(); + else { + tail->next = newNode(); + tail = tail->next; + } + tail->binary = ptr; + tail->binaryLen = len; + if(head==NULL) head = tail; + nodeCnt++; + } + } + + void * dequeue ( void ) + { + void * result = NULL; + if(head!=NULL) + { + node * next = head->next; + result = head->binary; + head->next = NULL; + deleteNode(head); + head = next; + if(head==NULL) tail = NULL; + nodeCnt--; + } + return result; + } + + + int dequeue ( char ** ptr, size_t * len ) + { + int result = -1; + *ptr = NULL; + *len = 0; + if(head!=NULL) + { + node * next = head->next; + result = 0; + *ptr = (char *)head->binary; + *len = head->binaryLen; + head->next = NULL; + deleteNode(head); + head = next; + if(head==NULL) tail = NULL; + nodeCnt--; + } + return result; + } + + int peek ( char ** ptr, size_t *len ) + { + int result = -1; + if(head!=NULL) + { + *ptr = (char *)head->binary; + *len = head->binaryLen; + result = 0; + } + return result; + } + + void undequeue ( void * ptr ) + { + if(ptr != NULL) + { + if(tail==NULL) enqueue(ptr); + else { + node * headnode = newNode(); + headnode->binary = ptr; + headnode->next = head; + head = headnode; + nodeCnt++; + } + } + } + + void undequeue ( char *ptr, size_t len) + { + if(ptr != NULL && len > 0) + { + if(tail==NULL) enqueue(ptr, len); + else { + node * headnode = newNode(); + headnode->binary = ptr; + headnode->binaryLen = len; + headnode->next = head; + head = headnode; + nodeCnt++; + } + } + } + + int getCount ( void ) { return nodeCnt; } + }; + + +class GENERIC_SERVER_API ListQueue : public QueueBase + { + protected: + node * prev; + node * bookmark; + + public: + ListQueue ( void ) : QueueBase () + { + prev = NULL; + bookmark = NULL; + } + virtual ~ListQueue ( void ) + { + while(first()==0) remove(); + } + int first ( void ) + { + prev = NULL; + bookmark = head; + return (bookmark==NULL?-1:0); + } + int next ( void ) + { + if(bookmark!=NULL) + { + prev = bookmark; + bookmark = bookmark->next; + } + return (bookmark==NULL?-1:0); + } + void * dequeue ( void ) + { + return (bookmark==NULL?NULL:bookmark->binary); + } + void enqueue ( void * ptr ) + { + if(ptr != NULL) + { + prev = tail; + if(tail==NULL) tail = newNode(); + else + { + tail->next = newNode(); + tail = tail->next; + } + tail->binary = ptr; + bookmark = tail; + if(head==NULL) head = tail; + } + } + int remove ( void ) + { + int retval = -1; + if(bookmark != NULL) + { + if(prev!=NULL) prev->next = bookmark->next; + else head = bookmark->next; + + bookmark->next = NULL; + deleteNode(bookmark); + + if(prev!=NULL) { + bookmark = prev->next; + } + else if(head!=NULL && head->next!=NULL) { + bookmark = head->next; + } + else bookmark = head; + + for( tail=head; + tail!=NULL && tail->next!=NULL; + tail=tail->next); + retval = 0; + } + else if(head!=NULL) first(); + else tail = NULL; + return retval; + } + }; + +#ifdef _FIFO_QUEUE_MASTER_ + QueueBase::node * QueueBase::freeList_ = NULL; +#endif + +#endif // __FIFO_H_ + diff --git a/extensions/cdevGenericServer/include/header.h b/extensions/cdevGenericServer/include/header.h new file mode 100644 index 0000000..0d5bb2e --- /dev/null +++ b/extensions/cdevGenericServer/include/header.h @@ -0,0 +1,16 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// +// +// Author: Jie Chen +// +// +// diff --git a/extensions/cdevGenericServer/include/makeinclude/Makefile.OS b/extensions/cdevGenericServer/include/makeinclude/Makefile.OS new file mode 100644 index 0000000..c16855a --- /dev/null +++ b/extensions/cdevGenericServer/include/makeinclude/Makefile.OS @@ -0,0 +1,93 @@ +# ****************************************************************************** +# * Makefile.Linux : This is the platform specific Makefile for Linux. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = Linux + +include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only specify the DEBUGFLAG if the DEBUG variable has been set. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +else +DEBUGFLAG = -O2 +endif + +CXX = g++ +CC = gcc +CXXFLAGS = -DLinux -fno-for-scope $(DEBUGFLAG) $(CXXEXTRA) $(CXXINCLUDES) \ + $(CDEVINCLUDES) $(BASEINCLUDES) +CFLAGS = -DLinux $(DEBUGFLAG) $(CEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(BASEINCLUDES) +AR = ar +ARFLAGS = ruv +RANLIB = ranlib +DLD = $(CXX) +SOFLAGS = -shared +PIC = -fpic +SHARED_EXT = so +NETLIBS = +OSLIBS = $(NETLIBS) -lm -ldl + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) $(PIC) -c -o $@ $^ +COMPILE.c = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = $(QUIET)$(LINK_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) -Xlinker -rpath -Xlinker $(BASELIB) -Xlinker -rpath -Xlinker $(CDEVLIB) +LINK.a = $(QUIET)$(AR_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(AR) $(ARFLAGS) +LINK.so = $(QUIET)$(SO_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(DLD) $(SOFLAGS) + +# ****************************************************************************** +# * This is the macro to build a shared object/library.... it requires the +# * following variables to be defined... +# * +# * SO_SRCS : Names of the component source files +# * SO_LIBS : Names of the dependent libraries +# * LIBS : All libraries necessary to compile the dummy application +# ****************************************************************************** +SOBUILD = rm -f $@;\ + mkdir -p $(@D);\ + echo "=> Building shared object $(@F)";\ + $(LINK.so) -o $@ $^ -R $(CDEVLIB) -L$(CDEVLIB) -L./ $(NETLIBS) + + diff --git a/extensions/cdevGenericServer/include/makeinclude/Makefile.WINNT-4.0 b/extensions/cdevGenericServer/include/makeinclude/Makefile.WINNT-4.0 new file mode 100644 index 0000000..09caf70 --- /dev/null +++ b/extensions/cdevGenericServer/include/makeinclude/Makefile.WINNT-4.0 @@ -0,0 +1,195 @@ +!IF "$(VERBOSE)" != "YES" +!CMDSWITCHES +S +!ELSE +!CMDSWITCHES -S +!ENDIF + +TARGET = WINNT +OS_MAJOR = 4 +OS_MINOR = 0 +OS_VERSION_DEF = /D "_OS_MAJOR_=$(OS_MAJOR)" /D "_OS_MINOR_=$(OS_MINOR)" + +!IF "$(DEBUG)" == "" +TARGETDIR = $(TARGET)-$(OS_MAJOR).$(OS_MINOR) +!ELSE +TARGETDIR = $(TARGET)-$(OS_MAJOR).$(OS_MINOR)-DEBUG +!ENDIF + +CDEVVERSION = 1.7.2 +CDEVINCLUDES = /I $(CDEV)\include +CDEVLIB = $(CDEV)\lib\$(TARGETDIR) +CDEVBIN = $(CDEV)\bin\$(TARGETDIR) +CREATE_LINK = copy $** $@ > nul + +BASEDIR = $(CDEV)\extensions\cdevGenericServer +BASEINCLUDES = /I $(BASEDIR)\include + +!IF "$(BASELIB)" == "" +BASELIB = $(BASEDIR)\lib\$(TARGETDIR) +!ENDIF + +!IF "$(BASEBIN)" == "" +BASEBIN = $(BASEDIR)\bin\$(TARGETDIR) +!ENDIF + +!IF "$(CDEVSHOBJ)" == "" +CDEVSHOBJ = $(CDEVLIB) +!ENDIF + +!IF "$(SHOBJ)" == "NO" +OBJDIR = .obj\$(TARGETDIR) +!ELSE +SHOBJ = YES +OBJDIR = .shobj\$(TARGETDIR) +!ENDIF + +CC = cl +CXX = cl +LIB32 = link +LINK = link + +CC_ALL_EXE = /nologo /D "WIN32" /D "_WINDOWS" /D "_MBCS" /Fo".exec\$(TARGETDIR)/"\ + $(CXXEXTRA) $(CXXEXTRA_EXE) $(CXXINCLUDES) $(CDEVINCLUDES) $(BASEINCLUDES) $(OS_VERSION_DEF) /TC /c +CXX_ALL_EXE = /nologo /D "WIN32" /D "_WINDOWS" /D "_MBCS" /Fo".exec\$(TARGETDIR)/"\ + $(CXXEXTRA) $(CXXEXTRA_EXE) $(CXXINCLUDES) $(CDEVINCLUDES) $(BASEINCLUDES) $(OS_VERSION_DEF) /TP /c +CXX_DEBUG_EXE = /MDd /Z7 /Od /D "_DEBUG" /GZ +CXX_RELEASE_EXE = /MD /O2 /D "NDEBUG" +LINK_ALL_EXE = kernel32.lib user32.lib gdi32.lib winspool.lib \ + comdlg32.lib advapi32.lib shell32.lib ole32.lib \ + oleaut32.lib uuid.lib odbc32.lib odbccp32.lib \ + ws2_32.lib /nologo /subsystem:console /pdb:NONE +LINK_DEBUG_EXE = /debug +LINK_RELEASE_EXE = + +CC_ALL_LIB = /nologo /D "WIN32" /D "_MBCS" /D "_LIB" /Fo"$(OBJDIR)/"\ + $(CXXEXTRA) $(CXXEXTRA_LIB) $(CXXINCLUDES) $(CDEVINCLUDES) $(BASEINCLUDES) $(OS_VERSION_DEF) /TC /c +CXX_ALL_LIB = /nologo /D "WIN32" /D "_MBCS" /D "_LIB" /Fo"$(OBJDIR)/"\ + $(CXXEXTRA) $(CXXEXTRA_LIB) $(CXXINCLUDES) $(CDEVINCLUDES) $(BASEINCLUDES) $(OS_VERSION_DEF) /TP /c +CXX_DEBUG_LIB = /MDd /Z7 /Od /D "_DEBUG" /GZ +CXX_RELEASE_LIB = /MD /O2 /D "NDEBUG" +LINK_ALL_LIB = -lib /nologo +LINK_DEBUG_LIB = +LINK_RELEASE_LIB = + +CC_ALL_DLL = /nologo /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /Fo"$(OBJDIR)/"\ + $(CXXEXTRA) $(CXXEXTRA_DLL) $(CXXINCLUDES) $(CDEVINCLUDES) $(BASEINCLUDES) $(OS_VERSION_DEF) /TC /c +CXX_ALL_DLL = /nologo /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /Fo"$(OBJDIR)/"\ + $(CXXEXTRA) $(CXXEXTRA_DLL) $(CXXINCLUDES) $(CDEVINCLUDES) $(BASEINCLUDES) $(OS_VERSION_DEF) /TP /c +CXX_DEBUG_DLL = /MDd /Z7 /Od /D "_DEBUG" /GZ +CXX_RELEASE_DLL = /MD /O2 /D "NDEBUG" +LINK_ALL_DLL = kernel32.lib user32.lib gdi32.lib winspool.lib \ + comdlg32.lib advapi32.lib shell32.lib ole32.lib \ + oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib \ + /nologo /dll /pdb:NONE +LINK_DEBUG_DLL = /debug +LINK_RELEASE_DLL = + +!IF "$(DEBUG)" != "" +CC_EXE_FLAGS = $(CC_ALL_EXE) $(CXX_DEBUG_EXE) +CC_LIB_FLAGS = $(CC_ALL_LIB) $(CXX_DEBUG_LIB) +CC_DLL_FLAGS = $(CC_ALL_DLL) $(CXX_DEBUG_DLL) +CXX_EXE_FLAGS = $(CXX_ALL_EXE) $(CXX_DEBUG_EXE) +CXX_LIB_FLAGS = $(CXX_ALL_LIB) $(CXX_DEBUG_LIB) +CXX_DLL_FLAGS = $(CXX_ALL_DLL) $(CXX_DEBUG_DLL) +LINK_EXE_FLAGS = $(LINK_ALL_EXE) $(LINK_DEBUG_EXE) +LINK_LIB_FLAGS = $(LINK_ALL_LIB) $(LINK_DEBUG_LIB) +LINK_DLL_FLAGS = $(LINK_ALL_DLL) $(LINK_DEBUG_DLL) +!ELSE +CC_EXE_FLAGS = $(CC_ALL_EXE) $(CXX_RELEASE_EXE) +CC_LIB_FLAGS = $(CC_ALL_LIB) $(CXX_RELEASE_LIB) +CC_DLL_FLAGS = $(CC_ALL_DLL) $(CXX_RELEASE_DLL) +CXX_EXE_FLAGS = $(CXX_ALL_EXE) $(CXX_RELEASE_EXE) +CXX_LIB_FLAGS = $(CXX_ALL_LIB) $(CXX_RELEASE_LIB) +CXX_DLL_FLAGS = $(CXX_ALL_DLL) $(CXX_RELEASE_DLL) +LINK_EXE_FLAGS = $(LINK_ALL_EXE) $(LINK_RELEASE_EXE) +LINK_LIB_FLAGS = $(LINK_ALL_LIB) $(LINK_RELEASE_LIB) +LINK_DLL_FLAGS = $(LINK_ALL_DLL) $(LINK_RELEASE_DLL) +!ENDIF + +!IF "$(HAIL)" != "NO" +HAILTARGET = hail +!ENDIF + +!IF "$(FAIRWELL)" != "NO" +BYETARGET = fairwell +!ENDIF + +# ****************************************************************************** +# * Master rules for building cdevGenericServer objects +# ****************************************************************************** +all : $(HAILTARGET) targets $(BYETARGET) + +hail: + @echo ^ ^ ^ =^> Building $(APPNAME) for Target: $(TARGETDIR) + +fairwell: + @echo ^ ^ ^ ^ ^ ^ Done... + +clean: +!IF "$(HAIL)" != "NO" + @echo ^ ^ ^ =^> Cleaning $(APPNAME) for Target: $(TARGETDIR) +!ENDIF + -@for %x in (.obj\$(TARGET)-$(OS_MAJOR).$(OS_MINOR)-DEBUG \ + .obj\$(TARGET)-$(OS_MAJOR).$(OS_MINOR) \ + .shobj\$(TARGET)-$(OS_MAJOR).$(OS_MINOR)-DEBUG \ + .shobj\$(TARGET)-$(OS_MAJOR).$(OS_MINOR) \ + .exec\$(TARGET)-$(OS_MAJOR).$(OS_MINOR)-DEBUG \ + .exec\$(TARGET)-$(OS_MAJOR).$(OS_MINOR)) DO \ + @if exist %x rmdir /s /q %x + -@for %x in ($(BINARIES) $(TARGETS)) DO @if exist %x erase %x +!IF "$(FAIRWELL)" != "NO" + @echo ^ ^ ^ ^ ^ ^ Done... +!ENDIF + +purge: +!IF "$(HAIL)" != "NO" + @echo ^ ^ ^ =^> Purging $(APPNAME) for Target: $(TARGETDIR) +!ENDIF + -@for %x in (.shobj .obj .exec) DO @if exist %x rmdir /s /q %x + -@for %x in ($(BINARIES) $(TARGETS) $(TEMPLINKS)) DO @if exist %x erase %x +!IF "$(FAIRWELL)" != "NO" + @echo ^ ^ ^ ^ ^ ^ Done... +!ENDIF + + +.cc{.obj\$(TARGETDIR)}.obj:: + @echo ^ ^ ^ ^ ^ ^ =^> Compiling $< + -@if not exist .obj\$(TARGETDIR) mkdir .obj\$(TARGETDIR) + -@if not exist $(BASEBIN) mkdir $(BASEBIN) + -@if not exist $(BASELIB) mkdir $(BASELIB) + $(CXX) $(CXX_LIB_FLAGS) $< + +.cc{.shobj\$(TARGETDIR)}.obj:: + @echo ^ ^ ^ ^ ^ ^ =^> Compiling $< + -@if not exist .shobj\$(TARGETDIR) mkdir .shobj\$(TARGETDIR) + -@if not exist $(BASEBIN) mkdir $(BASEBIN) + -@if not exist $(BASELIB) mkdir $(BASELIB) + $(CXX) $(CXX_DLL_FLAGS) $< + +.cc{.exec\$(TARGETDIR)}.obj:: + @echo ^ ^ ^ ^ ^ ^ =^> Compiling $< + -@if not exist .exec\$(TARGETDIR) mkdir .exec\$(TARGETDIR) + -@if not exist $(BASEBIN) mkdir $(BASEBIN) + -@if not exist $(BASELIB) mkdir $(BASELIB) + $(CXX) $(CXX_EXE_FLAGS) $< + +.c{.obj\$(TARGETDIR)}.obj:: + @echo ^ ^ ^ ^ ^ ^ =^> Compiling $< + -@if not exist .obj\$(TARGETDIR) mkdir .obj\$(TARGETDIR) + -@if not exist $(BASEBIN) mkdir $(BASEBIN) + -@if not exist $(BASELIB) mkdir $(BASELIB) + $(CC) $(CC_LIB_FLAGS) $< + +.c{.shobj\$(TARGETDIR)}.obj:: + @echo ^ ^ ^ ^ ^ ^ =^> Compiling $< + -@if not exist .shobj\$(TARGETDIR) mkdir .shobj\$(TARGETDIR) + -@if not exist $(BASEBIN) mkdir $(BASEBIN) + -@if not exist $(BASELIB) mkdir $(BASELIB) + $(CC) $(CC_DLL_FLAGS) $< + +.c{.exec\$(TARGETDIR)}.obj:: + @echo ^ ^ ^ ^ ^ ^ =^> Compiling $< + -@if not exist .exec\$(TARGETDIR) mkdir .exec\$(TARGETDIR) + -@if not exist $(BASEBIN) mkdir $(BASEBIN) + -@if not exist $(BASELIB) mkdir $(BASELIB) + $(CC) $(CC_EXE_FLAGS) $< diff --git a/extensions/cdevGenericServer/include/makeinclude/Makefile.aix b/extensions/cdevGenericServer/include/makeinclude/Makefile.aix new file mode 100755 index 0000000..4cda47b --- /dev/null +++ b/extensions/cdevGenericServer/include/makeinclude/Makefile.aix @@ -0,0 +1,68 @@ +# ****************************************************************************** +# * Makefile.aix : This is the platform specific Makefile for aix. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = aix +OS_MAJOR := $(shell uname -v) +OS_MAJOR_NUM := $(shell awk 'BEGIN {VAL=$(OS_MAJOR); print VAL; exit; }') +OS_MINOR := $(shell uname -r) +OS_MINOR_NUM := $(shell awk 'BEGIN {VAL=$(OS_MINOR); print VAL; exit; }') +OS_VERSION_DEF := -D_OS_MAJOR_=$(OS_MAJOR_NUM) -D_OS_MINOR_=$(OS_MINOR_NUM) + +include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.common + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only specify the DEBUGFLAG if the DEBUG variable has been set. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +endif + +CXX = xlC +CC = xlC +CXXFLAGS = $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) \ + $(BASEINCLUDES) $(OS_VERSION_DEF) $(DEBUGFLAG) -DAIX -qNOro +CFLAGS = $(CCEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) \ + $(BASEINCLUDES) $(OS_VERSION_DEF) $(DEBUGFLAG) -DAIX -qNOro +AR = ar +ARFLAGS = ruv +RANLIB = true +OSLIBS = -L/lib -lm + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + @echo "Shared objects not supported on AIX" +COMPILE.c = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + @echo "Shared objects not supported on AIX" +LINK.cc = $(QUIET)$(LINK_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) +LINK.a = $(QUIET)$(AR_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(AR) $(ARFLAGS) + + +#Note on the -qNOro option + +# The AIX compiler by default allocates memory for string literals in the +# read only area. As result, CLIP clients crash with segmentation fault +# when cdevClientRequestObj cleans up constant message strings passed by +# the user (in the code below "message" points directly to the user string) diff --git a/extensions/cdevGenericServer/include/makeinclude/Makefile.common b/extensions/cdevGenericServer/include/makeinclude/Makefile.common new file mode 100755 index 0000000..b1e5bc3 --- /dev/null +++ b/extensions/cdevGenericServer/include/makeinclude/Makefile.common @@ -0,0 +1,123 @@ +# ****************************************************************************** +# * Makefile.common : This is the community makefile for the cdevGenericServer +# * distribution. It contains the definitions that are common +# * for all Makefiles in this distribution. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# * CDEVVERSION : The version of cdev being used +# * TARGET : The name of the target platform +# * OS_MAJOR : The major version number of the target OS +# ****************************************************************************** +ifdef OS_MAJOR +TARGETDIR = $(TARGET)-$(OS_MAJOR).$(OS_MINOR) +else +TARGETDIR = $(TARGET) +endif + +CDEVVERSION = 1.7.2 +CDEVINCLUDES = -I$(CDEV)/include +CDEVLIB = $(CDEV)/lib/$(TARGETDIR) +CDEVBIN = $(CDEV)/bin/$(TARGETDIR) + +BASEDIR = $(CDEV)/extensions/cdevGenericServer +BASEINCLUDES = -I$(BASEDIR)/include +BASELIB = $(BASEDIR)/lib/$(TARGETDIR) +BASEBIN = $(BASEDIR)/bin/$(TARGETDIR) + +# ****************************************************************************** +# * This is the compressed command echo mechanism +# ****************************************************************************** +ifeq ("$(VERBOSE)", "") + VERBOSE = NO + MAKE := $(MAKE) -s VERBOSE=NO +endif + +ifeq ("$(VERBOSE)", "NO") + QUIET = @ + CXX_CMD_ECHO = @echo " => $(CXX) -c $( $(CC) -c $( $(AR) $(@F)"; + SO_CMD_ECHO = @echo " => $(DLD) -o $(@F)"; + LINK_CMD_ECHO = @echo " => $(CXX) -o $(@F)"; + COPY_CMD_ECHO = @echo " => Copying $(@F) to $^"; + LEX_CMD_ECHO = @echo " => lex -o $(@F) $(^F)"; + YACC_CMD_ECHO = @echo " => yacc -o $(@F) $(^F)"; +else + EMPTY_ECHO = + CXX_CMD_ECHO = $(EMPTY_ECHO) + CC_CMD_ECHO = $(EMPTY_ECHO) + AR_CMD_ECHO = $(EMPTY_ECHO) + SO_CMD_ECHO = $(EMPTY_ECHO) + LINK_CMD_ECHO = $(EMPTY_ECHO) + COPY_CMD_ECHO = $(EMPTY_ECHO) + LEX_CMD_ECHO = $(EMPTY_ECHO) + YACC_CMD_ECHO = $(EMPTY_ECHO) +endif + +# ****************************************************************************** +# * Set the CDEV shared object directory to a default location if not specified. +# ****************************************************************************** +ifeq ($(CDEVSHOBJ), ) + CDEVSHOBJ = $(CDEVLIB) +endif + + +# ****************************************************************************** +# * Set the object directory appropriately to the SHOBJ flag (default YES) +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + OBJDIR = .obj/$(TARGETDIR) +else + SHOBJ = YES + OBJDIR = .shobj/$(TARGETDIR) +endif + + +# ****************************************************************************** +# * Rule for compiling archive C++ files. +# ****************************************************************************** +.obj/$(TARGETDIR)/%.o : %.cc + $(COMPILE.cc) + + +# ****************************************************************************** +# * Rule for compiling shared C++ files. +# ****************************************************************************** +.shobj/$(TARGETDIR)/%.o : %.cc + $(COMPILE.cc.so) + +# ****************************************************************************** +# * Rule for compiling archive C files. +# ****************************************************************************** +.obj/$(TARGETDIR)/%.o : %.c + $(COMPILE.c) + + +# ****************************************************************************** +# * Rule for compiling shared C files. +# ****************************************************************************** +.shobj/$(TARGETDIR)/%.o : %.c + $(COMPILE.c.so) + +# ****************************************************************************** +# * Generic rules for makefiles. +# ****************************************************************************** +all: hail targets fairwell + +hail: + @echo " => Building [$(TARGETDIR)] in $(APPNAME)" + +fairwell: + @echo " Done..." + +clean: + @echo " => Cleaning [$(TARGETDIR)] in $(APPNAME)" + @rm -rf .o .a core .obj/$(TARGETDIR) .shobj/$(TARGETDIR) *.?.? TC.Cache $(BINARIES) $(TARGETS) ./ptrepository + @echo " Done..." +purge: + @echo " => Purging [All] in $(APPNAME)" + @rm -rf .shobj .obj .exec $(BINARIES) $(TARGETS) $(TEMPLINKS) .o .a core *.?.? TC.Cache ./ptrepository + @echo " Done..." diff --git a/extensions/cdevGenericServer/include/makeinclude/Makefile.hpux b/extensions/cdevGenericServer/include/makeinclude/Makefile.hpux new file mode 100755 index 0000000..a059313 --- /dev/null +++ b/extensions/cdevGenericServer/include/makeinclude/Makefile.hpux @@ -0,0 +1,131 @@ +# ****************************************************************************** +# * Makefile.hpux : This is the platform specific Makefile for HPUX. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = hpux +OS_MAJOR := $(shell uname -r | awk -F "." '{print $$2; exit}') +OS_MAJOR_NUM := $(shell awk 'BEGIN {VAL=$(OS_MAJOR); print VAL; exit; }') +OS_MINOR := $(shell uname -r | awk -F "." '{print $$3; exit}') +OS_MINOR_NUM := $(shell awk 'BEGIN {VAL=$(OS_MINOR); print VAL; exit; }') +OS_VERSION_DEF := -D_OS_MAJOR_=$(OS_MAJOR_NUM) -D_OS_MINOR_=$(OS_MINOR_NUM) + +include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Due to a change in the operating system, the CXX compiler for HP-UX may +# * be different depending on which platform is used. +# ****************************************************************************** +ifeq ($(OS_MAJOR), 09) + CXX := /usr/bin/CC + HP_FLAGS = -Aa -pta -ptb -D_SELECT_USES_INT_ +endif + +ifeq ($(OS_MAJOR).$(OS_MINOR), 10.10) + CXX := /opt/CC/bin/CC + HP_FLAGS = -Aa -pta -ptb -Dvolatile="" + NETLIBS = -lxti +endif + +ifeq ($(OS_MAJOR).$(OS_MINOR), 10.20) + CXX := /opt/aCC/bin/aCC + HP_FLAGS = +W302,749,829 + NETLIBS = -lxti +endif + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only specify the DEBUGFLAG if the DEBUG variable has been set. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +else +DEBUGFLAG = +O2 +endif + +CC = cc +CXXFLAGS = -z $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) \ + $(BASEINCLUDES) $(OS_VERSION_DEF) $(DEBUGFLAG) $(HP_FLAGS) -DSYSV +CFLAGS = -Aa $(CCEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) \ + $(BASEINCLUDES) $(OS_VERSION_DEF) $(DEBUGFLAG) -DSYSV +LDFLAGS = -L$(CDEVLIB) -Wl,+s +AR = ar +ARFLAGS = ruv +RANLIB = true +DLD = $(CXX) +SOFLAGS = -b -Wl,+s +PIC = +z +SHARED_EXT = sl +OSLIBS = -L/lib -lm + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(PURIFY) $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(PURIFY) $(CXX) -c $(CXXFLAGS) $(PIC) $^ -o $@ +COMPILE.c = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = $(QUIET)$(LINK_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(PURIFY) $(CXX) $(CXXFLAGS) +LINK.a = $(QUIET)$(AR_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(AR) $(ARFLAGS) +LINK.so = $(QUIET)$(SO_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(PURIFY) $(DLD) $(SOFLAGS) + +# ****************************************************************************** +# * This is the macro to build a shared object/library.... it requires the +# * following variables to be defined... +# * +# * SO_SRCS : Names of the component source files +# * SO_LIBS : Names of the dependent libraries +# * LIBS : All libraries necessary to compile the dummy application +# ****************************************************************************** +SOBUILD = rm -f $@;\ + mkdir -p $(@D);\ + echo "=> Building shared object $(@F)";\ + echo " => Instanciating templates for $(@F)";\ + echo "int main() {return 0;}" >dummy.cc;\ + $(CXX) -c $(CXXFLAGS) $(PIC) dummy.cc $(SO_SRCS) $(LDFLAGS) -ptr./pt$(@F) -ptr./ptrepository $(LIBS);\ + rm -rf a.out dummy.*;\ + if test -f ./pt$(@F)/*.o;\ + then\ + echo " => Linking $(@F) from objects and template objects";\ + $(LINK.so) -o $@ $^ ./pt$(@F)/*.o $(SO_LIBS);\ + else\ + echo " => Linking $(@F) from objects";\ + $(LINK.so) -o $@ $^ $(SO_LIBS);\ + fi;\ + rm -rf *.o ./pt$(@F) + + diff --git a/extensions/cdevGenericServer/include/makeinclude/Makefile.hpux-cl b/extensions/cdevGenericServer/include/makeinclude/Makefile.hpux-cl new file mode 100755 index 0000000..7afd48a --- /dev/null +++ b/extensions/cdevGenericServer/include/makeinclude/Makefile.hpux-cl @@ -0,0 +1,121 @@ +# ****************************************************************************** +# * Makefile.hpux-cl: This is the platform specific Makefile for HPUX using +# * the CenterLine C++ compiler. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = hpux-cl +SHOBJ = NO +OS_MAJOR := $(shell uname -r | awk -F "." '{print $$2; exit}') +OS_MAJOR_NUM := $(shell awk 'BEGIN {VAL=$(OS_MAJOR); print VAL; exit; }') +OS_MINOR := $(shell uname -r | awk -F "." '{print $$3; exit}') +OS_MINOR_NUM := $(shell awk 'BEGIN {VAL=$(OS_MINOR); print VAL; exit; }') +OS_VERSION_DEF := -D_OS_MAJOR_=$(OS_MAJOR_NUM) -D_OS_MINOR_=$(OS_MINOR_NUM) + +include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +ifeq ($(OS_MAJOR_NUM), 9) + HP_FLAGS = -D_SELECT_USES_INT_ +endif + +ifeq ($(OS_MAJOR_NUM), 10) + HP_FLAGS = -Dvolatile="" + NETLIBS = -lxti +endif + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only specify the DEBUGFLAG if the DEBUG variable has been set. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +endif + +CXX = /usr/csite4/CenterLine/bin/CC +CC = cc +CXXFLAGS = -z -pta -D__CENTERLINE__ $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) \ + $(BASEINCLUDES) $(OS_VERSION_DEF) $(DEBUGFLAG) $(HP_FLAGS) -DSYSV +CFLAGS = -Aa $(CCEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) \ + $(BASEINCLUDES) $(OS_VERSION_DEF) $(DEBUGFLAG) -DSYSV +LDFLAGS = -Wl,+s +AR = ar +ARFLAGS = ruv +RANLIB = true +DLD = $(CXX) +SOFLAGS = -b +PIC = +SHARED_EXT = sl +OSLIBS = -lm + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) -c $(CXXFLAGS) $(PIC) $^ -o $@ +COMPILE.c = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = $(QUIET)$(LINK_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(PROOF) $(CXX) $(CXXFLAGS) +LINK.a = $(QUIET)$(AR_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(AR) $(ARFLAGS) +LINK.so = $(QUIET)$(SO_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(DLD) $(SOFLAGS) + + +# ****************************************************************************** +# * This is the macro to build a shared object/library.... it requires the +# * following variables to be defined... +# * +# * SO_SRCS : Names of the component source files +# * SO_LIBS : Names of the dependent libraries +# * LIBS : All libraries necessary to compile the dummy application +# ****************************************************************************** +SOBUILD = rm -f $@;\ + mkdir -p $(@D);\ + echo "=> Building shared object $(@F)";\ + echo " => Instanciating templates for $(@F)";\ + echo "int main() {return 0;}" >dummy.cc;\ + $(CXX) -c $(CXXFLAGS) $(PIC) dummy.cc $(SO_SRCS) $(LDFLAGS) -ptr./pt$(@F) -ptr./ptrepository $(SO_LIBS);\ + rm -rf a.out dummy.*;\ + if test -f ./pt$(@F)/*.o;\ + then\ + echo " => Linking $(@F) from objects and template objects";\ + $(LINK.so) -o $@ $^ ./pt$(@F)/*.o $(LIBS);\ + else\ + echo " => Linking $(@F) from objects";\ + $(LINK.so) -o $@ $^ $(SO_LIBS);\ + fi;\ + rm -rf *.o ./pt$(@F) + + diff --git a/extensions/cdevGenericServer/include/makeinclude/Makefile.lib b/extensions/cdevGenericServer/include/makeinclude/Makefile.lib new file mode 100755 index 0000000..32db887 --- /dev/null +++ b/extensions/cdevGenericServer/include/makeinclude/Makefile.lib @@ -0,0 +1,148 @@ +ARCH = OS +SHOBJ = YES + +#include ../include/makeinclude/Makefile.$(ARCH) +include ../include/makeinclude/Makefile.linux + +APPNAME = "CDEV Generic Client/Server Engine" +TEMPLINKS = ClientAcceptor.cc\ + ClientHandler.cc\ + cdevServer.cc\ + cdevServerTools.cc\ + cdevSessionManager.cc\ + ServerInterface.cc\ + ServerHandler.cc\ + cdevClientRequestObject.cc\ + cdevClientService.cc\ + cdevMessage.cc\ + cdevMessageBinary.cc\ + cdevPacket.cc\ + cdevContextMap.cc\ + cdevMonitorTable.cc\ + cdevTagMap.cc\ + SignalManager.cc\ + cdevAddr.cc\ + cdevEventHandler.cc\ + cdevHandleSet.cc\ + cdevReactor.cc\ + cdevSocket.cc\ + cdevSocketAcceptor.cc\ + cdevSocketConnector.cc\ + cdevSocketDatagram.cc\ + cdevSocketStream.cc\ + cdevStreamNode.cc\ + cdevStreamQueue.cc\ + cdevTime.cc\ + fifo.cc\ + IntHash.cc + + +LIBS = $(CDEVLIBS) $(OSLIBS) + +SERVER_OBJS = $(OBJDIR)/cdevServer.o\ + $(OBJDIR)/cdevServerTools.o\ + $(OBJDIR)/cdevSessionManager.o\ + $(OBJDIR)/ClientHandler.o\ + $(OBJDIR)/ClientAcceptor.o\ + $(OBJDIR)/cdevTagMap.o\ + $(OBJDIR)/cdevMonitorTable.o + +CLIENT_OBJS = $(OBJDIR)/cdevClientService.o\ + $(OBJDIR)/cdevClientRequestObject.o\ + $(OBJDIR)/ServerInterface.o\ + $(OBJDIR)/ServerHandler.o + +COMMON_OBJS = $(OBJDIR)/cdevPacket.o\ + $(OBJDIR)/cdevMessageBinary.o\ + $(OBJDIR)/cdevMessage.o\ + $(OBJDIR)/cdevContextMap.o\ + $(OBJDIR)/SignalManager.o\ + $(OBJDIR)/fifo.o\ + $(OBJDIR)/IntHash.o + +ACE_OBJS = $(OBJDIR)/cdevAddr.o\ + $(OBJDIR)/cdevEventHandler.o\ + $(OBJDIR)/cdevHandleSet.o\ + $(OBJDIR)/cdevReactor.o\ + $(OBJDIR)/cdevSocket.o\ + $(OBJDIR)/cdevSocketAcceptor.o\ + $(OBJDIR)/cdevSocketConnector.o\ + $(OBJDIR)/cdevSocketDatagram.o\ + $(OBJDIR)/cdevSocketStream.o\ + $(OBJDIR)/cdevStreamNode.o\ + $(OBJDIR)/cdevStreamQueue.o\ + $(OBJDIR)/cdevTime.o + +OBJS = $(SERVER_OBJS) $(CLIENT_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + +# ****************************************************************************** +# * The BINARIES definition names all of the binary files that should be deleted +# * whenever "make clean" is executed. +# ****************************************************************************** +BINARIES = $(CDEVLIB)/libcdevGenericServer.$(SHARED_EXT) \ + $(CDEVLIB)/libcdevGenericServer.a + +ifeq ($(SHOBJ),YES) + TARGETS = $(TEMPLINKS) \ + $(CDEVLIB)/libcdevGenericServer.$(SHARED_EXT) +else + TARGETS = $(TEMPLINKS) \ + $(CDEVLIB)/libcdevGenericServer.a +endif + +targets : $(TARGETS) + +$(TEMPLINKS) : + @cp $^ $@ + +$(CDEVLIB)/libcdevGenericServer.a : $(OBJS) + $(LINK.a) $@ $^ + @$(RANLIB) $@ > /dev/null + +$(CDEVLIB)/libcdevGenericServer.$(SHARED_EXT) : $(OBJS) + $(LINK.so) -o $@ $^ -L$(CDEVLIB) -lrsvc $(NETLIBS) + +$(CDEVLIB)/libcdevServer.a : $(SERVER_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + $(LINK.a) $@ $^ + @$(RANLIB) $@ > /dev/null + +$(CDEVLIB)/libcdevServer.$(SHARED_EXT) : $(SERVER_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + $(LINK.so) -o $@ $^ -L$(CDEVLIB) -lrsvc $(NETLIBS) + +$(CDEVLIB)/libcdevClient.a : $(CLIENT_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + $(LINK.a) $@ $^ + @$(RANLIB) $@ > /dev/null + +$(CDEVLIB)/libcdevClient.$(SHARED_EXT) : $(CLIENT_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + $(LINK.so) -o $@ $^ -L$(CDEVLIB) -lrsvc $(NETLIBS) + +ClientAcceptor.cc : ../cdevServer/ClientAcceptor.cc +ClientHandler.cc : ../cdevServer/ClientHandler.cc +cdevServer.cc : ../cdevServer/cdevServer.cc +cdevServerTools.cc : ../cdevServer/cdevServerTools.cc +cdevSessionManager.cc : ../cdevServer/cdevSessionManager.cc +ServerHandler.cc : ../cdevClient/ServerHandler.cc +ServerInterface.cc : ../cdevClient/ServerInterface.cc +cdevClientRequestObject.cc : ../cdevClient/cdevClientRequestObject.cc +cdevClientService.cc : ../cdevClient/cdevClientService.cc +cdevMessage.cc : ../cdevPacket/cdevMessage.cc +cdevMessageBinary.cc : ../cdevPacket/cdevMessageBinary.cc +cdevPacket.cc : ../cdevPacket/cdevPacket.cc +cdevContextMap.cc : ../cdevContextMap/cdevContextMap.cc +cdevMonitorTable.cc : ../cdevMonitorTable/cdevMonitorTable.cc +cdevTagMap.cc : ../cdevTagMap/cdevTagMap.cc +SignalManager.cc : ../common/SignalManager.cc +cdevAddr.cc : ../cdevReactor/cdevAddr.cc +cdevEventHandler.cc : ../cdevReactor/cdevEventHandler.cc +cdevHandleSet.cc : ../cdevReactor/cdevHandleSet.cc +cdevReactor.cc : ../cdevReactor/cdevReactor.cc +cdevSocket.cc : ../cdevReactor/cdevSocket.cc +cdevSocketAcceptor.cc : ../cdevReactor/cdevSocketAcceptor.cc +cdevSocketConnector.cc : ../cdevReactor/cdevSocketConnector.cc +cdevSocketDatagram.cc : ../cdevReactor/cdevSocketDatagram.cc +cdevSocketStream.cc : ../cdevReactor/cdevSocketStream.cc +cdevStreamNode.cc : ../cdevReactor/cdevStreamNode.cc +cdevStreamQueue.cc : ../cdevReactor/cdevStreamQueue.cc +cdevTime.cc : ../cdevReactor/cdevTime.cc +fifo.cc : ../common/fifo.cc +IntHash.cc : ../common/IntHash.cc diff --git a/extensions/cdevGenericServer/include/makeinclude/Makefile.linux b/extensions/cdevGenericServer/include/makeinclude/Makefile.linux new file mode 100644 index 0000000..b9c52d1 --- /dev/null +++ b/extensions/cdevGenericServer/include/makeinclude/Makefile.linux @@ -0,0 +1,94 @@ +# ****************************************************************************** +# * Makefile.Linux : This is the platform specific Makefile for Linux. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = Linux + +include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only specify the DEBUGFLAG if the DEBUG variable has been set. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +else +DEBUGFLAG = -O2 +endif + +CXX = g++ +CC = gcc +CXXFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS -fno-for-scope $(DEBUGFLAG) $(CXXEXTRA) $(CXXINCLUDES) \ + $(CDEVINCLUDES) $(BASEINCLUDES) +CFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS $(DEBUGFLAG) $(CEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(BASEINCLUDES) +AR = ar +ARFLAGS = ruv +RANLIB = ranlib +DLD = $(CXX) +SOFLAGS = -shared +PIC = -fpic +SHARED_EXT = so +NETLIBS = +OSLIBS = $(NETLIBS) -lm -ldl + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) $(PIC) -c -o $@ $^ +COMPILE.c = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = $(QUIET)$(LINK_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) +#$(CXX) $(CXXFLAGS) -Xlinker -rpath -Xlinker $(BASELIB) -Xlinker -rpath -Xlinker $(CDEVLIB) +LINK.a = $(QUIET)$(AR_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(AR) $(ARFLAGS) +LINK.so = $(QUIET)$(SO_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(DLD) $(SOFLAGS) + +# ****************************************************************************** +# * This is the macro to build a shared object/library.... it requires the +# * following variables to be defined... +# * +# * SO_SRCS : Names of the component source files +# * SO_LIBS : Names of the dependent libraries +# * LIBS : All libraries necessary to compile the dummy application +# ****************************************************************************** +SOBUILD = rm -f $@;\ + mkdir -p $(@D);\ + echo "=> Building shared object $(@F)";\ + $(LINK.so) -o $@ $^ -R $(CDEVLIB) -L$(CDEVLIB) -L./ $(NETLIBS) + + diff --git a/extensions/cdevGenericServer/include/makeinclude/Makefile.linux-redhat5.2-alpha b/extensions/cdevGenericServer/include/makeinclude/Makefile.linux-redhat5.2-alpha new file mode 100644 index 0000000..e8e1f4f --- /dev/null +++ b/extensions/cdevGenericServer/include/makeinclude/Makefile.linux-redhat5.2-alpha @@ -0,0 +1,93 @@ +# ****************************************************************************** +# * Makefile.Linux : This is the platform specific Makefile for Linux. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = Linux + +include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only specify the DEBUGFLAG if the DEBUG variable has been set. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +else +DEBUGFLAG = -O2 +endif + +CXX = g++ +CC = gcc +CXXFLAGS = -DLinux -DCDEV_HAS_64BIT_LONGS -fno-for-scope $(DEBUGFLAG) $(CXXEXTRA) $(CXXINCLUDES) \ + $(CDEVINCLUDES) $(BASEINCLUDES) +CFLAGS = -DLinux -DCDEV_HAS_64BIT_LONGS $(DEBUGFLAG) $(CEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(BASEINCLUDES) +AR = ar +ARFLAGS = ruv +RANLIB = ranlib +DLD = $(CXX) +SOFLAGS = -shared +PIC = -fpic +SHARED_EXT = so +NETLIBS = +OSLIBS = $(NETLIBS) -lm -ldl + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) $(PIC) -c -o $@ $^ +COMPILE.c = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = $(QUIET)$(LINK_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) -Xlinker -rpath -Xlinker $(BASELIB) -Xlinker -rpath -Xlinker $(CDEVLIB) +LINK.a = $(QUIET)$(AR_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(AR) $(ARFLAGS) +LINK.so = $(QUIET)$(SO_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(DLD) $(SOFLAGS) + +# ****************************************************************************** +# * This is the macro to build a shared object/library.... it requires the +# * following variables to be defined... +# * +# * SO_SRCS : Names of the component source files +# * SO_LIBS : Names of the dependent libraries +# * LIBS : All libraries necessary to compile the dummy application +# ****************************************************************************** +SOBUILD = rm -f $@;\ + mkdir -p $(@D);\ + echo "=> Building shared object $(@F)";\ + $(LINK.so) -o $@ $^ -R $(CDEVLIB) -L$(CDEVLIB) -L./ $(NETLIBS) + + diff --git a/extensions/cdevGenericServer/include/makeinclude/Makefile.linux-redhat5.2-x86 b/extensions/cdevGenericServer/include/makeinclude/Makefile.linux-redhat5.2-x86 new file mode 100644 index 0000000..462843e --- /dev/null +++ b/extensions/cdevGenericServer/include/makeinclude/Makefile.linux-redhat5.2-x86 @@ -0,0 +1,94 @@ +# ****************************************************************************** +# * Makefile.Linux : This is the platform specific Makefile for Linux. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = Linux + +include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only specify the DEBUGFLAG if the DEBUG variable has been set. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +else +DEBUGFLAG = -O2 +endif + +CXX = g++ +CC = gcc +CXXFLAGS = -DLinux -fno-for-scope $(DEBUGFLAG) $(CXXEXTRA) $(CXXINCLUDES) \ + $(CDEVINCLUDES) $(BASEINCLUDES) +CFLAGS = -DLinux $(DEBUGFLAG) $(CEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(BASEINCLUDES) +AR = ar +ARFLAGS = ruv +RANLIB = ranlib +DLD = $(CXX) +SOFLAGS = -shared +PIC = -fpic +SHARED_EXT = so +NETLIBS = +OSLIBS = $(NETLIBS) -lm -ldl + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) $(PIC) -c -o $@ $^ +COMPILE.c = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = $(QUIET)$(LINK_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) +#$(CXX) $(CXXFLAGS) -Xlinker -rpath -Xlinker $(BASELIB) -Xlinker -rpath -Xlinker $(CDEVLIB) +LINK.a = $(QUIET)$(AR_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(AR) $(ARFLAGS) +LINK.so = $(QUIET)$(SO_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(DLD) $(SOFLAGS) + +# ****************************************************************************** +# * This is the macro to build a shared object/library.... it requires the +# * following variables to be defined... +# * +# * SO_SRCS : Names of the component source files +# * SO_LIBS : Names of the dependent libraries +# * LIBS : All libraries necessary to compile the dummy application +# ****************************************************************************** +SOBUILD = rm -f $@;\ + mkdir -p $(@D);\ + echo "=> Building shared object $(@F)";\ + $(LINK.so) -o $@ $^ -R $(CDEVLIB) -L$(CDEVLIB) -L./ $(NETLIBS) + + diff --git a/extensions/cdevGenericServer/include/makeinclude/Makefile.linux-redhat6.0-alpha b/extensions/cdevGenericServer/include/makeinclude/Makefile.linux-redhat6.0-alpha new file mode 100644 index 0000000..fff5966 --- /dev/null +++ b/extensions/cdevGenericServer/include/makeinclude/Makefile.linux-redhat6.0-alpha @@ -0,0 +1,93 @@ +# ****************************************************************************** +# * Makefile.Linux : This is the platform specific Makefile for Linux. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = Linux + +include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only specify the DEBUGFLAG if the DEBUG variable has been set. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +else +DEBUGFLAG = -O2 +endif + +CXX = g++ +CC = gcc +CXXFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS -DCDEV_HAS_64BIT_LONGS -fno-for-scope $(DEBUGFLAG) $(CXXEXTRA) $(CXXINCLUDES) \ + $(CDEVINCLUDES) $(BASEINCLUDES) +CFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS -DCDEV_HAS_64BIT_LONGS $(DEBUGFLAG) $(CEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(BASEINCLUDES) +AR = ar +ARFLAGS = ruv +RANLIB = ranlib +DLD = $(CXX) +SOFLAGS = -shared +PIC = -fpic +SHARED_EXT = so +NETLIBS = +OSLIBS = $(NETLIBS) -lm -ldl + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) $(PIC) -c -o $@ $^ +COMPILE.c = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = $(QUIET)$(LINK_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) -Xlinker -rpath -Xlinker $(BASELIB) -Xlinker -rpath -Xlinker $(CDEVLIB) +LINK.a = $(QUIET)$(AR_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(AR) $(ARFLAGS) +LINK.so = $(QUIET)$(SO_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(DLD) $(SOFLAGS) + +# ****************************************************************************** +# * This is the macro to build a shared object/library.... it requires the +# * following variables to be defined... +# * +# * SO_SRCS : Names of the component source files +# * SO_LIBS : Names of the dependent libraries +# * LIBS : All libraries necessary to compile the dummy application +# ****************************************************************************** +SOBUILD = rm -f $@;\ + mkdir -p $(@D);\ + echo "=> Building shared object $(@F)";\ + $(LINK.so) -o $@ $^ -R $(CDEVLIB) -L$(CDEVLIB) -L./ $(NETLIBS) + + diff --git a/extensions/cdevGenericServer/include/makeinclude/Makefile.linux-redhat6.0-x86 b/extensions/cdevGenericServer/include/makeinclude/Makefile.linux-redhat6.0-x86 new file mode 100644 index 0000000..b9c52d1 --- /dev/null +++ b/extensions/cdevGenericServer/include/makeinclude/Makefile.linux-redhat6.0-x86 @@ -0,0 +1,94 @@ +# ****************************************************************************** +# * Makefile.Linux : This is the platform specific Makefile for Linux. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = Linux + +include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only specify the DEBUGFLAG if the DEBUG variable has been set. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +else +DEBUGFLAG = -O2 +endif + +CXX = g++ +CC = gcc +CXXFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS -fno-for-scope $(DEBUGFLAG) $(CXXEXTRA) $(CXXINCLUDES) \ + $(CDEVINCLUDES) $(BASEINCLUDES) +CFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS $(DEBUGFLAG) $(CEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(BASEINCLUDES) +AR = ar +ARFLAGS = ruv +RANLIB = ranlib +DLD = $(CXX) +SOFLAGS = -shared +PIC = -fpic +SHARED_EXT = so +NETLIBS = +OSLIBS = $(NETLIBS) -lm -ldl + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) $(PIC) -c -o $@ $^ +COMPILE.c = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = $(QUIET)$(LINK_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) +#$(CXX) $(CXXFLAGS) -Xlinker -rpath -Xlinker $(BASELIB) -Xlinker -rpath -Xlinker $(CDEVLIB) +LINK.a = $(QUIET)$(AR_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(AR) $(ARFLAGS) +LINK.so = $(QUIET)$(SO_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(DLD) $(SOFLAGS) + +# ****************************************************************************** +# * This is the macro to build a shared object/library.... it requires the +# * following variables to be defined... +# * +# * SO_SRCS : Names of the component source files +# * SO_LIBS : Names of the dependent libraries +# * LIBS : All libraries necessary to compile the dummy application +# ****************************************************************************** +SOBUILD = rm -f $@;\ + mkdir -p $(@D);\ + echo "=> Building shared object $(@F)";\ + $(LINK.so) -o $@ $^ -R $(CDEVLIB) -L$(CDEVLIB) -L./ $(NETLIBS) + + diff --git a/extensions/cdevGenericServer/include/makeinclude/Makefile.linux-redhat6.2-x86 b/extensions/cdevGenericServer/include/makeinclude/Makefile.linux-redhat6.2-x86 new file mode 100644 index 0000000..b9c52d1 --- /dev/null +++ b/extensions/cdevGenericServer/include/makeinclude/Makefile.linux-redhat6.2-x86 @@ -0,0 +1,94 @@ +# ****************************************************************************** +# * Makefile.Linux : This is the platform specific Makefile for Linux. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = Linux + +include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only specify the DEBUGFLAG if the DEBUG variable has been set. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +else +DEBUGFLAG = -O2 +endif + +CXX = g++ +CC = gcc +CXXFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS -fno-for-scope $(DEBUGFLAG) $(CXXEXTRA) $(CXXINCLUDES) \ + $(CDEVINCLUDES) $(BASEINCLUDES) +CFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS $(DEBUGFLAG) $(CEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(BASEINCLUDES) +AR = ar +ARFLAGS = ruv +RANLIB = ranlib +DLD = $(CXX) +SOFLAGS = -shared +PIC = -fpic +SHARED_EXT = so +NETLIBS = +OSLIBS = $(NETLIBS) -lm -ldl + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) $(PIC) -c -o $@ $^ +COMPILE.c = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = $(QUIET)$(LINK_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) +#$(CXX) $(CXXFLAGS) -Xlinker -rpath -Xlinker $(BASELIB) -Xlinker -rpath -Xlinker $(CDEVLIB) +LINK.a = $(QUIET)$(AR_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(AR) $(ARFLAGS) +LINK.so = $(QUIET)$(SO_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(DLD) $(SOFLAGS) + +# ****************************************************************************** +# * This is the macro to build a shared object/library.... it requires the +# * following variables to be defined... +# * +# * SO_SRCS : Names of the component source files +# * SO_LIBS : Names of the dependent libraries +# * LIBS : All libraries necessary to compile the dummy application +# ****************************************************************************** +SOBUILD = rm -f $@;\ + mkdir -p $(@D);\ + echo "=> Building shared object $(@F)";\ + $(LINK.so) -o $@ $^ -R $(CDEVLIB) -L$(CDEVLIB) -L./ $(NETLIBS) + + diff --git a/extensions/cdevGenericServer/include/makeinclude/Makefile.solaris b/extensions/cdevGenericServer/include/makeinclude/Makefile.solaris new file mode 100755 index 0000000..68e7b95 --- /dev/null +++ b/extensions/cdevGenericServer/include/makeinclude/Makefile.solaris @@ -0,0 +1,93 @@ +# ****************************************************************************** +# * Makefile.solaris : This is the platform specific Makefile for solaris. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = solaris + +include $(CDEV)/extensions/cdevGenericServer/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only specify the DEBUGFLAG if the DEBUG variable has been set. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +endif + +CXX = CC +CC = cc +CXXFLAGS = -Dsolaris $(DEBUGFLAG) $(CXXEXTRA) $(CXXINCLUDES) \ + $(CDEVINCLUDES) $(BASEINCLUDES) -DSYSV +CFLAGS = -Dsolaris $(DEBUGFLAG) $(CEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(BASEINCLUDES) -DSYSV +AR = $(CXX) +ARFLAGS = -xar -o +RANLIB = ranlib +DLD = $(CXX) +SOFLAGS = -G $(CXXFLAGS) +PIC = -Kpic +SHARED_EXT = so +NETLIBS = -lsocket -lnsl -ldl -lgen +OSLIBS = $(NETLIBS) -ll -ly -lm + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) $(PIC) -c -o $@ $^;\ + $(CXX) $(CXXFLAGS) -G -o $(@D)/$(*F).so -h $(@D)/$(*F).so \ + -R $(CDEVLIB) -L$(CDEVLIB) -L./ $@ +COMPILE.c = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(QUIET)$(CC_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = $(QUIET)$(CXX_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(CXX) $(CXXFLAGS) +LINK.a = $(QUIET)$(AR_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(AR) $(ARFLAGS) +LINK.so = $(QUIET)$(SO_CMD_ECHO)rm -rf $@;\ + mkdir -p $(@D);\ + $(DLD) $(SOFLAGS) + +# ****************************************************************************** +# * This is the macro to build a shared object/library.... it requires the +# * following variables to be defined... +# * +# * SO_SRCS : Names of the component source files +# * SO_LIBS : Names of the dependent libraries +# * LIBS : All libraries necessary to compile the dummy application +# ****************************************************************************** +SOBUILD = rm -f $@;\ + mkdir -p $(@D);\ + echo "=> Building shared object $(@F)";\ + $(LINK.so) -o $@ $^ -R $(CDEVLIB) -L$(CDEVLIB) -L./ $(NETLIBS) + + diff --git a/extensions/cdevGenericServer/include/makeinclude/NMakefile.lib b/extensions/cdevGenericServer/include/makeinclude/NMakefile.lib new file mode 100644 index 0000000..dddc332 --- /dev/null +++ b/extensions/cdevGenericServer/include/makeinclude/NMakefile.lib @@ -0,0 +1,204 @@ +.SUFFIXES: .cc .obj + +APPNAME = CDEV Generic Client/Server Engine +ARCH = WINNT-4.0 + +BINARIES = $(CDEVLIB)\cdevGenericServer.dll \ + $(CDEVLIB)\cdevGenericServer.lib + +include ..\include\makeinclude\Makefile.WINNT-4.0 + +TEMPLINKS = ClientAcceptor.cc\ + ClientHandler.cc\ + cdevServer.cc\ + cdevServerTools.cc\ + cdevSessionManager.cc\ + ServerInterface.cc\ + ServerHandler.cc\ + cdevClientRequestObject.cc\ + cdevClientService.cc\ + cdevMessage.cc\ + cdevMessageBinary.cc\ + cdevPacket.cc\ + cdevContextMap.cc\ + cdevMonitorTable.cc\ + cdevTagMap.cc\ + SignalManager.cc\ + cdevAddr.cc\ + cdevEventHandler.cc\ + cdevHandleSet.cc\ + cdevReactor.cc\ + cdevSocket.cc\ + cdevSocketAcceptor.cc\ + cdevSocketConnector.cc\ + cdevSocketDatagram.cc\ + cdevSocketStream.cc\ + cdevStreamNode.cc\ + cdevStreamQueue.cc\ + cdevTime.cc\ + fifo.cc\ + IntHash.cc + + +LIBS = $(CDEVLIBS) $(OSLIBS) + +SERVER_OBJS = $(OBJDIR)\cdevServer.obj\ + $(OBJDIR)\cdevServerTools.obj\ + $(OBJDIR)\cdevSessionManager.obj\ + $(OBJDIR)\ClientHandler.obj\ + $(OBJDIR)\ClientAcceptor.obj\ + $(OBJDIR)\cdevTagMap.obj\ + $(OBJDIR)\cdevMonitorTable.obj + +CLIENT_OBJS = $(OBJDIR)\cdevClientService.obj\ + $(OBJDIR)\cdevClientRequestObject.obj\ + $(OBJDIR)\ServerInterface.obj\ + $(OBJDIR)\ServerHandler.obj + +COMMON_OBJS = $(OBJDIR)\cdevPacket.obj\ + $(OBJDIR)\cdevMessageBinary.obj\ + $(OBJDIR)\cdevMessage.obj\ + $(OBJDIR)\cdevContextMap.obj\ + $(OBJDIR)\SignalManager.obj\ + $(OBJDIR)\fifo.obj\ + $(OBJDIR)\IntHash.obj + +ACE_OBJS = $(OBJDIR)\cdevAddr.obj\ + $(OBJDIR)\cdevEventHandler.obj\ + $(OBJDIR)\cdevHandleSet.obj\ + $(OBJDIR)\cdevReactor.obj\ + $(OBJDIR)\cdevSocket.obj\ + $(OBJDIR)\cdevSocketAcceptor.obj\ + $(OBJDIR)\cdevSocketConnector.obj\ + $(OBJDIR)\cdevSocketDatagram.obj\ + $(OBJDIR)\cdevSocketStream.obj\ + $(OBJDIR)\cdevStreamNode.obj\ + $(OBJDIR)\cdevStreamQueue.obj\ + $(OBJDIR)\cdevTime.obj + +OBJS = $(SERVER_OBJS) $(CLIENT_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + +CXXEXTRA = /D "_CDEV_REACTOR_EXPORTS_=1" /D "_GENERIC_SERVER_EXPORTS_=1" + +# ****************************************************************************** +# * The BINARIES definition names all of the binary files that should be deleted +# * whenever "make clean" is executed. +# ****************************************************************************** +BINARIES = $(CDEVLIB)\cdevGenericServer.dll \ + $(CDEVLIB)\cdevGenericServer.lib + +!IF "$(SHOBJ)" == "YES" +TARGETS = $(TEMPLINKS) $(CDEVLIB)\cdevGenericServer.dll +!ELSE +TARGETS = $(TEMPLINKS) $(CDEVLIB)\cdevGenericServer.lib +!ENDIF + +targets : $(TARGETS) + @erase $(TEMPLINKS) + +$(CDEVLIB)\cdevGenericServer.lib : $(OBJS) + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\rsvc.lib\ + $(LINK_LIB_FLAGS) /out:$@ $(OBJS) + @echo ^ ^ ^ ^ ^ ^ Done... + +$(CDEVLIB)\cdevGenericServer.dll : $(OBJS) + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\rsvc.lib\ + $(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $(OBJS) + @echo ^ ^ ^ ^ ^ ^ Done... + +ClientAcceptor.cc : ..\cdevServer\ClientAcceptor.cc + -@$(CREATE_LINK) + +ClientHandler.cc : ..\cdevServer\ClientHandler.cc + -@$(CREATE_LINK) + +cdevServer.cc : ..\cdevServer\cdevServer.cc + -@$(CREATE_LINK) + +cdevServerTools.cc : ..\cdevServer\cdevServerTools.cc + -@$(CREATE_LINK) + +cdevSessionManager.cc : ..\cdevServer\cdevSessionManager.cc + -@$(CREATE_LINK) + +ServerHandler.cc : ..\cdevClient\ServerHandler.cc + -@$(CREATE_LINK) + +ServerInterface.cc : ..\cdevClient\ServerInterface.cc + -@$(CREATE_LINK) + +cdevClientRequestObject.cc : ..\cdevClient\cdevClientRequestObject.cc + -@$(CREATE_LINK) + +cdevClientService.cc : ..\cdevClient\cdevClientService.cc + -@$(CREATE_LINK) + +cdevMessage.cc : ..\cdevPacket\cdevMessage.cc + -@$(CREATE_LINK) + +cdevMessageBinary.cc : ..\cdevPacket\cdevMessageBinary.cc + -@$(CREATE_LINK) + +cdevPacket.cc : ..\cdevPacket\cdevPacket.cc + -@$(CREATE_LINK) + +cdevContextMap.cc : ..\cdevContextMap\cdevContextMap.cc + -@$(CREATE_LINK) + +cdevMonitorTable.cc : ..\cdevMonitorTable\cdevMonitorTable.cc + -@$(CREATE_LINK) + +cdevTagMap.cc : ..\cdevTagMap\cdevTagMap.cc + -@$(CREATE_LINK) + +SignalManager.cc : ..\common\SignalManager.cc + -@$(CREATE_LINK) + +cdevAddr.cc : ..\cdevReactor\cdevAddr.cc + -@$(CREATE_LINK) + +cdevEventHandler.cc : ..\cdevReactor\cdevEventHandler.cc + -@$(CREATE_LINK) + +cdevHandleSet.cc : ..\cdevReactor\cdevHandleSet.cc + -@$(CREATE_LINK) + +cdevReactor.cc : ..\cdevReactor\cdevReactor.cc + -@$(CREATE_LINK) + +cdevSocket.cc : ..\cdevReactor\cdevSocket.cc + -@$(CREATE_LINK) + +cdevSocketAcceptor.cc : ..\cdevReactor\cdevSocketAcceptor.cc + -@$(CREATE_LINK) + +cdevSocketConnector.cc : ..\cdevReactor\cdevSocketConnector.cc + -@$(CREATE_LINK) + +cdevSocketDatagram.cc : ..\cdevReactor\cdevSocketDatagram.cc + -@$(CREATE_LINK) + +cdevSocketStream.cc : ..\cdevReactor\cdevSocketStream.cc + -@$(CREATE_LINK) + +cdevStreamNode.cc : ..\cdevReactor\cdevStreamNode.cc + -@$(CREATE_LINK) + +cdevStreamQueue.cc : ..\cdevReactor\cdevStreamQueue.cc + -@$(CREATE_LINK) + +cdevTime.cc : ..\cdevReactor\cdevTime.cc + -@$(CREATE_LINK) + +fifo.cc : ..\common\fifo.cc + -@$(CREATE_LINK) + +IntHash.cc : ..\common\IntHash.cc + -@$(CREATE_LINK) + diff --git a/extensions/cdevGenericServer/include/rnsMonitorObj.h b/extensions/cdevGenericServer/include/rnsMonitorObj.h new file mode 100644 index 0000000..197a1ce --- /dev/null +++ b/extensions/cdevGenericServer/include/rnsMonitorObj.h @@ -0,0 +1,54 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Name Server Monitor Object +// +// Author: Jie Chen +// +// +// +#ifndef _RNS_MONITOR_OBJ_H +#define _RNS_MONITOR_OBJ_H + +#include + +class rnsRequestObject; + +class rnsMonitorObj : public cdevMonitorObj +{ +public: + // constructor and destructor + rnsMonitorObj (cdevTranObj& tranObj) + :cdevMonitorObj (tranObj), out_ (0), started_ (1) + { +#ifdef _TRACE_OBJECTS + printf (" Create rnsMonitorObj Class Object\n"); +#endif + } + + ~rnsMonitorObj (void) + { +#ifdef _TRACE_OBJECTS + printf (" Delete rnsMonitorObj Class Object\n"); +#endif + if (out_) + delete out_; + } + + const char* className (void) const {return "rnsMonitorObj";} + + // out bound cdevdata + cdevData* out_; + + // whether this monitor callback is restarted or not + int started_; +}; +#endif + diff --git a/extensions/cdevGenericServer/include/rnsQueryCollector.h b/extensions/cdevGenericServer/include/rnsQueryCollector.h new file mode 100644 index 0000000..3a7a1a7 --- /dev/null +++ b/extensions/cdevGenericServer/include/rnsQueryCollector.h @@ -0,0 +1,439 @@ +#include +#include +#include +#include + +class rnsQueryCollector +{ +private: + cdevData * data; + int deleteFlag; + unsigned char * byteData; + short * shortData; + unsigned short * ushortData; + long * longData; + unsigned long * ulongData; + float * floatData; + double * doubleData; + cdev_TS_STAMP * tsData; + size_t byteCnt; + size_t shortCnt; + size_t ushortCnt; + size_t longCnt; + size_t ulongCnt; + size_t floatCnt; + size_t doubleCnt; + size_t tsCnt; + +public: + rnsQueryCollector ( cdevData & userData, int deleteData = 0 ) + : data(&userData), deleteFlag(deleteData), + byteData(NULL), shortData(NULL), ushortData(NULL), + longData(NULL), ulongData(NULL), floatData(NULL), + doubleData(NULL), tsData(NULL), byteCnt(0), + shortCnt(0), ushortCnt(0), longCnt(0), ulongCnt(0), + floatCnt(0), doubleCnt(0), tsCnt(0) + { + data->remove(); + } + + ~rnsQueryCollector ( void ) + { + if(deleteFlag) delete data; + if(byteData) delete byteData; + if(shortData) delete shortData; + if(ushortData) delete ushortData; + if(longData) delete longData; + if(ulongData) delete ulongData; + if(floatData) delete floatData; + if(doubleData) delete doubleData; + if(tsData) delete tsData; + } + + cdevData * getData ( void ) { return data; } + void clearData ( void ) { data->remove(); } + inline int collect ( cdevData & userData ); + +private: + inline int collectAttribute ( cdevData & userData, int tag, int position ); + inline void collectByteAttribute ( cdevData & userData, int tag, int position ); + inline void collectShortAttribute ( cdevData & userData, int tag, int position ); + inline void collectUShortAttribute ( cdevData & userData, int tag, int position ); + inline void collectLongAttribute ( cdevData & userData, int tag, int position ); + inline void collectULongAttribute ( cdevData & userData, int tag, int position ); + inline void collectFloatAttribute ( cdevData & userData, int tag, int position ); + inline void collectDoubleAttribute ( cdevData & userData, int tag, int position ); + inline void collectStringAttribute ( cdevData & userData, int tag, int position ); + inline void collectTimestampAttribute ( cdevData & userData, int tag, int position ); +}; + + +// ***************************************************************************** +// * class rnsQueryCallback : +// * This class provides the methods to allow a rnsQueryCollector to be +// * incorporated into a cdevCallback. The localCallback function will +// * be called with results until the data has been completely collected, +// * and only then will the user callback be executed - providing full +// * data. +// ***************************************************************************** +class rnsQueryCallback : public cdevCallback +{ +private: + rnsQueryCollector collector; + cdevCallback callback; + +public: + rnsQueryCallback ( cdevCallback & Callback ) + : cdevCallback(), callback(Callback), collector(*(new cdevData), 1) + { + userarg_ = this; + function_ = rnsQueryCallback::localCallback; + } + + virtual ~rnsQueryCallback ( void ) + { + } + + static void localCallback ( int status, void * arg, cdevRequestObject & req, cdevData & data) + { + rnsQueryCallback * qCallback; + + if((qCallback = (rnsQueryCallback *)arg)!=NULL) + { + if(status==CDEV_SUCCESS || + status==CDEV_INCOMPLETE) + { + qCallback->collector.collect(data); + } + + if(status==CDEV_SUCCESS || + status==CDEV_ERROR || + status==CDEV_NOTFOUND || + status==CDEV_MSG_ERR) + { + qCallback->callback.fireCallback(status, qCallback->callback.userarg(), + req, *qCallback->collector.getData(), 0); + } + } + } +}; + + +// ***************************************************************************** +// * rnsQueryCollector::collect : +// * This method is called when a cdevData object needs to be appended to +// * the cdevData object that is serving as a collection. This method will +// * transfer each of the data items in the userData object to the proper +// * position in the local data object. +// ***************************************************************************** +int rnsQueryCollector::collect ( cdevData & userData ) + { + int cnt = 0; + size_t size = 0; + cdevDataIterator iter(&userData); + cdevDataIterator dIter(data); + + // ********************************************************************* + // * Look through the existing data and determine the largest number + // * of items that exist in a single tagged item. This value will be + // * used to specify the position of the data that is being added to the + // * array. + // ********************************************************************* + dIter.init(); + while(dIter.tag()!=0) + { + size_t elems = 0; + data->getElems(dIter.tag(), &elems); + if(elems>size) size = elems; + ++dIter; + } + + // ********************************************************************* + // * Walk through the list of tagged data items that are stored in the + // * inbound data object. Call the collectAttribute method for each + // * data item. This method will copy the contents of the inbound + // * data object to the correct position in the local data object. + // ********************************************************************* + iter.init(); + while(iter.tag()!=0) + { + cnt+=(collectAttribute(userData, iter.tag(), size)==0)?1:0; + ++iter; + } + + // ********************************************************************* + // * Return the count of data items that were assimilated into the + // * local data object. + // ********************************************************************* + return cnt; + } + + +// ***************************************************************************** +// * rnsQueryCollector::collectAttribute : +// * This method will assimilate a single attribute from the specified +// * userData object into the local cdevData object at the specified +// * position. +// ***************************************************************************** +int rnsQueryCollector::collectAttribute ( cdevData & userData, int tag, int position ) + { + cdevSystem & sys = cdevSystem::defaultSystem(); + int result = 0; + size_t dim = 0; + size_t userDim = 0; + cdevDataTypes type = data->getType(tag); + cdevDataTypes userType = userData.getType(tag); + + if(userData.getDim(tag, &dim)==CDEV_NOTFOUND || dim > 0) + { + sys.reportError(CDEV_SEVERITY_ERROR, "Name Server", NULL, + "Cannot add array data to query reply"); + result = -1; + } + else if(data->getDim(tag, &dim)!=CDEV_NOTFOUND && dim > 1) + { + sys.reportError(CDEV_SEVERITY_ERROR, "Name Server", NULL, + "Cannot assemble a query with multi-dimensional data"); + result = -1; + } + else if (userType == CDEV_INVALID) + { + sys.reportError(CDEV_SEVERITY_ERROR, "Name Server", NULL, + "Inbound query data object has invalid data type"); + result = -1; + } + else { + if(type!=CDEV_INVALID) + { + if(typeuserType)?type:userType; + } + else if(type==CDEV_TIMESTAMP) type = userType; + } + else type = userType; + + switch(type) + { + case CDEV_BYTE: + collectByteAttribute(userData, tag, position); + break; + case CDEV_INT16: + collectShortAttribute(userData, tag, position); + break; + case CDEV_UINT16: + collectUShortAttribute(userData, tag, position); + break; + case CDEV_INT32: + collectLongAttribute(userData, tag, position); + break; + case CDEV_UINT32: + collectULongAttribute(userData, tag, position); + break; + case CDEV_FLOAT: + collectFloatAttribute(userData, tag, position); + break; + case CDEV_DOUBLE: + collectDoubleAttribute(userData, tag, position); + break; + case CDEV_STRING: + collectStringAttribute(userData, tag, position); + break; + case CDEV_TIMESTAMP: + collectTimestampAttribute(userData, tag, position); + break; + default: + result = -1; + break; + } + } + return result; + } + + +// ***************************************************************************** +// * rnsQueryCollector::collectByteAttribute : +// * This method will transfer the byte attribute stored in the userData +// * object into the local cdevData object at the specified position. +// ***************************************************************************** +void rnsQueryCollector::collectByteAttribute (cdevData & userData, int tag, int position ) + { + if((position+1)>byteCnt) + { + if(byteData!=NULL) delete byteData; + byteCnt = ((position+1)>100)?(position+100):100; + byteData = new unsigned char [byteCnt]; + } + memset(byteData, 0, byteCnt*sizeof(unsigned char)); + data->get(tag, byteData); + userData.get(tag, &byteData[position]); + data->insert(tag, byteData, position+1); + } + +// ***************************************************************************** +// * rnsQueryCollector::collectShortAttribute : +// * This method will transfer the short attribute stored in the userData +// * object into the local cdevData object at the specified position. +// ***************************************************************************** +void rnsQueryCollector::collectShortAttribute (cdevData & userData, int tag, int position ) + { + if((position+1)>shortCnt) + { + if(shortData!=NULL) delete shortData; + shortCnt = ((position+1)>100)?(position+100):100; + shortData = new short [shortCnt]; + } + memset(shortData, 0, shortCnt*sizeof(short)); + data->get(tag, shortData); + userData.get(tag, &shortData[position]); + data->insert(tag, shortData, position+1); + } + +// ***************************************************************************** +// * rnsQueryCollector::collectUShortAttribute : +// * This method will transfer the unsigned short attribute stored in the +// * userData object into the local cdevData object at the specified +// * position. +// ***************************************************************************** +void rnsQueryCollector::collectUShortAttribute (cdevData & userData, int tag, int position ) + { + if((position+1)>ushortCnt) + { + if(ushortData!=NULL) delete ushortData; + ushortCnt = ((position+1)>100)?(position+100):100; + ushortData = new unsigned short [ushortCnt]; + } + memset(ushortData, 0, ushortCnt*sizeof(unsigned short)); + data->get(tag, ushortData); + userData.get(tag, &ushortData[position]); + data->insert(tag, ushortData, position+1); + } + +// ***************************************************************************** +// * rnsQueryCollector::collectLongAttribute : +// * This method will transfer the long attribute stored in the +// * userData object into the local cdevData object at the specified +// * position. +// ***************************************************************************** +void rnsQueryCollector::collectLongAttribute (cdevData & userData, int tag, int position ) + { + if((position+1)>longCnt) + { + if(longData!=NULL) delete longData; + longCnt = ((position+1)>100)?(position+100):100; + longData = new long [longCnt]; + } + memset(longData, 0, longCnt*sizeof(long)); + data->get(tag, longData); + userData.get(tag, &longData[position]); + data->insert(tag, longData, position+1); + } + +// ***************************************************************************** +// * rnsQueryCollector::collectULongAttribute : +// * This method will transfer the unsigned long attribute stored in the +// * userData object into the local cdevData object at the specified +// * position. +// ***************************************************************************** +void rnsQueryCollector::collectULongAttribute (cdevData & userData, int tag, int position ) + { + if((position+1)>ulongCnt) + { + if(ulongData!=NULL) delete ulongData; + ulongCnt = ((position+1)>100)?(position+100):100; + ulongData = new unsigned long [ulongCnt]; + } + memset(ulongData, 0, ulongCnt*sizeof(unsigned long)); + data->get(tag, ulongData); + userData.get(tag, &ulongData[position]); + data->insert(tag, ulongData, position+1); + } + +// ***************************************************************************** +// * rnsQueryCollector::collectFloatAttribute : +// * This method will transfer the float attribute stored in the +// * userData object into the local cdevData object at the specified +// * position. +// ***************************************************************************** +void rnsQueryCollector::collectFloatAttribute (cdevData & userData, int tag, int position ) + { + if((position+1)>floatCnt) + { + if(floatData!=NULL) delete floatData; + floatCnt = ((position+1)>100)?(position+100):100; + floatData = new float [floatCnt]; + } + memset(floatData, 0, floatCnt*sizeof(float)); + data->get(tag, floatData); + userData.get(tag, &floatData[position]); + data->insert(tag, floatData, position+1); + } + +// ***************************************************************************** +// * rnsQueryCollector::collectDoubleAttribute : +// * This method will transfer the double attribute stored in the +// * userData object into the local cdevData object at the specified +// * position. +// ***************************************************************************** +void rnsQueryCollector::collectDoubleAttribute (cdevData & userData, int tag, int position ) + { + if((position+1)>doubleCnt) + { + if(doubleData!=NULL) delete doubleData; + doubleCnt = ((position+1)>100)?(position+100):100; + doubleData = new double [doubleCnt]; + } + memset(doubleData, 0, doubleCnt*sizeof(double)); + data->get(tag, doubleData); + userData.get(tag, &doubleData[position]); + data->insert(tag, doubleData, position+1); + } + +// ***************************************************************************** +// * rnsQueryCollector::collectStringAttribute : +// * This method will transfer the string attribute stored in the +// * userData object into the local cdevData object at the specified +// * position. +// ***************************************************************************** +void rnsQueryCollector::collectStringAttribute (cdevData & userData, int tag, int position ) + { + int i; + char blank = 0; + + char ** stringData = new char * [ position+1 ]; + memset(stringData, 0, (position+1)*sizeof(char *)); + data->get(tag, stringData); + userData.get(tag, &stringData[position]); + + for(i=0; iinsert(tag, stringData, position+1); + + for(i=0; itsCnt) + { + if(tsData!=NULL) delete tsData; + tsCnt = ((position+1)>100)?(position+100):100; + tsData = new cdev_TS_STAMP [tsCnt]; + } + memset(tsData, 0, tsCnt); + data->get(tag, tsData); + userData.get(tag, &tsData[position]); + data->insert(tag, tsData, position+1); + } diff --git a/extensions/cdevGenericServer/include/rnsRequestObject.h b/extensions/cdevGenericServer/include/rnsRequestObject.h new file mode 100644 index 0000000..8d3b0e5 --- /dev/null +++ b/extensions/cdevGenericServer/include/rnsRequestObject.h @@ -0,0 +1,130 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// CDEV Resource Name Service Request Object +// +// Author: Jie Chen +// +// +// +#ifndef _RNS_REQUEST_OBJECT_H +#define _RNS_REQUEST_OBJECT_H + +#include +#include + +class rsvcClient; +class rnsService; +class rnsMonitorObj; + +class rnsRequestObject: public cdevRequestObject +{ +public: + // constructor and destructor + rnsRequestObject (char* device, + char* msg, + rnsService* svc, + cdevSystem& system = cdevSystem::defaultSystem()); + ~rnsRequestObject (void); + + int send (cdevData& out, cdevData& result); + int send (cdevData *out, cdevData& result); + int send (cdevData& out, cdevData* result); + int send (cdevData *out, cdevData* result); + // PURPOSE: Synchronous IO operations + // REQUIRE: When do query and get, result must be provided + // PROMISE: return CDEV_SUCCESS: success. + + int sendNoBlock (cdevData& out, cdevData& result); + int sendNoBlock (cdevData* out, cdevData& result); + int sendNoBlock (cdevData& out, cdevData* result); + int sendNoBlock (cdevData* out, cdevData* result); + // PURPOSE: Asynchronous IO operations used in conjunction with + // cdevGroup or system + // REQUIRE: + // PROMISE: return CDEV_SUCCESS: requests have been sent out. + + int sendCallback (cdevData& out, cdevCallback& callback); + int sendCallback (cdevData* out, cdevCallback& callback); + // PURPOSE: Asynchromous IO operations with a user supplied callback function + // REQUIRE: + // PROMISE: User callback function will be called with status information + // status = CDEV_DISCONNECTED: channel discconected + // status = CDEV_SUCCESS : everything is OK + // status = CDEV_ERROR : something fishy. + // status = CDEV_INCOMPLETE : data flow will coming (88) + // status = CDEV_CBK_FINISHED: query callback finished (89) + // status = CDEV_QUERYMSG_ERR: query message syntax erro (91) + + int getState (void); + // PURPOSE: get connection state + // REQUIRE: none + // PROMISE: CDEV_CONNECTED or CDEV_NOTCONNECTED + + const char *className (void) const {return "rnsRequestObject";} + +protected: + // find out action from message + static int findAction (char* msg, int& action); + + // action value + typedef enum {GET = 0x2000,QUERY,MONITORON,MONITOROFF, + MONITORENTRY, MONITORENTRYOFF, UNKNOWN} RNSENUMVERB; + + // get value callback + static void getCallback (int status, void* arg, rsvcData* data); + + // query value callback + static void queryCallback (int status, void* arg, rsvcData* data); + + // monitor value callback + static void monitorCallback (int status, void* arg, rsvcData* data); + + // monitor entry callback + static void entryCallback (int status, void* arg, rsvcData* data); + + // data conversion from rsvc to cdev + static int dataRsvcToCdev (rsvcData& data, cdevData& result); + + // data conversion from cdev to rsvc + static int dataCdevToRsvc (cdevData& data, rsvcData& result); + + // remove a monitor object + int removeMonitorObject (rnsMonitorObj* mobj); + + // monitor off a callback + int monitorOff (rsvcData& data, rnsMonitorObj* obj); + + // monitor off entry callback + int monitorEntryOff (rnsMonitorObj* obj); + + // resend a monitor callback + int sendMonitor (rnsMonitorObj* mobj); + + // resend a monitor entry callback + int sendEntryMonitor (rnsMonitorObj* mobj); + +private: + + // two tags are needed for all serachs + static char* stags_[]; + static int numstags_; + + // action type + int action_; + + // pointer of underlying client connection + rsvcClient* client_; + + // friend class + friend class rnsService; + +}; +#endif diff --git a/extensions/cdevGenericServer/include/rnsService.h b/extensions/cdevGenericServer/include/rnsService.h new file mode 100644 index 0000000..a96580b --- /dev/null +++ b/extensions/cdevGenericServer/include/rnsService.h @@ -0,0 +1,128 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of cdev interface to resouce service client +// +// This is only a subset of whole APIs of rsvc client +// +// Author: Jie Chen +// +// +// +#ifndef _NS_SERVICE_H +#define _NS_SERVICE_H + +#ifndef _CDEV_MANAGE_SERVERS +#define _CDEV_MANAGE_SERVERS +#endif + +#include +#include +#include +#include +#include +#include +#include + +extern "C" RSVCAPI cdevService * newRnsService (char* name, cdevSystem* system); + +class rnsMonitorObj; +class rnsRequestObject; + +class rnsService: public cdevService +{ +public: + // cornstructor + rnsService (char* name, cdevSystem& system = cdevSystem::defaultSystem ()); + + int getFd (int * &fd, int &numFd); + // PURPOSE: return channel access network file descriptors + // REQUIRE: callers provide pointer only and don't free memory + // PROMISE: numFd will be real number of file descriptors of the + // channel access client. return 0: always + + int flush (void); + // PURPOSE: flush network requests + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS: success + + int poll (void); + // PURPOSE: polling method + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS: success. Else error + + int pend (int fd = -1); + // PURPOSE: handle network pending + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS: success, else error + + int pend (double seconds, int fd = -1); + // PURPOSE: handle network pending for 'seconds' + // REQUIRE: nothing + // PROMISE: return 0: success. return CDEV_TIMEOUT for timeout + + int getRequestObject (char *deviceName, char *msg, + cdevRequestObject * &req); + // PURPOSE: return a rnsRequestObject (called from attachPtr function + // of cdevRequestObject class) + // REQUIRE: right pair of deviceName and msg. + // PROMISE: a rnsRequestObject + + int getNameServer (cdevDevice* &rns); + // PURPOSE: retrieve ca name server in case of missing DDL + // REQUIRE: nothing + // PROMISE: + + int monitorsRestarted (void); + // PURPOSE: check whether all monitors have been restarted or not + // REQUIRE: nothing + // PROMISE: 1: yes, 0: no + + int reconnect (void); + // PURPOSE: reconnect to name server + // REQUIRE: nothing + // PROMISE: CDEV_SUCCESS on sucessful connection + + const char* className (void) const {return "rnsService";} + +protected: + + // deny direct access to destructor + ~rnsService (void); + + // add a monitor object + int addMonitorObject (rnsMonitorObj* obj); + // remove a monitor object + int removeMonitorObject (rnsMonitorObj* obj); + // check whether this callback is in the list + rnsMonitorObj* hasCallback (cdevCallback& cbk); + + // server disconnection callback + static void discCallback (int status, void* arg, rsvcData* data); + +private: + rsvcClient client_; + int *fds_; + int numFds_; + + // list of monitor object + cdevSlist monobjs_; + + // all tags needed for this service + static char* tags_[]; + + // number of tags needed for this service + static int numtags_; + + // friend class + friend class rnsRequestObject; +}; +#endif + diff --git a/extensions/cdevGenericServer/include/rsvcAcceptor.h b/extensions/cdevGenericServer/include/rsvcAcceptor.h new file mode 100644 index 0000000..0776d76 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcAcceptor.h @@ -0,0 +1,90 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC TCP Connection Acceptor +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_ACCEPTOR_H +#define _RSVC_ACCEPTOR_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +class rsvcIO; + +class rsvcAcceptor : public cdevEventHandler +{ +public: + // constructor: deny direct instantiation + rsvcAcceptor (cdevReactor& reactor, + rsvcDataStoreTable& table); + + // destructor + ~rsvcAcceptor (void); + + // open local address + int open (unsigned short port); + // return number of IO connections + int numberConnections (void); + // remove a connection from the list + int remove (rsvcIO* channel); + // check whether a rsvcIO is in this list + int includes (rsvcIO* channel); + + + // send a result to all clients + int sendToAllConnections (rsvcNetData* data); + + // return port number + unsigned short port_number (void); + + // return all connection list + rsvcSlist& connectionList (void); + +protected: + // inherited operations + int getHandle (void) const; + int handleClose (void); + + // inherited operations + int handleInput (void); + + // delete all clients : only used in the destructor + void deleteAllConnections (void); + + // data area + + cdevSocketAcceptor listener_; + cdevReactor & reactor_; + rsvcSlist connectionList_; + int listLock_; + + // global data store table + rsvcDataStoreTable& storeTable_; + + // friend class + friend class rsvcIO; +}; +#endif + diff --git a/extensions/cdevGenericServer/include/rsvcCacheData.h b/extensions/cdevGenericServer/include/rsvcCacheData.h new file mode 100644 index 0000000..57ddf93 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcCacheData.h @@ -0,0 +1,126 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server Cached Data Class +// +// This Class models the data objects that are stored inside +// cache information of a database +// +// Data always stored with key value +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_CACHE_DATA +#define _RSVC_CACHE_DATA + +#include +#include +#include +#include +#include +#include +#include + +class rsvcVirtualDbase; +class rsvcTableDef; +class rsvcCacheDataAttr; + +class rsvcCacheData : public rsvcHashable +{ +public: + // constructor + + // construct a cache data with a rsvcData which is transmitted + // over from network or database with key tag specified + rsvcCacheData (rsvcData& data, rsvcVirtualDbase* dbase, + rsvcTableDef* table); + + // destructor + virtual ~rsvcCacheData (void); + + // return hash code : inherited operation from rsvcHashable + unsigned int hash (void); + + // monitor on/off methods for the whole data + virtual int monitorOn (rsvcCbk& cbk); + virtual int monitorOff (rsvcCbk& cbk); + + // monitor on/off a single attribute + virtual int monitorAttr (char* attr, rsvcCbk& cbk); + virtual int monitorOffAttr (char* attr, rsvcCbk& cbk); + + // remove monitor specified by a io ptr + virtual int monitorOff (void* ioptr); + + // remove all monitors and attributes + void removeAllMonitors (void); + + // remove all attributes + void removeAllAttrs (void); + + // create all attributes + void createAllAttrs (void); + + // check whether this data or any attributes are being monitored + int monitored (void); + + // assignment or update method + int assign (rsvcData& value); + + // in case of any change in value. send new value to all interested + // parties + virtual void notifyChannels (int status = RSVC_SUCCESS); + + // notify channels with a particular attribute name + virtual void notifyChannels (char* attr); + + // retrieve internal data + rsvcData& data (void); + + // return attribute data + rsvcCacheDataAttr* attribute (char* attr); + + // check whether data has the same key value as data 'key' + int sameKey (rsvcCacheData* key); + +protected: + + // notify a single channel denoted by a cbk pointer + virtual void notifySingleChannel (rsvcCbk* cbk); + + // real data + rsvcData data_; + + // all monitor callback list: callback pointers + rsvcHash monitorTable_; + + // all data for attributes + rsvcHash attributes_; + + // assocaited database + rsvcVirtualDbase* database_; + + // assocaited table definition + rsvcTableDef* table_; + + // friend class + friend class rsvcCacheDataAttr; + + + // deny copy and assignment operations + rsvcCacheData (const rsvcCacheData& data); + rsvcCacheData& operator = (const rsvcCacheData& data); +}; +#endif + + + diff --git a/extensions/cdevGenericServer/include/rsvcCacheDataAttr.h b/extensions/cdevGenericServer/include/rsvcCacheDataAttr.h new file mode 100644 index 0000000..ac005b3 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcCacheDataAttr.h @@ -0,0 +1,73 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server Cache Data Attributes +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_CACHE_DATA_ATTR_H +#define _RSVC_CACHE_DATA_ATTR_H + +#include +#include +#include +#include +#include +#include +#include + +class rsvcCbk; + +class rsvcCacheDataAttr : public rsvcHashable +{ +public: + // constructor and destructor + rsvcCacheDataAttr (char* attr, rsvcCacheData& cache); + virtual ~rsvcCacheDataAttr (void); + + // return hash code + unsigned int hash (void); + + // monitor on/off + // outdata's are newly allocated data. + // remember to free those + virtual int monitorOn (rsvcCbk& cbk); + virtual int monitorOff (rsvcCbk& cbk); + // monitor off all with same ioptr + virtual int monitorOff (void* ioptr); + virtual int getValue (rsvcCbk& cbk); + + // return attribute name + char* attrName (void) const; + + // notify channels + void notifyChannels (void); + +protected: + + // remove all callbacks from the lists + void removeAllCbks (void); + + // attribute name + char* name_; + + // all callback list : (with all cbk pointers) + rsvcHash monitorList_; + + // whole cached data storage + rsvcCacheData& cache_; + + // deny access to copy and assignment operations + rsvcCacheDataAttr (const rsvcCacheDataAttr& attr); + rsvcCacheDataAttr& operator = (const rsvcCacheDataAttr& attr); +}; +#endif diff --git a/extensions/cdevGenericServer/include/rsvcCallback.h b/extensions/cdevGenericServer/include/rsvcCallback.h new file mode 100644 index 0000000..74bcac8 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcCallback.h @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Callback Class for Client +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_CALLBACK_H +#define _RSVC_CALLBACK_H + +#include +#include +#include + +typedef void (*rsvcCbkFunc) (int status, void* arg, rsvcData* data); + +class RSVC_CLASS_SPEC rsvcCallback +{ +public: + // constructor + rsvcCallback (void); + rsvcCallback (rsvcCbkFunc func, void* arg); + rsvcCallback (const rsvcCallback& cbk); + rsvcCallback& operator = (const rsvcCallback& cbk); + // destructor + ~rsvcCallback (void); + + int operator == (const rsvcCallback& cbk); + int operator != (const rsvcCallback& cbk); + + virtual rsvcCbkFunc cbkFunc (void) const; + virtual void* userarg (void) const; + + // return whether this callback is empty + int empty (void); + +private: + rsvcCbkFunc cbk_; + void* arg_; +}; +#endif diff --git a/extensions/cdevGenericServer/include/rsvcCbk.h b/extensions/cdevGenericServer/include/rsvcCbk.h new file mode 100644 index 0000000..58c1b71 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcCbk.h @@ -0,0 +1,105 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Callback Class (Used on Server/Client Side) +// +// This class contains protocol information related to callbacks +// 1. operation code +// 2. request id +// 3. socket id -->for server only +// 4. client id +// 5. callback id -->from client to server +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_CBK_H +#define _RSVC_CBK_H + +#include +#include +#include +#include +#include +#include + +class rsvcCbk : public rsvcStreamable, public rsvcHashable +{ +public: + // constructor + rsvcCbk (void); + rsvcCbk (int opcode, int cbkid, int reqid, int clientid, + int socketid = 0, int status = RSVC_SUCCESS, + void* usrptr = 0); + rsvcCbk (const rsvcCbk& cbk); + rsvcCbk& operator = (const rsvcCbk& cbk); + ~rsvcCbk (void); + + // clean up all values + void cleanup (void); + + void socketid (int id); + int socketid (void) const; + + void cbkstatus (int st); + int cbkstatus (void) const; + + int reqid (void) const; + void reqid (int req); + int opcode (void) const; + void opcode (int op); + int cbkid (void) const; + void cbkid (int id); + int clientid (void) const; + void clientid (int cid); + + // use by local only , not transmitted through wire + void* userptr (void) const; + void userptr (void* ptr); + + // inherited operation + unsigned int hash (void); + + size_t streamSize (void); + // stream out to a newly allocated buffer with size 'size' + int streamOut (char** buf, size_t* size); + // stream out to a preallocate buffer with buffer size 'size' + int streamOut (char* buf, size_t len); + // stream in from a buffer + int streamIn (char* buf, size_t len); + + // check whether two callbacks are the same. + // if checkreq == 1, check reqid otherwise no + // this function is used by server side to check + // whether a monitoroff callback is inside the callback table + // on the server. + static int sameCallback (rsvcCbk* cbk1, rsvcCbk* callback2, + int checkreq = 1); + + // check whether a callback coming back from the server + // match a callback in the table + int match (rsvcCbk* scbk); + +private: + // all data + int opcode_; + int cbkid_; + int reqid_; + int clientid_; + int socketid_; + int status_; + + // used by local only, not transmitted on wire + void* private_; +}; +#endif + + diff --git a/extensions/cdevGenericServer/include/rsvcClient.h b/extensions/cdevGenericServer/include/rsvcClient.h new file mode 100644 index 0000000..66ad76f --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcClient.h @@ -0,0 +1,290 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Client Handler Class +// +// Limitation on monitor: Callers cannot use same function with same user +// argument to monitor on different pieces +// of database +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_CLIENT_H +#define _RSVC_CLIENT_H + +#include +#include +#include +#include + +#ifdef _WIN32 + #include +#else + #include +#endif + +#include +#include +#include +#include +#include +#include + +class rsvcClientLocker; + +class RSVC_CLASS_SPEC rsvcClient +{ +public: + // constructor + rsvcClient (void); + ~rsvcClient (void); + + // connect to a rsvc server + // if timeout is zero, blocked connect will be used + int connect (char* host, unsigned short port, + double timeout = 0.0); + + // disconnect from the server + int disconnect (void); + + // return whether this client is connected + int connected (void); + + // register a disconnect callback + int disconnectCallback (rsvcCbkFunc func, void* arg); + + // get tcp file descriptor + int getFd (void) const; + + // pend io on this connected client + // Wait until outstanding events occur + // seconds = 0.0 polling + int pendIO (double seconds); + + // wait on this connection forever + int pendIO (void); + + // operations + + // create a table with definition defined in the data object + // the data object has to contain the following tags + // "key" "name" + // "keyExp" "attributename" or "attr0+attr1" + // "keyType" anything + // followed by taged values + + // data return from server inside callback is the database definition + int createMemDbase (char* tablename, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // open a database + // data return from server inside callback is the database definition + int openDatabase (char* tablename, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // insert data into database + // data must be match table definition + int insertValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg, + int overwrite = 0); + + // get data out from database + // data either contain a tagged value to denote a index value + // Example: "id", "model+gold" + // or contains multiple tagged values which can be constructed + // into a key value + int getValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // delete data from database + // data either contain a tagged value to denote a index value + // Example: "id", "model+gold" + // or contains multiple tagged values which can be constructed + // into a key value + int delValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg); + + + // set value for a datum inside database + // data either contain a tagged value to denote a index value + // Example: "id", "model+gold" + // or contains multiple tagged values which can be constructed + // into a key value + // plus a subset of tagged values defined in the table definition + int setValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // monitor incoming entries inside database + // any insertion to a database will trigger a callback + int monitorIncomingEntries (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // stop monitoring the incoming entries inside database + int monitorOffIncomingEntries (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg); + + + // monitor on a data inside a database + // any changes to this data will trigger a callback + // data either contain a tagged value to denote a index value + // Example: "id", "model+gold" + // or contains multiple tagged values which can be constructed + // into a key value + int monitorValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg); + + + // monitor off on a data inside a database + // data either contain a tagged value to denote a index value + // Example: "id", "model+gold" + // or contains multiple tagged values which can be constructed + // into a key value + int monitorOffValue (char* name, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // monitor a single attribute of a data inside a database + // any changes to this attribute will trigger a callback containing a whole data + // data either contain a tagged value to denote a index value + // Example: "id", "model+gold" + // or contains multiple tagged values which can be constructed + // into a key value + int monitorAttr (char* name, char* attrname, + rsvcData& data, rsvcCbkFunc func, void* arg); + + + // monitor a single attribute of a data inside a database + // any changes to this attribute will trigger a callback containing a whole data + // data either contain a tagged value to denote a index value + // Example: "id", "model+gold" + // or contains multiple tagged values which can be constructed + // into a key value + int monitorOffAttr (char* name, char* attrname, + rsvcData& data, rsvcCbkFunc func, void* arg); + + // query a particular database 'name' + // query msg can be like regular C logic expression for all + // attributes + int query (char* name, char* qmsg, + rsvcCbkFunc func, void* arg); + + // test purpose only + void shutdownServer (void); + + +protected: + + // non block tcp connect + static int connect_nonblock (int fd, struct sockaddr* addr, + size_t addrlen, + struct timeval* timeout); + + // cleanup all callbacks + void cleanupCallbacks (void); + + // call all disconnection callbacks + void callAllDiscCbks (void); + + // stream out a network data and return actual number of bytes + int streamData (rsvcNetData& data); + + // low level handle input and handle close + int handle_input (int fd); + int handle_close (int fd); + + // read and write for block socket + static int read_n (int fd, char* buffer, size_t len); + static int write_n (int fd, const char* buffer, size_t len); + + // real processing function + int processData (rsvcNetData& data); + + // real command callback + int commandCallback (int opcode, rsvcData& data, + rsvcCbkFunc func, void* arg); + + + // monitor command callback + int monitorCallback (int opcode, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // monitoroff command callback + int monitorOffCallback (int opcode, rsvcData& data, + rsvcCbkFunc func, void* arg); + + // handle callbacks from server + int cmdCbkFromServer (int status, rsvcData& data, rsvcCbk& cbk); + int monitorCbkFromServer (int status, rsvcData& data, rsvcCbk& cbk); + + // check a monitor callback is in the table + rsvcCbk* monitorCbkInTable (rsvcCbkFunc func, void* arg); + + +private: + // flag of connection + int connected_; + + // tcp socket to the server + int tcp_fd_; + + // server information + char* server_host_; + unsigned short server_port_; + + // lock for client object to prevent from this object being called + // recursivly + int lock_; + void lock (void); + void unlock (void); + + // request id + int reqid_; + // unique callback id + int cbkid_; + + + // disconnection callback list + rsvcSlist discCbkList_; + + // all send/get command callback list + rsvcSlist cmdCbkList_; + // all monitor callback list + rsvcHash monitorCbkTable_; + + // data convertion buffer + char* cbuffer_; + size_t cbuflen_; + + // friend class + friend class rsvcClientLocker; + friend class rsvcDBHandler; + + // deny copy and assignment operator + rsvcClient (const rsvcClient& client); + rsvcClient& operator = (const rsvcClient& client); + +}; + +class rsvcClientLocker +{ +public: + rsvcClientLocker (rsvcClient* client); + ~rsvcClientLocker (void); + +private: + rsvcClient* cl_; + + // deny copy and assignment operations + rsvcClientLocker (const rsvcClientLocker& locker); + rsvcClientLocker& operator = (const rsvcClientLocker& locker); +}; + +#endif diff --git a/extensions/cdevGenericServer/include/rsvcConfig.h b/extensions/cdevGenericServer/include/rsvcConfig.h new file mode 100644 index 0000000..f6e4592 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcConfig.h @@ -0,0 +1,62 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Configuration Header +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_CONFIG_H +#define _RSVC_CONFIG_H + +#define RSVC_SERVER_PORT 10932 +#define RSVC_MAX_KEY_LEN (unsigned int)256 +#define RSVC_KEY_NAME "key" +#define RSVC_TABLE_NAME "table" +#define RSVC_TABLE_NAME_EXT ".def" +#define RSVC_KEY_TYPE_NAME "keyType" +#define RSVC_KEY_EXP_NAME "keyExp" +#define RSVC_MONITOR_TAG "monitorOn" +#define RSVC_QUERY_TAG "query" +#define RSVC_CACHE_MAX 20 /* tuned for name server */ +#define RSVC_CACHE_LF 5 +#define RSVC_RLIMIT_NOFILE 256 +#define RSVC_UDP_BUFFER_SIZE 4096 + + +#define RSVC_OP_UNKNOWN (unsigned int)2000 + +#define RSVC_CREATE_TABLE (unsigned int)1000 +#define RSVC_CREATE_MEMTABLE (unsigned int)1001 +#define RSVC_OPEN_DBASE (unsigned int)1002 +#define RSVC_GET (unsigned int)1010 +#define RSVC_SET (unsigned int)1011 +#define RSVC_DEL (unsigned int)1012 +#define RSVC_INSERT (unsigned int)1013 +#define RSVC_OVERWRITE (unsigned int)1014 +#define RSVC_QUERY (unsigned int)1020 + +#define RSVC_MONITOR_ON (unsigned int)1500 +#define RSVC_MONITOR_ONATTR (unsigned int)1501 +#define RSVC_MONITOR_OFF (unsigned int)1600 +#define RSVC_MONITOR_OFFATTR (unsigned int)1601 + +#define RSVC_MONITOR_ENTRIES (unsigned int)1650 +#define RSVC_MONITOR_OFFENTRIES (unsigned int)1651 + +#define RSVC_SERVER_EXIT (unsigned int)1700 + +#define RSVC_DATA_IN_MEMORY 1 +#define RSVC_DATA_ON_DISK 2 + +#include + +#endif diff --git a/extensions/cdevGenericServer/include/rsvcDBT.h b/extensions/cdevGenericServer/include/rsvcDBT.h new file mode 100644 index 0000000..bbb162a --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcDBT.h @@ -0,0 +1,46 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// C++ wrapper class for DBT class with user allocated memory +// +// Reason: Enable automatic memory release +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_DBT_H +#define _RSVC_DBT_H + +#include +#include +#include +#include + +class rsvcDBT +{ +public: + rsvcDBT (void); + ~rsvcDBT (void); + + void* data (void) const; + void data (void *ptr, int dealloc = 1); + size_t size (void) const; + void size (size_t len); + void datacpy (void* data); + + // return data pointer to internal DBT + DBT* dbt (void); + +private: + DBT data_; + int dealloc_; +}; +#endif diff --git a/extensions/cdevGenericServer/include/rsvcData.h b/extensions/cdevGenericServer/include/rsvcData.h new file mode 100644 index 0000000..a708ddd --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcData.h @@ -0,0 +1,316 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: rsvcData.h +// Self descibing data structure to manage the storage and transport +// of data between local rsvc functions, as well as remote client and +// server applications. +// +// Author: Walt Akers and Danjin Wu +// +// +// +//-------------------------------------------------------------------------- + +#ifndef _RSVC_DATA_H +#define _RSVC_DATA_H + +#ifdef _WIN32 +#include +#include +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef hpux +char * ltoa (long val); +char * ultoa (unsigned long val); +#endif + +#ifndef _WIN32 + extern "C" char *ctime (__const time_t *__timer) __THROW; +#endif + + +class RSVC_CLASS_SPEC rsvcData +{ +friend class rsvcDataIterator; +protected: + rsvcDataEntry *entries; + + // ********************************************************************* + // * copy: + // * This function copies the contents of the rsvcData object + // * specified by data into this rsvcData object. It is used by + // * both the copy constructor and by the assignment operator. + // ********************************************************************* + rsvcData & copy (const rsvcData & data); + +public: + + // ********************************************************************* + // * Convert data from a floating point value to a string. + // ********************************************************************* + static char * rsvc_gcvt(float value, size_t ndigit, char *buf); + static char * rsvc_gcvt(double value, size_t ndigit, char * buf); + + // ********************************************************************* + // * lookupTag: + // * This function is for internal use and allows a cdevData object + // * to locate and optionally create a tagged data item. + // ********************************************************************* + rsvcDataEntry * lookupTag(char * ctag, int create = 0); + + // ********************************************************************* + // * setupTag: + // * This function is for internal use and is used to prepare a new + // * rsvcDataEntry object prior to inserting data into it. + // ********************************************************************* + rsvcDataEntry * setupTag (char* tag, rsvcDataTypes type, size_t elemSize, + size_t numElems, size_t numDims ); + + // ********************************************************************* + // * insert: + // * The following functions insert a data entry into this datan + // ********************************************************************* + int insert (rsvcDataEntry* entry); + + + + // ********************************************************************* + // * rsvcData: + // * This is the default constructor, it simply initializes + // * variables within the rsvcData object. + // ********************************************************************* + rsvcData ( void ); + + // ********************************************************************* + // * rsvcData: + // * Copy constructor. This constructor duplicates the rsvcData + // * object that it has been passed as a parameter. + // ********************************************************************* + rsvcData ( const rsvcData & data ); + + // ********************************************************************* + // * ~rsvcData: + // * This is the default destructor for the rsvcData object. It + // * frees any memory allocated for storage and deletes the object. + // ********************************************************************* + ~rsvcData( void ); + + // ********************************************************************* + // * Assignment operator: + // * This function copies the contents of a rsvcData object to this + // * object. + // ********************************************************************* + rsvcData & operator = (const rsvcData & data); + + // ********************************************************************* + // * Append operation: + // * This operation will append a rsvcData onto an existing rsvcData + // * and return this object. If there is confilicts among tags, the + // * appended one wins + // ********************************************************************* + rsvcData& operator += (const rsvcData& data); + + // ********************************************************************* + // * asciiDump: + // * Performs a diagnostic dump of the entire contents of the + // * rsvcData object to the specified file pointer. + // ********************************************************************* +#ifdef _WIN32 + inline void asciiDump (FILE* fp = stdout) { + int fd = _fileno (fp); + long osfHandle = _get_osfhandle (fd); + asciiDump (osfHandle); + _lseek(fd, 0L, SEEK_END); + } + void asciiDump (long osfHandle); +#else + void asciiDump ( FILE * fp = stdout ); +#endif + + // ********************************************************************* + // * Stream Utilities + // * These functions provide the mechanisms for converting a rsvcData + // * object into a network portable bninary stream, and then + // * reconstructing them after transport. + // ********************************************************************* + +#define _RSVC_MAGIC_NUM 0x2c45da2a + + virtual int streamSize (size_t * bufLen, size_t * elementCount); + virtual int streamOut ( char ** buf, size_t * bufLen ); + virtual int streamOut ( char * buf, size_t bufLen, size_t count); + virtual int streamIn ( char * buf, size_t bufLen); + + // ********************************************************************* + // * remove: + // * Removes rsvcDataEntry objects from the rsvcData object by tag + // * integer or by tag string. If no tag is specified, then all + // * rsvcDataEntry objects will be removed. + // ********************************************************************* + void remove( void ); + void remove( char * ctag ); + + // ********************************************************************* + // * changeTag: + // * Replace a new tag with the old one within the + // * rsvcData object. If the old one can not be not found, + // * RSVC_NOTFOUND is returned. If the new tag has already + // * been found in that rsvcData object, RSVC_ERROR is returned. + // ********************************************************************* + int changeTag(char *c_oldTag, char *c_newTag); + + + // ********************************************************************* + // * dupWithTag: + // * copy data with tag 'old_tag' to tag 'new_tag'. + // * rsvcData object. If the old one can not be not found, + // * RSVC_NOTFOUND is returned. If the new tag has already + // * been found in that rsvcData object, RSVC_ERROR is returned. + // ********************************************************************* + int dupWithTag (char* old_tag, char* new_tag); + + // ********************************************************************* + // * getType: + // * Retrieves the rsvcDataTypes of the referenced tagged data item. + // * If no item with that tag is within the rsvcData object, then + // * RSVC_INVALID is returned. + // ********************************************************************* + rsvcDataTypes getType(char *ctag); + + + // ********************************************************************* + // * getDim: + // * Obtains the number of dimensions in the specified tagged data + // * item. Returns RSVC_SUCCESS if the tagged item exists, otherwise, + // * RSVC_NOTFOUND is returned. + // ********************************************************************** + int getDim(char *ctag, size_t *dim); + + // ********************************************************************* + // * getElems: + // * Obtains the number of elements in the specified tagged data + // * item. Returns RSVC_SUCCESS if the tagged item exists, otherwise, + // * RSVC_NOTFOUND is returned. + // ********************************************************************** + int getElems(char *ctag, size_t *elems); + + // ********************************************************************* + // * insert: + // * The following functions allow the insertion of scalar data into + // * a rsvcData object. + // ********************************************************************* + int insert ( char * ctag, BYTE data); + int insert ( char * ctag, short data); + int insert ( char * ctag, unsigned short data); + int insert ( char * ctag, int data); + int insert ( char * ctag, unsigned int data); + int insert ( char * ctag, long data); + int insert ( char * ctag, unsigned long data); + int insert ( char * ctag, float data); + int insert ( char * ctag, double data); + int insert ( char * ctag, rsvc_TS_STAMP data); + + // ******************************************************************** + // * insert: + // * The following functions allow the insertion of arrays of data + // * into a rsvcData object. The len variable contains the total + // * number of elements to be inserted, the ndim variable indicates + // * the number of dimensions in the array. + // ******************************************************************** + int insert (char * ctag, BYTE * data, size_t len, size_t ndim = 1); + int insert (char * ctag, short * data, size_t len, size_t ndim = 1); + int insert (char * ctag, unsigned short * data, size_t len, size_t ndim = 1); + int insert (char * ctag, int * data, size_t len, size_t ndim = 1); + int insert (char * ctag, unsigned int * data, size_t len, size_t ndim = 1); + int insert (char * ctag, long * data, size_t len, size_t ndim = 1); + int insert (char * ctag, unsigned long * data, size_t len, size_t ndim = 1); + int insert (char * ctag, float * data, size_t len, size_t ndim = 1); + int insert (char * ctag, double * data, size_t len, size_t ndim = 1); + int insert (char * ctag, rsvc_TS_STAMP *data, size_t len, size_t ndim =1 ); + + // ********************************************************************* + // * insert: + // * The following functions insert character strings and arrays of + // * character strings. Their treatment is different from the scalar + // * data types. + // ********************************************************************* + int insert ( char * ctag, char * data); + int insert ( char * ctag, char ** data, size_t len = 0, size_t ndim = 1); + + // ********************************************************************* + // * get: + // * This group of functions allows the user to extract scalar and + // * array data from the rsvcData object. + // ********************************************************************* + int get(char * ctag, BYTE * data); + int get(char * ctag, short * data); + int get(char * ctag, unsigned short * data); + int get(char * ctag, int * data); + int get(char * ctag, unsigned int * data); + int get(char * ctag, long * data); + int get(char * ctag, unsigned long * data); + int get(char * ctag, float * data); + int get(char * ctag, double * data); + int get(char * ctag, char * data, size_t len); + int get(char * ctag, char ** data); + int get(char * ctag, rsvc_TS_STAMP * data); + + // ********************************************************************* + // * find: + // * These functions allow the user to obtain a pointer to data + // * within the actual data variables within the rsvcData object. + // ********************************************************************* + int find(char * ctag, void* &data); + + // ********************************************************************* + // * replace: + // * This function allows part or all taged values being replaced + // * by other taged values represented by a rsvcData + // ********************************************************************* + int replace (const rsvcData& rep); + + // ********************************************************************* + // * operator ==, operator !=: + // * These methods provides a fast way for the caller to identify if two + // * rsvcData objects contain the identical fields and values... + // ********************************************************************* + int operator == (rsvcData & data); + int operator != (rsvcData & data) { return !(operator == (data)); } +}; + + + +class rsvcDataIterator +{ +public: + rsvcDataIterator (rsvcData* data); + ~rsvcDataIterator (void) {}; + int init (void); + int operator ! (void); + int operator ++(void); + const char* tag (void); + rsvcDataEntry* operator () (void); + +protected: + rsvcData *dataobj_; + rsvcDataEntry *cur_; +}; + +#endif diff --git a/extensions/cdevGenericServer/include/rsvcDataEntry.h b/extensions/cdevGenericServer/include/rsvcDataEntry.h new file mode 100644 index 0000000..12572bb --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcDataEntry.h @@ -0,0 +1,335 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//------------------------------------------------------------------------------ +// +// description: rsvcDataEntry.h +// This file defines the classes necessary for storage of an individual +// tagged data item within a rsvcData class object. +// +// Author: Walt Akers & Jie Chen +// +// +// +//------------------------------------------------------------------------------ + +#ifndef _RSVC_DATA_ENTRY_H_ +#define _RSVC_DATA_ENTRY_H_ + +#include +#include + +// ############################################################################# +// # rsvcDataEntryStorage: +// # This class contains the data elements and methods necessary to store data +// # associated with one tagged data item. +// # +// # Note: Because the rsvcData object must actively manipulate the data in +// # this structure - it has been made public to increase access speed +// # and to allow the subclassing of the rsvcData object. +// ############################################################################# +class rsvcDataEntryStorage +{ +public: + // ************************************************************* + // * tag_: + // * This is char string value that is used to uniquely identify + // * a data element within a rsvcData object. + // ************************************************************* + char tag_[RSVC_TAG_MAX_LEN]; + + // ************************************************************* + // * dataType_: + // * This is the data type of the tagged data item that is to be + // * stored in this rsvcDataEntryStorage object. + // ************************************************************* + rsvcDataTypes dataType_; + + // ************************************************************* + // * size_: + // * This variable is the allocated size of the buffer_ which is + // * used to store both the array data and its associated bounds + // * information. + // ************************************************************* + size_t size_; + + // ************************************************************* + // * dim_: + // * This variable indicates the user specified number of + // * dimensions that the array represents. + // * either 0 or 1 + // ************************************************************* + size_t dim_; + + // ************************************************************* + // * elems_: + // * This variable contains the maximum number of elements that + // * the array may contain. + // ************************************************************* + size_t elems_; + + // ************************************************************* + // * bytes_: + // * This variable contains the number of bytes per element. + // ************************************************************* + size_t bytes_; + + // ************************************************************* + // * buffer_: + // * This is the buffer that is allocated to store data and + // * bounds information. + // ************************************************************* + unsigned char * buffer_; + + // ************************************************************* + // * data_: + // * This is a union that is used to store scalar data and a + // * pointer to the array data this is stored within this object + // ************************************************************* + union dataUnion { + BYTE cval; + short sval; + unsigned short usval; + long lval; + unsigned long ulval; + float fval; + double dval; + void * vptr; + BYTE * cptr; + short * sptr; + unsigned short * usptr; + long * lptr; + unsigned long * ulptr; + float * fptr; + double * dptr; + char * str; + char ** strarr; + rsvc_TS_STAMP ts; + rsvc_TS_STAMP * tsptr; + } data_; + + // ************************************************************* + // * rsvcDataEntryStorage: + // * Default constructor for the rsvcDataEntryStorage class. It sets + // * the buffer_ pointer to NULL to prevent deletion of non- + // * allocated memory, and then calls the clear method to + // * initialize all data variables. + // ************************************************************* + rsvcDataEntryStorage ( void ) : buffer_(0) { + clear(); + } + + // ************************************************************* + // * ~rsvcDataEntryStorage: + // * Default destructor for the rsvcDaaEntry class. It calls + // * the clear method to release and reinitialize all data + // * elements. + // ************************************************************* + ~rsvcDataEntryStorage ( void ) { + clear(); + } + + // ************************************************************* + // * clear: + // * Releases and reinitializes all data variables. + // ************************************************************* + void clear ( void ) { + deallocate(); + tag_[0] = 0; + dataType_ = RSVC_INVALID; + } + + // ************************************************************* + // * allocate: + // * Allocates a block of memory sufficient to store a caller + // * specified number of bytes. If sufficient space has already + // * been allocated, then it will be used, otherwise, a new + // * block will be created to service the request. + // ************************************************************* + void allocate ( size_t dimensions, size_t elems, size_t bytesPerElem ) + { + size_t newBlockSize = (elems * bytesPerElem); + + if(buffer_==NULL || newBlockSize>size_) + { + deallocate(); + buffer_ = ::new unsigned char[newBlockSize]; + size_ = newBlockSize; + } + dim_ = dimensions; + elems_ = elems; + bytes_ = bytesPerElem; + data_.vptr = &buffer_[0]; + memset (buffer_, 0, newBlockSize); + } + + // ************************************************************* + // * deallocate: + // * Deallocates any memory previously allocated to the buffer + // * and reinitializes the size_, dim_, bytes_ and buffer_ + // * variables. Any references to the previously allocated + // * block is cleared. + // ************************************************************* + void deallocate ( void ) + { + if(buffer_ != 0) { + delete []buffer_; + buffer_ = 0; + } + size_ = 0; + dim_ = 0; + elems_ = 0; + bytes_ = 0; + data_.dval = 0.00; + } + + + // ************************************************************* + // * operator ==: + // * This operator allows you to directly and rapidly + // * compare two rsvcDataEntryStorage objects... + // ************************************************************* + int operator == (rsvcDataEntryStorage & entry); + + // ************************************************************* + // * operator !=: + // * This operator allows the caller to directly and rapidly + // * comapre two rsvcDataEntryStorage objects. + // ************************************************************* + int operator != (rsvcDataEntryStorage & entry) { + return !(operator == (entry)); + } + +}; + + +// ############################################################################# +// # rsvcDataEntry: +// # This class is used to define the node attributes necessary to support +// # linked lists of rsvcDataEntryStorage objects. It also provides an internal +// # freelist of rsvcDataEntry objects. +// # +// # Note: Because the rsvcData object must actively manipulate the data in +// # this structure - it has been made public to increase access speed +// # and to allow the subclassing of the rsvcData object. +// ############################################################################# +class rsvcDataEntry : public rsvcDataEntryStorage +{ +public: + // ************************************************************* + // * freeList_: + // * This is a pointer to a list of currently allocated + // * rsvcDataEntrys that will be provided to the user + // * upon request. This technique should reduce the number of + // * mallocs called to allocated rsvcDataEntrys. + // ************************************************************* + static rsvcDataEntry * freeList_; + + // ************************************************************* + // * ALLOCATION_COUNT: + // * This is the minimum number of rsvcDataEntrys that will + // * be allocated when the freeList_ becomes empty. + // ************************************************************* + enum { ALLOCATION_COUNT = 16 }; + + // ************************************************************* + // * next_ : + // * This is the pointer to the next element in the list of + // * rsvcDataEntry objects. + // ************************************************************* + rsvcDataEntry * next_; + + // ************************************************************* + // * rsvcDataEntry: + // * Constructor for the class. It serves only to set the next_ + // * pointer to NULL. + // ************************************************************* + rsvcDataEntry ( void ) : next_(NULL), rsvcDataEntryStorage() + { + } + + // ************************************************************* + // * ~rsvcDataEntry: + // * Destructor for the class. It is a placeholder that + // * does nothing when called. + // ************************************************************* + ~rsvcDataEntry ( void ) { } + + // ************************************************************* + // * next: + // * Retrieves a pointer to the next_ rsvcDataEntry object. + // * Incorporation of this function into a list object is the + // * responsibility of the caller. + // ************************************************************* + rsvcDataEntry * &next ( void ) + { + return next_; + } + + // ************************************************************* + // * new: + // * Allocation function for the object. It will get the next + // * preallocated rsvcDataEntry object from the freeList_, + // * or, if none are available, refill the freeList_ and then + // * return a new rsvcDataEntry object. + // ************************************************************* + void * operator new ( size_t size ); + + // ************************************************************* + // * delete: + // * Rather than deallocating the rsvcDataEntry object, this + // * function returns it to the freeList_ where it may be + // * retrieved by a later call of new. + // ************************************************************* + void operator delete ( void * ptr ) + { + rsvcDataEntry * node = (rsvcDataEntry *)ptr; + if(node != NULL) { + node->next_ = freeList_; + freeList_ = node; + } + } + + // ************************************************************* + // * Copy operation + // * Copy an existing data entry to a new data entry + // * this may allow new data entry to be inserted into data object + // * quickly + // ************************************************************* + rsvcDataEntry (const rsvcDataEntry& entry); + + // ************************************************************* + // * Assignment operation + // * Copy an existing data entry to a data entry + // ************************************************************* + rsvcDataEntry& operator = (const rsvcDataEntry& entry); + + // ************************************************************* + // * operator ==: + // * This operator allows you to directly and rapidly + // * compare two rsvcDataEntry objects... + // ************************************************************* + int operator == (rsvcDataEntry & entry) + { + rsvcDataEntryStorage *storage = &entry; + + return rsvcDataEntryStorage::operator == (*storage); + } + + // ************************************************************* + // * operator !=: + // * This operator allows the caller to directly and rapidly + // * comapre two rsvcDataEntry objects. + // ************************************************************* + int operator != (rsvcDataEntry & entry) + { + rsvcDataEntryStorage *storage = &entry; + return !(rsvcDataEntryStorage::operator == (*storage)); + } + +}; + +#endif /* __RSVC_DATA_ENTRY_H_ */ diff --git a/extensions/cdevGenericServer/include/rsvcDataStore.h b/extensions/cdevGenericServer/include/rsvcDataStore.h new file mode 100644 index 0000000..026ad9e --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcDataStore.h @@ -0,0 +1,174 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server All Data Storage Class (Abstract Class) +// +// This class behaves like a wrapper class that direct +// all actions to right components contained inside this class +// +// All member functions have 3 arguments. The first is the network +// incoming data, the second is the result of the action in the +// form of array of network data, and the 3rd argument is size +// of the array. Callers must free memory for the elements +// in the array +// +// Author: Jie Chen +// +// +// +// +#ifndef _RSVC_DATA_STORE_H +#define _RSVC_DATA_STORE_H + +#include +#include +#include + +#ifndef _WIN32 +#include +#include +#endif + +#include +#include +#include +#include +#include + + +class rsvcVirtualDbase; + +class rsvcDataStore : public rsvcHashable +{ +public: + // destrcutor + virtual ~rsvcDataStore (void); + + // operations + + // create table definition + virtual int createDatabase (rsvcNetData& data, + rsvcNetData* outdata[], size_t* num); + + virtual int openDatabase (rsvcNetData& data, + rsvcNetData* outdata[], size_t* num); + + // retrieve table definition and store inside data + virtual int getTableDef (rsvcNetData& data, + rsvcNetData* outdata[], size_t* num); + + // get data value + // specified by a key + virtual int getValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + // insert a rsvcData which must have a key inside + virtual int putValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num, + int overwite = 0) = 0; + // delete a data object pointed by key value + virtual int delValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + // flush all internal buffer to disk + virtual int flush (void) = 0; + + // set data value + // specified either by a key + virtual int setValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + + // monitor on incoming database entries + virtual int monitorIncomingEntries (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + + // monitor off the above incoming database entries + virtual int monitorOffIncomingEntries (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + // monitor on data values + // monitor on the whole data + virtual int monitorValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + + // monitor on attribute of a data + virtual int monitorAttr (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + + // monitor off data values + virtual int monitorOffValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + + // monitor off attribute of a data + virtual int monitorOffAttr (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + + // monitor off value for a single io channel + virtual int monitorOff (void* io) = 0; + + // query the data store + virtual int query (rsvcNetData& data, char* msg, + rsvcNetData* outdata[], size_t* num) = 0; + + // get every entry in the store + virtual int getAll (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num) = 0; + + // inherited operation from hashable + unsigned int hash (void); + + // return name of this data store + char* name (void) const; + + // open and close data store operation + virtual int openDatabase (void); + virtual int closeDatabase (void); + + // handle client close + virtual void handleClose (void * /* client */) {} + + // from existing table definition and files + // to create a right dataStore object + static rsvcDataStore* createDataStore (char* name); + +protected: + // constructor + // construct data store with a unique name + rsvcDataStore (char* name); + + // remove all monitors on incoming data + void removeAllMonitors (void); + + + // update this data store time stamp which is the time when last + // action was done on the store. + void updateTimeStamp (void); + + // notify interested parties about an incoming entry + int notifyAnEntryToChannels (rsvcData& entry); + + // data area + char* name_; + + // time stamp of this data store + double timestamp_; + + // table definition + rsvcTableDef tableDef_; + + // data cache handler + rsvcHash cache_; + + // insert/deleted data monitor + rsvcHSlist idataMonitorList_; + rsvcHSlist odataMonitorList_; + + // database handler + rsvcVirtualDbase* database_; +}; +#endif + diff --git a/extensions/cdevGenericServer/include/rsvcDataStoreMem.h b/extensions/cdevGenericServer/include/rsvcDataStoreMem.h new file mode 100644 index 0000000..11c7b57 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcDataStoreMem.h @@ -0,0 +1,105 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server In Memory Data Store +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_DATASTORE_MEM_H +#define _RSVC_DATASTORE_MEM_H + +#include +#include +#include +#include +#include + +class rsvcCacheData; + +class rsvcDataStoreMem: public rsvcDataStore +{ +public: + // constructor and destructor + rsvcDataStoreMem (char* name); + ~rsvcDataStoreMem (void); + + // inherited operations + // get data values + // specified by a key + virtual int getValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + // insert a rsvcData which may have a key inside or not + virtual int putValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num, + int overwrite = 0); + + // delete a data object pointed by key value + virtual int delValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + // flush all internal buffer to disk + virtual int flush (void); + + // set data value + // specified either by a key or a whole data + virtual int setValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + // monitor on incoming database entries + virtual int monitorIncomingEntries (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + // monitor off the above incoming database entries + virtual int monitorOffIncomingEntries (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + // monitor on data values + // monitor on either the whole data + virtual int monitorValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + // monitor on attribute of a data + virtual int monitorAttr (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + // monitor off data value + virtual int monitorOffValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + // monitor off attribute of a data + virtual int monitorOffAttr (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + + // monitor off data value for all monitors from same socket id + virtual int monitorOff (void* io); + + // query the data store + virtual int query (rsvcNetData& data, char* msg, + rsvcNetData* outdata[], size_t* num); + + // get every entry in the store + virtual int getAll (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + +protected: + + // find cached data item inside cache from a key data + rsvcCacheData* cachedData (rsvcData& keydata); + + // delete a cached data item inside cache from a key dta + int deleteCachedData (rsvcData& key); +}; +#endif + + diff --git a/extensions/cdevGenericServer/include/rsvcDataStoreTable.h b/extensions/cdevGenericServer/include/rsvcDataStoreTable.h new file mode 100644 index 0000000..7afd63b --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcDataStoreTable.h @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server All Data Store Table +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_DATA_STORE_TABLE_H +#define _RSVC_DATA_STORE_TABLE_H + +#include +#include +#include +#include +#include + +class rsvcDataStoreTable +{ +public: + // constructor + rsvcDataStoreTable (unsigned int max = 100, unsigned int lf = 5); + + // destructor + ~rsvcDataStoreTable (void); + + // add a data store + int add (rsvcDataStore* store); + + // find a data store + rsvcDataStore* find (char* name); + + // open a datastore with name + int openDatabase (char* name); + + // monitor off all values for a client + void monitorOff (void* io); + + // handle close for a client + void handleClose (void* io); + +private: + + // data area + rsvcHash table_; + + // deny access to copy and assignment operations + rsvcDataStoreTable (const rsvcDataStoreTable& table); + rsvcDataStoreTable operator = (const rsvcDataStoreTable& table); +}; +#endif diff --git a/extensions/cdevGenericServer/include/rsvcDataStreamer.h b/extensions/cdevGenericServer/include/rsvcDataStreamer.h new file mode 100644 index 0000000..d819611 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcDataStreamer.h @@ -0,0 +1,183 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// rsvc data streamer class +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_DATA_STREAMER +#define _RSVC_DATA_STREAMER + +#include +#include +#include +#include +#ifdef _WIN32 + #include +#else + #include + #include +#endif + +#include + +#define _RSVC_STREAM_BYTE_UNIT (sizeof (long)) + +inline int _RSVC_RNDUP (size_t x) +{ + return ((x + _RSVC_STREAM_BYTE_UNIT - 1) / _RSVC_STREAM_BYTE_UNIT) + * _RSVC_STREAM_BYTE_UNIT; +} + +inline size_t rsvcStreamSize (char c) +{ + return _RSVC_RNDUP (sizeof (c)); +} + +inline size_t rsvcStreamSize (unsigned char c) +{ + return _RSVC_RNDUP (sizeof (c)); +} + +inline size_t rsvcStreamSize (short c) +{ + return _RSVC_RNDUP (sizeof (c)); +} + +inline size_t rsvcStreamSize (unsigned short c) +{ + return _RSVC_RNDUP (sizeof (c)); +} + +inline size_t rsvcStreamSize (int c) +{ + return _RSVC_RNDUP (sizeof (c)); +} + +inline size_t rsvcStreamSize (unsigned int c) +{ + return _RSVC_RNDUP (sizeof (c)); +} + +inline size_t rsvcStreamSize (long c) +{ + return sizeof (c); +} + +inline size_t rsvcStreamSize (unsigned long c) +{ + return sizeof (c); +} + +inline size_t rsvcStreamSize (float c) +{ + return sizeof (c); +} + +inline size_t rsvcStreamSize (double c) +{ + return sizeof (c); +} + +inline size_t rsvcStreamSize (char* str) +{ + return sizeof (long) + _RSVC_RNDUP (strlen (str) + 1); +} + +inline size_t rsvcStreamSize (void*, size_t size) +{ + return sizeof (long) + _RSVC_RNDUP (size); +} + +inline size_t rsvcStreamSize (rsvc_TS_STAMP& ts) +{ + return sizeof (ts); +} + +class rsvcDataStreamer +{ +public: + // destructor + virtual ~rsvcDataStreamer (void); + + char* buffer (void) const; + size_t bufferLength (void) const; + + int streamStatus (void) const; + +protected: + // constructor + // attach to a stream buffer. + // dealloc == 1 free buffer in the detrcutor. + rsvcDataStreamer (char* buffer, size_t buflen, int dealloc = 1); + + // binray stream buffer + char* buffer_; + size_t buflen_; + + // free memory stratege + int dealloc_; + + // index pointing to current position + int pos_; + + // streaming status + int err_; +}; + +class rsvcDataStreamWriter : public rsvcDataStreamer +{ +public: + // constructor and destrcutor + rsvcDataStreamWriter (char* buffer, size_t buflen, int dealloc = 1); + ~rsvcDataStreamWriter (void); + + // operations + int write (char c); + int write (unsigned char c); + int write (short c); + int write (unsigned short c); + int write (int c); + int write (unsigned int c); + int write (long c); + int write (unsigned long c); + int write (float c); + int write (double c); + int write (char* str); + int write (void* data, size_t size); + int write (rsvc_TS_STAMP& ts); +}; + +class rsvcDataStreamReader : public rsvcDataStreamer +{ +public: + // constructor and destrcutor + rsvcDataStreamReader (char* buffer, size_t buflen, int dealloc = 1); + ~rsvcDataStreamReader (void); + + // operations + int read (char& c); + int read (unsigned char& c); + int read (short& c); + int read (unsigned short& c); + int read (int& c); + int read (unsigned int& c); + int read (long& c); + int read (unsigned long& c); + int read (float& c); + int read (double& c); + int read (char* &str); + int read (void* data, size_t size); + int read (rsvc_TS_STAMP& ts); +}; + +#endif diff --git a/extensions/cdevGenericServer/include/rsvcDataTypes.h b/extensions/cdevGenericServer/include/rsvcDataTypes.h new file mode 100644 index 0000000..088bb08 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcDataTypes.h @@ -0,0 +1,43 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: Data Type Definition +// +// Author: Jie Chen +// +// +// +//-------------------------------------------------------------------------- + +#ifndef _RSVC_TYPES_H +#define _RSVC_TYPES_H + +typedef unsigned char BYTE; + +enum rsvcDataTypes + { + RSVC_BYTE, + RSVC_INT16, + RSVC_UINT16, + RSVC_INT32, + RSVC_UINT32, + RSVC_FLOAT, + RSVC_DOUBLE, + RSVC_STRING, + RSVC_TIMESTAMP, + RSVC_INVALID + }; + +// rsvc time struct +typedef struct { + unsigned long secPastEpoch; // seconds since Jan. 1, 1970 + unsigned long nsec; // nanoseconds within second +} rsvc_TS_STAMP; + +#define RSVC_TAG_MAX_LEN 16 +#endif diff --git a/extensions/cdevGenericServer/include/rsvcDatabase.h b/extensions/cdevGenericServer/include/rsvcDatabase.h new file mode 100644 index 0000000..6878891 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcDatabase.h @@ -0,0 +1,205 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC database interface to db library (Thread Safe) +// +// Author: Jie Chen +// +// +// +// +#ifndef _RSVC_DATABASE_H +#define _RSVC_DATABASE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined (_RSVC_USE_THREAD) && defined (_REENTRANT) +#include +#endif + +// comparision function definition +typedef int (*rsvcCompFunc) (const DBT* key1, const DBT* key2); + +// this class will handle interface to btree based database implementation. +// data/key are rsvcData/undefined. When caller insert a rsvc, the +// rsvcData must have a key in this data with tag name 'key'. +// when caller tries to get rsvcData, caller has to specify the key +// which is in a rsvcData with tag name 'key' + +// This interface will not provide two iterators at the same time. +// This is the limitation by low level database library + +// All pointers to key must be the memory location provided by callers + +class rsvcDatabaseLocker; + +class rsvcDatabase : public rsvcVirtualDbase +{ +public: + // constructor + // default constructor, users have to call open explicitly + rsvcDatabase (void); + + // constructor: name is a file name, flags are the same flags as + // standard open routine. + // data_size is estimate of each data stored in the database + rsvcDatabase (char* name, int flags, int keyType = RSVC_STRING, + size_t data_size = 496, + size_t cache_size = 0, size_t page_size = 0, + int mode = 0666); + // destructor + ~rsvcDatabase (void); + + // operation + + // open a database + int open (char* name, int flags, int keyType = RSVC_STRING, + size_t cache_size = 0, + int mode = 0666); + // create a database + int create (char* name, int flags, int keyType = RSVC_STRING, + size_t data_size = 496, + size_t cache_size = 0, size_t page_size = 0, + int mode = 0666); + + // close connection to the database + int close (void); + + // get a rsvcData. + int get (rsvcData& data, rsvcData& key); + // insert a rsvcData which must have a key inside + int put (rsvcData& data, rsvcData& key); + // delete a data object pointed by key value + int del (rsvcData& key); + // flush all internal buffer to disk + int flush (void); + + // return database name + char* database (void) const; + // return file descriptor for the opened database + int fd (void); + // check to see the database is open or not + int opened (void) const; + + // iterator for sequential access to database + int cursorInit (void); + + // set cursor to the position pointed by key 'key', + // and return data 'data' if successful + int cursorSet (rsvcData& data, rsvcData& key); + + // move cursor to the next position. + // return CDEV_SUCCESS on success, CDEV_ERROR: check errno + // return CDEV_INVALIDOBJ: no more + int cursorNext (rsvcData& data, rsvcData& key); + + // move cursor to the previous position + // return CDEV_SUCCESS on success, CDEV_ERROR: check errno + // return CDEV_INVALIDOBJ: no more + int cursorPrev (rsvcData& data, rsvcData& key); + + // merge current value pointed by cursor: + // this routine can only used to update the data with the same + // or smaller size than the exisiting data + // If you like to update arbitrary size of data, use del and put + int cursorUpdate (rsvcData& data); + + // move cursor to the beginning of the database + // no need to provide key + int cursorFirst (rsvcData& data, rsvcData& key); + + // move cursor to the end of the database + // no need to provide key + int cursorLast (rsvcData& data, rsvcData& key); + + // close cursor operation + int cursorFinish (void); + + const char* className (void) const {return "rsvcDatabase";} + +protected: + // convert a DBT to rsvcData (database --> back to memory) + static int convertData (rsvcData& data, const DBT* res); + // convert rsvcData to rsvcDBT (memory --> to database ) + static int convertData (rsvcDBT* out, rsvcData& data); + + // convert rsvcData to DBT and a key (memory --> to database) + static int convertData (rsvcDBT* out, rsvcDBT* key, + rsvcData & data, rsvcData& tkey, int keyType); + // find key size + static size_t keySize (rsvcData& key, void* tkey, int keyType); + + // convert key from regular rsvcData to DBT format + // using convertion buffer keybuf + // used when convert memory -->to database + static int convertKey (rsvcDBT* key, rsvcData& tkey, int keyType, + char* keybuf); + + // copy key data from database back to memory + static int copyKeyData (rsvcData& key, DBT* data, int keyType); + +private: +#if defined (_RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex mutex_; +#endif + + // database access option: different site can change option + DB_INFO b_; + // internal DB pointer + DB* dbp_; + + // Database cursor pointer + DBC* dbc_; + + // keep track of size of data that have been written to a database + int wsize_; + + // static buffer for key + char keybuf_[RSVC_MAX_KEY_LEN]; + + // Function pointers to all comparision functions + static rsvcCompFunc compFuncs_[]; + + // deny access to copy and assignment operator + rsvcDatabase (const rsvcDatabase& dbase); + rsvcDatabase& operator = (const rsvcDatabase& dbase); + + // friend class + friend class rsvcDatabaseLocker; +}; + +class rsvcDatabaseLocker +{ +public: + // constructor and destructor + rsvcDatabaseLocker (rsvcDatabase* dbase); + ~rsvcDatabaseLocker (void); + +private: + rsvcDatabase* dbase_; + // deny access to assignment and copy operations + rsvcDatabaseLocker (const rsvcDatabaseLocker& ); + rsvcDatabaseLocker& operator = (const rsvcDatabaseLocker& ); +}; + +#endif + + + diff --git a/extensions/cdevGenericServer/include/rsvcDatabaseEnv.h b/extensions/cdevGenericServer/include/rsvcDatabaseEnv.h new file mode 100644 index 0000000..1d082ef --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcDatabaseEnv.h @@ -0,0 +1,49 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Database Environment Class +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_DATABASE_ENV_H +#define _RSVC_DATABASE_ENV_H + +#include +#include +#include +#include + +class rsvcDatabaseEnv +{ +public: + // destructor + ~rsvcDatabaseEnv (void); + + // static access to pointer of this object + static rsvcDatabaseEnv* dbaseEnv (void); + + DB_ENV* dbenv (void) const; + + // close all database actions, This is last one to call + static void close (void); + +protected: + // constructor + rsvcDatabaseEnv (void); + +private: + // single database environment + static rsvcDatabaseEnv* env_; + // real database stuff + DB_ENV* dbenv_; +}; +#endif diff --git a/extensions/cdevGenericServer/include/rsvcErr.h b/extensions/cdevGenericServer/include/rsvcErr.h new file mode 100644 index 0000000..7f7e1b3 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcErr.h @@ -0,0 +1,78 @@ +/* +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC error codes +// +// Author: Jie Chen +// +// +// +*/ +#ifndef _RSVC_ERROR_CODE_H +#define _RSVC_ERROR_CODE_H + +/* Error and status values */ +#define RSVC_WARNING -2 /* Failure of function is non-consequential */ +#define RSVC_ERROR -1 /* Errors that are not in any categories */ +#define RSVC_SUCCESS 0 /* RSVC success */ +#define RSVC_INVALIDOBJ 1 /* invalid RSVC objects */ +#define RSVC_INVALIDARG 2 /* invalid argument passed to RSVC calls */ +#define RSVC_INVALIDSVC 3 /* wrong service during dynamic loading */ +#define RSVC_INVALIDOP 4 /* operation is unsupported (collection) */ + +#define RSVC_NOTCONNECTED 5 /* not connected to low network service */ +#define RSVC_IOFAILED 6 /* low level network service IO failed */ +#define RSVC_CONFLICT 7 /* conflicts of data types or tags */ +#define RSVC_NOTFOUND 8 /* RSVC cannot find user request (RSVCData) */ + +#define RSVC_TIMEOUT 9 /* time out */ +#define RSVC_CONVERT 10 /* RSVCData conversion error */ +#define RSVC_OUTOFRANGE 11 /* value out of range for device attribute */ +#define RSVC_NOACCESS 12 /* insufficient access to perform request */ +#define RSVC_ACCESSCHANGED 13 /* change in access permission of device */ + +#define RSVC_DISCONNECTED 60 /* channel has been disconnected */ +#define RSVC_RECONNECTED 61 /* channel has been reconnected */ +#define RSVC_OVERFLOW 62 /* overflow existing data buffer */ + +#define RSVC_DELETE_CALLBACK 70 /* the callback object will be deleted */ + +#define RSVC_NOKEY 80 /* data has no key in the data */ +#define RSVC_CONN_TIMEOUT 82 /* connection timeout */ +#define RSVC_FILTERED 83 /* messages have been filtered */ +#define RSVC_NOFILTERING 84 /* no filtering applied */ +#define RSVC_DROPPED 85 /* message is dropped */ +#define RSVC_BADIO 86 /* TCP io is bad file descriptor */ +#define RSVC_INCOMPLETE 88 /* data flow will coming (unfinished) */ +#define RSVC_CBK_FINISHED 89 /* callback finished (monitor off) */ +#define RSVC_PAUSED 90 /* query callback is paused */ +#define RSVC_QUERYMSG_ERR 91 /* query message syntax error */ + +/* Request object state values */ +#define RSVC_STATE_CONNECTED 0 /* request object is connected to device */ +#define RSVC_STATE_NOTCONNECTED 1 /* request object is not connected */ +#define RSVC_STATE_INVALID 2 /* request object is invalid */ + +/* Request object access values */ +#define RSVC_ACCESS_NONE 0 /* no access to specified attribute */ +#define RSVC_ACCESS_READONLY 1 /* read-only access to attribute */ +#define RSVC_ACCESS_WRITE 2 /* read-write access to attribute */ + +/* RSVCError class severity codes */ +#define RSVC_SEVERITY_INFO 0 /* informative message */ +#define RSVC_SEVERITY_WARN 1 /* warning message */ +#define RSVC_SEVERITY_ERROR 2 /* error message */ +#define RSVC_SEVERITY_SEVERE 3 /* severe or fatal error message */ + +#define RSVC_IOERROR RSVC_IOFAILED + + +#endif diff --git a/extensions/cdevGenericServer/include/rsvcHSlist.h b/extensions/cdevGenericServer/include/rsvcHSlist.h new file mode 100644 index 0000000..07a95bf --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcHSlist.h @@ -0,0 +1,256 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Single Linked List for pointers rsvcHashable pointer +// Primary used inside rsvcHash +// +// Note: remove and clean operations on the list +// will only remove link nodes without removal of +// the content inside the nodes. It is callers' +// responsiblity to clean up those contents +// +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// +// +// +#ifndef _RSVC_HSLIST_H +#define _RSVC_HSLIST_H + +#include +#include + +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +#include +#endif + +#include +#include +#include +#include + + +//====================================================================== +// class rsvcSlist +// Single Linked List for void* pointer +//====================================================================== +class rsvcHSlistLink; +class rsvcHSlistIterator; +class rsvcHSlistCursor; +class rsvcHash; +class rsvcHashable; + +class rsvcHSlist +{ +public: + // constructors + rsvcHSlist (void); + rsvcHSlist (const rsvcHSlist & source); + virtual ~rsvcHSlist (void); + + // operations + + // add list item to the beginning of the list + virtual void add (rsvcHashable* value); + // add item to the end of list + virtual void addToEnd (rsvcHashable* value); + + // remove a list item from the list + // return 0: nothing to remove + // return 1: remove success + virtual int remove (rsvcHashable* value); + + // clean up the list. + virtual void deleteAllValues (void); + + // return first element of the list + virtual rsvcHashable* firstElement (void); + + // return last element of the list + virtual rsvcHashable* lastElement (void); + + // duplicate ths whole list + virtual rsvcHSlist* duplicate (void); + + // check whether this list contains a particular item + // return 1: yes. return 0: no + virtual int includes (rsvcHashable* value); + + // Is list empty + // return 1: yes. return 0: no + virtual int isEmpty (void); + + // remove first element of the list + virtual void removeFirst (void); + + // return number of elements inside the list + virtual int count (void); + +protected: + // data field + rsvcHSlistLink* ptrToFirstLink; + + // number elements in the list + int count_; + +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif + + // some internal functions which must be called with lock held + virtual void add_i (rsvcHashable* value); + virtual int isEmpty_i (void) const; + virtual void deleteAllValues_i (void); + virtual void removeFirst_i (void); + virtual rsvcHashable* firstElement_i (void); + virtual rsvcHashable* lastElement_i (void); + + // friends + friend class rsvcHSlistIterator; + // cannot modify list in anyways + friend class rsvcHSlistCursor; + friend class rsvcHash; + +private: + // deny access to assignment operation + rsvcHSlist& operator = (const rsvcHSlist& list); +}; + +//====================================================================== +// class rsvcHSlistLink +// Single linked list link node +//====================================================================== +class rsvcHSlistLink +{ +public: + // constructor + rsvcHSlistLink (rsvcHashable* linkValue, rsvcHSlistLink * nextPtr); + + // insert a new element following the current value + rsvcHSlistLink* insert (rsvcHashable* val); + // return data value + rsvcHashable* data (void); + + // return next data item + rsvcHSlistLink* next (void); + + +private: + + // duplicate + rsvcHSlistLink* duplicate (void); + + // data areas + rsvcHashable* value; + rsvcHSlistLink* ptrToNextLink; + + // friends + friend class rsvcHSlist; + friend class rsvcHSlistIterator; + friend class rsvcHSlistCursor; +}; + +//=================================================================== +// class rsvcHSlistIterator +// implements iterator protocol for linked lists +// also permits removal and addition of elements +//=================================================================== + +class rsvcHashIterator; + +class rsvcHSlistIterator +{ +public: + // constructor + rsvcHSlistIterator (rsvcHSlist& aList); + + // iterator protocol + virtual int init (void); + virtual rsvcHashable* operator () (void); + virtual int operator ! (void); + virtual int operator ++ (void); + virtual void operator = (rsvcHashable* value); + + // new methods specific to list iterators + + // remove current item pointed by the iterator from the list + void removeCurrent(void); + + // add an item to the list before the position pointed by the iterator + void addBefore(rsvcHashable* newValue); + + // add an item to the list after the position pointed by the iterator + void addAfter(rsvcHashable* newValue); + + // search an item and move the iterator to that position + int searchSame(rsvcHashable* &value); + +protected: + // some internal functions which must be called with lock held + virtual int init_i (void); + // move cursor forward + virtual int forward_i (void); + // internal remove current + void removeCurrent_i (void); + // data areas + rsvcHSlistLink * currentLink; + rsvcHSlistLink * previousLink; + rsvcHSlist& theList; +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif + +private: + // friend class + friend class rsvcHashIterator; + + // deny access of copy and assignment + rsvcHSlistIterator (const rsvcHSlistIterator& ir); + rsvcHSlistIterator& operator = (const rsvcHSlistIterator& ir); +}; + +//=================================================================== +// class rsvcHSlistCursor +// implements cursor protocol for linked lists +//=================================================================== +class rsvcHSlistCursor +{ +public: + // constructor + rsvcHSlistCursor (const rsvcHSlist& aList); + + // iterator protocol + virtual int init (void); + virtual rsvcHashable* operator () (void); + virtual int operator ! (void); + virtual int operator ++ (void); + virtual void operator = (rsvcHashable* value); + + int searchSame (rsvcHashable* &value); + +protected: + // internal functions which must be called with lock + virtual int init_i (void); + // data areas + rsvcHSlistLink * currentLink; + rsvcHSlistLink * previousLink; + const rsvcHSlist& theList; +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif + +private: + // deny access to copy and assignment operations + rsvcHSlistCursor (const rsvcHSlistCursor &); + rsvcHSlistCursor& operator = (const rsvcHSlistCursor &); +}; +#endif diff --git a/extensions/cdevGenericServer/include/rsvcHash.h b/extensions/cdevGenericServer/include/rsvcHash.h new file mode 100644 index 0000000..def1821 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcHash.h @@ -0,0 +1,144 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606 +// Email: coda@cebaf.gov Tel: (804) 249-7101 Fax: (804) 249-7363 +//----------------------------------------------------------------------------- +// +// Description: +// rsvcStrHash: rsvc hash table keyed by a variable length string +// Open Hash with buckets implemented by single linked lists +// +// Note: void *s are stored inside the table. This class +// will not manage these pointers. Callers have to +// manage these pointers +// +// Note: this is unsafe C++ practice. Use at your own risk +// +// Reason: It is so difficult to use a template class inside +// a shared library. (Cfront based C++ compiler cannot +// instantiate a template class during compilation time +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// +// +// +#ifndef _RSVC_HASH_H +#define _RSVC_HASH_H + +#include +#include +#include +#include + + +//====================================================================== +// class rsvcHash +// collection of buckets indexed by hashed values +//====================================================================== +class rsvcHashIterator; + +class rsvcHash +{ +public: + // constructor + + // construct a hash table with estimate max entry and load fator + rsvcHash (unsigned int estimatemax, unsigned int lf = 5); + + // destructor + virtual ~rsvcHash (void); + + // operations + + // is the table empty: return 1: yes. return 0: no + virtual int isEmpty(); + + // clear the elements of the set + virtual void deleteAllValues(); + + // add an element to the collection + virtual void add (rsvcHashable* ele); + + // dump all hash distribution + void asciiDump (FILE* fd = stdout); + + // return a reference to a particular bucket according to the key + rsvcHSlist& bucketRef (rsvcHashable* ele); + + // return a reference to a particular bucket according to a hash value + rsvcHSlist& bucketRef (unsigned int hashcode); + + // return a pointer to an array of linked list + void bucketList (rsvcHSlist* &list, unsigned int& size); + +protected: + friend class rsvcHashIterator; + + // the actual table itself is a vector of buckets + unsigned int tablesize; + unsigned int lf; + // current index of prime number table + int primeindex; + // buckets + rsvcHSlist* buckets; + + // convert key into unsigned integer value in range + unsigned int hash(rsvcHashable* ele) const; + + // expand the hash table size to next prime number when + // load factor reaches the preset value + void rehash (void); + +private: + +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif +}; + +//====================================================================== +// class rsvcHashIterator +// iterator protocol for hash tables +//====================================================================== +class rsvcHashIterator +{ +public: + // constructor and destructor + rsvcHashIterator (rsvcHash& v); + ~rsvcHashIterator (void); + + // iterator protocol + int init (void); + rsvcHashable* operator ()(void); + int operator ! (void); + int operator ++(void); + + // change value at this position + // make sure the hash key are the same inside the value + void operator = (rsvcHashable* value); + + // new operations + // remove current item pointed by this cursor + void removeCurrent (void); + +protected: + rsvcHash& base; + unsigned int currentIndex; + // Single iterator within a bucket + rsvcHSlistIterator* itr; + // getNextIterator used to set internal iterator pointer + // return 1: got it. return 0: no more iterator + int getNextIterator (void); + +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif +}; +#endif diff --git a/extensions/cdevGenericServer/include/rsvcHashable.h b/extensions/cdevGenericServer/include/rsvcHashable.h new file mode 100644 index 0000000..ec04dec --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcHashable.h @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Abstract class +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_HASHABLE_H +#define _RSVC_HASHABLE_H + +class rsvcHashable +{ +public: + // destructor + virtual ~rsvcHashable (void); + virtual unsigned int hash (void) = 0; + +protected: + rsvcHashable (void); +}; +#endif diff --git a/extensions/cdevGenericServer/include/rsvcIO.h b/extensions/cdevGenericServer/include/rsvcIO.h new file mode 100644 index 0000000..30852ed --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcIO.h @@ -0,0 +1,146 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC TCP IO handler (Generic Class) +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_IO_H +#define _RSVC_IO_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +class rsvcAcceptor; + +class rsvcIO: public cdevEventHandler +{ +public: + // constructor + rsvcIO (cdevReactor& r, rsvcAcceptor* acceptor, + rsvcDataStoreTable& st); + + // destructor + virtual ~rsvcIO (void); + + // remember connected peer address + int peerAddr (const cdevInetAddr & addr); + + // conversion operator for SOCK_Stream + operator cdevSocketStream & (void); + + // set socket options + int setSockOption (int level, int option, void* optval, + int optlen) const; + + // send result to the connected peer + int sendToPeer (rsvcNetData* data); + + // return socket file descriptor + int getHandle (void) const; + + // enable/disable socket io options + void enable (int num); + void disable (int num); + +protected: + // handle socket close + int handleClose ( void ); + + // handleOutput + int handleOutput ( void ); + + // handleInput + int handleInput ( void ); + + // write msg buffer + int writeStreamBuffer (void); + + // shutdown this io stream + void shutdownIO (void); + + // handle process data + int processData (rsvcNetData& data); + + // all those processing functions + int createMemTable (rsvcNetData& ndata); + + int openTable (rsvcNetData& ndata); + + int insertValue (rsvcNetData& ndata, int overwrite = 0); + + int getValue (rsvcNetData& ndata); + + int delValue (rsvcNetData& ndata); + + int setValue (rsvcNetData& ndata); + + int monitorValue (rsvcNetData& ndata); + + int monitorOffValue (rsvcNetData& ndata); + + int monitorAttr (rsvcNetData& ndata); + + int monitorOffAttr (rsvcNetData& ndata); + + int monitorEntries (rsvcNetData& ndata); + + int monitorOffEntries (rsvcNetData& ndata); + + int query (rsvcNetData& ndata); + + // connection to remote client + cdevSocketStream sockStream_; + // Reactor reference + cdevReactor & reactor_; + // client host address + char* clientHost_; + // acceptor that creates this IO + rsvcAcceptor* acceptor_; + + // data queue for writing + rsvcQueue dataQueue_; + + // current writing msg + rsvcStreamMsg wmsg_; + + // output data streaming buffer + char* dbuffer_; + size_t dbuflen_; + + // input data convertion buffer + char* ibuffer_; + size_t ibuflen_; + + // data store index table + rsvcDataStoreTable& storeTable_; + + // flag to tell whether write mask is set or not + int wmaskSet_; + + // deny copy and assignment operations + rsvcIO (const rsvcIO& io); + rsvcIO& operator = (const rsvcIO& io); +}; +#endif diff --git a/extensions/cdevGenericServer/include/rsvcLocalConfig.h b/extensions/cdevGenericServer/include/rsvcLocalConfig.h new file mode 100644 index 0000000..ea274a5 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcLocalConfig.h @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// This a local configuration header file for JLAB use only +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_LOCAL_CONFIG_H +#define _RSVC_LOCAL_CONFIG_H + +#ifdef _CDEV_MANAGE_SERVERS + +#define _RSVC_CDEV_SERVERS "cdevServers" // database name +#define _RSVC_CDEV_SERVERS_KEY "svcid" // key name +#define _RSVC_CDEV_SERVER_TKO 30 // if we do not see a server + // for this long, it is dead +#define _RSVC_CDEV_SCAN_PERIOD 10 + +#endif + +#endif diff --git a/extensions/cdevGenericServer/include/rsvcLogic.h b/extensions/cdevGenericServer/include/rsvcLogic.h new file mode 100644 index 0000000..006ee0e --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcLogic.h @@ -0,0 +1,128 @@ +/* +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606 +// coda@cebaf.gov Tel: (804) 249-7030 Fax: (804) 249-5800 +//----------------------------------------------------------------------------- +// +// Description: +// Header File for rsvcServer Query +// +// Author: +// Jie Chen +// CEBAF Data Acquisition Group +// +// +// +*/ +#ifndef _RSVC_LOGIC_H +#define _RSVC_LOGIC_H + +#define RSVC_LOGIC_UNK 200 +#define RSVC_LOGIC_INT 201 +#define RSVC_LOGIC_DBL 202 +#define RSVC_LOGIC_STR 203 + +/* data structure to hold all values on the stack */ +typedef struct _rsvc_logic_data +{ + short type; + union { + int ival; + double dval; + char* string; + }u; +}rsvc_logic_data; + +/* global input test string for parser */ +extern char* _logic_input_text; + +/* global parsing engine */ +extern void* _logic_q_eng; + +/* instruction set */ +typedef int (*rsvcLogicInst)(void* data); + +#define RSVC_LOGIC_STOP (rsvcLogicInst) 0 + +/* function decleration of supporting functions */ +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (__STDC__) || defined (__cplusplus) +extern rsvc_logic_data* new_logic_data (void); +extern rsvc_logic_data* logic_data_dup (rsvc_logic_data* data); +extern void logic_data_assign_int (rsvc_logic_data* data, int val); +extern void logic_data_assign_dbl (rsvc_logic_data* data, double val); +extern void logic_data_assign_str (rsvc_logic_data* data, char* str); +extern void free_logic_data (rsvc_logic_data* data); + +extern void set_input_text (char* text); +extern void set_query_engine (void* eng); + +extern rsvcLogicInst* logic_code (rsvcLogicInst f); +extern int logic_val_push (void* data); +extern int rsvc_data_equal_int (void* data); +extern int rsvc_data_equal_dbl (void* data); +extern int rsvc_data_equal_str (void* data); +extern int rsvc_data_has_str (void* data); +extern int rsvc_data_less_int (void* data); +extern int rsvc_data_less_dbl (void* data); +extern int rsvc_data_greater_int (void* data); +extern int rsvc_data_greater_dbl (void* data); +extern int rsvc_data_lesseq_int (void* data); +extern int rsvc_data_lesseq_dbl (void* data); +extern int rsvc_data_greatereq_int (void* data); +extern int rsvc_data_greatereq_dbl (void* data); +extern int rsvc_data_noequal_int (void* data); +extern int rsvc_data_noequal_dbl (void* data); +extern int rsvc_data_noequal_str (void* data); +extern int rsvc_logic_and (void* data); +extern int rsvc_logic_or (void* data); +extern int rsvc_logic_neg (void* data); +extern int rsvc_logic_end (void* data); + +#else +extern rsvc_logic_data* new_logic_data (); +extern rsvc_logic_data* logic_data_dup (); +extern void logic_data_assign_int (); +extern void logic_data_assign_dbl (); +extern void logic_data_assign_str (); +extern void free_logic_data (); +extern void set_input_text (); +extern void set_query_engine (); +extern rsvcLogicInst* logic_code (); +extern int logic_val_push (); +extern int rsvc_data_equal_int (); +extern int rsvc_data_equal_dbl (); +extern int rsvc_data_equal_str (); +extern int rsvc_data_has_str (); +extern int rsvc_data_less_int (); +extern int rsvc_data_less_dbl (); +extern int rsvc_data_greater_int (); +extern int rsvc_data_greater_dbl (); +extern int rsvc_data_lesseq_int (); +extern int rsvc_data_lesseq_dbl (); +extern int rsvc_data_greatereq_int (); +extern int rsvc_data_greatereq_dbl (); +extern int rsvc_data_noequal_int (); +extern int rsvc_data_noequal_dbl (); +extern int rsvc_data_noequal_str (); +extern int rsvc_logic_and (); +extern int rsvc_logic_or (); +extern int rsvc_logic_neg (); +extern int rsvc_logic_end (); +#endif + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/extensions/cdevGenericServer/include/rsvcLogicQEng.h b/extensions/cdevGenericServer/include/rsvcLogicQEng.h new file mode 100644 index 0000000..6cdda74 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcLogicQEng.h @@ -0,0 +1,84 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606 +// coda@cebaf.gov Tel: (804) 249-7030 Fax: (804) 249-5800 +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server Query Simple Engine +// +// Author: +// Jie Chen +// CEBAF Data Acquisition Group +// +// +// +#ifndef _RSVC_LOGIC_Q_ENG_H +#define _RSVC_LOGIC_Q_ENG_H + +#include +#include +#include +#include + +/* stack size */ +#define RSVC_NSTACK 1024 + +/* program counter */ +#define RSVC_NPROG 4096 + +class rsvcLogicQEng +{ +public: + // constructor and destructor + rsvcLogicQEng (char* qstring); + ~rsvcLogicQEng (void); + + // operation + + // parse string and produce simple engine + // return 0 success, return -1 syntax error + int parse (void); + + // execute the engine + int execute (rsvcData& data); + + // clean the engine + int clean (void); + + // stack operation + int push (rsvc_logic_data* data); + rsvc_logic_data* pop (void); + +private: + // machine stack + rsvc_logic_data* stack_[RSVC_NSTACK]; + // next free slot on the stack + rsvc_logic_data** stackp_; + + // simple computing machine + rsvcLogicInst prog_[RSVC_NPROG]; + // next free spot for code + rsvcLogicInst* progp_; + // program counter + rsvcLogicInst* pc_; + + // parsing string + char* qstr_; + + // result of execution + int result_; + + friend rsvcLogicInst* logic_code (rsvcLogicInst f); + friend int logic_val_push (void* d); + friend int rsvc_logic_end (void* d); +}; + + +#endif + diff --git a/extensions/cdevGenericServer/include/rsvcLogicSup.h b/extensions/cdevGenericServer/include/rsvcLogicSup.h new file mode 100644 index 0000000..f0cb666 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcLogicSup.h @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606 +// coda@cebaf.gov Tel: (804) 249-7030 Fax: (804) 249-5800 +//----------------------------------------------------------------------------- +// +// Description: +// Simple Header File for rsvc logic expression parser +// +// Author: +// Jie Chen +// CEBAF Data Acquisition Group +// +// +// +#ifndef _RSVC_LOGIC_SUP_H +#define _RSVC_LOGIC_SUP_H + +// check whether a cdevData matches a logic expression +// return -1: string has grammer error +// return 0: not matching +// return 1: yes +extern int dataMatchLogic (rsvcData& data, char* string); + +#endif diff --git a/extensions/cdevGenericServer/include/rsvcNetData.h b/extensions/cdevGenericServer/include/rsvcNetData.h new file mode 100644 index 0000000..a7dd048 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcNetData.h @@ -0,0 +1,124 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Network Protocol Data +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_NET_DATA_H +#define _RSVC_NET_DATA_H + +#include +#include +#include +#include +#include +#include +#include +#include + +class RSVC_CLASS_SPEC rsvcNetData : public rsvcStreamable +{ +public: + // constructors + // create empty data + rsvcNetData (void); + + // create a data with operation code and reqid + rsvcNetData (rsvcData& data, long opcode, long cbkid, + long reqid = 0, long clientid = 0, long socketid = 0, + long status = RSVC_SUCCESS); + + // create a data with explicit callback data + rsvcNetData (rsvcData& data, rsvcCbk& cbk); + + // create a data with callback data only + rsvcNetData (rsvcCbk& cbk); + + // create a data with real data only + rsvcNetData (rsvcData& data); + + // copy operation + rsvcNetData (const rsvcNetData& data); + + // destructor + ~rsvcNetData (void); + + // set method + void set (rsvcData& data, rsvcCbk& cbk); + void set (rsvcCbk& cbk); + + // cleanup everything + void cleanup (void); + + // opcode + long opcode (void) const; + void opcode (long op); + + // request id + long reqid (void) const; + void reqid (long id); + + // client id + long clientid (void) const; + void clientid (long cid); + + // callback id + long cbkid (void) const; + void cbkid (long cid); + + // socket id + long socketid (void) const; + void socketid (long id); + + // net operation status + long cbkstatus (void) const; + void cbkstatus (long status); + + // return underlying data object + rsvcData& data (void); + // return underlying callback object + rsvcCbk& cbk (void); + + // stream in and out operation + size_t streamSize (void); + + // stream out to a newly allocated buffer with size 'size' + int streamOut (char** buf, size_t* size); + // stream out to a preallocate buffer with buffer size 'size' + int streamOut (char* buf, size_t len); + + // stream in from a buffer + // this function is called after one has read in the header + // information already + int streamIn (char* buf, size_t len); + + // stream out to a preallocate buffer with buffer size 'len' + // and data size 'datasize' + int streamOut (char* buf, size_t len, size_t datasize); + + // retrieve header information + static int readHeader (char* buf, size_t len, size_t* datasize); + + // return header length + static size_t headerLen (void); + +private: + // callback object + rsvcCbk cbk_; + + // data object + rsvcData data_; +}; +#endif + + diff --git a/extensions/cdevGenericServer/include/rsvcServerConfig.h b/extensions/cdevGenericServer/include/rsvcServerConfig.h new file mode 100644 index 0000000..c4d4980 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcServerConfig.h @@ -0,0 +1,68 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Configuration Class +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_SERVER_CONFIG_H +#define _RSVC_SERVER_CONFIG_H + +#include +#include +#include +#include + +#define RSVC_DBASE_HOME "/tmp/" +#define RSVC_SERVER_ENV "RSVC_SERVER_CONFIG" + +class rsvcServerConfig +{ +public: + static int configure (char* filename = 0); + // this is the port all servers to connected to (udp) + static unsigned short serverPort (void); + // this is the port all client program to connect to + static unsigned short port (void); + static size_t dbasePageSize (void); + static size_t dbaseCacheSize (void); + static size_t dbaseCacheMax (void); + static size_t dbaseCacheLf (void); + static size_t maxNoFiles (void); + static char* key (void); + static char* table (void); + static char* keyType (void); + static char* keyExp (void); + static char* dbaseHome (void); + static char* tableNameExt (void); + static char* monitorTag (void); + static char* queryTag (void); + static char** defaultDbases (void); + +protected: + static unsigned short port_; + static size_t pageSize_; + static size_t cacheSize_; + static size_t cacheMax_; + static size_t cacheLf_; + static size_t maxnofiles_; + static char* keyName_; + static char* keyType_; + static char* keyExp_; + static char* tableName_; + static char* dbaseHome_; + static char* tableNameExt_; + static char* monitorTag_; + static char* queryTag_; + static char** defaultDbases_; +}; +#endif diff --git a/extensions/cdevGenericServer/include/rsvcServerStore.h b/extensions/cdevGenericServer/include/rsvcServerStore.h new file mode 100644 index 0000000..f5677a6 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcServerStore.h @@ -0,0 +1,106 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// rsvcServerStore Class for JLAB Control System Use Only +// +// This is a storage class for all network servers running +// in the JLAB control system +// +// This database has a fixed definition as the following +// "table" "cdevServers" +// "key" "svid" +// "keyExp" "name+domain" +// "keyType" RSVC_STRING +// "name" RSVC_STRING +// "domain" RSVC_STRING +// "host" RSVC_STRING +// "owner" RSVC_STRING +// "time" RSVC_LONG +// "port" LONG +// "pid" LONG +// +// the following are appended by this class +// 0 --> active +// "status" 1 --> dormant +// 2 --> dead +// 3 --> newserver +// +// 0 --> normal +// "severity" 1 --> minor +// 2 --> major +// +// "ping" RSVC_LONG +// "client" RSVC_LONG +// +// +// +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_SERVER_STORE_H +#define _RSVC_SERVER_STORE_H + +#ifdef _CDEV_MANAGE_SERVERS + +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#else +#include +#endif + +#include + +class rsvcCacheData; + +class rsvcServerStore: public rsvcDataStoreMem +{ +public: + // constructor + rsvcServerStore (void); + ~rsvcServerStore (void); + + // inherited operations + virtual int putValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num, + int overwrite = 0); + + virtual int setValue (rsvcNetData& incoming, + rsvcNetData* outdata[], size_t* num); + + virtual void handleClose (void* ptr); + + // check all data inside table + void checkAll (void); + +protected: + // check whether a data is valid or not by checking + // status field of cached data + int dataValid (rsvcCacheData* data); + + // update ping number + void ping (rsvcCacheData* data); + + // check ping number + void checkPing (rsvcCacheData* data); + +private: + // Fixed table definition + rsvcData tdata_; +}; +#endif + +#endif diff --git a/extensions/cdevGenericServer/include/rsvcSignal.h b/extensions/cdevGenericServer/include/rsvcSignal.h new file mode 100644 index 0000000..7cf6b34 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcSignal.h @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// rsvc server signal handler +// +// Author: +// Jie Chen +// +// +// +#ifndef _RSVC_SIGNAL_HANDLER_H +#define _RSVC_SIGNAL_HANDLER_H + +class cdevReactor; + +extern int rsvc_finished; +extern cdevReactor* rsvc_reactor; + +class rsvcSignal +{ +public: + // operation + static int registerSignalHandlers (void); + + // all signal handlers + static void signalFunc (int signo); + +private: + // all signals we want to catch + static int signals[]; + static int numSignals; + // deny direct access + rsvcSignal (void); +}; +#endif + + + diff --git a/extensions/cdevGenericServer/include/rsvcSlist.h b/extensions/cdevGenericServer/include/rsvcSlist.h new file mode 100644 index 0000000..2ca3955 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcSlist.h @@ -0,0 +1,304 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Single Linked List for pointers void * +// +// Note: remove and clean operations on the list +// will only remove link nodes without removal of +// the content inside the nodes. It is callers' +// responsiblity to clean up those contents +// +// This is unsafe C++ practice, use this list at you own risk +// +// Reason for this list: It is very difficult to instantiate +// a template class in a stand alone shared library +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// +// +// +#ifndef _RSVC_SLIST_H +#define _RSVC_SLIST_H + +#include +#include + +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) +#include +#endif + +#include +#include +#include +#include + + +typedef void* rsvcSlistItem; + +//====================================================================== +// class rsvcSlist +// Single Linked List for void* pointer +//====================================================================== +class rsvcSlistLink; +class rsvcSlistIterator; +class rsvcSlistCursor; +class rsvcHash; + +class rsvcSlist +{ +public: + // constructors + rsvcSlist (void); + rsvcSlist (const rsvcSlist & source); + virtual ~rsvcSlist (void); + + // operations + + // add list item to the beginning of the list + virtual void add (rsvcSlistItem value); + // add item to the end of list + virtual void addToEnd (rsvcSlistItem value); + + // remove a list item from the list + // return 0: nothing to remove + // return 1: remove success + virtual int remove (rsvcSlistItem value); + + // clean up the list. + virtual void deleteAllValues (void); + + // return first element of the list + virtual rsvcSlistItem firstElement (void); + + // return last element of the list + virtual rsvcSlistItem lastElement (void); + + // duplicate ths whole list + virtual rsvcSlist* duplicate (void); + + // check whether this list contains a particular item + // return 1: yes. return 0: no + virtual int includes (rsvcSlistItem value); + + // Is list empty + // return 1: yes. return 0: no + virtual int isEmpty (void); + + // remove first element of the list + virtual void removeFirst (void); + + // return number of elements inside the list + virtual int count (void); + +protected: + // data field + rsvcSlistLink* ptrToFirstLink; + + // number elements in the list + int count_; + +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif + + // some internal functions which must be called with lock held + virtual void add_i (rsvcSlistItem value); + virtual int isEmpty_i (void) const; + virtual void deleteAllValues_i (void); + virtual void removeFirst_i (void); + virtual rsvcSlistItem firstElement_i (void); + virtual rsvcSlistItem lastElement_i (void); + + // friends + friend class rsvcSlistIterator; + // cannot modify list in anyways + friend class rsvcSlistCursor; + friend class rsvcHash; + +private: + // deny access to assignment operation + rsvcSlist& operator = (const rsvcSlist& list); +}; + +//====================================================================== +// class rsvcSlistLink +// Single linked list link node +//====================================================================== +class rsvcSlistLink +{ +public: + // constructor + rsvcSlistLink (rsvcSlistItem linkValue, rsvcSlistLink * nextPtr); + + // insert a new element following the current value + rsvcSlistLink* insert (rsvcSlistItem val); + // return data value + rsvcSlistItem data (void); + + // return next data item + rsvcSlistLink* next (void); + + +private: + + // duplicate + rsvcSlistLink* duplicate (void); + + // data areas + rsvcSlistItem value; + rsvcSlistLink* ptrToNextLink; + + // friends + friend class rsvcSlist; + friend class rsvcSlistIterator; + friend class rsvcSlistCursor; +}; + +//=================================================================== +// class rsvcSlistIterator +// implements iterator protocol for linked lists +// also permits removal and addition of elements +//=================================================================== + +class rsvcHashIterator; + +class rsvcSlistIterator +{ +public: + // constructor + rsvcSlistIterator (rsvcSlist& aList); + + // iterator protocol + virtual int init (void); + virtual rsvcSlistItem operator () (void); + virtual int operator ! (void); + virtual int operator ++ (void); + virtual void operator = (rsvcSlistItem value); + + // new methods specific to list iterators + + // remove current item pointed by the iterator from the list + void removeCurrent(void); + + // add an item to the list before the position pointed by the iterator + void addBefore(rsvcSlistItem newValue); + + // add an item to the list after the position pointed by the iterator + void addAfter(rsvcSlistItem newValue); + + // search an item and move the iterator to that position + int searchSame(rsvcSlistItem &value); + +protected: + // some internal functions which must be called with lock held + virtual int init_i (void); + // move cursor forward + virtual int forward_i (void); + // internal remove current + void removeCurrent_i (void); + // data areas + rsvcSlistLink * currentLink; + rsvcSlistLink * previousLink; + rsvcSlist& theList; +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif + +private: + // friend class + friend class rsvcHashIterator; + + // deny access of copy and assignment + rsvcSlistIterator (const rsvcSlistIterator& ir); + rsvcSlistIterator& operator = (const rsvcSlistIterator& ir); +}; + +//=================================================================== +// class rsvcSlistCursor +// implements cursor protocol for linked lists +//=================================================================== +class rsvcSlistCursor +{ +public: + // constructor + rsvcSlistCursor (const rsvcSlist& aList); + + // iterator protocol + virtual int init (void); + virtual rsvcSlistItem operator () (void); + virtual int operator ! (void); + virtual int operator ++ (void); + virtual void operator = (rsvcSlistItem value); + + int searchSame (rsvcSlistItem &value); + +protected: + // internal functions which must be called with lock + virtual int init_i (void); + // data areas + rsvcSlistLink * currentLink; + rsvcSlistLink * previousLink; + const rsvcSlist& theList; +#if defined (RSVC_USE_THREAD) && defined (_REENTRANT) + cpMutex lock_; +#endif + +private: + // deny access to copy and assignment operations + rsvcSlistCursor (const rsvcSlistCursor &); + rsvcSlistCursor& operator = (const rsvcSlistCursor &); +}; + +//====================================================================== +// class doubleEndedList +// Not only keeps a pointer to first node +// but also keeps a pointer to last node +//====================================================================== +class rsvcDoubleEndedSlist: public rsvcSlist{ +public: + //constructor + rsvcDoubleEndedSlist (void); + rsvcDoubleEndedSlist (const rsvcDoubleEndedSlist &v); + + // override the following methods from the rsvcSlist + virtual void add (rsvcSlistItem value); + virtual void deleteAllValues (void); + virtual void removeFirst (void); + + // add new element to the end of the list + virtual void addToEnd (rsvcSlistItem value); + +protected: + rsvcSlistLink *ptrToLastLink; + +private: + // deny access to assignment operation + rsvcDoubleEndedSlist& operator = (const rsvcDoubleEndedSlist); +}; + +class rsvcQueue: public rsvcDoubleEndedSlist +{ +public: + // constructor and destructor + rsvcQueue (void); + + // operations + rsvcSlistItem dequeue (void); + void enqueue (rsvcSlistItem value); + rsvcSlistItem front (void); + +private: + // deny access to assignment and copy operations + rsvcQueue (const rsvcQueue& queue); + rsvcQueue& operator = (const rsvcQueue& queue); +}; +#endif diff --git a/extensions/cdevGenericServer/include/rsvcSpec.h b/extensions/cdevGenericServer/include/rsvcSpec.h new file mode 100644 index 0000000..6b8ee09 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcSpec.h @@ -0,0 +1,62 @@ +/*----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + *----------------------------------------------------------------------------- + * + * Description: + * RSVC and API Specification + * + * Every class header file and C interface header should include + * this header + * + * Authors: Jie Chen + * + * Revision History: + * $Log: rsvcSpec.h,v $ + * Revision 1.1.1.1 2000/05/23 15:12:51 pal + * cdev_psi_1.7.2 + * + * Revision 1.1 1999/03/15 16:40:09 chen + * New file + * + * + */ +#ifndef _RSVC_SPEC_H +#define _RSVC_SPEC_H + +#if defined (_WIN32) + +#if !defined (DLLIMPORT) +#define DLLIMPORT __declspec(dllimport) +#endif + +#if !defined (DLLEXPORT) +#define DLLEXPORT __declspec(dllexport) +#endif + +#if defined (_RSVC_CORE_EXPORTS_) +#define RSVCAPI DLLEXPORT +#define RSVC_CLASS_SPEC DLLEXPORT +#elif defined (_RSVC_BUILD_EXE) +#define RSVCAPI +#define RSVC_CLASS_SPEC +#else +#define RSVCAPI DLLIMPORT +#define RSVC_CLASS_SPEC DLLIMPORT +#endif + +#else /* WIN32 */ + +#define RSVCAPI +#define DLLIMPORT +#define DLLEXPORT +#define RSVC_CLASS_SPEC + +#endif + +#endif + diff --git a/extensions/cdevGenericServer/include/rsvcStreamMsg.h b/extensions/cdevGenericServer/include/rsvcStreamMsg.h new file mode 100644 index 0000000..b5b7c30 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcStreamMsg.h @@ -0,0 +1,98 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Server Streamed Message +// +// This class allows either partial read/write not both +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_STREAM_MSG_H +#define _RSVC_STREAM_MSG_H + +#include +#include +#include + +class rsvcNetData; + +class rsvcStreamMsg +{ +public: + // constructor + + // create an empty stream + rsvcStreamMsg (void); + + // create a stream with data buffer and size and flag denoting + // whether we delete this data buffer we we are done + rsvcStreamMsg (char* data, size_t size, int deleteit = 1); + + // create a stream from rsvcNetData + rsvcStreamMsg (rsvcNetData* data); + + // destructor + ~rsvcStreamMsg (void); + + // attach buffer + void attach (char* data, size_t size, int deleteit = 1); + + // check we are in the middle of action + int active (void) const; + + // set action pointer + void actionPtr (char* ptr); + // move ptr forward + void actionPtr (size_t n); + // return action pointer + char* actionPtr (void) const; + + // total message size + size_t length (void) const; + + // set msg length + void length (size_t len); + + // base pointer + char* base (void) const; + + // remaining message size (or space) + size_t size (void); + // check whether we have reached end of message buffer + int endMsg (void); + + // reset everything + void reset (void); + + // resize buffer to twice of current size + void resize (void); + +private: + + // data area + char* buffer_; + size_t buflen_; + + // pointer to current action ptr + size_t cursor_; + + // flag denoting whether we are deleting the buffer or not + int deleteBuffer_; + + // flag to denoting whether this stream is in the middle of read/write + int active_; + + // deny copy and assignment operations + rsvcStreamMsg (const rsvcStreamMsg& msg); + rsvcStreamMsg& operator = (const rsvcStreamMsg& msg); +}; +#endif diff --git a/extensions/cdevGenericServer/include/rsvcStreamable.h b/extensions/cdevGenericServer/include/rsvcStreamable.h new file mode 100644 index 0000000..fd6929f --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcStreamable.h @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Abstract class for network streamable class +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_STREAMABLE_H +#define _RSVC_STREAMABLE_H + +#include +#include + +class rsvcStreamable +{ +public: + // virtual destrcutor + virtual ~rsvcStreamable (void); + // return stream size + virtual size_t streamSize (void) = 0; + + // stream data object out into a newly allocated buffer + virtual int streamOut (char** buffer, size_t* size) = 0; + + // stream data object out into a preallocated buffer + virtual int streamOut (char* buffer, size_t len) = 0; + + // recreate data from incoming data buffer + virtual int streamIn (char* buffer, size_t len) = 0; + +protected: + rsvcStreamable (void); +}; +#endif diff --git a/extensions/cdevGenericServer/include/rsvcTableDef.h b/extensions/cdevGenericServer/include/rsvcTableDef.h new file mode 100644 index 0000000..390cb8e --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcTableDef.h @@ -0,0 +1,142 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC Database (Memory) Table Definition +// +// Author: Jie Chen +// +// +// +// +#ifndef _RSVC_TABLE_DEF_H +#define _RSVC_TABLE_DEF_H + +#include +#include +#include +#include + +//========================================================================= +// Table Definition by a rsvcData Object +// tag value +// +// "table" "name" +// "key" "name" +// "keyExp" "expression" +// "keyType" something +// "*******" "anything" +// "*******" "anything" +//========================================================================= + +// currently the key can be only in the form of the following +// attr0 + attr1 +// eventually I am going to use yacc to build a better function + +class rsvcTableDef; + +typedef int (*rsvcKeyFunc)(rsvcData& data, rsvcTableDef* table); + +class rsvcTableDef +{ +public: + // constructor and destructor + + // create an empty table definition + rsvcTableDef (char* name); + ~rsvcTableDef (void); + + // construct table definition from a rsvcData + int create (rsvcData& data); + // construct table definition from disk + int create (void); + // dump table definition to disk: overwrite existing table definition + int output (void); + // output table definition to a rsvcData object + int output (rsvcData& data); + + // is table definition set + int tableDefined (void) const; + + // some commonly used operations + + // check whether this row name is valid + int rowNameValid (char* row); + int rowValid (char* row, int type); + // is this data valid: all tags must be a subset of table + int dataValid (rsvcData& data); + // does this data look the same as the table? + int dataInsertable (rsvcData& data); + // check whether this data has key value in it + int hasKey (rsvcData& data); + + // get key information + // What is the name for the key? This determines the file name + // of the datafile + char* keyName (void) const; + // What is the expression for the key? Currently the expression + // must be one of the row name + char* keyExp (void) const; + // what is the key type for the key? + int keyType (void) const; + + // insert tagged key value into a data + int keyValue (rsvcData& data); + + // table name + char* name (void) const; + +protected: + + // all key calculation functions + static int sameAttr (rsvcData& data, rsvcTableDef* table); + static int attrPlus (rsvcData& data, rsvcTableDef* table); + +private: + // function for figure out real table definition file name + // caller release returned memory + static char* tableDefFileName (char* tablename); + + // check whether two types are convertable or not + static int typeConvertable (int type0, int type1); + + // parse simple key expression + int parseKeyExp (char* exp); + + // real rsvcData object + rsvcData table_; + int defined_; + + // table name + char* name_; + + // key name + char* keyname_; + + // key exp + char* keyexp_; + + // key type + int keytype_; + + // index calculate function pointer + rsvcKeyFunc keyfunc_; + + // attributes that make up the key + char* attr0_; + char* attr1_; + + + // deny copy and assignment operations + rsvcTableDef (const rsvcTableDef& def); + rsvcTableDef& operator = (const rsvcTableDef& def); +}; +#endif + + diff --git a/extensions/cdevGenericServer/include/rsvcUdpClient.h b/extensions/cdevGenericServer/include/rsvcUdpClient.h new file mode 100644 index 0000000..d5db6f3 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcUdpClient.h @@ -0,0 +1,69 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC UDP Client +// +// This is very limited, it only allows update to a single table +// Internal CEBAF use only +// +// Author: Jie Chen +// +// +// +// +#ifndef _RSVC_UDP_CLIENT_H +#define _RSVC_UDP_CLIENT_H + +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#else +#include +#include +#include +#include +#endif + +#include +#include +#include + +class RSVC_CLASS_SPEC rsvcUdpClient +{ +public: + // constructor + rsvcUdpClient (void); + ~rsvcUdpClient (void); + + int connect (char* host, unsigned short port); + + int update (rsvcData& data); + + int disconnect (void); + +private: + // stream a data object + int streamData (rsvcNetData& data); + + // open udp port + int openUdpPort (char* host, unsigned short port); + + // udp socket + struct sockaddr_in udp_addr_; + int fd_; + // data convertion buffer + char obuffer_[RSVC_UDP_BUFFER_SIZE]; +}; +#endif + diff --git a/extensions/cdevGenericServer/include/rsvcUdpHandler.h b/extensions/cdevGenericServer/include/rsvcUdpHandler.h new file mode 100644 index 0000000..f5d1b0d --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcUdpHandler.h @@ -0,0 +1,68 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC UDP Service Handler (For managed servers only) +// +// Author: Jie Chen +// +// +// +#ifndef _RSVC_UDP_HANDLER_H +#define _RSVC_UDP_HANDLER_H + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + + +class rsvcUdpHandler : public cdevEventHandler +{ +public: + // constructor and destructor + + // constructor a UDP handler + rsvcUdpHandler (char* dbasename, cdevReactor& r, + rsvcDataStoreTable& st); + // destructor + ~rsvcUdpHandler (void); + + // open the listener of the udp + int open (unsigned short port, int async = 0); + + // return port number + unsigned short port_number (void); + +protected: + // inherited operations + int getHandle (void) const; + int handleClose (void); + int handleInput (void); + +private: + // data area + cdevReactor& reactor_; + cdevSocketDatagram listener_; + + // data conversion buffer + char ibuffer_[RSVC_UDP_BUFFER_SIZE]; + // data storage index table + rsvcDataStoreTable& storeTable_; + // database this udp to update to + char* dbasename_; +}; +#endif diff --git a/extensions/cdevGenericServer/include/rsvcVirtualDbase.h b/extensions/cdevGenericServer/include/rsvcVirtualDbase.h new file mode 100644 index 0000000..4317427 --- /dev/null +++ b/extensions/cdevGenericServer/include/rsvcVirtualDbase.h @@ -0,0 +1,138 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// RSVC database interface +// +// Author: Jie Chen +// +// +// +// +#ifndef _RSVC_VIRTUAL_DATABASE_H +#define _RSVC_VIRTUAL_DATABASE_H + +#include +#include +#include +#include +#include +#include + +class rsvcVirtualDbase +{ +public: + // constructor + // default constructor, users have to call open explicitly + rsvcVirtualDbase (void); + + // constructor: name is a file name, flags are the same flags as + // standard open routine. + // data_size is estimate of each data stored in the database + rsvcVirtualDbase (char* name, int flags, int keyType = RSVC_STRING, + size_t data_size = 496, + size_t cache_size = 0, size_t page_size = 0, + int mode = 0666); + + // destructor + virtual ~rsvcVirtualDbase (void); + + // operation + + // open a database + virtual int open (char* name, int flags, int keyType = RSVC_STRING, + size_t cache_size = 0, + int mode = 0666); + // create a database + virtual int create (char* name, int flags, int keyType = RSVC_STRING, + size_t data_size = 496, + size_t cache_size = 0, size_t page_size = 0, + int mode = 0666); + + // close connection to the database + virtual int close (void) {return RSVC_SUCCESS;} + + // get a rsvcData. + virtual int get (rsvcData& /* data */, rsvcData& /* key */) {return RSVC_SUCCESS;} + // insert a rsvcData which must have a key inside + virtual int put (rsvcData& /* data */, rsvcData& /* key */) {return RSVC_SUCCESS;} + // delete a data object pointed by key value + virtual int del (rsvcData& /* key */) {return RSVC_SUCCESS;} + // flush all internal buffer to disk + virtual int flush (void) {return RSVC_SUCCESS;} + + // return database name + char* database (void) const {return name_;} + // return file descriptor for the opened database + virtual int fd (void) {return 0;} + // check to see the database is open or not + virtual int opened (void) const {return opened_;} + + // iterator for sequential access to database + virtual int cursorInit (void) {return RSVC_SUCCESS;} + + // set cursor to the position pointed by key 'key', + // and return data 'data' if successful + virtual int cursorSet (rsvcData& /* data */, rsvcData& /* key */) {return RSVC_SUCCESS;} + + // move cursor to the next position. + // return CDEV_SUCCESS on success, CDEV_ERROR: check errno + // return CDEV_INVALIDOBJ: no more + virtual int cursorNext (rsvcData& /* data */, rsvcData& /* key */) {return RSVC_SUCCESS;} + + // move cursor to the previous position + // return CDEV_SUCCESS on success, CDEV_ERROR: check errno + // return CDEV_INVALIDOBJ: no more + virtual int cursorPrev (rsvcData& /* data */, rsvcData& /* key */) {return RSVC_SUCCESS;} + + // merge current value pointed by cursor: + // this routine can only used to update the data with the same + // or smaller size than the exisiting data + // If you like to update arbitrary size of data, use del and put + virtual int cursorUpdate (rsvcData& /* data */) {return RSVC_SUCCESS;} + + // move cursor to the beginning of the database + // no need to provide key + virtual int cursorFirst (rsvcData& /* data */, rsvcData& /* key */) {return RSVC_SUCCESS;} + + // move cursor to the end of the database + // no need to provide key + virtual int cursorLast (rsvcData& /* data */, rsvcData& /* key */) {return RSVC_SUCCESS;} + + // close cursor operation + virtual int cursorFinish (void) {return RSVC_SUCCESS;} + + virtual const char* className (void) const {return "rsvcVirtualDbase";} + +protected: + // open flag and mode + int flag_; + int mode_; + // page size + size_t page_size_; + // database name + char* name_; + + // flag to tell whether this database is opened or not + int opened_; + + // key type of this database + int keyType_; + + // error status of open or create of this database + int err_; + + // deny access to copy and assignment operator + rsvcVirtualDbase (const rsvcVirtualDbase& dbase); + rsvcVirtualDbase& operator = (const rsvcVirtualDbase& dbase); +}; +#endif + + + diff --git a/extensions/cdevGenericServer/include/y.tab.h b/extensions/cdevGenericServer/include/y.tab.h new file mode 100644 index 0000000..66a731a --- /dev/null +++ b/extensions/cdevGenericServer/include/y.tab.h @@ -0,0 +1,26 @@ +#ifndef YYERRCODE +#define YYERRCODE 256 +#endif + +#define TAGNAME 257 +#define CSTRING 258 +#define DVALUE 259 +#define IVALUE 260 +#define EQUAL 261 +#define LESS 262 +#define GREATER 263 +#define NOTEQUAL 264 +#define LESSOREQUAL 265 +#define GREATEROREQUAL 266 +#define LEFTP 267 +#define RIGHTP 268 +#define OR 269 +#define AND 270 +#define LIKE 271 +#define NOT 272 +#define CERROR 273 +typedef union { + rsvc_logic_data* data; + rsvcLogicInst* inst; +} YYSTYPE; +extern YYSTYPE yylval; diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/ClientAcceptor.o b/extensions/cdevGenericServer/lib/.obj/Linux/ClientAcceptor.o new file mode 100644 index 0000000..18854eb Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/ClientAcceptor.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/ClientHandler.o b/extensions/cdevGenericServer/lib/.obj/Linux/ClientHandler.o new file mode 100644 index 0000000..c0cea04 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/ClientHandler.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/IntHash.o b/extensions/cdevGenericServer/lib/.obj/Linux/IntHash.o new file mode 100644 index 0000000..d931fed Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/IntHash.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/ServerHandler.o b/extensions/cdevGenericServer/lib/.obj/Linux/ServerHandler.o new file mode 100644 index 0000000..63eca0f Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/ServerHandler.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/ServerInterface.o b/extensions/cdevGenericServer/lib/.obj/Linux/ServerInterface.o new file mode 100644 index 0000000..04c2408 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/ServerInterface.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/SignalManager.o b/extensions/cdevGenericServer/lib/.obj/Linux/SignalManager.o new file mode 100644 index 0000000..516c8cf Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/SignalManager.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevAddr.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevAddr.o new file mode 100644 index 0000000..fd07978 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevAddr.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevClientRequestObject.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevClientRequestObject.o new file mode 100644 index 0000000..1b82228 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevClientRequestObject.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevClientService.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevClientService.o new file mode 100644 index 0000000..669ef25 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevClientService.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevContextMap.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevContextMap.o new file mode 100644 index 0000000..fe02a5e Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevContextMap.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevEventHandler.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevEventHandler.o new file mode 100644 index 0000000..5277b62 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevEventHandler.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevHandleSet.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevHandleSet.o new file mode 100644 index 0000000..4bb048f Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevHandleSet.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevMessage.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevMessage.o new file mode 100644 index 0000000..6bf3201 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevMessage.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevMessageBinary.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevMessageBinary.o new file mode 100644 index 0000000..63d42ef Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevMessageBinary.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevMonitorTable.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevMonitorTable.o new file mode 100644 index 0000000..0d5d702 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevMonitorTable.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevPacket.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevPacket.o new file mode 100644 index 0000000..66bd44c Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevPacket.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevReactor.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevReactor.o new file mode 100644 index 0000000..486c837 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevReactor.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevServer.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevServer.o new file mode 100644 index 0000000..9e264e6 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevServer.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevServerTools.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevServerTools.o new file mode 100644 index 0000000..61920c2 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevServerTools.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevSessionManager.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevSessionManager.o new file mode 100644 index 0000000..d2be965 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevSessionManager.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevSocket.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevSocket.o new file mode 100644 index 0000000..0b7bf50 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevSocket.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevSocketAcceptor.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevSocketAcceptor.o new file mode 100644 index 0000000..ebdecb6 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevSocketAcceptor.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevSocketConnector.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevSocketConnector.o new file mode 100644 index 0000000..b95362f Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevSocketConnector.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevSocketDatagram.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevSocketDatagram.o new file mode 100644 index 0000000..fadc3d1 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevSocketDatagram.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevSocketStream.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevSocketStream.o new file mode 100644 index 0000000..fd67049 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevSocketStream.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevStreamNode.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevStreamNode.o new file mode 100644 index 0000000..8fc5fef Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevStreamNode.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevStreamQueue.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevStreamQueue.o new file mode 100644 index 0000000..ce3d5fe Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevStreamQueue.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevTagMap.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevTagMap.o new file mode 100644 index 0000000..b6d6e97 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevTagMap.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/cdevTime.o b/extensions/cdevGenericServer/lib/.obj/Linux/cdevTime.o new file mode 100644 index 0000000..8f94149 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/cdevTime.o differ diff --git a/extensions/cdevGenericServer/lib/.obj/Linux/fifo.o b/extensions/cdevGenericServer/lib/.obj/Linux/fifo.o new file mode 100644 index 0000000..49d129a Binary files /dev/null and b/extensions/cdevGenericServer/lib/.obj/Linux/fifo.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/ClientAcceptor.o b/extensions/cdevGenericServer/lib/.shobj/Linux/ClientAcceptor.o new file mode 100644 index 0000000..bb0901e Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/ClientAcceptor.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/ClientHandler.o b/extensions/cdevGenericServer/lib/.shobj/Linux/ClientHandler.o new file mode 100644 index 0000000..1f0b2b4 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/ClientHandler.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/IntHash.o b/extensions/cdevGenericServer/lib/.shobj/Linux/IntHash.o new file mode 100644 index 0000000..98dc63d Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/IntHash.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/ServerHandler.o b/extensions/cdevGenericServer/lib/.shobj/Linux/ServerHandler.o new file mode 100644 index 0000000..e8c6790 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/ServerHandler.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/ServerInterface.o b/extensions/cdevGenericServer/lib/.shobj/Linux/ServerInterface.o new file mode 100644 index 0000000..c666055 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/ServerInterface.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/SignalManager.o b/extensions/cdevGenericServer/lib/.shobj/Linux/SignalManager.o new file mode 100644 index 0000000..5efb17a Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/SignalManager.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevAddr.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevAddr.o new file mode 100644 index 0000000..3685551 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevAddr.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevClientRequestObject.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevClientRequestObject.o new file mode 100644 index 0000000..22e1fa1 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevClientRequestObject.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevClientService.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevClientService.o new file mode 100644 index 0000000..9f9a064 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevClientService.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevContextMap.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevContextMap.o new file mode 100644 index 0000000..1cd05e3 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevContextMap.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevEventHandler.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevEventHandler.o new file mode 100644 index 0000000..8e0f594 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevEventHandler.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevHandleSet.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevHandleSet.o new file mode 100644 index 0000000..d25aac2 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevHandleSet.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevMessage.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevMessage.o new file mode 100644 index 0000000..91561da Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevMessage.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevMessageBinary.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevMessageBinary.o new file mode 100644 index 0000000..6e0c780 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevMessageBinary.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevMonitorTable.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevMonitorTable.o new file mode 100644 index 0000000..61d49ed Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevMonitorTable.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevPacket.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevPacket.o new file mode 100644 index 0000000..2c52741 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevPacket.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevReactor.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevReactor.o new file mode 100644 index 0000000..f47d089 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevReactor.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevServer.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevServer.o new file mode 100644 index 0000000..6e0ad17 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevServer.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevServerTools.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevServerTools.o new file mode 100644 index 0000000..1b782ab Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevServerTools.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSessionManager.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSessionManager.o new file mode 100644 index 0000000..e293c96 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSessionManager.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSocket.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSocket.o new file mode 100644 index 0000000..2259c3d Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSocket.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSocketAcceptor.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSocketAcceptor.o new file mode 100644 index 0000000..4b917ea Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSocketAcceptor.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSocketConnector.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSocketConnector.o new file mode 100644 index 0000000..280fc5a Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSocketConnector.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSocketDatagram.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSocketDatagram.o new file mode 100644 index 0000000..fc5f39b Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSocketDatagram.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSocketStream.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSocketStream.o new file mode 100644 index 0000000..05daec5 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevSocketStream.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevStreamNode.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevStreamNode.o new file mode 100644 index 0000000..20e651c Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevStreamNode.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevStreamQueue.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevStreamQueue.o new file mode 100644 index 0000000..ccdd043 Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevStreamQueue.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevTagMap.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevTagMap.o new file mode 100644 index 0000000..670764a Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevTagMap.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/cdevTime.o b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevTime.o new file mode 100644 index 0000000..305ae8b Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/cdevTime.o differ diff --git a/extensions/cdevGenericServer/lib/.shobj/Linux/fifo.o b/extensions/cdevGenericServer/lib/.shobj/Linux/fifo.o new file mode 100644 index 0000000..49d129a Binary files /dev/null and b/extensions/cdevGenericServer/lib/.shobj/Linux/fifo.o differ diff --git a/extensions/cdevGenericServer/lib/ClientAcceptor.cc b/extensions/cdevGenericServer/lib/ClientAcceptor.cc new file mode 100755 index 0000000..b858e90 --- /dev/null +++ b/extensions/cdevGenericServer/lib/ClientAcceptor.cc @@ -0,0 +1,87 @@ +#include "ClientAcceptor.h" +#include "ClientHandler.h" + +// ***************************************************************************** +// * ClientAcceptor: +// * Default constructor for the ClientAcceptor class +// ***************************************************************************** +ClientAcceptor::ClientAcceptor (cdevSessionManager & s) + : server(s) + { + } + + +// ***************************************************************************** +// * ClientAcceptor::~ClientAcceptor: +// * Destructor for the ClientAcceptor class +// ***************************************************************************** +ClientAcceptor::~ClientAcceptor (void) + { + if(reactor) reactor->extractHandler(this); + handleClose(); + } + +// ***************************************************************************** +// * open: +// * Initializes the listening socket +// ***************************************************************************** +int ClientAcceptor::open (const cdevInetAddr &addr) + { + int result = -1; + if (this->acceptor.open (addr, TRUE) == -1) + { + outputError(CDEV_SEVERITY_SEVERE, (char *)getName(), + "Failed to open listening port"); + } + else if (acceptor.setFlags (O_NONBLOCK) == -1) + { + outputError(CDEV_SEVERITY_ERROR, (char *)getName(), + "Could not enable non-blocking I/O"); + } + else result = 0; + return result; + } + +// ***************************************************************************** +// * getHandle: +// * Returns the device descriptor of the listening socket +// ***************************************************************************** +int ClientAcceptor::getHandle (void) const + { + return acceptor.getHandle (); + } + +// ***************************************************************************** +// * handleInput: +// * Accepts a connection on a listening socket and then creates a +// * ClientHandler class to manage the connection. +// ***************************************************************************** +int ClientAcceptor::handleInput (void) + { + cdevInetAddr addr; + ClientHandler *svc_handler = new ClientHandler(server); + if (acceptor.accept (*svc_handler, &addr) != -1) + { + svc_handler->open(this); + } + else + { + outputError(CDEV_SEVERITY_ERROR, (char *)getName(), + "Failed to accept connection"); + } + // ********************************************************************* + // * Always return 0... Otherwise, the accepting socket will + // * be destroyed and a crippled server is all that will remain. + // ********************************************************************* + return 0; + } + +// ***************************************************************************** +// * handleClose: +// * Closes the listening socket +// ***************************************************************************** +int ClientAcceptor::handleClose (void) + { + acceptor.close (); + return 0; + } diff --git a/extensions/cdevGenericServer/lib/ClientHandler.cc b/extensions/cdevGenericServer/lib/ClientHandler.cc new file mode 100755 index 0000000..cbb6607 --- /dev/null +++ b/extensions/cdevGenericServer/lib/ClientHandler.cc @@ -0,0 +1,268 @@ +#include "ClientHandler.h" +#include "ClientAcceptor.h" +#include + +// ***************************************************************************** +// * ClientHandler: +// * Default constructor for the ClientHandler class +// ***************************************************************************** +ClientHandler::ClientHandler (cdevSessionManager & s) + : server(s), queue(NULL), clientQuitFlag(0), + SocketReader(CLIP_MAGIC_NUMBER), SocketWriter(CLIP_MAGIC_NUMBER), + packetsSent(0), packetsRecv(0) + { + hostName[0] = 0; + } + +// ***************************************************************************** +// * ClientHandler::getHostName: +// * This function returns the name of the remote host. +// ***************************************************************************** +char * ClientHandler::getHostName( void ) + { + if(*hostName==0) + { + cdevInetAddr addr; + if(stream.getRemoteAddress (addr)==0) + { + const char * ptr=addr.getHostName(); + if(ptr) strncpy (hostName, ptr, MAXHOSTNAMELEN+1); + } + } + return hostName; + } + +// ***************************************************************************** +// * open: +// * Initializes the new socket and adds this ClientHandler class to +// * the reactor +// ***************************************************************************** +int ClientHandler::open (class ClientAcceptor * ) + { + cdevInetAddr addr; + int result = 0; + + if (stream.getRemoteAddress (addr) == -1) + { + outputError(CDEV_SEVERITY_SEVERE, (char *)getName(), + "Couldn't get local address"); + result = -1; + } + else + { + if (server.Reactor.registerHandler (this, READ_MASK|WRITE_MASK|EXCEPT_MASK)!=0) + { + outputError(CDEV_SEVERITY_SEVERE, (char *)getName(), + "Cannot register handler with reactor"); + result = -1; + } + else { + // ***************************************************** + // * Get the socket number and use it to identify the + // * socket within the cdevSessionManager. + // ***************************************************** + int handle = getHandle(); + if((queue = server.findSocket(handle))!=NULL) + { + server.removeSocket(handle); + } + queue = server.addSocket(handle); + + outputError(CDEV_SEVERITY_INFO, (char *)getName(), + "Establishing connection to %s on socket %i", + getHostName(), handle); + } + } + return result; + } + +// ***************************************************************************** +// * getHandle: +// * Returns the device descriptor for the underlying socket +// ***************************************************************************** +int ClientHandler::getHandle (void) const + { + return stream.getHandle (); + } + +// ***************************************************************************** +// * ~ClientHandler: +// * Destructor for the ClientHandler object +// ***************************************************************************** +ClientHandler::~ClientHandler (void) + { + if(stream.getHandle()>0 && clientQuitFlag==0) writeGoodbye(); + if(reactor) reactor->extractHandler(this); + handleClose(); + } + +// ***************************************************************************** +// * handleClose: +// * Removes the object from the reactor class and then deletes it. +// ***************************************************************************** +int ClientHandler::handleClose (void) + { + outputError(CDEV_SEVERITY_INFO, (char *)getName(), + "Terminating connection to %s on socket %i", + getHostName(), queue?queue->getSocketID():0); + + stream.close(); + if(queue) + { + server.removeSocket(queue->getSocketID()); + queue = NULL; + } + return 0; + } + + +// ***************************************************************************** +// # handleInput : +// # This function is called when data is ready to be read from a connected +// # socket. This function will read the data from the socket, and will then +// # submit the buffer to the processIncomingPacket function for processing. +// ***************************************************************************** +int ClientHandler::handleInput (void) +{ +int retval = 0; +char * buf = NULL; +size_t len = 0; +int result = 1; + +// ***************************************************************************** +// * Record oriented semantics dictate that the length of the transmission +// * always preceeds the actual data. Therefore, read the length of the +// * transmission into the len variable. +// ***************************************************************************** +while(result>0) + { + if(buf==NULL) result = read(&buf, (int *)&len); + else result = readNextPacket(&buf, (int *)&len); + switch(result) + { + // ************************************************************* + // * A return value of SHUTDOWN_CODE indicates that a negative + // * one was provided as the packet length - indicating a + // * shutdown... + // ************************************************************* + case SHUTDOWN_CODE: + outputError(CDEV_SEVERITY_INFO, (char *)getName(), + "Connection to %s terminated by client", getHostName()); + retval = -1; + break; + + // ************************************************************* + // * A return value of -1 indicates an error occured while + // * reading from the socket. A value of -1 is returned to + // * shutdown the socket and remove it from the reactor. + // ************************************************************* + case -1: + outputError(CDEV_SEVERITY_WARN, (char *)getName(), + "Error reading from connection to client %s", getHostName()); + retval = -1; + break; + + // ************************************************************* + // * A return value of 0 means that no data was ready to be + // * retrieved from the socket. + // ************************************************************* + case 0: + break; + + // ************************************************************* + // * Any other value returned from the socket represents the + // * number of bytes actually read into the local buffer object. + // ************************************************************* + default: + server.enqueue(getHandle(), buf, len); + packetsSent++; + break; + } + } + +// ***************************************************************************** +// * Return the value specified by retval. +// ***************************************************************************** +return retval; +} + + +// ***************************************************************************** +// # handleOutput : +// # This function is called when data is ready to be transmitted to a +// # connected socket. This function will read the data from the queue, +// # translate it to XDR, and then transmit it to the client. +// ***************************************************************************** +int ClientHandler::handleOutput (void) +{ +int retval = 0; +char * buf = NULL; +size_t len = 0; + +// ***************************************************************************** +// * Attempt to transmit or continue transmitting the data. Note, the peek +// * method is used to attempt to writeEnqueue a data item without actually +// * removing it from the outbound queue. If the item can be writeEnqueued, +// * then the dequeue method is called to remove it from the queue... +// * This method is repeated until the output buffer is fully populated. +// ***************************************************************************** +if(!writing() && queue!=NULL && queue->peek(&buf, &len)==0) + { + int full = 0; + while(!full) + { + full = writeEnqueue(buf, len); + if(!full) + { + queue->dequeue(&buf, &len); + delete buf; + buf = NULL; + len = 0; + if(queue->peek(&buf, &len)!=0) full=-1; + packetsRecv++; + } + } + if(writeContinue()<0) retval = -1; + } +else if(writing()) + { + if(writeContinue()<0) retval = -1; + } + +// ***************************************************************************** +// * Display an error message if the transmission failed. +// ***************************************************************************** +if(retval!=0) + { + outputError(CDEV_SEVERITY_WARN, (char *)getName(), + "Error transmitting to %s", getHostName()); + } + +// ***************************************************************************** +// * If there are no further messages in the outbound queue and the +// * ACE_Event_Handler has finished servicing the current message, turn off the +// * WRITE_MASK for this ACE_Event_Handler. +// ***************************************************************************** +if(retval!=0 || ((queue==NULL || queue->empty()) && !writing())) + { + setMask(READ_MASK|EXCEPT_MASK); + } + +// ***************************************************************************** +// * Return the value specified by retval. +// ***************************************************************************** +return retval; +} + + +// ***************************************************************************** +// * ClientHandler::handleExcept : +// * This function is called when out of band data is ready to be received +// * from the socket. +// ***************************************************************************** +int ClientHandler::handleExcept(void) + { + clientQuitFlag=1; + return -1; + } + diff --git a/extensions/cdevGenericServer/lib/IntHash.cc b/extensions/cdevGenericServer/lib/IntHash.cc new file mode 100644 index 0000000..d81e314 --- /dev/null +++ b/extensions/cdevGenericServer/lib/IntHash.cc @@ -0,0 +1,13 @@ +#include + +IntHashNode::IntHashNode ( int HashInt, void * HashData) + : next(NULL) + { + hashInt = HashInt; + hashData = HashData; + } + +IntHashNode::~IntHashNode ( void ) + { + } + diff --git a/extensions/cdevGenericServer/lib/Linux/CLIPService.so b/extensions/cdevGenericServer/lib/Linux/CLIPService.so new file mode 100755 index 0000000..6193d0c Binary files /dev/null and b/extensions/cdevGenericServer/lib/Linux/CLIPService.so differ diff --git a/extensions/cdevGenericServer/lib/Linux/libcdevReactor.a b/extensions/cdevGenericServer/lib/Linux/libcdevReactor.a new file mode 100644 index 0000000..3c83c0d Binary files /dev/null and b/extensions/cdevGenericServer/lib/Linux/libcdevReactor.a differ diff --git a/extensions/cdevGenericServer/lib/Linux/libcdevReactor.so b/extensions/cdevGenericServer/lib/Linux/libcdevReactor.so new file mode 100755 index 0000000..a1a98a0 Binary files /dev/null and b/extensions/cdevGenericServer/lib/Linux/libcdevReactor.so differ diff --git a/extensions/cdevGenericServer/lib/Linux/librnsService.a b/extensions/cdevGenericServer/lib/Linux/librnsService.a new file mode 100644 index 0000000..3f732ac Binary files /dev/null and b/extensions/cdevGenericServer/lib/Linux/librnsService.a differ diff --git a/extensions/cdevGenericServer/lib/Linux/librsvc.a b/extensions/cdevGenericServer/lib/Linux/librsvc.a new file mode 100644 index 0000000..01aee62 Binary files /dev/null and b/extensions/cdevGenericServer/lib/Linux/librsvc.a differ diff --git a/extensions/cdevGenericServer/lib/Linux/librsvc.so b/extensions/cdevGenericServer/lib/Linux/librsvc.so new file mode 100755 index 0000000..bb68f2a Binary files /dev/null and b/extensions/cdevGenericServer/lib/Linux/librsvc.so differ diff --git a/extensions/cdevGenericServer/lib/Linux/rnsService.so b/extensions/cdevGenericServer/lib/Linux/rnsService.so new file mode 100755 index 0000000..1db1306 Binary files /dev/null and b/extensions/cdevGenericServer/lib/Linux/rnsService.so differ diff --git a/extensions/cdevGenericServer/lib/Makefile b/extensions/cdevGenericServer/lib/Makefile new file mode 100755 index 0000000..32db887 --- /dev/null +++ b/extensions/cdevGenericServer/lib/Makefile @@ -0,0 +1,148 @@ +ARCH = OS +SHOBJ = YES + +#include ../include/makeinclude/Makefile.$(ARCH) +include ../include/makeinclude/Makefile.linux + +APPNAME = "CDEV Generic Client/Server Engine" +TEMPLINKS = ClientAcceptor.cc\ + ClientHandler.cc\ + cdevServer.cc\ + cdevServerTools.cc\ + cdevSessionManager.cc\ + ServerInterface.cc\ + ServerHandler.cc\ + cdevClientRequestObject.cc\ + cdevClientService.cc\ + cdevMessage.cc\ + cdevMessageBinary.cc\ + cdevPacket.cc\ + cdevContextMap.cc\ + cdevMonitorTable.cc\ + cdevTagMap.cc\ + SignalManager.cc\ + cdevAddr.cc\ + cdevEventHandler.cc\ + cdevHandleSet.cc\ + cdevReactor.cc\ + cdevSocket.cc\ + cdevSocketAcceptor.cc\ + cdevSocketConnector.cc\ + cdevSocketDatagram.cc\ + cdevSocketStream.cc\ + cdevStreamNode.cc\ + cdevStreamQueue.cc\ + cdevTime.cc\ + fifo.cc\ + IntHash.cc + + +LIBS = $(CDEVLIBS) $(OSLIBS) + +SERVER_OBJS = $(OBJDIR)/cdevServer.o\ + $(OBJDIR)/cdevServerTools.o\ + $(OBJDIR)/cdevSessionManager.o\ + $(OBJDIR)/ClientHandler.o\ + $(OBJDIR)/ClientAcceptor.o\ + $(OBJDIR)/cdevTagMap.o\ + $(OBJDIR)/cdevMonitorTable.o + +CLIENT_OBJS = $(OBJDIR)/cdevClientService.o\ + $(OBJDIR)/cdevClientRequestObject.o\ + $(OBJDIR)/ServerInterface.o\ + $(OBJDIR)/ServerHandler.o + +COMMON_OBJS = $(OBJDIR)/cdevPacket.o\ + $(OBJDIR)/cdevMessageBinary.o\ + $(OBJDIR)/cdevMessage.o\ + $(OBJDIR)/cdevContextMap.o\ + $(OBJDIR)/SignalManager.o\ + $(OBJDIR)/fifo.o\ + $(OBJDIR)/IntHash.o + +ACE_OBJS = $(OBJDIR)/cdevAddr.o\ + $(OBJDIR)/cdevEventHandler.o\ + $(OBJDIR)/cdevHandleSet.o\ + $(OBJDIR)/cdevReactor.o\ + $(OBJDIR)/cdevSocket.o\ + $(OBJDIR)/cdevSocketAcceptor.o\ + $(OBJDIR)/cdevSocketConnector.o\ + $(OBJDIR)/cdevSocketDatagram.o\ + $(OBJDIR)/cdevSocketStream.o\ + $(OBJDIR)/cdevStreamNode.o\ + $(OBJDIR)/cdevStreamQueue.o\ + $(OBJDIR)/cdevTime.o + +OBJS = $(SERVER_OBJS) $(CLIENT_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + +# ****************************************************************************** +# * The BINARIES definition names all of the binary files that should be deleted +# * whenever "make clean" is executed. +# ****************************************************************************** +BINARIES = $(CDEVLIB)/libcdevGenericServer.$(SHARED_EXT) \ + $(CDEVLIB)/libcdevGenericServer.a + +ifeq ($(SHOBJ),YES) + TARGETS = $(TEMPLINKS) \ + $(CDEVLIB)/libcdevGenericServer.$(SHARED_EXT) +else + TARGETS = $(TEMPLINKS) \ + $(CDEVLIB)/libcdevGenericServer.a +endif + +targets : $(TARGETS) + +$(TEMPLINKS) : + @cp $^ $@ + +$(CDEVLIB)/libcdevGenericServer.a : $(OBJS) + $(LINK.a) $@ $^ + @$(RANLIB) $@ > /dev/null + +$(CDEVLIB)/libcdevGenericServer.$(SHARED_EXT) : $(OBJS) + $(LINK.so) -o $@ $^ -L$(CDEVLIB) -lrsvc $(NETLIBS) + +$(CDEVLIB)/libcdevServer.a : $(SERVER_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + $(LINK.a) $@ $^ + @$(RANLIB) $@ > /dev/null + +$(CDEVLIB)/libcdevServer.$(SHARED_EXT) : $(SERVER_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + $(LINK.so) -o $@ $^ -L$(CDEVLIB) -lrsvc $(NETLIBS) + +$(CDEVLIB)/libcdevClient.a : $(CLIENT_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + $(LINK.a) $@ $^ + @$(RANLIB) $@ > /dev/null + +$(CDEVLIB)/libcdevClient.$(SHARED_EXT) : $(CLIENT_OBJS) $(COMMON_OBJS) $(ACE_OBJS) + $(LINK.so) -o $@ $^ -L$(CDEVLIB) -lrsvc $(NETLIBS) + +ClientAcceptor.cc : ../cdevServer/ClientAcceptor.cc +ClientHandler.cc : ../cdevServer/ClientHandler.cc +cdevServer.cc : ../cdevServer/cdevServer.cc +cdevServerTools.cc : ../cdevServer/cdevServerTools.cc +cdevSessionManager.cc : ../cdevServer/cdevSessionManager.cc +ServerHandler.cc : ../cdevClient/ServerHandler.cc +ServerInterface.cc : ../cdevClient/ServerInterface.cc +cdevClientRequestObject.cc : ../cdevClient/cdevClientRequestObject.cc +cdevClientService.cc : ../cdevClient/cdevClientService.cc +cdevMessage.cc : ../cdevPacket/cdevMessage.cc +cdevMessageBinary.cc : ../cdevPacket/cdevMessageBinary.cc +cdevPacket.cc : ../cdevPacket/cdevPacket.cc +cdevContextMap.cc : ../cdevContextMap/cdevContextMap.cc +cdevMonitorTable.cc : ../cdevMonitorTable/cdevMonitorTable.cc +cdevTagMap.cc : ../cdevTagMap/cdevTagMap.cc +SignalManager.cc : ../common/SignalManager.cc +cdevAddr.cc : ../cdevReactor/cdevAddr.cc +cdevEventHandler.cc : ../cdevReactor/cdevEventHandler.cc +cdevHandleSet.cc : ../cdevReactor/cdevHandleSet.cc +cdevReactor.cc : ../cdevReactor/cdevReactor.cc +cdevSocket.cc : ../cdevReactor/cdevSocket.cc +cdevSocketAcceptor.cc : ../cdevReactor/cdevSocketAcceptor.cc +cdevSocketConnector.cc : ../cdevReactor/cdevSocketConnector.cc +cdevSocketDatagram.cc : ../cdevReactor/cdevSocketDatagram.cc +cdevSocketStream.cc : ../cdevReactor/cdevSocketStream.cc +cdevStreamNode.cc : ../cdevReactor/cdevStreamNode.cc +cdevStreamQueue.cc : ../cdevReactor/cdevStreamQueue.cc +cdevTime.cc : ../cdevReactor/cdevTime.cc +fifo.cc : ../common/fifo.cc +IntHash.cc : ../common/IntHash.cc diff --git a/extensions/cdevGenericServer/lib/ServerHandler.cc b/extensions/cdevGenericServer/lib/ServerHandler.cc new file mode 100755 index 0000000..2461bd5 --- /dev/null +++ b/extensions/cdevGenericServer/lib/ServerHandler.cc @@ -0,0 +1,526 @@ +#include +#include +#include +#include +#include + +#define _CDEV_CONNECTION_RETRIES 5 + +SignalManager ServerHandler::signalManager; +int ServerHandler::signalManagerInit = 0; + +// ***************************************************************************** +// * ServerHandlerCallbackNode: +// * This is a node of a linked list that isolates the ServerHandlerCallback +// * object from inadverntently being corrupted by being placed in more +// * than one ServerHandler object. +// * +// * The ALLOCATION_COUNT of 128 forces the allocation of blocks that are +// * close to 1 kilobyte in size. +// ***************************************************************************** +class ServerHandlerCallbackNode +{ +friend class ServerHandler; +private: + static ServerHandlerCallbackNode * freeList_; + ServerHandlerCallbackNode * next; + ServerHandlerCallback * callback; + enum { ALLOCATION_COUNT=128 }; + + ServerHandlerCallbackNode ( void ); +public: + ServerHandlerCallbackNode ( ServerHandlerCallback * Callback ); + ~ServerHandlerCallbackNode( void ); + void * operator new ( size_t ); + void operator delete ( void * ptr ); +}; + +ServerHandlerCallbackNode * ServerHandlerCallbackNode::freeList_; + +// ***************************************************************************** +// * ServerHandler::ServerHandler +// * Default constructor for the ServerHandler class +// ***************************************************************************** +ServerHandler::ServerHandler ( char * Server, ServerInterface * Interface ) + : SocketReader(CLIP_MAGIC_NUMBER), SocketWriter(CLIP_MAGIC_NUMBER), + queue(*(Interface->getQueue(Server))), serverface(Interface), callbacks(NULL), + enqueuedPackets(0), enqueuedBytes(0), clientID(-1), contextID(-1), + tagChanged(1), serverQuitFlag(0) + { + strncpy(server, Server, 256); + server[255] = 0; + hostName[0] = 0; + clientID = getNextClientID(); + + if(!signalManagerInit) signalManager.installDefaults(); + + // ********************************************************************* + // * If any data exists in the queue for this server, walk through each + // * entry and determine if it is valid - if so, reenqueue it, + // * otherwise, delete it. + // ********************************************************************* + if(!queue.empty()) + { + FifoQueue tempQueue; + char * binary; + size_t len; + while(queue.dequeue(&binary, &len)==0) + { + if(serverface->isPacketValid(binary, len)) + { + tempQueue.enqueue(binary, len); + } + else delete binary; + } + while(tempQueue.dequeue(&binary, &len)==0) + { + enqueue(binary, len); + } + } + } + +// ***************************************************************************** +// * ServerHandler::outputError : +// * This mechanism is used to report errors to the system. +// ***************************************************************************** +int ServerHandler::outputError(int severity, char *name, char *formatString, ...) + { + va_list argp; + static char msg[1024]; + + va_start (argp, formatString); + vsprintf (msg, formatString, argp); + va_end (argp); + + return serverface->outputError(severity, name, msg); + } + +// ***************************************************************************** +// * open: +// * Established a connection with the host specified by remote_sap +// ***************************************************************************** +int ServerHandler::open ( const cdevAddr & addr ) + { + int result = 0; + int count = 0; + + result = stream.connect (addr); + + if (result != -1) + { + if((result = serverface->Reactor.registerHandler(this, READ_MASK|WRITE_MASK|EXCEPT_MASK))==-1) + { + handleClose(); + } + } + return result; + } + + +// ***************************************************************************** +// * ~ServerHandler: +// * Default destructor for the ServerHandler object. +// ***************************************************************************** +ServerHandler::~ServerHandler (void) + { + ServerHandlerCallbackNode * cb = callbacks; + + // ********************************************************************* + // * Write a -1 as the packetLength to the connection in order to + // * terminate. + // ********************************************************************* + if(stream.getHandle()>0 && serverQuitFlag==0) + { + #ifndef _WIN32 + void (*action)(int) = signal(SIGPIPE, SIG_IGN); + #endif + + writeGoodbye(); + + #ifndef _WIN32 + signal(SIGPIPE, action); + #endif + } + + // ********************************************************************* + // * Contact all of the objects that rely on the existance of this + // * class. + // ********************************************************************* + while(cb!=NULL) + { + ServerHandlerCallbackNode * oldCB = cb; + cb = cb->next; + oldCB->callback->executeServerHandlerCallback(this); + delete oldCB; + } + + // ********************************************************************* + // * Perform standard shutdown steps. + // ********************************************************************* + if(reactor) reactor->extractHandler(this); + handleClose(); + } + + +// ***************************************************************************** +// * ServerHandler::getHostName: +// * This function returns the name of the remote host. +// ***************************************************************************** +char * ServerHandler::getHostName( void ) + { + if(*hostName==0) + { + cdevInetAddr addr; + if(stream.getRemoteAddress (addr)==0) + { + const char * ptr=addr.getHostName(); + if(ptr) strncpy (hostName, ptr, MAXHOSTNAMELEN+1); + } + } + return hostName; + } + +// ***************************************************************************** +// * ServerHandler::getName : +// * Allows the caller to obtain the name of the class. +// ***************************************************************************** +char * ServerHandler::getName (void) const + { + return "ServerHandler"; + } + + +// ***************************************************************************** +// * ServerHandler::getHandle +// * Allows the caller to obtain the file identifier of the socket. +// ***************************************************************************** +int ServerHandler::getHandle (void) const + { + return stream.getHandle(); + } + + + +// ***************************************************************************** +// * ServerHandler::getServer: +// * Allows the caller to obtain the name of the connected server. +// ***************************************************************************** +char * ServerHandler::getServer (void) const + { + return (char *)server; + } + + +// ***************************************************************************** +// * handleClose: +// * Closes the stream. +// ***************************************************************************** +int ServerHandler::handleClose (void) + { + serverface->disconnect(server); + stream.close(); + return 0; + } + + +// ***************************************************************************** +// * handleInput : +// * This function is called when data is ready to be read from a connected +// * socket. This function will read the data from the socket, and will then +// * submit the buffer to the ServerInterface class for processing. +// ***************************************************************************** +int ServerHandler::handleInput (void) +{ +int retval = 0; +char * buf = NULL; +size_t len = 0; +int result = 1; + +// ***************************************************************************** +// * Record oriented semantics dictate that the length of the transmission +// * always preceeds the actual data. Therefore, read the length of the +// * transmission into the len variable. +// ***************************************************************************** +while(result>0) + { + result = read(&buf, (int *)&len); + + switch(result) + { + // ************************************************************* + // * A return value of SHUTDOWN_CODE indicates that a negative + // * one was provided as the packet length - indicating a + // * shutdown... + // ************************************************************* + case SHUTDOWN_CODE: + outputError(CDEV_SEVERITY_INFO, (char *)getName(), + "Connection to %s terminated by client", getHostName()); + retval = -1; + break; + + // ************************************************************* + // * A return value of -1 indicates an error occured while + // * reading from the socket. A value of -1 is returned to + // * shutdown the socket and remove it from the reactor. + // ************************************************************* + case -1: + outputError(CDEV_SEVERITY_WARN, (char *)getName(), + "Error reading from connection to client %s", getHostName()); + retval = -1; + break; + + // ************************************************************* + // * A return value of 0 means that no data was ready to be + // * retrieved from the socket. + // ************************************************************* + case 0: + break; + + // ************************************************************* + // * Any other value returned from the socket represents the + // * number of bytes actually read into the local Session object. + // ************************************************************* + default: + serverface->enqueue(ServerInterface::COMPLETED, this, buf, len); + break; + } + } + +// ***************************************************************************** +// * Return the value specified by retval. +// ***************************************************************************** +return retval; +} + + + +// ***************************************************************************** +// * handleOutput : +// * This function is called when data is ready to be transmitted to a +// * connected socket. This function will read the data from the queue, +// * translate it to XDR, and then transmit it to the client. +// ***************************************************************************** +int ServerHandler::handleOutput ( void ) +{ +int retval = 0; +char * buf = NULL; +size_t len = 0; + +// ***************************************************************************** +// * Attempt to transmit or continue transmitting the data. Note, the peek +// * method is used to attempt to writeEnqueue a data item without actually +// * removing it from the outbound queue. If the item can be writeEnqueued, +// * then the dequeue method is called to remove it from the queue... +// * This method is repeated until the output buffer is fully populated. +// ***************************************************************************** +if(!writing() && dequeue(&buf, &len)==0) + { + int full = 0; + while(!full) + { + if(!(full = writeEnqueue(buf, len))) + { + delete buf; + full = dequeue(&buf, &len); + } + else undequeue(buf, len); + } + if(writeContinue()<0) retval = -1; + } +else if(writing()) + { + if(writeContinue()<0) retval = -1; + } + +// ***************************************************************************** +// * Display an error message if the transmission failed. +// ***************************************************************************** +if(retval!=0) + { + outputError(CDEV_SEVERITY_WARN, (char *)getName(), + "Error transmitting to %s", getHostName()); + } + +// ***************************************************************************** +// * If there are no further messages in the outbound queue and the +// * ACE_Event_Handler has finished servicing the current message, turn off the +// * WRITE_MASK for this ACE_Event_Handler. +// ***************************************************************************** +if(empty() && !writing()) + { + setMask(READ_MASK|EXCEPT_MASK); + } + +// ***************************************************************************** +// * Return the value specified by retval. +// ***************************************************************************** +return retval; +} + + +// ***************************************************************************** +// * handleExcept : +// * This function is called when out of band data has been received from +// * the server. It will terminate the connection with the server. +// ***************************************************************************** +int ServerHandler::handleExcept ( void ) + { + stream.close(); + serverQuitFlag=1; + return -1; + } + + +// ***************************************************************************** +// * registerServerCallback : +// * This method is called to add a ServerHandlerCallback object to the list +// * of objects that the ServerHandler will notify when it is destroyed... +// * This notification process protects objects that use this class for +// * communications from using a pointer to a ServerHandler that has been +// * deleted. +// ***************************************************************************** +void ServerHandler::registerServerCallback(ServerHandlerCallback * cb) + { + ServerHandlerCallbackNode *cbPrev=NULL, *cbNext=callbacks; + + while(cbNext!=NULL && cbNext->callback!=cb) + { + cbPrev = cbNext; + cbNext = cbNext->next; + } + if(cbNext==NULL) + { + if(cbPrev==NULL) callbacks = new ServerHandlerCallbackNode(cb); + else cbPrev->next = new ServerHandlerCallbackNode(cb); + } + } + +// ***************************************************************************** +// * unregisterServerCallback : +// * This method is used to remove a ServerHandlerCallback object from the +// * list of objects that will be notified when the ServerHandler object +// * is destroyed. +// ***************************************************************************** +void ServerHandler::unregisterServerCallback (ServerHandlerCallback * cb) + { + ServerHandlerCallbackNode *cbPrev=NULL, *cbNext=callbacks; + + while(cbNext!=NULL && cbNext->callback!=cb) + { + cbPrev = cbNext; + cbNext = cbNext->next; + } + if(cbNext->callback==cb) + { + if(cbPrev==NULL) callbacks = cbNext->next; + else cbPrev->next = cbNext->next; + delete cbNext; + } + } + + +// ***************************************************************************** +// * enqueue : +// * This method places an object into the embedded FifoQueue and will force +// * a flush of the socket if it reaches the high water mark. +// ***************************************************************************** +void ServerHandler::enqueue (char * buf, size_t len) + { + enqueuedPackets++; + enqueuedBytes+=len; + queue.enqueue(buf, len); + if(enqueuedPackets>100 || enqueuedBytes>16000) + { + serverface->flush(getHandle()); + enqueuedPackets=0; + enqueuedBytes=0; + } + } + + +// ***************************************************************************** +// * ServerHandler::getNextClientID : +// * This method allows the caller to retrieve a unique clientID to be +// * assigned to a client. The nextClientID value is automatically +// * incremented. +// ***************************************************************************** +short ServerHandler::getNextClientID ( void ) + { + static short nextClientID = 0; + + nextClientID++; + if(nextClientID<=0) nextClientID = 1; + return nextClientID; + } + + +// ***************************************************************************** +// * ServerHandlerCallbackNode::ServerHandlerCallbackNode : +// * Default constructor for the ServerHandlerCallbackNode class. +// ***************************************************************************** +ServerHandlerCallbackNode::ServerHandlerCallbackNode ( void ) + : callback(NULL), next(NULL) + { + } + + +// ***************************************************************************** +// * ServerHandlerCallbackNode::ServerHandlerCallbackNode : +// * Parameterized constructor for the ServerHandlerCallbackNode class. +// ***************************************************************************** +ServerHandlerCallbackNode::ServerHandlerCallbackNode( ServerHandlerCallback * Callback ) + : callback(Callback), next(NULL) + { + } + + +// ***************************************************************************** +// * ServerHandlerCallbackNode::~ServerHandlerCallbackNode : +// * Destructor for the ServerHandlerCallbackNode class. +// ***************************************************************************** +ServerHandlerCallbackNode::~ServerHandlerCallbackNode( void ) + { + } + + +// ***************************************************************************** +// * ServerHandlerCallbackNode::operator new : +// * Gets a ServerHandlerCallbackNode instance from the freelist. +// ***************************************************************************** +void * ServerHandlerCallbackNode::operator new ( size_t ) + { + ServerHandlerCallbackNode * result = NULL; + + if(freeList_==NULL) + { + freeList_ = ::new ServerHandlerCallbackNode[ALLOCATION_COUNT]; + for(int i=0; inext; + result->next = NULL; + } + return result; + } + + +// ***************************************************************************** +// * ServerHandlerCallbackNode::operator delete : +// * Returns a ServerHandlerCallbackNode instance to the freelist. +// ***************************************************************************** +void ServerHandlerCallbackNode::operator delete ( void * ptr ) + { + ServerHandlerCallbackNode * node = (ServerHandlerCallbackNode *)ptr; + if(node != NULL) + { + node->next = freeList_; + freeList_ = node; + } + } + diff --git a/extensions/cdevGenericServer/lib/ServerInterface.cc b/extensions/cdevGenericServer/lib/ServerInterface.cc new file mode 100755 index 0000000..76f9525 --- /dev/null +++ b/extensions/cdevGenericServer/lib/ServerInterface.cc @@ -0,0 +1,506 @@ +#include "cdevClock.h" +#include "ServerInterface.h" + +cdevReactor ServerInterface::Reactor; + +// ***************************************************************************** +// * ServerConnectionList::ServerConnectionList : +// * Constructor for the list of active connections that is being managed +// * by the ServerHandler. +// ***************************************************************************** +ServerConnectionList::ServerConnectionList ( void ) + { + maxItems = ALLOCATION_COUNT; + items = (ServerHandler **)malloc(maxItems*sizeof(ServerHandler *)); + memset(items, 0, maxItems*sizeof(ServerHandler *)); + } + + +// ***************************************************************************** +// * ServerConnectionList::~ServerConnectionList : +// * Destructor for the list of active connections that is being managed +// * by the ServerHandler. +// ***************************************************************************** +ServerConnectionList::~ServerConnectionList ( void ) + { + free (items); + } + +// ***************************************************************************** +// * ServerConnectionList::find : +// * Locates a ServerHandler object that is associated with the specified +// * server name. +// ***************************************************************************** +ServerHandler * ServerConnectionList::find ( char * server ) + { + int i; + for(i=0; + igetServer()); + i++); + return (igetServer(); + for(i=0; + igetServer()); + i++); + + if(i>=maxItems) + { + items = (ServerHandler **) realloc(items, 2*maxItems*sizeof(ServerHandler *)); + memset(&items[maxItems], 0, maxItems*sizeof(ServerHandler *)); + maxItems*=2; + } + + if(items[i]==NULL) + { + items[i] = handler; + result = 0; + } + } + return result; + } + + +// ***************************************************************************** +// * ServerConnectionList::remove : +// * Removes the ServerHandler object specified by handler if it exists in +// * list. +// ***************************************************************************** +int ServerConnectionList::remove ( ServerHandler * handler ) + { + int result = -1; + if(handler!=NULL) + { + int i; + for(i=0; idequeue(&buf, &len)==0) delete buf; + connections.remove(handler); + delete handler; + } + + // ********************************************************************* + // * Iterate through the queues associated with servers and remove + // * all messages that have not been transmitted. + // ********************************************************************* + StringHashIterator iter(&connectionQueues); + iter.first(); + while((buf = iter.key())!=NULL) + { + FifoQueue * queue = (FifoQueue *)iter.data(); + connectionQueues.remove(buf); + while(queue->dequeue(&buf, &len)==0) delete buf; + delete queue; + iter.first(); + } + } + + +// ***************************************************************************** +// * ServerInterface::getDefault : +// * This method allows the caller to obtain a pointer to the name of the +// * default server. +// ***************************************************************************** +char * ServerInterface::getDefault ( void ) + { + return defaultServer; + } + + +// ***************************************************************************** +// * ServerInterface::setDefault : +// * This method allows the caller to set the name of the default server. +// ***************************************************************************** +void ServerInterface::setDefault ( char * Default ) + { + if(defaultServer!=NULL) + { + delete defaultServer; + defaultServer = NULL; + defaultServerHandler = NULL; + } + if(Default!=NULL && *Default) + { + defaultServer = strdup(Default); + defaultServerHandler = connect(defaultServer); + } + } + + +// ***************************************************************************** +// * ServerInterface::connect : +// * This is a stub method that should be overridden by the developer in +// * a child class. +// ***************************************************************************** +ServerHandler * ServerInterface::connect ( char *, char *, unsigned short ) + { + return NULL; + } + +// ***************************************************************************** +// * ServerInterface::disconnect : +// * This is a stub method that should be overridden by the developer in +// * a child class. +// ***************************************************************************** +ServerHandler * ServerInterface::disconnect ( char * ) + { + return NULL; + } + +// ***************************************************************************** +// * ServerInterface::enqueue : +// * This enqueue mechanism is called by the client if they have already +// * identified the server that they wish to communicate with and have +// * obtained a pointer to its ServerHandler object. +// * +// * If the specified server handler is NULL then the message will be +// * submitted to the default server. +// ***************************************************************************** +int ServerInterface::enqueue( ServerHandler * handler, char * binary, size_t binaryLen ) + { + int result; + + if(handler!=NULL || (handler=defaultServerHandler)!=NULL || + (defaultServer!=NULL && (handler=(defaultServerHandler=connect(defaultServer)))!=NULL)) + { + handler->enqueue(binary, binaryLen); + result = CDEV_SUCCESS; + } + else + { + outputError(CDEV_SEVERITY_ERROR, + "ServerInterface::enqueue", + "No default server has been specified"); + result = CDEV_ERROR; + } + return result; + } + + +// ***************************************************************************** +// * ServerInterface::getQueue : +// * This method allows the caller to obtain a pointer to the FifoQueue +// * associated with a specific server. This queue is then attached to +// * the ServerHandler that is connected to that server. +// ***************************************************************************** +FifoQueue * ServerInterface::getQueue ( char * server ) + { + FifoQueue * queue = (FifoQueue *)connectionQueues.find(server); + if(queue==NULL) + { + queue=new FifoQueue; + connectionQueues.insert(server, (void *)queue); + } + return queue; + } + + +// ***************************************************************************** +// * ServerInterface::isPacketValid : +// * This method is called by the ServerHandler after it has been restarted. +// * If the ServerHandler inherits packets that are already in the queue, it +// * will call this method for each pcket in order to determine if they are +// * valid. If the packets are no longer valid (i.e., there is no longer +// * a cdevTransObj associated with them, they will be deleted. Otherwise, +// * they will be submitted to the server. +// * +// * Because this functionality will be handled in a derived class, this +// * method will always return 1 to indicate that the packet is valid. +// ***************************************************************************** +int ServerInterface::isPacketValid ( char * binary, size_t binaryLen ) + { + return (binary!=NULL && binaryLen>0)?1:0; + } + +// ***************************************************************************** +// * ServerInterface::getFd : +// * This mechanism is used to obtain a list of the file descriptors that +// * are used by the ServerInterface. These file descriptors may then be +// * used for polling. +// ***************************************************************************** +int ServerInterface::getFd (int * &fd, int &numFd ) + { + int idx = 0; + + numFd = 0; + + while(connections[idx]!=NULL) + { + if((numFd+1)>maxFd) + { + maxFd*=2; + fdList = (int *)realloc(fdList, maxFd*sizeof(int)); + } + fdList[numFd++] = connections[idx++]->getHandle(); + } + + if(numFd) fd = fdList; + else fd = NULL; + + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * ServerInterface::flush : +// * This mechanism is used to flush all outbound buffers to their respective +// * servers. +// ***************************************************************************** +int ServerInterface::flush ( void ) + { + // ********************************************************************* + // * First - determine if there is any outbound data that needs to be + // * processed. Walk through the connectionQueue objects - which exist + // * even if the connection has been lost - and count up the number of + // * queues that are not empty. + // ********************************************************************* + StringHashIterator iter(&connectionQueues); + FifoQueue * queue = NULL; + int needsFlush = 0; + + // ********************************************************************* + // * Invoke a brief reactor.checkHandlers in order to cause any + // * dead ServerHandlers to be removed from the Reactor. Then + // * attempt to reattach to any ServerHandlers that have + // * outbound data. + // ********************************************************************* + char * server; + Reactor.checkHandlers(); + + for(iter.first(); (server=iter.key())!=NULL; iter++) + { + queue = (FifoQueue *)iter.data(); + if(queue && !queue->empty()) + { + needsFlush++; + connect(server); + } + } + + // ********************************************************************* + // * At this point he needsFlush variable will be non-zero if any of + // * the queues contain outbound data. The remainder of this code + // * only needs to be performed if this is the case. + // ********************************************************************* + if(needsFlush) + { + // ************************************************************* + // * Provide a maximum timeout value of 5 seconds. If the system + // * cannot be flushed in that amount of time - then an error or + // * a hang must exist on the other side. + // ************************************************************* + cdevTimeValue t(5.0); + cdevClock timer; + timer.schedule(NULL, t); + + // ************************************************************* + // * While there are sockets that have outbound data AND the + // * timer has not expired - process events. + // ************************************************************* + int idx = 0; + while(needsFlush && !timer.expired()) + { + needsFlush = 0; + for(idx=0; connections[idx]!=NULL; idx++) + { + if(!connections[idx]->empty()) + { + connections[idx]->setMask(cdevEventHandler::WRITE_MASK|cdevEventHandler::EXCEPT_MASK); + needsFlush++; + } + else connections[idx]->setMask(cdevEventHandler::READ_MASK|cdevEventHandler::EXCEPT_MASK); + } + if(needsFlush) Reactor.handleEvents(1.0, cdevReactor::UNTIL_EVENT); + } + + // ********************************************************************* + // * Walk through all of the ServerHandlers and restore them to + // * READ_MASK mode. + // ********************************************************************* + if(needsFlush) + { + for(idx=0; connections[idx]!=NULL; idx++) + { + connections[idx]->setMask(cdevEventHandler::READ_MASK|cdevEventHandler::EXCEPT_MASK); + } + } + } + + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * ServerInterface::flush : +// * This mechanism is used to flush all outbound buffers to their respective +// * servers. +// ***************************************************************************** +int ServerInterface::flush ( int fd ) + { + // ********************************************************************* + // * Walk through each item and locate the handler that needs to be + // * flushed. If the connection is located, then handle events until + // * it is empty. + // ********************************************************************* + int i; + for(i=0; connections[i]!=NULL && connections[i]->getHandle()!=fd; i++); + if(connections[i]!=NULL) + { + cdevTimeValue t(5.0); + cdevClock timer; + timer.schedule(NULL, t); + + connections[i]->setMask(cdevEventHandler::WRITE_MASK|cdevEventHandler::EXCEPT_MASK); + while(connections[i]!=NULL && !connections[i]->empty() && !timer.expired()) + { + Reactor.handleEvents(1.0, cdevReactor::UNTIL_EVENT); + } + // ************************************************************* + // * If an error occurs during the write, the ServerHandler may + // * have been deleted - therefore, check to ensure that the + // * connection is valid prior to restoring its mask. + // ************************************************************* + if(connections[i]!=NULL) + { + connections[i]->setMask(cdevEventHandler::READ_MASK|cdevEventHandler::EXCEPT_MASK); + } + } + + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * ServerInterface::pend : +// * Pends for the specified period of time. The int parameter is not used +// * in this implementation. In later designs it may be used to allow the +// * interface to pend on a specific file descriptor. +// ***************************************************************************** +int ServerInterface::pend ( double seconds, int ) + { + // ********************************************************************* + // * Test to determine if there are any ServerHandlers in operation. + // ********************************************************************* + if(connections[0]!=NULL) + { + // ************************************************************* + // * Flush outbound requests if necessary. + // ************************************************************* + flush(); + + // ************************************************************* + // * Handle events for the specified period. + // ************************************************************* + Reactor.handleEvents(seconds); + } + + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * ServerInterface::poll : +// * This method polls the cdevReactor to see if any events are ready to be +// * processed on any of the sockets. If events are ready, then they are +// * processed immediately - otherwise, the function returns immediately. +// ***************************************************************************** +int ServerInterface::poll ( void ) + { + // ********************************************************************* + // * Test to determine if there are any ServerHandlers in operation. + // ********************************************************************* + if(connections[0]!=NULL) + { + // ************************************************************* + // * Flush outbound requests if necessary. + // ************************************************************* + flush(); + + // ************************************************************* + // * Handle events for 0 seconds - effectively polling. + // ************************************************************* + Reactor.handleEvents(0.0001, cdevReactor::UNTIL_EVENT); + } + + return CDEV_SUCCESS; + } diff --git a/extensions/cdevGenericServer/lib/SignalManager.cc b/extensions/cdevGenericServer/lib/SignalManager.cc new file mode 100755 index 0000000..1c68328 --- /dev/null +++ b/extensions/cdevGenericServer/lib/SignalManager.cc @@ -0,0 +1,257 @@ +#include + +#ifdef __linux + +#ifndef SIGSYS +#define SIGSYS SIGUNUSED +#endif + +#endif + +// ***************************************************************************** +// * SignalManager::reporter : +// * This is the declaration for the error reporter. +// ***************************************************************************** +ErrorReporter SignalManager::reporter; + +// ***************************************************************************** +// * SignalHandler::SignalHandler : +// * This is the initializer for a SignalHandler class. It holds the +// * information needed to handle a single signal number. +// ***************************************************************************** +_SignalHandler_::_SignalHandler_ ( void ) + : signo(0), handler(NULL), oldHandler(NULL) + { + } + +// ***************************************************************************** +// * SignalHandler::~SignalHandler : +// * This is the destructor for the SignlaHandler class. It will call the +// * uninstall method to remove the handler that was imposed for the signal. +// ***************************************************************************** +_SignalHandler_::~_SignalHandler_ ( void ) + { + uninstall (); + } + +// ***************************************************************************** +// * SignalHandler::install : +// * This method will install the specified signal handler function on the +// * signal number specified by signo. The old handler will be preserved +// * for later restoration. +// ***************************************************************************** +void _SignalHandler_::install ( int newSigno, SignalHandlerFunc newHandler ) + { + // ********************************************************************* + // * If a local signal handler has already been installed on the + // * specified signal number, uninstall it before proceeding. + // ********************************************************************* + if(handler!=NULL && signo==newSigno) uninstall(); + + // ********************************************************************* + // * Setup the control variables. + // ********************************************************************* + signo = newSigno; + handler = newHandler; + + // ********************************************************************* + // * Install the new signal handler, preserving the old handler in the + // * oact sigaction structure. + // ********************************************************************* + oldHandler = signal(signo, handler); + } + +// ***************************************************************************** +// * SignalHandler::uninstall : +// * This method will remove a user specified signal handler and will restore +// * the previously installed handler. +// ***************************************************************************** +void _SignalHandler_::uninstall ( void ) + { + // ********************************************************************* + // * Check to see if the signal handler has been installed. If so, + // * call sigaction to confirm that the current signal handler is the + // * one that was installed. + // ********************************************************************* + if(signo!=0 && handler!=NULL) + { + SignalHandlerFunc current = signal(signo, SIG_DFL); + if(current==handler) signal(signo, oldHandler); + else signal(signo, current); + } + + signo = 0; + handler = NULL; + } + +// ***************************************************************************** +// * SignalManager::installHandler : +// * This method will install the specified signal handler. +// ***************************************************************************** +void SignalManager::installHandler (int signo, SignalHandlerFunc handler ) + { + if(signo>0 && signo<=MAXSIGNAL) signals[signo-1].install(signo, handler); + } + +// ***************************************************************************** +// * SignalManager::uninstallHandler : +// * This method will remove a signal handler that was previously installed. +// ***************************************************************************** +void SignalManager::uninstallHandler ( int signo ) + { + if(signo>0 && signo<=MAXSIGNAL) signals[signo-1].uninstall(); + } + +// ***************************************************************************** +// * SignalManager::installDefaults : +// * This method will install a default collection of signal handlers. +// ***************************************************************************** +void SignalManager::installDefaults ( void ) + { + static int sigList[] = + { + #if !defined (_WIN32) + SIGFPE, // Erroneous arithmetic operation. + SIGHUP, // Hangup. + SIGILL, // Illegal instruction. + SIGINT, // Terminal interrupt signal. + SIGPIPE, // Write on a socket with no one to read + SIGQUIT, // Terminal quit signal. + SIGSEGV, // Invalid memory reference. + SIGTERM, // Termination signal. + SIGBUS, // Bus error. + SIGSYS, // Bad system call. + #else + SIGABRT, // Process abort signal. + SIGFPE, // Erroneous arithmetic operation. + SIGILL, // Illegal instruction. + SIGINT, // Terminal interrupt signal. + SIGSEGV, // Invalid memory reference. + SIGTERM, // Termination signal. + #endif + 0 + }; + + for(int i=0; sigList[i]!=0; i++) installHandler(sigList[i], defaultHandler); + } + +// ***************************************************************************** +// * SignalManager::defaultHandler : +// * This is the default signal handler method. +// ***************************************************************************** +void SignalManager::defaultHandler( int signo ) + { + switch(signo) + { + // ************************************************************* + // * Process the interrupt signal by reporting it and exiting. + // ************************************************************* + case SIGINT: + reporter.outputError ( + CDEV_SEVERITY_INFO, + "Signal Manager", + "[SIGINT] Terminating at user's request"); + exit(0); + + // ************************************************************* + // * Process the terminate signal by reporting it and exiting. + // ************************************************************* + case SIGTERM: + reporter.outputError ( + CDEV_SEVERITY_INFO, + "Signal Manager", + "[SIGTERM] Terminating normally"); + exit(0); + + // ************************************************************* + // * Process abort signal by reporting the error and exiting. + // ************************************************************* + case SIGABRT: + reporter.outputError ( + CDEV_SEVERITY_SEVERE, + "Signal Manager", + "[SIGABRT] Application terminating due to abort signal"); + abort(); + + + // ************************************************************* + // * Process erroneous arithmetic operations by reporting them + // * and exiting. + // ************************************************************* + case SIGFPE: + reporter.outputError ( + CDEV_SEVERITY_SEVERE, + "Signal Manager", + "[SIGFPE] Floating point error - terminating\n"); + abort(); + + + // ************************************************************* + // * Process illegal instructions by reporting them and exiting. + // ************************************************************* + case SIGILL: + reporter.outputError ( + CDEV_SEVERITY_SEVERE, + "Signal Manager", + "[SIGILL] Illegal instruction"); + abort(); + + // ************************************************************* + // * Process the segmentation fault signal by reporting the + // * error and terminating. + // ************************************************************* + case SIGSEGV: + reporter.outputError ( + CDEV_SEVERITY_SEVERE, + "Signal Manager", + "[SIGSEGV] Segmentation fault"); + abort(); + +#if !defined(_WIN32) + // ************************************************************* + // * Report pipe errors, however, do not terminate. + // ************************************************************* + case SIGPIPE: + reporter.outputError ( + CDEV_SEVERITY_ERROR, + "Signal Manager", + "[SIGPIPE] Write on a pipe with no one to read it"); + errno = SIGPIPE; + break; + + // ************************************************************* + // * Process a bus error by reporting it and exiting. + // ************************************************************* + case SIGBUS: + reporter.outputError ( + CDEV_SEVERITY_SEVERE, + "Signal Manager", + "[SIGBUS] Bus error"); + abort(); + + // ************************************************************* + // * Process a bad system call by reporting it and exiting. + // ************************************************************* + case SIGSYS: + reporter.outputError ( + CDEV_SEVERITY_SEVERE, + "Signal Manager", + "[SIGSYS] Bad system call"); + abort(); + + // ************************************************************* + // * Ignore the following signals: + // * SIGHUP: hangup signal. + // * SIGQUIT: terminal quit signal + // * default: All other signals + // ************************************************************* + case SIGHUP: + case SIGQUIT: +#endif + + default: + break; + } + signal(signo, SignalManager::defaultHandler); + } + diff --git a/extensions/cdevGenericServer/lib/cdevAddr.cc b/extensions/cdevGenericServer/lib/cdevAddr.cc new file mode 100644 index 0000000..a623539 --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevAddr.cc @@ -0,0 +1,190 @@ +#include "cdevAddr.h" + +// ***************************************************************************** +// * cdevInetAddr::set : +// * Allows the caller to set the address using a port number and +// * internet address. +// ***************************************************************************** +int cdevInetAddr::set (unsigned short portnum, long ip_addr) + { + setType(AF_INET); + setSize(sizeof(inet_addr)); + inet_addr.sin_family = AF_INET; + inet_addr.sin_port = htons(portnum); + + if(ip_addr == INADDR_ANY) inet_addr.sin_addr.s_addr=INADDR_ANY; + else memcpy((void *)&inet_addr.sin_addr, + (void *)&ip_addr, + sizeof(inet_addr.sin_addr)); + return 0; + } + + +// ***************************************************************************** +// * cdevInetAddr::set : +// * Allows the caller to set the address using a port number and host name. +// ***************************************************************************** +int cdevInetAddr::set (unsigned short portnum, const char hostname[]) + { + hostent * server_info; + long addr; + int retval; + + setType(AF_INET); + setSize(sizeof(inet_addr)); + memset((void *)&inet_addr, 0, sizeof(inet_addr)); + + if(hostname==NULL || *hostname==0) + { + errno = EINVAL; + retval = -1; + } + else if((addr=::inet_addr(hostname))!=-1 || + ::strcmp(hostname, "255.255.255.255")==0) + { + retval = set(portnum, addr); + } + else if((server_info=::gethostbyname(hostname)) != 0) + { + ::memcpy((void *)&addr, (void *)server_info->h_addr, server_info->h_length); + retval = set(portnum, addr); + } + else retval = -1; + + return retval; + } + + +// ***************************************************************************** +// * cdevInetAddr::set : +// * Allows the caller to set the address using a sockaddr_in structure +// * and its length. +// ***************************************************************************** +int cdevInetAddr::set (const sockaddr_in *addr, int len) + { + setType(AF_INET); + setSize(len); + memcpy((void *)&inet_addr, (void *)addr, len); + return 0; + } + + +// ***************************************************************************** +// * cdevInetAddr::cdevInetAddr : +// * This constructor creates an empty address object. +// ***************************************************************************** +cdevInetAddr::cdevInetAddr ( void ) + : cdevAddr(AF_INET, sizeof(sockaddr_in)) + { + ::memset((void *)&inet_addr, 0, sizeof(inet_addr)); + } + + +// ***************************************************************************** +// * cdevInetAddr::cdevInetAddr : +// * This constructor copies the contents of one cdevInetAddr object to +// * the new cdevInetAddr object. +// ***************************************************************************** +cdevInetAddr::cdevInetAddr ( const cdevInetAddr & addr ) + : cdevAddr(AF_INET, sizeof(inet_addr)) + { + memcpy((void *)&inet_addr, (void *)&addr.inet_addr, sizeof(inet_addr)); + } + + +// ***************************************************************************** +// * cdevInetAddr::cdevInetAddr : +// * This constructor creates a new cdevInetAddr object that contains the +// * address provided in the sockaddr_in object. +// ***************************************************************************** +cdevInetAddr::cdevInetAddr (const sockaddr_in *addr, int len) + { + set(addr, len); + } + + +// ***************************************************************************** +// * cdevInetAddr::cdevInetAddr : +// * This constructor initializes the new cdevInetAddr object using the +// * specified port number and host name. +// ***************************************************************************** +cdevInetAddr::cdevInetAddr (unsigned short portnum, char hostname[]) + { + set(portnum, hostname); + } + + +// ***************************************************************************** +// * cdevInetAddr::cdevInetAddr : +// * This constructor initializes the new cdevInetAddr object with the +// * specified port number and ip address. +// ***************************************************************************** +cdevInetAddr::cdevInetAddr (unsigned short portnum, long ip_addr) + { + set(portnum, ip_addr); + } + + +// ***************************************************************************** +// * cdevInetAddr::getHostName : +// * This method allows the caller to return the name of the host that +// * the cdevInetAddr structure identifies. +// ***************************************************************************** +const char * cdevInetAddr::getHostName ( void ) const + { + char * retval; + hostent * hp; + int len = sizeof(inet_addr.sin_addr.s_addr); + + if((hp = ::gethostbyaddr((char *)&inet_addr.sin_addr, len, addr_type))==0) + { + retval = NULL; + } + else retval = hp->h_name; + + return retval; + } + + +// ***************************************************************************** +// * cdevInetAddr::getHostAddr : +// * This method allows the caller to retrieve the internet address (in +// * string format) of the host that the cdevInetAddr object identifies. +// ***************************************************************************** +const char * cdevInetAddr::getHostAddr ( void ) const + { + return ::inet_ntoa(inet_addr.sin_addr); + } + + +// ***************************************************************************** +// * cdevInetAddr::getInetAddr : +// * This method allows the caller to obtain the internet address of the +// * host that the cdevInetAddr object identifies. +// ***************************************************************************** +unsigned long cdevInetAddr::getInetAddr ( void ) const + { + return ntohl((unsigned long)inet_addr.sin_addr.s_addr); + } + + +// ***************************************************************************** +// * cdevInetAddr::getPortNum : +// * This method allows the caller to retrieve the port number that is +// * associated with this cdevInetAddr. +// ***************************************************************************** +unsigned short cdevInetAddr::getPortNum ( void ) const + { + return ntohs (inet_addr.sin_port); + } + + +// ***************************************************************************** +// * cdevInetAddr::getAddress : +// * Returns the address of the sockaddr_in structure. +// ***************************************************************************** +void * cdevInetAddr::getAddress ( void ) const + { + return (void *)&inet_addr; + } + diff --git a/extensions/cdevGenericServer/lib/cdevClientRequestObject.cc b/extensions/cdevGenericServer/lib/cdevClientRequestObject.cc new file mode 100755 index 0000000..742c923 --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevClientRequestObject.cc @@ -0,0 +1,432 @@ +#include +#include +#include +#include +#include + +// ***************************************************************************** +// * cdevClientRequestObject::cdevClientRequestObject : +// * This constructor initializes the internals of a device/message +// * pair associated with a cdevClientService based service. +// * +// * Returns nothing. +// * +// * Remember it is the responsibility of the requestObject to ensure +// * that the message is not laden with extraneous spaces. +// ***************************************************************************** +cdevClientRequestObject::cdevClientRequestObject ( char * device, char * msg, cdevSystem & system) + : cdevRequestObject(device, msg, system), + syncCallback(defaultCallback, (void *)&sendStatus), + handler(NULL), contextID(-1) + { + char message[256]; + char * ptr; + + *server = 0; + *DDL_server = 0; + + // ********************************************************************* + // * Remove any extra spaces from the message. + // * Copy user supplied msg to a message buffer to allow + // * modification in this routine since the user supplied + // * msg could be a constant string + // ********************************************************************* + strncpy (message, msg, sizeof (message) - 1); + message[255] = 0; + + for(ptr=message; *ptr!=0; ptr++) + { + if(isspace(*ptr)) + { + char * nextChar; + + for(nextChar=ptr+1; isspace(*nextChar) && *nextChar!=0; nextChar++); + if(nextChar!=ptr+1) strcpy(ptr+1, nextChar); + *ptr=' '; + } + } + + // ********************************************************************* + // * Remove all trailing spaces from the message. + // ********************************************************************* + for(ptr = message+(strlen(message)-1); ptr>=message && isspace(*ptr); ptr--) + { + *ptr=0; + } + // ********************************************************************* + // * Determine the commandCode from the message string. + // ********************************************************************* + if(!strncmp(message, "get ", 4)) commandCode = GET_COMMAND; + else if(!strncmp(message, "set ", 4)) commandCode = SET_COMMAND; + else if(!strncmp(message, "monitorOn ", 10)) commandCode = MONITOR_ON_COMMAND; + else if(!strncmp(message, "monitorOff ", 11)) commandCode = MONITOR_OFF_COMMAND; + else commandCode = OTHER_COMMAND; + + // ********************************************************************* + // * Determine the messageCode from the message string. + // ********************************************************************* + if(!strcmp(message, "get servers")) messageCode = GET_SERVERS_MESSAGE; + else if(!strcmp(message, "get default")) messageCode = GET_DEFAULT_MESSAGE; + else if(!strcmp(message, "set default")) messageCode = SET_DEFAULT_MESSAGE; + else if(!strcmp(message, "disconnect")) messageCode = DISCONNECT_MESSAGE; + else if(!strcmp(message, "get ClientInfo")) messageCode = GET_CLIENTINFO_MESSAGE; + else if(!strcmp(message, "get ServerInfo")) messageCode = GET_SERVERINFO_MESSAGE; + else messageCode = OTHER_MESSAGE; + + // ********************************************************************* + // * Attempt to read the server name from the DDL file. + // ********************************************************************* + cdevData output; + + sprintf (DDL_server, "resolveServiceData %s %s", device, message); + if((system.nameServer()).send(DDL_server, NULL, &output)==CDEV_SUCCESS) + { + *DDL_server = 0; + output.get ("server", DDL_server, 256); + } + else *DDL_server = 0; + } + + +// ***************************************************************************** +// * cdevClientRequestObject::~cdevClientRequestObject: +// * This is the destructor for the object. It will free any memory that it +// * has allocated and remove itself from its associated ServerHandler +// * callback. +// ***************************************************************************** +cdevClientRequestObject::~cdevClientRequestObject ( void ) + { + if(handler!=NULL) handler->unregisterServerCallback(this); + } + + +// ***************************************************************************** +// * cdevClientRequestObject::getState : +// * Returns the connection state of the cdevClientRequestObject. +// ***************************************************************************** +int cdevClientRequestObject::getState ( void ) + { + ServerHandler * Handler = NULL; + return (getServerHandler(&Handler)==CDEV_SUCCESS)?CDEV_STATE_NOTCONNECTED:CDEV_STATE_CONNECTED; + } + + + +// ***************************************************************************** +// * cdevClientRequestObject::className : +// * Obtains the name of this class as a string. +// ***************************************************************************** +const char * cdevClientRequestObject::className ( void ) const + { + return "cdevClientRequestObject"; + } + + +// ***************************************************************************** +// * cdevClientRequestObject::setContext : +// * This method is called to set the context of the request object. The +// * first step in this process is to determine if the caller has specified +// * a server in the context. If so, the server name should be set to that +// * value. Next call the setContext method of the underlying +// * cdevRequestObject... +// ***************************************************************************** +int cdevClientRequestObject::setContext (cdevData& cxt) + { + cdevClientService * svc = (cdevClientService *)service_; + int result = CDEV_SUCCESS; + int newContextID = 0; + + if((newContextID = svc->contexts.insert(cxt))!=contextID) + { + ServerHandler * Handler = NULL; + + if(handler!=NULL) handler->unregisterServerCallback(this); + + contextID = newContextID; + *server = 0; + handler = NULL; + + cxt.get ("server", server, 256); + getServerHandler(&Handler); + + result = cdevRequestObject::setContext(cxt); + } + return result; + } + + +// ***************************************************************************** +// * cdevClientRequestObject::sendNoBlock : +// * This function allows the caller to submit an asynchronous message to the +// * server for processing. +// ***************************************************************************** +int cdevClientRequestObject::sendNoBlock (cdevData & in, cdevData & out) + { return sendNoBlock(&in, &out); } +int cdevClientRequestObject::sendNoBlock (cdevData * in, cdevData & out) + { return sendNoBlock(in, &out); } +int cdevClientRequestObject::sendNoBlock (cdevData & in, cdevData * out) + { return sendNoBlock(&in, out); } +int cdevClientRequestObject::sendNoBlock (cdevData * in, cdevData * out) + { + cdevClientService * svc = (cdevClientService *)service_; + cdevTranObj * xobj = new cdevTranObj(&system_, this, out, &svc->syncCallback); + ServerHandler * Handler = NULL; + int status = CDEV_SUCCESS; + + xobj->disableDeleteCbk(); + + if((status=getServerHandler(&Handler))==CDEV_SUCCESS) + { + status = svc->enqueue(Handler, in, *xobj); + } + else delete xobj; + return status; + } + + +// ***************************************************************************** +// * cdevClientRequestObject::sendCallback : +// * This function allows the caller to submit an asynchronous message to the +// * server for processing. +// ***************************************************************************** +int cdevClientRequestObject::sendCallback (cdevData & in, cdevCallback & callback) + { return sendCallback(&in, callback); } +int cdevClientRequestObject::sendCallback (cdevData * in, cdevCallback & callback) + { + cdevCallback * cb = new cdevCallback(callback); + cdevClientService * svc = (cdevClientService *)service_; + cdevTranObj * xobj = new cdevTranObj(&system_, this, NULL, cb); + ServerHandler * Handler = NULL; + int status = CDEV_SUCCESS; + + xobj->enableDeleteCbk(); + + if((status=getServerHandler(&Handler))==CDEV_SUCCESS) + { + status = svc->enqueue(Handler, in, *xobj); + } + else delete xobj; + return status; + } + + +// ***************************************************************************** +// * cdevClientRequestObject::send : +// * The send interface is used to provide synchronous I/O with the service. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int cdevClientRequestObject::send ( cdevData & in, cdevData & out ) + { return send(&in, &out); } +int cdevClientRequestObject::send ( cdevData * in, cdevData & out ) + { return send(in, &out); } +int cdevClientRequestObject::send ( cdevData & in, cdevData * out ) + { return send(&in, out); } +int cdevClientRequestObject::send ( cdevData * in, cdevData * out ) + { + int status = CDEV_SUCCESS; + cdevClientService * svc = (cdevClientService *)service_; + cdevTranObj * xobj = new cdevTranObj(&system_, this, out, &syncCallback); + ServerHandler * Handler; + + sendStatus.completionCode = 0; + sendStatus.finished = 0; + xobj->disableDeleteCbk(); + + if((status=getServerHandler(&Handler))==CDEV_SUCCESS) + { + if((status = svc->enqueue(Handler, in, *xobj))==CDEV_SUCCESS) + { + // ***************************************************** + // * I used to wait for a response here only if the outbound + // * cdevData object was non-null. However, that provided + // * unexpected behavior to the client. Now I wait whether + // * output data is expected or not. + // ***************************************************** + cdevTimeValue t(waitPeriod()); + cdevClock timer; + timer.schedule(NULL,t); + + // ***************************************************** + // * WAITING WITH system_.pend(): + // * Previously I was using system_.pend() to process + // * events while waiting for the service to respond. + // * This resulted in a lock-up when the connection + // * could not be established or if the connection + // * collapsed while in use. + // * + // * WAITING WITH system_.poll(): + // * When in a heavy inbound traffic situation, the + // * calls from other services will trample all over + // * the inbound data coming from the server. + // * This results in unreliable delivery and processing + // * of messages from the server. + // * + // * WAITING WITH service_.poll(): + // * So far so good. + // ***************************************************** + + while(!sendStatus.finished && !timer.expired()) service_->poll(); + if (!sendStatus.finished) + { + svc->cancel(*xobj); + status = CDEV_ERROR; + system_.reportError( + CDEV_SEVERITY_ERROR, + "cdevRequestObject", + this, + "Server failed to respond after %.1f seconds", + (float)waitPeriod()); + } + else + { + status = sendStatus.completionCode; + } + } + } + else delete xobj; + + return status; + } + + +// ***************************************************************************** +// * cdevClientRequestObject::defaultCallback : +// * This is the callback function that is used by the object to +// * receive callbacks for send operations. +// ***************************************************************************** +void cdevClientRequestObject::defaultCallback (int status, void * user, cdevRequestObject &, cdevData &) + { + SendStatus * result = (SendStatus *)user; + + if(result) + { + result->completionCode = status; + result->finished = 1; + } + } + + +// ***************************************************************************** +// * cdevClientRequestObject::executeServerHandlerCallback : +// * The requestObject registers itself with the ServerHandler when it +// * attaches to it... If the Serverhandler is destroyed, it will +// * call this method on all of the registered request objects in order +// * to notify them that it is going away. This allows the request +// * object to clear the pointer to the ServerHandler. +// ***************************************************************************** +void cdevClientRequestObject::executeServerHandlerCallback (ServerHandler * Handler) + { + if(Handler==handler) + { + /* + * system_.reportError(CDEV_SEVERITY_INFO, "cdevRequestObject", + * this, "Connection to %s broken for %s:%s", + * Handler->get_server(), device().name(), message()); + */ + handler=NULL; + } + } + + +// ***************************************************************************** +// * cdevClientRequestObject::getServerHandler : +// * This method is used to obtain the ServerHandler for this request +// * object... +// * +// * The following rules will be followed: +// * +// * 1) If a server has been specified in the context, then that +// * server will be used. +// * +// * - otherwise - +// * +// * 2) If a server has been specified in the service data of the +// * DDL file, then that server will be used. +// * +// * - otherwise - +// * +// * 3) The default server as specified at the cdevClientService will +// * be used. +// ***************************************************************************** +int cdevClientRequestObject::getServerHandler (ServerHandler ** Handler) + { + cdevClientService * svc = (cdevClientService *)service_; + int result = CDEV_SUCCESS; + + *Handler = NULL; + + if (*server==0 && *DDL_server!=0) strcpy(server, DDL_server); + if (*server!=0 && handler==NULL) + { + if((*Handler = svc->connect(server))==NULL) result = CDEV_ERROR; + else + { + handler = *Handler; + handler->registerServerCallback(this); + } + } + else *Handler = handler; + + return result; + } + +// ***************************************************************************** +// * cdevClientRequestObject::isRequestRestartable : +// * This method allows the caller to determine if the request object +// * is restartable. If a server goes down and then a new server comes +// * up in its place, this method will be called for each request object +// * that has an outstanding request that has not been serviced. +// * If the isRequestRestartable method returns 1, the request will be +// * sent to the new server - otherwise, the request will be terminated. +// ***************************************************************************** +int cdevClientRequestObject::isRequestRestartable ( void ) + { + int result = 0; + + switch(getCommandCode()) + { + case GET_COMMAND: + case MONITOR_ON_COMMAND: + result = 1; + break; + + case SET_COMMAND: + case MONITOR_OFF_COMMAND: + default: + result = 0; + break; + } + + return result; + } + +// ***************************************************************************** +// * cdevClientRequestObject::getContextID : +// * This method will retrieve the identifier of the context that is +// * currently in use by this object. +// ***************************************************************************** +int cdevClientRequestObject::getContextID ( void ) + { + return contextID; + } + + +// ***************************************************************************** +// * getCommandCode : +// * This method will return the current value of the commandCode variable. +// * This variable is used to identify the VERB that is utilized by this +// * cdevClientRequestObject. The default set of verbs are "get", "set", +// * "monitorOn", and "monitorOff". +// ***************************************************************************** +int cdevClientRequestObject::getCommandCode ( void ) { return commandCode; } + +// ***************************************************************************** +// * getMessageCode : +// * This method will return the current value of the messageCode variable. +// * This variable is used to identify the message that is utilized by this +// * cdevClientRequestObject. The default set of supported messages are +// * "get servers", "get default", "set default", and "disconnect". +// ***************************************************************************** +int cdevClientRequestObject::getMessageCode ( void ) { return messageCode; } + diff --git a/extensions/cdevGenericServer/lib/cdevClientService.cc b/extensions/cdevGenericServer/lib/cdevClientService.cc new file mode 100755 index 0000000..e3f6950 --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevClientService.cc @@ -0,0 +1,1219 @@ +#include +#include +#include +#include +#include + +int cdevClientService::ServerTag = 0; +int cdevClientService::HostTag = 0; +int cdevClientService::PortTag = 0; + +cdevGenericServerTagDef cdevClientService::tags; + +// ***************************************************************************** +// * ClientInfo clientInfo : +// * This is a static member of the cdevClientService class that contains +// * descriptive information about the client process. +// ***************************************************************************** +ClientInfo cdevClientService::clientInfo; + +// ***************************************************************************** +// * cdevClientTransaction::freeList_ : +// * This is the free list for the cdevClientTransaction object that is +// * used to reduce run-time memory allocations. +// ***************************************************************************** +cdevClientTransaction * cdevClientTransaction::freeList_ = NULL; + +// ***************************************************************************** +// * This is the text string that will be used to define the cdevNameServer +// * if it has not yet been defined in the cdevDirectory file. +// ***************************************************************************** +static char * NameServerDefinitionString = +"service rns { tags {PV} }\n\ +class RNS { messages { query rns; get rns; monitorOn rns; monitorOff rns; monitorEntry rns; monitorEntryOff rns; } }\n\ +RNS :\nNameServer\n;\n"; + +// ***************************************************************************** +// * cdevClientService::cdevClientService : +// * This is the constructor for the object. Its is responsible for +// * initializing the underlying classes and data items. +// ***************************************************************************** +cdevClientService::cdevClientService ( char * Domain, char * name, cdevSystem & system ) + : ServerInterface (), + syncCallback (defaultCallback, NULL), + domain (strdup(Domain)), + cdevService (name, system), + transactions (), + contexts (), + nsCallbackArgs (0) + { + // ********************************************************************* + // * Determine if the NameServer has been provided in the CDEVDDL file. + // * If not, add the NameServer to the cdevDirectory. + // ********************************************************************* + cdevDirectory & nameServer = system.nameServer(); + cdevData request; + cdevData reply; + + request.insert("device", "NameServer"); + if(nameServer.send("queryClass", request, reply)==CDEV_NOTFOUND) + { + request.insert("file", NameServerDefinitionString); + nameServer.send("update", request, NULL); + } + + // ********************************************************************* + // * If the tags used by this service have not yet been defined in the + // * cdevGlobalTagTable, then automatically define them here. + // ********************************************************************* + if(ServerTag==0) + { + cdevData::insertTag(ServiceTagBase+1, "server"); + cdevData::insertTag(ServiceTagBase+2, "host"); + cdevData::insertTag(ServiceTagBase+3, "port"); + cdevData::tagC2I("server", &ServerTag); + cdevData::tagC2I("host", &HostTag); + cdevData::tagC2I("port", &PortTag); + } + + // ********************************************************************* + // * Install a tag callback that will automicatically be executed each + // * time a new tag is added to the cdevGlobalTagTable. + // ********************************************************************* + cdevData::addTagCallback(this); + } + + +// ***************************************************************************** +// * cdevClientService::~cdevClientService : +// * This is the destructor for the object. It will call release any +// * memory that was allocated by the class. +// ***************************************************************************** +cdevClientService::~cdevClientService ( void ) + { + AddressIndexIterator iter (&transactions); + StringHashIterator sIter(&nsCallbackArgs); + cdevClientTransaction * xobj; + + if(domain) delete domain; + + for(iter.first(); (xobj = (cdevClientTransaction *)iter.data())!=NULL; iter++) + { + transactions.remove(iter.key()); + + delete xobj; + } + + NSCallbackArg * nsData; + for(sIter.first(); (nsData = (NSCallbackArg *)sIter.data())!=NULL; sIter++) + { + delete nsData; + } + + cdevData::delTagCallback(this); + } + + +// ***************************************************************************** +// * cdevClientService::defaultCallback : +// * This is the callback function that is used to support sendNoBlock +// * requests that are issued by the cdevRequestObject. +// ***************************************************************************** +void cdevClientService::defaultCallback (int, void *, cdevRequestObject &, cdevData & ) + { + } + + +// ***************************************************************************** +// * cdevClientService::nameServerCallback : +// * This is the callback function that is executed whenever one of the +// * connected servers becomes disconnected. This function will call each +// * of the request objects associated with the server and notify them +// * of the server's change in status. +// ***************************************************************************** +void cdevClientService::nameServerCallback(int, void *userarg, cdevRequestObject &, cdevData & data) + { + NSCallbackArg * arg = (NSCallbackArg *)userarg; + cdevClientService * cService = arg->service; + unsigned short port = 0; + int statusCode = -1; + cdevData userData; + char server[255]; + char host[255]; + + // ********************************************************************* + // * Initialize the server and host variables to empty strings, this + // * will allow me to detect if the data was actually extracted from the + // * cdevData object. + // ********************************************************************* + *server = 0; + *host = 0; + + // ********************************************************************* + // * The status code from the name server should be between 0 and 3. + // * If the status code is out of range, display an error and return. + // ********************************************************************* + data.get("status", &statusCode); + if(statusCode<0) + { + cService->outputError(CDEV_SEVERITY_ERROR, + "cdevClientService", + "Name Server is down..."); + return; + } + else if(statusCode>3) + { + cService->outputError(CDEV_SEVERITY_ERROR, + "cdevClientService", + "Unknown status code (%i) received from Name Server", + statusCode); + return; + } + + // ********************************************************************* + // * Read critical tags from the cdevData object. + // ********************************************************************* + data.get("name", server, 255); + data.get("host", host, 255); + data.get("port", &port); + + // ********************************************************************* + // * Determine if a live connection still exists to the specified server + // ********************************************************************* + ServerHandler * handler = cService->connections.find(server); + + // ********************************************************************* + // * If the handler is NULL this means that the application has already + // * become disconnected from the server. Consequently, all restartable + // * requests will have to be resent and all other requests will have + // * to be terminated. + // * For this reason, if the statusCode coming from Name Server is 0, + // * it should be set to 3 (indicating a server restart). If the status + // * code coming from the server is a 1 then it should be set to 2 + // * (indicating a dead server). + // ********************************************************************* + if(handler==NULL && statusCode==0) statusCode=3; + if(handler==NULL && statusCode==1) statusCode=2; + + // ********************************************************************* + // * If the statusCode is 2 (terminated server) and the ServerHandler + // * is not equal to NULL, then delete the ServerHandler to force the + // * connection to be closed. + // ********************************************************************* + if(statusCode==2 && handler!=NULL) + { + delete handler; + handler = NULL; + } + + // ********************************************************************* + // * Report the condition of the connection. + // ********************************************************************* + cService->outputError(CDEV_SEVERITY_INFO, "cdevClientService", + "Name Server reports server %s in domain %s has been %s", + server, cService->getDomain(), + ((statusCode==0)?"CONNECTED":((statusCode==1)?"DISCONNECTED": + ((statusCode==2)?"TERMINATED":"RESTARTED")))); + + // ********************************************************************* + // * Walk through the list of transactions and process those with a + // * matching server name and a differing status code. + // ********************************************************************* + AddressIndexIterator iter(&cService->transactions); + cdevClientTransaction * trans; + + for(iter.first(); (trans = (cdevClientTransaction *)iter.data())!=NULL; iter++) + { + cdevTranObj * xobj = trans->xobj; + cdevCallback * cb = xobj->userCallback_; + + // ************************************************************* + // * Process transactions associated with this specific server. + // ************************************************************* + if(trans->statusCode!=statusCode && !strcmp(trans->server, server)) + { + // ***************************************************** + // * Status code of 0 indicates that the server is + // * online and operational. We also check the + // * ServerHandler to ensure that we still have a + // * valid connection. + // ***************************************************** + if(statusCode==0) + { + cb->fireCallback(CDEV_RECONNECTED, cb->userarg(), + *xobj->reqObj_, userData, 1); + if(trans->statusCode<0) + { + trans->reconnect(host, port, iter.key()); + } + } + // ***************************************************** + // * Status code of 1 indicates that the server has + // * ceased sending periodic updates to the name server + // ***************************************************** + else if (statusCode==1) + { + cb->fireCallback(CDEV_DISCONNECTED, cb->userarg(), + *xobj->reqObj_, userData, 1); + trans->statusCode = statusCode; + } + // ***************************************************** + // * Status code of 2 indicates that the server has + // * terminated and all connections are lost. + // ***************************************************** + else if (statusCode==2 && trans->restartable) + { + cb->fireCallback(CDEV_DISCONNECTED, cb->userarg(), + *xobj->reqObj_, userData, 1); + trans->statusCode = statusCode; + } + // ***************************************************** + // * Status code of 3 indicates that a new server with + // * an identical name and domain has taken the place + // * of the dead server. If the transaction is + // * restartable, resubmit the request to the server. + // ***************************************************** + else if (statusCode==3 && trans->restartable) + { + trans->statusCode = -1; + trans->reconnect(host, port, iter.key()); + } + // ***************************************************** + // * This section will catch the statusCode 2 and 3 + // * events where the request is not restartable and + // * will delete these transactions. + // ***************************************************** + else if (statusCode==2 || statusCode==3) + { + cb->fireCallback(CDEV_ERROR, cb->userarg(), + *xobj->reqObj_, userData, 0); + cService->transactions.remove(iter.key()); + delete trans; + } + } + } + } + + +// ***************************************************************************** +// * cdevClientService::outputError : +// * This mechanism is used to report errors to the system. +// ***************************************************************************** +int cdevClientService::outputError(int severity, char *name, char *formatString, ...) + { + int status; + va_list argp; + + va_start (argp, formatString); + status = system_.vreportError(severity, name, NULL, formatString, argp); + va_end (argp); + + return status; + } + + +// ***************************************************************************** +// * cdevClientService::connect : +// * This mechanism will establish a new connection with a server and will +// * will return a pointer to the ServerHandler. If the host and port are +// * specified in the arguments, then the method will attempt to connect +// * using those values without going through the CDEV Name Server. +// * +// * Note: This method will insert the ServerHandler into the connections +// * object and will install it in the Reactor. +// ***************************************************************************** +ServerHandler * cdevClientService::connect ( char * server, char * host, unsigned short port ) + { + ServerHandler * handler = NULL; + + // ********************************************************************* + // * First attempt to locate the handler from the existing connections. + // ********************************************************************* + if(server && *server && (handler = connections.find(server))==NULL) + { + int errCode = CDEV_SUCCESS; + char serverHost[255]; + unsigned short serverPort; + int serverStatus; + + // ************************************************************* + // * If the host and port have been specified, then use them + // * rather than going through the CDEV Name Server. + // ************************************************************* + if(host!=NULL && *host && port>0) + { + strcpy(serverHost, host); + serverPort = port; + } + else { + cdevData input; + cdevData output; + cdevRequestObject & rnsReq = + cdevRequestObject::attachRef("NameServer", "get"); + + *serverHost = 0; + serverPort = 0; + + // ***************************************************** + // * Insert domain and name in the input request object + // * to be sent to the CDEV Name Server. + // ***************************************************** + input.insert("name", server); + input.insert("domain", domain); + + // ***************************************************** + // * Query the Name Server to obtain the hostname and + // * port of the specified domain and server. + // ***************************************************** + if((errCode=rnsReq.send(input, output))!=CDEV_SUCCESS || + output.get("host", serverHost, 255)!=CDEV_SUCCESS || + output.get("port", &serverPort)!=CDEV_SUCCESS || + output.get("status", &serverStatus)!=CDEV_SUCCESS || + *serverHost==0 || serverPort<=0 || serverStatus!=0) + { + errCode = CDEV_ERROR; + + // ********************************************* + // * If the hostname could not be found, report + // * the error and set the return value to + // * CDEV_ERROR. + // ********************************************* + outputError(CDEV_SEVERITY_ERROR, + "cdevClientService::connect", + "Cannot find host for server \"%s\" in domain \"%s\"", + server, domain); + } + } + + + // ************************************************************* + // * If the hostname was discovered, then the errCode should be + // * CDEV_SUCCESS. Attempt to connect to the server using the + // * cdevReactor mechanisms. + // ************************************************************* + if(errCode==CDEV_SUCCESS) + { + cdevInetAddr addr; + + addr.set (serverPort, serverHost); + + handler = new ServerHandler(server, this); + + if(handler->open(addr)!=0) + { + outputError(CDEV_SEVERITY_ERROR, + "cdevClientService::connect", + "Failed to connect to %s on port %i", + serverHost, + serverPort); + delete handler; + handler = NULL; + } + else { + outputError(CDEV_SEVERITY_INFO, + "cdevClientService::connect", + "Connected to %s on port %i", + serverHost, + serverPort); + connections.insert(handler); + + // ********************************************* + // * This calls the registerFd method of the + // * service which will cause the FD Changed + // * callbacks to be triggered. + // ********************************************* + registerFd(handler->getHandle(), 1); + + // ********************************************* + // * Install a Name Server monitor to maintain + // * the status of the connection. + // * Note: If a monitor has already been + // * installed using this informations, then the + // * CDEV Name Server service should not create + // * a second monitor. + // * + // * Note: I am using the FifoQueue associated + // * with the specific server in order to + // * differentiate between the various servers. + // ********************************************* + cdevData monData; + cdevCallback monCb(nameServerCallback, (void *)getCallbackArg(server)); + cdevRequestObject & monReq = cdevRequestObject::attachRef("NameServer", "monitorOn"); + + monData.insert("name", server); + monData.insert("domain", domain); + monReq.sendCallback(monData, monCb); + + // ********************************************* + // * Here is where a "set ClientInfo" message + // * will be sent to the server to provide + // * descriptive information about the client. + // ********************************************* + cdevData tagMap; + int * itags; + char ** ctags; + int ntags; + char * binary = NULL; + size_t binaryLen = 0; + + cdevData::readTagTable(itags, ctags, ntags); + tagMap.insert(1, itags, ntags); + tagMap.insert(2, ctags, ntags); + + delete itags; + delete ctags; + handler->setTagChangeFlag(0); + + cdevMessageBinary packet(handler->getClientID(), + 0, 0, 0, 0, CDEV_SERVER_OP, 0, 0, + NULL, "set ClientInfo", + &clientInfo.getClientData(), + NULL, &tagMap); + + packet.streamOut(&binary, &binaryLen); + packet.detachData(); + + ServerInterface::enqueue(handler, binary, binaryLen); + } + } + } + return handler; + } + + +// ***************************************************************************** +// * cdevClientService::disconnect : +// * This mechanism will remove the ServerHandler pointer from the +// * connections list and will return the ServerHandler pointer to the +// * caller. It is the responsibility of the caller to delete the +// * ServerHandler pointer. +// ***************************************************************************** +ServerHandler * cdevClientService::disconnect ( char * server ) + { + ServerHandler * handler; + + // ********************************************************************* + // * Find and remove the specified server. This method will also check + // * to determine if the handler that is being disconnected is the + // * defaultServer - if so, the defaultServerHandler variable will be + // * set to NULL. + // ********************************************************************* + if((handler = connections.remove(server))==defaultServerHandler) + { + defaultServerHandler = NULL; + } + // ********************************************************************* + // * This calls the registerFd method of the service which will cause + // * the FD Changed callbacks to be triggered. + // ********************************************************************* + if(handler!=NULL && handler->getHandle()!=cdevSocket::INVALID_HANDLE) + { + registerFd(handler->getHandle(), 0); + } + + return handler; + } + +// ***************************************************************************** +// * cdevClientService::flush : +// * This is method calls the flush mechanism of the underlying +// * ServerInterface class. +// ***************************************************************************** +int cdevClientService::flush ( void ) + { + return ServerInterface::flush(); + } + + + +// ***************************************************************************** +// * cdevClientService::pend : +// * This method calls the pend mechanism of the underlying +// * ServerInterface class. +// ***************************************************************************** +int cdevClientService::pend ( double seconds, int fd ) + { + return ServerInterface::pend(seconds, fd); + } + + +// ***************************************************************************** +// * cdevClientService::getFd : +// * This method calls the getFd mechanism of the underlying +// * ServerInterface class. +// ***************************************************************************** +int cdevClientService::getFd( int * &fd, int & numFd ) + { + return ServerInterface::getFd(fd, numFd); + } + + +// ***************************************************************************** +// * cdevClientService::poll : +// * This is the polling mechanism for the service. +// ***************************************************************************** +int cdevClientService::poll ( void ) + { + return ServerInterface::poll(); + } + + +// ***************************************************************************** +// * cdevClientService::pend : +// * This method does not implement the full functionality of the +// * cdev prototype. Rather it pends for a default amount of time. +// ***************************************************************************** +int cdevClientService::pend( int fd) + { + return pend(0.01, fd); + } + + +// ***************************************************************************** +// * cdevClientService::getNameServer : +// * This method is used to provide a cdevDevice that can be used as the +// * name server for the service. It is not implemented here. +// ***************************************************************************** +int cdevClientService::getNameServer ( cdevDevice * &ns ) + { + ns = NULL; + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * cdevClientService::getRequestObject : +// * This is the interface that cdev objects will use to obtain a +// * cdevClientRequestObject object. The cdevClientRequestObject +// * represents a combined device and message pair that is associated +// * with the cdevClientService. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int cdevClientService::getRequestObject ( char * device, char * message, cdevRequestObject * &req) + { + req = new cdevClientRequestObject (device, message, system_); + return (req ? CDEV_SUCCESS : CDEV_ERROR); + } + + +// ***************************************************************************** +// * cdevClientService::enqueue : +// * This is the method that is used by the cdevRequestObject to submit a +// * message to the cdevServer when the name of the server is known, but a +// * ServerHandler object has not yet been obtained... +// ***************************************************************************** +int cdevClientService::enqueue ( char * server, cdevData * in, cdevTranObj & xobj ) + { + ServerHandler * handler = server==NULL?defaultServerHandler:connect(server); + + return enqueue(handler, in, xobj); + } + + +// ***************************************************************************** +// * cdevClientService::enqueue : +// * This method is used by the cdevRequestObject to enqueue an outbound +// * message to the cdevServer when the ServerHandler has already been +// * obtained. +// ***************************************************************************** +int cdevClientService::enqueue ( ServerHandler * handler, cdevData * in, cdevTranObj &xobj) + { + int result = CDEV_SUCCESS; + + // ********************************************************************* + // * Determine if the message will be processed locally first. + // * If not, then submit it to the underlying ServerInterface + // * for processing. + // ********************************************************************* + if(processLocal(in, xobj)!=0) + { + // ************************************************************* + // * Determine if the handler is valid or use the + // * defaultServerHandler + // ************************************************************* + if(handler==NULL) + { + if(defaultServerHandler!=NULL) + { + handler=defaultServerHandler; + } + else if(defaultServerHandler==NULL && defaultServer!=NULL) + { + handler = (defaultServerHandler=connect(defaultServer)); + } + else { + system_.reportError(CDEV_SEVERITY_ERROR, + "cdevClientService::enqueue", + xobj.reqObj_, + "No default server has been defined for this service"); + } + } + + // ************************************************************* + // * If a valid ServerHandler has been located. + // ************************************************************* + if(handler!=NULL) + { + cdevClientRequestObject * reqObj; + int restart; + int ctxID; + cdevClientTransaction * node; + unsigned index; + + reqObj = (cdevClientRequestObject *)xobj.reqObj_; + restart = reqObj->isRequestRestartable(); + ctxID = reqObj->getContextID(); + node = new cdevClientTransaction(xobj, *handler, restart, in, ctxID); + index = transactions.insert(node); + + if((result=enqueue(handler, *node, index))!=CDEV_SUCCESS) + { + transactions.remove(index); + delete node; + } + else { + // ********************************************* + // * If the message is monitorOff, then the + // * method will walk through all of the active + // * monitors and remove those that exactly match + // * all attributes of the request.... + // * - Server name + // * - Device name + // * - Attribute name + // * - Context values + // ********************************************* + if(reqObj->getCommandCode()==cdevClientRequestObject::MONITOR_OFF_COMMAND) + { + #define xCommand ((cdevClientRequestObject *)trans->xobj->reqObj_)->getCommandCode() + #define xDevice xobj->reqObj_->device().name() + #define xMessage xobj->reqObj_->message() + #define xUserarg xobj->userCallback_->userarg() + #define xCallback xobj->userCallback_->callbackFunction() + + AddressIndexIterator iter(&transactions); + cdevClientTransaction * trans; + cdevMessageBinary packet; + char * device = (char *)reqObj->device().name(); + char * binary; + size_t binaryLen; + + for(iter.first(); (trans=(cdevClientTransaction *)iter.data())!=NULL; iter++) + { + if(xCommand==cdevClientRequestObject::MONITOR_ON_COMMAND && + (node->xUserarg==NULL || node->xUserarg==trans->xUserarg) && + (node->xCallback==NULL || node->xCallback==trans->xCallback) && + !strcmp(node->xDevice, trans->xDevice) && + !strcmp(node->xMessage+11, trans->xMessage+10) && + !strcmp(node->server, trans->server)) + { + int cancelTransIdx = iter.key(); + + // ********************************************** + // * Remove the transaction and delete it. + // ********************************************** + transactions.remove(cancelTransIdx); + + // ********************************************** + // * Fire the callback with the + // * partialTransaction flag set to 0 to notify + // * the developer that the transaction is + // * finished. Note that the status is + // * CDEV_WARNING because no actual data is + // * being delivered. + // ********************************************** + fireCallback(CDEV_WARNING, *trans->xobj, NULL, 0); + + delete trans; + + // ********************************************** + // * Send a packet containing the transaction to + // * be destroyed. + // ********************************************** + packet.set(handler->getClientID(), 0, cancelTransIdx, 0, 0, 0, 0, 1, + &device, xobj.reqObj_->message()); + + packet.streamOut(&binary, &binaryLen); + packet.detachData(); + ServerInterface::enqueue(handler, binary, binaryLen); + } + } + + #undef xCommand + #undef xDevice + #undef XMessage + #undef XUserarg + #undef XCallback + } + } + } + else result = CDEV_ERROR; + } + + return result; + } + + +// ***************************************************************************** +// * cdevClientService::enqueue : +// * This method is called by the internals of the cdevClientService to +// * submit a message to a server. This method is called by either the +// * enqueue method (to initially submit a request), or the nameServerCallback +// * method ( to resubmit a request when a server has restarted). +// ***************************************************************************** +int cdevClientService::enqueue ( ServerHandler * handler, cdevClientTransaction &trans, unsigned transID ) + { + int result; + + // ********************************************************************* + // * If the server handler is valid and a connection has been + // * established. + // ********************************************************************* + if(handler!=NULL) + { + cdevTranObj * xobj = trans.xobj; + cdevClientRequestObject * reqObj = (cdevClientRequestObject *)xobj->reqObj_; + char * device = (char *)reqObj->device().name(); + int ctxID = trans.contextID; + cdevData * in = trans.userData; + cdevData * context = NULL; + cdevData * tagMap = NULL; + int opCode = CDEV_NORMAL_OP; + + // ************************************************************* + // * Set the operation code to CDEV_SERVER_OP if the message + // * should be processed by the cdevGenericServer Engine rather + // * than the user defined server engine. + // ************************************************************* + if(reqObj->getMessageCode()==cdevClientRequestObject::GET_CLIENTINFO_MESSAGE || + reqObj->getMessageCode()==cdevClientRequestObject::GET_SERVERINFO_MESSAGE) + { + opCode=CDEV_SERVER_OP; + } + + // ************************************************************* + // * Switch to the contextID specified in trans parameter. + // ************************************************************* + if(handler->getContextID()!=ctxID) + { + context = contexts.find(ctxID); + handler->setContextID(ctxID); + } + + // ************************************************************* + // * If the tag map has changed, include it in the transmission + // ************************************************************* + if(handler->getTagChangeFlag()) + { + int * itags; + char ** ctags; + int ntags; + + cdevData::readTagTable(itags, ctags, ntags); + tagMap = new cdevData; + tagMap->insert(1, itags, ntags); + tagMap->insert(2, ctags, ntags); + + delete itags; + delete ctags; + handler->setTagChangeFlag(0); + } + + // ************************************************************* + // * Construct the outbound packet. + // ************************************************************* + cdevMessageBinary packet(handler->getClientID(), transID, + 0, 0, 0, opCode, 0, 1, + &device, + reqObj->message(), + in, + context, + tagMap); + + // ************************************************************* + // * Delete the tag map if it was allocated. + // ************************************************************* + if(tagMap) delete tagMap; + + // ************************************************************* + // * Extract the binary stream representation of the data and + // * then use the detach data mechanism to ensure that the + // * binary buffer is not deleted when the packet object is + // * destroyed. + // ************************************************************* + char * binary = NULL; + size_t binaryLen = 0; + packet.streamOut(&binary, &binaryLen); + packet.detachData(); + + + // ************************************************************* + // * Enqueue the message into the outbound queue. + // ************************************************************* + result=ServerInterface::enqueue(handler, binary, binaryLen); + } + else result = CDEV_ERROR; + + return result; + } + +// ***************************************************************************** +// * cdevClientService::cancel : +// * This method is used to cancel a transaction that has taken too long +// * to be processed. +// ***************************************************************************** +int cdevClientService::cancel ( cdevTranObj & xobj ) + { + AddressIndexIterator iter(&transactions); + cdevClientTransaction * node; + + for(iter.first(); (node=(cdevClientTransaction *)iter.data())!=NULL && node->xobj!=&xobj; iter++); + if(node!=NULL) + { + transactions.remove(iter.key()); + delete node; + } + + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * cdevClientService::enqueue : +// * This is the mechanism that is used by the underlying ServerInterface +// * to return the result of a transmission to the caller. DO NOT DELETE +// * THE BINARY PROVIDED TO THIS CLASS. +// ***************************************************************************** +int cdevClientService::enqueue ( int status, ServerHandler * /*handler*/, char * binary, size_t binaryLen ) + { + cdevMessage message(binary, binaryLen); + cdevClientTransaction * node; + + if((node=(cdevClientTransaction *)transactions.find(message.getTransIndex()))!=NULL) + { + int completionCode = (status==FAILED_TO_SEND)?CDEV_ERROR:message.getCompletionCode(); + + if(status==FAILED_TO_SEND) node->permanent = 0; + + fireCallback(completionCode, *node->xobj, message.getData(), node->permanent); + + if(!node->permanent) + { + transactions.remove(message.getTransIndex()); + delete node; + } + } + + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * cdevClientService::fireCallback : +// * This method is used to deploy a callback on a specific transaction. +// ***************************************************************************** +void cdevClientService::fireCallback ( int status, + cdevTranObj &xobj, + cdevData *resultData, + int partialTransaction) + { + static cdevData dummy; + + if(resultData==NULL) + { + dummy.remove(); + resultData = &dummy; + } + if(xobj.resultData_!=NULL) *xobj.resultData_ = *resultData; + + xobj.userCallback_->fireCallback + (status, + xobj.userCallback_->userarg(), + *xobj.reqObj_, + xobj.resultData_!=NULL?*xobj.resultData_:*resultData, + partialTransaction); + } + + +// ***************************************************************************** +// * cdevClientService::processLocal: +// * This method performs any localized data processing that the service +// * might require. If the message is processed locally, this method should +// * return 0... otherwise, the method should return non-zero. +// ***************************************************************************** +int cdevClientService::processLocal ( cdevData * in, cdevTranObj & xobj) + { + int result = 1; + int status = CDEV_SUCCESS; + cdevClientRequestObject * reqObj = (cdevClientRequestObject *)xobj.reqObj_; + + switch(reqObj->getMessageCode()) + { + case cdevClientRequestObject::GET_SERVERS_MESSAGE: + { + char queryMsg[256]; + cdevData input; + cdevData output; + cdevRequestObject & nsReq = + cdevRequestObject::attachRef("NameServer", "query"); + + sprintf(queryMsg, "domain=='%s'", getDomain()); + input.insert("queryMsg", queryMsg); + if((status=nsReq.send(input, output))==CDEV_SUCCESS) + { + output.changeTag ("name", "value"); + } + fireCallback(status, xobj, &output); + result = CDEV_SUCCESS; + } + break; + + case cdevClientRequestObject::GET_DEFAULT_MESSAGE: + { + cdevData resultData; + resultData.insert("value", getDefault()); + fireCallback(CDEV_SUCCESS, xobj, &resultData); + result = CDEV_SUCCESS; + } + break; + + case cdevClientRequestObject::SET_DEFAULT_MESSAGE: + { + cdevData resultData; + char DefaultServer[128]; + + *DefaultServer = 0; + + if(in!=NULL && in->get("value", DefaultServer, 128)==CDEV_SUCCESS && *DefaultServer!=0) + { + setDefault(DefaultServer); + } + else status=CDEV_ERROR; + fireCallback(status, xobj, &resultData); + result = CDEV_SUCCESS; + } + break; + + case cdevClientRequestObject::DISCONNECT_MESSAGE: + { + cdevData resultData; + char server [128]; + int status; + + if(xobj.reqObj_->getContext().get("server", server, 128)==CDEV_SUCCESS) + { + disconnect(server); + status = CDEV_SUCCESS; + } + else status = CDEV_ERROR; + + fireCallback(status, xobj, &resultData); + result = CDEV_SUCCESS; + } + break; + + default: + break; + } + return result; + } + + +// ***************************************************************************** +// * cdevClientService::isPacketValid : +// * This method is called by the ServerHandler after it has been restarted. +// * If the ServerHandler inherits packets that are already in the queue, it +// * will call this method for each packet in order to determine if they are +// * valid. If the packets are no longer valid (i.e., there is no longer +// * a cdevTransObj associated with them, they will be deleted. Otherwise, +// * they will be submitted to the server. +// ***************************************************************************** +int cdevClientService::isPacketValid ( char * binary, size_t binaryLen ) + { + int result; + + if(binary!=NULL && binaryLen>0) + { + cdevMessageBinary message; + unsigned int trans; + message.getTransIndex(trans); + message.attachData(binary, binaryLen); + result = transactions.find(trans)?1:0; + message.detachData(); + } + else result = 0; + + return result; + } + + +// ***************************************************************************** +// * cdevClientService::callback : +// * This method is called by the cdevData object whenever a new tag is +// * added. +// ***************************************************************************** +void cdevClientService::callback ( int, char * ) + { + for(int idx=0; connections[idx]!=NULL; idx++) + { + connections[idx]->setTagChangeFlag(1); + } + } + + +// ***************************************************************************** +// * cdevClientService::getCallbackArg : +// * This method creates a unique callback argument that can be passed to the +// * CDEV Name Server service to allow it to differentiate between two +// * servers that are being accessed through the same service. +// ***************************************************************************** +NSCallbackArg * cdevClientService::getCallbackArg ( char * server ) + { + NSCallbackArg * ptr; + if((ptr = (NSCallbackArg *)nsCallbackArgs.find(server))==NULL) + { + ptr = new NSCallbackArg(server, this); + nsCallbackArgs.insert(ptr->server, ptr); + } + return ptr; + } + +// ***************************************************************************** +// * cdevClientTransaction::operator new: +// * Allocation function for the object. It will get the next preallocated +// * cdevClientTransaction object from the free list, or, if none are available, +// * refill the free list and then return a new cdevClientTransaction object. +// ***************************************************************************** +void * cdevClientTransaction::operator new ( size_t ) + { + cdevClientTransaction * result = NULL; + + if(freeList_==NULL) + { + freeList_ = ::new cdevClientTransaction[ALLOCATION_COUNT]; + for(int i=0; ifreeListNext_; + result->freeListNext_ = NULL; + } + + return result; + } + +// ***************************************************************************** +// * cdevClientTransaction::delete: +// * Rather than deallocating the cdevClientTransaction object, this function +// * returns it to the free list where it may be retrieved by a later call +// * of new. +// ***************************************************************************** +void cdevClientTransaction::operator delete ( void * ptr ) + { + cdevClientTransaction * node = (cdevClientTransaction *)ptr; + if(node != NULL) + { + node->freeListNext_ = freeList_; + freeList_ = node; + } + } + +// ***************************************************************************** +// * cdevClienTransaction::cdevClientTransaction : +// * Array constructor for the cdevClientTransaction object. +// ***************************************************************************** +cdevClientTransaction::cdevClientTransaction (void) + : xobj (NULL), + permanent (0), + statusCode (0), + restartable(0), + contextID (0), + userData (NULL) + { + *server = 0; + } + + +// ***************************************************************************** +// * cdevClienTransaction::cdevClientTransaction : +// * Constructor for the cdevClientTransaction object. +// ***************************************************************************** +cdevClientTransaction::cdevClientTransaction (cdevTranObj & XObj, ServerHandler &handler, + int Restartable, cdevData * data, + unsigned ContextID) + : xobj (&XObj), + permanent (0), + statusCode (0), + restartable(Restartable), + contextID (ContextID), + userData (NULL) + { + permanent = ((cdevClientRequestObject *)xobj->reqObj_)->getCommandCode()== + cdevClientRequestObject::MONITOR_ON_COMMAND; + strncpy(server, handler.getServer(), 256); + server[255] = 0; + + if(restartable && data) userData = new cdevData(*data); + else userData = data; + } + +// ***************************************************************************** +// * cdevClientTransaction::~cdevClientTransaction : +// * Destructor for the cdevClientTransaction object. +// ***************************************************************************** +cdevClientTransaction::~cdevClientTransaction ( void ) + { + if(xobj) delete xobj; + if(restartable && userData) delete userData; + } + + +// ***************************************************************************** +// * cdevClientTransaction::reconnect : +// * This method will attempt to recreate a connection for a server to +// * a specified host and port. If the host and port are not specified, +// * the the cdevClientService::connect and cdevClientService::find methods +// * will be used to reattach to the specified server. +// ***************************************************************************** +void cdevClientTransaction::reconnect ( char * host, unsigned short port, unsigned key) + { + cdevClientService &service = (cdevClientService &)xobj->reqObj_->service(); + + if(key==0) key = service.transactions.find((void *)this); + + if(restartable && statusCode<0 && key) + { + ServerHandler *handler = NULL; + + // ************************************************************* + // * Use the find method to locate the ServerHandler if + // * possible, otherwise use the connect method to reconnect to + // * the server. + // ************************************************************* + if((handler=service.connections.find(server))==NULL) + handler = service.connect(server, host, port); + + // ************************************************************* + // * If a connection was established to the server, then use + // * the enqueue method to resubmit the request to the server. + // ************************************************************* + if(handler!=NULL) + { + if(service.enqueue(handler, *this, key)==CDEV_SUCCESS) + { + cdevData cData; + statusCode = 0; + xobj->userCallback_->fireCallback + (CDEV_RECONNECTED, + xobj->userCallback_->userarg(), + *xobj->reqObj_, cData, 1); + } + } + } + } diff --git a/extensions/cdevGenericServer/lib/cdevContextMap.cc b/extensions/cdevGenericServer/lib/cdevContextMap.cc new file mode 100755 index 0000000..145e407 --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevContextMap.cc @@ -0,0 +1,123 @@ +#include + +// ***************************************************************************** +// * cdevContextMap::cdevContextMap : +// * This is the constructor for the class and it initializes all +// * data items to 0 or NULL... +// ***************************************************************************** +cdevContextMap::cdevContextMap ( void ) + : entries(NULL), maximum(0), cnt(0) + {} + +// ***************************************************************************** +// * cdevContextMap::~cdevContextMap : +// * This is the destructor for the class and it will delete any +// * cdevData objects that have been allocated using new and will +// * then free the array that was allocated using malloc or realloc. +// ***************************************************************************** +cdevContextMap::~cdevContextMap ( void ) + { + if(entries!=NULL) + { + for(int i=0; i=maximum) resize(); + entries[i] = new cdevData(context); + cnt++; + } + return i; + } + + +// ***************************************************************************** +// * cdevContextMap::find : +// * This method allows the caller to obtain the index of a context +// * cdevData object that matches the cdevData object he provides... +// * If a matching context object cannot be found, then -1 will be +// * returned. +// ***************************************************************************** +int cdevContextMap::find ( cdevData & context ) + { + int i; + int found; + + for(i=0; + iasciiDump(fp); + fflush(fp); + } + fprintf(fp, "----------------------------------------------------------\n"); + fprintf(fp, " End of Diagnostic Dump of CDEV Context Map\n"); + fprintf(fp, "----------------------------------------------------------\n\n"); + fflush(fp); + } diff --git a/extensions/cdevGenericServer/lib/cdevEventHandler.cc b/extensions/cdevGenericServer/lib/cdevEventHandler.cc new file mode 100755 index 0000000..08f1251 --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevEventHandler.cc @@ -0,0 +1,96 @@ +#include "cdevReactor.h" +#include "cdevEventHandler.h" +#include + +cdevEventHandler::cdevEventHandler ( void ) + : mask(0), + next(NULL), + timeoutRate(0, 0), + nextTimeout(0, 0), + reactor(NULL) + { + } + + +cdevEventHandler::~cdevEventHandler ( void ) + { + if(reactor!=NULL) reactor->extractHandler(this); + handleClose(); + } + +void cdevEventHandler::setHandle ( int ) + { + } + +int cdevEventHandler::getHandle ( void ) const + { + return -1; + } + +void cdevEventHandler::setReactor (cdevReactor * r) + { + reactor = r; + } + + +cdevEventHandler * cdevEventHandler::getNext (void ) + { + return next; + } + + +void cdevEventHandler::setNext (cdevEventHandler * n) + { + next = n; + } + + +int cdevEventHandler::getMask ( void ) + { + return mask; + } + + +cdevReactor * cdevEventHandler::getReactor ( void ) + { + return reactor; + } + + +cdevTime & cdevEventHandler::getTimeoutRate ( void ) + { + return timeoutRate; + } + +cdevTime & cdevEventHandler::getNextTimeout ( void ) + { + return nextTimeout; + } + + +void cdevEventHandler::setMask ( unsigned Mask ) + { + mask = (Mask&(READ_MASK|WRITE_MASK|EXCEPT_MASK|DONT_CALL)); + } + + +void cdevEventHandler::setTimeoutRate ( cdevTime time ) + { + timeoutRate = time; + resetTimer(); + } + + +void cdevEventHandler::resetTimer ( void ) + { + nextTimeout.setTime(); + nextTimeout = nextTimeout+getTimeoutRate(); + } + +int cdevEventHandler::handleInput ( void ) { return 0; } +int cdevEventHandler::handleOutput ( void ) { return 0; } +int cdevEventHandler::handleExcept ( void ) { return 0; } +int cdevEventHandler::handleTimeout ( void ) { return 0; } +int cdevEventHandler::handleSignal ( void ) { return -1; } +int cdevEventHandler::handleClose ( void ) { return 0; } + diff --git a/extensions/cdevGenericServer/lib/cdevHandleSet.cc b/extensions/cdevGenericServer/lib/cdevHandleSet.cc new file mode 100644 index 0000000..69c0e40 --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevHandleSet.cc @@ -0,0 +1,304 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// FD_Set Wrapper Based on ACE +// + +#include "cdevHandleSet.h" + +#ifndef __VMS + #ifndef __linux + extern "C" bzero (char *, int); + #endif +#else + extern "C" bzero (char *, unsigned int); +#endif + +#if defined(__VMS) && defined(_TGV_MULTINET) + // ********************************************************************* + // * Unfortunately when you use TGV Multinet, the bit offsets in the + // * file * descriptor bitmasks used by select() cannot be found by + // * simply using the value of the file descriptor. Fortunately, there + // * is a simple relationship between the file descriptor value and the + // * desired bit offset. + // * (These macros are required because this file accesses the file + // * descriptor bitmasks directly, without using the FD_SET(), FD_CLR(), + // * FD_ISSSET() macros). + // ********************************************************************* + #define FD_TO_BIT_OFFSET( fd ) ((fd)/CHANNELSIZE) + #define FD_FROM_BIT_OFFSET( ibit ) ((ibit)*CHANNELSIZE) +#else + // ********************************************************************* + // * Under most operating systems the file descriptor value and the + // * associated bit offset are one and the same. + // ********************************************************************* + #define FD_TO_BIT_OFFSET( fd ) (fd) + #define FD_FROM_BIT_OFFSET( ibit ) (ibit) +#endif + +#ifdef CDEV_HAS_UNDERSCORE_FDBITS +#define fds_bits __fds_bits +#endif + +inline int BIT_ENABLED (unsigned long word, int bit = 1) { return (word & bit) != 0; } +inline int BIT_DISABLED (unsigned long word, int bit = 1) { return (word & bit) == 0; } +inline void SET_BIT (unsigned long &word, int bit) { word |= bit; } +inline void CLR_BIT (unsigned long &word, int bit) { word &= ~bit; } + +const char cdevHandleSet::nbits_[256] = + { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, + }; + +// ***************************************************************************** +// * Counts the number of bits enabled in N. Uses a table lookup to speed up +// * the count. +// ***************************************************************************** + +int cdevHandleSet::count_bits (unsigned long n) const + { + return (cdevHandleSet::nbits_[n & 0xff] + cdevHandleSet::nbits_[(n >> 8) & 0xff] + + cdevHandleSet::nbits_[(n >> 16) & 0xff] + cdevHandleSet::nbits_[n >> 24]); + } + +void cdevHandleSetIterator::operator++ (void) + { + #ifdef _WIN32 + this->index_++; + #else + this->val_ = (this->val_ >> 1) & cdevHandleSet::MSB_MASK; + this->num_++; + + if (this->val_ == 0) + { + for (this->index_++; + this->index_ < cdevHandleSet::NUM_WORDS && fds_.mask_.fds_bits[this->index_] == 0; + this->index_++); + + if (this->index_ == cdevHandleSet::NUM_WORDS) + { + this->num_ = fds_.max_handle_ + 1; + return; + } + else + { + this->val_ = fds_.mask_.fds_bits[this->index_]; + this->num_ = this->index_ * cdevHandleSet::WORD_SIZE; + } + } + + for (; BIT_DISABLED (this->val_); this->num_++) + this->val_ = (this->val_ >> 1) & cdevHandleSet::MSB_MASK; + #endif + } + +cdevHandleSetIterator::cdevHandleSetIterator (cdevHandleSet &f) + : fds_ (f), index_ (0), num_ (f.size_ == 0 ? f.max_handle_ + 1 : 0) + { + #ifndef _WIN32 + for (; fds_.mask_.fds_bits[this->index_] == 0; this->index_++) + this->num_ += cdevHandleSet::WORD_SIZE; + + for (this->val_ = this->fds_.mask_.fds_bits[this->index_]; + (BIT_DISABLED (this->val_)) && this->num_ < cdevHandleSet::MAX_SIZE; + this->num_++) + this->val_ = (this->val_ >> 1) & cdevHandleSet::MSB_MASK; + #endif + } + +// ***************************************************************************** +// * Synchronize the underlying FD_SET with the MAX_FD and the SIZE. +// ***************************************************************************** +void cdevHandleSet::sync (int max) + { + #ifndef _WIN32 + this->size_ = 0; + + for (int i = max / cdevHandleSet::WORD_SIZE; i >= 0; i--) + this->size_ += count_bits (this->mask_.fds_bits[i]); + + this->set_max (max); + #endif + } + +// ***************************************************************************** +// * Resets the MAX_FD after a clear of the original MAX_FD. +// ***************************************************************************** +void cdevHandleSet::set_max (int current_max) + { + #ifndef _WIN32 + int i = 0; + + if (this->size_ == 0) + this->max_handle_ = -1; + else + { + for (i = current_max / cdevHandleSet::WORD_SIZE; + this->mask_.fds_bits[i] == 0; + i--) + ; + + this->max_handle_ = i * cdevHandleSet::WORD_SIZE; + for (fd_mask val = this->mask_.fds_bits[i]; + (val & ~1) != 0; + val = (val >> 1) & cdevHandleSet::MSB_MASK) + this->max_handle_++; + } + #endif + } + +// ***************************************************************************** +// * Debugging method that prints out the underlying mask. +// ***************************************************************************** +int cdevHandleSet::asciiDump (FILE * fp) + { + fprintf(fp, "[ "); + for (int i = 0; i < this->max_handle_ + 1; i++) + if (this->is_set (i)) + fprintf(fp," %d ", i); + + fprintf(fp, " ]"); + return this->size_; + } + +void cdevHandleSet::reset (void) + { + this->max_handle_ = -1; + this->size_ = 0; + FD_ZERO (&this->mask_); + } + +// ***************************************************************************** +// * Constructor, initializes the bitmask to all 0s. +// ***************************************************************************** +cdevHandleSet::cdevHandleSet (void) + { + this->reset (); + } + +cdevHandleSet::cdevHandleSet (const fd_set &fd_mask): size_ (0) + { + memcpy ((void *) &this->mask_, (void *) &fd_mask, sizeof this->mask_); + // sync is empty for WIN32 + this->sync (FD_SETSIZE); + } + +// ***************************************************************************** +// * Returns the number of the large bit. +// ***************************************************************************** +int cdevHandleSet::max_set (void) const + { + return this->max_handle_; + } + +// ***************************************************************************** +// * Checks whether FD is enabled. +// ***************************************************************************** +int cdevHandleSet::is_set (int fd) const + { + #ifdef _WIN32 + return FD_ISSET ((SOCKET)fd, &this->mask_); + #else + return FD_ISSET (fd, &this->mask_); + #endif + } + +// ***************************************************************************** +// * Enables the FD. +// ***************************************************************************** +void cdevHandleSet::set_bit (int fd) + { + if (!this->is_set (fd)) + { + #ifdef _WIN32 + FD_SET ((SOCKET)fd, &this->mask_); + #else + FD_SET (fd, &this->mask_); + this->size_++; + // ***************************************************** + // * again VMS system has different idea + // ***************************************************** + #if defined(__VMS) && defined(_TGV_MULTINET) + if (FD_TO_BIT_OFFSET(fd) > this->max_handle_) + this->max_handle_ = FD_TO_BIT_OFFSET(fd); + #else + if (fd > this->max_handle_) + this->max_handle_ = fd; + #endif + #endif + } + } + +// ***************************************************************************** +// * Disables the FD. +// ***************************************************************************** +void cdevHandleSet::clr_bit (int fd) + { + if (this->is_set (fd)) + { + #ifdef _WIN32 + FD_CLR ((SOCKET)fd, &this->mask_); + #else + FD_CLR (fd, &this->mask_); + this->size_--; + + #if defined(__VMS) && defined(_TGV_MULTINET) + if (FD_TO_BIT_OFFSET(fd) == this->max_handle_) + this->set_max (this->max_handle_); + #else + if (fd == this->max_handle_) + this->set_max (this->max_handle_); + #endif + #endif + } + } + +// ***************************************************************************** +// * Returns a count of the number of enabled bits. +// ***************************************************************************** +int cdevHandleSet::num_set (void) const + { + #ifdef _WIN32 + return this->mask_.fd_count; + #else + return this->size_; + #endif + } + +int cdevHandleSetIterator::operator () (void) + { + #ifdef _WIN32 + return this->index_ < this->fds_.mask_.fd_count + ? fds_.mask_.fd_array[this->index_] : -1; + #else + #if defined(__VMS) && defined(_TGV_MULTINET) + return FD_FROM_BIT_OFFSET(this->num_ <= this->fds_.max_handle_ + ? this->num_ :-1); + #else + return this->num_ <= this->fds_.max_handle_ + ? this->num_ : -1; + #endif + #endif + } diff --git a/extensions/cdevGenericServer/lib/cdevMessage.cc b/extensions/cdevGenericServer/lib/cdevMessage.cc new file mode 100755 index 0000000..9e8b9e4 --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevMessage.cc @@ -0,0 +1,310 @@ +#include + +// ***************************************************************************** +// * cdevMessage::import : +// * This metod is used by the cdevPacket class to generate a cdevMessage +// * object from a cdevBinaryPacket object. In order for the cdevPacket +// * class to perform this task, the import method and the +// * CDEV_PACKET_VERSION must be registered using the +// * cdevPacket::registerImportMethod function. +// ***************************************************************************** +cdevPacket * cdevMessage::import( cdevPacketBinary & packet) + { + char * binary = NULL; + size_t binaryLen = 0; + + packet.streamOut(&binary, &binaryLen); + + return new cdevMessage(binary, binaryLen); + } + +// ***************************************************************************** +// * cdevMessage::cdevMessage : +// * This is a parameterized constructor for the cdevMessage object. If none +// * of the parameters are specified then this constructor will build a +// * cdevMessage object made completely from defaults. +// ***************************************************************************** +cdevMessage::cdevMessage ( short ClientID, + unsigned TransIndex, + unsigned CancelTransIndex, + unsigned LocalDataIndex, + unsigned ForeignDataIndex, + unsigned OperationCode, + int CompletionCode, + unsigned DeviceCount, + char ** DeviceList, + char * Message, + cdevData * Data, + cdevData * Context, + cdevData * TagMap) + : clientID (ClientID), + transIndex (TransIndex), + cancelTransIndex (CancelTransIndex), + localDataIndex (LocalDataIndex), + foreignDataIndex (ForeignDataIndex), + operationCode (OperationCode), + completionCode (CompletionCode), + deviceCount (DeviceCount), + deviceList (NULL), + message (NULL), + data (NULL), + context (NULL), + tagMap (NULL) + { + saveTbl.rawData=0; + + if(DeviceCount>0 && DeviceList!=NULL) + { + deviceList = (char **)new char * [deviceCount]; + for(int i=0; i0 && Message.deviceList!=NULL) + { + deviceList = (char **)new char * [deviceCount]; + for(int i=0; iasciiDump(fp); + + fprintf(fp, "Context Object : %s", context!=NULL?"\n":"(not specified)\n"); + fflush(fp); + if(context) context->asciiDump(fp); + + fprintf(fp, "Tag Map : %s", tagMap!=NULL?"\n":"(not specified)\n"); + if(tagMap) + { + size_t tagNumCnt = 0; + int * tagNums = NULL; + size_t tagNameCnt = 0; + char ** tagNames = NULL; + + if(tagMap->getElems(1, &tagNumCnt)==CDEV_SUCCESS && + tagMap->getElems(2, &tagNameCnt)==CDEV_SUCCESS && + tagMap->getType (2)==CDEV_STRING && + tagNumCnt==tagNameCnt) + { + char ** tagNames = NULL; + char * singleName = NULL; + + tagNums = new int[tagNumCnt]; + tagMap->get(1, tagNums); + + if(tagNameCnt==1) + { + tagNames = &singleName; + tagMap->find(2, (void *&)singleName); + } + else tagMap->find(2, (void *&)tagNames); + + for(int i=0; i + +const unsigned BIT01 = 1; +const unsigned BIT02 = 2; +const unsigned BIT03 = 4; +const unsigned BIT04 = 8; +const unsigned BIT05 = 16; +const unsigned BIT06 = 32; +const unsigned BIT07 = 64; +const unsigned BIT08 = 128; +const unsigned BIT09 = 256; +const unsigned BIT10 = 512; +const unsigned BIT11 = 1024; +const unsigned BIT12 = 2048; +const unsigned BIT13 = 4096; +const unsigned BIT14 = 8192; +const unsigned BIT15 = 16384; +const unsigned BIT16 = 32768; + +// ***************************************************************************** +// * cdevMessageBinary::map2int ( void ) +// * This method will convert the cdevMessageBinaryMap to a long integer. +// ***************************************************************************** +unsigned cdevMessageBinary::map2int ( cdevMessageBinaryMap mapdata, unsigned & value) + { + value = (mapdata.value.version << 16); + if(mapdata.value.clientIDSet!=0) value |= BIT16; + if(mapdata.value.transIndexSet!=0) value |= BIT15; + if(mapdata.value.cancelTransIndexSet!=0) value |= BIT14; + if(mapdata.value.localDataIndexSet!=0) value |= BIT13; + if(mapdata.value.foreignDataIndexSet!=0) value |= BIT12; + if(mapdata.value.operationCodeSet!=0) value |= BIT11; + if(mapdata.value.completionCodeSet!=0) value |= BIT10; + if(mapdata.value.deviceListSet!=0) value |= BIT09; + if(mapdata.value.messageSet!=0) value |= BIT08; + if(mapdata.value.dataSet!=0) value |= BIT07; + if(mapdata.value.contextSet!=0) value |= BIT06; + if(mapdata.value.tagMapSet!=0) value |= BIT05; + return value; + } + +// ***************************************************************************** +// * cdevMessageBinary::int2map ( void ) +// * This method will convert a long integer to a cdevMessageBinaryMap. +// ***************************************************************************** +cdevMessageBinaryMap cdevMessageBinary::int2map ( cdevMessageBinaryMap &mapdata, unsigned value) + { + mapdata.rawData = 0; + mapdata.value.version = (value >> 16); + mapdata.value.clientIDSet = (value & BIT16)?1:0; + mapdata.value.transIndexSet = (value & BIT15)?1:0; + mapdata.value.cancelTransIndexSet = (value & BIT14)?1:0; + mapdata.value.localDataIndexSet = (value & BIT13)?1:0; + mapdata.value.foreignDataIndexSet = (value & BIT12)?1:0; + mapdata.value.operationCodeSet = (value & BIT11)?1:0; + mapdata.value.completionCodeSet = (value & BIT10)?1:0; + mapdata.value.deviceListSet = (value & BIT09)?1:0; + mapdata.value.messageSet = (value & BIT08)?1:0; + mapdata.value.dataSet = (value & BIT07)?1:0; + mapdata.value.contextSet = (value & BIT06)?1:0; + mapdata.value.tagMapSet = (value & BIT05)?1:0; + return mapdata; + } + +// ***************************************************************************** +// * cdevMessageBinary::cdevMessageBinary : +// * Copy constructaor for the class. Sets all of the variables to the +// * values stored in the referenced objects. +// ***************************************************************************** +cdevMessageBinary::cdevMessageBinary ( cdevMessageBinary & packet ) + : cdevPacketBinary() + { + streamIn(packet.binary, packet.binaryLen); + } + + +// ***************************************************************************** +// * cdevMessageBinary::cdevMessageBinary : +// * This is the default and parameterized constructor. Allows the caller to +// * directly specify each of the components. +// ***************************************************************************** +cdevMessageBinary::cdevMessageBinary ( short clientID, + unsigned transIndex, + unsigned cancelTransIndex, + unsigned localDataIndex, + unsigned foreignDataIndex, + unsigned operationCode, + int completionCode, + unsigned deviceCount, + char ** deviceList, + char * message, + cdevData * data, + cdevData * context, + cdevData * tagMap) + : cdevPacketBinary() + { + set(clientID, transIndex, cancelTransIndex, localDataIndex, + foreignDataIndex, operationCode, completionCode, deviceCount, + deviceList, message, data, context, tagMap); + } + + +// ***************************************************************************** +// * cdevMessageBinary::~cdevMessageBinary : +// * This is the destructor for the class. +// ***************************************************************************** +cdevMessageBinary::~cdevMessageBinary ( void ) + { + // ********************************************************************* + // * Execute a detach on the embedded data to ensure that it is not + // * deleted locally. + // ********************************************************************* + reader.detachData(); + } + + +// ***************************************************************************** +// * cdevMessageBinary::streamIn : +// * The streamIn function will read a memory buffer provided by the caller +// * and then populate the class with these values. This stream remains the +// * property of the caller and he is responsible for deleting it. +// ***************************************************************************** +int cdevMessageBinary::streamIn ( char *stream, size_t len ) + { + int result = -1; + unsigned packetMap = 0; + + // ********************************************************************* + // * Delete the binary data buffer and set its length to 0. + // ********************************************************************* + if(binary!=NULL) + { + delete binary; + binary = NULL; + } + binaryLen = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(stream, len); + + // ********************************************************************* + // * Clear the packet map prior to reading data from the stream. + // ********************************************************************* + map.rawData = 0; + + // ********************************************************************* + // * Read the packet map from the stream. This object contains a bit + // * field that identifies the version of the packet and tells what + // * other components are embedded in the binary stream. + // ********************************************************************* + result = !reader.get(packetMap); + int2map (map, packetMap); + + // ********************************************************************* + // * Before processing anything else, the method must ensure that this + // * packet is of the correct version. Version 1 for this object. + // * + // * Note that reading each field is contingent on the prior fields + // * being read correctly. + // ********************************************************************* + if(!result && map.value.version == CDEV_PACKET_VERSION) + { + binaryLen = len; + binary = new char[binaryLen]; + memcpy(binary, stream, binaryLen); + } + else result = -1; + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + +// ********************************************************************* +// * cdevMessageBinary::attachData : +// * This method allows the caller to assign a preallocated binary +// * buffer to this object. This prevents the cdevMessageBinary class +// * from having to allocate the data. +// ********************************************************************* +int cdevMessageBinary::attachData ( char * stream, size_t len ) + { + int result = -1; + unsigned packetMap = 0; + + // ********************************************************************* + // * Delete the binary data buffer and set its length to 0. + // ********************************************************************* + if(binary!=NULL) + { + delete binary; + binary = NULL; + } + binaryLen = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(stream, len); + + // ********************************************************************* + // * Clear the packet map prior to reading data from the stream. + // ********************************************************************* + map.rawData = 0; + + // ********************************************************************* + // * Read the packet map from the stream. This object contains a bit + // * field that identifies the version of the packet and tells what + // * other components are embedded in the binary stream. + // ********************************************************************* + result = !reader.get(packetMap); + int2map (map, packetMap); + + // ********************************************************************* + // * Before processing anything else, the method must ensure that this + // * packet is of the correct version. Version 1 for this object. + // * + // * Note that reading each field is contingent on the prior fields + // * being read correctly. + // ********************************************************************* + if(!result && map.value.version == CDEV_PACKET_VERSION) + { + binaryLen = len; + binary = stream; + } + else result = -1; + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + +// ***************************************************************************** +// * cdevMessageBinary::asciiDump : +// * This method performs a diagnostic dump of the text representation of the +// * packets contents. +// ***************************************************************************** +void cdevMessageBinary::asciiDump ( FILE * fp ) + { + short clientID; + unsigned transIndex, cancelTransIndex, localDataIndex; + unsigned foreignDataIndex, operationCode, deviceCount; + int completionCode; + char ** deviceList; + char * message; + cdevData temp; + + getClientID(clientID); + getTransIndex(transIndex); + getCancelTransIndex(cancelTransIndex); + getLocalDataIndex(localDataIndex); + getForeignDataIndex(foreignDataIndex); + getOperationCode (operationCode); + getCompletionCode (completionCode); + getDeviceList(deviceList, deviceCount); + getMessage(message); + + fprintf(fp, "----------------------------------------------------------\n"); + fprintf(fp, " Diagnostic Dump of CDEV Packet\n"); + fprintf(fp, "----------------------------------------------------------\n\n"); + fprintf(fp, "Packet Version : %i\n", CDEV_PACKET_VERSION); + fprintf(fp, "Binary Stream Size : %i\n", binaryLen); + fprintf(fp, "Client Identifier : %s\n", clientID==-1?"(not specified)":ltoa(clientID)); + fprintf(fp, "Transaction Index : %s\n", transIndex==0?"(not specified)":ultoa(transIndex)); + fprintf(fp, "Cancel Transaction : %s\n", cancelTransIndex==0?"(not specified)":ultoa(cancelTransIndex)); + fprintf(fp, "Local Data Index : %s\n", localDataIndex==0?"(not specified)":ultoa(localDataIndex)); + fprintf(fp, "Foreign Data Index : %s\n", foreignDataIndex==0?"(not specified)":ultoa(foreignDataIndex)); + fprintf(fp, "Operation Code : %s\n", operationCode==0?"(not specified)":ultoa(operationCode)); + fprintf(fp, "Completion Code : %i\n", completionCode); + fprintf(fp, "Number of Devices : %s\n", deviceCount==0?"(not specified)":ultoa(deviceCount)); + fprintf(fp, "List of Devices : "); + + if(deviceCount==0) fprintf(fp, "(not specified)\n"); + else fprintf(fp, "%s\n", deviceList[0]); + + for(int i=1; i GOTO_CLIENTID) + { + if(map.value.clientIDSet!=0) + result=!xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+XDR_Sizeof((short)1)); + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the clientID. + // ************************************************************* + else if(flag==GOTO_CLIENTID && !map.value.clientIDSet) result=-1; + + + // ************************************************************* + // * If the selected element is beyond the transIndex, then + // * advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_TRANSINDEX) + { + if(!result && map.value.transIndexSet!=0) + result=!xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+XDR_Sizeof((unsigned)1)); + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the transIndex. + // ************************************************************* + else if(flag==GOTO_TRANSINDEX && !map.value.transIndexSet) result=-1; + + + + // ************************************************************* + // * If the selected element is beyond the cancelTransIndex, + // * then advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_CANCELTRANSINDEX) + { + if(!result && map.value.cancelTransIndexSet!=0) + result=!xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+XDR_Sizeof((unsigned)1)); + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the cancelTransIndex. + // ************************************************************* + else if(flag==GOTO_CANCELTRANSINDEX && !map.value.cancelTransIndexSet) result=-1; + + + + // ************************************************************* + // * If the selected element is beyond the localDataIndex, then + // * advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_LOCALDATAINDEX) + { + if(!result && map.value.localDataIndexSet!=0) + result=!xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+XDR_Sizeof((unsigned)1)); + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the localDataIndex. + // ************************************************************* + else if(flag==GOTO_LOCALDATAINDEX && !map.value.localDataIndexSet) result=-1; + + + + // ************************************************************* + // * If the selected element is beyond the foreignDataIndex, then + // * advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_FOREIGNDATAINDEX) + { + if(!result && map.value.foreignDataIndexSet!=0) + result=!xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+XDR_Sizeof((unsigned)1)); + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the foreignDataIndex. + // ************************************************************* + else if(flag==GOTO_FOREIGNDATAINDEX && !map.value.foreignDataIndexSet) result=-1; + + + + // ************************************************************* + // * If the selected element is beyond the operationCode, + // * then advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_OPERATIONCODE) + { + if(!result && map.value.operationCodeSet!=0) + result=!xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+XDR_Sizeof((unsigned)1)); + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the operationCode. + // ************************************************************* + else if(flag==GOTO_OPERATIONCODE && !map.value.operationCodeSet) result=-1; + + + + // ************************************************************* + // * If the selected element is beyond the operationCode, + // * then advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_COMPLETIONCODE) + { + if(!result && map.value.completionCodeSet!=0) + result=!xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+XDR_Sizeof((int)1)); + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the operationCode. + // ************************************************************* + else if(flag==GOTO_COMPLETIONCODE && !map.value.completionCodeSet) result=-1; + + + // ************************************************************* + // * If the selected element is beyond the deviceList, then + // * advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_DEVICELIST) + { + if(!result && map.value.deviceListSet!=0) + { + int deviceCount; + if((result = !Reader.get(deviceCount))==0) + { + // ************************************* + // * Step over each string in the array. + // ************************************* + for(int i=0; i GOTO_MESSAGE) + { + if(!result && map.value.messageSet!=0) + { + slen = Reader.get_string_len(); + slen = XDR_Sizeof((char *)NULL, slen); + result = !xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+slen); + } + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the message. + // ************************************************************* + else if(flag==GOTO_MESSAGE && !map.value.messageSet) result=-1; + + + + // ************************************************************* + // * If the selected element is beyond the data, then + // * advance the buffer to the next item. + // ************************************************************* + if(flag > GOTO_DATA) + { + if(!result && map.value.dataSet!=0) + { + slen = Reader.get_string_len(); + slen = XDR_Sizeof((void *)NULL, slen); + result = !xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+slen); + } + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the data. + // ************************************************************* + else if(flag==GOTO_DATA && !map.value.dataSet) result=-1; + + + + // ************************************************************* + // * If the selected element is beyond the context, then it + // * contains an invalid value and should be cleared. + // ************************************************************* + if(flag > GOTO_CONTEXT) + { + if(!result && map.value.contextSet!=0) + { + slen = Reader.get_string_len(); + slen = XDR_Sizeof((void *)NULL, slen); + result = !xdr_setpos( + Reader.xdr(), + xdr_getpos(Reader.xdr())+slen); + } + } + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the context. + // ************************************************************* + else if(flag==GOTO_CONTEXT && !map.value.contextSet) result=-1; + + + // ************************************************************* + // * If the selected element is beyond the context, then it + // * contains an invalid value and should be cleared. + // ************************************************************* + if(flag > GOTO_TAGMAP) result = -1; + // ************************************************************* + // * Otherwise... set the result to indicate the existence (or + // * non-existence) of the context. + // ************************************************************* + else if(flag==GOTO_TAGMAP && !map.value.tagMapSet) result=-1; + } + + return result; + } + + +// ***************************************************************************** +// * cdevMessageBinary::set : +// * This method will convert the user provided data into the binary stream. +// ***************************************************************************** +void cdevMessageBinary::set ( short clientID, + unsigned transIndex, + unsigned cancelTransIndex, + unsigned localDataIndex, + unsigned foreignDataIndex, + unsigned operationCode, + int completionCode, + unsigned deviceCount, + char ** deviceList, + char * message, + cdevData * data, + cdevData * context, + cdevData * tagMap) + { + unsigned packetMap = 0; + size_t dataLen = 0, dataCnt = 0; + size_t contextLen = 0, contextCnt = 0; + size_t tagMapLen = 0, tagMapCnt = 0; + + if(binary!=NULL) + { + delete binary; + binary = NULL; + } + binaryLen = 0; + + // ********************************************************************* + // * Construct the packet map to indicate which components will be + // * transmitted. + // ********************************************************************* + map.rawData = 0; + map.value.version = CDEV_PACKET_VERSION; + + // ********************************************************************* + // * Because the cdevPacketBinary relies on the ordered existance of the + // * client identifier... this entry will automatically be tagged as + // * present, even though it may contain a default value... + // ********************************************************************* + map.value.clientIDSet = 1; + + // ********************************************************************* + // * All other components will only be marked as present if they have + // * actually been specified. + // ********************************************************************* + if(transIndex > 0) map.value.transIndexSet = 1; + if(cancelTransIndex > 0) map.value.cancelTransIndexSet = 1; + if(localDataIndex > 0) map.value.localDataIndexSet = 1; + if(foreignDataIndex > 0) map.value.foreignDataIndexSet = 1; + if(operationCode > 0) map.value.operationCodeSet = 1; + if(completionCode != 0) map.value.completionCodeSet = 1; + if(deviceCount>0 && deviceList!=NULL) map.value.deviceListSet = 1; + if(message!=NULL) map.value.messageSet = 1; + + if(data!=NULL) data->xdrSize (&dataLen, &dataCnt); + if(context!=NULL) context->xdrSize(&contextLen, &contextCnt); + if(tagMap!=NULL) tagMap->xdrSize (&tagMapLen, &tagMapCnt); + + if(dataCnt > 0) map.value.dataSet = 1; + if(contextCnt > 0) map.value.contextSet = 1; + if(tagMapCnt > 0) map.value.tagMapSet = 1; + + // ********************************************************************* + // * Calculate the total size of the packet. + // ********************************************************************* + binaryLen = XDR_Sizeof( map2int(map, packetMap) ); + if(map.value.clientIDSet!=0) binaryLen += XDR_Sizeof(clientID); + if(map.value.transIndexSet!=0) binaryLen += XDR_Sizeof(transIndex); + if(map.value.cancelTransIndexSet!=0) binaryLen += XDR_Sizeof(cancelTransIndex); + if(map.value.localDataIndexSet!=0) binaryLen += XDR_Sizeof(localDataIndex); + if(map.value.foreignDataIndexSet!=0) binaryLen += XDR_Sizeof(foreignDataIndex); + if(map.value.operationCodeSet!=0) binaryLen += XDR_Sizeof(operationCode); + if(map.value.completionCodeSet!=0) binaryLen += XDR_Sizeof(completionCode); + if(map.value.deviceListSet!=0) + { + binaryLen += XDR_Sizeof(deviceCount); + for(int i=0; ixdrExport(tbuf, dataLen, dataCnt); + xdr_setpos(writer.xdr(), tpos+XDR_Sizeof((void *)NULL, dataLen)); + } + if(map.value.contextSet!=0) + { + tpos = xdr_getpos(writer.xdr()); + writer.put(contextLen); + tbuf = writer.buffer()+xdr_getpos(writer.xdr()); + context->xdrExport(tbuf, contextLen, contextCnt); + xdr_setpos(writer.xdr(), tpos+XDR_Sizeof((void *)NULL, contextLen)); + } + if(map.value.tagMapSet!=0) + { + tpos = xdr_getpos(writer.xdr()); + writer.put(tagMapLen); + tbuf = writer.buffer()+xdr_getpos(writer.xdr()); + tagMap->xdrExport(tbuf, tagMapLen, tagMapCnt); + xdr_setpos(writer.xdr(), tpos+XDR_Sizeof((void *)NULL, tagMapLen)); + } + + writer.detachData(); + } + + +// ***************************************************************************** +// * cdevMessageBinary::getVersion : +// * This method is used to obtain the version number of the packet. +// ***************************************************************************** +int cdevMessageBinary::getVersion ( short & version ) + { + version = CDEV_PACKET_VERSION; + return 0; + } + + +// ***************************************************************************** +// * cdevMessageBinary::getClientID : +// * This method is used to obtain the client identifier for the packet. +// * This method returns 0 on success, or -1 if the clientID was not +// * specified. +// ***************************************************************************** +int cdevMessageBinary::getClientID ( short & clientID ) + { + int result = -1; + clientID = -1; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_CLIENTID))==0) + { + if(map.value.clientIDSet!=0) result=!reader.get(clientID); + } + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + + +// ***************************************************************************** +// * cdevMessageBinary::getTransIndex : +// * This method is used to obtain the transaction object index. This +// * object is used on the client side to obtain a pointer to the transaction +// * object. +// * This method returns 0 on success, or -1 if the transIndex could not +// * be read. +// ***************************************************************************** +int cdevMessageBinary::getTransIndex ( unsigned & transIndex ) + { + int result = -1; + transIndex = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_TRANSINDEX))==0) + { + result = !reader.get(transIndex); + } + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + +// ***************************************************************************** +// * cdevMessageBinary::getCancelTransIndex : +// * This method is used to obtain the identifier of a transaction object +// * that is to be canceled. +// * +// * This method returns 0 on success, or -1 if the cancelCancelTransIndex could not +// * be read. +// ***************************************************************************** +int cdevMessageBinary::getCancelTransIndex ( unsigned & cancelTransIndex ) + { + int result = -1; + cancelTransIndex = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_CANCELTRANSINDEX))==0) + { + result = !reader.get(cancelTransIndex); + } + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + +// ***************************************************************************** +// * cdevMessageBinary::getLocalDataIndex : +// * This method is used to obtain an index to any data that may be +// * maintained on the senders side of the connection. +// * This method returns 0 on success, or -1 if the localDataIndex could +// * not be read. +// ***************************************************************************** +int cdevMessageBinary::getLocalDataIndex ( unsigned & localDataIndex ) + { + int result = -1; + localDataIndex = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_LOCALDATAINDEX))==0) + { + result = !reader.get(localDataIndex); + } + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + +// ***************************************************************************** +// * cdevMessageBinary::getForeignDataIndex : +// * This method is used to obtain an index to any data that may be +// * maintained on the senders side of the connection. +// * This method returns 0 on success, or -1 if the foreignDataIndex could +// * not be read. +// ***************************************************************************** +int cdevMessageBinary::getForeignDataIndex ( unsigned & foreignDataIndex ) + { + int result = -1; + foreignDataIndex = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_FOREIGNDATAINDEX))==0) + { + result = !reader.get(foreignDataIndex); + } + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + +// ***************************************************************************** +// * cdevMessageBinary::getOperationCode : +// * This method is used to obtain the operation code. An operation code may +// * be used by the developer to define a particular message. This is faster +// * to manipulate than the supported string messages. +// ***************************************************************************** +int cdevMessageBinary::getOperationCode ( unsigned & operationCode ) + { + int result = -1; + operationCode = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_OPERATIONCODE))==0) + { + result = !reader.get(operationCode); + } + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + + +// ***************************************************************************** +// * cdevMessageBinary::getCompletionCode : +// * This method is used to obtain the completion code. The completion code +// * is returned by the server to indicate the result code from an operation. +// ***************************************************************************** +int cdevMessageBinary::getCompletionCode ( int & completionCode ) + { + int result = -1; + completionCode = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_COMPLETIONCODE))==0) + { + result = !reader.get(completionCode); + } + + // ********************************************************************* + // * Detach the binary buffer from the XDR_Reader to prevent it from + // * being deleted when the XDR_Reader class is destroyed. + // ********************************************************************* + reader.detachData(); + + return result; + } + +// ***************************************************************************** +// * cdevMessageBinary::getDeviceList : +// * This method is used to obtains an array of device names that are +// * associated with the request. It is the responsibility of the caller +// * to delete each element of the array, and the array itself when they +// * are no longer needed. +// * This method returns 0 on success, or -1 if the deviceList could +// * not be read. +// ***************************************************************************** +int cdevMessageBinary::getDeviceList ( char ** & deviceList, unsigned & deviceCount) + { + int result = -1; + + deviceList = NULL; + deviceCount = 0; + + // ********************************************************************* + // * Attach the data to the XDR_Reader class so that its components + // * can be extracted. + // ********************************************************************* + reader.attachData(binary, binaryLen); + + // ********************************************************************* + // * Reposition the binary structure to point to the correct location + // * and read the data item. + // ********************************************************************* + if((result = setBinaryPosition(reader, GOTO_DEVICELIST))==0) + { + if((result = !reader.get(deviceCount))==0) + { + // ********************************************* + // * Allocate and initialize an array sufficient + // * to hold the contents of the stream. + // ********************************************* + deviceList = new char * [deviceCount]; + memset(deviceList, 0, sizeof(char *)*deviceCount); + + // ********************************************* + // * Read the individual strings into the array. + // * Note that the XDR_Reader will automatically + // * allocate data if the pointers are set to + // * NULL. + // ********************************************* + for(int i=0; i + +// ***************************************************************************** +// * cdevMonitorNode::cdevMonitorEntry Static Variables. +// ***************************************************************************** +int cdevMonitorNode::cdevMonitorEntry::VALUE_TAG = 0; +int cdevMonitorNode::cdevMonitorEntry::STATUS_TAG = 0; +int cdevMonitorNode::cdevMonitorEntry::TIME_TAG = 0; +int cdevMonitorNode::cdevMonitorEntry::DEVICE_TAG = 0; + + +// ***************************************************************************** +// * cdevMonitorData::cdevMonitorData: +// * This is the default constructor. +// ***************************************************************************** +cdevMonitorData::cdevMonitorData ( void ) : + criticalTags(NULL), criticalTagCnt(0), cdevData() + { + } + +// ***************************************************************************** +// * cdevMonitorData::cdevMonitorData: +// * This builds a cdevMonitorData from a cdevData. +// ***************************************************************************** +cdevMonitorData::cdevMonitorData ( const cdevData & data ) : + criticalTags(NULL), criticalTagCnt(0), cdevData(data) + { + } + +// ***************************************************************************** +// * cdevMonitorData::cdevMonitorData: +// * This builds a cdevMonitorData from a cdevMonitorData. +// ***************************************************************************** +cdevMonitorData::cdevMonitorData ( const cdevMonitorData & data ) : + criticalTags(data.criticalTags), + criticalTagCnt(data.criticalTagCnt), + cdevData(*(const cdevData *)&data) + { + } + +// ***************************************************************************** +// * isTagCritical : +// * This method will walk through the list of tags and attempt to find +// * the caller specified tag. This method returns 1 if it is present, or +// * 0 if it is not. +// ***************************************************************************** +int cdevMonitorData::isTagCritical ( int tag ) + { + for(int i=0; inext_) + { + // ***************************** + // * Do not process entries * + // * with CDEV_INVALID as the * + // * dataType or 0 as the tag. * + // ***************************** + if(ptr->dataType_==CDEV_INVALID || + ptr->tag_==0 || + !isTagCritical(ptr->tag_)) continue; + + // ***************************** + // * Calculate the number of * + // * elements in this tagged * + // * data item. * + // ***************************** + int numElements = ptr->dim_!=0?ptr->elems_:1; + + // ***************************** + // * Increment the counter * + // ***************************** + cdevElementCnt++; + + // ***************************** + // * Add the size of the * + // * cdevDataEntries tag_, * + // * dataType_, dim_, elems_. * + // ***************************** + xdrDataSize += 4 * XDR_Sizeof((int)1); + + // ***************************** + // * Add the size of the * + // * cdevBounds data. * + // ***************************** + xdrDataSize += ptr->dim_ * (XDR_Sizeof((int)1) * 2); + + // ***************************** + // * Add the size of the data * + // ***************************** + if (ptr->dataType_==CDEV_BYTE) xdrDataSize += numElements * XDR_Sizeof((unsigned char)'c'); + else if(ptr->dataType_==CDEV_INT16) xdrDataSize += numElements * XDR_Sizeof((short)1); + else if(ptr->dataType_==CDEV_UINT16) xdrDataSize += numElements * XDR_Sizeof((unsigned short)1); + else if(ptr->dataType_==CDEV_INT32) xdrDataSize += numElements * XDR_Sizeof((long)1); + else if(ptr->dataType_==CDEV_UINT32) xdrDataSize += numElements * XDR_Sizeof((unsigned long)1); + else if(ptr->dataType_==CDEV_FLOAT) xdrDataSize += numElements * XDR_Sizeof((float)1); + else if(ptr->dataType_==CDEV_DOUBLE) xdrDataSize += numElements * XDR_Sizeof((double)1); + else if(ptr->dataType_==CDEV_STRING) + { + if(numElements==1) xdrDataSize += XDR_Sizeof(ptr->data_.str); + else for(i=0; idata_.strarr[i]); + } + else if(ptr->dataType_==CDEV_TIMESTAMP) xdrDataSize += numElements * XDR_Sizeof(ptr->data_.ts); + } + + *elementCount = cdevElementCnt; + *bufLen = xdrDataSize; + + return *bufLen>0?CDEV_SUCCESS:CDEV_ERROR; + } + + +// ***************************************************************************** +// * xdrExport: +// * This function encapsulates the contents of the cdevData class into a +// * binary stream. This function allocates the buffer and returns the new +// * buffer and the buffer size. +// ***************************************************************************** +int cdevMonitorData::xdrExport ( char ** buf, size_t * bufLen ) +{ + size_t count = 0; + + // ************************************# + // * Calculate the size of the buffer # + // ************************************# + xdrSize(bufLen, &count); + + // ************************************# + // * Allocate the buffer and call the # + // * export function. # + // ************************************# + if((*buf = new char[*bufLen])!=NULL) xdrExport(*buf, *bufLen, count); + + return buf==NULL?CDEV_ERROR:CDEV_SUCCESS; +} + + +// ***************************************************************************** +// * xdrExport: +// * This function encapsulates the contents of the cdevData class into a +// * preallocated binary stream. The buf parameter contains the address of +// * the caller allocated buffer, the bufLen parameter specifies the size +// * of the buffer, and the count parameter specifies the number of tagged +// * data items that will be copied from the cdevData object into the +// * binary stream. +// ***************************************************************************** +int cdevMonitorData::xdrExport ( char * buf, size_t bufLen, size_t count ) + { + cdevDataEntry * ptr; + XDR_Writer writer; + int xdrDataSize = bufLen; + int cdevElementCnt = count; + int i; + + // ************************************# + // * Allocate the buffer # + // ************************************# + writer.attachData(buf, bufLen); + + // ************************************# + // * Transfer the data to the buffer # + // ************************************# + // ************************************* + // * Write the number of elements * + // ************************************* + writer.put(cdevElementCnt); + + // ************************************* + // * Write each valid item. * + // ************************************* + for(ptr = entries; ptr != NULL; ptr = ptr->next_) + { + // ***************************** + // * Do not process entries * + // * with CDEV_INVALID as the * + // * dataType or 0 as the tag. * + // ***************************** + if(ptr->dataType_==CDEV_INVALID || + ptr->tag_==0 || + !isTagCritical(ptr->tag_)) continue; + + // ***************************** + // * Calculate the number of * + // * elements in this tagged * + // * data item. * + // ***************************** + int numElements = ptr->dim_!=0?ptr->elems_:1; + + // ***************************** + // * Decrement the counter * + // ***************************** + cdevElementCnt--; + + // ***************************** + // * Write the tag_, dataType_ * + // * dim_, and elems_ of the * + // * cdevDataEntry object. * + // ***************************** + writer.put((int)ptr->tag_); + writer.put((int)ptr->dataType_); + writer.put((int)ptr->dim_); + writer.put((int)ptr->elems_); + + // ***************************** + // * Write the cdevBounds * + // * values asssociated with * + // * the cdevDataEntry (if any)* + // ***************************** + cdevBounds * bounds = ptr->bounds(); + for(i=0; idim_; i++) + { + writer.put((int)bounds[i].offset); + writer.put((int)bounds[i].length); + } + + // ***************************** + // * Write the data * + // ***************************** + if(ptr->dataType_==CDEV_BYTE) + { + if(numElements==1) writer.put(ptr->data_.cval); + else for(i=0; idata_.cptr[i]); + } + else if(ptr->dataType_==CDEV_INT16) + { + if(numElements==1) writer.put(ptr->data_.sval); + else for(i=0; idata_.sptr[i]); + } + else if(ptr->dataType_==CDEV_UINT16) + { + if(numElements==1) writer.put(ptr->data_.usval); + else for(i=0; idata_.usptr[i]); + } + else if(ptr->dataType_==CDEV_INT32) + { + if(numElements==1) writer.put(ptr->data_.lval); + else for(i=0; idata_.lptr[i]); + } + else if(ptr->dataType_==CDEV_UINT32) + { + if(numElements==1) writer.put(ptr->data_.ulval); + else for(i=0; idata_.ulptr[i]); + } + else if(ptr->dataType_==CDEV_FLOAT) + { + if(numElements==1) writer.put(ptr->data_.fval); + else for(i=0; idata_.fptr[i]); + } + else if(ptr->dataType_==CDEV_DOUBLE) + { + if(numElements==1) writer.put(ptr->data_.dval); + else for(i=0; idata_.dptr[i]); + } + else if(ptr->dataType_==CDEV_STRING) + { + if(numElements==1) writer.put(ptr->data_.str); + else for(i=0; idata_.strarr[i]); + } + else if(ptr->dataType_==CDEV_TIMESTAMP) + { + if(numElements==1) writer.put(ptr->data_.ts); + } + } + + // ************************************* + // * Detach the data from the writer * + // * object before the object is * + // * destroyed. * + // ************************************* + writer.detachData(); + + return CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * cdevMonitorNode::cdevMonitorEntry::cdevMonitorEntry : +// * This is the constructor for the cdevMonitorEntry class that is internal to the +// * cdevMonitorNode class. +// * +// * This constructor will initialize all data items and will then populate +// * the list of triggers with all properties from the context that are +// * marked with 2 or 3. It will then populate the properties list with +// * all properties from the context that have any value other than 0. +// * +// * If not properties are in the context, then the following settings will +// * be used by default... +// * value = 3 +// * status = 1 +// * time = 1 +// * +// * The cdevMessage object becomes the property of the cdevMonitorNode +// * object and should not be accessed again by the caller. +// * +// * The deviceIdx indicates the specific device that is being monitored +// * within a multi-device list. +// ***************************************************************************** +cdevMonitorNode::cdevMonitorEntry::cdevMonitorEntry( cdevMessage * Message, int DeviceIdx=0 ) + : next(NULL), message(Message), triggers(NULL), trigType(NULL), + trigCnt(0), properties(NULL), propCnt(0), deviceIdx(DeviceIdx) + { + // ********************************************************************* + // * Populate the static variables if they have not already been set. + // ********************************************************************* + if(VALUE_TAG==0) + { + cdevData::tagC2I("value", &VALUE_TAG); + cdevData::tagC2I("status", &STATUS_TAG); + cdevData::tagC2I("time", &TIME_TAG); + + // ************************************************************* + // * Added to support multi-device monitors. + // ************************************************************* + cdevData::tagC2I("device", &DEVICE_TAG); + } + + if(message!=NULL) + { + int tag; + size_t tagElems; + int tagVal; + + // ************************************************************* + // * Start by removing the cdevData data if it has been + // * included. This component will not be necessary to process + // * the monitors. + // ************************************************************* + message->setData(NULL); + + // ************************************************************* + // * If the context has been specified, then read the context + // * to determine the number of monitorable data items. + // ************************************************************* + if(message->getContext()!=NULL) + { + cdevData * context = message->getContext(); + cdevDataIterator iter(context); + iter.init(); + + while((tag=iter.tag())!=0) + { + tagElems = 0; + tagVal = 0; + context->getElems(tag, &tagElems); + if(tagElems==1) + { + context->get(tag, &tagVal); + if(tagVal>1) trigCnt++; + if(tagVal>0) propCnt++; + } + ++iter; + } + // ***************************************************** + // * If the number of monitorable data items is greater + // * than 0, then allocate a sufficient buffer and copy + // * the tag names and tag types into the buffer. + // ***************************************************** + if(trigCnt>0) + { + // ********************************************* + // * Added to support multi-device list. + // ********************************************* + if(message->getDeviceCount()>1) propCnt++; + + iter.init(); + triggers = new int[trigCnt+trigCnt+propCnt]; + trigType = &triggers[trigCnt]; + properties = &triggers[trigCnt+trigCnt]; + trigCnt = 0; + propCnt = 0; + while((tag=iter.tag())!=0) + { + tagElems = 0; + tagVal = 0; + context->getElems(tag, &tagElems); + if(tagElems==1) + { + context->get(tag, &tagVal); + if(tagVal>1) + { + triggers[trigCnt] = tag; + trigType[trigCnt++] = tagVal; + } + if(tagVal>0) properties[propCnt++] = tag; + } + ++iter; + } + // ********************************************* + // * Added to support multi-device list. + // ********************************************* + if(message->getDeviceCount()>1) + properties[propCnt++] = DEVICE_TAG; + } + } + + // ************************************************************* + // * If not tags were specified or the context was blank... then + // * use the default setup. + // ************************************************************* + if(trigCnt<=0) + { + trigCnt = 1; + propCnt = 3; + + // ***************************************************** + // * Added to support multi-device list. + // ***************************************************** + if(message->getDeviceCount()>1) propCnt++; + + triggers = new int[2+propCnt]; + trigType = &triggers[1]; + properties = &triggers[2]; + triggers[0] = VALUE_TAG; + trigType[0] = 3; + properties[0] = VALUE_TAG; + properties[1] = STATUS_TAG; + properties[2] = TIME_TAG; + // ***************************************************** + // * Added to support multi-device list. + // ***************************************************** + if(message->getDeviceCount()>1) properties[3] = DEVICE_TAG; + } + } + } + + +// ***************************************************************************** +// * cdevMonitorNode::cdevMonitorEntry::~cdevMonitorEntry : +// * This is the destructor for the node object that is internal to the +// * cdevMonitorNode class. It is responsible for deleteing the cdevMessage +// * object and freeing any memory that was allocated to the triggers +// * object. +// * +// * Note that this destructor will delete all of the nodes that are stored +// * below this one in the list. +// ****************************************************************************** +cdevMonitorNode::cdevMonitorEntry::~cdevMonitorEntry ( void ) + { + if(message) delete message; + if(triggers) delete triggers; + if(next!=NULL) delete next; + } + + +// ***************************************************************************** +// * cdevMonitorNode::cdevMonitorNode : +// * This is the constructor for the cdevMonitorNode class. It will save a +// * copy of the Parent variable and will use the user specified Device and +// * Attrib to create the hashString. +// ***************************************************************************** +cdevMonitorNode::cdevMonitorNode ( cdevMonitorTable * Parent, + char * Device, + char * Attrib ) + : parent(Parent), hashString(NULL), nodes(NULL) + { + hashString = new char[strlen(Device)+strlen(Attrib)+2]; + sprintf(hashString, "%s %s", Device, Attrib); + } + + +// ***************************************************************************** +// * cdevMonitorNode::~cdevMonitorNode : +// * This is the destructor for the cdevMonitorNode object. It will delete +// * the hashString and each node from the list of monitors. +// ***************************************************************************** +cdevMonitorNode::~cdevMonitorNode ( void ) + { + if(hashString) delete hashString; + if(nodes) + { + // ************************************************************* + // * Prior to deleteing itself, this class will first fire its + // * monitors once more using a 1 in the endOfTransaction + // * parameter in order to inform the client side that it will + // * receive no further transactions. + // ************************************************************* + cdevMonitorEntry * node = nodes; + while(node) + { + fireMonitor(node, -1, &mData, 1); + node = node->next; + } + delete nodes; + } + } + +// ***************************************************************************** +// * cdevMonitorNode::insertMonitor : +// * This method is used to add a new monitor for the device / attribute +// * pair associated with this object. +// * +// * The cdevData object that is provided in the cdevData object is the +// * collection of all current property values for the device / attribute +// * pair. This data will be used to automatically dispatch the first +// * callback when the monitor is initially installed. +// * +// * The deviceIdx indicates the specific device that is being monitored +// * within a multi-device list. +// ***************************************************************************** +int cdevMonitorNode::insertMonitor ( cdevMessage * request, + cdevData * data, + int deviceIdx = 0 ) + { + int result = 0; + cdevMonitorEntry * node = new cdevMonitorEntry(request, deviceIdx); + if(node->trigCnt > 0) + { + node->next = nodes; + nodes = node; + } + else { + delete node; + result = -1; + } + if(data!=NULL) + { + mData = *data; + fireMonitor(node, -1, &mData); + } + return result; + } + +// ***************************************************************************** +// * cdevMonitorNode::removeMonitor : +// * This method is used to remove a specific monitor by submitting a +// * cdevMessage that contains the transaction index to be canceled in the +// * cancelTransIndex element. +// ***************************************************************************** +int cdevMonitorNode::removeMonitor ( cdevMessage * request ) + { + return request==NULL?-1:removeMonitor(request->getCancelTransIndex()); + } + +// ***************************************************************************** +// * cdevMonitorNode::removeMonitor : +// * This method is used to remove a specific monitor by submitting a +// * the transaction index to be canceled. +// ***************************************************************************** +int cdevMonitorNode::removeMonitor ( unsigned cancelTransIndex ) + { + int result = -1; + cdevMonitorEntry * node = nodes, *prev = NULL; + + while(node!=NULL && + node->message->getTransIndex() != cancelTransIndex) + { + prev = node; + node = node->next; + } + if(node!=NULL) + { + if(prev==NULL) nodes = node->next; + else prev->next = node->next; + node->next = NULL; + + // ************************************************************* + // * This code portion added to inform client side that the + // * monitor is terminating. When a monitor returns an + // * operationCode of 0 - it indicates that there will be no + // * further data transmissions. + // * + // * The 1 provided in the endOfTransaction parameter indicates + // * that this transaction is finished. + // ************************************************************* + fireMonitor(node, -1, &mData, 1); + + delete node; + result = 0; + } + return result; + } + + +// ***************************************************************************** +// * cdevMonitorNode::removeClientMonitors : +// * This method is used to remove all nodes that are associated with a +// * specified clientID. +// ***************************************************************************** +int cdevMonitorNode::removeClientMonitors ( short clientID, int fire ) + { + cdevMonitorEntry * node = nodes, *prev = NULL; + while(node!=NULL) + { + if(node->message->getClientID() == clientID) + { + cdevMonitorEntry * nextcdevMonitorEntry = node->next; + node->next = NULL; + + // ***************************************************** + // * This code portion added to inform client side that + // * the monitor is terminating. When a monitor returns + // * an operationCode of 0 - it indicates that there + // * will be no further data transmissions. + // * + // * The 1 provided in the endOfTransaction parameter + // * indicates that this transaction is finished. + // ***************************************************** + if(fire) fireMonitor(node, -1, &mData, 1); + + delete node; + + if(prev==NULL) nodes = nextcdevMonitorEntry; + else prev->next = nextcdevMonitorEntry; + node = nextcdevMonitorEntry; + } + else { + prev = node; + node = node->next; + } + } + return 0; + } + +// ***************************************************************************** +// * cdevMonitorNode::fireMonitor : +// * This method is used to submit a change to a monitored property. If the +// * value of property is NULL, then all of the trigger properties will be +// * fired. +// * +// * Note that the data parameter should be populated with all of the +// * properties that are associated with the particular device / attribute +// * pair. +// ***************************************************************************** +int cdevMonitorNode::fireMonitor( char * property, cdevData * data ) + { + int tag = -1; + if(property!=NULL) cdevData::tagC2I(property, &tag); + return fireMonitor(tag, data); + } + + +// ***************************************************************************** +// * cdevMonitorNode::fireMonitor : +// * This method is used to submit a change to a monitored property. If the +// * value of property is -1, then it will fire all monitors that are listed +// * in the triggers parameter. +// * +// * Note that the data parameter should be populated with all of the +// * properties that are associated with the particular device / attribute +// * pair. +// * +// * This method will return 0 if any monitors were actually dispatched, +// * otherwise it will return -1. +// ***************************************************************************** +int cdevMonitorNode::fireMonitor( int property, cdevData * data ) + { + int result = -1; + cdevMonitorEntry * node = nodes; + + // ********************************************************************* + // * Attach the data that is contained in the cdevData object to the + // * cdevMonitorData object. + // ********************************************************************* + if(data!=NULL) + { + // ************************************************************* + // * Note here I am copying the contents of the user provided + // * data to the mData structure that is local to the + // * cdevMonitorNode. + // ************************************************************* + mData = *data; + while(node!=NULL) + { + if(fireMonitor(node, property, &mData)==0) result = 0; + node = node->next; + } + } + return result; + } + +// ***************************************************************************** +// * cdevMonitorNode::fireMonitor : +// * This method is used to submit a change to a monitored property. If the +// * value of property is -1, then it will fire all monitors that are listed +// * in the triggers parameter. +// * +// * The endOfTransaction flag indicates that this is the last monitor that +// * will be returned in association with this cdevMonitorNode and, +// * therefore, the cdevMessage's operationCode should be set to indicate +// * that. +// * +// * Note that the data parameter should be populated with all of the +// * properties that are associated with the particular device / attribute +// * pair. +// * +// * This method will return 0 if any monitors were actually dispatched, +// * otherwise it will return -1. +// ***************************************************************************** +int cdevMonitorNode::fireMonitor( cdevMonitorEntry * entry, + int property, + cdevMonitorData *data, + int endOfTransaction ) + { + int result = -1; + + if(entry!=NULL && data!=NULL) + { + int found = 0; + + // ************************************************************* + // * An operationCode value with bit one set indicates that this + // * is NOT the end of the transaction, an operationCode value + // * with bit one unset indicates that this IS the end of the + // * transaction. + // ************************************************************* + entry->message->setOperationCode(endOfTransaction?0:1); + + for(int i=0; !found && itrigCnt; i++) + { + if(property<0 || entry->triggers[i]==property) + { + if(property>0) found = 1; + // ********************************************* + // * Trigger type 3 means that the callback + // * wants the changed value and all other + // * values that were specified in the + // * context. + // ********************************************* + if(entry->trigType[i]==3) + data->setCriticalTags(entry->properties, + entry->propCnt); + + // ********************************************* + // * Trigger type 2 means that the callback + // * wants only the changed value. + // ********************************************* + if(entry->trigType[i]==2) + data->setCriticalTags(&entry->triggers[i], 1); + + // ********************************************* + // * Determine if the changed data item exists + // * in the user provided data. If it does, + // * then execute the fireCallback method on + // * the cdevMonitorTable to dispatch the + // * monitor. + // ********************************************* + if(data->getType(entry->triggers[i])!=CDEV_INVALID) + { + // ************************************* + // * Added to support multi-device + // ************************************* + if(entry->message->getDeviceCount()>1) + data->insert(cdevMonitorEntry::DEVICE_TAG, + entry->message->getDeviceList() + [entry->deviceIdx]); + + entry->message->setData(data, 1); + parent->fireCallback(entry->message); + + // ************************************* + // * Added to support multi-device + // ************************************* + if(entry->message->getDeviceCount()>0) + data->remove(cdevMonitorEntry::DEVICE_TAG); + + result = 0; + } + } + } + } + + return result; + } + + +// ***************************************************************************** +// * cdevMonitorTable::cdevMonitorTable : +// * This is the constructor for the cdevMonitortable class. This class +// * contains a hash table that maintains a list of all of the monitored +// * device / attribute pairs on the system. +// ***************************************************************************** +cdevMonitorTable::cdevMonitorTable ( void ) + : monitors(0) + { + } + +// ***************************************************************************** +// * cdevMonitorTable::~cdevMonitorTable : +// * This method walks through the monitors hash table and deletes all +// * cdevMonitorNodes that have been allocated. +// ***************************************************************************** +cdevMonitorTable::~cdevMonitorTable ( void ) + { + char * ptr; + StringHashIterator iter(&monitors); + + iter.first(); + while((ptr= iter.key())!=NULL) + { + cdevMonitorNode * node = (cdevMonitorNode *)iter.data(); + monitors.remove(ptr); + delete node; + iter.first(); + } + } + +// ***************************************************************************** +// * cdevMonitorTable::insertMonitor: +// * This method allows the caller to add a new monitored device / attribute +// * pair to the cdevMonitorTable. +// * +// * The cdevData object that is provided in the cdevData object is the +// * collection of all current property values for the device / attribute +// * pair. This data will be used to automatically dispatch the first +// * callback when the monitor is initially installed. +// ***************************************************************************** +int cdevMonitorTable::insertMonitor ( cdevMessage * request, cdevData * data ) + { + return insertMonitor(request, &data, 1); + } + + +// ***************************************************************************** +// * cdevMonitorTable::insertMonitor: +// * This method allows the caller to add a new monitored device / attribute +// * pair to the cdevMonitorTable. +// * +// * The cdevData objects that are provided in the data parameter are the +// * initial values for each item in the deviceList in sequence. This data +// * will be used to automatically dispatch the first callback when the +// * monitor is initially installed. +// ***************************************************************************** +int cdevMonitorTable::insertMonitor ( cdevMessage * request, cdevData ** data, size_t dataCnt ) + { + if(request!=NULL && request->getDeviceList()!=NULL && request->getMessage()!=NULL) + { + char * attrib = strchr(request->getMessage(), ' '); + if(attrib) + { + attrib++; + cdevMonitorNode * node; + cdevMessage ** msgList; + + // ***************************************************** + // * Allocate additional cdevMessage objects if a + // * deviceList greater than 1 is specified. + // ***************************************************** + if(request->getDeviceCount()>1) + { + msgList = new cdevMessage *[request->getDeviceCount()]; + msgList[0] = request; + } + else msgList = &request; + + // ***************************************************** + // * Walk through each device in the list. + // ***************************************************** + for(int i=0; igetDeviceCount(); i++) + { + if(i>0) msgList[i] = new cdevMessage(*request); + if((node=findMonitor(request->getDeviceList()[i], attrib))==NULL) + { + node = new cdevMonitorNode(this, request->getDeviceList()[i], attrib); + monitors.insert(node->getHashString(), node); + } + if(dataCnt>0 && data!=NULL) + { + node->insertMonitor(msgList[i], ((iinsertMonitor(msgList[i], NULL, i); + } + + // ***************************************************** + // * Delete the containing array of cdevMessage pointers + // ***************************************************** + if(request->getDeviceCount()>1) delete msgList; + } + } + return 0; + } + + +// ***************************************************************************** +// * cdevMonitorTable::removeMonitor : +// * This method allows the caller to remove a specific monitor using the +// * cancelTransIndex component of the cdevMessage object. +// ***************************************************************************** +int cdevMonitorTable::removeMonitor ( cdevMessage * request ) + { + int cancelTransIndex = request->getCancelTransIndex(); + if(cancelTransIndex > 0) + { + StringHashIterator iter(&monitors); + iter.first(); + + while(iter.key()!=NULL) + { + cdevMonitorNode * node = (cdevMonitorNode *)iter.data(); + node->removeMonitor(cancelTransIndex); + ++iter; + } + } + return 0; + } + +// ***************************************************************************** +// * cdevMonitorTable::removeClientMonitors : +// * This method will walk through the hash table and will remove all +// * monitors that are associated with a specific clientID. +// ***************************************************************************** +int cdevMonitorTable::removeClientMonitors ( short clientID, int fire ) + { + char * ptr; + StringHashIterator iter(&monitors); + + iter.first(); + while((ptr= iter.key())!=NULL) + { + cdevMonitorNode * node = (cdevMonitorNode *)iter.data(); + node->removeClientMonitors(clientID, fire); + iter++; + } + return 0; + } + +// ***************************************************************************** +// * cdevMonitorTable::findMonitor : +// * This method locates a cdevMonitorNode associated with the specified +// * device / attribute pair and returns it to the caller. +// ***************************************************************************** +cdevMonitorNode * cdevMonitorTable::findMonitor ( char * device, char * attrib ) + { + char hashString [512]; + sprintf(hashString, "%s %s", device, attrib); + return (cdevMonitorNode *)monitors.find(hashString); + } + + +// ***************************************************************************** +// * cdevMonitorTable:fireMonitor : +// * This method is used to deploy all monitors associated with the +// * device / attribute / property set. +// * +// * If the property parameter is NULL, then all properties will be fired +// * for all monitor associated with the device / attribute pair. +// ***************************************************************************** +int cdevMonitorTable::fireMonitor ( char * device, char * attrib, + char * property, cdevData * data ) + { + cdevMonitorNode * node = findMonitor(device, attrib); + return node==NULL?-1:node->fireMonitor(property, data); + } + +// ***************************************************************************** +// * cdevMonitorTable:fireMonitor : +// * This method is used to deploy all monitors associated with the +// * device / attribute / property set. +// * +// * If the property parameter is -1, then all properties will be fired +// * for all monitors associated with the device / attribute pair. +// ***************************************************************************** +int cdevMonitorTable::fireMonitor ( char * device, char * attrib, + int property, cdevData * data ) + { + cdevMonitorNode * node = findMonitor(device, attrib); + return node==NULL?-1:node->fireMonitor(property, data); + } + + +// ***************************************************************************** +// * cdevMonitorTable::fireCallback : +// * This is a stub for the fireCallback method that must b e provided by +// * the developer. This method is provided here - because this method may +// * potentially be called during program termination - resulting in the +// * attempted execution of a pure virtual function. +// ***************************************************************************** +int cdevMonitorTable::fireCallback ( cdevMessage * /* message */ ) + { + return CDEV_SUCCESS; + } diff --git a/extensions/cdevGenericServer/lib/cdevPacket.cc b/extensions/cdevGenericServer/lib/cdevPacket.cc new file mode 100755 index 0000000..6adcd6e --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevPacket.cc @@ -0,0 +1,76 @@ +#include + +cdevPacket::ImportTable * cdevPacket::importTables = NULL; +int cdevPacket::maxTables = 0; + + +// ***************************************************************************** +// * cdevPacket::import : +// * The import mechanism will walk through the importTables and attempt to +// * locate an entry that has the same packet version as the cdevPacketBinary +// * parameter. If a matching netry is found, then it will be used to decode +// * the binary and create a cdevPacket object from it, otherwise NULL will +// * be returned. +// * +// * Note: Subclasses of the cdevPacket class that wish to employ this +// * functionality must register their import methods and their packet +// * versions using the registerImportMethod mechanism. +// ***************************************************************************** +cdevPacket * cdevPacket::import ( cdevPacketBinary & packet ) + { + short packetVersion = 0; + int idx = 0; + int found = 0; + cdevPacket * result = NULL; + + packet.getVersion(packetVersion); + + while(idx +#include +#include "cdevReactor.h" + +// ***************************************************************************** +// * This is the number of times that InitializeNetwork was called to perform +// * network initialization. The InitializeNetwork and corresponding +// * TerminateNetwork methods are wrappers to provide support for WIN32 +// * WSAStartup and WSACleanup methods. They perform no actiual function on +// * UNIX platforms. +// ***************************************************************************** +int cdevReactor::netInitCount = 0; + +// ***************************************************************************** +// * cdevReactor::cdevReactor : +// * This is the constructor for the cdevReactor class. It takes no +// * arguments. It will set maxEntries to the value of the MAX_SIZE +// * variable and the size variable (the highest fd installed) will be set +// * to zero. +// * +// * The method will allocate space in the handlers array for the +// * cdevEventHandlers that will be installed during operation. The +// * read_set, write_set and except_set masks will be cleared. These masks +// * will be populated later as file descriptors are added to the +// * cdevReactor. +// ***************************************************************************** +cdevReactor::cdevReactor ( void ) + : maxEntries(cdevHandleSet::MAX_SIZE), + size (0), + handlers (NULL), + timers (NULL) + { + if(!netInitCount) + { + if(InitializeNetwork()==0) netInitCount++; + } + else netInitCount++; + + handlers = (cdevEventHandler **)malloc((maxEntries+1)*sizeof(cdevEventHandler *)); + memset(handlers, 0, sizeof(cdevEventHandler *)*(maxEntries+1)); + read_set.reset(); + write_set.reset(); + except_set.reset(); + } + + +// ***************************************************************************** +// * cdevReactor::~cdevReactor : +// * This is the destructor for the cdevReactor class. It wil first remove +// * all of the timer cdevEventHandlers from the timer array, it will then +// * remove all of the file-descriptor based cdevEventHandlers from the +// * handlers array. It will finish by deleteing the handlers array that +// * was allocated in the constructor. +// ***************************************************************************** +cdevReactor::~cdevReactor ( void ) + { + if(netInitCount && (-netInitCount)==0) TerminateNetwork(); + + while(timers!=NULL) removeHandler(timers); + for(int i=0; i<=maxEntries; i++) + { + if(handlers[i]!=NULL) removeHandler(handlers[i]); + } + delete handlers; + } + + +// ***************************************************************************** +// * cdevReactor::calculateMask : +// * This method will walk through the handlers array and setup the read_set, +// * write_set and except_set masks. +// ***************************************************************************** +void cdevReactor::calculateMask ( void ) + { + int i; + read_set.reset(); + write_set.reset(); + except_set.reset(); + size = 0; + + for(i=0; i<=maxEntries; i++) + { + unsigned mask; + if(handlers[i]!=NULL) + { + mask = handlers[i]->getMask(); + if(!(mask&cdevEventHandler::DONT_CALL)) + { + if(mask&cdevEventHandler::READ_MASK) + { + read_set.set_bit(i); + size = i+1; + } + if(mask&cdevEventHandler::WRITE_MASK) + { + write_set.set_bit(i); + size = i+1; + } + if(mask&cdevEventHandler::EXCEPT_MASK) + { + except_set.set_bit(i); + size = i+1; + } + } + } + } + } + + + +// ***************************************************************************** +// * cdevReactor::calculateTimeout : +// * This method will walk through the timers and determine the duration of +// * time that the cdevReactor should wait for events on the file +// * descriptors before automatically terminating. +// ***************************************************************************** +int cdevReactor::calculateTimeout ( cdevTime defaultPeriod, struct timeval &timeout ) + { + if(defaultPeriod==cdevTime(0,0)) timeout.tv_sec=(timeout.tv_usec=0); + else { + cdevTime now; + cdevTime target; + cdevEventHandler * timer; + + if(defaultPeriodnow; timer=timer->getNext()) + { + cdevTime nextTimeout = timer->getNextTimeout(); + + if(!(timer->getMask()&cdevEventHandler::DONT_CALL) && + (double)nextTimeout > 0.0) + { + if(nextTimeouthandleSignal()<0) + { + removeHandler(handlers[i]); + eventCnt++; + } + } + read_set.clr_bit(i); + } + } + } + return eventCnt; + } + +// ***************************************************************************** +// * cdevReactor::registerHandler : +// * This method is called to register a file-descriptor based +// * cdevEventHandler with the reactor. It will first check the validity +// * of the handler and its file descriptor. It will then determine if +// * another handler already occupies the position associated with the +// * specified handle. +// * +// * If the handler is valid, it will install it in the handlers array and +// * will add it to the read_set, write_set and except_set masks as +// * required. The size variable will be incremented if the new handler +// * has the highest file-descriptor in the array. +// ***************************************************************************** +int cdevReactor::registerHandler ( cdevEventHandler * handler, unsigned mask ) + { + int fd = -1; + REACTOR_RESULT result = SUCCESS; + + if(handler == NULL) + { + result = INVALID_HANDLER; + } + else if(handler->getReactor()!=NULL && handler->getReactor()!=this) + { + result = UNKNOWN_HANDLER; + } + else if((fd = handler->getHandle())<=0) + { + result = INVALID_HANDLE; + } + else if(fdgetHandle()]!=NULL) + { + result = HANDLE_EXISTS; + } + else { + if(fd>=maxEntries) + { + int oldMaxEntries = maxEntries; + maxEntries = fd+1; + handlers = (cdevEventHandler **)realloc(handlers, (maxEntries+1) * sizeof(cdevEventHandler *)); + memset(&handlers[oldMaxEntries], 0, sizeof(cdevEventHandler *)*((maxEntries+1)-oldMaxEntries)); + } + handler->setReactor(this); + handler->setMask (mask); + handlers[fd] = handler; + } + + return (int)result; + } + + +// ***************************************************************************** +// * cdevReactor::removeHandler : +// * This method allows the caller to remove an cdevEventHandler from the +// * cdevReactor and delete it. The method will call the extractHandler +// * method to remove the cdevEventHandler from the cdevReactor after which +// * the handler will be deleted. +// ***************************************************************************** +int cdevReactor::removeHandler ( cdevEventHandler * handler ) + { + REACTOR_RESULT result = INVALID_HANDLER; + if(handler!=NULL) + { + extractHandler(handler); + delete handler; + result = SUCCESS; + } + return (int)result; + } + +// ***************************************************************************** +// * cdevReactor::removeHandler : +// * This method will remove the specified handler using the file descriptor +// * provided by the caller. +// ***************************************************************************** +int cdevReactor::removeHandler ( int fd ) + { + REACTOR_RESULT result = SUCCESS; + + if(fd>0 && fd<=maxEntries) + { + result = (REACTOR_RESULT)removeHandler(handlers[fd]); + } + else result = INVALID_HANDLE; + + return (int) result; + } + +// ***************************************************************************** +// * cdevReactor::extractHandler : +// * This method will remove the specified cdevEventHandler from the +// * cdevReactor, however, it will not delete the cdevEventHandler when +// * finished. +// ***************************************************************************** +int cdevReactor::extractHandler ( cdevEventHandler * handler ) + { + int fd = -1; + REACTOR_RESULT result = UNKNOWN_HANDLER; + + if(handler == NULL) result = INVALID_HANDLER; + else { + cdevEventHandler * currTimer = timers; + cdevEventHandler * prevTimer = NULL; + + while(currTimer!=NULL && currTimer!=handler) + { + prevTimer = currTimer; + currTimer = prevTimer->getNext(); + } + + if(currTimer) + { + if(prevTimer) prevTimer->setNext(currTimer->getNext()); + else timers = currTimer->getNext(); + result = SUCCESS; + } + + if((fd = handler->getHandle())>=0 && + fd<=maxEntries && + handlers[fd]==handler) + { + handlers[fd] = NULL; + result = SUCCESS; + } + else for(fd=0; fd<=maxEntries; fd++) + { + if(handlers[fd]==handler) + { + handlers[fd] = NULL; + result = SUCCESS; + } + } + + if(result==SUCCESS) + { + handler->setMask(0); + handler->setReactor(NULL); + } + } + + return (int)result; + } + + +// ***************************************************************************** +// * cdevReactor::getHandler : +// * This method allows the caller to retrieve the cdevEventHandler +// * associated with a specific file descriptor. +// ***************************************************************************** +int cdevReactor::getHandler ( int fd, cdevEventHandler * & handler ) + { + REACTOR_RESULT result = SUCCESS; + + handler = NULL; + + if(fd<=0 || fd>maxEntries) result = INVALID_HANDLE; + else if((handler = handlers[fd])==NULL) result = INVALID_HANDLE; + + return (int) result; + } + +// ***************************************************************************** +// * cdevReactor::registerTimer : +// * This method will install a timer cdevEventHandler in the timers array. +// * The handleTimeout method of this class will be called each time the +// * timer expires. The timer's handleTimeout method will be called +// * immediately, and then the timer will be set to expire at the next +// * time period. +// ***************************************************************************** +int cdevReactor::registerTimer ( cdevEventHandler * timer ) + { + REACTOR_RESULT result = SUCCESS; + + if(timer==NULL) + { + result = INVALID_HANDLER; + } + else if(timer->getReactor()!=NULL && timer->getReactor()!=this) + { + result = UNKNOWN_HANDLER; + } + else if((double)timer->getTimeoutRate()<=0.0) + { + result = INVALID_TIMEOUT; + } + else { + timer->setReactor(this); + timer->resetTimer(); + timer->setNext(timers); + timers = timer; + } + + return (int)result; + } + +// ***************************************************************************** +// * cdevReactor::cancelTimer : +// * This method will remove the timer from the array of timers that are +// * being serviced by the reactor, however, it will NOT delete the +// * cdevEventHandler. Additionally, if the handler is also being used +// * for file-descriptor based operations - it will be not be removed from +// * that array. +// * +// * The user is responsible for deleteing the cdevEventHandler if it will +// * no longer be needed. +// ***************************************************************************** +int cdevReactor::cancelTimer ( cdevEventHandler * timer ) + { + REACTOR_RESULT result = SUCCESS; + + if(timer==NULL) result = INVALID_HANDLER; + else + { + cdevEventHandler * currTimer = timers; + cdevEventHandler * prevTimer = NULL; + + while(currTimer!=NULL && currTimer!=timer) + { + prevTimer = currTimer; + currTimer = prevTimer->getNext(); + } + + if(currTimer) + { + if(prevTimer) prevTimer->setNext(currTimer->getNext()); + else timers = currTimer->getNext(); + currTimer->setNext(NULL); + } + else result = UNKNOWN_HANDLER; + } + + return (int)result; + } + + +// ***************************************************************************** +// * cdevReactor::handleFileEvent : +// * This method will process the events that have occurred on a single +// * file descriptor. The caller must provide two arguments... +// * +// * fd_set * fds : The fd_set to be checked +// * REACTOR_EVENT event : The type of event being processed... +// * INPUT, OUTPUT, EXCEPTION, or SIGNAL. +// * +// * This method will return the number of events that have been processed +// * to completion. Note that if a cdevEventHandler returns a value greater +// * than 0, it will be called again after all other ready file descriptors +// * have been called - therefore, its occurance will not be included in the +// * number of events returned by this method. +// ***************************************************************************** +int cdevReactor::handleFileEvent ( cdevHandleSet * fds, REACTOR_EVENT event) + { + int result = 0; + int eventCnt = 0; + int i; + + for(i=0; i<=size; i++) + { + if(fds->is_set(i)) + { + if(handlers[i]) + { + if(event==INPUT) result = handlers[i]->handleInput(); + else if(event==OUTPUT) result = handlers[i]->handleOutput(); + else if(event==EXCEPTION) result = handlers[i]->handleExcept(); + else if(event==SIGNAL) result = handlers[i]->handleSignal(); + + if(result<=0) + { + if(result<0) removeHandler(handlers[i]); + eventCnt++; + fds->clr_bit(i); + } + } + else eventCnt++; + } + } + + return eventCnt; + } + +// ***************************************************************************** +// * cdevReactor::handleEvents : +// * This method is called to allow the cdevReactor to wait for events to +// * occur on the cdevEventHandler objects. This method will process events +// * until the specified time period has expired - if a negative time period +// * (or no time period) has been specified, then it will process messages +// * until the next event occurs. +// * +// * The flags parameter was added to allow the caller to specify either +// * UNTIL_TIMEOUT or UNTIL_EVENT. If the caller specifies UNTIL_TIMEOUT, +// * the cdevReactor will continue to handle events until the time period +// * has expired. If the caller specifies UNTIL_EVENT, the cdevReactor will +// * return after the first SOCKET-BASED EVENT occurs or after the time +// * expires, whichever comes first. +// * +// * Note: If the cdevEventHandler may return a -1, 0, or 1. These return +// * codes will have the following effect. +// * +// * -1 : The cdevEventHandler will be removed from the cdevReactor +// * and deleted. +// * 0 : The bit associated with the cdevEventHandler will be +// * cleared and processing will continue. +// * 1 : The bit associated with the cdevEventHandler will not be +// * cleared and it will be called to process more data after +// * after all of the subsequent cdevEventHandlers have been +// * called - this allows the cdevEventHandler in a lengthy +// * process to yeild time back for processing other events. +// ***************************************************************************** +int cdevReactor::handleEvents ( cdevTime period, int flags ) + { + int result = 0; + int finished = 0; + cdevTime startTime, currTime; + struct timeval timeout; + + startTime.setTime(); + + do + { + int i; + + calculateMask (); + calculateTimeout(period, timeout); + + result=cdevSelect(size, read_set, write_set, except_set, &timeout); + + if(result<0) + { + finished = 1; + checkHandlers(); + } + else { + if(result>0) + { + int cnt = 0; + + while(cnt0) finished = 1; + } + + if(timers!=NULL) + { + cdevEventHandler * timer=timers; + + currTime.setTime(); + + while(timer!=NULL) + { + cdevTime nextTimeout = timer->getNextTimeout(); + + if((timer->getMask()&cdevEventHandler::DONT_CALL)==0 && + (double)nextTimeout>0.0 && nextTimeout<=currTime) + { + if(timer->handleTimeout()<0) + { + cdevEventHandler *temp = timer->getNext(); + removeHandler(timer); + timer = temp; + } + else + { + timer->resetTimer(); + timer = timer->getNext(); + } + currTime.setTime(); + } + else timer = timer->getNext(); + } + } + } + + currTime.setTime(); + period = period-(currTime-startTime); + } while(!finished && period>cdevTime(0,0)); + + return result; + } diff --git a/extensions/cdevGenericServer/lib/cdevServer.cc b/extensions/cdevGenericServer/lib/cdevServer.cc new file mode 100755 index 0000000..06ec51a --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevServer.cc @@ -0,0 +1,692 @@ +#include "cdevServer.h" +#include "ClientAcceptor.h" +#include "ClientHandler.h" + +sig_atomic_t cdevServer::Finished = 0; +SignalManager cdevServer::SigManager; +cdevGenericServerTagDef cdevServer::tags; + +// ***************************************************************************** +// * This function is an interrupt handler that will be executed whenever the +// * program receives a SIGINT. When called it will set the finished flag to 1 +// * and trigger the termination of the program. +// ***************************************************************************** +static void SIGINT_handler (int signo) + { + cdevServer::Finished = 1; + signal(signo, SIGINT_handler); + } + + +// ***************************************************************************** +// * cdevServer::cdevServer : +// * This is the constructor for the class. It will post the listening +// * socket, establish registration with the name server and record all +// * other pertinent information. +// ***************************************************************************** +cdevServer::cdevServer (char * DomainName, char * ServerName, unsigned short Port, double Rate) + : cdevSessionManager(), + serverName (NULL), + acceptor (NULL), + timer (NULL), + status (UNINITIALIZED), + serverInfo (NULL) + { + // ********************************************************************* + // * Register the import method for the cdevMessage class with the + // * cdevPacket class. + // ********************************************************************* + cdevPacket::registerImportMethod(cdevMessage::CDEV_PACKET_VERSION, + cdevMessage::import); + + startServer(DomainName, ServerName, Port, Rate, 0); + } + +// ***************************************************************************** +// * cdevServer::cdevServer : +// * This is the do nothing constructor for the class. +// ***************************************************************************** +cdevServer::cdevServer ( void ) + : cdevSessionManager (), + serverName (NULL), + acceptor (NULL), + timer (NULL), + status (UNINITIALIZED), + serverInfo (NULL) + { + // ********************************************************************* + // * Register the import method for the cdevMessage class with the + // * cdevPacket class. + // ********************************************************************* + cdevPacket::registerImportMethod(cdevMessage::CDEV_PACKET_VERSION, + cdevMessage::import); + + } + +// ***************************************************************************** +// * cdevServer::~cdevServer : +// * This is the destructor for the object. It will close all listening +// * sockets and will delete all allocated items. +// ***************************************************************************** +cdevServer::~cdevServer ( void ) + { + outputError ( CDEV_SEVERITY_INFO, "CDEV Server", + "Server %s is Terminating...", + serverName); + + Reactor.extractHandler(this); + + if(timer!=NULL) delete timer; + if(serverName!=NULL) delete serverName; + if(acceptor!=NULL) delete acceptor; + } + + +// ***************************************************************************** +// * cdevServer::startServer : +// * This method will initialize a cdevServer within a given name, will +// * register it within the CDEV Name Server and will commence listening +// * for connections on the specified port. +// ***************************************************************************** +int cdevServer::startServer (char * DomainName, char * ServerName, unsigned short Port, double Rate, int searchForPort) + { + if(acceptor!=NULL) + { + delete acceptor; + acceptor=NULL; + } + if(timer) + { + delete timer; + timer=NULL; + } + if(serverName) + { + delete serverName; + serverName = NULL; + } + if(serverInfo) + { + delete serverInfo; + serverInfo = NULL; + } + + Reactor.extractHandler(this); + + setTimeoutRate(Rate); + serverName = strdup(ServerName); + status = UNINITIALIZED; + acceptor = new ClientAcceptor(*this); + + // ********************************************************************* + // * Attempt to open the acceptor to receive new connections. + // ********************************************************************* + if(searchForPort) Port = 0; + cdevInetAddr addr(Port); + int initialized=!(acceptor->open(addr)); + + // ********************************************************************* + // * Call getLocalAddress to retrieve the actual port number that was + // * opened. This value will differ from the specified port if... + // * 1) the user specified 0 for the port number -or- + // * 2) the user set the searchForPort flag to non-zero. + // ********************************************************************* + if(acceptor->getLocalAddress(addr)==0) Port = addr.getPortNum(); + else Port = (unsigned short)-1; + + // ********************************************************************* + // * ServerInfo must be created after the port has been searched for + // * and found. Otherwise, the server will report the original port + // * number rather than the actual port number. + // ********************************************************************* + serverInfo = new ServerInfo(DomainName, ServerName, Port); + + if(initialized) + { + // ************************************************************* + // * Register the acceptor with the Reactor. + // ************************************************************* + if(Reactor.registerHandler(acceptor, READ_MASK)!=-1) + { + // ***************************************************** + // * Register this event handler with the Reactor. + // ***************************************************** + if(Reactor.registerHandler(this, READ_MASK)!=-1) + { + // ********************************************* + // * Schedule the periodic timer if it is + // * greater than 0. + // ********************************************* + if(Rate <= 0.0 || + Reactor.registerTimer(this)!=-1) + { + // ************************************* + // * Install a name server timer to + // * continuously register this server + // * with the Name Server. + // ************************************* + timer = new cdevNameServerManager(Reactor, DomainName, ServerName, Port); + outputError (CDEV_SEVERITY_INFO, "CDEV Server", + "Server %s is operational and servicing requests...", + serverName); + } + else + { + outputError ( CDEV_SEVERITY_SEVERE, "CDEV Server", + "Server %s - Unable to register server timer with cdevReactor", + serverName); + status = CANT_REGISTER_TIMER; + } + } + else + { + outputError ( CDEV_SEVERITY_SEVERE, "CDEV Server", + "Server %s - Unable to register server handler with cdevReactor", + serverName); + status = CANT_REGISTER_SERVER; + } + } + else + { + outputError (CDEV_SEVERITY_SEVERE, "CDEV Server", + "Server %s - Unable to register listening service with cdevReactor", + serverName); + status = CANT_REGISTER_LISTENER; + } + } + else + { + outputError ( CDEV_SEVERITY_SEVERE, "CDEV Server", + "Server %s - Unable to open listening socket", + serverName); + status = CANT_OPEN_SOCKET; + } + + switch (status) + { + case CANT_REGISTER_TIMER: + Reactor.extractHandler(this); + + case CANT_REGISTER_SERVER: + Reactor.extractHandler(acceptor); + + case CANT_REGISTER_LISTENER: + case CANT_OPEN_SOCKET: + delete acceptor; + acceptor = NULL; + break; + + case SUCCESS: + default: + status = SUCCESS; + break; + } + + return status; + } + + +// *************************************************************************** +// * cdevServer::runServer : +// * This method is called to simultaneously execute all servers that +// * reside in the system. +// *************************************************************************** +void cdevServer::runServer ( void ) + { + SigManager.installDefaults(); + SigManager.installHandler (SIGINT, SIGINT_handler); + while (!Finished) Reactor.handleEvents (); + } + + +// ***************************************************************************** +// * cdevServer::registerClient : +// * This is the cdevMessage specific method that is used to send a +// * "register" message to the server. +// ***************************************************************************** +void cdevServer::registerClient ( short localID ) + { + cdevMessage message(localID,0,0,0,0,0,0,0,NULL,"register"); + cdevPacketBinary * packet = new cdevPacketBinary; + char * binary; + size_t binaryLen; + + message.streamOut (&binary, &binaryLen); + packet->attachData(binary, binaryLen); + inbound.enqueue (packet); + } + + +// ***************************************************************************** +// * cdevServer::unregisterClient : +// * This is the cdevMessage specific method that is used to send an +// * "unregister" message to the server. +// ***************************************************************************** +void cdevServer::unregisterClient ( short localID ) + { + cdevMessage message(localID,0,0,0,0,0,0,0,NULL,"unregister"); + cdevPacketBinary * packet = new cdevPacketBinary; + char * binary; + size_t binaryLen; + + message.streamOut (&binary, &binaryLen); + packet->attachData(binary, binaryLen); + inbound.enqueue (packet); + trigger.insertEvent(); + } + + +// ***************************************************************************** +// * cdevServer::newClientSession : +// * This method allows the caller to create a new ClientSession object. The +// * ClientSession object functions primarily as a pointer to the queue that +// * holds packets destined for a specific client, however, the developer +// * can create a subclass of the ClientSession that may be used to associate +// * additional, client specific information to the structure. +// * +// * The CLIPClientSession class allows the developer to associate a context +// * with the clientID. +// ***************************************************************************** +ClientSession * cdevServer::newClientSession ( int SocketID, int ClientID, int LocalID ) + { + return new CLIPClientSession (SocketID, ClientID, LocalID); + } + + +// ***************************************************************************** +// * cdevServer::newSocketSession : +// * This method allows the caller to create a new SocketSession object. The +// * SocketSession object functions primarily as a pointer to the queue that +// * holds packets destined for a specific socket, however, the developer +// * can create a subclass of the SocketSession that may be used to associate +// * additional, socket specific information to the structure. +// * +// * The CLIPSocketSession class allows the developer to associate a +// * context map and a tag table with the socket number. +// ***************************************************************************** +SocketSession * cdevServer::newSocketSession ( int SocketID ) + { + if(serverInfo) serverInfo->clientCnt++; + + return new CLIPSocketSession (SocketID); + } + +// ***************************************************************************** +// * cdevServer::deleteSocketSession : +// * This method is called to delete an existing socket session. +// ***************************************************************************** +void cdevServer::deleteSocketSession ( SocketSession *socket ) + { + if(socket) + { + if(serverInfo) + { + if(serverInfo->clientCnt>0) serverInfo->clientCnt--; + else serverInfo->clientCnt=0; + } + + sockets.remove(socket->getSocketID()); + delete socket; + } + } + +// ***************************************************************************** +// * cdevServer::dequeue : +// * This method provides a mechanism for the cdevServer object to only +// * dequeue packets that are of the type cdevMessage. +// ***************************************************************************** +int cdevServer::dequeue ( cdevMessage * &message ) + { + cdevPacket * packet = NULL; + + while(packet==NULL && cdevSessionManager::dequeue(packet)==0) + { + if(packet->getVersion()!=cdevMessage::CDEV_PACKET_VERSION) + { + delete packet; + packet = NULL; + } + else if(((cdevMessage *)packet)->getOperationCode()==CDEV_SERVER_OP) + { + processLocal((cdevMessage * &)packet); + delete packet; + packet = NULL; + } + } + + message = (cdevMessage *)packet; + return message==NULL?-1:0; + } + +// ***************************************************************************** +// * cdevServer::processLocal : +// * This method is called to process requests that are being transmitted +// * directly to the cdev Generic Server Engine to set or retrieve statistics +// * about the operation of the server or its clients. +// ***************************************************************************** +void cdevServer::processLocal ( cdevMessage * & message ) + { + CLIPClientSession * client = NULL; + CLIPSocketSession * socket = NULL; + + if((client = (CLIPClientSession *)findLocalClient(message->getClientID()))!=NULL) + { + socket = (CLIPSocketSession *)findSocket(client->getSocketID()); + } + if(!strcmp(message->getMessage(), "set ClientInfo")) + { + cdevData * data = message->getData(); + if(data && socket) socket->updateClientInfo(*data); + } + else if(!strcmp(message->getMessage(), "get ServerInfo")) + { + if(serverInfo) + { + message->setOperationCode(CDEV_NORMAL_OP); + message->setData(&serverInfo->getServerData(), 1); + } + else { + message->setOperationCode(CDEV_NORMAL_OP); + message->setCompletionCode(-1); + } + enqueue(message); + } + else if(!strcmp(message->getMessage(), "get ClientInfo")) + { + IntHashIterator iter(&sockets); + ClientHandler * handler = NULL; + int socketCnt = 0; + int index = 0; + cdevData result; + + iter.first(); + while(iter.data()!=NULL) + { + iter++; + socketCnt++; + } + if(socketCnt) + { + char ** username = new char *[socketCnt]; + char ** group = new char *[socketCnt]; + unsigned * uid = new unsigned [socketCnt]; + unsigned * gid = new unsigned [socketCnt]; + unsigned * pid = new unsigned [socketCnt]; + char ** program = new char *[socketCnt]; + char ** commandline = new char *[socketCnt]; + unsigned * starttime = new unsigned [socketCnt]; + unsigned * connecttime = new unsigned [socketCnt]; + char ** host = new char *[socketCnt]; + char ** os = new char *[socketCnt]; + char ** osrelease = new char *[socketCnt]; + char ** osversion = new char *[socketCnt]; + char ** machine = new char *[socketCnt]; + char ** shell = new char *[socketCnt]; + unsigned * socketNum = new unsigned[socketCnt]; + unsigned * sendPktCnt = new unsigned[socketCnt]; + unsigned * recvPktCnt = new unsigned[socketCnt]; + + iter.first(); + while(indexgetUsername(); + group[index] = socket->getGroup(); + uid[index] = socket->getUid(); + gid[index] = socket->getGid(); + pid[index] = socket->getPid(); + program[index] = socket->getProgram(); + commandline[index] = socket->getCommandLine(); + starttime[index] = (unsigned)socket->getStartTime(); + connecttime[index] = (unsigned)socket->getConnectTime(); + host[index] = socket->getHost(); + os[index] = socket->getOs(); + osrelease[index] = socket->getOsRelease(); + osversion[index] = socket->getOsVersion(); + machine[index] = socket->getMachine(); + shell[index] = socket->getShell(); + socketNum[index] = socket->getSocketID(); + if(Reactor.getHandler(socketNum[index], (cdevEventHandler *&)handler)==0) + { + sendPktCnt[index] = handler->getPacketsSent(); + recvPktCnt[index] = handler->getPacketsRecv(); + } + else { + sendPktCnt[index] = 0; + recvPktCnt[index] = 0; + } + index++; + iter++; + } + + result.insert("username", username, socketCnt); delete username; + result.insert("group", group, socketCnt); delete group; + result.insert("uid", uid, socketCnt); delete uid; + result.insert("gid", gid, socketCnt); delete gid; + result.insert("pid", pid, socketCnt); delete pid; + result.insert("program", program, socketCnt); delete program; + result.insert("commandline", commandline, socketCnt); delete commandline; + result.insert("starttime", starttime, socketCnt); delete starttime; + result.insert("connecttime", connecttime, socketCnt); delete connecttime; + result.insert("host", host, socketCnt); delete host; + result.insert("os", os, socketCnt); delete os; + result.insert("osrelease", osrelease, socketCnt); delete osrelease; + result.insert("osversion", osversion, socketCnt); delete osversion; + result.insert("machine", machine, socketCnt); delete machine; + result.insert("shell", shell, socketCnt); delete shell; + result.insert("socket", socketNum, socketCnt); delete socketNum; + result.insert("sendPktCnt", sendPktCnt, socketCnt); delete sendPktCnt; + result.insert("recvPktCnt", recvPktCnt, socketCnt); delete recvPktCnt; + } + message->setOperationCode(CDEV_NORMAL_OP); + message->setData(&result, 1); + enqueue(message); + } + } + +// ***************************************************************************** +// * cdevServer::decodePacket : +// * This method is used to perform preprocessing on a newly dequeued binary +// * packet before it is provided to the caller. This method allows the +// * developer to perform special preparations on the packet before providing +// * it to the caller. +// ***************************************************************************** +cdevPacket * cdevServer::decodePacket( cdevPacketBinary * input ) + { + cdevPacket * packet = NULL; + + if(input!=NULL) + { + short version; + input->getVersion(version); + switch (version) + { + // ***************************************************** + // * If it is a cdevMessage object, I want to call the + // * cdevMessage specific decodePacket method. + // ***************************************************** + case cdevMessage::CDEV_PACKET_VERSION: + packet = decodePacket ((cdevMessage *)cdevPacket::import(*input)); + break; + + // ***************************************************** + // * Use the cdevSessionManager::decodePacket method + // * to handle any other type of packet. + // ***************************************************** + default: + packet = cdevSessionManager::decodePacket(input); + break; + } + if(serverInfo) serverInfo->recvPktCnt++; + } + return packet; + } + +// ***************************************************************************** +// * cdevServer::decodePacket : +// * This decodePacket method is designed specifically to preprocess the +// * data associated with a cdevMessage object. +// ***************************************************************************** +cdevPacket * cdevServer::decodePacket (cdevMessage * message ) + { + CLIPClientSession * client = NULL; + CLIPSocketSession * socket = NULL; + + if(message!=NULL && + (client = (CLIPClientSession *)findLocalClient(message->getClientID()))!=NULL && + (socket = (CLIPSocketSession *)findSocket(client->getSocketID()))!=NULL) + { + // ************************************************************* + // * If a tagMap has been provided... use it to update + // * the tagMap stored in the SocketSession object. + // ************************************************************* + if(message->getTagMap()!=NULL) + { + socket->TagMap().updateTagMap(*message->getTagMap()); + message->setTagMap(NULL); + } + + // ************************************************************* + // * Pass the data and context objects through the tag map to + // * convert their tags from the remote integers to the local + // * integers. + // ************************************************************* + if(message->getData()!=NULL) + socket->TagMap().remoteToLocal(*message->getData()); + if(message->getContext()!=NULL) + socket->TagMap().remoteToLocal(*message->getContext()); + + // ************************************************************* + // * If a context has been provided by the client side + // * of the connection - perform the following steps... + // * + // * 1) Add the context to the cdevContextMap for this + // * socketID if it does not already exist, and + // * obtain the index that identifies the new + // * context. + // * + // * 2) Delete the context from within the message. + // * + // * 3) Set the context within the message to the + // * current context that is specified in the + // * ClientSession object. + // * + // * 4) Set the saveContext flag in the message to + // * prevent its inadvertant destruction when the + // * message is deleted. + // ************************************************************* + if(message->getContext()!=NULL) + { + cdevData * lastContext = client->getContext(); + if(lastContext==NULL || *lastContext!=*message->getContext()) + { + int contextID = socket->ContextMap().insert(*message->getContext()); + client->setContext(socket->ContextMap().find(contextID)); + } + } + message->setContext(client->getContext(), 1); + + // ************************************************************* + // * Toggle the local and foreign data indices. + // ************************************************************* + unsigned int index = message->getForeignDataIndex(); + message->setForeignDataIndex(message->getLocalDataIndex()); + message->setLocalDataIndex (index); + } + + return message; + } + + +// ***************************************************************************** +// * cdevSessionManager::encodePacket : +// * This method is used to perform postprocessing on a packet that has been +// * enqueued to be sent to a client. This method allows the developer to +// * perform special preparations on the packet before providing it to the +// * client. +// ***************************************************************************** +cdevPacketBinary * cdevServer::encodePacket ( cdevPacket * input ) + { + cdevPacketBinary * packet = NULL; + + if(input!=NULL) + { + switch(input->getVersion()) + { + case cdevMessage::CDEV_PACKET_VERSION: + packet = encodePacket ((cdevMessage *)input); + break; + + default: + packet = cdevSessionManager::encodePacket(input); + break; + } + if(serverInfo) serverInfo->sendPktCnt++; + } + return packet; + } + + +// ***************************************************************************** +// * cdevServer::encodePacket : +// * This encodePacket method is designed specifically to postprocess the +// * data associated with a cdevMessage object. +// ***************************************************************************** +cdevPacketBinary * cdevServer::encodePacket (cdevMessage * message ) + { + cdevPacketBinary * result = NULL; + CLIPClientSession * client = NULL; + CLIPSocketSession * socket = NULL; + + if(message!=NULL && + message->getClientID()>0 && + message->getTransIndex()>0 && + (client = (CLIPClientSession *)findLocalClient(message->getClientID()))!=NULL && + (socket = (CLIPSocketSession *)findSocket(client->getSocketID()))!=NULL) + { + char * binary = NULL; + size_t binaryLen = 0; + static cdevMessage outBound; + + // ************************************************************* + // * Remap the data to its foreign design. + // ************************************************************* + if(message->getData()!=NULL) + socket->TagMap().localToRemote(*message->getData()); + + // ************************************************************* + // * Transfer the critical data items into the class. Note that + // * we are not returning the deviceList, message, context, + // * cancelTransIndex, or operationCode with the return packet. + // * + // * Also note that the cdevData object is marked as permanent + // * and is using a pointer to the same cdevData object that is + // * in the message object. + // ************************************************************* + outBound.clear(); + outBound.setClientID (client->getClientID()&0xFFFF); + outBound.setTransIndex (message->getTransIndex()); + outBound.setLocalDataIndex (message->getForeignDataIndex()); + outBound.setForeignDataIndex (message->getLocalDataIndex()); + outBound.setOperationCode (message->getOperationCode()); + outBound.setCompletionCode (message->getCompletionCode()); + outBound.setData (message->getData(), 1); + + // ************************************************************* + // * Create a binary stream from the cdevMessage object and then + // * place it into the outbound queue system. + // ************************************************************* + outBound.streamOut(&binary, &binaryLen); + outBound.clear (); + + result = new cdevPacketBinary; + result->attachData(binary, binaryLen); + + // ************************************************************* + // * Remap the data to its local design. + // ************************************************************* + if(message->getData()!=NULL) + socket->TagMap().remoteToLocal(*message->getData()); + } + return result; + } + diff --git a/extensions/cdevGenericServer/lib/cdevServerTools.cc b/extensions/cdevGenericServer/lib/cdevServerTools.cc new file mode 100755 index 0000000..e418f02 --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevServerTools.cc @@ -0,0 +1,403 @@ +#include "cdevServerTools.h" + + +// **************************************************************************** +// cdevSimpleTimer::cdevSimpleTimer : +// Constructor. +// **************************************************************************** +cdevSimpleTimer::cdevSimpleTimer ( cdevReactor & Reactor, double Rate) + { + setTimeoutRate(Rate); + if(Reactor.registerTimer (this) == -1) + { + outputError ( CDEV_SEVERITY_SEVERE, "cdevSimpleTimer", + "Unable to register timer with cdevReactor"); + } + } + +// **************************************************************************** +// cdevSimpleTimer::~cdevSimpleTimer : +// Destructor. +// **************************************************************************** +cdevSimpleTimer::~cdevSimpleTimer ( void ) + { + if(reactor) reactor->extractHandler(this); + handleClose(); + } + +// **************************************************************************** +// cdevSimpleTimer::handle_timeout : +// Called when the timer expires. +// **************************************************************************** +int cdevSimpleTimer::handleTimeout(void) + { + return execute(); + } + + +// ***************************************************************************** +// * cdevNameServerManager::cdevNameServerManager : +// * This method will read the CDEV_NAME_SERVER environment variable to +// * obtain a list of one or more cdev name servers that should be notified +// * that this server is operational. The class will create a +// * cdevNameServerHandler event handler to manage the connection to each of +// * the specified name servers. If a connection is lost to one of the +// * name servers, the cdevNameServerManager will attempt periodically to +// * reconnect to the specific name server. +// ***************************************************************************** +cdevNameServerManager::cdevNameServerManager ( cdevReactor & Reactor, + char * DomainName, + char * ServerName, + unsigned short ServerPort ) + : domainName(strdup(DomainName)), + serverName(strdup(ServerName)), + serverPort(ServerPort), + nameServerList(NULL), + nameServerHandlers(NULL), + nameServerCnt(0) + { + // ********************************************************************* + // * Prior to establishing any connections, the class must first install + // * all of the necessary data into the serverInfo and updateInfo + // * objects. + // ********************************************************************* + char * userName = getenv("USER"); + char hostname[255]; + struct hostent * hostPtr; + struct timeval tv; + + gettimeofday (&tv); + gethostname(hostname, 255); + hostPtr = gethostbyname(hostname); + + serverInfo.insert ("name", serverName); + serverInfo.insert ("domain", domainName); + serverInfo.insert ("host", (char *)hostPtr->h_name); + serverInfo.insert ("owner", userName?userName:(char *)"UNKNOWN"); + serverInfo.insert ("time", (long)tv.tv_sec); + serverInfo.insert ("port", (long)serverPort); + serverInfo.insert ("pid", getpid ()); + updateInfo.insert ("name", serverName); + updateInfo.insert ("domain", domainName); + + // ********************************************************************* + // * First obtain a list of name servers from the CDEV_NAME_SERVER + // * environment variable. If this list is empty, then report an + // * error once and then never call the handler again. + // ********************************************************************* + char * nsList = getenv("CDEV_NAME_SERVER"); + int idx; + int length; + + if(nsList!=NULL) + { + char * nsPtr = nsList; + char * endPtr = nsList; + + // ************************************************************* + // * Determine the number of name servers that have been + // * defined in the CDEV_NAME_SERVER environment variable. + // ************************************************************* + while(*nsPtr==':' && *nsPtr!=0) nsPtr++; + if(*nsPtr!=0) + { + nameServerCnt = 1; + while(nsPtr!=NULL && *nsPtr!=0) + { + if((nsPtr = strchr(nsPtr, ':'))!=NULL) + { + while(*(++nsPtr)==':' && *nsPtr!=0); + if(*nsPtr!=0) nameServerCnt++; + } + } + } + + // ************************************************************* + // * Copy each of the defined cdev name server host names into + // * the nameServerList. + // ************************************************************* + if(nameServerCnt>0) + { + nameServerList = new char *[nameServerCnt]; + nameServerHandlers = new cdevNameServerHandler *[nameServerCnt]; + + for(nsPtr = nsList, idx=0; idx No name servers have been specified in the CDEV_NAME_SERVER", + " => environment variable.", + " => This server WILL NOT be registered with any name servers..."); + } + // ********************************************************************* + // * Otherwise, set all of the cdevNameServerHandler pointers to NULL + // * so that they will be connected when the execute timeout method + // * is called. + // ********************************************************************* + else { + for(idx=0; idxconnect(nameServerList[idx], RSVC_SERVER_PORT, 2.0)!=RSVC_SUCCESS) + { + outputError ( CDEV_SEVERITY_ERROR, "CDEV Name Server Manager", + "Failed to connect to name server on host %s", + nameServerList[idx]); + error = -1; + } + else if(udpClient->connect(nameServerList[idx], RSVC_SERVER_PORT+1024)!=RSVC_SUCCESS) + { + outputError ( CDEV_SEVERITY_ERROR, "CDEV Name Server Manager", + "Failed to open UDP port to name server on host %s", + nameServerList[idx]); + error = -1; + } + else if(client->insertValue ("cdevServers", serverInfo, rsvcCallback, nameServerList[idx], 1)!=RSVC_SUCCESS) + { + outputError ( CDEV_SEVERITY_ERROR, "CDEV Name Server Manager", + "Error transmitting to name server on host %s", + nameServerList[idx]); + error = -1; + } + + if(!error) nameServerHandlers[idx] = new cdevNameServerHandler(*this, *reactor, idx, client, udpClient); + else { + client->disconnect(); + udpClient->disconnect(); + delete client; + delete udpClient; + } + } + } + return 0; + } + +// ***************************************************************************** +// * cdevNameServerManager::unregisterHandler: +// * This method is called whenever a cdevNameServerHandler needs to +// * unregister itself from the cdevNameServerManager. The handlers index +// * will be set to 0 and the connection will be reestablished the next time +// * the handleTimeout method is called. +// ***************************************************************************** +void cdevNameServerManager::unregisterHandler ( size_t index ) + { + if(index < nameServerCnt) nameServerHandlers[index] = NULL; + } + + +// ***************************************************************************** +// * cdevNameServerManager::rsvcCallback : +// * This is the method that is called when the register server method +// * is executed. +// ***************************************************************************** +void cdevNameServerManager::rsvcCallback (int status, void* arg, rsvcData* /* data */) + { + char * nameServer = (char *)arg; + + if (status != RSVC_SUCCESS) + { + #ifndef _WIN32 + fprintf(stderr, "CDEV Name Server Manager Error: %s %s\n", + "Failed to register with name server on host", + nameServer?nameServer:"UNKNOWN"); + #endif + } + } + + +// ***************************************************************************** +// * cdevNameServerHandler::cdevNameServerHandler : +// * This is the constructor for the cdevNameServerHandler class. It is +// * called by the cdevNameServerManager when a new cdevNameServerHandler +// * must be created to communicate with a name server. The connected +// * rsvcClient and rsvcUdpClient objects are provided to the class. +// ****************************************************************************** +cdevNameServerHandler::cdevNameServerHandler ( cdevNameServerManager & Manager, + cdevReactor & Reactor, + int index, + rsvcClient * tcpClient, + rsvcUdpClient * udpClient ) + : nameServerTCP(tcpClient), nameServerUDP(udpClient), + nameServerIndex(index), nameServerManager(Manager) + { + setTimeoutRate(5.0); + setMask(WRITE_MASK); + Reactor.registerHandler(this, WRITE_MASK); + Reactor.registerTimer (this); + } + +// ***************************************************************************** +// * cdevNameServerHandler::~cdevNameServerHandler : +// * This is the destructor for the class. this method is responsible for +// * disconnecting and closing the tcp and udp client connections and +// * sending notification to the cdevNameServerManager that it is +// * terminating. +// ***************************************************************************** +cdevNameServerHandler::~cdevNameServerHandler ( void ) + { + nameServerTCP->disconnect(); + nameServerUDP->disconnect(); + delete nameServerTCP; + delete nameServerUDP; + if(reactor) reactor->extractHandler(this); + nameServerManager.unregisterHandler(nameServerIndex); + } + +// ***************************************************************************** +// * cdevNameServerHandler::handleInput : +// * This method is called whenever data is ready to be read from the +// * nameServerTCP rsvcClient connection. +// ***************************************************************************** +int cdevNameServerHandler::handleInput ( void ) + { + return (nameServerTCP->pendIO()==RSVC_IOERROR)?-1:0; + } + +// ***************************************************************************** +// * cdevNameServerHandler::handleOutput : +// * This method is called whenever data is ready to be written to the +// * nameServerTCP rsvcClient connection. +// ***************************************************************************** +int cdevNameServerHandler::handleOutput ( void ) + { + setMask(READ_MASK); + return (nameServerTCP->pendIO()==RSVC_IOERROR)?-1:0; + } + +// ***************************************************************************** +// * cdevNameServerHandler::handleTimeout : +// * This method is called every five seconds to allow the object to emit +// * a UDP packet to the name server to notify it that the server is alive. +// ***************************************************************************** +int cdevNameServerHandler::handleTimeout ( void ) + { + if(nameServerUDP->update(*nameServerManager.getUpdateInfo())!=RSVC_SUCCESS) + { + outputError(CDEV_SEVERITY_ERROR, "CDEV Name Server Handler", + "Failed to update name server on host %s", + nameServerManager.getHostName(nameServerIndex)); + } + return 0; + } + +// ***************************************************************************** +// * cdevNameServerHandler::getHandle : +// * This method allows the caller to obtain the file handle that is being +// * used by the nameServerTCP rsvcClient connection. This handle is used +// * by the cdevReactor to detect when an event has occured. +// ***************************************************************************** +int cdevNameServerHandler::getHandle ( void ) const + { + return nameServerTCP->getFd(); + } + + +#ifndef DONT_SUPPORT_CDEV_CALLS + // ********************************************************************* + // * cdevSystemHandler::cdevSystemHandler : + // * This is the constructor for the cdevSystemHandler object. + // ********************************************************************* + cdevSystemHandler::cdevSystemHandler (cdevReactor & Reactor, + double pollRate, + cdevSystem & System) + : cdevSimpleTimer(Reactor, pollRate), system(System) + { + execute(); + } +#endif + +#ifndef DONT_SUPPORT_CDEV_CALLS + // ********************************************************************* + // * cdevSystemHandler::~cdevSystemHandler : + // * This is the destructor for the cdevSystemHandler object. + // ********************************************************************* + cdevSystemHandler::~cdevSystemHandler (void) + { + } +#endif + +#ifndef DONT_SUPPORT_CDEV_CALLS + // ********************************************************************* + // * cdevSystemHandler::execute : + // * This is the method that is executed when the specified timer + // * expires. + // ********************************************************************* + int cdevSystemHandler::execute (void) + { + system.poll(); + return 0; + } +#endif diff --git a/extensions/cdevGenericServer/lib/cdevSessionManager.cc b/extensions/cdevGenericServer/lib/cdevSessionManager.cc new file mode 100755 index 0000000..32d212f --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevSessionManager.cc @@ -0,0 +1,635 @@ +#include + +cdevReactor cdevSessionManager::Reactor; +IntHash cdevSessionManager::localIdx; + +// ***************************************************************************** +// * ClientSession::ClientSession : +// * This method serves only to initialize the internals of the class. +// ***************************************************************************** +ClientSession::ClientSession ( int SocketID, int ClientID, int LocalID ) + : socketID(SocketID), clientID(ClientID), localID(LocalID) + { + } + +// ***************************************************************************** +// * ClientSession::~ClientSession : +// * This method deletes all unprocessed binary packets that are stored +// * within the queue. +// ***************************************************************************** +ClientSession::~ClientSession ( void ) + { + } + +// ***************************************************************************** +// * SocketSession::SocketSession : +// * This is the constructor for the SocketSession object, it serves only +// * to initialize internal variables. +// ***************************************************************************** +SocketSession::SocketSession( int SocketID ) + : FifoQueue(), socketID(SocketID) + { + } + + +// ***************************************************************************** +// * SocketSession::~SocketSession : +// * This method deletes all unprocessed binary packets that are stored +// * within the queue. +// ***************************************************************************** +SocketSession::~SocketSession ( void ) + { + char * binary; + size_t binaryLen; + + while(dequeue(&binary, &binaryLen)==0) delete binary; + } + + +// ***************************************************************************** +// * cdevSessionManager::~cdevSessionManager : +// * This method deletes all entries from the client and socket queues +// * and then deletes all queue objects... +// ***************************************************************************** +cdevSessionManager::~cdevSessionManager ( void ) + { + int socketID; + int clientID; + IntHashIterator clientIter(&clients); + IntHashIterator socketIter(&sockets); + ClientSession * clientPtr; + SocketSession * socketPtr; + cdevPacketBinary * packet; + + while((packet = (cdevPacketBinary *)inbound.dequeue())!=NULL) + { + delete packet; + } + + clientIter.first(); + while((clientPtr=(ClientSession *)clientIter.data())!=NULL) + { + clientID = clientPtr->getClientID(); + clientIter++; + removeClient(clientID, 0); + } + + socketIter.first(); + while((socketPtr=(SocketSession *)socketIter.data())!=NULL) + { + socketID = socketIter.key(); + socketIter++; + removeSocket(socketID); + } + } + + +// ***************************************************************************** +// * cdevSessionManager::newClientSession : +// * This method allows the caller to create a new ClientSession object. The +// * ClientSession object functions primarily as a pointer to the queue that +// * holds packets destined for a specific client, however, the developer +// * can create a subclass of the ClientSession that may be used to associate +// * additional, client specific information to the structure. +// ***************************************************************************** +ClientSession * cdevSessionManager::newClientSession ( int SocketID, int ClientID, int LocalID ) + { + return new ClientSession (SocketID, ClientID, LocalID); + } + + +// ***************************************************************************** +// * cdevSessionManager::newSocketSession : +// * This method allows the caller to create a new SocketSession object. The +// * SocketSession object functions primarily as a pointer to the queue that +// * holds packets destined for a specific socket, however, the developer +// * can create a subclass of the SocketSession that may be used to associate +// * additional, socket specific information to the structure. +// ***************************************************************************** +SocketSession * cdevSessionManager::newSocketSession ( int SocketID ) + { + return new SocketSession (SocketID); + } + +// ***************************************************************************** +// * cdevSessionManager::deleteSocketSession : +// * This method is called to delete a SocketSession object. +// ***************************************************************************** +void cdevSessionManager::deleteSocketSession ( SocketSession *socket ) + { + if(socket) + { + sockets.remove(socket->getSocketID()); + delete socket; + } + } + +// ***************************************************************************** +// * cdevSessionManager::findLocalClient : +// * This method allows the caller to locate a ClientSession using the local +// * client identifier that is assigned by the cdevSessionManager class. +// ***************************************************************************** +ClientSession * cdevSessionManager::findLocalClient( short localID ) + { + return (ClientSession *)localIdx.find(localID); + } + +// ***************************************************************************** +// * cdevSessionManager::findClient : +// * This method allows the caller to locate a ClientSession using its +// * clientID. +// ***************************************************************************** +ClientSession * cdevSessionManager::findClient( int clientID ) + { + return (ClientSession *)clients.find(clientID); + } + +// ***************************************************************************** +// * cdevSessionManager::findSocket : +// * This method allows the caller to locate a SocketSession using its +// * socketID. +// ***************************************************************************** +SocketSession * cdevSessionManager::findSocket( int socketID ) + { + return (SocketSession *)sockets.find(socketID); + } + +// ***************************************************************************** +// * cdevSessionManager::addClient : +// * This method allows the caller to add a new clientID and construct a +// * ClientSession object for it. +// * +// * The socketID must have already been registered using the addSocket +// * method. If the clientID already exists or if an error occurs NULL will +// * be returned. +// ***************************************************************************** +ClientSession * cdevSessionManager::addClient( int socketID, int clientID ) + { + ClientSession * session = NULL; + + if(findSocket(socketID)!=NULL && findClient(clientID)==NULL) + { + short localID = getNextLocalID(); + if(localID>0 && + (session = newClientSession(socketID, clientID, localID))!=NULL) + { + clients.insert (clientID, session); + localIdx.insert((int)localID, session); + } + } + return session; + } + +// ***************************************************************************** +// * cdevSessionManager::addSocket : +// * This method allows the caller to add a new socketID and construct a +// * SocketSession object to service it. +// * +// * This function will fail if the socketID has already been registered... +// * On failure this method will return NULL. +// ***************************************************************************** +SocketSession * cdevSessionManager::addSocket ( int socketID ) + { + SocketSession * session = NULL; + if(findSocket(socketID)==NULL && + (session = newSocketSession(socketID))!=NULL) + { + sockets.insert(socketID, session); + } + return session; + } + +// ***************************************************************************** +// * cdevSessionManager::removeClient : +// * This method will remove the specified clientID from the clients list +// * and will delete the associated ClientSession object. +// ***************************************************************************** +void cdevSessionManager::removeClient ( int clientID, int unregisterFlag) + { + ClientSession * session; + + if((session = (ClientSession *)clients.find(clientID))!=NULL) + { + // ***************************************************** + // * Submit an unregister command to notify the server + // ***************************************************** + if(unregisterFlag) unregisterClient(session->getLocalID()); + + localIdx.remove((int)session->getLocalID()); + clients.remove (clientID); + delete session; + } + } + + +// ***************************************************************************** +// * cdevSessionManager::removeSocket : +// * This method will remove the specified socketID from the sockets list +// * and will delete the associated SocketSession object. It will then +// * ascend the clients list and will remove all ClientSessions that are +// * associated with the socketID. +// ***************************************************************************** +void cdevSessionManager::removeSocket ( int socketID ) + { + cdevEventHandler * handler = NULL; + SocketSession * socket; + ClientSession * client; + int clientID; + + if(Reactor.getHandler(socketID, handler)==0 && handler!=NULL) + { + delete handler; + } + + if((socket = (SocketSession *)sockets.find(socketID))!=NULL) + { + IntHashIterator clientIter(&clients); + clientIter.first(); + while((client=(ClientSession *)clientIter.data())!=NULL) + { + if(client->getSocketID()==socketID) + { + clientID = client->getClientID(); + clientIter++; + removeClient(clientID); + } + else clientIter++; + } + + deleteSocketSession(socket); + } + } + +// ***************************************************************************** +// * cdevSessionManager::getNextLocalID : +// * This method allows the caller to retrieve a unique localID to be +// * assigned to a client. The nextLocalID value is automatically +// * incremented. +// ***************************************************************************** +short cdevSessionManager::getNextLocalID ( void ) + { + static short nextLocalID = 0; + short startingPoint = nextLocalID; + ClientSession *session = NULL; + + if(nextLocalID>=32767) nextLocalID = 1; + else nextLocalID++; + + startingPoint = nextLocalID; + + do { + session=(ClientSession *)localIdx.find((int)nextLocalID); + if(session!=NULL) + { + if(nextLocalID>=32767) nextLocalID = 1; + else nextLocalID++; + } + } while(session!=NULL && nextLocalID!=startingPoint); + + return session==NULL?nextLocalID:-1; + } + +// ***************************************************************************** +// * cdevSessionManager::enqueue : +// * This method is used to enqueue a binary packet into the inbound +// * fifoQueue. This method is called by the client handler objects. +// * +// * The binary data item becomes the property of the queue and should not +// * be accessed later by the caller. +// ***************************************************************************** +int cdevSessionManager::enqueue( int socketID, char * binary, unsigned binaryLen ) + { + int result = -1; + SocketSession * socket = NULL; + ClientSession * client = NULL; + cdevPacketBinary * packet = new cdevPacketBinary; + + // ********************************************************************* + // * Make sure its a valid packet. + // ********************************************************************* + if(packet->streamIn(binary, binaryLen)==0) + { + // ************************************************************* + // * Add the socketID if it does not already exist. + // ************************************************************* + if((socket = findSocket(socketID))==NULL) + { + socket = addSocket(socketID); + } + + // ************************************************************* + // * Combine the (short)clientID and the (short)socketID to + // * create a unique identifier for this client. + // * + // * < HIGH WORD > < LOW WORD > + // * SSSSSSSS CCCCCCCCC + // ************************************************************* + short packetClientID; + int clientID; + + packet->getClientID(packetClientID); + clientID = ((socketID<<16)|packetClientID); + + // ************************************************************* + // * Add a clientID if it does not already exist. + // ************************************************************* + if((client = findClient(clientID))==NULL && + (client = addClient(socketID, clientID))!=NULL) + { + registerClient ( client->getLocalID() ); + } + + // ************************************************************* + // * This would only fail if the clientID had already been used + // * by another socket. + // ************************************************************* + if(client!=NULL && client->getSocketID()==socketID) + { + result = 0; + + // ***************************************************** + // * At this point everything necessary is known to + // * submit the packet for processing... + // ***************************************************** + + // ***************************************************** + // * Set the clientID to the localClientID to be used + // * by the server side of the connection. + // ***************************************************** + packet->setClientID(client->getLocalID()); + + // ***************************************************** + // * Enqueue the packet and set the pointer to NULL to + // * prevent its later deletion. + // ***************************************************** + inbound.enqueue((void *)packet); + packet = NULL; + } + } + if(packet!=NULL) delete packet; + + // ********************************************************************* + // * If a packet was successfully added to the inbound queue and the + // * queue is not empty , then add an event to the FDTrigger to cause + // * the handle_input mechanism to be called. + // ********************************************************************* + if(result==0 && !inbound.empty()) trigger.insertEvent(); + + // ********************************************************************* + // * Due to the new design of the SocketUtil class, the binary should + // * never be deleted. + // ********************************************************************* + return result; + } + + +// ***************************************************************************** +// * cdevSessionManager::enqueue : +// * This method is used to enqueue a cdevPacket packet into an outbound +// * queue. The method will first identify the target client and place the +// * packet into its queue... then it will identify the socket and place the +// * packet into its queue. +// * +// * This method will return -1 if either the socket or the client is +// * undefined. +// * +// * The packet remains the property of the caller who must delete it. +// ***************************************************************************** +int cdevSessionManager::enqueue ( cdevPacket * input ) + { + cdevPacketBinary * packet = encodePacket(input); + ClientSession * client = NULL; + SocketSession * socket = NULL; + int result = -1; + + // ********************************************************************* + // * Note that this condition makes sure that a queue exists for both + // * the client ID and the socketID. If both of these conditions are + // * met, then it checks to ensure that the socket has not been overrun + // * with data (500 or more packets). + // ********************************************************************* + if(packet!=NULL && + input->getClientID()>0 && + (client = findLocalClient(input->getClientID()))!=NULL && + (socket = findSocket(client->getSocketID()))!=NULL) + { + cdevEventHandler * handler = NULL; + Reactor.getHandler(client->getSocketID(), handler); + + // ************************************************************* + // * Attempt to flush the handler if more than 500 packets + // * have already been inserted. + // ************************************************************* + if(handler && socket->getCount()>=500) + { + outputError(CDEV_SEVERITY_WARN, "CDEV Server", + "Forcing flush of socket %i to prevent overflow...", + client->getSocketID()); + + // ***************************************************** + // * Call handleOutput to cause the handler to attempt + // * to write its contents. + // ***************************************************** + if(handler->handleOutput()<0) + { + Reactor.removeHandler(handler); + handler = NULL; + } + } + + if(handler && socket->getCount()<500) + { + char * binary = NULL; + size_t binaryLen = 0; + + // ***************************************************** + // * Create a binary stream from the cdevPacketBinary + // * object and then use the detachData method to + // * prevent the buffer from being deleted when the + // * cdevPacketBinary is destroyed. + // ***************************************************** + packet->streamOut(&binary, &binaryLen); + packet->detachData(); + + // ***************************************************** + // * Populate the cdevServerBinary object with the data + // * that was extracted from the cdevPacketBinary object + // ***************************************************** + socket->enqueue(binary, binaryLen); + + // ***************************************************** + // * Set the event mask for the outbound socket to read/ + // * write to force it to attempt to write to the socket + // * until data is transmitted. + // ***************************************************** + if(handler) handler->setMask(READ_MASK|WRITE_MASK); + + result = 0; + } + else if(handler) + { + outputError ( CDEV_SEVERITY_ERROR, "CDEV Server", + "Dropping packet to socket %i : queue is full...", + client->getSocketID()); + } + } + + // ********************************************************************* + // * Delete the cdevPacketBinary if it was generated. + // ********************************************************************* + if(packet) delete packet; + + return result; + } + + +// ***************************************************************************** +// * cdevSessionManager::dequeue : +// * This method is used to by the server engine to extract a message from +// * the inbound queue. Once the packet has been enqueue it will be sent to +// * the decodePacket method which will perform any preprocessing that the +// * developer may deem necessary before returning the packet to the caller. +// * +// * The cdevPacket object becomes the property of the caller and must +// * be deleted when it is no longer needed. +// ***************************************************************************** +int cdevSessionManager::dequeue ( cdevPacket * &packet ) + { + cdevPacketBinary * binary = NULL; + packet = NULL; + + // ********************************************************************* + // * Conitnue this loop unitl a valid packet has been extracted, or + // * until there are no more binary packets left in the queue. + // ********************************************************************* + do { + // ************************************************************* + // * Attempt to dequeue the cdevPacketBinary from the queue... + // * If it is not NULL, then begin processing. + // ************************************************************* + if((binary = (cdevPacketBinary *)inbound.dequeue())!=NULL) + { + // ***************************************************** + // * Call the decodePacket mechanism... This will use + // * the factory mechanisms of the cdevPacket class to + // * import the data and then will complete any required + // * preprocessing... + // ***************************************************** + packet = decodePacket(binary); + + // ***************************************************** + // * Delete the binary as it is no longer needed. + // ***************************************************** + delete binary; + } + } while(binary!=NULL && packet==NULL); + + // ********************************************************************* + // * Return 0 if a cdevPacket was successfully dequeued, otherwise, + // * return -1. + // ********************************************************************* + return packet?0:-1; + } + +// ***************************************************************************** +// * cdevServer::decodePacket : +// * This method is used to perform preprocessing on a newly dequeued binary +// * packet before it is provided to the caller. This method allows the +// * developer to perform special preparations on the packet before providing +// * it to the caller. +// ***************************************************************************** +cdevPacket * cdevSessionManager::decodePacket (cdevPacketBinary * input) + { + return input?cdevPacket::import(*input):(cdevPacket *)NULL; + } + + +// ***************************************************************************** +// * cdevSessionManager::encodePacket : +// * This method is used to perform postprocessing on a packet that has been +// * enqueued to be sent to a client. This method allows the developer to +// * perform special preparations on the packet before providing it to the +// * client. +// ***************************************************************************** +cdevPacketBinary * cdevSessionManager::encodePacket ( cdevPacket * input ) + { + cdevPacketBinary *result; + + if(input) + { + char * binary; + size_t binaryLen; + input->streamOut(&binary, &binaryLen); + if(binary && binaryLen) + { + result = new cdevPacketBinary; + result->attachData(binary, binaryLen); + } + } + return result; + } + +// ***************************************************************************** +// * cdevSessionManager::getHandle : +// * This method is used to obtain a copy of the file handle that is used +// * to poll for events. In this case it will be the read file descriptor +// * of the FD_Trigger object. +// ***************************************************************************** +int cdevSessionManager::getHandle ( void ) const + { + return trigger.readfd(); + } + +// ***************************************************************************** +// * cdevSessionManager::handleInput : +// * This method is called whenever there is a read event pending on the +// * FD_Trigger object. +// ***************************************************************************** +int cdevSessionManager::handleInput ( void ) + { + processMessages(); + if(inbound.empty()) trigger.purge(); + return 0; + } + +// **************************************************************************** +// cdevSessionManager::handleClose : +// Shuts down the timer - this will result in the destruction of the +// * cdevSessionManager object. +// **************************************************************************** +int cdevSessionManager::handleClose(void) + { + return -1; + } + + +// **************************************************************************** +// * cdevSessionManager::handleTimeout : +// * Called when the timer expires... This method serves only to call the +// * processMessages function. +// **************************************************************************** +int cdevSessionManager::handleTimeout(void) + { + processMessages(); + if(inbound.empty()) trigger.purge(); + return 0; + } + + +// *************************************************************************** +// * cdevServer::processMessages : +// * This is a simple stand-in function that retrieves a message from the +// * queue and then immediately returns it to the outbound queue. This +// * function should be overloaded by the developers mechanism for +// * processing messages. +// *************************************************************************** +void cdevSessionManager::processMessages ( void ) + { + cdevPacket * packet; + + while(dequeue(packet)==0) + { + enqueue(packet); + delete packet; + } + } diff --git a/extensions/cdevGenericServer/lib/cdevSocket.cc b/extensions/cdevGenericServer/lib/cdevSocket.cc new file mode 100644 index 0000000..5d5b057 --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevSocket.cc @@ -0,0 +1,157 @@ +#include "cdevSocket.h" + +void cdevSocket::setHandle ( int fd ) + { + handle = fd; + } + + +int cdevSocket::getHandle ( void ) const + { + return handle; + } + + +int cdevSocket::open (int type, int protocol_family, int protocol) + { + setHandle(::socket(protocol_family, type, protocol)); + return getHandle(); + } + + +int cdevSocket::close (void) + { + int result = ::close(getHandle()); + setHandle(INVALID_HANDLE); + return result; + } + + +int cdevSocket::unsetFlags ( int flags ) + { + int retval = -1; + int fd = getHandle(); + + if(fd!=cdevSocket::INVALID_HANDLE) + { + #ifdef WIN32 + if(flags==O_NONBLOCK) + { + unsigned long val = 0; + retval = ::ioctlsocket(fd, FIONBIO, &val); + } + #else + int val; + if((val=::fcntl(fd, F_GETFL, 0)) != -1) + { + val &= ~flags; + retval = (::fcntl(fd, F_SETFL, val)!=-1)?0:1; + } + #endif + } + + return retval; + } + + +int cdevSocket::setFlags ( int flags ) + { + int retval = -1; + int fd = getHandle(); + + if(fd!=cdevSocket::INVALID_HANDLE) + { + #ifdef WIN32 + if(flags==O_NONBLOCK) + { + unsigned long val = 1; + retval = ::ioctlsocket(fd, FIONBIO, &val); + } + #else + int val; + if ((val=::fcntl(fd, F_GETFL, 0)) != -1) + { + val |= flags; + if(::fcntl(fd, F_SETFL, val) != -1) retval = 0; + } + #endif + } + + return retval; + } + + +int cdevSocket::getFlags ( void ) + { + int retval = -1; + int fd = getHandle(); + + #ifdef WIN32 + retval = 0; + #else + if(fd!=cdevSocket::INVALID_HANDLE) + { + retval=::fcntl(fd, F_GETFL, 0); + } + #endif + + return retval; + } + +int cdevSocket::setOption (int level, int option, void *optval, int optlen) const + { + return ::setsockopt(getHandle(), level, option, (char *)optval, (SOCKOPT_SIZE_PARM)optlen); + } + + +int cdevSocket::getOption (int level, int option, void *optval, int *optlen) const + { + return ::getsockopt(getHandle(), level, option, (char *)optval, (SOCKOPT_SIZE_PARM *)optlen); + } + + +int cdevSocket::getLocalAddress (cdevAddr & addr) + { + int retval; + int len=addr.getSize(); + + if(::getsockname(getHandle(), (sockaddr *)addr.getAddress(), (SOCKOPT_SIZE_PARM *)&len)==INVALID_HANDLE) + { + retval = INVALID_HANDLE; + } + else { + addr.setSize(len); + retval = 0; + } + return retval; + } + + +int cdevSocket::getRemoteAddress (cdevAddr & addr) + { + int retval; + int len = addr.getSize(); + if(::getpeername(getHandle(), (sockaddr *)addr.getAddress(), (SOCKOPT_SIZE_PARM *)&len)==INVALID_HANDLE) + { + retval = INVALID_HANDLE; + } + else { + addr.setSize(len); + retval = 0; + } + return retval; + } + + +cdevSocket::cdevSocket ( void ) + : handle(INVALID_HANDLE) + { + } + + +cdevSocket::cdevSocket(int type, int protocol_family, int protocol) + : handle(INVALID_HANDLE) + { + setHandle(open(type, protocol_family, protocol)); + } + diff --git a/extensions/cdevGenericServer/lib/cdevSocketAcceptor.cc b/extensions/cdevGenericServer/lib/cdevSocketAcceptor.cc new file mode 100644 index 0000000..1004b3a --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevSocketAcceptor.cc @@ -0,0 +1,93 @@ +#include "cdevSocketAcceptor.h" + +// ***************************************************************************** +// * cdevSocketAcceptor::cdevSocketAcceptor : +// * Do nothing routine for constructor. +// ***************************************************************************** +cdevSocketAcceptor::cdevSocketAcceptor(void) + { + } + +// ***************************************************************************** +// * cdevSocketAcceptor::open : +// * General purpose routine for performing server cdevSocket creation. +// ***************************************************************************** +int cdevSocketAcceptor::open + ( + const cdevAddr &addr, + int reuse_addr, + int protocol_family, + int backlog, + int protocol, + int reopen) + { + int one = 1; + int retval; + + if(reopen) cdevSocket::open(SOCK_STREAM, protocol_family, protocol); + + if(this->getHandle() == cdevSocket::INVALID_HANDLE) + { + retval = cdevSocket::INVALID_HANDLE; + close(); + } + else { + if(reuse_addr && setOption(SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == cdevSocket::INVALID_HANDLE) + { + close(); + } + else if(::bind(getHandle(), (sockaddr *)addr.getAddress(), + addr.getSize()) == cdevSocket::INVALID_HANDLE || + ::listen(getHandle(), backlog) == cdevSocket::INVALID_HANDLE) + { + close(); + } + retval = getHandle(); + } + return retval; + } + +// ***************************************************************************** +// * cdevSocketAcceptor::cdevSocketAcceptor : +// * General purpose routine for performing server cdevSocket creation. +// ***************************************************************************** +cdevSocketAcceptor::cdevSocketAcceptor ( + const cdevAddr &addr, + int reuse_addr, + int protocol_family, + int backlog, + int protocol) + : cdevSocket(SOCK_STREAM, protocol_family, protocol) + { + open(addr, reuse_addr, protocol_family, backlog, protocol, 0); + } + +// ***************************************************************************** +// * cdevSocketAcceptor::accept : +// * General purpose routine for accepting new connections. +// ***************************************************************************** +int cdevSocketAcceptor::accept(cdevSocketStream &new_stream, cdevAddr *addr) const + { + sockaddr *sock_addr=0; + int *len_ptr=0; + int len; + int new_handle; + + if(addr != 0) + { + len=addr->getSize(); + len_ptr= &len; + sock_addr=(sockaddr *) addr->getAddress(); + } + + do { + new_handle=::accept(this->getHandle(), sock_addr, (SOCKOPT_SIZE_PARM *)len_ptr); + } while(new_handle==cdevSocket::INVALID_HANDLE && errno==EINTR); + + if(addr != 0) addr->setSize(*len_ptr); + + new_stream.setHandle(new_handle); + new_stream.configureHandle(); + + return new_handle; + } diff --git a/extensions/cdevGenericServer/lib/cdevSocketConnector.cc b/extensions/cdevGenericServer/lib/cdevSocketConnector.cc new file mode 100644 index 0000000..880a5db --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevSocketConnector.cc @@ -0,0 +1,65 @@ +#include "cdevSocketConnector.h" +#include "cdevHandleSet.h" + +// ***************************************************************************** +// * cdevSocketConnector::connect : +// * Actively connect and produce a new cdevSocketStream if things go well... +// ***************************************************************************** +int cdevSocketConnector::connect ( const cdevAddr & remote_addr ) + { + int retval = 0; + + if(getHandle() == cdevSocket::INVALID_HANDLE && + cdevSocket::open(SOCK_STREAM, PF_INET, 0) == cdevSocket::INVALID_HANDLE) + { + retval = -1; + } + else + { + double secondsWaited = 0.0; + sockaddr *addr=(sockaddr *) remote_addr.getAddress(); + size_t size=remote_addr.getSize(); + + if(configureHandle()<0) + { + retval = -1; + } + else if(::connect(getHandle(), addr, size) == cdevSocket::INVALID_HANDLE) + { + int errCode = GetSocketErrno(); + + if(getBlockingSemantics()==O_NONBLOCK && errCode==EINPROGRESS) + { + errCode=EWOULDBLOCK; + } + + if(errCode == EISCONN) + { + retval = 0; + } + else if(errCode != EWOULDBLOCK) + { + close(); + setHandle(cdevSocket::INVALID_HANDLE); + retval = -1; + } + else { + cdevHandleSet ws; + cdevHandleSet es; + struct timeval tv; + int fd = getHandle(); + + ws.set_bit(fd); + es.set_bit(fd); + tv.tv_sec = 3; + tv.tv_usec = 0; + + if(cdevSelect(fd+1, NULL, ws, es, &tv)>0 && ws.is_set(fd)) retval = 0; + else retval = -1; + } + } + } + + return retval; + } + diff --git a/extensions/cdevGenericServer/lib/cdevSocketDatagram.cc b/extensions/cdevGenericServer/lib/cdevSocketDatagram.cc new file mode 100644 index 0000000..58bd240 --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevSocketDatagram.cc @@ -0,0 +1,44 @@ +#include "cdevSocketDatagram.h" + +int cdevSocketDatagram::open ( const cdevAddr &addr, int protocol_family, int protocol ) + { + int result = 0; + + if((result = cdevSocket::open(SOCK_DGRAM, protocol_family, protocol))!=-1) + { + result = bind(getHandle(), (sockaddr *)addr.getAddress(), addr.getSize()); + } + if(result!=0) close(); + + return result; + } + + +ssize_t cdevSocketDatagram::send (const void *buf, size_t n, const cdevAddr &addr, int flags) const + { + sockaddr *saddr = (sockaddr *) addr.getAddress (); + size_t len = addr.getSize (); + return sendto (this->getHandle (), (const char *) buf, n, flags, (struct sockaddr *) saddr, len); + } + + +ssize_t cdevSocketDatagram::recv (void *buf, size_t n, cdevAddr &addr, int flags) const + { + sockaddr *saddr = (sockaddr *) addr.getAddress(); + int len = addr.getSize(); + ssize_t status = recvfrom (this->getHandle(), (char *)buf, n, flags, (sockaddr *) saddr, (SOCKOPT_SIZE_PARM *)&len); + addr.setSize (len); + return status; + } + + +cdevSocketDatagram::cdevSocketDatagram ( void ) + { + } + + +cdevSocketDatagram::cdevSocketDatagram ( const cdevAddr &addr, int protocol_family, int protocol ) + { + open(addr, protocol_family, protocol); + } + diff --git a/extensions/cdevGenericServer/lib/cdevSocketStream.cc b/extensions/cdevGenericServer/lib/cdevSocketStream.cc new file mode 100755 index 0000000..325b1e5 --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevSocketStream.cc @@ -0,0 +1,177 @@ +#include "cdevSocketStream.h" + +// ***************************************************************************** +// * cdevSocketStream::cdevSocketStream : +// * Constructor for the cdevSocketStream class. Only serves to initialize +// * the readRetryCount variable. +// ***************************************************************************** +cdevSocketStream::cdevSocketStream ( void ) + { + } + +// ***************************************************************************** +// * cdevSocketStream::send : +// * Send an n byte message to the connected socket. +// ***************************************************************************** +ssize_t cdevSocketStream::send(const void *buf, size_t n, int flags) const + { + int retval; + if((retval = ::send(getHandle(), (const char *) buf, n, flags))<=0) + { + int errCode = GetSocketErrno(); + + if(errCode==EAGAIN || errCode==EWOULDBLOCK) retval = 0; + } + return retval; + } + +// ***************************************************************************** +// * cdevSocketStream::send_n : +// * This method will transmit an n byte message to a connected socket, +// * waiting until all data has been transmitted or an error occurs. +// ***************************************************************************** +ssize_t cdevSocketStream::send_n(const void *buf, size_t n, int flags) const + { + ssize_t amntsent = 0; + int result = 0; + + while(amntsent<(ssize_t)n && result>=0) + { + if((result = ::send(getHandle(), (const char *)buf+amntsent, n-amntsent, flags))<=0) + { + int errCode = GetSocketErrno(); + + if(errCode==EAGAIN || errCode==EWOULDBLOCK) result = 0; + else result = -1; + } + else amntsent+=result; + } + return (amntsent>=(ssize_t)n)?amntsent:-1; + } + + +// ***************************************************************************** +// * cdevSocketStream::recv : +// * Recv an n byte message from the connected socket. +// ***************************************************************************** +ssize_t cdevSocketStream::recv(void *buf, size_t n, int flags) + { + int retval = 0; + + if((retval = ::recv(getHandle(), (char *)buf, n, flags))<=0) + { + int errCode = GetSocketErrno(); + + if(errCode==EAGAIN || errCode==EWOULDBLOCK) retval = 0; + } + return retval; + } + + +// ***************************************************************************** +// * cdevSocketStream::recv_n : +// * This method will receive an n byte message from a connected socket, +// * waiting until all data has been received or an error occurs. +// ***************************************************************************** +ssize_t cdevSocketStream::recv_n(void *buf, size_t n, int flags) + { + ssize_t amntrecv = 0; + int result = 0; + + while(amntrecv < (ssize_t)n) + { + if((result = ::recv(getHandle(), (char *)buf+amntrecv, n-amntrecv, flags)) < 0) + { + return -1; + } + else if (result == 0) + break; + else amntrecv+=result; + } + return amntrecv; + } + + +// ***************************************************************************** +// * cdevSocketStream::closeReader : +// * Shut down just the reading end of a cdevSocket. +// ***************************************************************************** +int cdevSocketStream::closeReader(void) + { + return ::shutdown(getHandle(), 0); + } + + +// ***************************************************************************** +// * cdevSocketStream::closeWriter : +// * Shut down just the writing end of a cdevSocket. +// ***************************************************************************** +int cdevSocketStream::closeWriter(void) + { + return ::shutdown(getHandle(), 1); + } + + +int cdevSocketStream::getBlockingSemantics ( void ) const + { + return O_NONBLOCK; + } + +int cdevSocketStream::getRcvLowWaterMark ( void ) const + { + return 0; + } + +int cdevSocketStream::getRcvBufferSize ( void ) const + { + return 56000; + } + +int cdevSocketStream::getSndLowWaterMark ( void ) const + { + return 16000; + } + +int cdevSocketStream::getSndBufferSize ( void ) const + { + return 56000; + } + +int cdevSocketStream::configureHandle ( void ) + { + int retval = 0; + int parm = 1; + + + if(getBlockingSemantics()==O_NONBLOCK && setFlags(O_NONBLOCK)==-1) + { + retval = -1; + } + + setOption(IPPROTO_TCP, TCP_NODELAY, &parm, sizeof(parm)); + + if((parm = getRcvBufferSize())>0) + { + setOption(SOL_SOCKET, SO_RCVBUF, &parm, sizeof(parm)); + } +#ifndef __linux + if((parm = getRcvLowWaterMark())>0) + { + setOption(SOL_SOCKET, SO_RCVLOWAT, &parm, sizeof(parm)); + } +#endif + + if((parm = getSndBufferSize())>0) + { + setOption(SOL_SOCKET, SO_SNDBUF, &parm, sizeof(parm)); + } + +#ifndef __linux + if((parm = getSndLowWaterMark())>0) + { + setOption(SOL_SOCKET, SO_SNDLOWAT, &parm, sizeof(parm)); + } +#endif + + return retval; + } diff --git a/extensions/cdevGenericServer/lib/cdevStreamNode.cc b/extensions/cdevGenericServer/lib/cdevStreamNode.cc new file mode 100644 index 0000000..350c437 --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevStreamNode.cc @@ -0,0 +1,20 @@ +#include "cdevStreamNode.h" + +cdevStreamNode::cdevStreamNode ( void ) + : nextStreamNode(NULL) + { + } + +cdevStreamNode::~cdevStreamNode ( void ) + { + } + +cdevStreamNode * cdevStreamNode::getNext( void ) const + { + return nextStreamNode; + } + +void cdevStreamNode::setNext (cdevStreamNode * node) + { + nextStreamNode = node; + } diff --git a/extensions/cdevGenericServer/lib/cdevStreamQueue.cc b/extensions/cdevGenericServer/lib/cdevStreamQueue.cc new file mode 100644 index 0000000..81ea4ce --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevStreamQueue.cc @@ -0,0 +1,35 @@ +#include "cdevStreamQueue.h" + +cdevSimpleStreamNode::cdevSimpleStreamNode( char * buffer, size_t size) + : cdevStreamNode(), buf(buffer), len(size) + { + } + +cdevSimpleStreamNode::~cdevSimpleStreamNode ( void ) + { + if(buf) delete buf; + } + +size_t cdevSimpleStreamNode::getLen (void) const + { + return len; + } + +void cdevSimpleStreamNode:: setLen (size_t size) + { + len=size; + } + +char * cdevSimpleStreamNode::getBuf (void) const + { + return buf; + } + +void cdevSimpleStreamNode::setBuf (char * buffer, size_t size) + { + buf=buffer; len=size; + } + +cdevNodeFactory::~cdevNodeFactory ( void ) + { + } diff --git a/extensions/cdevGenericServer/lib/cdevTagMap.cc b/extensions/cdevGenericServer/lib/cdevTagMap.cc new file mode 100755 index 0000000..e1a11e0 --- /dev/null +++ b/extensions/cdevGenericServer/lib/cdevTagMap.cc @@ -0,0 +1,221 @@ +#include + +// ***************************************************************************** +// * cdevTagMap::cdevTagMap : +// * This is the constructor for the cdevTagMap class. +// ***************************************************************************** +cdevTagMap::cdevTagMap ( void ) + : cnt(0), + maximum(0), + local(NULL), + remote(NULL) + { + } + + +// ***************************************************************************** +// * cdevTagMap::cdevTagMap : +// * This is the destructor for the cdevTagMap class. +// ***************************************************************************** +cdevTagMap::~cdevTagMap ( void ) + { + if(local !=NULL) free(local); + if(remote!=NULL) free(remote); + } + +// ***************************************************************************** +// * cdevTagMap::updateTagMap : +// * This method will read the names and integers from a cdevData object and +// * will then pass these values to the updateTagMap method for processing. +// * +// * For standardization the tag integers are placed in tag 1, and the +// * tag strings are placed in tag 2... +// ***************************************************************************** +void cdevTagMap::updateTagMap ( cdevData & data ) + { + char ** names; + int * tags; + size_t nameCnt=0, tagCnt=0; + + if(data.getElems(1, &tagCnt)==CDEV_SUCCESS && + data.getElems(2, &nameCnt)==CDEV_SUCCESS && + tagCnt>0 && tagCnt==nameCnt) + { + names = new char *[nameCnt]; + tags = new int [tagCnt]; + memset(names, 0, sizeof(char *)*nameCnt); + data.get(1, tags); + data.get(2, names); + updateTagMap(names, tags, nameCnt); + while(nameCnt>0) + { + --nameCnt; + delete names[nameCnt]; + } + delete names; + delete tags; + } + } + +// ***************************************************************************** +// * cdevTagMap::updateTagMap : +// * This method will create a mapping of the differences between the tags +// * specified in the user provided array and the tags that are stored +// * within cdevData. +// ***************************************************************************** +void cdevTagMap::updateTagMap ( char ** names, int * tags, int count ) + { + // ********************************************************************* + // * Process each item in the names array from last to first. + // ********************************************************************* + while((--count)>=0) + { + int localTag = -1; + + // ************************************************************* + // * Determine if a tag that is identified by the names[count] + // * string exists in the cdevData Global Tag Table. If it + // * does, copy its integer representation into the localTag + // * variable. + // ************************************************************* + if(cdevData::tagC2I(names[count], &localTag)!=CDEV_SUCCESS) + { + // ***************************************************** + // * If the string does not already exist in the + // * cdevData Global Tag Table, then attempt to add it. + // * + // * If the specified integer is in use locally by + // * another cdevData tag - then the value will be + // * incremented until an open slot is found. + // ***************************************************** + char * s; + localTag = tags[count]; + while(cdevData::tagI2C(localTag, s)==CDEV_SUCCESS) + { + localTag++; + } + cdevData::insertTag(localTag, names[count]); + } + + // ************************************************************* + // * If the local integer tag value differs from the remote + // * integer tag value, then this tag must be added to the + // * list. + // ************************************************************* + if(localTag != tags[count]) + { + int idx; + + // ***************************************************** + // * Walk through the list and determine if the tag + // * has already been added to the list... + // ***************************************************** + for(idx=0; idx=cnt) + { + // ********************************************* + // * If the internal arrays have not yet been + // * allocated, then allocate a default number + // * of entries (64). + // ********************************************* + if(maximum==0) + { + maximum=64; + local = (int *)malloc(maximum*sizeof(int)); + remote = (int *)malloc(maximum*sizeof(int)); + } + // ********************************************* + // * If the internal arrays are already filled + // * by the existing entries, then double the + // * size of the arrays. + // ********************************************* + else if(idx>=maximum) + { + maximum*=2; + local = (int *)realloc(local, maximum*sizeof(int)); + remote = (int *)realloc(remote, maximum*sizeof(int)); + } + + // ********************************************* + // * Populate the new entry with the mismatch + // * data and increment the total number of + // * mismatches. + // ********************************************* + local [idx] = localTag; + remote[idx] = tags[count]; + cnt = idx+1; + } + } + } + } + + +// ***************************************************************************** +// * cdevTagMap::swapTags : +// * This method is used to swap between two sets of tags... If a tag +// * listed in the outTags array is used in the cdevData item, its tag will +// * be converted to the corresponding value in the inTags array. +// ***************************************************************************** +void cdevTagMap::swapTags ( cdevData & data, int *inTags, int *outTags, int count) + { + int tag; + int changeCount = 0; + cdevDataIterator iter(&data); + + iter.init(); + do { + int idx; + for(idx=0, tag=iter.tag(); idxtv_sec = tv_sec; + t->tv_usec = tv_usec; + } + } + + +void cdevTime::setTime ( void ) + { + struct timeval tv_time; + + gettimeofday(&tv_time); + + tv_sec = tv_time.tv_sec; + tv_usec = tv_time.tv_usec; + } + + +void cdevTime::setTime ( double t ) + { + tv_sec = (long)t; + tv_usec = (long)((double)fmod(t, 1.0)*(double)ONE_SECOND); + normalize(); + } + + +void cdevTime::setTime ( long sec, long usec ) + { + tv_sec = sec; + tv_usec = usec; + normalize(); + } + + +void cdevTime::setTime ( timeval & t ) + { + tv_sec = t.tv_sec; + tv_usec = t.tv_usec; + normalize(); + } + + +void cdevTime::setTime ( const cdevTime & t ) + { + t.getTime(&tv_sec, &tv_usec); + normalize(); + } + + +void cdevTime::clear ( void ) + { + tv_sec = 0; + tv_usec = 0; + } + + +int cdevTime::isSet ( void ) const + { + return (tv_sec||tv_usec)?1:0; + } + + +int cdevTime::normalize ( void ) + { + while ((this->tv_usec >= ONE_SECOND) + || (this->tv_sec < 0 && this->tv_usec > 0 )) + { + this->tv_usec -= ONE_SECOND; + this->tv_sec++; + } + + while ((this->tv_usec <= -ONE_SECOND) + || (this->tv_sec > 0 && this->tv_usec < 0)) + { + this->tv_usec += ONE_SECOND; + this->tv_sec--; + } + + return isSet(); + } + + +cdevTime & cdevTime::operator = ( const cdevTime & t ) + { + if (this != &t) + { + tv_sec = t.tv_sec; + tv_usec = t.tv_usec; + } + return *this; + } + + +cdevTime::operator double ( void ) + { + return (double)tv_sec+(double)tv_usec/(double)ONE_SECOND; + } + + +cdevTime::operator timeval ( void ) + { + timeval tv_time; + + tv_time.tv_sec = tv_sec; + tv_time.tv_usec = tv_usec; + + return tv_time; + } + + +cdevTime operator + (cdevTime t1, cdevTime t2) + { + cdevTime sum (t1.tv_sec + t2.tv_sec, t1.tv_usec + t2.tv_usec); + + sum.normalize (); + return sum; + } + + +cdevTime operator - (cdevTime t1, cdevTime t2) + { + cdevTime delta (t1.tv_sec - t2.tv_sec, t1.tv_usec - t2.tv_usec); + + delta.normalize (); + return delta; + } + + +int operator > (cdevTime t1, cdevTime t2) + { + if (t1.tv_sec > t2.tv_sec) return 1; + else if (t1.tv_sec == t2.tv_sec && t1.tv_usec > t2.tv_usec) return 1; + else return 0; + } + + +int operator >= (cdevTime t1, cdevTime t2) + { + if (t1.tv_sec > t2.tv_sec) return 1; + else if (t1.tv_sec == t2.tv_sec && t1.tv_usec >= t2.tv_usec) return 1; + else return 0; + } + + +int operator < (cdevTime t1, cdevTime t2) + { + return t2 > t1; + } + + +int operator <= (cdevTime t1, cdevTime t2) + { + return t2 >= t1; + } + + +int operator == (cdevTime t1, cdevTime t2) + { + return t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec; + } + + +int operator != (cdevTime t1, cdevTime t2) + { + return !(t1 == t2); + } diff --git a/extensions/cdevGenericServer/lib/fifo.cc b/extensions/cdevGenericServer/lib/fifo.cc new file mode 100644 index 0000000..794ef71 --- /dev/null +++ b/extensions/cdevGenericServer/lib/fifo.cc @@ -0,0 +1,2 @@ +#define _FIFO_QUEUE_MASTER_ 1 +#include diff --git a/extensions/cdevGenericServer/liteClient/Makefile b/extensions/cdevGenericServer/liteClient/Makefile new file mode 100755 index 0000000..9453654 --- /dev/null +++ b/extensions/cdevGenericServer/liteClient/Makefile @@ -0,0 +1,229 @@ +ARCH = OS +SHOBJ = YES + +include ../include/makeinclude/Makefile.$(ARCH) + +# ****************************************************************************** +# * Due to a change in the operating system, the CXX compiler for HP-UX may +# * be different depending on which platform is used. +# ****************************************************************************** +ifeq ($(OS_MAJOR), 09) + CXX := /usr/bin/CC + HP_FLAGS = -Aa -pta -ptb -D_SELECT_USES_INT_ +endif + +ifeq ($(OS_MAJOR).$(OS_MINOR), 10.10) + CXX := /opt/CC/bin/CC + HP_FLAGS = -Aa -pta -ptb -Dvolatile="" + NETLIBS = -lxti +endif + +ifeq ($(OS_MAJOR).$(OS_MINOR), 10.20) + CXX := /opt/aCC/bin/aCC + HP_FLAGS = +W302,749,829 + NETLIBS = -lxti +endif + +APPNAME = "Lite Client Interface" +DEBUG = -g +CXXFLAGS = -D_NO_CDEV_SYSTEM_ -z $(CXXEXTRA) $(SELECTFLAG) $(CXXINCLUDES) $(OS_VERSION_DEF) $(DEBUG) $(HP_FLAGS) +LDFLAGS = -Wl,+s +AR = ar +ARFLAGS = ruv +RANLIB = true +DLD = $(CXX) +SOFLAGS = -b -Wl,+s +PIC = +z +SHARED_EXT = sl +OSLIBS = -ll -ly -lm + + +CXXINCLUDES = -I./ -I../include + +PERMLINKS = ClientInfo.h\ + cdevMessage.cc \ + cdevMessage.h \ + cdevMessageBinary.cc \ + cdevMessageBinary.h \ + cdevPacket.cc \ + cdevPacket.h \ + cdevPacketBinary.h \ + AddressIndex.h \ + ServerInterface.cc \ + ServerInterface.h \ + ServerHandler.cc \ + ServerHandler.h \ + ErrorReporter.h \ + SocketUtil.h \ + SignalManager.cc \ + SignalManager.h \ + fifo.cc \ + fifo.h \ + clipMagicNumber.h \ + cdevCommon.h \ + cdevClock.cc \ + cdevClock.h \ + cdevTimeValue.cc \ + cdevTimeValue.h \ + cdevStrHash.cc \ + cdevStrHash.h \ + cdevIntHash.cc \ + cdevIntHash.h \ + cdevSlist.cc \ + cdevSlist.h \ + cdevErrCode.h \ + cdevSpec.h \ + cdevData.cc \ + cdevData.h \ + cdevData.i \ + cdevDataEntry.cc \ + cdevDataEntry.h \ + cdevGlobalTagTable.cc \ + cdevGlobalTagTable.h \ + cdevTagTable.cc \ + cdevTagTable.h \ + cdevTypes.h \ + xdrClass.h\ + cdevAddr.cc\ + cdevAddr.h\ + cdevEventHandler.cc\ + cdevEventHandler.h\ + cdevHandleSet.cc\ + cdevHandleSet.h\ + cdevPlatforms.h\ + cdevReactor.cc\ + cdevReactor.h\ + cdevSocket.cc\ + cdevSocket.h\ + cdevSocketAcceptor.cc\ + cdevSocketAcceptor.h\ + cdevSocketConnector.cc\ + cdevSocketConnector.h\ + cdevSocketDatagram.cc\ + cdevSocketDatagram.h\ + cdevSocketStream.cc\ + cdevSocketStream.h\ + cdevStreamNode.cc\ + cdevStreamNode.h\ + cdevStreamQueue.cc\ + cdevStreamQueue.h\ + cdevTime.cc\ + cdevTime.h\ + StringHash.h + +OBJS = $(OBJDIR)/ServerHandler.o \ + $(OBJDIR)/ServerInterface.o \ + $(OBJDIR)/cdevClock.o \ + $(OBJDIR)/cdevData.o \ + $(OBJDIR)/cdevDataEntry.o \ + $(OBJDIR)/cdevGlobalTagTable.o \ + $(OBJDIR)/cdevIntHash.o \ + $(OBJDIR)/cdevMessage.o \ + $(OBJDIR)/cdevMessageBinary.o \ + $(OBJDIR)/cdevPacket.o \ + $(OBJDIR)/cdevSlist.o \ + $(OBJDIR)/cdevStrHash.o \ + $(OBJDIR)/cdevTagTable.o \ + $(OBJDIR)/cdevTimeValue.o\ + $(OBJDIR)/SignalManager.o\ + $(OBJDIR)/cdevReactor.o\ + $(OBJDIR)/cdevEventHandler.o\ + $(OBJDIR)/cdevSocketStream.o + +# ****************************************************************************** +# * The BINARIES definition names all of the binary files that should be deleted +# * whenever "make clean" is executed. +# ****************************************************************************** +BINARIES = $(PERMLINKS) $(CDEVLIB)/libcdevClientLite.$(SHARED_EXT) \ + $(CDEVLIB)/libcdevClientLite.a + +ifeq ($(SHOBJ),YES) + TARGETS = $(PERMLINKS) $(CDEVLIB)/libcdevClientLite.$(SHARED_EXT) +else + TARGETS = $(PERMLINKS) $(CDEVLIB)/libcdevClientLite.a +endif + +targets : $(TARGETS) + +links : $(PERMLINKS) + +$(PERMLINKS) : + @cp $^ $@ + +$(CDEVLIB)/libcdevClientLite.a : $(OBJS) + $(LINK.a) $@ $(OBJS) + @$(RANLIB) $@ > /dev/null + +$(CDEVLIB)/libcdevClientLite.$(SHARED_EXT) : $(OBJS) + @$(LINK.so) -o $@ $^ + +ClientInfo.h : ../common/ClientInfo.h +cdevMessage.cc : ../cdevPacket/cdevMessage.cc +cdevMessageBinary.cc : ../cdevPacket/cdevMessageBinary.cc +cdevPacket.cc : ../cdevPacket/cdevPacket.cc +cdevMessage.h : ../cdevPacket/cdevMessage.h +cdevMessageBinary.h : ../cdevPacket/cdevMessageBinary.h +cdevPacket.h : ../cdevPacket/cdevPacket.h +cdevPacketBinary.h : ../cdevPacket/cdevPacketBinary.h +AddressIndex.h : ../common/AddressIndex.h +ServerInterface.cc : ../cdevClient/ServerInterface.cc +ServerInterface.h : ../cdevClient/ServerInterface.h +ServerHandler.cc : ../cdevClient/ServerHandler.cc +ServerHandler.h : ../cdevClient/ServerHandler.h +ErrorReporter.h : ../common/ErrorReporter.h +SocketUtil.h : ../common/SocketUtil.h +SignalManager.cc : ../common/SignalManager.cc +SignalManager.h : ../common/SignalManager.h +fifo.cc : ../common/fifo.cc +fifo.h : ../common/fifo.h +cdevPlatforms.h : ../common/cdevPlatforms.h +clipMagicNumber.h : ../common/clipMagicNumber.h +cdevCommon.h : ../../../src/common/cdevCommon.h +cdevClock.cc : ../../../src/common/cdevClock.cc +cdevClock.h : ../../../src/common/cdevClock.h +cdevTimeValue.cc : ../../../src/common/cdevTimeValue.cc +cdevTimeValue.h : ../../../src/common/cdevTimeValue.h +cdevStrHash.cc : ../../../src/common/cdevStrHash.cc +cdevStrHash.h : ../../../src/common/cdevStrHash.h +cdevIntHash.cc : ../../../src/common/cdevIntHash.cc +cdevIntHash.h : ../../../src/common/cdevIntHash.h +cdevSlist.cc : ../../../src/common/cdevSlist.cc +cdevSlist.h : ../../../src/common/cdevSlist.h +cdevSpec.h : ../../../src/common/cdevSpec.h +cdevErrCode.h : ../../../src/system/cdevErrCode.h +cdevData.cc : ../../../src/cdevIO/cdevData.cc +cdevData.h : ../../../src/cdevIO/cdevData.h +cdevData.i : ../../../src/cdevIO/cdevData.i +cdevDataEntry.cc : ../../../src/cdevIO/cdevDataEntry.cc +cdevDataEntry.h : ../../../src/cdevIO/cdevDataEntry.h +cdevGlobalTagTable.cc : ../../../src/cdevIO/cdevGlobalTagTable.cc +cdevGlobalTagTable.h : ../../../src/cdevIO/cdevGlobalTagTable.h +cdevTagTable.cc : ../../../src/cdevIO/cdevTagTable.cc +cdevTagTable.h : ../../../src/cdevIO/cdevTagTable.h +cdevTypes.h : ../../../src/cdevIO/cdevTypes.h +xdrClass.h : ../../../src/cdevIO/xdrClass.h +cdevAddr.cc : ../cdevReactor/cdevAddr.cc +cdevAddr.h : ../cdevReactor/cdevAddr.h +cdevEventHandler.cc : ../cdevReactor/cdevEventHandler.cc +cdevEventHandler.h : ../cdevReactor/cdevEventHandler.h +cdevHandleSet.cc : ../cdevReactor/cdevHandleSet.cc +cdevHandleSet.h : ../cdevReactor/cdevHandleSet.h +cdevReactor.cc : ../cdevReactor/cdevReactor.cc +cdevReactor.h : ../cdevReactor/cdevReactor.h +cdevSocket.cc : ../cdevReactor/cdevSocket.cc +cdevSocket.h : ../cdevReactor/cdevSocket.h +cdevSocketAcceptor.cc : ../cdevReactor/cdevSocketAcceptor.cc +cdevSocketAcceptor.h : ../cdevReactor/cdevSocketAcceptor.h +cdevSocketConnector.cc : ../cdevReactor/cdevSocketConnector.cc +cdevSocketConnector.h : ../cdevReactor/cdevSocketConnector.h +cdevSocketDatagram.cc : ../cdevReactor/cdevSocketDatagram.cc +cdevSocketDatagram.h : ../cdevReactor/cdevSocketDatagram.h +cdevSocketStream.cc : ../cdevReactor/cdevSocketStream.cc +cdevSocketStream.h : ../cdevReactor/cdevSocketStream.h +cdevStreamNode.cc : ../cdevReactor/cdevStreamNode.cc +cdevStreamNode.h : ../cdevReactor/cdevStreamNode.h +cdevStreamQueue.cc : ../cdevReactor/cdevStreamQueue.cc +cdevStreamQueue.h : ../cdevReactor/cdevStreamQueue.h +cdevTime.cc : ../cdevReactor/cdevTime.cc +cdevTime.h : ../cdevReactor/cdevTime.h +StringHash.h : ../common/StringHash.h diff --git a/extensions/cdevGenericServer/liteClient/Makefile.common b/extensions/cdevGenericServer/liteClient/Makefile.common new file mode 100755 index 0000000..90539ff --- /dev/null +++ b/extensions/cdevGenericServer/liteClient/Makefile.common @@ -0,0 +1,89 @@ +# ****************************************************************************** +# * Makefile.common : This is the community makefile for the cdevGenericServer +# * distribution. It contains the definitions that are common +# * for all Makefiles in this distribution. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# * TARGET : The name of the target platform +# * OS_MAJOR : The major version number of the target OS +# ****************************************************************************** +TARGETDIR = $(TARGET)-$(OS_MAJOR).$(OS_MINOR) +CDEVVERSION = 1.7.2 +CDEVINCLUDES = -I$(CDEV)/include +CDEVLIB = $(CDEV)/lib/$(TARGETDIR) +CDEVBIN = $(CDEV)/bin/$(TARGETDIR) + +BASEDIR = $(CDEV)/extensions/cdevGenericServer +BASEINCLUDES = -I$(BASEDIR)/include +BASELIB = $(BASEDIR)/lib/$(TARGETDIR) +BASEBIN = $(BASEDIR)/bin/$(TARGETDIR) + + + +# ****************************************************************************** +# * Set the CDEV shared object directory to a default location if not specified. +# ****************************************************************************** +ifeq ($(CDEVSHOBJ), ) + CDEVSHOBJ = $(CDEVLIB) +endif + + +# ****************************************************************************** +# * Set the object directory appropriately to the SHOBJ flag (default YES) +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + OBJDIR = .obj/$(TARGETDIR) +else + SHOBJ = YES + OBJDIR = .shobj/$(TARGETDIR) +endif + + +# ****************************************************************************** +# * Rule for compiling archive C++ files. +# ****************************************************************************** +.obj/$(TARGETDIR)/%.o : %.cc + @rm -f $@ + @echo "=> $(CXX) -c $(^F) -o $(@F)" + @mkdir -p .obj/$(TARGETDIR) + @$(COMPILE.cc) + + +# ****************************************************************************** +# * Rule for compiling shared C++ files. +# ****************************************************************************** +.shobj/$(TARGETDIR)/%.o : %.cc + @rm -f $@ + @echo "=> $(CXX) -c $(^F) -o $(@F)" + @mkdir -p .shobj/$(TARGETDIR) + @$(COMPILE.cc.so) + +# ****************************************************************************** +# * Generic rules for makefiles. +# ****************************************************************************** +all: hail targets fairwell + +hail: + @echo + @echo ---------------------------------------------------------------- + @echo Building $(APPNAME) for Target: $(TARGET) + @echo ---------------------------------------------------------------- + +fairwell: + @echo ---------------------------------------------------------------- + @echo Finished Building $(APPNAME) for Target: $(TARGET) + @echo ---------------------------------------------------------------- + @echo + +clean: + @echo "=> Cleaning $(APPNAME) on $(TARGETDIR)" + @rm -rf .o .a core .obj/$(TARGETDIR) .shobj/$(TARGETDIR) *.?.? TC.Cache $(BINARIES) $(TARGETS) ./ptrepository + @echo "<= Done...\n" + +purge: + @echo "=> Purging $(APPNAME)" + @rm -rf .shobj .obj $(BINARIES) $(TARGETS) $(TEMPLINKS) .o .a core *.?.? TC.Cache ./ptrepository + @echo "<= Done...\n" diff --git a/extensions/cdevGenericServer/liteClient/NMakefile.mak b/extensions/cdevGenericServer/liteClient/NMakefile.mak new file mode 100644 index 0000000..55c95ef --- /dev/null +++ b/extensions/cdevGenericServer/liteClient/NMakefile.mak @@ -0,0 +1,8 @@ +.SUFFIXES: .cc .obj + +APPNAME = Light-Weight Generic Client/Server +ARCH = WINNT-4.0 + +include ..\include\makeinclude\Makefile.WINNT-4.0 + +targets : $(TARGETS) diff --git a/extensions/cdevGenericServer/tests/BadMagic/BadMagic.cc b/extensions/cdevGenericServer/tests/BadMagic/BadMagic.cc new file mode 100755 index 0000000..24363e4 --- /dev/null +++ b/extensions/cdevGenericServer/tests/BadMagic/BadMagic.cc @@ -0,0 +1,171 @@ +#include +#include +#include +#include + +int GlobalDone = 0; +cdevReactor GlobalReactor; + +// ***************************************************************************** +// * BadMagicHandler::BadMagicHandler +// * Default constructor for the BadMagicHandler class +// ***************************************************************************** +BadMagicHandler::BadMagicHandler ( void ) + : stream() + { + } + +// ***************************************************************************** +// * open: +// * Established a connection with the host specified by remote_sap +// ***************************************************************************** +int BadMagicHandler::open ( const cdevAddr & addr ) + { + int result = stream.connect (addr); + if (result != -1) + { + if((result = GlobalReactor.registerHandler(this, READ_MASK|WRITE_MASK|EXCEPT_MASK))==-1) + { + handleClose(); + } + } + return result; + } + + +// ***************************************************************************** +// * ~BadMagicHandler: +// * Default destructor for the BadMagicHandler object. +// ***************************************************************************** +BadMagicHandler::~BadMagicHandler (void) + { + GlobalReactor.extractHandler(this); + handleClose(); + } + + +// ***************************************************************************** +// * BadMagicHandler::getHandle +// * Allows the caller to obtain the file identifier of the socket. +// ***************************************************************************** +int BadMagicHandler::getHandle (void) const + { + return stream.getHandle(); + } + + + +// ***************************************************************************** +// * handleClose: +// * Closes the stream. +// ***************************************************************************** +int BadMagicHandler::handleClose (void) + { + stream.close(); + fprintf(stdout, "=> Closing the BadMagic handler\n"); + fflush(stdout); + GlobalDone = 1; + return 0; + } + + +// ***************************************************************************** +// * handleInput : +// * This function is called when data is ready to be read from a connected +// * socket. This function will read the data from the socket, and will then +// * submit the buffer to the ServerInterface class for processing. +// ***************************************************************************** +int BadMagicHandler::handleInput (void) + { + char buf[1000]; + + fprintf(stdout, "=> Receiving unwanted input\n"); + fflush(stdout); + + while(stream.recv(buf, 1000)>0); + + return 0; + } + + +// ***************************************************************************** +// * handleOutput : +// * This function is called when data is ready to be transmitted to a +// * connected socket. This function will read the data from the queue, +// * translate it to XDR, and then transmit it to the client. +// ***************************************************************************** +int BadMagicHandler::handleOutput ( void ) + { + static int count = 0; + + long length = 72; + long packets = 1; + long magic = CLIP_MAGIC_NUMBER; + char * deviceList = "device1"; + cdevMessageBinary msg (1, 12, 0, 100, 200, 22, 14, 1, (char **)&deviceList, (char *)"get funky"); + XDR_Writer writer (2400); + char * msgBuf = NULL; + size_t msgLen = 0; + + msg.streamOut(&msgBuf, &msgLen); + + count++; + if(count==50) magic++; + fflush (stdout); + writer.put(magic); + writer.put(length); + writer.put(packets); + writer.put(msgLen); + writer.put((void *)msgBuf, msgLen); + + fprintf(stdout, "=> I have sent %i bytes...\n", stream.send(writer.buf, 80)); + fflush(stdout); + + if(count>=100) GlobalDone = -1; + return GlobalDone; + } + + +// ***************************************************************************** +// * handleExcept : +// * This function is called when out of band data has been received from +// * the server. It will terminate the connection with the server. +// ***************************************************************************** +int BadMagicHandler::handleExcept ( void ) + { + fprintf(stdout, "=> I have received a terminator from the server\n"); + fflush(stdout); + stream.close(); + GlobalDone = 1; + return -1; + } + + +int main ( int argc, char ** argv) + { + fprintf(stdout, "\n\ +=> **********************************************************************\n\ +=> * This is a test of the cdevGenericServer server-side software. *\n\ +=> * This application will transmit a group of packets to the server *\n\ +=> * and will then transmit a packet with a bad magic number. The *\n\ +=> * should immediately terminate the client connection as soon as the *\n\ +=> * packet with the invalid magic number is received. *\n\ +=> **********************************************************************\n\n"); + + if(argc<3) + { + fprintf(stdout, "\ +=> Insufficient parameters\n\ +=> Format is : %s host port\n\ +=> Terminating\n", argv[0]); + + exit(1); + } + + BadMagicHandler handler; + cdevInetAddr addr(atoi(argv[2]), argv[1]); + handler.open(addr); + while(!GlobalDone) GlobalReactor.handleEvents(); + + return 0; + } diff --git a/extensions/cdevGenericServer/tests/BadMagic/BadMagic.h b/extensions/cdevGenericServer/tests/BadMagic/BadMagic.h new file mode 100755 index 0000000..4bafafd --- /dev/null +++ b/extensions/cdevGenericServer/tests/BadMagic/BadMagic.h @@ -0,0 +1,31 @@ +#ifndef _BAD_MAGIC_H_ +#define _BAD_MAGIC_H_ 1 + +#include "cdevEventHandler.h" +#include "cdevAddr.h" +#include "cdevSocketConnector.h" +#include "cdevReactor.h" +#include "fifo.h" + +// ***************************************************************************** +// * BadMagicHandler: +// * This class provides the mechanisms that will be used to service the +// * requests of a client. +// ***************************************************************************** +class BadMagicHandler : public cdevEventHandler +{ +protected: + cdevSocketConnector stream; + +public: + BadMagicHandler (void); + ~BadMagicHandler (void); + virtual int open (const cdevAddr &addr); + virtual int getHandle (void) const; + virtual int handleClose (void); + virtual int handleInput (void); + virtual int handleOutput (void); + virtual int handleExcept (void); +}; + +#endif /* _BAD_MAGIC_H_ */ diff --git a/extensions/cdevGenericServer/tests/BadMagic/Makefile b/extensions/cdevGenericServer/tests/BadMagic/Makefile new file mode 100755 index 0000000..e553d68 --- /dev/null +++ b/extensions/cdevGenericServer/tests/BadMagic/Makefile @@ -0,0 +1,18 @@ +ARCH = OS +SHOBJ = YES + +include ../../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Server Bad Magic Number Test" +OUTPUTDIR = $(BASEBIN) +CXXINCLUDES = -I./ +LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + +TARGETS = $(OUTPUTDIR)/BadMagic +BINARIES = $(TARGETS) + +targets : $(TARGETS) + +$(OUTPUTDIR)/BadMagic : $(OBJDIR)/BadMagic.o + $(LINK.cc) $^ $(LIBS) -o $@ + diff --git a/extensions/cdevGenericServer/tests/BadMagic/NMakefile.mak b/extensions/cdevGenericServer/tests/BadMagic/NMakefile.mak new file mode 100755 index 0000000..16da979 --- /dev/null +++ b/extensions/cdevGenericServer/tests/BadMagic/NMakefile.mak @@ -0,0 +1,20 @@ +.SUFFIXES: .cc .obj + +APPNAME = Server Bad Magic Number Test +ARCH = WINNT-4.0 +SHOBJ = YES + +BINARIES = $(BASEBIN)\BadMagic.exe + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +CXXINCLUDES = /I .\\ + +targets : $(BINARIES) + +$(BASEBIN)\BadMagic.exe : .exec\$(TARGETDIR)\BadMagic.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... diff --git a/extensions/cdevGenericServer/tests/EarlyDeath/EarlyDeath.cc b/extensions/cdevGenericServer/tests/EarlyDeath/EarlyDeath.cc new file mode 100755 index 0000000..ac7a158 --- /dev/null +++ b/extensions/cdevGenericServer/tests/EarlyDeath/EarlyDeath.cc @@ -0,0 +1,173 @@ +#include +#include +#include +#include + +int GlobalDone = 0; +cdevReactor GlobalReactor; + +// ***************************************************************************** +// * EarlyDeathHandler::EarlyDeathHandler +// * Default constructor for the EarlyDeathHandler class +// ***************************************************************************** +EarlyDeathHandler::EarlyDeathHandler ( void ) + : stream() + { + } + +// ***************************************************************************** +// * open: +// * Established a connection with the host specified by remote_sap +// ***************************************************************************** +int EarlyDeathHandler::open ( const cdevAddr & addr ) + { + int result = stream.connect (addr); + if (result != -1) + { + if((result = GlobalReactor.registerHandler(this, READ_MASK|WRITE_MASK|EXCEPT_MASK))==-1) + { + handleClose(); + } + } + return result; + } + + +// ***************************************************************************** +// * ~EarlyDeathHandler: +// * Default destructor for the EarlyDeathHandler object. +// ***************************************************************************** +EarlyDeathHandler::~EarlyDeathHandler (void) + { + GlobalReactor.extractHandler(this); + handleClose(); + } + + +// ***************************************************************************** +// * EarlyDeathHandler::getHandle +// * Allows the caller to obtain the file identifier of the socket. +// ***************************************************************************** +int EarlyDeathHandler::getHandle (void) const + { + return stream.getHandle(); + } + + + +// ***************************************************************************** +// * handleClose: +// * Closes the stream. +// ***************************************************************************** +int EarlyDeathHandler::handleClose (void) + { + stream.close(); + fprintf(stdout, "=> Closing the EarlyDeath handler\n"); + fflush(stdout); + GlobalDone = 1; + return 0; + } + + +// ***************************************************************************** +// * handleInput : +// * This function is called when data is ready to be read from a connected +// * socket. This function will read the data from the socket, and will then +// * submit the buffer to the ServerInterface class for processing. +// ***************************************************************************** +int EarlyDeathHandler::handleInput (void) + { + char buf[1000]; + + fprintf(stdout, "=> Receiving unwanted input\n"); + fflush(stdout); + + while(stream.recv(buf, 1000)>0); + + return 0; + } + + +// ***************************************************************************** +// * handleOutput : +// * This function is called when data is ready to be transmitted to a +// * connected socket. This function will read the data from the queue, +// * translate it to XDR, and then transmit it to the client. +// ***************************************************************************** +int EarlyDeathHandler::handleOutput ( void ) + { + static int count = 0; + + long length = 72; + long packets = 1; + long magic = CLIP_MAGIC_NUMBER; + char * deviceList = "device1"; + cdevMessageBinary msg (1, 12, 0, 100, 200, 22, 14, 1, (char **)&deviceList, (char *)"get funky"); + XDR_Writer writer (2400); + char * msgBuf = NULL; + size_t msgLen = 0; + + msg.streamOut(&msgBuf, &msgLen); + + fflush (stdout); + writer.put(magic); + writer.put(length); + writer.put(packets); + writer.put(msgLen); + writer.put((void *)msgBuf, msgLen); + + if(++count < 100) fprintf(stdout, "=> I have sent %i bytes...\n", stream.send(writer.buf, 80)); + else fprintf(stdout, "=> I have sent %i bytes and now I'm quitting\n", stream.send(writer.buf, 40)); + fflush(stdout); + + + if(count>=100) GlobalDone = -1; + return GlobalDone; + } + + +// ***************************************************************************** +// * handleExcept : +// * This function is called when out of band data has been received from +// * the server. It will terminate the connection with the server. +// ***************************************************************************** +int EarlyDeathHandler::handleExcept ( void ) + { + fprintf(stdout, "=> I have received a terminator from the server\n"); + fflush(stdout); + stream.close(); + GlobalDone = 1; + return -1; + } + + +int main ( int argc, char ** argv) + { + fprintf(stdout, "\n\ +=> **********************************************************************\n\ +=> * This is a test of the cdevGenericServer server-side software. *\n\ +=> * This application will transmit a partial packet to the server *\n\ +=> * and will then immediately terminate. The developer should inspect *\n\ +=> * the behavior of the server and ensure that it responds properly. *\n\ +=> * *\n\ +=> * The correct response to this sort of event would be to terminate *\n\ +=> * the connection and remove the client from the server. *\n\ +=> **********************************************************************\n\n"); + + if(argc<3) + { + fprintf(stdout, "\ +=> Insufficient parameters\n\ +=> Format is : %s host port\n\ +=> Terminating\n", argv[0]); + + exit(1); + } + + EarlyDeathHandler handler; + cdevInetAddr addr(atoi(argv[2]), argv[1]); + handler.open(addr); + while(!GlobalDone) GlobalReactor.handleEvents(); + + return 0; + } diff --git a/extensions/cdevGenericServer/tests/EarlyDeath/EarlyDeath.h b/extensions/cdevGenericServer/tests/EarlyDeath/EarlyDeath.h new file mode 100755 index 0000000..3d8fbc9 --- /dev/null +++ b/extensions/cdevGenericServer/tests/EarlyDeath/EarlyDeath.h @@ -0,0 +1,31 @@ +#ifndef _EARLY_DEATH_H_ +#define _EARLY_DEATH_H_ 1 + +#include "cdevEventHandler.h" +#include "cdevAddr.h" +#include "cdevSocketConnector.h" +#include "cdevReactor.h" +#include "fifo.h" + +// ***************************************************************************** +// * EarlyDeathHandler: +// * This class provides the mechanisms that will be used to service the +// * requests of a client. +// ***************************************************************************** +class EarlyDeathHandler : public cdevEventHandler +{ +protected: + cdevSocketConnector stream; + +public: + EarlyDeathHandler (void); + ~EarlyDeathHandler (void); + virtual int open (const cdevAddr &addr); + virtual int getHandle (void) const; + virtual int handleClose (void); + virtual int handleInput (void); + virtual int handleOutput (void); + virtual int handleExcept (void); +}; + +#endif /* _EARLY_DEATH_H_ */ diff --git a/extensions/cdevGenericServer/tests/EarlyDeath/Makefile b/extensions/cdevGenericServer/tests/EarlyDeath/Makefile new file mode 100755 index 0000000..5f7f8a4 --- /dev/null +++ b/extensions/cdevGenericServer/tests/EarlyDeath/Makefile @@ -0,0 +1,18 @@ +ARCH = OS +SHOBJ = YES + +include ../../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Server Early Death Test" +OUTPUTDIR = $(BASEBIN) +CXXINCLUDES = -I./ +LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + +TARGETS = $(OUTPUTDIR)/EarlyDeath +BINARIES = $(TARGETS) + +targets : $(TARGETS) + +$(OUTPUTDIR)/EarlyDeath : $(OBJDIR)/EarlyDeath.o + $(LINK.cc) $^ $(LIBS) -o $@ + diff --git a/extensions/cdevGenericServer/tests/EarlyDeath/NMakefile.mak b/extensions/cdevGenericServer/tests/EarlyDeath/NMakefile.mak new file mode 100755 index 0000000..f6a91bb --- /dev/null +++ b/extensions/cdevGenericServer/tests/EarlyDeath/NMakefile.mak @@ -0,0 +1,20 @@ +.SUFFIXES: .cc .obj + +APPNAME = Server Early Death Test +ARCH = WINNT-4.0 +SHOBJ = YES + +BINARIES = $(BASEBIN)\EarlyDeath.exe + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +CXXINCLUDES = /I .\\ + +targets : $(BINARIES) + +$(BASEBIN)\EarlyDeath.exe : .exec\$(TARGETDIR)\EarlyDeath.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... diff --git a/extensions/cdevGenericServer/tests/GetServers/GetServers.cc b/extensions/cdevGenericServer/tests/GetServers/GetServers.cc new file mode 100644 index 0000000..774b765 --- /dev/null +++ b/extensions/cdevGenericServer/tests/GetServers/GetServers.cc @@ -0,0 +1,15 @@ +#include +#include +#include +#include +#include + +int main( ) +{ +cdevData data; +cdevDevice & device = cdevDevice::attachRef("device1"); +device.send("get servers", NULL, data); +data.asciiDump(); + +return 0; +} diff --git a/extensions/cdevGenericServer/tests/GetServers/GetServers.ddl b/extensions/cdevGenericServer/tests/GetServers/GetServers.ddl new file mode 100644 index 0000000..7312cae --- /dev/null +++ b/extensions/cdevGenericServer/tests/GetServers/GetServers.ddl @@ -0,0 +1,28 @@ +service Test + { + tags {server} + } + +class Tests + { + verbs {get, set} + attributes + { + default Test; + clientID Test; + servers Test; + connections Test; + attrib Test {server=TestServer1}; + } + messages + { + shutdown Test; + } + } + + +Tests : + device1, + device2, + device3 +; diff --git a/extensions/cdevGenericServer/tests/GetServers/Makefile b/extensions/cdevGenericServer/tests/GetServers/Makefile new file mode 100644 index 0000000..82b730a --- /dev/null +++ b/extensions/cdevGenericServer/tests/GetServers/Makefile @@ -0,0 +1,29 @@ +ARCH = OS +SHOBJ = YES + +include ../../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Get Servers Test" +CXXINCLUDES = -I./ +SO_SRCS = GetServers.cc +SO_LIBS = -L$(CDEVLIB) -lcdevGenericServer $(NETLIBS) + +# ****************************************************************************** +# * The BINARIES definition names all of the binary files that should be deleted +# * whenever "make clean" is executed. +# ****************************************************************************** +BINARIES = $(BASEBIN)/GetServers + +ifeq ($(SHOBJ), YES) + LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + TARGETS = $(BASEBIN)/GetServers +else + LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + TARGETS = $(BASEBIN)/GetServers +endif + +targets : $(TARGETS) + +$(BASEBIN)/GetServers : $(OBJDIR)/GetServers.o + $(LINK.cc) $^ -o $@ $(LIBS) + diff --git a/extensions/cdevGenericServer/tests/GetServers/NMakefile.mak b/extensions/cdevGenericServer/tests/GetServers/NMakefile.mak new file mode 100755 index 0000000..3f60910 --- /dev/null +++ b/extensions/cdevGenericServer/tests/GetServers/NMakefile.mak @@ -0,0 +1,20 @@ +.SUFFIXES: .cc .obj + +APPNAME = Get Servers Test +ARCH = WINNT-4.0 +SHOBJ = YES + +BINARIES = $(BASEBIN)\GetServers.exe + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +CXXINCLUDES = /I .\\ + +targets : $(BINARIES) + +$(BASEBIN)\GetServers.exe : .exec\$(TARGETDIR)\GetServers.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... diff --git a/extensions/cdevGenericServer/tests/Makefile b/extensions/cdevGenericServer/tests/Makefile new file mode 100755 index 0000000..ded2c69 --- /dev/null +++ b/extensions/cdevGenericServer/tests/Makefile @@ -0,0 +1,15 @@ +BASEDIR = $(shell pwd) +DIRS = $(BASEDIR)/TransmissionTest \ + $(BASEDIR)/Performance \ + $(BASEDIR)/EarlyDeath \ + $(BASEDIR)/BadMagic \ + $(BASEDIR)/MonitorTest \ + $(BASEDIR)/GetServers \ + $(BASEDIR)/SyncSet + +all commit clean purge: + @for dir in $(DIRS); \ + do \ + $(MAKE) -C $$dir $@; \ + done + diff --git a/extensions/cdevGenericServer/tests/MonitorTest/DefaultServerTest.cc b/extensions/cdevGenericServer/tests/MonitorTest/DefaultServerTest.cc new file mode 100644 index 0000000..078ab4a --- /dev/null +++ b/extensions/cdevGenericServer/tests/MonitorTest/DefaultServerTest.cc @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include + +int main ( ) + { + fprintf(stdout, "\n\ +=> **********************************************************************\n\ +=> * This is the program is used to test what happens when a default *\n\ +=> * server is set that does not exist... Does the message go to the *\n\ +=> * old default server - or does it generate an error. *\n\ +=> **********************************************************************\n\n"); + fflush(stdout); + cdevRequestObject * setDefReq = cdevRequestObject::attachPtr("device0", "set default"); + cdevRequestObject * req = cdevRequestObject::attachPtr("device0", "set attrib0"); + cdevData data; + int val = 0; + + fprintf(stdout, "\n\ +=> **********************************************************************\n\ +=> * Commencing communications with MonitorTestServer (100 sends). *\n\ +=> **********************************************************************\n\n"); + fflush(stdout); + data.insert("value", "MonitorTestServer"); + data.asciiDump(); + setDefReq->send(data, NULL); + + for(val=0; val<100; val++) + { + data.insert("value", val); + req->send(data, NULL); + } + + fprintf(stdout, "\n\ +=> **********************************************************************\n\ +=> * Now setting the default server to MonitorTestServer1... This *\n\ +=> * server should not exist. Performing 100 sends. *\n\ +=> **********************************************************************\n\n"); + fflush(stdout); + data.insert("value", "MonitorTestServer1"); + data.asciiDump(); + setDefReq->send(data, NULL); + + for(val=0; val<100; val++) + { + data.insert("value", val); + req->send(data, NULL); + } + + fprintf(stdout, "\n\ +=> **********************************************************************\n\ +=> * Switching back to the other default server. *\n\ +=> **********************************************************************\n\n"); + fflush(stdout); + data.insert("value", "MonitorTestServer"); + data.asciiDump(); + setDefReq->send(data, NULL); + + for(val=0; val<100; val++) + { + data.insert("value", val); + req->send(data, NULL); + } + + return 0; + } diff --git a/extensions/cdevGenericServer/tests/MonitorTest/Makefile b/extensions/cdevGenericServer/tests/MonitorTest/Makefile new file mode 100644 index 0000000..ffabfdf --- /dev/null +++ b/extensions/cdevGenericServer/tests/MonitorTest/Makefile @@ -0,0 +1,47 @@ +ARCH = OS +SHOBJ = YES + +include ../../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Client/Server Monitor Test" +CXXINCLUDES = -I./ +SERVER_LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + +ifeq ($(SHOBJ), YES) + LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + TARGETS = $(BASELIB)/MonitorTestService.so $(BASEBIN)/MonitorTestServer $(BASEBIN)/MonitorTest $(BASEBIN)/MonitorReader $(BASEBIN)/MonitorOffTest $(BASEBIN)/MonitorWriter $(BASEBIN)/DefaultServerTest +else + LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + TARGETS = $(BASELIB)/libMonitorTestService.a $(BASEBIN)/MonitorTestServer $(BASEBIN)/MonitorTest $(BASEBIN)/MonitorReader $(BASEBIN)/MonitorOffTest $(BASEBIN)/MonitorWriter $(BASEBIN)/DefaultServerTest +endif + + +targets : $(TARGETS) + +$(BASEBIN)/MonitorTestServer : $(OBJDIR)/MonitorTestServer.o $(OBJDIR)/MonitorTestAttrib.o + $(LINK.cc) $^ $(SERVER_LIBS) -o $@ + +$(BASELIB)/MonitorTestService.so : $(OBJDIR)/MonitorTestService.o + $(LINK.so) -o $@ $^ -L$(CDEVLIB) -lcdevGenericServer $(OSLIBS) + @mkdir -p $(CDEVSHOBJ)/$(CDEVVERSION) + @cp $@ $(CDEVSHOBJ)/$(CDEVVERSION)/$(@F) + +$(BASELIB)/libMonitorTestService.a : $(OBJDIR)/MonitorTestService.o + $(LINK.a) $@ $^ + @$(RANLIB) $@ > /dev/null + +$(BASEBIN)/MonitorTest : $(OBJDIR)/MonitorTest.o + $(LINK.cc) $^ -o $@ $(LIBS) + +$(BASEBIN)/DefaultServerTest : $(OBJDIR)/DefaultServerTest.o + $(LINK.cc) $^ -o $@ $(LIBS) + +$(BASEBIN)/MonitorReader : $(OBJDIR)/MonitorReader.o + $(LINK.cc) $^ -o $@ $(LIBS) + +$(BASEBIN)/MonitorOffTest : $(OBJDIR)/MonitorOffTest.o + $(LINK.cc) $^ -o $@ $(LIBS) + +$(BASEBIN)/MonitorWriter : $(OBJDIR)/MonitorWriter.o + $(LINK.cc) $^ -o $@ $(LIBS) + diff --git a/extensions/cdevGenericServer/tests/MonitorTest/MonitorOffTest.cc b/extensions/cdevGenericServer/tests/MonitorTest/MonitorOffTest.cc new file mode 100644 index 0000000..d8fca71 --- /dev/null +++ b/extensions/cdevGenericServer/tests/MonitorTest/MonitorOffTest.cc @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include + +int callbackCount = 0; + +void callback ( int status, void * /*arg*/, cdevRequestObject & req, cdevData & /*data*/ ) + { + if(status==CDEV_SUCCESS) + { + callbackCount++; + if(callbackCount%1==0) fprintf(stdout, "Received callback %i - %s:%s \n", callbackCount, req.device().name(), req.message()); + } + else if(status==CDEV_DISCONNECTED) fprintf(stdout, "The monitor has become disconnected on %s:%s\n", req.device().name(), req.message()); + else if(status==CDEV_RECONNECTED) fprintf(stdout, "The monitor has become reconnected on %s:%s\n", req.device().name(), req.message()); + else fprintf(stdout, "Status code %i was received on %s:%s\n", status, req.device().name(), req.message()); + fflush(stdout); + } + +const int DEVICE_COUNT = 9; +const int MESSAGE_COUNT = 9; + +int main ( ) + { + cdevRequestObject & monOnReq = cdevRequestObject::attachRef("ExpSrv", "monitorOn attrib1"); + cdevRequestObject & monOffReq = cdevRequestObject::attachRef("ExpSrv", "monitorOff attrib1"); + cdevCallback cb (callback, NULL); + monOnReq.sendCallback(NULL, cb); + while(callbackCount<10) + { + cdevSystem::defaultSystem().pend(1.0); + } + monOffReq.sendCallback(NULL, cb); + fprintf(stdout, "Kill me when you're tired of looking at this...\n"); + fflush(stdout); + while(1) cdevSystem::defaultSystem().pend(1.0); + + return 0; + } diff --git a/extensions/cdevGenericServer/tests/MonitorTest/MonitorReader.cc b/extensions/cdevGenericServer/tests/MonitorTest/MonitorReader.cc new file mode 100644 index 0000000..4b4dec6 --- /dev/null +++ b/extensions/cdevGenericServer/tests/MonitorTest/MonitorReader.cc @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include + +int callbackCount = 0; + +void callback ( int status, void * /*arg*/, cdevRequestObject & req, cdevData & /*data*/ ) + { + if(status==CDEV_SUCCESS) + { + callbackCount++; + if(callbackCount%1000==0) fprintf(stdout, "Received callback %i - %s:%s \n", callbackCount, req.device().name(), req.message()); + } + else if(status==CDEV_DISCONNECTED) fprintf(stdout, "The monitor has become disconnected on %s:%s\n", req.device().name(), req.message()); + else if(status==CDEV_RECONNECTED) fprintf(stdout, "The monitor has become reconnected on %s:%s\n", req.device().name(), req.message()); + else fprintf(stdout, "Status code %i was received on %s:%s\n", req.device().name(), req.message()); + fflush(stdout); + } + +const int DEVICE_COUNT = 9; +const int MESSAGE_COUNT = 9; + +int main ( ) + { + fprintf(stdout, "\n\ +=> **********************************************************************\n\ +=> * This is is the receiving part of a two part application. This *\n\ +=> * program willl post monitors and will listen for changes that are *\n\ +=> * generated by the other application - MonitorWriter *\n\ +=> **********************************************************************\n\n"); + cdevDevice * deviceList[DEVICE_COUNT]; + cdevCallback cb(callback, NULL); + cdevData data; + char msg[255]; + int deviceCnt; + int msgCnt; + + cdevRequestObject & req = cdevRequestObject::attachRef("device0", "set default"); + data.insert("value", "MonitorTestServer"); + req.send(data, NULL); + + for(deviceCnt=0; deviceCntsendCallback(msg, NULL, cb); + } + } + cdevSystem::defaultSystem().setThreshold(CDEV_SEVERITY_INFO); + while(1) cdevSystem::defaultSystem().pend(5.0); + + return 0; + } diff --git a/extensions/cdevGenericServer/tests/MonitorTest/MonitorTest.cc b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTest.cc new file mode 100644 index 0000000..371fb61 --- /dev/null +++ b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTest.cc @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include + +int callbackCount = 0; + +void callback ( int status, void * arg, cdevRequestObject & req, cdevData & data ) + { + if(status==CDEV_SUCCESS) callbackCount++; + } + +const int DEVICE_COUNT = 9; +const int MESSAGE_COUNT = 9; + +int main ( int argc, char ** argv ) + { + fprintf(stdout, "\n\ +=> **********************************************************************\n\ +=> * This is program will post a collection of monitors to the monitor *\n\ +=> * server and will then post changes to the attributes. The program *\n\ +=> * will wait for results to be returned. *\n\ +=> **********************************************************************\n\n"); + fflush(stdout); + cdevDevice * deviceList[DEVICE_COUNT]; + cdevRequestObject * reqList[DEVICE_COUNT*MESSAGE_COUNT]; + cdevCallback cb(callback, NULL); + cdevData data; + float values[DEVICE_COUNT*MESSAGE_COUNT]; + char msg[255]; + int deviceCnt; + int msgCnt; + int repeatCount = (argc>1)?atoi(argv[1]):5; + + // ********************************************************************* + // * First get all of the values from the devices and install monitors. + // ********************************************************************* + for(deviceCnt=0; deviceCntsend(msg, NULL, data)==CDEV_SUCCESS) + { + data.get("value", &values[deviceCnt*MESSAGE_COUNT+msgCnt]); + } + else { + values[deviceCnt*MESSAGE_COUNT+msgCnt] = 0; + fprintf(stdout, "ERROR : device %s : %s failed\n", deviceList[deviceCnt]->name(), msg); + } + sprintf(msg, "monitorOn attrib%i", msgCnt); + deviceList[deviceCnt]->sendCallback(msg, NULL, cb); + callbackCount--; + + sprintf(msg, "set attrib%i", msgCnt); + reqList[deviceCnt*MESSAGE_COUNT+msgCnt] = deviceList[deviceCnt]->getRequestObject(msg); + } + } + + fprintf(stdout, "=> Sending %i changes to %i monitors\n", repeatCount, DEVICE_COUNT*MESSAGE_COUNT); + + for(int i = 0; isendNoBlock(data, NULL); + } + cdevSystem::defaultSystem().pend(); + fprintf(stdout, "%i Change Requests Transmitted\n", (i+1)*DEVICE_COUNT*MESSAGE_COUNT); + } + + while(callbackCount %i Monitors received so far...\n", callbackCount); + } + fprintf(stdout, "=> %i Monitors have been fired\n", callbackCount); + + // ********************************************************************* + // * Finally, remove all monitors. + // ********************************************************************* + for(deviceCnt=0; deviceCntsendCallback(msg, NULL, cb); + } + } + cdevSystem::defaultSystem().pend(); + + return 0; + } diff --git a/extensions/cdevGenericServer/tests/MonitorTest/MonitorTest.ddl b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTest.ddl new file mode 100644 index 0000000..4f6cadf --- /dev/null +++ b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTest.ddl @@ -0,0 +1,34 @@ +service Gateway + { + tags {server} + } + +class MonitorTests + { + verbs {get, set, monitorOn, monitorOff} + attributes + { + default Gateway; + servers Gateway; + attrib0 Gateway {server=Gateway1}; + attrib1 Gateway {server=Gateway1}; + attrib2 Gateway {server=Gateway1}; + attrib3 Gateway {server=Gateway1}; + attrib4 Gateway {server=Gateway1}; + attrib5 Gateway {server=Gateway1}; + attrib6 Gateway {server=Gateway1}; + attrib7 Gateway {server=Gateway1}; + attrib8 Gateway {server=Gateway1}; + attrib9 Gateway {server=Gateway1}; + } + messages + { + disconnect Gateway; + } + } + + +MonitorTests : + device0, device1, device2, device3, device4, + device5, device6, device7, device8, device9 +; diff --git a/extensions/cdevGenericServer/tests/MonitorTest/MonitorTest1.cc b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTest1.cc new file mode 100644 index 0000000..5e478a7 --- /dev/null +++ b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTest1.cc @@ -0,0 +1,67 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +void callback ( int status, void * arg, cdevRequestObject & req, cdevData & data ) + { + } + +const int DEVICE_COUNT = 9; +const int MESSAGE_COUNT = 9; + +int main ( int argc, char ** argv ) + { + cdevDevice * deviceList[DEVICE_COUNT]; + cdevRequestObject * reqList[DEVICE_COUNT*MESSAGE_COUNT]; + cdevCallback cb(callback, NULL); + cdevData data; + float values[DEVICE_COUNT][MESSAGE_COUNT]; + char msg[255]; + int deviceCnt; + int msgCnt; + + // ********************************************************************* + // * First get all of the values from the devices and install monitors. + // ********************************************************************* + for(deviceCnt=0; deviceCntsend(msg, NULL, data)==CDEV_SUCCESS) + { + data->get("value", &values[deviceCnt][msgCnt]); + } + else values[deviceCnt][msgCnt] = 0; + + sprintf(msg, "monitorOn attrib%i", msgCnt); + deviceList[deviceCnt]->sendCallback(msg, cb, NULL); + + sprintf(msg, "set attrib%i", msgCnt); + reqList[deviceCnt*MESSAGE_COUNT+msgCnt] = deviceList[deviceCount]->getRequestObject(msg); + } + } + + // ********************************************************************* + // * Finally, remove all monitors. + // ********************************************************************* + for(deviceCnt=0; deviceCntsendCallback(msg, cb, NULL); + } + } + cdevSystem::defaultSystem().pend(); + } diff --git a/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestAttrib.cc b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestAttrib.cc new file mode 100644 index 0000000..a556711 --- /dev/null +++ b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestAttrib.cc @@ -0,0 +1,445 @@ +#include + +static int VALUE_TAG_ID = -1; +static int STATUS_TAG_ID = -1; +static int SEVERITY_TAG_ID = -1; +static int UNITS_TAG_ID = -1; +static int ALARMHIGH_TAG_ID = -1; +static int ALARMLOW_TAG_ID = -1; +static int WARNINGHIGH_TAG_ID = -1; +static int WARNINGLOW_TAG_ID = -1; +static int CONTROLHIGH_TAG_ID = -1; +static int CONTROLLOW_TAG_ID = -1; + +#define VALUE_TAG ((VALUE_TAG_ID<0 && cdevData::tagC2I("value", &VALUE_TAG_ID)!=CDEV_SUCCESS)?-1:VALUE_TAG_ID) +#define STATUS_TAG ((STATUS_TAG_ID<0 && cdevData::tagC2I("status", &STATUS_TAG_ID)!=CDEV_SUCCESS)?-1:STATUS_TAG_ID) +#define SEVERITY_TAG ((SEVERITY_TAG_ID<0 && cdevData::tagC2I("severity", &SEVERITY_TAG_ID)!=CDEV_SUCCESS)?-1:SEVERITY_TAG_ID) +#define UNITS_TAG ((UNITS_TAG_ID<0 && cdevData::tagC2I("units", &UNITS_TAG_ID)!=CDEV_SUCCESS)?-1:UNITS_TAG_ID) +#define ALARMHIGH_TAG ((ALARMHIGH_TAG_ID<0 && cdevData::tagC2I("alarmHigh", &ALARMHIGH_TAG_ID)!=CDEV_SUCCESS)?-1:ALARMHIGH_TAG_ID) +#define ALARMLOW_TAG ((ALARMLOW_TAG_ID<0 && cdevData::tagC2I("alarmLow", &ALARMLOW_TAG_ID)!=CDEV_SUCCESS)?-1:ALARMLOW_TAG_ID) +#define WARNINGHIGH_TAG ((WARNINGHIGH_TAG_ID<0 && cdevData::tagC2I("warningHigh", &WARNINGHIGH_TAG_ID)!=CDEV_SUCCESS)?-1:WARNINGHIGH_TAG_ID) +#define WARNINGLOW_TAG ((WARNINGLOW_TAG_ID<0 && cdevData::tagC2I("warningLow", &WARNINGLOW_TAG_ID)!=CDEV_SUCCESS)?-1:WARNINGLOW_TAG_ID) +#define CONTROLHIGH_TAG ((CONTROLHIGH_TAG_ID<0 && cdevData::tagC2I("controlHigh", &CONTROLHIGH_TAG_ID)!=CDEV_SUCCESS)?-1:CONTROLHIGH_TAG_ID) +#define CONTROLLOW_TAG ((CONTROLLOW_TAG_ID<0 && cdevData::tagC2I("controlLow", &CONTROLLOW_TAG_ID)!=CDEV_SUCCESS)?-1:CONTROLLOW_TAG_ID) + +// ***************************************************************************** +// * MonitorTestAttrib::MonitorTestAttrib : +// * This is the constructor for the MonitorTestAttrib class. It initializes the +// * internal mechanisms to 0. +// ***************************************************************************** +MonitorTestAttrib::MonitorTestAttrib ( char * Device, char * Attrib ) + : device(strdup(Device)), + attrib(strdup(Attrib)), + monitors(NULL), + value(0.0), + alarmHigh(0.0), + alarmLow(0.0), + warningHigh(0.0), + warningLow(0.0), + controlHigh(0.0), + controlLow(0.0) + { + *severity = 0; + *units = 0; + strcpy(status, "NORMAL"); + } + + +// ***************************************************************************** +// * MonitorTestAttrib::~MonitorTestAttrib : +// * This is the destructor for the MonitorTestAttrib class. It must free the +// * memory associated with the device and attribute names. +// ***************************************************************************** +MonitorTestAttrib::~MonitorTestAttrib ( void ) + { + delete device; + delete attrib; + } + +// ***************************************************************************** +// * MonitorTestAttrib::setFromData : +// * This method will populate the MonitorTestAttrib object with the data contained in +// * the cdevData object. +// ***************************************************************************** +int MonitorTestAttrib::setFromData ( cdevData * data ) + { + double val; + int result; + if(data!=NULL) + { + result = CDEV_SUCCESS; + data->get(UNITS_TAG, units, 255); + if(data->get(CONTROLLOW_TAG, &val)==CDEV_SUCCESS) setControlLow(val); + if(data->get(CONTROLHIGH_TAG, &val)==CDEV_SUCCESS) setControlHigh(val); + if(data->get(ALARMLOW_TAG, &val)==CDEV_SUCCESS) setAlarmLow(val); + if(data->get(ALARMHIGH_TAG, &val)==CDEV_SUCCESS) setAlarmHigh(val); + if(data->get(WARNINGLOW_TAG, &val)==CDEV_SUCCESS) setWarningLow(val); + if(data->get(WARNINGHIGH_TAG, &val)==CDEV_SUCCESS) setWarningHigh(val); + if(data->get(VALUE_TAG, &val)==CDEV_SUCCESS) + { + result=setValue(val); + } + } + else result = CDEV_ERROR; + checkAlarms(); + return result; + } + + +// ***************************************************************************** +// * MonitorTestAttrib::getToData : +// * This method will populate the MonitorTestAttrib object with the data contained in +// * the cdevData object. +// ***************************************************************************** +void MonitorTestAttrib::getToData ( cdevData * data, cdevData * context ) + { + if(data!=NULL) + { + data->remove(); + if(context!=NULL) + { + if(context->getType(VALUE_TAG)!=CDEV_INVALID) data->insert(VALUE_TAG, getValue()); + if(context->getType(STATUS_TAG)!=CDEV_INVALID) data->insert(STATUS_TAG, getStatus()); + if(context->getType(SEVERITY_TAG)!=CDEV_INVALID) data->insert(SEVERITY_TAG, getSeverity()); + if(context->getType(UNITS_TAG)!=CDEV_INVALID) data->insert(UNITS_TAG, getUnits()); + if(context->getType(CONTROLLOW_TAG)!=CDEV_INVALID) data->insert(CONTROLLOW_TAG, getControlLow()); + if(context->getType(CONTROLHIGH_TAG)!=CDEV_INVALID) data->insert(CONTROLHIGH_TAG, getControlHigh()); + if(context->getType(ALARMLOW_TAG)!=CDEV_INVALID) data->insert(ALARMLOW_TAG, getAlarmLow()); + if(context->getType(ALARMHIGH_TAG)!=CDEV_INVALID) data->insert(ALARMHIGH_TAG, getAlarmHigh()); + if(context->getType(WARNINGLOW_TAG)!=CDEV_INVALID) data->insert(WARNINGLOW_TAG, getWarningLow()); + if(context->getType(WARNINGHIGH_TAG)!=CDEV_INVALID) data->insert(WARNINGHIGH_TAG, getWarningHigh()); + } + else + { + data->insert(VALUE_TAG, getValue()); + data->insert(STATUS_TAG, getStatus()); + data->insert(SEVERITY_TAG, getSeverity()); + } + } + } + + +// ***************************************************************************** +// * MonitorTestAttrib::getAllToData : +// * This method will populate the MonitorTestAttrib object with the data contained in +// * the cdevData object. +// ***************************************************************************** +void MonitorTestAttrib::getAllToData ( cdevData * data ) + { + if(data!=NULL) + { + data->remove(); + data->insert(VALUE_TAG, getValue()); + data->insert(STATUS_TAG, getStatus()); + data->insert(SEVERITY_TAG, getSeverity()); + data->insert(UNITS_TAG, getUnits()); + data->insert(CONTROLLOW_TAG, getControlLow()); + data->insert(CONTROLHIGH_TAG, getControlHigh()); + data->insert(ALARMLOW_TAG, getAlarmLow()); + data->insert(ALARMHIGH_TAG, getAlarmHigh()); + data->insert(WARNINGLOW_TAG, getWarningLow()); + data->insert(WARNINGHIGH_TAG, getWarningHigh()); + } + } + +// ***************************************************************************** +// * MonitorTestAttrib::setValue : +// * This method allows the caller to set the value of the MonitorTestAttrib. +// * This call will fail if the specified value is outside of the legal +// * range. +// ***************************************************************************** +int MonitorTestAttrib::setValue ( double Value ) + { + resultCode = CDEV_SUCCESS; + + if(controlHigh>controlLow && + (ValuecontrolHigh)) + { + resultCode = CDEV_OUTOFRANGE; + } + else if(value != Value) + { + value = Value; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(VALUE_TAG, &data); + } + } + return resultCode; + } + +// ***************************************************************************** +// * MonitorTestAttrib::setStatus : +// * This method allows the caller to set the status of the device. +// ***************************************************************************** +int MonitorTestAttrib::setStatus ( char * Status ) + { + if(strcmp(status, Status)) + { + strncpy(status, Status, 255); + status[254] = 0; + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(STATUS_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * MonitorTestAttrib::setSeverity : +// * This method allows the caller to set the severity flag for the device. +// ***************************************************************************** +int MonitorTestAttrib::setSeverity ( char * Severity ) + { + if(strcmp(severity, Severity)) + { + strncpy(severity, Severity, 255); + severity[254] = 0; + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(SEVERITY_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * MonitorTestAttrib::setUnits : +// * This method allows the caller to set the units for the device. +// ***************************************************************************** +int MonitorTestAttrib::setUnits ( char * Units ) + { + if(strcmp(units, Units)) + { + strncpy(units, Units, 255); + units[254] = 0; + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(UNITS_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * MonitorTestAttrib::setAlarmHigh : +// * This method allows the caller to set the high alarm value of the device. +// ***************************************************************************** +int MonitorTestAttrib::setAlarmHigh ( double AlarmHigh ) + { + if(alarmHigh!=AlarmHigh) + { + alarmHigh = AlarmHigh; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(ALARMHIGH_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * MonitorTestAttrib::setAlarmLow : +// * This method allows the caller to set the low alarm value of the device. +// ***************************************************************************** +int MonitorTestAttrib::setAlarmLow ( double AlarmLow ) + { + if(alarmLow!=AlarmLow) + { + alarmLow = AlarmLow; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(ALARMLOW_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * MonitorTestAttrib::setWarningHigh : +// * This method allows the caller to set the high warning value of a device. +// ***************************************************************************** +int MonitorTestAttrib::setWarningHigh ( double WarningHigh ) + { + if(warningHigh!=WarningHigh) + { + warningHigh = WarningHigh; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(WARNINGHIGH_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * MonitorTestAttrib::setWarningLow : +// * This method allows the caller to set the low warning value of a device. +// ***************************************************************************** +int MonitorTestAttrib::setWarningLow ( double WarningLow ) + { + if(warningLow != WarningLow) + { + warningLow = WarningLow; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(WARNINGLOW_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * MonitorTestAttrib::setControlHigh : +// * This method allows the caller to set the maximum value for a device. +// ***************************************************************************** +int MonitorTestAttrib::setControlHigh ( double ControlHigh ) + { + if(controlHigh != ControlHigh) + { + controlHigh = ControlHigh; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(CONTROLHIGH_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * MonitorTestAttrib::setControlLow : +// * This method allows the caller to set the minimum value of a device. +// ***************************************************************************** +int MonitorTestAttrib::setControlLow ( double ControlLow ) + { + if(controlLow != ControlLow) + { + controlLow = ControlLow; + checkAlarms(); + if(monitors && monitors->isMonitored()) + { + cdevData data; + getAllToData(&data); + monitors->fireMonitor(CONTROLLOW_TAG, &data); + } + } + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * MonitorTestAttrib::checkAlarms : +// * This method allows the caller to read the value in comparison with all +// * of its limits and set the status and severity tag appropriately. +// ***************************************************************************** +void MonitorTestAttrib::checkAlarms ( void ) + { + int done = 0; + if(controlHigh>controlLow) + { + if(valuecontrolHigh) + { + setStatus("OUT OF RANGE HIGH"); + setSeverity("ERROR"); + done = 1; + } + } + if(!done && alarmHigh>alarmLow) + { + if(valuealarmHigh) + { + setStatus("ALARM HIGH"); + setSeverity("ALARM"); + done = 1; + } + } + if(!done && warningHigh>warningLow) + { + if(valuewarningHigh) + { + setStatus("WARNING HIGH"); + setSeverity("WARNING"); + done = 1; + } + } + if(!done) + { + setStatus("NORMAL"); + setSeverity("\0"); + } + } + +// ***************************************************************************** +// * MonitorTestAttrib::insertMonitor : +// * This message adds a monitor to the cdevMonitorTable for this device/ +// * attribute pair. The message parameter becomes the property of the +// * monitorTable and should not be accessed again by the caller. +// ***************************************************************************** +void MonitorTestAttrib::insertMonitor ( cdevMonitorTable * table, cdevMessage * message ) + { + if(table!=NULL && message!=NULL) + { + cdevData data; + getAllToData(&data); + table->insertMonitor(message, &data); + monitors = table->findMonitor(device, attrib); + if(monitors && !monitors->isMonitored()) monitors = NULL; + } + else if(message!=NULL) delete message; + } + +// ***************************************************************************** +// * MonitorTestAttrib::removeMonitor: +// * This method uses the cancelTransIdx to locate and delete a monitor +// * that was previously posted using that transaction index. +// ***************************************************************************** +void MonitorTestAttrib::removeMonitor (cdevMonitorTable * table, cdevMessage * message ) + { + if(table!=NULL && message!=NULL) + { + table->removeMonitor(message); + if(monitors && !monitors->isMonitored()) monitors = NULL; + } + } diff --git a/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestAttrib.h b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestAttrib.h new file mode 100644 index 0000000..691134a --- /dev/null +++ b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestAttrib.h @@ -0,0 +1,68 @@ +#ifndef _VIRTUAL_ATTRIB_H_ +#define _VIRTUAL_ATTRIB_H_ 1 + +#include +#include + + +// ***************************************************************************** +// * class MonitorTestAttrib: +// * This class maintains a list of items that make-up a MonitorTest Attrib. And +// * access mechanisms. +// ***************************************************************************** +class MonitorTestAttrib +{ +private: + char * device; + char * attrib; + cdevMonitorNode * monitors; + + double value; + char status [255]; + char severity[255]; + char units [255]; + double alarmHigh; + double alarmLow; + double warningHigh; + double warningLow; + double controlHigh; + double controlLow; + + int resultCode; +public: + MonitorTestAttrib (char * Device, char * Attrib); + ~MonitorTestAttrib ( void ); + + int setFromData ( cdevData * data ); + void getToData ( cdevData * data, cdevData * context = NULL ); + void getAllToData ( cdevData * data ); + + int setValue ( double Value ); + int setStatus ( char * Status ); + int setSeverity ( char * Severity ); + int setUnits ( char * Units ); + int setAlarmHigh ( double AlarmHigh ); + int setAlarmLow ( double AlarmLow ); + int setWarningHigh ( double WarningHigh ); + int setWarningLow ( double WarningLow ); + int setControlHigh ( double ControlHigh ); + int setControlLow ( double ControlLow ); + void checkAlarms ( void ); + + double getValue ( void ) { return value; } + char * getStatus ( void ) { return status; } + char * getSeverity ( void ) { return severity; } + char * getUnits ( void ) { return units; } + double getAlarmHigh ( void ) { return alarmHigh; } + double getAlarmLow ( void ) { return alarmLow; } + double getWarningHigh ( void ) { return warningHigh; } + double getWarningLow ( void ) { return warningLow; } + double getControlHigh ( void ) { return controlHigh; } + double getControlLow ( void ) { return controlLow; } + int getResultCode ( void ) { return resultCode; } + + void insertMonitor ( cdevMonitorTable * table, cdevMessage * message ); + void removeMonitor ( cdevMonitorTable * table, cdevMessage * message ); +}; + +#endif diff --git a/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestServer.cc b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestServer.cc new file mode 100644 index 0000000..e53b0c6 --- /dev/null +++ b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestServer.cc @@ -0,0 +1,174 @@ +#include +#include + +// ***************************************************************************** +// * This has to be added in order to support the CenterLine Compiler. +// ***************************************************************************** +#if defined (__CENTERLINE__) + long va_alist; +#endif + +MonitorTestServer::~MonitorTestServer ( void ) + { + StringHashIterator iter(&attribHash); + MonitorTestAttrib * attrib = NULL; + char * key = NULL; + + iter.first(); + while((key=iter.key())!=NULL) + { + attrib = (MonitorTestAttrib *)iter.data(); + iter++; + attribHash.remove(key); + if(attrib!=NULL) delete attrib; + } + } + +void MonitorTestServer::populateTable ( void ) + { + char device[10]; + char attrib[10]; + char key[20]; + for(int i=0; i<10; i++) + { + for(int j=0; j<10; j++) + { + sprintf(device, "device%i", i); + sprintf(attrib, "attrib%i", j); + sprintf(key, "device%i attrib%i", i, j); + attribHash.insert(key, new MonitorTestAttrib(device, attrib)); + } + } + } + +void MonitorTestServer::processMessages ( void ) + { + char key[255]; + int saveMessageFlag; + int sendMessageFlag; + cdevMessage * message; + MonitorTestAttrib * attrib; + cdevData output; + + while(dequeue(message)==0) + { + // ************************************************************* + // * Note at this point a cdevTagMap has already been received + // * from the client. This tag map will have initialized all + // * of the tags that are required by the service. + // ************************************************************* + if(!strcmp(message->getMessage(), "unregister")) + { + sendMessageFlag = 0; + removeClientMonitors(message->getClientID()); + } + if(!strncmp(message->getMessage(), "get ", 4)) + { + output.remove(); + saveMessageFlag = 0; + sendMessageFlag = 1; + + sprintf(key, "%s %s", + message->getDeviceList()[0], + &message->getMessage()[4]); + + if((attrib = (MonitorTestAttrib *)attribHash.find(key))!=NULL) + { + attrib->getToData(&output, message->getContext()); + output.insert("resultCode", CDEV_SUCCESS); + } + else output.insert("resultCode", CDEV_NOTFOUND); + } + else if(!strncmp(message->getMessage(), "set ", 4)) + { + output.remove(); + saveMessageFlag = 0; + sendMessageFlag = 1; + + sprintf(key, "%s %s", + message->getDeviceList()[0], + &message->getMessage()[4]); + + if((attrib = (MonitorTestAttrib *)attribHash.find(key))!=NULL) + { + output.insert("resultCode", + attrib->setFromData(message->getData())); + } + else output.insert("resultCode", CDEV_NOTFOUND); + } + else if(!strncmp(message->getMessage(), "monitorOn ", 10)) + { + saveMessageFlag = 1; + sendMessageFlag = 0; + + sprintf(key, "%s %s", + message->getDeviceList()[0], + &message->getMessage()[10]); + + if((attrib = (MonitorTestAttrib *)attribHash.find(key))!=NULL) + { + attrib->insertMonitor(this, message); + } + } + else if(!strncmp(message->getMessage(), "monitorOff ", 11)) + { + saveMessageFlag = 0; + sendMessageFlag = 1; + + sprintf(key, "%s %s", + message->getDeviceList()[0], + &message->getMessage()[11]); + + if((attrib = (MonitorTestAttrib *)attribHash.find(key))!=NULL) + { + attrib->removeMonitor(this, message); + } + } + else + { + saveMessageFlag = 0; + sendMessageFlag = 1; + output.insert("resultCode", CDEV_NOTFOUND); + } + + if(sendMessageFlag) + { + message->setData(&output, 1); + enqueue(message); + } + if(!saveMessageFlag) delete message; + } + } + +int MonitorTestServer::fireCallback ( cdevMessage * message ) + { + int result = CDEV_SUCCESS; + cdevData * data = NULL; + + if(message && (data = message->getData())!=NULL) + { + data->insert("resultCode", CDEV_SUCCESS); + result = enqueue(message); + } + return result; + } + +int main(int argc, char ** argv) +{ +fprintf(stdout, "\n\ +=> **********************************************************************\n\ +=> * This is a test server that is used to test the Monitoring *\n\ +=> * capabilities of the cdevGenericServer engine. This server will be *\n\ +=> * contacted with a list of monitor requests to which it will respond *\n\ +=> **********************************************************************\n\n"); +fflush(stdout); + +char * name = "MonitorTestServer"; + +if(argc>1) name = argv[1]; + +MonitorTestServer server("MONITOR_TEST", name, 0, 60); +cdevServer::runServer(); + +return 0; +} diff --git a/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestServer.h b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestServer.h new file mode 100644 index 0000000..fa3e10c --- /dev/null +++ b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestServer.h @@ -0,0 +1,40 @@ +#ifndef _VIRTUAL_SERVER_H_ +#define _VIRTUAL_SERVER_H_ 1 + +#include +#include +#include + +// ***************************************************************************** +// * class MonitorTestServer : +// * This is the server class for the MonitorTestDevice. It simply receives +// * messages from a client and immediately returns them. +// * +// * The constructor passes the domain, server, port and rate to the +// * underlying cdevServer class to be processed. The cdevServer constructor +// * will add this server to the Name Server and will begin processing +// * messages when the cdevServer::runServer() method is executed. +// * +// * The processMessages method is the servers interface to the world... Each +// * time a complete message is received or the time specified in rate +// * expires, that method will be called. +// ***************************************************************************** +class MonitorTestServer : public cdevServer, public cdevMonitorTable +{ +private: + StringHash attribHash; + +public: + MonitorTestServer ( char * domain, char * server, unsigned int port, double pulse ) + : cdevServer(domain, server, port, pulse), attribHash() + { + populateTable(); + } + + virtual ~MonitorTestServer ( void ); + virtual void processMessages ( void ); + void populateTable ( void ); + virtual int fireCallback ( cdevMessage * message ); +}; + +#endif diff --git a/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestService.cc b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestService.cc new file mode 100644 index 0000000..c1fd568 --- /dev/null +++ b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestService.cc @@ -0,0 +1,60 @@ +#include + +// ***************************************************************************** +// * newMonitorTestService: +// * This function will be called by the cdevSystem object to create an +// * initial instance of the MonitorTestService. +// ***************************************************************************** +extern "C" cdevService * newMonitorTestService (char * name, cdevSystem * system) + { + return new MonitorTestService(name, *system); + } + +// ***************************************************************************** +// * MonitorTestService::MonitorTestService : +// * This is teh constructor for the MonitorTestService. It initializes the +// * underlying cdevClientService by specifying that it is in the domain of +// * VIRTUAL. +// ***************************************************************************** +MonitorTestService::MonitorTestService ( char * name, cdevSystem & system) + : cdevClientService("MONITOR_TEST", name, system) + { + // ********************************************************************* + // * Install the RESULT_CODE_TAG at a location of 30 or higher if it + // * does not already exist. + // ********************************************************************* + RESULT_CODE_TAG = 0; + cdevData::tagC2I("resultCode", &RESULT_CODE_TAG); + + for(int i=30; RESULT_CODE_TAG==0 && i<65534; i++) + { + cdevData::insertTag(i, "resultCode"); + cdevData::tagC2I("resultCode", &RESULT_CODE_TAG); + } + + system.reportError(CDEV_SEVERITY_INFO, "MonitorTestService", NULL, + "Constructing a new MonitorTestService"); + + } + +// ***************************************************************************** +// * MonitorTestService::fireCallback : +// * This is the method that will be called to dispatch the callback methods +// * that are associated with the calls to the MonitorTest Server. If the +// * message has been processed successfully, then the method will remove +// * the resultCode from the outbound data and use that as the status. +// ***************************************************************************** +void MonitorTestService::fireCallback ( int status, cdevTranObj &xobj, cdevData *resultData, int partialTransaction ) + { + // ********************************************************************* + // * If the message was transmitted successfully, get the result code + // * from the data that was returned and use that as the status. + // ********************************************************************* + if(status==CDEV_SUCCESS && resultData!=NULL) + { + resultData->get(RESULT_CODE_TAG, &status); + resultData->remove(RESULT_CODE_TAG); + } + + cdevClientService::fireCallback(status, xobj, resultData, partialTransaction); + } diff --git a/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestService.h b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestService.h new file mode 100644 index 0000000..c838fd1 --- /dev/null +++ b/extensions/cdevGenericServer/tests/MonitorTest/MonitorTestService.h @@ -0,0 +1,29 @@ +#include + +#ifndef MONITOR_TEST_SERVICE_API + #define MONITOR_TEST_SERVICE_API +#endif + +// ***************************************************************************** +// * newMonitorTestService : +// * This function will be called by the cdevSystem object to create an +// * initial instance of the MonitorTestService. +// ***************************************************************************** +extern "C" MONITOR_TEST_SERVICE_API cdevService * newMonitorTestService ( char * name, cdevSystem * system ); + +// ***************************************************************************** +// * class MonitorTestService : +// * This class simply inherits from the cdevClientService and must define +// * only a constructor and destructor. +// ***************************************************************************** +class MonitorTestService : public cdevClientService +{ +public: + MonitorTestService ( char * name, cdevSystem & system = cdevSystem::defaultSystem()); + +protected: + int RESULT_CODE_TAG; + + virtual ~MonitorTestService ( void ) {}; + virtual void fireCallback ( int status, cdevTranObj &xobj, cdevData *resultData, int partialTransaction = 0 ); +}; diff --git a/extensions/cdevGenericServer/tests/MonitorTest/MonitorWriter.cc b/extensions/cdevGenericServer/tests/MonitorTest/MonitorWriter.cc new file mode 100644 index 0000000..5b337f2 --- /dev/null +++ b/extensions/cdevGenericServer/tests/MonitorTest/MonitorWriter.cc @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include + +int callbackCount = 0; + +const int DEVICE_COUNT = 9; +const int MESSAGE_COUNT = 9; + +int main ( ) + { + fprintf(stdout, "\n\ +=> **********************************************************************\n\ +=> * This is the writing side of a two part monitoring test program. *\n\ +=> * This program will set up a list of devices and attributes and *\n\ +=> * will modify them at a regular rate. *\n\ +=> **********************************************************************\n\n"); + fflush(stdout); + cdevDevice * deviceList[DEVICE_COUNT]; + cdevRequestObject * reqList[DEVICE_COUNT*MESSAGE_COUNT]; + cdevData data; + float values[DEVICE_COUNT*MESSAGE_COUNT]; + char msg[255]; + int deviceCnt; + int msgCnt; + + // ********************************************************************* + // * First get all of the values from the devices. + // ********************************************************************* + for(deviceCnt=0; deviceCntsend(msg, NULL, data)==CDEV_SUCCESS) + { + data.get("value", &values[deviceCnt*MESSAGE_COUNT+msgCnt]); + } + else { + values[deviceCnt*MESSAGE_COUNT+msgCnt] = 0; + fprintf(stdout, "ERROR : device %s : %s failed\n", deviceList[deviceCnt]->name(), msg); + } + sprintf(msg, "set attrib%i", msgCnt); + reqList[deviceCnt*MESSAGE_COUNT+msgCnt] = deviceList[deviceCnt]->getRequestObject(msg); + } + } + + while(1) + { + for(int i=0; isendNoBlock(data, NULL); + } + cdevSystem::defaultSystem().pend(); + } + return 0; + } diff --git a/extensions/cdevGenericServer/tests/MonitorTest/NMakefile.mak b/extensions/cdevGenericServer/tests/MonitorTest/NMakefile.mak new file mode 100755 index 0000000..6d1bb4c --- /dev/null +++ b/extensions/cdevGenericServer/tests/MonitorTest/NMakefile.mak @@ -0,0 +1,100 @@ +.SUFFIXES: .cc .obj + +APPNAME = Client/Server Monitor Test +ARCH = WINNT-4.0 +SHOBJ = YES + +BINARIES = $(BASEBIN)\MonitorTestServer.exe \ + $(CDEVLIB)\MonitorTestService.dll \ + $(CDEVLIB)\MonitorTestService.lib \ + $(BASEBIN)\MonitorTest.exe \ + $(BASEBIN)\MonitorReader.exe \ + $(BASEBIN)\MonitorOffTest.exe \ + $(BASEBIN)\MonitorWriter.exe \ + $(BASEBIN)\DefaultServerTest.exe + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +CXXINCLUDES = /I .\\ +CXXEXTRA_DLL = /D "MONITOR_TEST_SERVICE_API=__declspec(dllexport)" +CXXEXTRA_LIB = /D "MONITOR_TEST_SERVICE_API=" + +!IF "$(SHOBJ)" == "YES" +TARGETS = $(BASEBIN)\MonitorTestServer.exe \ + $(CDEVLIB)\MonitorTestService.dll \ + $(BASEBIN)\MonitorTest.exe \ + $(BASEBIN)\MonitorReader.exe \ + $(BASEBIN)\MonitorOffTest.exe \ + $(BASEBIN)\MonitorWriter.exe \ + $(BASEBIN)\DefaultServerTest.exe +!ELSE +TARGETS = $(BASEBIN)\MonitorTestServer.exe \ + $(CDEVLIB)\MonitorTestService.lib \ + $(BASEBIN)\MonitorTest.exe \ + $(BASEBIN)\MonitorReader.exe \ + $(BASEBIN)\MonitorOffTest.exe \ + $(BASEBIN)\MonitorWriter.exe \ + $(BASEBIN)\DefaultServerTest.exe +!ENDIF + +targets : $(TARGETS) + +$(CDEVLIB)\MonitorTestService.dll : $(OBJDIR)\MonitorTestService.obj + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib\ + $(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $? + -@copy $@ $(CDEVSHOBJ)\$(CDEVVERSION)\$(@F) > nul + @echo ^ ^ ^ ^ ^ ^ Done... + +$(CDEVLIB)\MonitorTestService.lib : $(OBJDIR)\MonitorTestService.obj + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib\ + $(LINK_LIB_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\MonitorTestServer.exe : .exec\$(TARGETDIR)\MonitorTestServer.obj $(OBJDIR)\MonitorTestAttrib.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\MonitorTest.exe : .exec\$(TARGETDIR)\MonitorTest.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\MonitorReader.exe : .exec\$(TARGETDIR)\MonitorReader.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\MonitorOffTest.exe : .exec\$(TARGETDIR)\MonitorOffTest.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\MonitorWriter.exe : .exec\$(TARGETDIR)\MonitorWriter.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\DefaultServerTest.exe : .exec\$(TARGETDIR)\DefaultServerTest.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + diff --git a/extensions/cdevGenericServer/tests/NMakefile.mak b/extensions/cdevGenericServer/tests/NMakefile.mak new file mode 100644 index 0000000..80474cc --- /dev/null +++ b/extensions/cdevGenericServer/tests/NMakefile.mak @@ -0,0 +1,13 @@ +BASEDIR = $(MAKEDIR) +DIRS = $(BASEDIR)\TransmissionTest \ + $(BASEDIR)\PerformanceTest \ + $(BASEDIR)\EarlyDeath \ + $(BASEDIR)\BadMagic \ + $(BASEDIR)\MonitorTest \ + $(BASEDIR)\GetServers \ + $(BASEDIR)\SyncSet + +notarget: all + +all clean purge: + @for %d in ($(DIRS)) do @if exist %d cd %d & $(MAKE) /NOLOGO $@ /f NMakefile.mak diff --git a/extensions/cdevGenericServer/tests/Performance/Makefile b/extensions/cdevGenericServer/tests/Performance/Makefile new file mode 100755 index 0000000..204cc4e --- /dev/null +++ b/extensions/cdevGenericServer/tests/Performance/Makefile @@ -0,0 +1,38 @@ +ARCH = OS +SHOBJ = YES + +include ../../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Performance Client/Server Test" +CXXINCLUDES = -I./ -DMANUAL=TRUE +SO_SRCS = PerformanceService.cc +SO_LIBS = -L$(CDEVLIB) -lcdevGenericServer $(OSLIBS) +LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + +ifeq ($(SHOBJ), YES) + TARGETS = $(BASELIB)/PerformanceService.so $(BASEBIN)/PerformanceServer $(BASEBIN)/PerformanceTest $(BASEBIN)/PerformanceTest2 +else + TARGETS = $(BASELIB)/libPerformanceService.a $(BASEBIN)/PerformanceServer $(BASEBIN)/PerformanceTest $(BASEBIN)/PerformanceTest2 +endif + +targets : $(TARGETS) + +$(BASEBIN)/PerformanceTest : $(OBJDIR)/PerformanceTest.o + $(LINK.cc) $^ $(LIBS) -o $@ + +$(BASEBIN)/PerformanceTest2 : $(OBJDIR)/PerformanceTest2.o + $(LINK.cc) $^ $(LIBS) -o $@ + +$(BASEBIN)/PerformanceServer : $(OBJDIR)/PerformanceServer.o + $(LINK.cc) $^ $(LIBS) -o $@ + +$(BASELIB)/PerformanceService.so : $(OBJDIR)/PerformanceService.o + $(LINK.so) -o $@ $^ -L$(CDEVLIB) -lcdevGenericServer $(OSLIBS) + @mkdir -p $(CDEVSHOBJ)/$(CDEVVERSION) + @cp $@ $(CDEVSHOBJ)/$(CDEVVERSION)/$(@F) + + +$(BASELIB)/libPerformanceService.a : $(OBJDIR)/PerformanceService.o + $(LINK.a) $@ $(OBJDIR)/PerformanceService.o + @$(RANLIB) $@ > /dev/null + diff --git a/extensions/cdevGenericServer/tests/Performance/NMakefile.mak b/extensions/cdevGenericServer/tests/Performance/NMakefile.mak new file mode 100755 index 0000000..27a3eb4 --- /dev/null +++ b/extensions/cdevGenericServer/tests/Performance/NMakefile.mak @@ -0,0 +1,59 @@ +.SUFFIXES: .cc .obj + +APPNAME = Client/Server Performance Test +ARCH = WINNT-4.0 +SHOBJ = YES + +BINARIES = $(BASEBIN)\PerformanceServer.exe \ + $(BASEBIN)\PerformanceTest.exe \ + $(CDEVLIB)\PerformanceService.dll \ + $(CDEVLIB)\PerformanceService.lib + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +CXXINCLUDES = /I .\\ /D "MANUAL=TRUE" +CXXEXTRA_DLL = /D "PERFORMANCE_SERVICE_API=__declspec(dllexport)" +CXXEXTRA_LIB = /D "PERFORMANCE_SERVICE_API=" + +!IF "$(SHOBJ)" == "YES" +TARGETS = $(BASEBIN)\PerformanceServer.exe \ + $(BASEBIN)\PerformanceTest.exe \ + $(CDEVLIB)\PerformanceService.dll +!ELSE +TARGETS = $(BASEBIN)\PerformanceServer.exe \ + $(BASEBIN)\PerformanceTest.exe \ + $(CDEVLIB)\PerformanceService.lib +!ENDIF + +targets : $(TARGETS) + +$(CDEVLIB)\PerformanceService.dll : $(OBJDIR)\PerformanceService.obj + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib\ + $(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $? + -@copy $@ $(CDEVSHOBJ)\$(CDEVVERSION)\$(@F) > nul + @echo ^ ^ ^ ^ ^ ^ Done... + +$(CDEVLIB)\PerformanceService.lib : $(OBJDIR)\PerformanceService.obj + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib\ + $(LINK_LIB_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\PerformanceServer.exe : .exec\$(TARGETDIR)\PerformanceServer.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\PerformanceTest.exe : .exec\$(TARGETDIR)\PerformanceTest.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... diff --git a/extensions/cdevGenericServer/tests/Performance/Performance.ddl b/extensions/cdevGenericServer/tests/Performance/Performance.ddl new file mode 100755 index 0000000..0d01715 --- /dev/null +++ b/extensions/cdevGenericServer/tests/Performance/Performance.ddl @@ -0,0 +1,26 @@ +service Performance + { + tags {server} + } + +class Performances + { + verbs {get, set} + attributes + { + default Performance; + servers Performance; + attrib0 Performance {server=Performance1}; + attrib1 Performance {server=Performance1}; + } + messages + { + disconnect Performance; + } + } + + +Performances : + device0; + +alias device1 device0 diff --git a/extensions/cdevGenericServer/tests/Performance/PerformanceServer.cc b/extensions/cdevGenericServer/tests/Performance/PerformanceServer.cc new file mode 100755 index 0000000..28de382 --- /dev/null +++ b/extensions/cdevGenericServer/tests/Performance/PerformanceServer.cc @@ -0,0 +1,51 @@ +#include + + +// ***************************************************************************** +// * class PerformanceServer : +// * This is a performance test server. It simply receives messages +// * from a client and immediately returns them. +// * +// * The constructor passes the domain, server, port and rate to the +// * underlying cdevServer class to be processed. The cdevServer constructor +// * will add this server to the Name Server and will begin processing +// * messages when the cdevServer::runServer() method is executed. +// * +// * The processMessages method is the servers interface to the world... Each +// * time a complete message is received or the time specified in rate +// * expires, that method will be called. +// ***************************************************************************** +class PerformanceServer : public cdevServer +{ +cdevMessage * pmMessage; + +public: + PerformanceServer ( char * domain, char * server, unsigned int port, double pulse ) + : cdevServer(domain, server, port, pulse) + { + } + + virtual void processMessages ( void ) + { + while(dequeue(pmMessage)==0) + { + enqueue(pmMessage); + delete pmMessage; + } + } + +}; + + +int main(int argc, char ** argv) +{ +char * serverName; + +if(argc>1) serverName = argv[1]; +else serverName = strdup("Performance1"); + +PerformanceServer server("PERFORMANCE", serverName, 0, 5); +cdevServer::runServer(); + +return 0; +} diff --git a/extensions/cdevGenericServer/tests/Performance/PerformanceService.cc b/extensions/cdevGenericServer/tests/Performance/PerformanceService.cc new file mode 100755 index 0000000..c1d6fff --- /dev/null +++ b/extensions/cdevGenericServer/tests/Performance/PerformanceService.cc @@ -0,0 +1,28 @@ +#include + +// ***************************************************************************** +// * newPerformanceService: +// * This function will be called by the cdevSystem object to create an +// * initial instance of the PerformanceService. +// ***************************************************************************** +extern "C" cdevService * newPerformanceService (char * name, cdevSystem * system) + { + return new PerformanceService(name, *system); + } + +// ***************************************************************************** +// * PerformanceService::PerformanceService : +// * This is teh constructor for the PerformanceService. It initializes the +// * underlying cdevClientService by specifying that it is in the domain of +// * PERFORMANCE. +// ***************************************************************************** +PerformanceService::PerformanceService ( char * name, cdevSystem & system) + : cdevClientService("PERFORMANCE", name, system) + { + system.reportError(CDEV_SEVERITY_INFO, "PerformanceService", NULL, + "Constructing a new PerformanceService"); + } + +PerformanceService::~PerformanceService ( void ) + { + } diff --git a/extensions/cdevGenericServer/tests/Performance/PerformanceService.h b/extensions/cdevGenericServer/tests/Performance/PerformanceService.h new file mode 100755 index 0000000..c798126 --- /dev/null +++ b/extensions/cdevGenericServer/tests/Performance/PerformanceService.h @@ -0,0 +1,27 @@ +#include + +#ifndef PERFORMANCE_SERVICE_API + #define PERFORMANCE_SERVICE_API +#endif + +// ***************************************************************************** +// * newPerformanceService : +// * This function will be called by the cdevSystem object to create an +// * initial instance of the PerformanceService. +// ***************************************************************************** +extern "C" PERFORMANCE_SERVICE_API cdevService * newPerformanceService ( char * name, cdevSystem * system ); + +// ***************************************************************************** +// * class PerformanceService : +// * This class simply inherits from the cdevClientService and must define +// * only a constructor and destructor. +// ***************************************************************************** +class PerformanceService : public cdevClientService +{ +public: + PerformanceService ( char * name, cdevSystem & system = cdevSystem::defaultSystem()); + +protected: + ~PerformanceService ( void ); + +}; diff --git a/extensions/cdevGenericServer/tests/Performance/PerformanceTest.cc b/extensions/cdevGenericServer/tests/Performance/PerformanceTest.cc new file mode 100644 index 0000000..c75be00 --- /dev/null +++ b/extensions/cdevGenericServer/tests/Performance/PerformanceTest.cc @@ -0,0 +1,383 @@ +#include +#include +#include +#include +#include +#include +#include + +struct timeval first; +int callbackCount = 0; +int reportCount = 0; +int reportFrequency = 0; +int bunchSize = 0; +char * deviceName = "device0"; +char * messageStr = "set attrib0"; +double PerformanceRate = 0.0; +double * performanceRatePtr = &PerformanceRate; +size_t PacketSize = 0; +size_t * packetSizePtr = &PacketSize; +int synchroValue = 0; +int synchroFound = 0; + +void synchroCallback (int status, void *, cdevRequestObject &, cdevData & data) + { + if(status==CDEV_SUCCESS) + { + int value; + data.get("value", &value); + if(value==synchroValue) synchroFound = 1; + } + } + +void callback ( int status, void *, cdevRequestObject &, cdevData & ) + { + if(status==CDEV_SUCCESS) + { + callbackCount++; + reportCount++; + + if(reportCount==reportFrequency) + { + reportCount = 0; + struct timeval second, lapsed; + + gettimeofday(&second); + + if (first.tv_usec > second.tv_usec) + { + second.tv_usec += 1000000; + second.tv_sec--; + } + + lapsed.tv_usec = second.tv_usec - first.tv_usec; + lapsed.tv_sec = second.tv_sec - first.tv_sec; + + if(lapsed.tv_sec) + { + *performanceRatePtr = (double)callbackCount/(double)lapsed.tv_sec; + fprintf(stdout, "Average rate is %lf pkts/sec after %ld packets\n", *performanceRatePtr, callbackCount); + } + fflush(stdout); + } + } + } + +cdevData * createPayload1 ( int ) + { + char * binary = 0; + cdevMessage msg(1, 1, 0, 0, 0, 0, 0, 1, &deviceName, messageStr); + msg.streamOut(&binary, packetSizePtr); + delete binary; + return NULL; + } + +cdevData * createPayload2 ( int cnt ) + { + cdevData * data = new cdevData; + if(cnt>1) + { + int * x = new int[cnt]; + for(int i=0; iinsert("value", x, cnt); + delete x; + } + else data->insert("value", 1); + + char * binary = 0; + cdevMessage msg(1, 1, 0, 0, 0, 0, 0, 1, &deviceName, messageStr, data); + msg.streamOut(&binary, packetSizePtr); + delete binary; + + return data; + } + +cdevData * createPayload3 ( int cnt ) + { + cdevData * data = new cdevData; + if(cnt>1) + { + float * x = new float[cnt]; + for(int i=0; iinsert("value", x, cnt); + delete x; + } + else data->insert("value", (float)1.0); + + char * binary = 0; + cdevMessage msg(1, 1, 0, 0, 0, 0, 0, 1, &deviceName, messageStr, data); + msg.streamOut(&binary, packetSizePtr); + delete binary; + + return data; + } + +cdevData * createPayload4 ( int cnt ) + { + cdevData * data = new cdevData; + if(cnt>1) + { + double * x = new double[cnt]; + for(int i=0; iinsert("value", x, cnt); + delete x; + } + else data->insert("value", (double)1.0); + + char * binary = 0; + cdevMessage msg(1, 1, 0, 0, 0, 0, 0, 1, &deviceName, messageStr, data); + msg.streamOut(&binary, packetSizePtr); + delete binary; + + return data; + } + +cdevData * createPayload5 ( int cnt ) + { + cdevData * data = new cdevData; + char buf[64]; + + if(cnt>1) + { + char ** x = new char *[cnt]; + int i; + for(i=0; iinsert("value", x, cnt); + for(i=0; iinsert("value", buf); + } + + char * binary = 0; + cdevMessage msg(1, 1, 0, 0, 0, 0, 0, 1, &deviceName, messageStr, data); + + msg.streamOut(&binary, packetSizePtr); + delete binary; + + return data; + } + +const int payloadCount = 10; + +char * payloadType[payloadCount] = + { + "None", + "1 - Barebones cdevMessage", + "2 - cdevMessage with one integer value", + "3 - cdevMessage with one float value", + "4 - cdevMessage with one double value", + "5 - cdevMessage with a character string", + "6 - cdevMessage with an array of integers", + "7 - cdevMessage with an array of floats", + "8 - cdevMessage with an array of doubles", + "9 - cdevMessage with an array of strings" + }; + +typedef cdevData * (*PayloadFunc)(int cnt); + +PayloadFunc payloadFunc[payloadCount] = + { + NULL, + createPayload1, + createPayload2, + createPayload3, + createPayload4, + createPayload5, + createPayload2, + createPayload3, + createPayload4, + createPayload5 + }; + +int main ( int argc, char ** argv ) + { + int i; + int payload = 0; + int payloadItems = 0; + int count = -1; + + if(argc>1) for(i=1; i=argc) goto QUIT_LABEL; + + switch (argv[i][1]) + { + case 'd': // (d)evice + deviceName = strdup(argv[++i]); + break; + + case 'm': // (m)essage + messageStr = strdup(argv[++i]); + break; + + case 't': // payload (t)ype + payload = atoi(argv[++i]); + break; + + case 'e': // payload (e)lements + payloadItems = atoi(argv[++i]); + break; + + case 'b': // (b)unch size + bunchSize = atoi(argv[++i]); + break; + + case 'f': // report (f)requency + reportFrequency = atoi(argv[++i]); + break; + + case 'c': // packet (c)ount + count = atoi(argv[++i]); + break; + + case 'h': + default: + QUIT_LABEL: + printf("\nFormat is: PerformanceTest -d dev -m msg -t type -e elements -b bunch -f freq -c count\n"); + printf(" -d dev ... where dev is the name of the cdev device\n"); + printf(" -m msg ... where msg is the cdev message string\n"); + printf(" -t type ... where type is the outbound data's payload type\n"); + for(int x=1; x=payloadCount) + { + fprintf(stdout, "Payload type specifies the type of data that will\n"); + fprintf(stdout, "transmitted in each message...\n"); + for(i=1; i=payloadCount) + { + fprintf(stdout, "Enter payload type (1 - %i): ", payloadCount-1); + fscanf (stdin, "%ld", &payload); + } + } + + if(payload>5) + { + if(payloadItems<1) + { + for(payloadItems = 0; payloadItems<1; ) + { + fprintf(stdout, "Enter the number of array elements: "); + fscanf(stdin, "%ld", &payloadItems); + } + } + } + else payloadItems = 1; + + data = payloadFunc[payload](payloadItems); + + if(bunchSize<1 || bunchSize>500) + { + fprintf(stdout, "\nBunch size is the number of packets that will be\n"); + fprintf(stdout, "transmitted TO the server before the application\n"); + fprintf(stdout, "pauses to listen for replies FROM the server.\n\n"); + while(bunchSize<1 || bunchSize>500) + { + fprintf(stdout, "Enter bunch size (1-500): "); + fscanf (stdin, "%ld", &bunchSize); + } + } + + if(reportFrequency<1) + { + fprintf(stdout, "\nReport frequency is the number of packets that\n"); + fprintf(stdout, "should be received from the server before the application\n"); + fprintf(stdout, "pauses to calculate and report performance information.\n\n"); + while(reportFrequency<1) + { + fprintf(stdout, "Enter report frequency (1 - Infinity): "); + fscanf (stdin, "%ld", &reportFrequency); + } + } + + fprintf(stdout, "\nStarting Test:\n=> Device : %s\n=> Message : %s\n=> Payload : %s\n=> Packet size : %ld\n=> Bunch size : %ld\n=> Frequency : %ld\n", deviceName, messageStr, payloadType[payload], *packetSizePtr, bunchSize, reportFrequency); + if(payloadItems>1) fprintf(stdout, "=> Array Size : %ld\n", payloadItems); + if(count>0) fprintf(stdout, "=> Test Length : %ld Packets\n", count); + + cdevRequestObject & req = cdevRequestObject::attachRef(deviceName, messageStr); + if(req.send(NULL, NULL)!=CDEV_SUCCESS) + { + fprintf(stdout, "\nPerformanceTest Error: Request %s %s appears to be invalid\nExiting...\n\n", deviceName, messageStr); + fflush(stdout); + return 0; + } + + gettimeofday(&first); + + int sendCount = 0; + cdevData recvData; + + while(count<0 || sendCount1000) + { + fprintf(stdout, "Attempting to resynchronize after polling timeout (%i)\n", dryPollCount); + fflush (stdout); + } + + synchroFound = 0; + synchroValue++; + syncData.insert("value", synchroValue); + req.sendCallback(syncData, sb); + + while(!synchroFound && dryPollCount%10!=0) + { + if(cdevSystem::defaultSystem().poll()<=0) dryPollCount++; + else dryPollCount=0; + } + dryPollCount++; + } while(!synchroFound); + } + } + + return 0; + } diff --git a/extensions/cdevGenericServer/tests/Performance/PerformanceTest2.cc b/extensions/cdevGenericServer/tests/Performance/PerformanceTest2.cc new file mode 100644 index 0000000..dab02f5 --- /dev/null +++ b/extensions/cdevGenericServer/tests/Performance/PerformanceTest2.cc @@ -0,0 +1,347 @@ +#include +#include +#include +#include +#include +#include +#include + +void callback ( int status, void *, cdevRequestObject & req, cdevData & data ); + +struct timeval first; +int testLength = 0x0FFFFFFF; +int callbackCount = 0; +int reportCount = 0; +int reportFrequency = 0; +int bunchSize = 0; +char * deviceName = "device0"; +char * messageStr = "set attrib0"; +double PerformanceRate = 0.0; +double * performanceRatePtr = &PerformanceRate; +size_t PacketSize = 0; +size_t * packetSizePtr = &PacketSize; +cdevCallback cb(callback, NULL); + +void callback ( int status, void *, cdevRequestObject & req, cdevData & data ) + { + if(status==CDEV_SUCCESS) + { + callbackCount++; + reportCount++; + + if(reportCount==reportFrequency) + { + reportCount = 0; + struct timeval second, lapsed; + + gettimeofday(&second); + + if (first.tv_usec > second.tv_usec) + { + second.tv_usec += 1000000; + second.tv_sec--; + } + + lapsed.tv_usec = second.tv_usec - first.tv_usec; + lapsed.tv_sec = second.tv_sec - first.tv_sec; + + if(lapsed.tv_sec) + { + *performanceRatePtr = (double)callbackCount/(double)lapsed.tv_sec; + fprintf(stdout, "Average rate is %lf pkts/sec after %ld packets\n", *performanceRatePtr, callbackCount); + } + fflush(stdout); + + if(callbackCount>=testLength) + { + exit(0); + } + } + + req.sendCallback(data, cb); + + } + } + + +cdevData * createPayload1 ( int ) + { + char * binary = 0; + cdevMessage msg(1, 1, 0, 0, 0, 0, 0, 1, &deviceName, messageStr); + msg.streamOut(&binary, packetSizePtr); + delete binary; + return NULL; + } + +cdevData * createPayload2 ( int cnt ) + { + cdevData * data = new cdevData; + if(cnt>1) + { + int * x = new int[cnt]; + for(int i=0; iinsert("value", x, cnt); + delete x; + } + else data->insert("value", 1); + + char * binary = 0; + cdevMessage msg(1, 1, 0, 0, 0, 0, 0, 1, &deviceName, messageStr, data); + msg.streamOut(&binary, packetSizePtr); + delete binary; + + return data; + } + +cdevData * createPayload3 ( int cnt ) + { + cdevData * data = new cdevData; + if(cnt>1) + { + float * x = new float[cnt]; + for(int i=0; iinsert("value", x, cnt); + delete x; + } + else data->insert("value", (float)1.0); + + char * binary = 0; + cdevMessage msg(1, 1, 0, 0, 0, 0, 0, 1, &deviceName, messageStr, data); + msg.streamOut(&binary, packetSizePtr); + delete binary; + + return data; + } + +cdevData * createPayload4 ( int cnt ) + { + cdevData * data = new cdevData; + if(cnt>1) + { + double * x = new double[cnt]; + for(int i=0; iinsert("value", x, cnt); + delete x; + } + else data->insert("value", (double)1.0); + + char * binary = 0; + cdevMessage msg(1, 1, 0, 0, 0, 0, 0, 1, &deviceName, messageStr, data); + msg.streamOut(&binary, packetSizePtr); + delete binary; + + return data; + } + +cdevData * createPayload5 ( int cnt ) + { + cdevData * data = new cdevData; + char buf[64]; + + if(cnt>1) + { + char ** x = new char *[cnt]; + int i; + for(i=0; iinsert("value", x, cnt); + for(i=0; iinsert("value", buf); + } + + char * binary = 0; + cdevMessage msg(1, 1, 0, 0, 0, 0, 0, 1, &deviceName, messageStr, data); + + msg.streamOut(&binary, packetSizePtr); + delete binary; + + return data; + } + +const int payloadCount = 10; + +char * payloadType[payloadCount] = + { + "None", + "1 - Barebones cdevMessage", + "2 - cdevMessage with one integer value", + "3 - cdevMessage with one float value", + "4 - cdevMessage with one double value", + "5 - cdevMessage with a character string", + "6 - cdevMessage with an array of integers", + "7 - cdevMessage with an array of floats", + "8 - cdevMessage with an array of doubles", + "9 - cdevMessage with an array of strings" + }; + +typedef cdevData * (*PayloadFunc)(int cnt); + +PayloadFunc payloadFunc[payloadCount] = + { + NULL, + createPayload1, + createPayload2, + createPayload3, + createPayload4, + createPayload5, + createPayload2, + createPayload3, + createPayload4, + createPayload5 + }; + +int main ( int argc, char ** argv ) + { + int i; + int payload = 0; + int payloadItems = 0; + + if(argc>1) for(i=1; i=argc) goto QUIT_LABEL; + + switch (argv[i][1]) + { + case 'd': // (d)evice + deviceName = strdup(argv[++i]); + break; + + case 'm': // (m)essage + messageStr = strdup(argv[++i]); + break; + + case 't': // payload (t)ype + payload = atoi(argv[++i]); + break; + + case 'e': // payload (e)lements + payloadItems = atoi(argv[++i]); + break; + + case 'b': // (b)unch size + bunchSize = atoi(argv[++i]); + break; + + case 'f': // report (f)requency + reportFrequency = atoi(argv[++i]); + break; + + case 'c': // packet (c)ount + testLength = atoi(argv[++i]); + break; + + case 'h': + default: + QUIT_LABEL: + printf("\nFormat is: PerformanceTest -d dev -m msg -t type -e elements -b bunch -f freq -c count\n"); + printf(" -d dev ... where dev is the name of the cdev device\n"); + printf(" -m msg ... where msg is the cdev message string\n"); + printf(" -t type ... where type is the outbound data's payload type\n"); + for(int x=1; x=payloadCount) + { + fprintf(stdout, "Payload type specifies the type of data that will\n"); + fprintf(stdout, "transmitted in each message...\n"); + for(i=1; i=payloadCount) + { + fprintf(stdout, "Enter payload type (1 - %i): ", payloadCount-1); + fscanf (stdin, "%ld", &payload); + } + } + + if(payload>5) + { + if(payloadItems<1) + { + for(payloadItems = 0; payloadItems<1; ) + { + fprintf(stdout, "Enter the number of array elements: "); + fscanf(stdin, "%ld", &payloadItems); + } + } + } + else payloadItems = 1; + + data = payloadFunc[payload](payloadItems); + + if(bunchSize<1 || bunchSize>500) + { + fprintf(stdout, "\nBunch size is the number of packets that will be\n"); + fprintf(stdout, "transmitted TO the server before the application\n"); + fprintf(stdout, "pauses to listen for replies FROM the server.\n\n"); + while(bunchSize<1 || bunchSize>500) + { + fprintf(stdout, "Enter bunch size (1-500): "); + fscanf (stdin, "%ld", &bunchSize); + } + } + + if(reportFrequency<1) + { + fprintf(stdout, "\nReport frequency is the number of packets that\n"); + fprintf(stdout, "should be received from the server before the application\n"); + fprintf(stdout, "pauses to calculate and report performance information.\n\n"); + while(reportFrequency<1) + { + fprintf(stdout, "Enter report frequency (1 - Infinity): "); + fscanf (stdin, "%ld", &reportFrequency); + } + } + + fprintf(stdout, "\nStarting Test:\n=> Device : %s\n=> Message : %s\n=> Payload : %s\n=> Packet size : %ld\n=> Bunch size : %ld\n=> Frequency : %ld\n", deviceName, messageStr, payloadType[payload], *packetSizePtr, bunchSize, reportFrequency); + if(payloadItems>1) fprintf(stdout, "=> Array Size : %ld\n", payloadItems); + fprintf(stdout, "=> Test Length : %ld Packets\n", testLength); + + cdevRequestObject & req = cdevRequestObject::attachRef(deviceName, messageStr); + if(req.send(NULL, NULL)!=CDEV_SUCCESS) + { + fprintf(stdout, "\nPerformanceTest Error: Request %s %s appears to be invalid\nExiting...\n\n", deviceName, messageStr); + fflush(stdout); + return 0; + } + + gettimeofday(&first); + + for(i=0; i +#include +#include +#include + +void callback (int status, void * arg, cdevRequestObject &req, cdevData & data) + { + fprintf(stdout, "Received callback with status %i\n", status); + fflush(stdout); + } + +int main ( ) + { + cdevRequestObject & setReq = cdevRequestObject::attachRef("device0", "set attrib1"); + cdevCallback cb (callback, NULL); + cdevData data; + + data.insert("value", 1); + + setReq.sendCallback(data, cb); + cdevSystem::defaultSystem().pend(); + + fprintf(stdout, "Enter a character after you stop and restart the server\n"); + getc(stdin); + + setReq.sendCallback(data, cb); + cdevSystem::defaultSystem().pend(); + return 0; + } diff --git a/extensions/cdevGenericServer/tests/SyncSet/Makefile b/extensions/cdevGenericServer/tests/SyncSet/Makefile new file mode 100644 index 0000000..48906d1 --- /dev/null +++ b/extensions/cdevGenericServer/tests/SyncSet/Makefile @@ -0,0 +1,25 @@ +ARCH = OS +SHOBJ = YES + +include ../../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Sync/Async Test Client" +CXXINCLUDES = -I./ + +ifeq ($(SHOBJ), YES) + LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + TARGETS = $(BASEBIN)/SyncSet $(BASEBIN)/AsyncSet +else + LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + TARGETS = $(BASEBIN)/SyncSet $(BASEBIN)/AsyncSet +endif + + +targets : $(TARGETS) + +$(BASEBIN)/AsyncSet : $(OBJDIR)/AsyncSet.o + $(LINK.cc) $^ -o $@ $(LIBS) + +$(BASEBIN)/SyncSet : $(OBJDIR)/SyncSet.o + $(LINK.cc) $^ -o $@ $(LIBS) + diff --git a/extensions/cdevGenericServer/tests/SyncSet/NMakefile.mak b/extensions/cdevGenericServer/tests/SyncSet/NMakefile.mak new file mode 100755 index 0000000..fc208cc --- /dev/null +++ b/extensions/cdevGenericServer/tests/SyncSet/NMakefile.mak @@ -0,0 +1,27 @@ +.SUFFIXES: .cc .obj + +APPNAME = Sync/Async Test Client +ARCH = WINNT-4.0 +SHOBJ = YES + +BINARIES = $(BASEBIN)\AsyncSet.exe $(BASEBIN)\SyncSet.exe + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +CXXINCLUDES = /I .\\ + +targets : $(BINARIES) + +$(BASEBIN)\AsyncSet.exe : .exec\$(TARGETDIR)\AsyncSet.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\SyncSet.exe : .exec\$(TARGETDIR)\SyncSet.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... diff --git a/extensions/cdevGenericServer/tests/SyncSet/SyncSet.cc b/extensions/cdevGenericServer/tests/SyncSet/SyncSet.cc new file mode 100644 index 0000000..41d66e4 --- /dev/null +++ b/extensions/cdevGenericServer/tests/SyncSet/SyncSet.cc @@ -0,0 +1,21 @@ +#include +#include +#include +#include + + +int main ( ) + { + cdevRequestObject & setReq = cdevRequestObject::attachRef("device0", "set attrib1"); + cdevData data; + + data.insert("value", 1); + + setReq.send(data, NULL); + + fprintf(stdout, "Enter a character after you stop and restart the server\n"); + getc(stdin); + + setReq.send(data, NULL); + return 0; + } diff --git a/extensions/cdevGenericServer/tests/TransmissionTest/GatewayTest.ddl b/extensions/cdevGenericServer/tests/TransmissionTest/GatewayTest.ddl new file mode 100755 index 0000000..8dc4d77 --- /dev/null +++ b/extensions/cdevGenericServer/tests/TransmissionTest/GatewayTest.ddl @@ -0,0 +1,30 @@ +service Gateway + { + tags {server} + } + +class Tests + { + verbs {get, set} + attributes + { + default Gateway; + clientID Gateway; + servers Gateway; + connections Gateway; + attrib Gateway {server=Gateway1}; + ClientInfo Gateway {server=Gateway1}; + ServerInfo Gateway {server=Gateway1}; + } + messages + { + shutdown Gateway; + } + } + + +Tests : + device1, + device2, + device3 +; diff --git a/extensions/cdevGenericServer/tests/TransmissionTest/Makefile b/extensions/cdevGenericServer/tests/TransmissionTest/Makefile new file mode 100755 index 0000000..f890555 --- /dev/null +++ b/extensions/cdevGenericServer/tests/TransmissionTest/Makefile @@ -0,0 +1,4 @@ +all commit clean purge: + @$(MAKE) $@ -f Makefile.service + @$(MAKE) $@ -f Makefile.server + diff --git a/extensions/cdevGenericServer/tests/TransmissionTest/Makefile.server b/extensions/cdevGenericServer/tests/TransmissionTest/Makefile.server new file mode 100755 index 0000000..2e1fb00 --- /dev/null +++ b/extensions/cdevGenericServer/tests/TransmissionTest/Makefile.server @@ -0,0 +1,16 @@ +ARCH = OS +SHOBJ = YES + +include ../../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Transmission Test Server" +OUTPUTDIR = $(BASEBIN) +CXXINCLUDES = -I./ +LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + +TARGETS = $(OUTPUTDIR)/TestServer + +targets : $(TARGETS) + +$(OUTPUTDIR)/TestServer : $(OBJDIR)/TestServer.o + $(LINK.cc) $^ $(LIBS) -o $@ diff --git a/extensions/cdevGenericServer/tests/TransmissionTest/Makefile.service b/extensions/cdevGenericServer/tests/TransmissionTest/Makefile.service new file mode 100755 index 0000000..d724925 --- /dev/null +++ b/extensions/cdevGenericServer/tests/TransmissionTest/Makefile.service @@ -0,0 +1,37 @@ +ARCH = OS +SHOBJ = YES + +include ../../include/makeinclude/Makefile.$(ARCH) + +APPNAME = "Transmission Test Client" +CXXINCLUDES = -I./ + +# ****************************************************************************** +# * The BINARIES definition names all of the binary files that should be deleted +# * whenever "make clean" is executed. +# ****************************************************************************** +BINARIES = $(BASELIB)/libTestService.a \ + $(BASELIB)/TestService.so \ + $(BASEBIN)/TestProgram + +ifeq ($(SHOBJ), YES) + LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + TARGETS = $(BASELIB)/TestService.so $(BASEBIN)/TestProgram +else + LIBS = -L$(CDEVLIB) -lcdevGenericServer $(CDEVLIBS) $(OSLIBS) + TARGETS = $(BASELIB)/libTestService.a $(BASEBIN)/TestProgram +endif + +targets : $(TARGETS) + +$(BASELIB)/TestService.so : $(OBJDIR)/TestService.o + $(LINK.so) -o $@ $^ -L$(CDEVLIB) -lcdevGenericServer $(NETLIBS) + @mkdir -p $(CDEVSHOBJ)/$(CDEVVERSION) + @cp $@ $(CDEVSHOBJ)/$(CDEVVERSION)/$(@F) + +$(BASELIB)/libTestService.a : $(OBJDIR)/TestService.o + $(LINK.a) $@ $^ + @$(RANLIB) $@ > /dev/null + +$(BASEBIN)/TestProgram : $(OBJDIR)/TestProgram.o + $(LINK.cc) $^ -o $@ $(LIBS) diff --git a/extensions/cdevGenericServer/tests/TransmissionTest/NMakefile.mak b/extensions/cdevGenericServer/tests/TransmissionTest/NMakefile.mak new file mode 100644 index 0000000..da9b03d --- /dev/null +++ b/extensions/cdevGenericServer/tests/TransmissionTest/NMakefile.mak @@ -0,0 +1,6 @@ +notarget : all + +all clean purge: + @$(MAKE) /NOLOGO $@ -f NMakefile.service + @$(MAKE) /NOLOGO $@ -f NMakefile.server + diff --git a/extensions/cdevGenericServer/tests/TransmissionTest/NMakefile.server b/extensions/cdevGenericServer/tests/TransmissionTest/NMakefile.server new file mode 100644 index 0000000..6dbbcfd --- /dev/null +++ b/extensions/cdevGenericServer/tests/TransmissionTest/NMakefile.server @@ -0,0 +1,20 @@ +.SUFFIXES: .cc .obj + +APPNAME = Transmission Test Server +ARCH = WINNT-4.0 +SHOBJ = YES + +BINARIES = $(BASEBIN)\TestServer.exe + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +CXXINCLUDES = /I .\\ + +targets : $(BINARIES) + +$(BASEBIN)\TestServer.exe : .exec\$(TARGETDIR)\TestServer.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib \ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... diff --git a/extensions/cdevGenericServer/tests/TransmissionTest/NMakefile.service b/extensions/cdevGenericServer/tests/TransmissionTest/NMakefile.service new file mode 100644 index 0000000..5100491 --- /dev/null +++ b/extensions/cdevGenericServer/tests/TransmissionTest/NMakefile.service @@ -0,0 +1,49 @@ +.SUFFIXES: .cc .obj + + +APPNAME = Transmission Test Client +ARCH = WINNT-4.0 +SHOBJ = YES + +BINARIES = $(CDEVLIB)\TestService.lib \ + $(CDEVLIB)\TestService.dll \ + $(BASEBIN)\TestProgram.exe + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +CXXINCLUDES = /I .\\ +CXXEXTRA_DLL = /D "TEST_SERVICE_API=__declspec(dllexport)" +CXXEXTRA_LIB = /D "TEST_SERVICE_API=" + +!IF "$(SHOBJ)" == "YES" +TARGETS = $(CDEVLIB)\TestService.dll $(BASEBIN)\TestProgram.exe +!ELSE +TARGETS = $(CDEVLIB)\TestService.lib $(BASEBIN)\TestProgram.exe +!ENDIF + +targets : $(TARGETS) + +$(CDEVLIB)\TestService.dll : $(OBJDIR)\TestService.obj + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib\ + $(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $? + -@copy $@ $(CDEVSHOBJ)\$(CDEVVERSION)\$(@F) > nul + @echo ^ ^ ^ ^ ^ ^ Done... + +$(CDEVLIB)\TestService.lib : $(OBJDIR)\TestService.obj + @echo ^ ^ ^ =^> Linking $(@F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib\ + $(LINK_LIB_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ Done... + +$(BASEBIN)\TestProgram.exe : .exec\$(TARGETDIR)\TestProgram.obj + -@if exist $@ erase $@ + @echo ^ ^ ^ ^ ^ ^ =^> Linking $(@F) + $(LINK) $(CDEVLIB)\cdev.lib $(CDEVLIB)\cdevGenericServer.lib\ + $(LINK_EXE_FLAGS) /out:$@ $? + @echo ^ ^ ^ ^ ^ ^ ^ ^ ^ Done... + diff --git a/extensions/cdevGenericServer/tests/TransmissionTest/TestProgram.cc b/extensions/cdevGenericServer/tests/TransmissionTest/TestProgram.cc new file mode 100755 index 0000000..09538e7 --- /dev/null +++ b/extensions/cdevGenericServer/tests/TransmissionTest/TestProgram.cc @@ -0,0 +1,179 @@ +#include +#include + +#include +#include +#include +#include +#include +#include + +int fouled = 0; +int expectedHits = 0; +int hits = 0; +unsigned totalCount = 0; + +void callback ( int status, void * arg, cdevRequestObject &, cdevData & data) + { + hits++; + if(status!=CDEV_SUCCESS) + { + printf("ERROR: Transmission failure of %i\n", (int)arg); + } + else + { + if(data!=*TestMessage[(int)arg].getData()) + { + fouled = 1; + printf("ERROR: Mismatch on entry %i - Inbound data differs from expected\n", + (int)arg); + printf("----------------------------- INBOUND DATA -----------------------------\n"); + data.asciiDump(); + printf("----------------------------- EXPECTED DATA ----------------------------\n"); + TestMessage[(int)arg].getData()->asciiDump(); + } + else + { + totalCount++; + if(totalCount%100==0) + { + printf("Transmission %i still matches correctly\n", totalCount); + } + } + } + } + + +int main(int argc, char ** argv) +{ +createTestMessages(); +int maxCount = 0; +int group1 = TestMessageCount/3; +int group2 = group1+group1; + +cdevRequestObject &tReq = cdevRequestObject::attachRef(TestMessage[TestMessageIndex].getDeviceList()[0], TestMessage[TestMessageIndex].getMessage()); +tReq.setContext(*TestMessage[0].getContext()); + +if(argc>1) maxCount = atoi(argv[1]); + +while(!fouled && (!maxCount || maxCountsetContext(*TestMessage[TestMessageIndex].getContext()); + + if(req->send(TestMessage[TestMessageIndex].getData(), &data)==CDEV_SUCCESS) + { + if(data!=*TestMessage[TestMessageIndex].getData()) + { + fouled = -1; + printf("ERROR: Mismatch on entry %i - Inbound data differs from expected\n", + TestMessageIndex); + printf("----------------------------- INBOUND DATA -----------------------------\n"); + data.asciiDump(); + printf("----------------------------- EXPECTED DATA ----------------------------\n"); + TestMessage[TestMessageIndex].getData()->asciiDump(); + } + else + { + totalCount++; + if(totalCount%100==0) + { + printf("Transmission %i still matches correctly\n", totalCount); + } + } + } + else { + printf("ERROR: Transmission failure of %i\n", + TestMessageIndex); + } + } + + for( ; TestMessageIndexsetContext(*TestMessage[TestMessageIndex].getContext()); + + if(req->sendCallback(TestMessage[TestMessageIndex].getData(), cb)!=CDEV_SUCCESS) + { + fouled = -1; + printf("ERROR: Transmission failure of %i\n", + TestMessageIndex); + } + else expectedHits++; + } + + for(int retryCnt=0; hitssetContext(*TestMessage[TestMessageIndex].getContext()); + + if(req->sendNoBlock(TestMessage[TestMessageIndex].getData(), outputData[dataIdx])!=CDEV_SUCCESS) + { + fouled = -1; + printf("ERROR: Transmission failure of %i\n", + TestMessageIndex); + } + } + group.end(); + + for(int grpRetryCnt=0; !group.allFinished() && grpRetryCnt<1000; grpRetryCnt++) + { + group.poll(); + } + + if(!group.allFinished()) + { + printf("ERROR: Failed to process all group requests after %i attempts\n", grpRetryCnt); + } + + for(dataIdx=0, TestMessageIndex=group2; TestMessageIndexasciiDump(); + } + else + { + totalCount++; + if(totalCount%100==0) + { + printf("Transmission %i still matches correctly\n", totalCount); + } + } + } + delete [] outputData; + } +return 1; +} diff --git a/extensions/cdevGenericServer/tests/TransmissionTest/TestServer.cc b/extensions/cdevGenericServer/tests/TransmissionTest/TestServer.cc new file mode 100755 index 0000000..7e6f304 --- /dev/null +++ b/extensions/cdevGenericServer/tests/TransmissionTest/TestServer.cc @@ -0,0 +1,160 @@ +#include +#include + +class myServer : public cdevServer +{ +private: + IntHash TestIndexes; + unsigned totalCount; + +public: + myServer ( void ) + : cdevServer(), totalCount(0) + { + } + + myServer ( char * domain, char * server, unsigned int port, double pulse ) + : cdevServer(domain, server, port, pulse), totalCount(0) + { + } + + virtual void processMessages ( void ) + { + cdevMessage * message; + while(dequeue(message)==0) + { + if(!strcmp(message->getMessage(), "register")) + { + int * ptr = new int; + TestIndexes.insert((int)message->getClientID(), (void *)ptr); + printf("Starting Testing on Client %i\n", message->getClientID()); + } + else if(!strcmp(message->getMessage(), "unregister")) + { + int * ptr = NULL; + if((ptr = (int *)TestIndexes.find((int)message->getClientID()))!=NULL) + { + TestIndexes.remove((int)message->getClientID()); + delete ptr; + } + printf("Finishing Testing on Client %i\n", message->getClientID()); + } + else + { + int ptr = 0; + int *idxPtr = (int *)TestIndexes.find((int)message->getClientID()); + int curPtr = 0; + + if(idxPtr == NULL) + { + printf("ERROR: Failed to retrieve the index for client %i\n", message->getClientID()); + idxPtr = &ptr; + } + if(*idxPtr >= TestMessageCount) *idxPtr = 0; + + if(message->getData()==NULL) + { + printf("ERROR: NULL data received from client %i\n", message->getClientID()); + } + else + { + message->getData()->get("packetNumber", &curPtr); + if(curPtr!=*idxPtr) + { + printf("Mismatch between packet number %i and expected %i\n", curPtr, *idxPtr); + *idxPtr = curPtr; + } + + int mismatch = 0; + + if(strcmp(message->getDeviceList()[0], TestMessage[*idxPtr].getDeviceList()[0])) + { + printf("ERROR: Client %i mismatch on entry %i - Device \"%s\" not equal to \"%s\"\n", + message->getClientID(), + *idxPtr, + message->getDeviceList()[0], + TestMessage[*idxPtr].getDeviceList()[0]); + mismatch++; + } + + if(strcmp(message->getMessage(), TestMessage[*idxPtr].getMessage())) + { + printf("ERROR: Client %i mismatch on entry %i - Message \"%s\" not equal to \"%s\"\n", + message->getClientID(), + *idxPtr, + message->getMessage(), + TestMessage[*idxPtr].getMessage()); + mismatch++; + } + + if(message->getData()==NULL) + { + printf("ERROR: Client %i mismatch on entry %i - Inbound data is NULL\n", + message->getClientID(), + *idxPtr); + mismatch++; + } + else if(*message->getData()!=*TestMessage[*idxPtr].getData()) + { + printf("ERROR: Client %i mismatch on entry %i - Inbound data differs from expected\n", + message->getClientID(), + *idxPtr); + printf("----------------------------- INBOUND DATA -----------------------------\n"); + message->getData()->asciiDump(); + printf("----------------------------- EXPECTED DATA ----------------------------\n"); + TestMessage[*idxPtr].getData()->asciiDump(); + mismatch++; + } + + if(message->getContext()==NULL && TestMessage[*idxPtr].getContext()!=NULL) + { + printf("ERROR: Client %i mismatch on entry %i - Inbound context is NULL\n", + message->getClientID(), + *idxPtr); + mismatch++; + } + else if(TestMessage[*idxPtr].getContext()==NULL) + { + } + else if(*message->getContext()!=*TestMessage[*idxPtr].getContext()) + { + printf("ERROR: Client %i mismatch on entry %i - Inbound context differs from expected\n", + message->getClientID(), + *idxPtr); + printf("---------------------------- INBOUND CONTEXT ---------------------------\n"); + message->getContext()->asciiDump(); + printf("---------------------------- EXPECTED CONTEXT --------------------------\n"); + TestMessage[*idxPtr].getContext()->asciiDump(); + mismatch++; + } + + if(mismatch) printf("\n\n"); + else { + totalCount++; + if(totalCount%1000==0) printf("Transmission %i still matches correctly\n", totalCount); + } + (*idxPtr)++; + } + } + enqueue(message); + delete message; + } + } +}; + +int main(int argc, char ** argv) +{ +char * name; +short port; + +name = (argc>1)?argv[1]:(char *)"TestServer1"; +port = 0; + +cdevSystem::defaultSystem().setThreshold(CDEV_SEVERITY_INFO); +myServer *server = new myServer(); +server->startServer("TEST", name, port, 60.0, 1); +createTestMessages(); +cdevServer::runServer(); +delete server; +return 0; +} diff --git a/extensions/cdevGenericServer/tests/TransmissionTest/TestService.cc b/extensions/cdevGenericServer/tests/TransmissionTest/TestService.cc new file mode 100755 index 0000000..6c49e77 --- /dev/null +++ b/extensions/cdevGenericServer/tests/TransmissionTest/TestService.cc @@ -0,0 +1,17 @@ +#include + +extern "C" cdevService * newTestService ( char * name, cdevSystem * system ) + { + return new TestService(name, *system); + } + +TestService::TestService ( char * name, cdevSystem & system) + : cdevClientService("TEST", name, system) + { + system.reportError(CDEV_SEVERITY_INFO, "TestService", NULL, + "Constructing a new TestService"); + } + +TestService::~TestService ( void ) + { + } diff --git a/extensions/cdevGenericServer/tests/TransmissionTest/TestService.ddl b/extensions/cdevGenericServer/tests/TransmissionTest/TestService.ddl new file mode 100755 index 0000000..b1122b6 --- /dev/null +++ b/extensions/cdevGenericServer/tests/TransmissionTest/TestService.ddl @@ -0,0 +1,30 @@ +service Test + { + tags {server} + } + +class Tests + { + verbs {get, set} + attributes + { + default Test; + clientID Test; + servers Test; + connections Test; + attrib Test {server=TestServer1}; + ClientInfo Test {server=TestServer1}; + ServerInfo Test {server=TestServer1}; + } + messages + { + shutdown Test; + } + } + + +Tests : + device1, + device2, + device3 +; diff --git a/extensions/cdevGenericServer/tests/TransmissionTest/TestService.h b/extensions/cdevGenericServer/tests/TransmissionTest/TestService.h new file mode 100755 index 0000000..5816dd6 --- /dev/null +++ b/extensions/cdevGenericServer/tests/TransmissionTest/TestService.h @@ -0,0 +1,17 @@ +#include + +#ifndef TEST_SERVICE_API + #define TEST_SERVICE_API +#endif + + +extern "C" TEST_SERVICE_API cdevService * newTestService ( char * name, cdevSystem * system ); + +class TestService : public cdevClientService +{ +public: + TestService ( char * name, cdevSystem & system = cdevSystem::defaultSystem()); + +protected: + virtual ~TestService ( void ); +}; diff --git a/extensions/cdevGenericServer/tests/TransmissionTest/cdevTagTable.txt b/extensions/cdevGenericServer/tests/TransmissionTest/cdevTagTable.txt new file mode 100755 index 0000000..f35dd28 --- /dev/null +++ b/extensions/cdevGenericServer/tests/TransmissionTest/cdevTagTable.txt @@ -0,0 +1,21 @@ +21 value +20 status +19 severity +18 time +17 units +16 displayHigh +15 displayLow +14 alarmHigh +13 alarmLow +12 warningHigh +11 warningLow +10 controlHigh +9 controlLow +8 bitMask +7 file +6 class +5 device +4 message +3 verb +2 attribute +1 collection diff --git a/extensions/cdevGenericServer/tests/TransmissionTest/testMessages.cc b/extensions/cdevGenericServer/tests/TransmissionTest/testMessages.cc new file mode 100755 index 0000000..eb0b84f --- /dev/null +++ b/extensions/cdevGenericServer/tests/TransmissionTest/testMessages.cc @@ -0,0 +1,45 @@ +#include +#include + +const size_t TestMessageCount = 1000; +cdevMessage TestMessage[TestMessageCount]; +char *TestDeviceName = "device1"; +int TestMessageIndex = 0; + +void createTestMessages ( void ) +{ +cdevData data; +cdevData context; + +for(int i=0; i> ../../../lib/itcl/pkgIndex.tcl + +clean: + @rm -rf *.o *.a *.sl *~ core ish + + +breakit: breakit.o + CC -o $@ breakit.o -L$(CDEV)/lib/$(TARGETDIR) -lcdev -ll -ly -lm diff --git a/extensions/tcl/README.txt b/extensions/tcl/README.txt new file mode 100755 index 0000000..c9c2d8b --- /dev/null +++ b/extensions/tcl/README.txt @@ -0,0 +1,55 @@ +// ***************************************************************************** +// * Tcl/Tk Interface to cdev +// ***************************************************************************** + +1) All communication is through strings, the cdevdata object takes care of + all conversion. + +2) Use a 'get' in your client code, 'find' will not do type conversions. + + +3) syntax: + + cdev $service $message "$tag1 $val1" "$tag2 $val2" ... + + or + + cdev $service $message "$tag1 $val1" "$tag2 $val2" $cb + + + where: + $service is any cdev service, i.e. "model", "IPM1A01" + $message a message to that device, i.e "get elements" + + the rest of the arguments are list of length 2 with the + first entry the tag name, and the second the tag value. + + If the length of the last list is 1 the cdev routine + sendCallback is used instead of the synchronous send. + + The result of the call will appear in the tcl array "$Control($cb)" + in due time. + + On return only the 'value' tag will be converted into a tcl result, + arbitrary dimensional results are handled. + + +Error handling: + See code for 'status' and 'severity' tag handling, this will be + superseded by real cdev errorhandler interface + +Bugs: + Cannot send space delimited string since the interface will parse + these up as char**'s + +examples: + + cdev IPM1S01 "get XPOS" + + cdev IPM1S01 "monitorOn XPOS" IPM1S01.XPOS + results appear in $Control(IPM1S01.XPOS) + + cdev model "get elements" "value quads" "section {arc1 arc2 arc3}" + value is char* + section is char** length 3 + diff --git a/extensions/tcl/blt.h b/extensions/tcl/blt.h new file mode 100755 index 0000000..0e90fb3 --- /dev/null +++ b/extensions/tcl/blt.h @@ -0,0 +1,79 @@ +/* + * blt.h -- + * + * Copyright 1993-1994 by AT&T Bell Laboratories. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and warranty + * disclaimer appear in supporting documentation, and that the + * names of AT&T Bell Laboratories any of their entities not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * AT&T disclaims all warranties with regard to this software, including + * all implied warranties of merchantability and fitness. In no event + * shall AT&T be liable for any special, indirect or consequential + * damages or any damages whatsoever resulting from loss of use, data + * or profits, whether in an action of contract, negligence or other + * tortuous action, arising out of or in connection with the use or + * performance of this software. + * + */ + +#ifndef _BLT_H +#define _BLT_H + +#ifndef _ANSI_ARGS_ +# define _ANSI_ARGS_(x) () +#endif + +#define BLT_MAJOR_VERSION 2 +#define BLT_MINOR_VERSION 1 + +typedef enum { + BLT_VECTOR_NOTIFY_UPDATE=1, /* The vector's values has been updated */ + BLT_VECTOR_NOTIFY_DESTROY=2 /* The vector has been destroyed and the client + * should no longer use its data (calling + * Blt_FreeVectorId) */ +} Blt_VectorNotify; + +typedef void (Blt_VectorChangedProc) _ANSI_ARGS_((Tcl_Interp *interp, + ClientData clientData, Blt_VectorNotify notify)); + +//typedef struct Blt_VectorId *Blt_VectorId; +typedef struct Blt_VectorId; + +typedef struct { + double *valueArr; /* Array of values (possibly malloc-ed) */ + int numValues; /* Number of values in the array */ + int arraySize; /* Size (in values) of the allocated space */ + double min, max; /* Minimum and maximum values in the vector */ + int reserved; /* Reserved for future use */ +} Blt_Vector; + +extern "C" Blt_VectorId Blt_AllocVectorId _ANSI_ARGS_((Tcl_Interp *interp, + char *vecName)); +extern "C" void Blt_SetVectorChangedProc _ANSI_ARGS_((Blt_VectorId clientId, + Blt_VectorChangedProc * proc, ClientData clientData)); +extern "C" void Blt_FreeVectorId _ANSI_ARGS_((Blt_VectorId clientId)); +extern "C" int Blt_GetVectorById _ANSI_ARGS_((Tcl_Interp *interp, + Blt_VectorId clientId, Blt_Vector *vecPtr)); +extern "C" char *Blt_NameOfVectorId _ANSI_ARGS_((Blt_VectorId clientId)); +extern "C" int Blt_VectorNotifyPending _ANSI_ARGS_((Blt_VectorId clientId)); + +extern "C" int Blt_CreateVector _ANSI_ARGS_((Tcl_Interp *interp, char *vecName, + int size, Blt_Vector *vecPtr)); +extern "C" int Blt_GetVector _ANSI_ARGS_((Tcl_Interp *interp, char *vecName, + Blt_Vector *vecPtr)); +extern "C" int Blt_VectorExists _ANSI_ARGS_((Tcl_Interp *interp, char *vecName)); +extern "C" int Blt_ResetVector _ANSI_ARGS_((Tcl_Interp *interp, char *vecName, + Blt_Vector *vecPtr, Tcl_FreeProc *freeProc)); +extern "C" int Blt_ResizeVector _ANSI_ARGS_((Tcl_Interp *interp, char *vecName, + int newSize)); +extern "C" int Blt_DeleteVector _ANSI_ARGS_((Tcl_Interp *interp, char *vecName)); + +extern "C" int Blt_Init _ANSI_ARGS_((Tcl_Interp *interp)); + + +#endif /*_BLT_H*/ diff --git a/extensions/tcl/cdevtcl.doc b/extensions/tcl/cdevtcl.doc new file mode 100755 index 0000000..6b6017e --- /dev/null +++ b/extensions/tcl/cdevtcl.doc @@ -0,0 +1,57 @@ +Interface tcl to cdev + + +Features: + Access all of cdev world from within the tcl shells. + Handle arbitrary cdevData tag/value pairs + Handle arbitrary cdevData arrays + Handle synchronous get/set + Handle asynchronous get/set/monitors + Set cdev context + +Implementation: + Dynamically loadable module including all of cdev library for tcl7.5 + Polls cdev 5 time a second + Soon: Install cdev filedescriptors in tcl select list + + +Important note: All communication is through strings, the cdevdata object takes care of all conversion. + Cdev service writers: Use a 'get' in your client code, 'find' will not do type conversions. + +syntax: + +cdev $service $message "$tag1 $val1" "$tag2 $val2" ... + Where $service is any cdev service, i.e. "model" or "IPM1A01" + and $message a message to that device, i.e "get elements" or "get XPOS" + the rest of the arguments are list of length 2 with the first entry the tag name, and the second the tag value. + List of length > 2 are handled as tag/string with spaces. + +or + +cdev $service $message "$tag1 $val1" "$tag2 $val2" $cb + The message is send asynchronously. + The result of the call will appear in the tcl array "$Control($cb)" in due time. + +Return tags: + On return the 'value' tag will be converted into a tcl result, arbitrary dimensional results are handled. + Arbitrary tags will be converted using the -tags {$tag $tag2 ...} option + +Context: + The context can be accessed by -context "$tag $value" ... + all tag/value pairs after the context switch will be put in the context + +Error handling: + See code for 'status' and 'severity' tag handling, this will be superseded by proper cdev errorhandler interface + +examples: + + cdev IPM1S01 "get XPOS" + + cdev lockarc1 "set status" "value Waiting for Beam" + the status is set to the string "Waiting for Beam" + + cdev IPM1S01 "monitorOn XPOS" IPM1S01.XPOS + results appear in Control(IPM1S01.XPOS) + + cdev model "get elements" "value Quadrupoles" "section {arc1 arc2 arc3}" + diff --git a/extensions/tcl/pkgIndex.tcl b/extensions/tcl/pkgIndex.tcl new file mode 100755 index 0000000..4bb0353 --- /dev/null +++ b/extensions/tcl/pkgIndex.tcl @@ -0,0 +1 @@ +package ifneeded Cdev 1.3 "load [file join $dir libtclcdev.sl] Cdev" diff --git a/extensions/tcl/tcl_cdev.cc b/extensions/tcl/tcl_cdev.cc new file mode 100755 index 0000000..b7a69bd --- /dev/null +++ b/extensions/tcl/tcl_cdev.cc @@ -0,0 +1,800 @@ +// a CDEV access interface for tcl +// Johannes van Zeijts, March 95, first version +// May 95, second version, using Walt Akers callback example +// Dec 95, added arbitrary dimensional array output and context +// Jan 96, added handling of strings with spaces +// Aug 96, deleted callbackinfo when we are not monitoring +// Aug 96, converted to tcl7.5 +// Nov 1, 96, moved to cdev 1.4 +// March, 97, overhaul, allowed multiple devices + +/* Output formatting + Attention given to 'Strings with spaces' which have special meaning in tcl + +#devices = 1 + +#tags = 0 (only value tag) + + dim = 0 1 + String + String with spaces + + dim = 1 1 1 1 + St1 St2 St3 + {St w sp1} {St w sp2} {St w sp3} + + dim = 2 {11 12 13} {21 22 23} + {st1 st2 st3} {...} + {{st w sp1} {st w sp2} {st w sp3}} { ...} + + + + +#tags > 0 (value tag + other tags) + Each tag in its own list index + Result is always list of length (#tags + 1) + + + dim = 0 + 1 + St1 + {St w sp1} + + + dim = 1 + {1 1 1} + {St1 St2 St3} + {{St w sp1} {St w sp2} {St w sp3}} + + + dim = 2 + {{1 1 1} {1 1 1}} + {{{st w sp1} {st w sp2} {st w sp3}} {{st w sp1} {st w sp2} {st w sp3}}} + + +--------------------------------------------------------------------------------------- +#devices > 1 , + +#tags = 0 + dim = 0 1 1 1 + {str w sp} {str w sp} + + dim = 1 {1 1 1} {1 1 1} + {{str w sp} ..} { } + + +#tags > 0 + dim = 0 {0 1 2} {0 1 2} + + dim = 1 {{1 1 1} {1 1 1}} + +*/ + +#include + +#include +#include +#include +#include +#include + +// cdev includes +#include +#include +#include +#include +#include + +static int VALUE_TAG_ID =- 1; +#define VALUE_TAG ((VALUE_TAG_ID<0 && cdevData::tagC2I("value", &VALUE_TAG_ID)!= CDEV_SUCCESS)?-1:VALUE_TAG_ID) +static int STATUS_TAG_ID =- 1; +#define STATUS_TAG ((STATUS_TAG_ID<0 && cdevData::tagC2I("status", &STATUS_TAG_ID)!= CDEV_SUCCESS)?-1:STATUS_TAG_ID) +static int SEVERITY_TAG_ID =- 1; +#define SEVERITY_TAG ((SEVERITY_TAG_ID<0 && cdevData::tagC2I("severity", &SEVERITY_TAG_ID)!= CDEV_SUCCESS)?-1:SEVERITY_TAG_ID) + +static int cdevdebug = 0; + +class tclCdevData { + public: + tclCdevData(); + void parse(Tcl_Interp*, char* *, int); + ~tclCdevData(); + + cdevData out, context; + int hascontext; + + int tagn, *taglist; + char *callbacktag; + + int state, async; +} +; + +tclCdevData::~tclCdevData() { + delete taglist; +} + +tclCdevData::tclCdevData():hascontext(0), tagn(0), taglist(NULL), async(0), state(TCL_ERROR) { +} +; +// Parses command line, fills up the outgoing cdevData and the context (if any) +void tclCdevData::parse(Tcl_Interp *interp, char **argv, int argc) { + int i, c1, c2; + cdevData *ptr; + char **s1 = NULL; + char **s2 = NULL; + + // Point to 'out' cdevData until we hit the context (if any) + ptr = &out; + for(i = 3; i < argc; i++) { + // skip 'cdev' '$device' and '$message' + if(Tcl_SplitList(interp, argv[i], &c1, &s1) != TCL_OK) { + return; + } + if(c1 == 2) { + // {tag value} pair, check if the value is a scalar + if(Tcl_SplitList(interp, s1[1], &c2, &s2) != TCL_OK) { + free((char *) s1); + return; + } + if(c2 == 1) { + // we have a scalar + ptr->insert(s1[0], s1[1]); + // insert scalar + } + else { + ptr->insert(s1[0], s2, c2); + // insert vector of scalars, does not handle matrices + } + free((char *) s2); + } + else if(c1 == 1) { + // can be one of "-context" , "-tags" or a callbacktag + if(strcmp(argv[i], "-context") == 0) { + // all remaining 'tag value' pairs go in the context + ptr = &context; + hascontext = 1; + } + else if(strcmp(argv[i], "-tags") == 0) { + // get the list of tags to print out from the result data + i++; + // points to next entry in argv + if(i == argc) { + interp->result = "expected tag names"; + free((char *) s1); + return; + } + if(Tcl_SplitList(interp, argv[i], &tagn, &s2) != TCL_OK) { + interp->result = "tag problem"; + free((char *) s1); + return; + } + else { + taglist = new int[tagn]; + for(int j = 0; j < tagn; j++) { + if(cdevData::tagC2I(s2[j], &taglist[j]) != CDEV_SUCCESS) { + interp->result = "unknown tag"; + free((char *) s2); + free((char *) s1); + return; + } + } + } + free((char *) s2); + } + else { + // single entry, a callbacktag, better be at end of input + if(i != argc-1) { + interp->result = "expecting callbacktag at end"; + free((char *) s1); + return; + } + // Here we have a callback tag, hence we want to send asynchronously + callbacktag = argv[i]; + async = 1; + } + } + else { + // c1 > 2 + // tag / string pair (i.e. "value this is a string with spaces embedded" + char **av = s1; + av++; + char *concat = Tcl_Concat(c1-1, av); + ptr->insert(s1[0], concat); + if(cdevdebug == 1) { + fprintf(stderr, "inserted: %s, with value: %s\n", s1[0], concat); + } + free(concat); + } + free((char *) s1); + } + state = TCL_OK; +} + +class callbackInfo { + public: + callbackInfo(Tcl_Interp*, char *); + callbackInfo(Tcl_Interp*, char*, char *); + ~callbackInfo(); + Tcl_Interp *interp; + char *s; + cdevCallback *callback; + + void addtags(int, int *); + + int *tags, ntags; +} +; + +callbackInfo::callbackInfo(Tcl_Interp *e, char *arg) { + interp = e; + s = new char[strlen(arg)+1]; + strcpy(s, arg); + ntags = 0; + tags = NULL; + callback = NULL; +} + +callbackInfo::callbackInfo(Tcl_Interp *e, char *arg1, char *arg2) { + interp = e; + s = new char[strlen(arg1)+strlen(arg2)+1]; + strcpy(s, arg1); + strcat(s, arg2); + ntags = 0; + tags = NULL; + callback = NULL; +} + +callbackInfo::~callbackInfo() { + delete tags; + delete s; +} + +void callbackInfo::addtags(int n, int *v) { + ntags = n; + tags = new int[n]; + for(int i = 0; i < ntags; i++) { + tags[i] = v[i]; + } + delete callback; +} + +static char cs[512]; +cdevBounds *Bounds; +int Dim; + +static int K = 0; + +void HandleLevel(char **in, int level, Tcl_DString &ds) { + int i; + for(i = 0; i < Bounds[level].length; i++) { + if(level >= Dim-1) { + Tcl_DStringAppendElement(&ds, in[K]); + K++; + } + else { + Tcl_DStringStartSublist(&ds); + HandleLevel(in, level+1, ds); + Tcl_DStringEndSublist(&ds); + } + } +} + +// Format a cdevData tag result into a tcl result +// mode == #ntags + +void HandleTag(int tag, cdevData &result, Tcl_DString &ds, int mode, int ndevices) { + int i, len; + size_t dim; + char **sp; + + if(result.getDim(tag, &dim) != CDEV_SUCCESS) { + cs[0] = NULL; + if (ndevices == 1 && mode == 0) { + Tcl_DStringAppend(&ds, cs, -1); // append an empty string + } else { + Tcl_DStringAppendElement(&ds, cs); // append an empty list + } + return; + } + + // Always retrieve the result as a char*, cdevData does the conversion for me! + + if(dim == 0) { + /* + * // put this in if we want format conversions. + * i = result.getType(tag); + * if ((i == CDEV_FLOAT) || (i == CDEV_DOUBLE)) { + * result.get(tag,&dres); + * sprintf(cs,"%.2g",dres); + * } else { + */ + cs[0] = NULL; + result.get(tag, cs, 255); + + if (mode == 0 && ndevices == 1) { + Tcl_DStringAppend(&ds,cs,-1); + } else { + Tcl_DStringAppendElement(&ds,cs); + } + return; + } + else { + // dim > 0 + Dim = (int) dim; + K = 0; + Bounds = new cdevBounds[Dim]; + result.getBounds(tag, Bounds, Dim); + len = 1; + for(i = 0; i < Dim; i++) { + len *= Bounds[i].length; + } + sp = new char*[len]; + result.get(tag, sp); + + if (mode>0 || (mode==0&&ndevices>1)) Tcl_DStringStartSublist(&ds); + HandleLevel(sp, 0, ds); + if (mode>0 || (mode==0&&ndevices>1)) Tcl_DStringEndSublist(&ds); + // append the result to a Tcl_DString + } + + delete Bounds; + while(len > 0) { + len--; + delete sp[len]; + } + delete [] sp; +} + +int Cdev_Handleresult(int *tags, int ntags, cdevData &result, Tcl_DString &ds, int ndevices) { + // assume we always return the "value" tag + + if (ndevices>1 && ntags>0) Tcl_DStringStartSublist(&ds); + + HandleTag(VALUE_TAG, result, ds, ntags, ndevices); + if(ntags > 0) { + for(int i = 0; i < ntags; i++) { + HandleTag(tags[i], result, ds, ntags, ndevices); + } + } + if (ndevices>1 && ntags>0) Tcl_DStringEndSublist(&ds); + return TCL_OK; +} + +// executes inside poll() whenever 'file' is readable +void Cdev_CallbackFunction(int, void *userarg, cdevRequestObject&, cdevData &result) { + Tcl_DString ds; + // could check status and do appropriate action like: set Error(info->s) ??? + callbackInfo *info = (callbackInfo *) userarg; + Tcl_DStringInit(&ds); + int i = Cdev_Handleresult(info->tags, info->ntags, result, ds, 1); + Tcl_SetVar2(info->interp, "Control", info->s, Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY); + Tcl_DStringFree(&ds); +} + +// same as above, plus removes callbackinfo +void Cdev_CallbackFunctionOnce(int, void *userarg, cdevRequestObject&, cdevData &result) { + Tcl_DString ds; + // have to check status and do appropriate action like: set Error(info->s) ??? + callbackInfo *info = (callbackInfo *) userarg; + Tcl_DStringInit(&ds); + int i = Cdev_Handleresult(info->tags, info->ntags, result, ds, 1); + Tcl_SetVar2(info->interp, "Control", info->s, Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY); + Tcl_DStringFree(&ds); + delete info; +} + +// Old way of polling, superseded by FileHandler calls, but since FD's are not working yet, still in use +void Cdev_UpdateProc(ClientData dummy) { + cdevSystem::defaultSystem().poll(); + Tcl_CreateTimerHandler(200, Cdev_UpdateProc, dummy); +} + +void Cdev_FileProc(ClientData, int) { + cdevSystem::defaultSystem().poll(); +} + +int CdevDebugCmd(ClientData, Tcl_Interp*, int, char* *) { + if(cdevdebug == 0) { + cdevdebug = 1; + } + else { + cdevdebug = 0; + } + return TCL_OK; +} + +void Cdev_RegisterFD(int*, Tcl_File fd, int condition) { + printf("fd callback\n"); + if(condition) { + Tcl_CreateFileHandler(fd, TCL_READABLE, Cdev_FileProc, NULL); + } + else { + Tcl_DeleteFileHandler(fd); + } +} +typedef cdevRequestObject *cdevRequestObjectPtr; + +int CdevCmd(ClientData, Tcl_Interp *interp, int argc, char **argv) { + // cdev device message {tag value} {..} cb + // cdev device message {tag value} {..} -context (tag value} {..} cb + + char **devices = NULL; + int i, n, ndevices; + Tcl_DString ds; + cdevData result; + cdevCallback *cb = NULL; + callbackInfo *info; + cdevRequestObjectPtr request, *requests; + tclCdevData data; + int delinfo = 0; + + if(argc < 3) { + Tcl_AppendResult(interp, "cdev: wrong # args", (char *) NULL); + return TCL_ERROR; + } + + ndevices = 0; + if(Tcl_SplitList(interp, argv[1], &ndevices, &devices) != TCL_OK) { + return TCL_ERROR; + } + + if(ndevices == 1) { + request = cdevRequestObject::attachPtr(argv[1], argv[2]); + free((char*)devices); + } + else { + requests = new cdevRequestObjectPtr[ndevices]; + for(n = 0; n < ndevices; n++) { + requests[n] = cdevRequestObject::attachPtr(devices[n], argv[2]); + } + } + + data.parse(interp, argv, argc); + + if(data.state != TCL_OK) { + return TCL_ERROR; + } + + if(data.async) { + // we want to sent it async + + if(ndevices == 1) { + info = new callbackInfo(interp, data.callbacktag); + if(data.tagn != 0) { + info->addtags(data.tagn, data.taglist); + } + + if(strncmp(argv[2], "monitorOn", 9) == 0) { + cb = new cdevCallback(Cdev_CallbackFunction, (void *) info); + } + else if(strncmp(argv[2], "monitorOff", 10) == 0) { + delinfo = 1; + cb = new cdevCallback(NULL, NULL); + } + else { + cb = new cdevCallback(Cdev_CallbackFunctionOnce, (void *) info); + } + + info->callback = cb; + + if(data.hascontext) { + if(cdevdebug == 1) { + cout << "Context data: " << endl; + data.context.asciiDump(stdout); + } + if(request->setContext(data.context) != CDEV_SUCCESS) { + interp->result = "setContext error"; + delete info; + return TCL_ERROR; + } + } + if(cdevdebug == 1) { + cout << argv[1] << " " << argv[2] << " OutBound data: " << endl; + data.out.asciiDump(stdout); + } + + if(request->sendCallback(data.out, *cb) != 0) { + delete info; + return TCL_ERROR; + } + else { + if(delinfo) delete info; + return TCL_OK; + } + } + else { + // ndevices > 1, send each one separately + int j = 0; + + if(strncmp(argv[2], "monitorOn", 9) == 0) { + j = 1; + } + else if(strncmp(argv[2], "monitorOff", 10) == 0) { + j = 2; + } + + for(n = 0; n < ndevices; n++) { + info = new callbackInfo(interp, devices[n], data.callbacktag); + if(data.tagn != 0) { + info->addtags(data.tagn, data.taglist); + } + if(j == 1) { + cb = new cdevCallback(Cdev_CallbackFunction, (void *) info); + } + else if(j == 2) { + delinfo = 1; + cb = new cdevCallback(NULL, NULL); + } + else { + cb = new cdevCallback(Cdev_CallbackFunctionOnce, (void *) info); + } + + info->callback = cb; + + if(data.hascontext) { + if(requests[n]->setContext(data.context) != 0) { + interp->result = "setContext error"; + delete requests; + free((char *) devices); + delete info; + return TCL_ERROR; + } + } + if(requests[n]->sendCallback(data.out, *cb) != CDEV_SUCCESS) { + delete requests; + delete info; + free((char *) devices); + return TCL_ERROR; + } + else { + if(delinfo) delete info; + } + } + delete requests; + free((char *) devices); + return TCL_OK; + } + } + + // send it sync + Tcl_DStringInit(&ds); + + if(ndevices == 1) { + if(data.hascontext) { + if(cdevdebug == 1) { + cout << "Context data: " << endl; + data.context.asciiDump(stdout); + } + if(request->setContext(data.context) != CDEV_SUCCESS) { + interp->result = "setContext error"; + return TCL_ERROR; + } + } + + if(cdevdebug == 1) { + cout << argv[1] << " " << argv[2] << " OutBound data: " << endl; + data.out.asciiDump(stdout); + } + + if(request->send(data.out, result) != CDEV_SUCCESS) { + sprintf(interp->result, "error in send: %s %s", argv[1], argv[2]); + return TCL_ERROR; + } + + if(cdevdebug == 1) { + cout << "Result data: " << endl; + result.asciiDump(stdout); + } + + if(STATUS_TAG !=- 1) { + if(result.get(STATUS_TAG, &i) == CDEV_SUCCESS) { + if(i != CDEV_SUCCESS) { + if(SEVERITY_TAG !=- 1) { + Tcl_DStringFree(&ds); + result.get(SEVERITY_TAG, cs, 255); + Tcl_DStringAppend(&ds, cs, -1); + Tcl_DStringResult(interp, &ds); + } + else { + interp->result = "cdev status != 0"; + } + return TCL_ERROR; + } + } + } + if(Cdev_Handleresult(data.taglist, data.tagn, result, ds, 1) != TCL_OK) { + interp->result = "cannot handle cdev result"; + Tcl_DStringFree(&ds); + return TCL_ERROR; + } + + Tcl_DStringResult(interp, &ds); + interp->freeProc = TCL_DYNAMIC; + } + else { + // ndevices > 1 + size_t valuedim; + int addbraces = 0; + for(n = 0; n < ndevices; n++) { + if(data.hascontext) { + if(requests[n]->setContext(data.context) != CDEV_SUCCESS) { + interp->result = "setContext error"; + delete requests; + free((char *) devices); + return TCL_ERROR; + } + } + if(requests[n]->send(data.out, result) != CDEV_SUCCESS) { + sprintf(interp->result, "error in send: %s %s", devices[n], argv[2]); + delete requests; + free((char *) devices); + return TCL_ERROR; + } + if(STATUS_TAG !=- 1) { + if(result.get(STATUS_TAG, &i) == CDEV_SUCCESS) { + if(i != CDEV_SUCCESS) { + if(SEVERITY_TAG !=- 1) { + Tcl_DStringFree(&ds); + result.get(SEVERITY_TAG, cs, 255); + Tcl_DStringAppend(&ds, cs, -1); + Tcl_DStringResult(interp, &ds); + } + else { + interp->result = "cdev status != 0"; + } + delete requests; + free((char *) devices); + return TCL_ERROR; + } + } + } + if(Cdev_Handleresult(data.taglist, data.tagn, result, ds, ndevices) != TCL_OK) { + interp->result = "cannot handle cdev result"; + Tcl_DStringFree(&ds); + return TCL_ERROR; + } + } + Tcl_DStringResult(interp, &ds); + interp->freeProc = TCL_DYNAMIC; + delete requests; + free((char *) devices); + } + return TCL_OK; +} + +int CdevDirectoryCmd(ClientData, Tcl_Interp *interp, int argc, char **argv) { + int ndevices = 0; + cdevData result; + Tcl_DString ds; + cdevCallback *cb = NULL; + callbackInfo *info; + int i; + tclCdevData data; + int delinfo = 0; + + if(argc < 3) { + Tcl_AppendResult(interp, "cdevDirectory: wrong # args", (char *) NULL); + return TCL_ERROR; + } + + if(argc < 3) { + Tcl_AppendResult(interp, "cdevDirectory: wrong # args", (char *) NULL); + return TCL_ERROR; + } + + cdevDevice &device = cdevDevice::attachRef("cdevDirectory"); + + data.parse(interp, argv-1, argc+1); + + if(data.state != TCL_OK) { + return TCL_ERROR; + } + + if(data.async) { + // we want to sent it async + + info = new callbackInfo(interp, data.callbacktag); + if(data.tagn != 0) { + info->addtags(data.tagn, data.taglist); + } + + if(strncmp(argv[2], "monitorOn", 9) == 0) { + cb = new cdevCallback(Cdev_CallbackFunction, (void *) info); + } + else if(strncmp(argv[2], "monitorOff", 10) == 0) { + delinfo = 1; + cb = new cdevCallback(NULL, NULL); + } + else { + cb = new cdevCallback(Cdev_CallbackFunctionOnce, (void *) info); + } + + info->callback = cb; + + if(cdevdebug == 1) { + cout << argv[1] << " " << argv[2] << " OutBound data: " << endl; + data.out.asciiDump(stdout); + } + + if(device.sendCallback(argv[1], data.out, *cb) != 0) { + delete info; + return TCL_ERROR; + } + else { + if(delinfo) delete info; + return TCL_OK; + } + } + // send it sync + Tcl_DStringInit(&ds); + + if(cdevdebug == 1) { + cout << argv[1] << " " << argv[2] << " OutBound data: " << endl; + data.out.asciiDump(stdout); + } + + if(device.send(argv[1], data.out, result) != CDEV_SUCCESS) { + sprintf(interp->result, "error in send: %s", argv[1]); + return TCL_ERROR; + } + + if(cdevdebug == 1) { + cout << "Result data: " << endl; + result.asciiDump(stdout); + } + + if(STATUS_TAG !=- 1) { + if(result.get(STATUS_TAG, &i) == CDEV_SUCCESS) { + if(i != CDEV_SUCCESS) { + if(SEVERITY_TAG !=- 1) { + Tcl_DStringFree(&ds); + result.get(SEVERITY_TAG, cs, 255); + Tcl_DStringAppend(&ds, cs, -1); + Tcl_DStringResult(interp, &ds); + } + else { + interp->result = "cdev status != 0"; + } + return TCL_ERROR; + } + } + } + + if(Cdev_Handleresult(data.taglist, data.tagn, result, ds, 1) != TCL_OK) { + interp->result = "cannot handle cdev result"; + Tcl_DStringFree(&ds); + return TCL_ERROR; + } + + Tcl_DStringResult(interp, &ds); + interp->freeProc = TCL_DYNAMIC; + + return TCL_OK; +} + +extern"C"int Cdev_Init(Tcl_Interp *interp) { + + // int i,fd[20],numFD = 20; + // System.getFd(fd, numFD); + // for (i=0;i +#include "blt.h" + +#include +#include +#include +#include +#include + +// cdev includes +#include +#include +#include +#include +#include + +static int VALUE_TAG_ID =- 1; +#define VALUE_TAG ((VALUE_TAG_ID<0 && cdevData::tagC2I("value", &VALUE_TAG_ID)!= CDEV_SUCCESS)?-1:VALUE_TAG_ID) +static int STATUS_TAG_ID =- 1; +#define STATUS_TAG ((STATUS_TAG_ID<0 && cdevData::tagC2I("status", &STATUS_TAG_ID)!= CDEV_SUCCESS)?-1:STATUS_TAG_ID) +static int SEVERITY_TAG_ID =- 1; +#define SEVERITY_TAG ((SEVERITY_TAG_ID<0 && cdevData::tagC2I("severity", &SEVERITY_TAG_ID)!= CDEV_SUCCESS)?-1:SEVERITY_TAG_ID) + +typedef cdevRequestObject *cdevRequestObjectPtr; + +// class DeviceEntry { +// public: +// DeviceEntry(char*); +// ~DeviceEntry(); +// +// cdevRequestObject *request; +// cdevData result; +// int status; +// }; + + +class TclCdevCollection { +public: + TclCdevCollection(int, char**); + ~TclCdevCollection(); + + char *getAttrib(); + void setAttrib(char*); + + void getDevices(Tcl_Interp *); + void getStatus(Tcl_Interp *); + void getResult(Tcl_Interp *); + void getCallback(Tcl_Interp *); + int getLength() { return ndevices;} + void getVector(double*); + + static void deleteCollection(ClientData); + + int send(); + int sendCallback(Tcl_Interp*, char*); + int checkCallback(); + + static void callbackFunction(int, void *, cdevRequestObject&, cdevData &); + static void TimerHandler(ClientData); + +private: + cdevRequestObjectPtr *requests; + cdevData *results; + char **devices; + int ndevices; + char *attrib; + int *status, *callbacks; +}; + +TclCdevCollection::TclCdevCollection(int n, char** s) : ndevices(0), devices(NULL), attrib(NULL) { + if (n < 0) return; + + ndevices = n; + devices = new char*[ndevices]; + for (int i = 0; iptr; + c->status[info->index] = stat; + c->results[info->index] = result; + c->callbacks[info->index] = 1; +} + +int TclCdevCollection::checkCallback() { + int stat = 0; + for (int i = 0; i < ndevices; i++) { + if (callbacks[i] == 0) return 0; + } + return 1; +} + +void TclCdevCollection::TimerHandler(ClientData dummy) { + cdevSystem::defaultSystem().poll(); + callbackInfo2 *info = (callbackInfo2 *) dummy; + if (info->ptr->checkCallback()) { + // set something + Tcl_SetVar2(info->interp, "Control", info->s, "1", TCL_GLOBAL_ONLY); + delete info; + } else { /// try again later + Tcl_CreateTimerHandler(50, TclCdevCollection::TimerHandler, dummy); + } +} + +void TclCdevCollection::setAttrib(char* a) { + char message[256]; + delete attrib; + attrib = new char[strlen(a)+1]; + strcpy(attrib, a); + strcpy(message,"get "); + strcat(message, attrib); + for(int i = 0; i < ndevices; i++) { + requests[i] = cdevRequestObject::attachPtr(devices[i], message); + } +} + +char* TclCdevCollection::getAttrib() { + return attrib; +} + +void TclCdevCollection::getDevices(Tcl_Interp *interp) { + int i; + for (i = 0; i < ndevices; i++) { + Tcl_AppendElement(interp, devices[i]); + } +} + +void TclCdevCollection::getStatus(Tcl_Interp *interp) { + int i; + char res[256]; + for (i = 0; i < ndevices; i++) { + sprintf(res, "%d", status[i]); + Tcl_AppendElement(interp, res); + } +} + +void TclCdevCollection::getCallback(Tcl_Interp *interp) { + int i; + char res[256]; + for (i = 0; i < ndevices; i++) { + sprintf(res, "%d", callbacks[i]); + Tcl_AppendElement(interp, res); + } +} + +void TclCdevCollection::getResult(Tcl_Interp *interp) { + int i; + char res[300]; + for (i = 0; i < ndevices; i++) { + results[i].get(VALUE_TAG, res, 255); + Tcl_AppendElement(interp, res); + } +} + +void TclCdevCollection::getVector(double *res) { + for (int i = 0; i < ndevices; i++) { + results[i].get(VALUE_TAG, &res[i]); + } +} + +int TclCdevCollection::send() { + int stat = CDEV_SUCCESS; + int i; + for (i = 0; i < ndevices; i++) { + results[i].remove(); + status[i] = requests[i]->send(NULL, results[i]); + if ((status[i] != CDEV_SUCCESS) && (stat == CDEV_SUCCESS)) { + stat = CDEV_ERROR; + } + } + return stat; +} + +int TclCdevCollection::sendCallback(Tcl_Interp* interp, char* v) { + int stat = CDEV_SUCCESS; + for (int i = 0; i < ndevices; i++) { + results[i].remove(); + callbacks[i] = 0; + callbackInfo1* info1 = new callbackInfo1(this, i); + cdevCallback* cb = new cdevCallback(TclCdevCollection::callbackFunction, (void *) info1); + status[i] = requests[i]->sendCallback(NULL, *cb); + if ((status[i] != CDEV_SUCCESS) && (stat == CDEV_SUCCESS)) { + stat = CDEV_ERROR; + } + } + callbackInfo2 *info2 = new callbackInfo2(interp, this, v); + Tcl_SetVar2(interp, "Control", v, "0", TCL_GLOBAL_ONLY); + Tcl_CreateTimerHandler(50, TclCdevCollection::TimerHandler, (ClientData) info2); + return stat; +} + +void TclCdevCollection::deleteCollection(ClientData clientData) { + TclCdevCollection *collectionPtr; + collectionPtr = (TclCdevCollection *) clientData; + delete collectionPtr; +} + +int CollectionCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ + TclCdevCollection *collectionPtr; + collectionPtr = (TclCdevCollection *) clientData; + + if (strcmp(argv[1], "get") == 0) { + if (argc == 2) { // send it out to cdev // get + if (collectionPtr->getAttrib() == NULL) { + interp->result = "did not set attrib"; + return TCL_ERROR; + } + if (collectionPtr->send() == CDEV_SUCCESS) { + collectionPtr->getResult(interp); + return TCL_OK; + } + interp->result = "encountered cdev error"; + return TCL_ERROR; + } + if (strcmp(argv[2], "attrib") == 0) { // get attrib + Tcl_SetResult(interp, collectionPtr->getAttrib(), TCL_STATIC); + return TCL_OK; + } + if (strcmp(argv[2], "devices") == 0) { // get devices + collectionPtr->getDevices(interp); + return TCL_OK; + } + if (strcmp(argv[2], "status") == 0) { // get status + collectionPtr->getStatus(interp); + return TCL_OK; + } + if (strcmp(argv[2], "callback") == 0) { // get status + collectionPtr->getCallback(interp); + return TCL_OK; + } + if (strcmp(argv[2], "vector") == 0) { // get vector + if (argc != 4) return TCL_ERROR; + Blt_Vector vecInfo; + + if (!Blt_VectorExists(interp, argv[3])) { + interp->result = "vector does not exist"; + return TCL_ERROR; + } + if (collectionPtr->send() != CDEV_SUCCESS) { + interp->result = "encountered cdev error"; + return TCL_ERROR; + } + if (vecInfo.arraySize < collectionPtr->getLength()) { // resize if necc. + if (Blt_ResizeVector(interp, argv[3], collectionPtr->getLength()) != TCL_OK) return TCL_ERROR; + } + + if (Blt_GetVector(interp, argv[3], &vecInfo) != TCL_OK) return TCL_ERROR; + + vecInfo.numValues = collectionPtr->getLength(); + vecInfo.valueArr = (double *) malloc(sizeof(double) * collectionPtr->getLength()); + + collectionPtr->getVector(vecInfo.valueArr); + if (Blt_ResetVector(interp, argv[3], &vecInfo, TCL_DYNAMIC) != TCL_OK) { + return TCL_ERROR; + } + return TCL_OK; + } + } + + if (strcmp(argv[1], "set") == 0) { + if (argc != 4) return TCL_ERROR; + if (strcmp(argv[2], "attrib") == 0) { // set attrib $value + collectionPtr->setAttrib(argv[3]); + return TCL_OK; + } + } + + if (strcmp(argv[1], "sendcallback") == 0) { + if (strcmp(argv[2], "vector") == 0) { // sendcallback vector $v + if (argc != 4) return TCL_ERROR; + Blt_Vector vecInfo; + + if (!Blt_VectorExists(interp, argv[3])) { + interp->result = "vector does not exist"; + return TCL_ERROR; + } + if (collectionPtr->sendCallback(interp, argv[3]) != CDEV_SUCCESS) { + interp->result = "encountered cdev error"; + return TCL_ERROR; + } + return TCL_OK; + } + return TCL_ERROR; + } + + if (strcmp(argv[1], "checkcallback") == 0) { + if (collectionPtr->checkCallback()) { + interp->result = "1"; + } else { + interp->result = "0"; + } + return TCL_OK; + } + + if (strcmp(argv[1], "getcallback") == 0) { + if (strcmp(argv[2], "vector") == 0) { // getcallback vector $v + if (argc != 4) return TCL_ERROR; + Blt_Vector vecInfo; + + if (!Blt_VectorExists(interp, argv[3])) { + interp->result = "vector does not exist"; + return TCL_ERROR; + } + + if (!collectionPtr->checkCallback()) { + interp->result = "callbacks not ready"; + return TCL_ERROR; + } + + if (vecInfo.arraySize < collectionPtr->getLength()) { // resize if necc. + if (Blt_ResizeVector(interp, argv[3], collectionPtr->getLength()) != TCL_OK) return TCL_ERROR; + } + + if (Blt_GetVector(interp, argv[3], &vecInfo) != TCL_OK) return TCL_ERROR; + + vecInfo.numValues = collectionPtr->getLength(); + vecInfo.valueArr = (double *) malloc(sizeof(double) * collectionPtr->getLength()); + + collectionPtr->getVector(vecInfo.valueArr); + if (Blt_ResetVector(interp, argv[3], &vecInfo, TCL_DYNAMIC) != TCL_OK) { + return TCL_ERROR; + } + return TCL_OK; + } + } + + interp->result = "unknown command"; + return TCL_ERROR; +} + +int MakeCollectionCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ + TclCdevCollection *collectionPtr; + static int id = 0; + int c1; + char** s1; + + if (argc < 2 || argc >3) { + interp->result = "wrong # args"; + return TCL_ERROR; + } + + if(Tcl_SplitList(interp, argv[1], &c1, &s1) != TCL_OK) { + return TCL_ERROR; + } + + collectionPtr = new TclCdevCollection(c1,s1); + free ((char*) s1); + + sprintf(interp->result, "col%d", id); + id++; + + Tcl_CreateCommand(interp, interp->result, CollectionCmd, (ClientData) collectionPtr, TclCdevCollection::deleteCollection); + + if (argc == 3) { + collectionPtr->setAttrib(argv[2]); + } + + return TCL_OK; +} + + +extern "C" int Cdevcollection_Init(Tcl_Interp *interp) { + + Tcl_PkgRequire(interp, "Blt", "2.1", 0); + Tcl_PkgRequire(interp, "Cdev", "1.4", 0); + + if(Tcl_PkgProvide(interp, "Cdevcollection", CDEV_VERSION) != TCL_OK) { + return TCL_ERROR; + } + + Tcl_CreateCommand(interp, "cdevcollection", MakeCollectionCmd, (ClientData *) NULL, (Tcl_CmdDeleteProc *) NULL); + return TCL_OK; +} + + diff --git a/extensions/tcl/tcl_cdevvector.cc b/extensions/tcl/tcl_cdevvector.cc new file mode 100755 index 0000000..8a76244 --- /dev/null +++ b/extensions/tcl/tcl_cdevvector.cc @@ -0,0 +1,435 @@ +// March, 97, start +// cdev $vector $device $message ... .. + +#include +#include "blt.h" + +#include +#include +#include +#include +#include + +// cdev includes +#include +#include +#include +#include +#include + +static int VALUE_TAG_ID =- 1; +#define VALUE_TAG ((VALUE_TAG_ID<0 && cdevData::tagC2I("value", &VALUE_TAG_ID)!= CDEV_SUCCESS)?-1:VALUE_TAG_ID) +// static int STATUS_TAG_ID =- 1; +// #define STATUS_TAG ((STATUS_TAG_ID<0 && cdevData::tagC2I("status", &STATUS_TAG_ID)!= CDEV_SUCCESS)?-1:STATUS_TAG_ID) +// static int SEVERITY_TAG_ID =- 1; +// #define SEVERITY_TAG ((SEVERITY_TAG_ID<0 && cdevData::tagC2I("severity", &SEVERITY_TAG_ID)!= CDEV_SUCCESS)?-1:SEVERITY_TAG_ID) + +static int cdevdebug = 0; + +class tclCdevDataV { + public: + tclCdevDataV(); + void parse(Tcl_Interp*, char* *, int); + ~tclCdevDataV(); + + cdevData out, context; + int hascontext; + + int tagn, *taglist; + char *callbacktag; + + int state, async; +}; + +tclCdevDataV::~tclCdevDataV() { + delete taglist; +} + +tclCdevDataV::tclCdevDataV():hascontext(0), tagn(0), taglist(NULL), async(0), state(TCL_ERROR) { +}; + +// Parses command line, fills up the outgoing cdevData and the context (if any) +void tclCdevDataV::parse(Tcl_Interp *interp, char **argv, int argc) { + int i, c1, c2; + cdevData *ptr; + char **s1 = NULL; + char **s2 = NULL; + + // Point to 'out' cdevData until we hit the context (if any) + ptr = &out; + for(i = 3; i < argc; i++) { + // skip 'cdev' '$device' and '$message' + if(Tcl_SplitList(interp, argv[i], &c1, &s1) != TCL_OK) { + return; + } + if(c1 == 2) { + // {tag value} pair, check if the value is a scalar + if(Tcl_SplitList(interp, s1[1], &c2, &s2) != TCL_OK) { + free((char *) s1); + return; + } + if(c2 == 1) { + // we have a scalar + ptr->insert(s1[0], s1[1]); + // insert scalar + } + else { + ptr->insert(s1[0], s2, c2); + // insert vector of scalars, does not handle matrices + } + free((char *) s2); + } + else if(c1 == 1) { + // can be one of "-context" , "-tags" or a callbacktag + if(strcmp(argv[i], "-context") == 0) { + // all remaining 'tag value' pairs go in the context + ptr = &context; + hascontext = 1; + } + else if(strcmp(argv[i], "-tags") == 0) { + // get the list of tags to print out from the result data + i++; + // points to next entry in argv + if(i == argc) { + interp->result = "expected tag names"; + free((char *) s1); + return; + } + if(Tcl_SplitList(interp, argv[i], &tagn, &s2) != TCL_OK) { + interp->result = "tag problem"; + free((char *) s1); + return; + } + else { + taglist = new int[tagn]; + for(int j = 0; j < tagn; j++) { + if(cdevData::tagC2I(s2[j], &taglist[j]) != CDEV_SUCCESS) { + interp->result = "unknown tag"; + free((char *) s2); + free((char *) s1); + return; + } + } + } + free((char *) s2); + } + else { + // single entry, a callbacktag, better be at end of input + if(i != argc-1) { + interp->result = "expecting callbacktag at end"; + free((char *) s1); + return; + } + // Here we have a callback tag, hence we want to send asynchronously + callbacktag = argv[i]; + async = 1; + } + } + else { + // c1 > 2 + // tag / string pair (i.e. "value this is a string with spaces embedded" + char **av = s1; + av++; + char *concat = Tcl_Concat(c1-1, av); + ptr->insert(s1[0], concat); + if(cdevdebug == 1) { + fprintf(stderr, "inserted: %s, with value: %s\n", s1[0], concat); + } + free(concat); + } + free((char *) s1); + } + state = TCL_OK; +} + +class callbackInfoV { + public: + callbackInfoV(Tcl_Interp*, char *, Blt_Vector); // vectorname + callbackInfoV(Tcl_Interp*, char *, Blt_Vector, int); // vectorname + ~callbackInfoV(); + Tcl_Interp *interp; + cdevCallback *callback; + Blt_Vector vecInfo; + char *vecName; + int index; +}; + +callbackInfoV::callbackInfoV(Tcl_Interp *e, char *arg, Blt_Vector i) { + interp = e; + vecName = new char[strlen(arg)+1]; + vecInfo = i; + strcpy(vecName, arg); + callback = NULL; + index = -1; +} + +callbackInfoV::callbackInfoV(Tcl_Interp *e, char *arg, Blt_Vector i, int ind) { + interp = e; + vecName = new char[strlen(arg)+1]; + vecInfo = i; + strcpy(vecName, arg); + callback = NULL; + index = ind; +} + +callbackInfoV::~callbackInfoV() { + delete vecName; +} + +cdevBounds *BoundsV; +int DimV; + +int HandleTagV(Tcl_Interp *interp, cdevData &result, Blt_Vector *vecInfo, char* vecname, int index) { + int i, len; + size_t dim; + + if(result.getDim(VALUE_TAG, &dim) != CDEV_SUCCESS) { + return TCL_ERROR; + } + + if( ((dim == 0) && (index < 0)) || ((dim == 1) && (index >= 0)) ) { + return TCL_ERROR; + } + + if (dim == 0) { + if (vecInfo->numValues <= index) { + return TCL_ERROR; + } + vecInfo->valueArr[index] = (double)result; + return Blt_ResetVector(interp, vecname, vecInfo, TCL_DYNAMIC); + } + + // dim = 1 + DimV = (int) dim; + BoundsV = new cdevBounds[DimV]; + result.getBounds(VALUE_TAG, BoundsV, DimV); + len = 1; + for(i = 0; i < DimV; i++) { + len *= BoundsV[i].length; + } + + if (vecInfo->arraySize < len) { // resize if necc. + if (Blt_ResizeVector(interp, vecname, len) != TCL_OK) return TCL_ERROR; + Blt_GetVector(interp, vecname, vecInfo); + } + + result.get(VALUE_TAG, vecInfo->valueArr); + + delete BoundsV; + if (Blt_ResetVector(interp, vecname, vecInfo, TCL_DYNAMIC) != TCL_OK) { + return TCL_ERROR; + } + return TCL_OK; +} + +// executes inside poll() whenever 'file' is readable +void Cdev_CallbackFunctionV(int, void *userarg, cdevRequestObject&, cdevData &result) { + // could check status and do appropriate action like: set Error(info->s) ??? + callbackInfoV *info = (callbackInfoV *) userarg; + HandleTagV(info->interp, result, &info->vecInfo, info->vecName, info->index); +} + +// same as above, plus removes callbackinfo +void Cdev_CallbackFunctionOnceV(int, void *userarg, cdevRequestObject&, cdevData &result) { + callbackInfoV *info = (callbackInfoV *) userarg; + HandleTagV(info->interp, result, &info->vecInfo, info->vecName, info->index); + delete info; +} + +typedef cdevRequestObject *cdevRequestObjectPtr; + +int CdevVectorCmd(ClientData, Tcl_Interp *interp, int argc, char **argv) { + // cdevvector vector device message {tag value} {..} cb + + cdevData result; + cdevCallback *cb = NULL; + callbackInfoV *info; + tclCdevDataV data; + int n, delinfo = 0; + Blt_Vector vecInfo; + char **devices = NULL; + cdevRequestObjectPtr request, *requests; + + if(argc < 4) { + Tcl_AppendResult(interp, "cdevvector: wrong # args", (char *) NULL); + return TCL_ERROR; + } + + if (!Blt_VectorExists(interp, argv[1])) { + if (Blt_CreateVector(interp, argv[1], 64, &vecInfo) != TCL_OK) { + interp->result = "vector creation error"; + return TCL_ERROR; + } + } else { + if (Blt_GetVector(interp, argv[1], &vecInfo) != TCL_OK) { + return TCL_ERROR; + } + } + + int ndevices = 0; + + if(Tcl_SplitList(interp, argv[2], &ndevices, &devices) != TCL_OK) { + return TCL_ERROR; + } + + if (ndevices == 1) { + request = cdevRequestObject::attachPtr(argv[2], argv[3]); + free((char*)devices); + } else { + requests = new cdevRequestObjectPtr[ndevices]; + for(n = 0; n < ndevices; n++) { + requests[n] = cdevRequestObject::attachPtr(devices[n], argv[3]); + } + if (vecInfo.arraySize < ndevices) { // resize if necc. + if (Blt_ResizeVector(interp, argv[1], ndevices) != TCL_OK) return TCL_ERROR; + Blt_GetVector(interp, argv[1], &vecInfo); + } + free((char *) devices); + } + + data.parse(interp, argv+1, argc-1); + + if(data.state != TCL_OK) { + return TCL_ERROR; + } + + if(strncmp(argv[3], "monitorOn", 9) == 0) data.async = 1; + + if(data.async) { + // we want to sent it async + + if (ndevices == 1) { + info = new callbackInfoV(interp, argv[1], vecInfo); + + if(strncmp(argv[3], "monitorOn", 9) == 0) { + cb = new cdevCallback(Cdev_CallbackFunctionV, (void *) info); + } + else if(strncmp(argv[3], "monitorOff", 10) == 0) { + delinfo = 1; + cb = new cdevCallback(NULL, NULL); + } + else { + cb = new cdevCallback(Cdev_CallbackFunctionOnceV, (void *) info); + } + + info->callback = cb; + + if(data.hascontext) { + if(request->setContext(data.context) != CDEV_SUCCESS) { + interp->result = "setContext error"; + delete info; + return TCL_ERROR; + } + } + + if(request->sendCallback(data.out, *cb) != CDEV_SUCCESS) { + delete info; + return TCL_ERROR; + } else { + if(delinfo) delete info; + return TCL_OK; + } + } else { // ndevices > 1 + int j = 0; + + if(strncmp(argv[3], "monitorOn", 9) == 0) { + j = 1; + } + else if(strncmp(argv[3], "monitorOff", 10) == 0) { + j = 2; + } + + for(n = 0; n < ndevices; n++) { + info = new callbackInfoV(interp, argv[1], vecInfo, n); + + if(j == 1) { + cb = new cdevCallback(Cdev_CallbackFunctionV, (void *) info); + } + else if(j == 2) { + delinfo = 1; + cb = new cdevCallback(NULL, NULL); + } + else { + cb = new cdevCallback(Cdev_CallbackFunctionOnceV, (void *) info); + } + + info->callback = cb; + + if(data.hascontext) { + if(requests[n]->setContext(data.context) != 0) { + interp->result = "setContext error"; + delete [] requests; + delete info; + return TCL_ERROR; + } + } + if(requests[n]->sendCallback(data.out, *cb) != CDEV_SUCCESS) { + delete [] requests; + delete info; + return TCL_ERROR; + } else { + if(delinfo) delete info; + } + } + delete [] requests; + return TCL_OK; + } + } + + // send it sync + if (ndevices == 1) { + if(data.hascontext) { + if(request->setContext(data.context) != CDEV_SUCCESS) { + interp->result = "setContext error"; + return TCL_ERROR; + } + } + + if(request->send(data.out, result) != CDEV_SUCCESS) { + sprintf(interp->result, "error in send: %s %s", argv[2], argv[3]); + return TCL_ERROR; + } + + HandleTagV(interp, result, &vecInfo, argv[1], -1); + + return TCL_OK; + } else { + for(n = 0; n < ndevices; n++) { + if(data.hascontext) { + if(requests[n]->setContext(data.context) != 0) { + interp->result = "setContext error"; + delete [] requests; + delete info; + return TCL_ERROR; + } + } + if(requests[n]->send(data.out, result) != CDEV_SUCCESS) { + delete [] requests; + delete info; + return TCL_ERROR; + } else { + if(delinfo) delete info; + HandleTagV(interp, result, &vecInfo, argv[1], n); + } + } + delete [] requests; + return TCL_OK; + } +} + +extern "C" int Cdevvector_Init(Tcl_Interp *interp) { + + Tcl_PkgRequire(interp, "Blt", "2.1", 0); + Tcl_PkgRequire(interp, "Cdev", CDEV_VERSION, 0); + + if(Tcl_PkgProvide(interp, "Cdevvector", CDEV_VERSION) != TCL_OK) { + return TCL_ERROR; + } + + Tcl_CreateCommand(interp, "cdevvector", CdevVectorCmd, (ClientData *) NULL, (Tcl_CmdDeleteProc *) NULL); + + return TCL_OK; +} + + + diff --git a/extensions/tcl/tkAppInit.cc b/extensions/tcl/tkAppInit.cc new file mode 100755 index 0000000..aaeb3c6 --- /dev/null +++ b/extensions/tcl/tkAppInit.cc @@ -0,0 +1,119 @@ +/* + * tkAppInit.c -- + * + * Provides a default version of the Tcl_AppInit procedure for + * use in wish and similar Tk-based applications. + * + * Copyright (c) 1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#ifndef lint +static char sccsid[] = "@(#) tkAppInit.c 1.15 95/06/28 13:14:28"; +#endif /* not lint */ + +#include "tk.h" +#include + +/* + * The following variable is a special hack that is needed in order for + * Sun shared libraries to be used for Tcl. + */ + +//extern int matherr(); +//int *tclDummyMathPtr = (int *) matherr; + +/* + *---------------------------------------------------------------------- + * + * main -- + * + * This is the main program for the application. + * + * Results: + * None: Tk_Main never returns here, so this procedure never + * returns either. + * + * Side effects: + * Whatever the application does. + * + *---------------------------------------------------------------------- + */ + +int main(int argc, char **argv) +{ + Tk_Main(argc, argv, Tcl_AppInit); + return 0; /* Needed only to prevent compiler warning. */ +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_AppInit -- + * + * This procedure performs application-specific initialization. + * Most applications, especially those that incorporate additional + * packages, will have their own version of this procedure. + * + * Results: + * Returns a standard Tcl completion code, and leaves an error + * message in interp->result if an error occurs. + * + * Side effects: + * Depends on the startup script. + * + *---------------------------------------------------------------------- + */ + +extern "C" Extension_Init(Tcl_Interp* interp); +extern "C" Cdev_Init (Tcl_Interp *interp); + +int +Tcl_AppInit(Tcl_Interp *interp) +{ + /* + * Tk_Window main; + */ + + if (Tcl_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + if (Tk_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + + /* + * Call the init procedures for included packages. Each call should + * look like this: + * + * if (Mod_Init(interp) == TCL_ERROR) { + * return TCL_ERROR; + * } + * + * where "Mod" is the name of the module. + */ + + Extension_Init(interp); + + if (Cdev_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + + /* + * Call Tcl_CreateCommand for application-specific commands, if + * they weren't already created by the init procedures called above. + */ + + /* + * Specify a user-specific startup file to invoke if the application + * is run interactively. Typically the startup file is "~/.apprc" + * where "app" is the name of the application. If this line is deleted + * then no user-specific startup file will be run under any conditions. + */ + + tcl_RcFileName = "~/.wishrc"; + return TCL_OK; +} diff --git a/extensions/tclnew/CVS/Entries b/extensions/tclnew/CVS/Entries new file mode 100644 index 0000000..04433b5 --- /dev/null +++ b/extensions/tclnew/CVS/Entries @@ -0,0 +1,17 @@ +/README.txt/1.1.1.1/Mon Jun 21 19:56:02 1999// +/blt.h/1.1.1.1/Mon Jun 21 19:56:02 1999// +/cdevtcl.doc/1.1.1.1/Mon Jun 21 19:56:02 1999/-kb/ +/many.tcl/1.1.1.1/Mon Jun 21 19:56:02 1999// +/pkgIndex.tcl/1.1.1.1/Mon Jun 21 19:56:02 1999// +/result/1.1.1.1/Mon Jun 21 19:56:02 1999// +/setup/1.1.1.1/Mon Jun 21 19:56:02 1999// +/tcl_cdev.cc/1.1.1.1/Thu Jul 15 09:32:42 1999// +/tcl_cdevcollections.cc/1.1.1.1/Mon Jun 21 19:56:03 1999// +/tcl_cdevvector.cc/1.1.1.1/Mon Jun 21 19:56:03 1999// +/tcltest.cc/1.1.1.1/Mon Jun 21 19:56:02 1999// +/test_cout.cc/1.1.1.1/Mon Jun 21 19:56:03 1999// +/testit/1.1.1.1/Mon Jun 21 19:56:03 1999// +/tkAppInit.cc/1.1.1.1/Mon Jun 21 19:56:03 1999// +/tmp/1.1.1.1/Tue Aug 3 07:49:56 1999// +/Makefile/1.2/Fri Aug 20 16:13:05 1999// +D diff --git a/extensions/tclnew/CVS/Repository b/extensions/tclnew/CVS/Repository new file mode 100644 index 0000000..d352254 --- /dev/null +++ b/extensions/tclnew/CVS/Repository @@ -0,0 +1 @@ +/home/pss060/sls/controls/CVSROOT/PACKAGES/cdev/cdev_psi_1.7/extensions/tclnew diff --git a/extensions/tclnew/CVS/Root b/extensions/tclnew/CVS/Root new file mode 100644 index 0000000..3d55408 --- /dev/null +++ b/extensions/tclnew/CVS/Root @@ -0,0 +1 @@ +/home/pss060/sls/controls/CVSROOT diff --git a/extensions/tclnew/Makefile b/extensions/tclnew/Makefile new file mode 100644 index 0000000..89c23d6 --- /dev/null +++ b/extensions/tclnew/Makefile @@ -0,0 +1,51 @@ +ARCH = Linux +APPNAME = TCL/TK CDEV Interface + +T_A=Linux +CDEVVERSION=1.7.2 +#CDEVINCLUDE = /tools/include + +CXXFLAGS = -DUNIX -D$(T_A) -DTCLCDEV_VERSION=\"1.1sls\" -I . -I $(CDEVINCLUDE) +LDFLAGS = -L$(CDEVLIB) -ldl -lm -lc -lcdev -ltcl $(CDEVSHOBJ)/$(CDEVVERSION)/caService.so + + +targets: libtclcdev.so libtclcdev80.so libtclcdevcollections.so libtclvector.so +########################################################################3 + + +libtclcdev.so: tcl_cdev.o + g++ -shared -olibtclcdev.so tcl_cdev.o $(LDFLAGS) + +libtclcdev80.so: tcl_cdev80.o + g++ -shared -olibtclcdev80.so tcl_cdev80.o $(LDFLAGS) + +#tcl_cdev.o -L$(CDEVLIB) -L$(EPICSLIB) -ldl -lCom -lca -lm -lc -lcdev -lg++ -ltcl caService.so + +tcltest.o : tcltest.cc + g++ -c -DTCLCDEV_VERSION=\"1.1\" -I../../include tcltest.cc -o tcltest.o + +libtcltest.so: tcltest.o + rm -f $@ + g++ -shared -o $@ tcltest.o -L$(CDEVLIB) -L$(EPICSLIB) -ldl -lCom -lca -lm -lc -lcdev -lg++ -ltcl caService.so + + +libtclcdevcollections.so: tcl_cdevcollections.o + rm -f $@ +# ld -b -o $@ tcl_cdevcollections.o -ll -ly + g++ -shared -o $@ tcl_cdevcollections.o + +libtclvector.so: tcl_cdevvector.o + rm -f $@ +# ld -b -o $@ tcl_cdevvector.o -ll -ly + g++ -shared -o $@ tcl_cdevvector.o + +install: libtclcdev.so + mv libtclcdev.so $(CDEVLIB) +# cat pkgIndex.tcl >> ../../../lib/itcl/pkgIndex.tcl + +clean: + @rm -rf *.o *.a *.so *~ core ish + + +breakit: breakit.o + $(CC) -o $@ breakit.o -L$(CDEV)/lib/$(TARGETDIR) -lcdev -ll -ly -lm diff --git a/extensions/tclnew/README.txt b/extensions/tclnew/README.txt new file mode 100644 index 0000000..c9c2d8b --- /dev/null +++ b/extensions/tclnew/README.txt @@ -0,0 +1,55 @@ +// ***************************************************************************** +// * Tcl/Tk Interface to cdev +// ***************************************************************************** + +1) All communication is through strings, the cdevdata object takes care of + all conversion. + +2) Use a 'get' in your client code, 'find' will not do type conversions. + + +3) syntax: + + cdev $service $message "$tag1 $val1" "$tag2 $val2" ... + + or + + cdev $service $message "$tag1 $val1" "$tag2 $val2" $cb + + + where: + $service is any cdev service, i.e. "model", "IPM1A01" + $message a message to that device, i.e "get elements" + + the rest of the arguments are list of length 2 with the + first entry the tag name, and the second the tag value. + + If the length of the last list is 1 the cdev routine + sendCallback is used instead of the synchronous send. + + The result of the call will appear in the tcl array "$Control($cb)" + in due time. + + On return only the 'value' tag will be converted into a tcl result, + arbitrary dimensional results are handled. + + +Error handling: + See code for 'status' and 'severity' tag handling, this will be + superseded by real cdev errorhandler interface + +Bugs: + Cannot send space delimited string since the interface will parse + these up as char**'s + +examples: + + cdev IPM1S01 "get XPOS" + + cdev IPM1S01 "monitorOn XPOS" IPM1S01.XPOS + results appear in $Control(IPM1S01.XPOS) + + cdev model "get elements" "value quads" "section {arc1 arc2 arc3}" + value is char* + section is char** length 3 + diff --git a/extensions/tclnew/blt.h b/extensions/tclnew/blt.h new file mode 100644 index 0000000..0e90fb3 --- /dev/null +++ b/extensions/tclnew/blt.h @@ -0,0 +1,79 @@ +/* + * blt.h -- + * + * Copyright 1993-1994 by AT&T Bell Laboratories. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and warranty + * disclaimer appear in supporting documentation, and that the + * names of AT&T Bell Laboratories any of their entities not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * AT&T disclaims all warranties with regard to this software, including + * all implied warranties of merchantability and fitness. In no event + * shall AT&T be liable for any special, indirect or consequential + * damages or any damages whatsoever resulting from loss of use, data + * or profits, whether in an action of contract, negligence or other + * tortuous action, arising out of or in connection with the use or + * performance of this software. + * + */ + +#ifndef _BLT_H +#define _BLT_H + +#ifndef _ANSI_ARGS_ +# define _ANSI_ARGS_(x) () +#endif + +#define BLT_MAJOR_VERSION 2 +#define BLT_MINOR_VERSION 1 + +typedef enum { + BLT_VECTOR_NOTIFY_UPDATE=1, /* The vector's values has been updated */ + BLT_VECTOR_NOTIFY_DESTROY=2 /* The vector has been destroyed and the client + * should no longer use its data (calling + * Blt_FreeVectorId) */ +} Blt_VectorNotify; + +typedef void (Blt_VectorChangedProc) _ANSI_ARGS_((Tcl_Interp *interp, + ClientData clientData, Blt_VectorNotify notify)); + +//typedef struct Blt_VectorId *Blt_VectorId; +typedef struct Blt_VectorId; + +typedef struct { + double *valueArr; /* Array of values (possibly malloc-ed) */ + int numValues; /* Number of values in the array */ + int arraySize; /* Size (in values) of the allocated space */ + double min, max; /* Minimum and maximum values in the vector */ + int reserved; /* Reserved for future use */ +} Blt_Vector; + +extern "C" Blt_VectorId Blt_AllocVectorId _ANSI_ARGS_((Tcl_Interp *interp, + char *vecName)); +extern "C" void Blt_SetVectorChangedProc _ANSI_ARGS_((Blt_VectorId clientId, + Blt_VectorChangedProc * proc, ClientData clientData)); +extern "C" void Blt_FreeVectorId _ANSI_ARGS_((Blt_VectorId clientId)); +extern "C" int Blt_GetVectorById _ANSI_ARGS_((Tcl_Interp *interp, + Blt_VectorId clientId, Blt_Vector *vecPtr)); +extern "C" char *Blt_NameOfVectorId _ANSI_ARGS_((Blt_VectorId clientId)); +extern "C" int Blt_VectorNotifyPending _ANSI_ARGS_((Blt_VectorId clientId)); + +extern "C" int Blt_CreateVector _ANSI_ARGS_((Tcl_Interp *interp, char *vecName, + int size, Blt_Vector *vecPtr)); +extern "C" int Blt_GetVector _ANSI_ARGS_((Tcl_Interp *interp, char *vecName, + Blt_Vector *vecPtr)); +extern "C" int Blt_VectorExists _ANSI_ARGS_((Tcl_Interp *interp, char *vecName)); +extern "C" int Blt_ResetVector _ANSI_ARGS_((Tcl_Interp *interp, char *vecName, + Blt_Vector *vecPtr, Tcl_FreeProc *freeProc)); +extern "C" int Blt_ResizeVector _ANSI_ARGS_((Tcl_Interp *interp, char *vecName, + int newSize)); +extern "C" int Blt_DeleteVector _ANSI_ARGS_((Tcl_Interp *interp, char *vecName)); + +extern "C" int Blt_Init _ANSI_ARGS_((Tcl_Interp *interp)); + + +#endif /*_BLT_H*/ diff --git a/extensions/tclnew/cdevtcl.doc b/extensions/tclnew/cdevtcl.doc new file mode 100644 index 0000000..6b6017e --- /dev/null +++ b/extensions/tclnew/cdevtcl.doc @@ -0,0 +1,57 @@ +Interface tcl to cdev + + +Features: + Access all of cdev world from within the tcl shells. + Handle arbitrary cdevData tag/value pairs + Handle arbitrary cdevData arrays + Handle synchronous get/set + Handle asynchronous get/set/monitors + Set cdev context + +Implementation: + Dynamically loadable module including all of cdev library for tcl7.5 + Polls cdev 5 time a second + Soon: Install cdev filedescriptors in tcl select list + + +Important note: All communication is through strings, the cdevdata object takes care of all conversion. + Cdev service writers: Use a 'get' in your client code, 'find' will not do type conversions. + +syntax: + +cdev $service $message "$tag1 $val1" "$tag2 $val2" ... + Where $service is any cdev service, i.e. "model" or "IPM1A01" + and $message a message to that device, i.e "get elements" or "get XPOS" + the rest of the arguments are list of length 2 with the first entry the tag name, and the second the tag value. + List of length > 2 are handled as tag/string with spaces. + +or + +cdev $service $message "$tag1 $val1" "$tag2 $val2" $cb + The message is send asynchronously. + The result of the call will appear in the tcl array "$Control($cb)" in due time. + +Return tags: + On return the 'value' tag will be converted into a tcl result, arbitrary dimensional results are handled. + Arbitrary tags will be converted using the -tags {$tag $tag2 ...} option + +Context: + The context can be accessed by -context "$tag $value" ... + all tag/value pairs after the context switch will be put in the context + +Error handling: + See code for 'status' and 'severity' tag handling, this will be superseded by proper cdev errorhandler interface + +examples: + + cdev IPM1S01 "get XPOS" + + cdev lockarc1 "set status" "value Waiting for Beam" + the status is set to the string "Waiting for Beam" + + cdev IPM1S01 "monitorOn XPOS" IPM1S01.XPOS + results appear in Control(IPM1S01.XPOS) + + cdev model "get elements" "value Quadrupoles" "section {arc1 arc2 arc3}" + diff --git a/extensions/tclnew/libtclcdev.so b/extensions/tclnew/libtclcdev.so new file mode 100755 index 0000000..c8dc863 Binary files /dev/null and b/extensions/tclnew/libtclcdev.so differ diff --git a/extensions/tclnew/libtclcdev80.so b/extensions/tclnew/libtclcdev80.so new file mode 100755 index 0000000..3952ba7 Binary files /dev/null and b/extensions/tclnew/libtclcdev80.so differ diff --git a/extensions/tclnew/libtclcdevcollections.so b/extensions/tclnew/libtclcdevcollections.so new file mode 100755 index 0000000..83edc3a Binary files /dev/null and b/extensions/tclnew/libtclcdevcollections.so differ diff --git a/extensions/tclnew/libtclvector.so b/extensions/tclnew/libtclvector.so new file mode 100755 index 0000000..90dfb33 Binary files /dev/null and b/extensions/tclnew/libtclvector.so differ diff --git a/extensions/tclnew/many.tcl b/extensions/tclnew/many.tcl new file mode 100755 index 0000000..8344c4d --- /dev/null +++ b/extensions/tclnew/many.tcl @@ -0,0 +1,24 @@ +#!/usr/bin/wish8.0 +load libtclcdev.so + + +set chans { + sls_bi0:b0 sls_bi0:b1 sls_bi0:b2 sls_bi0:b3 + sls_bi0:b4 sls_bi0:b5 sls_bi0:b6 sls_bi0:b7 + sls_bi0:b8 sls_bi0:b9 sls_bi0:b10 sls_bi0:b11 + sls_bi0:b12 sls_bi0:b13 sls_bi0:b14 sls_bi0:b15 +} + + +foreach name $chans { + puts $name + label .$name -textvariable Control($name) -width 10 + pack .$name + cdev $name "monitorOn VAL" $name +} + + + + + + diff --git a/extensions/tclnew/pkgIndex.tcl b/extensions/tclnew/pkgIndex.tcl new file mode 100644 index 0000000..4bb0353 --- /dev/null +++ b/extensions/tclnew/pkgIndex.tcl @@ -0,0 +1 @@ +package ifneeded Cdev 1.3 "load [file join $dir libtclcdev.sl] Cdev" diff --git a/extensions/tclnew/result b/extensions/tclnew/result new file mode 100644 index 0000000..ea4d092 --- /dev/null +++ b/extensions/tclnew/result @@ -0,0 +1,14 @@ + +---------------------------------------------------------------- +Building TCL/TK CDEV Interface for Target: +---------------------------------------------------------------- +g++ -c -DTCLCDEV_VERSION=\"1.1\" -I../../include tcl_cdev.cc -o tcl_cdev.o +tcl_cdev.cc: In function `void HandleTag(int, class cdevData &, struct Tcl_DString &, int, int)': +tcl_cdev.cc:375: warning: assignment to `char' from `void *' lacks a cast +tcl_cdev.cc:405: warning: assignment to `char' from `void *' lacks a cast +rm -f libtclcdev.so +ld -shared -o libtclcdev.so tcl_cdev.o -L/home/pss060/sls/hunt/cdev-1.6/lib/linux -L/home/pss060/sls/hunt/epics313b11/base/lib/Linux -ldl -lCom -lca -lm -lc -lcdev -lg++ -ltcl /home/pss060/sls/hunt/cdev-1.6/lib/linux/1.6/caService.so +---------------------------------------------------------------- +TCL/TK CDEV Interface Has Been Built for Target: +---------------------------------------------------------------- + diff --git a/extensions/tclnew/setup b/extensions/tclnew/setup new file mode 100644 index 0000000..8c65aac --- /dev/null +++ b/extensions/tclnew/setup @@ -0,0 +1,5 @@ +setenv LD_LIBRARY_PATH .:/home/pss060/sls/controls/Soft/cdev1.6.2/lib/Linux +setenv CDEVDDL /tools/lib/sls.ddl +setenv CDEVSHOBJ /home/pss060/sls/controls/Soft/cdev1.6.2/lib/Linux +setenv CDEVVERSION 1.6.2 + diff --git a/extensions/tclnew/tcl_cdev.cc b/extensions/tclnew/tcl_cdev.cc new file mode 100644 index 0000000..3d0007f --- /dev/null +++ b/extensions/tclnew/tcl_cdev.cc @@ -0,0 +1,1334 @@ +// a CDEV access interface for tcl +// Johannes van Zeijts, March 95, first version +// May 95, second version, using Walt Akers callback example +// Dec 95, added arbitrary dimensional array output and context +// Jan 96, added handling of strings with spaces +// Aug 96, deleted callbackinfo when we are not monitoring +// Aug 96, converted to tcl7.5 +// Nov 1, 96, moved to cdev 1.4 +// March, 97, overhaul, allowed multiple devices +// Feb, 98 Make it work with select event handling +// For generic services this works only in cdev/1.6.2 +// $id$ + +/* Output formatting + Attention given to 'Strings with spaces' which have special meaning in tcl + +#devices = 1 + +#tags = 0 (only value tag) + + dim = 0 1 + String + String with spaces + + dim = 1 1 1 1 + St1 St2 St3 + {St w sp1} {St w sp2} {St w sp3} + + dim = 2 {11 12 13} {21 22 23} + {st1 st2 st3} {...} + {{st w sp1} {st w sp2} {st w sp3}} { ...} + + + + +#tags > 0 (value tag + other tags) + Each tag in its own list index + Result is always list of length (#tags + 1) + + + dim = 0 + 1 + St1 + {St w sp1} + + + dim = 1 + {1 1 1} + {St1 St2 St3} + {{St w sp1} {St w sp2} {St w sp3}} + + + dim = 2 + {{1 1 1} {1 1 1}} + {{{st w sp1} {st w sp2} {st w sp3}} {{st w sp1} {st w sp2} {st w sp3}}} + + +--------------------------------------------------------------------------------------- +#devices > 1 , + +#tags = 0 + dim = 0 1 1 1 + {str w sp} {str w sp} + + dim = 1 {1 1 1} {1 1 1} + {{str w sp} ..} { } + + +#tags > 0 + dim = 0 {0 1 2} {0 1 2} + + dim = 1 {{1 1 1} {1 1 1}} + +*/ + +#include +#include + +#include +#include +#include +#include +//#include + +// cdev includes +#include +#include +#include +#include +#include + +static int VALUE_TAG_ID =- 1; +#define VALUE_TAG ((VALUE_TAG_ID<0 && cdevData::tagC2I("value", &VALUE_TAG_ID)!= CDEV_SUCCESS)?-1:VALUE_TAG_ID) +static int STATUS_TAG_ID =- 1; +#define STATUS_TAG ((STATUS_TAG_ID<0 && cdevData::tagC2I("status", &STATUS_TAG_ID)!= CDEV_SUCCESS)?-1:STATUS_TAG_ID) +static int SEVERITY_TAG_ID =- 1; +#define SEVERITY_TAG ((SEVERITY_TAG_ID<0 && cdevData::tagC2I("severity", &SEVERITY_TAG_ID)!= CDEV_SUCCESS)?-1:SEVERITY_TAG_ID) + +static int cdevdebug = 0; +static char* cdevFormat; +static char* defaultFormat = "%.4g"; + +class tclCdevData { + public: + tclCdevData(); + void parse(Tcl_Interp*, char* *, int); + ~tclCdevData(); + + cdevData out, context; + int hascontext; + + int tagn, *taglist; + char *callbacktag; + int filtersame; + int state, async; + int unroll; +private: + int getTag(char*); +}; + +tclCdevData::~tclCdevData() { + delete taglist; +} + +tclCdevData::tclCdevData():hascontext(0), tagn(0), taglist(NULL), async(0), state(TCL_ERROR) { + filtersame = 1; + unroll = 0; +}; + +int tclCdevData::getTag(char * s) { + int TT=0; + if (cdevData::tagC2I(s, &TT) == CDEV_SUCCESS) { + return TT; + } + for (int i = 30; TT==0 && i<65534; i++) { + cdevData::insertTag(i,s); /// bug in cdev: this does not return status + if (cdevData::tagC2I(s, &TT) == CDEV_SUCCESS) break; + } + return TT; +} + + +// Parses command line, fills up the outgoing cdevData and the context (if any) +void tclCdevData::parse(Tcl_Interp *interp, char **argv, int argc) { + int i, c1, c2, tag; + cdevData *ptr; + char **s1 = NULL; + char **s2 = NULL; + + // Point to 'out' cdevData until we hit the context (if any) + ptr = &out; + for(i = 3; i < argc; i++) { + // skip 'cdev' '$device' and '$message' + if(Tcl_SplitList(interp, argv[i], &c1, &s1) != TCL_OK) { + return; + } + if(c1 == 2) { + // {tag value} pair, check if the value is a scalar + if(Tcl_SplitList(interp, s1[1], &c2, &s2) != TCL_OK) { + free((char *) s1); + return; + } + tag = getTag(s1[0]); + if(c2 <= 1) { + // we have a scalar + if (c2 == 0) { // handle empty string + ptr->insert(tag,""); + } else { + ptr->insert(tag, s1[1]); + // insert scalar + } + } + else { + ptr->insert(tag, s2, c2); + // insert vector of scalars, does not handle matrices + } + free((char *) s2); + } + else if (c1 == 1) { + // can be one of "-context" , "-tags", "-filtersame" or a callbacktag + if(strcmp(argv[i], "-context") == 0) { + // all remaining 'tag value' pairs go in the context + ptr = &context; + hascontext = 1; + } + else if(strcmp(argv[i], "-tags") == 0) { + // get the list of tags to print out from the result data + i++; + // points to next entry in argv + if(i == argc) { + interp->result = "expected tag names"; + free((char *) s1); + return; + } + if(Tcl_SplitList(interp, argv[i], &tagn, &s2) != TCL_OK) { + interp->result = "tag problem"; + free((char *) s1); + return; + } + else { + taglist = new int[tagn]; + for(int j = 0; j < tagn; j++) { + taglist[j] = getTag(s2[j]); + } + } + free((char *) s2); + } else if (strcmp(argv[i], "-filtersame") == 0) { + i++; + if (i == argc) { + interp->result = "expected boolean"; + free((char*) s1); + return; + } + if (Tcl_GetBoolean(interp, argv[i], &filtersame) != TCL_OK) { + free((char*) s1); + return; + } + } else if (strcmp(argv[i], "-unroll") == 0) { + i++; + if (i == argc) { + interp->result = "expected number"; + free((char*) s1); + return; + } + if (Tcl_GetInt(interp, argv[i], &unroll) != TCL_OK) { + free((char*) s1); + return; + } + } else { + // single entry, a callbacktag, better be at end of input + if(i != argc-1) { + interp->result = "expecting callbacktag at end"; + free((char *) s1); + return; + } + // Here we have a callback tag, hence we want to send asynchronously + callbacktag = argv[i]; + async = 1; + } + } + else { + // c1 > 2 + // tag / string pair (i.e. "value this is a string with spaces embedded" + char **av = s1; + av++; + char *concat = Tcl_Concat(c1-1, av); + tag = getTag(s1[0]); + ptr->insert(tag, concat); + if(cdevdebug == 1) { + fprintf(stderr, "inserted: %s, with value: %s\n", s1[0], concat); + } + free(concat); + } + free((char *) s1); + } + state = TCL_OK; +} + +class callbackInfo { + public: + callbackInfo(Tcl_Interp*, char *); + callbackInfo(Tcl_Interp*, char*, char *); + ~callbackInfo(); + Tcl_Interp *interp; + char *s; + char *value; // keep pointer to previous string to compare new result too. + int status, filtersame; + void addtags(int, int *); + + int *tags, ntags; + char **devicetags; + int unroll, unrolllength; + char **unrolldata; +}; + +callbackInfo::callbackInfo(Tcl_Interp *e, char *arg) { + interp = e; + s = new char[strlen(arg)+1]; + strcpy(s, arg); + ntags = 0; + tags = NULL; + value = NULL; + devicetags = NULL; + status = -999; + filtersame = 1; + unroll = 0; + unrolllength = 0; + unrolldata = NULL; +} + +callbackInfo::callbackInfo(Tcl_Interp *e, char *arg1, char *arg2) { + interp = e; + s = new char[strlen(arg1)+strlen(arg2)+1]; + strcpy(s, arg1); + strcat(s, arg2); + ntags = 0; + tags = NULL; + value = NULL; + status = -999; + devicetags = NULL; + filtersame = 1; + unroll = 0; + unrolllength = 0; + unrolldata = NULL; +} + +callbackInfo::~callbackInfo() { + delete tags; + for (int i = 0; i < ntags; i++) { + delete devicetags[i]; + } + delete unrolldata; + delete devicetags; + delete s; +} + +void callbackInfo::addtags(int n, int *v) { + char *tagstring; + ntags = n; + tags = new int[n]; + devicetags = new char*[ntags]; + for(int i = 0; i < ntags; i++) { + tags[i] = v[i]; + cdevData::tagI2C(tags[i],tagstring); + devicetags[i] = new char[strlen(s) + 2 + strlen(tagstring)]; + strcpy(devicetags[i], s); + strcat(devicetags[i], "."); + strcat(devicetags[i], tagstring); + } +} + +static char cs[512]; +cdevBounds *Bounds; +int Dim; + +static int K = 0; + +void HandleLevel(char **in, int level, Tcl_DString &ds) { + int i; + for(i = 0; i < Bounds[level].length; i++) { + if(level >= Dim-1) { + Tcl_DStringAppendElement(&ds, in[K]); + K++; + } + else { + Tcl_DStringStartSublist(&ds); + HandleLevel(in, level+1, ds); + Tcl_DStringEndSublist(&ds); + } + } +} + +// Format a cdevData tag result into a tcl result +// mode == #ntags + +void HandleTag(int tag, cdevData &result, Tcl_DString &ds, int mode, int ndevices) { + int i, len; + size_t dim; + char **sp; + char *tagname = NULL; + + if(cdevdebug == 1) { + if (cdevData::tagI2C(tag, tagname) != CDEV_SUCCESS) { +// cout << "HandleTag " << tag << " Could not convert" << endl; + printf("HandleTag: %d counld not convert\n",tag); + } else { +// cout << "HandleTag " << tag << " " << tagname << endl; + printf("HandleTag: %d %s\n",tag,tagname); + } + tagname = NULL; + } + + if(result.getDim(tag, &dim) != CDEV_SUCCESS) { + if(cdevdebug == 1) { + printf("HandleTag: result.getDim failed\n"); + } + cs[0] = (char)NULL; + if (ndevices == 1 && mode == 0) { + Tcl_DStringAppend(&ds, cs, -1); // append an empty string + } else { + Tcl_DStringAppendElement(&ds, cs); // append an empty list + } + return; + } + + // Always retrieve the result as a char*, cdevData does the conversion for me! + // do special conversion for: DOUBLE and TIMESTAMP + + if(cdevdebug == 1) { + printf("HandleTag: result.getDim ok : dim=%d\n",dim); + } + if(dim == 0) { + // put this in if we want format conversions. + int i = result.getType(tag); + if(cdevdebug == 1) { + printf("Type is %d \n",i); + } + if ((i == CDEV_FLOAT) || (i == CDEV_DOUBLE)) { + if(cdevdebug == 1) { + printf("HandleTag: is CDEV_DOUB\n"); + } + double dres; + result.get(tag, &dres); + sprintf(cs, cdevFormat, dres); + } else if (i == CDEV_TIMESTAMP) { + unsigned long timeres; + result.get(tag, &timeres); + sprintf(cs, "%lu", timeres); + } else if(i== CDEV_BYTE) { + printf("CAN'T HANDLE CDEV_BYTE/n"); + cs[0] = (char)NULL; + result.get(tag, cs, 255); + } else { + cs[0] = (char)NULL; + result.get(tag, cs, 255); + } + + if (mode == 0 && ndevices == 1) { + Tcl_DStringAppend(&ds,cs,-1); + } else { + Tcl_DStringAppendElement(&ds,cs); + } + return; + } else if (dim==1) { + size_t elems; + + if( (result.getElems(tag,&elems)) != 0){ + printf("error geting number of elements in value\n"); + exit(0); + } + int i = result.getType(tag); + if(cdevdebug == 1) { + printf("Type is %d \n",i); + } + if (i == CDEV_INT32) { + int *ival; + if(cdevdebug == 1) { + printf("HandleTag: is CDEV_INT32\n"); + } + ival = (int *)malloc(elems*(size_t)sizeof(int)); + result.get(tag,ival); + if(cdevdebug == 1) { + printf("cdev format = %s\n",cdevFormat); + } + for(i=0;i 1 + Dim = (int) dim; + K = 0; + Bounds = new cdevBounds[Dim]; + result.getBounds(tag, Bounds, Dim); + len = 1; + for(i = 0; i < Dim; i++) { + if(cdevdebug == 1) { + printf("HandleT:Bounds[%d].offset = %d\n",i,Bounds[i].offset); + printf("HandleT:Bounds[%d].length = %d\n",i,Bounds[i].length); + } + len *= Bounds[i].length; + } + if(cdevdebug == 1) { + printf("HandleTag: len = %d\n",len); + int i = result.getType(tag); + if ((i == CDEV_FLOAT) || (i == CDEV_DOUBLE)) { + printf("HandleTag: is CDEV_DOUB\n"); + } + } + + sp = new char*[len]; + result.get(tag, sp); + + if (mode>0 || (mode==0&&ndevices>1)) { + if(cdevdebug == 1) { + printf("HandleTag: will Tcl_DStringStart..\n"); + } + Tcl_DStringStartSublist(&ds); + } + if(cdevdebug == 1) { + printf("HandleTag: will call HandleLevel\n"); + } + HandleLevel(sp, 0, ds); + if (mode>0 || (mode==0&&ndevices>1)) { + if(cdevdebug == 1) { + printf("HandleTag: will Tcl_DStringEnd...\n"); + } + Tcl_DStringEndSublist(&ds); + } + // append the result to a Tcl_DString + } + + if(cdevdebug == 1) { + printf("HandleTag: will delete bounds \n"); + } + delete Bounds; + while(len > 0) { + len--; + delete sp[len]; + } + if(cdevdebug == 1) { + printf("HandleTag: will delete sp \n"); + } + delete [] sp; + if(cdevdebug == 1) { + printf("HandleTag: finished\n"); + } +} + +int Cdev_Handleresult(int *tags, int ntags, cdevData &result, Tcl_DString &ds, int ndevices) { + if(cdevdebug == 1) { +// cout << "Cdev_Handleresult" << endl; + printf("Cdev_Handleresult\n"); + } + + // assume we always return the "value" tag + + if (ndevices>1 && ntags>0) Tcl_DStringStartSublist(&ds); + + HandleTag(VALUE_TAG, result, ds, ntags, ndevices); + if(cdevdebug == 1) { + printf("CdevHandleresult: ntags = %d ndevices = %d\n",ntags,ndevices); + } + if(ntags > 0) { + for(int i = 0; i < ntags; i++) { + HandleTag(tags[i], result, ds, ntags, ndevices); + } + } + if (ndevices>1 && ntags>0) Tcl_DStringEndSublist(&ds); + return TCL_OK; +} + +char* getCdevErrorCode(int); + + +//int cbcount = 0; +// executes inside poll() or pend(file) whenever 'file' is readable +void Cdev_CallbackFunction(int status, void *userarg, cdevRequestObject&, cdevData &result) { + Tcl_DString ds; + int i, j, t; + + if(cdevdebug == 1) { +// cout << "Cdev_CallbackFunction" << endl; + } + + callbackInfo *info = (callbackInfo *) userarg; + + if(cdevdebug == 1) { + printf("callback: status = %d, done = %d\n", status, cdevCallback::isTransactionDone()); + result.asciiDump(); +// cout << "dumped cdevData" << endl; + } + + if (info->status != status) { + info->status = status; + Tcl_SetVar2(info->interp, "CdevStatus", info->s, getCdevErrorCode(status), TCL_GLOBAL_ONLY); + } + + if (cdevCallback::isTransactionDone() == 1) { +// Tcl_SetVar2(info->interp, "CdevDone", info->s, getCdevErrorCode(status), TCL_GLOBAL_ONLY); + delete info; + return; + } + +// if ((status == CDEV_SUCCESS || status == CDEV_WARNING) && (result.getType(VALUE_TAG) != CDEV_INVALID)) + if ((status == CDEV_SUCCESS || status == CDEV_WARNING)) { + + if (info->unroll == 0) { // Do the old stuff + Tcl_DStringInit(&ds); + i = Cdev_Handleresult(info->tags, info->ntags, result, ds, 1); + if (info->filtersame) { + if (info->value != NULL) { + if (strcmp(info->value, Tcl_DStringValue(&ds)) != 0) { // only set if value is changed + info->value = Tcl_SetVar2(info->interp, "Control", info->s, Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY); + } + } else { + info->value = Tcl_SetVar2(info->interp, "Control", info->s, Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY); + } + } else { + info->value = Tcl_SetVar2(info->interp, "Control", info->s, Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY); + } + Tcl_DStringFree(&ds); + } else if (info->unroll == 1) { + // First to the "value" tag, next loop through all the requested tags + + Tcl_DStringInit(&ds); + + HandleTag(VALUE_TAG, result, ds, 0, 1); + info->value = Tcl_SetVar2(info->interp, "Control", info->s, Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY); + Tcl_DStringFree(&ds); + + for (i = 0; i < info->ntags; i++) { + HandleTag(info->tags[i], result, ds, 0, 1); + info->value = Tcl_SetVar2(info->interp, "Control", info->devicetags[i], Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY); + Tcl_DStringFree(&ds); + } + } else { // unroll > 1 + // Loop through the cdevData since it is supposed to be vector valued. + Tcl_DStringInit(&ds); + +// HandleTag(VALUE_TAG, result, ds, 0, 1); +// info->value = Tcl_SetVar2(info->interp, "Control", info->s, Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY); +// Tcl_DStringFree(&ds); + + size_t nElems; + result.getElems(VALUE_TAG, &nElems); + char** outString; + if (result.find(VALUE_TAG, (void*&) outString) != CDEV_SUCCESS) { + if (cdevdebug) { +// cout << "Could not find value tag" << endl; + } + return; + } + + char *namePtr, name[512]; + + if ((info->unrolldata == NULL) || (nElems > info->unrolllength)) { + delete info->unrolldata; + info->unrolldata = new char*[nElems]; + info->unrolllength = nElems; + } + + double *dp; + unsigned long *lp; + + for (j = 0; j < info->ntags; j++) { + t = result.getType(info->tags[i]); + if ((t == CDEV_FLOAT) || (t == CDEV_DOUBLE)) { + result.find(info->tags[i], (void* &) dp); + for (i = 0; i < nElems; i++) { + sprintf(cs, cdevFormat, dp[i]); + info->unrolldata[i] = new char[strlen(cs)+1]; + strcpy(info->unrolldata[i],cs); + } + } else if (t == CDEV_TIMESTAMP) { + result.find(info->tags[i], (void* &)lp); + for (i = 0; i < nElems; i++) { + sprintf(cs, "%lu", lp[i]); + info->unrolldata[i] = new char[strlen(cs)+1]; + strcpy(info->unrolldata[i],cs); + } + } else { + result.get(info->tags[i], info->unrolldata); + } + + for (i = 0; i < nElems; i++) { + namePtr = name; + strcpy(namePtr, outString[i]); + strcat(namePtr, info->devicetags[i]); + Tcl_SetVar2(info->interp, "Control", name, info->unrolldata[i], TCL_GLOBAL_ONLY); + delete info->unrolldata[i]; + } + } + } + } +} + +// Old way of polling, superseded by FileHandler calls, but since FD's are not working yet, still in use +void Cdev_UpdateProc(ClientData dummy) { + if(cdevdebug == 1) { +// cout << "Cdev_UpdateProc" << endl; + } + cdevSystem::defaultSystem().poll(); + Tcl_CreateTimerHandler(200, Cdev_UpdateProc, dummy); +} + + +void Cdev_FileProc(ClientData clientData, int mask) { + int fd = (int) clientData; + if (cdevdebug) { +// cout << "Cdev_FileProc: polling: " << fd << " mask = " << mask << endl; + } + if (mask == TCL_EXCEPTION) { + if (cdevdebug) { +// cout << "Cdev_FileProc: TCL_EXCEPTION" << endl; + } +// SMH Tcl_File f = Tcl_GetFile(clientData, TCL_UNIX_FD); + int f = (int) clientData; + Tcl_DeleteFileHandler(f); + return; + } + + cdevSystem::defaultSystem().pend(0.0001, fd); + if (cdevdebug) { +// cout << "Cdev_FileProc: did pend " << endl; + } +// cdevSystem::defaultSystem().poll(); +} + +int CdevDebugCmd(ClientData, Tcl_Interp*, int, char* *) { + if(cdevdebug == 0) { + cdevdebug = 1; + } + else { + cdevdebug = 0; + } + return TCL_OK; +} + +int CdevFormatCmd(ClientData, Tcl_Interp* interp, int argc, char** argv) { + if (argc == 1) { + sprintf(interp->result, "%s", cdevFormat); + return TCL_OK; + } + + delete cdevFormat; + cdevFormat = new char[strlen(argv[1])+1]; + strcpy(cdevFormat, argv[1]); + return TCL_OK; +} + +int PutEnvCmd(ClientData, Tcl_Interp*, int argc, char** argv) { + if (argc == 1) { + return TCL_OK; + } + + putenv(argv[1]); + return TCL_OK; +} + +static int Finished = 0; + +void Cdev_RegisterFD(int fd, int condition, void *) { + if (cdevdebug) { +// cout << "Register FD " << fd << " " << condition << " Finished = " << Finished << endl; + } + + if (Finished == 1) { + return; + } + +// SMH Tcl_File f = Tcl_GetFile((ClientData) fd, TCL_UNIX_FD); + int f = fd; + + if (condition == 1) { + Tcl_CreateFileHandler(f, TCL_READABLE|TCL_EXCEPTION, Cdev_FileProc, (ClientData) fd); + } else { + Tcl_DeleteFileHandler(f); + } +} + +void Cdev_ExitProc(ClientData) { + Finished = 1; +} + +typedef cdevRequestObject *cdevRequestObjectPtr; + +int CdevCmd(ClientData, Tcl_Interp *interp, int argc, char **argv) { + // cdev device message {tag value} {..} cb + // cdev device message {tag value} {..} -context (tag value} {..} cb + + char **devices = NULL; + int i, n, ndevices; + Tcl_DString ds; + cdevData result; + cdevCallback *cb = NULL; + callbackInfo *info; + cdevRequestObjectPtr request, *requests; + tclCdevData data; + int delinfo = 0; + +// printf("CdevCmd: \n"); + + if(argc < 3) { + Tcl_AppendResult(interp, "cdev: wrong # args", (char *) NULL); + return TCL_ERROR; + } + + ndevices = 0; + if(Tcl_SplitList(interp, argv[1], &ndevices, &devices) != TCL_OK) { + return TCL_ERROR; + } + + if(ndevices == 1) { +// printf("CdevCmd: ndevices=1 argv[1]= %s argv[2]=%s\n",argv[1],argv[2]); + if((request=cdevRequestObject::attachPtr(argv[1],argv[2]))==NULL){ + if(cdevdebug == 1) { + printf("::attachPtr returned NULL\n"); + } + return TCL_ERROR; + } + free((char*)devices); + } + else { + requests = new cdevRequestObjectPtr[ndevices]; + for(n = 0; n < ndevices; n++) { + requests[n] = cdevRequestObject::attachPtr(devices[n], argv[2]); + } + } + +// printf("have got request object\n"); + data.parse(interp, argv, argc); + + if(data.state != TCL_OK) { + return TCL_ERROR; + } + + if(data.async) { + // we want to sent it async +// printf("data.async is true\n"); + if(cdevdebug == 1) { + printf("data.async is true\n"); +// cout << "data.async is true" << endl; + } + if(ndevices == 1) { + info = new callbackInfo(interp, data.callbacktag); + info->filtersame = data.filtersame; + info->unroll = data.unroll; + if(data.tagn != 0) { + info->addtags(data.tagn, data.taglist); + } + + if(strncmp(argv[2], "monitorOff", 10) == 0) { + delinfo = 1; + cb = new cdevCallback(Cdev_CallbackFunction, NULL); + } + else { + cb = new cdevCallback(Cdev_CallbackFunction, (void *) info); + } + + if(data.hascontext) { + if(cdevdebug == 1) { +// cout << "Context data: " << endl; + printf("Context data: \n"); + data.context.asciiDump(stdout); + } + if(request->setContext(data.context) != CDEV_SUCCESS) { + interp->result = "setContext error"; + delete info; + return TCL_ERROR; + } + } + if(cdevdebug == 1) { +// cout << argv[1] << " " << argv[2] << " OutBound data: " << endl; + data.out.asciiDump(stdout); + } + + if(request->sendCallback(data.out, *cb) != 0) { + delete info; + delete cb; + return TCL_ERROR; + } + else { + if(delinfo) delete info; + delete cb; + cdevSystem::defaultSystem().flush(); + return TCL_OK; + } + } + else { + // ndevices > 1, send each one separately + int j = 0; + + if(strncmp(argv[2], "monitorOn", 9) == 0) { + j = 1; + } + else if(strncmp(argv[2], "monitorOff", 10) == 0) { + j = 2; + } + + for(n = 0; n < ndevices; n++) { + info = new callbackInfo(interp, devices[n], data.callbacktag); + if(data.tagn != 0) { + info->addtags(data.tagn, data.taglist); + } + info->filtersame = data.filtersame; + info->unroll = data.unroll; + if(j == 1) { + cb = new cdevCallback(Cdev_CallbackFunction, (void *) info); + } + else if(j == 2) { + delinfo = 1; + cb = new cdevCallback(Cdev_CallbackFunction, NULL); + } + else { + cb = new cdevCallback(Cdev_CallbackFunction, (void *) info); + } + + if(data.hascontext) { + if(requests[n]->setContext(data.context) != 0) { + interp->result = "setContext error"; + delete requests; + free((char *) devices); + delete info; + return TCL_ERROR; + } + } + if(requests[n]->sendCallback(data.out, *cb) != CDEV_SUCCESS) { + delete requests; + delete info; + free((char *) devices); + delete cb; + return TCL_ERROR; + } + else { + if(delinfo) delete info; + delete cb; + } + } + delete requests; + free((char *) devices); + cdevSystem::defaultSystem().flush(); + return TCL_OK; + } + } + + // send it sync + if(cdevdebug == 1) { +// cout << "will send it sync " << endl; + printf("will send it sync\n "); + } + Tcl_DStringInit(&ds); + + if(ndevices == 1) { + if(data.hascontext) { + if(cdevdebug == 1) { +// cout << "Context data: " << endl; + printf("ndevices=1, Context data:\n "); + data.context.asciiDump(stdout); + } + if(request->setContext(data.context) != CDEV_SUCCESS) { + interp->result = "setContext error"; + return TCL_ERROR; + } + } + + if(cdevdebug == 1) { +// cout << argv[1] << " " << argv[2] << " OutBound data: " << endl; + printf(" CdevCmd: sync: ndevices=1, OutBound data:\n "); + data.out.asciiDump(stdout); + } + + if(request->send(data.out, result) != CDEV_SUCCESS) { + sprintf(interp->result, "Is an error in send: %s %s", argv[1], argv[2]); + return TCL_ERROR; + } + + + if(cdevdebug == 1) { +// cout << "Result data: " << endl; + printf("ndevices=1, send ok \n"); + result.asciiDump(stdout); + printf("finished ascii-dump \n"); + } + +// if(STATUS_TAG !=- 1) { +// if(result.get(STATUS_TAG, &i) == CDEV_SUCCESS) { +// if(i != CDEV_SUCCESS) { +// if(SEVERITY_TAG !=- 1) { +// Tcl_DStringFree(&ds); +// result.get(SEVERITY_TAG, cs, 255); +// Tcl_DStringAppend(&ds, cs, -1); +// Tcl_DStringResult(interp, &ds); +// } +// else { +// interp->result = "cdev status != 0"; +// } +// return TCL_ERROR; +// } +// } +// } + + if(Cdev_Handleresult(data.taglist, data.tagn, result, ds, 1) != TCL_OK) { + interp->result = "cannot handle cdev result"; + Tcl_DStringFree(&ds); + return TCL_ERROR; + } + + if(cdevdebug == 1) { +// cout << "Cdev_Handleresult Done " << endl; + printf("Cdev_Handleresult Done \n"); + } + Tcl_DStringResult(interp, &ds); + if(cdevdebug == 1) { +// cout << "will call interp->freeProc " << endl; + } +// interp->freeProc = TCL_DYNAMIC; + } + else { + // ndevices > 1 + if(cdevdebug == 1) { + printf(" CdevCmd: sync: ndevices=%d:\n ",ndevices); + } + int addbraces = 0; + for(n = 0; n < ndevices; n++) { + if(cdevdebug == 1) { + printf(" doing device %d:\n ",n); + } + if(data.hascontext) { + if(requests[n]->setContext(data.context) != CDEV_SUCCESS) { + interp->result = "setContext error"; + delete requests; + free((char *) devices); + return TCL_ERROR; + } + } + if(requests[n]->send(data.out, result) != CDEV_SUCCESS) { + sprintf(interp->result, "error in send: %s %s", devices[n], argv[2]); + delete requests; + free((char *) devices); + return TCL_ERROR; + } + if(cdevdebug == 1) { + printf(" send worked:\n"); + result.asciiDump(stdout); + } + if(STATUS_TAG !=- 1) { + if(result.get(STATUS_TAG, &i) == CDEV_SUCCESS) { + if(i != CDEV_SUCCESS) { + if(SEVERITY_TAG !=- 1) { + Tcl_DStringFree(&ds); + result.get(SEVERITY_TAG, cs, 255); + Tcl_DStringAppend(&ds, cs, -1); + Tcl_DStringResult(interp, &ds); + } + else { + interp->result = "cdev status != 0"; + } + delete requests; + free((char *) devices); + return TCL_ERROR; + } + } + } + if(Cdev_Handleresult(data.taglist, data.tagn, result, ds, ndevices) != TCL_OK) { + interp->result = "cannot handle cdev result"; + Tcl_DStringFree(&ds); + return TCL_ERROR; + } + } + Tcl_DStringResult(interp, &ds); +// changed SMH : 13MAR98 : do not know why - but this line dumps core +// interp->freeProc = TCL_DYNAMIC; + delete requests; + free((char *) devices); + } + + if(cdevdebug == 1) { + printf(" all fine - will return TCL_OK:\n"); + } + return TCL_OK; +} + +int CdevDirectoryCmd(ClientData, Tcl_Interp *interp, int argc, char **argv) { + int ndevices = 0; + cdevData result; + Tcl_DString ds; + cdevCallback *cb = NULL; + callbackInfo *info; + tclCdevData data; + int delinfo = 0; + + if(cdevdebug == 1) { + printf("CdevDirectoryCmd \n"); + } + if(argc < 3) { + Tcl_AppendResult(interp, "cdevDirectory: wrong # args", (char *) NULL); + return TCL_ERROR; + } + + if(argc < 3) { + Tcl_AppendResult(interp, "cdevDirectory: wrong # args", (char *) NULL); + return TCL_ERROR; + } + + cdevDevice &device = cdevDevice::attachRef("cdevDirectory"); + + data.parse(interp, argv-1, argc+1); + + if(data.state != TCL_OK) { + return TCL_ERROR; + } + + if(data.async) { + // we want to sent it async + + info = new callbackInfo(interp, data.callbacktag); + if(data.tagn != 0) { + info->addtags(data.tagn, data.taglist); + } + + if(strncmp(argv[2], "monitorOn", 9) == 0) { + cb = new cdevCallback(Cdev_CallbackFunction, (void *) info); + } + else if(strncmp(argv[2], "monitorOff", 10) == 0) { + delinfo = 1; + cb = new cdevCallback(Cdev_CallbackFunction, NULL); + } + else { + cb = new cdevCallback(Cdev_CallbackFunction, (void *) info); + } + + if(cdevdebug == 1) { +// cout << argv[1] << " " << argv[2] << " OutBound data: " << endl; + data.out.asciiDump(stdout); + } + + if(device.sendCallback(argv[1], data.out, *cb) != 0) { + delete info; + return TCL_ERROR; + } + else { + if(delinfo) delete info; + return TCL_OK; + } + } + // send it sync + Tcl_DStringInit(&ds); + + if(cdevdebug == 1) { +// cout << argv[1] << " " << argv[2] << " OutBound data: " << endl; + data.out.asciiDump(stdout); + } + + if(device.send(argv[1], data.out, result) != CDEV_SUCCESS) { + sprintf(interp->result, "error in send: %s", argv[1]); + return TCL_ERROR; + } + + if(cdevdebug == 1) { +// cout << "Result data: " << endl; + result.asciiDump(stdout); + } + +// if(STATUS_TAG !=- 1) { +// if(result.get(STATUS_TAG, &i) == CDEV_SUCCESS) { +// if(i != CDEV_SUCCESS) { +// if(SEVERITY_TAG !=- 1) { +// Tcl_DStringFree(&ds); +// result.get(SEVERITY_TAG, cs, 255); +// Tcl_DStringAppend(&ds, cs, -1); +// Tcl_DStringResult(interp, &ds); +// } +// else { +// interp->result = "cdev status != 0"; +// } +// return TCL_ERROR; +// } +// } +// } + + if(Cdev_Handleresult(data.taglist, data.tagn, result, ds, 1) != TCL_OK) { + interp->result = "cannot handle cdev result"; + Tcl_DStringFree(&ds); + return TCL_ERROR; + } + + Tcl_DStringResult(interp, &ds); +// interp->freeProc = TCL_DYNAMIC; + + return TCL_OK; +} + +char *getCdevErrorCode(int code) { + switch (code) { + case -2: return "CDEV_WARNING"; + case -1: return "CDEV_ERROR"; + case 0: return "CDEV_SUCCESS"; + case 1: return "CDEV_INVALIDOBJ"; + case 2: return "CDEV_INVALIDARG"; + case 3: return "CDEV_INVALIDSVC"; + case 4: return "CDEV_INVALIDOP"; + case 5: return "CDEV_NOTCONNECTED"; + case 6: return "CDEV_IOFAILED"; + case 7: return "CDEV_CONFLICT"; + case 8: return "CDEV_NOTFOUND"; + case 9: return "CDEV_TIMEOUT"; + case 10: return "CDEV_CONVERT"; + case 11: return "CDEV_OUTOFRANGE"; + case 12: return "CDEV_NOACCESS"; + case 13: return "CDEV_ACCESSCHANGED"; + case 60: return "CDEV_DISCONNECTED"; + case 61: return "CDEV_RECONNECTED"; + case 70: return "CDEV_DELETE_CALLBACK"; + default: return "UNKNOWN"; + } +} + +int CdevErrorCodeCmd(ClientData, Tcl_Interp *interp, int argc, char **argv) { + // cdevconvertcode code + + if(argc < 2) { + Tcl_AppendResult(interp, "cdevconvertcode: wrong # args", (char *) NULL); + return TCL_ERROR; + } + + int code = atoi(argv[1]); + interp->result = getCdevErrorCode(code); +// switch (code) { +// case -2: interp->result = "CDEV_WARNING"; break; +// case -1: interp->result = "CDEV_ERROR"; break; +// case 0: interp->result = "CDEV_SUCCESS"; break; +// case 1: interp->result = "CDEV_INVALIDOBJ"; break; +// case 2: interp->result = "CDEV_INVALIDARG"; break; +// case 3: interp->result = "CDEV_INVALIDSVC"; break; +// case 4: interp->result = "CDEV_INVALIDOP"; break; +// case 5: interp->result = "CDEV_NOTCONNECTED"; break; +// case 6: interp->result = "CDEV_IOFAILED"; break; +// case 7: interp->result = "CDEV_CONFLICT"; break; +// case 8: interp->result = "CDEV_NOTFOUND"; break; +// case 9: interp->result = "CDEV_TIMEOUT"; break; +// case 10: interp->result = "CDEV_CONVERT"; break; +// case 11: interp->result = "CDEV_OUTOFRANGE"; break; +// case 12: interp->result = "CDEV_NOACCESS"; break; +// case 13: interp->result = "CDEV_ACCESSCHANGED"; break; +// case 60: interp->result = "CDEV_DISCONNECTED"; break; +// case 61: interp->result = "CDEV_RECONNECTED"; break; +// case 70: interp->result = "CDEV_DELETE_CALLBACK"; break; +// default: interp->result = "UNKNOWN"; +// } + return TCL_OK; +} + +// #define CDEV_WARNING -2 /* Failure of function is non-consequential */ +// #define CDEV_ERROR -1 /* Errors that are not in any categories */ +// #define CDEV_SUCCESS 0 /* cdev success */ +// #define CDEV_INVALIDOBJ 1 /* invalid cdev objects */ +// #define CDEV_INVALIDARG 2 /* invalid argument passed to cdev calls */ +// #define CDEV_INVALIDSVC 3 /* wrong service during dynamic loading */ +// #define CDEV_INVALIDOP 4 /* operation is unsupported (collection) */ +// #define CDEV_NOTCONNECTED 5 /* not connected to low network service */ +// #define CDEV_IOFAILED 6 /* low level network service IO failed */ +// #define CDEV_CONFLICT 7 /* conflicts of data types or tags */ +// #define CDEV_NOTFOUND 8 /* cdev cannot find user request (cdevData) */ +// #define CDEV_TIMEOUT 9 /* time out */ +// #define CDEV_CONVERT 10 /* cdevData conversion error */ +// #define CDEV_OUTOFRANGE 11 /* value out of range for device attribute */ +// #define CDEV_NOACCESS 12 /* insufficient access to perform request */ +// #define CDEV_ACCESSCHANGED 13 /* change in access permission of device */ +// #define CDEV_DISCONNECTED 60 /* channel has been disconnected */ +// #define CDEV_RECONNECTED 61 /* channel has been reconnected */ +// #define CDEV_DELETE_CALLBACK 70 /* the callback object will be deleted */ +// +// /* Request object state values */ +// #define CDEV_STATE_CONNECTED 0 /* request object is connected to device */ +// #define CDEV_STATE_NOTCONNECTED 1 /* request object is not connected */ +// #define CDEV_STATE_INVALID 2 /* request object is invalid */ +// +// /* Request object access values */ +// #define CDEV_ACCESS_NONE 0 /* no access to specified attribute */ +// #define CDEV_ACCESS_READONLY 1 /* read-only access to attribute */ +// #define CDEV_ACCESS_WRITE 2 /* read-write access to attribute */ +// +// /* cdevError class severity codes */ +// #define CDEV_SEVERITY_INFO 0 /* informative message */ +// #define CDEV_SEVERITY_WARN 1 /* warning message */ +// #define CDEV_SEVERITY_ERROR 2 /* error message */ +// #define CDEV_SEVERITY_SEVERE 3 /* severe or fatal error message */ + +// SMH changed for tcl8.0 +// extern"C"int Cdev_Init(Tcl_Interp *interp) { +extern"C"int Tclcdev_Init(Tcl_Interp *interp) { + +// printf("This is Tclcdev_Init \n"); + + int i, numFD = 20; + int fds[20]; + cdevSystem::defaultSystem().getFd(fds, numFD); + for (i=0;i +#include +#include +#include +#include + +const int VALUE = cdevData::addTag("value"); +static int cdevdebug = 0; + +/** Handle double *data, recursively if dimension > 1. Result is a Tcl_ListObj + @author Johannes van Zeijts +*/ +Tcl_Obj* HandleLevel(double *res, int &count, int level, cdevBounds *bounds, int dim) { + int len = bounds[level].length; + Tcl_Obj *list[len]; + if (level == dim-1) { + for (int i=0; i 1. Result is a Tcl_ListObj +Tcl_Obj* HandleLevel(float *res, int &count, int level, cdevBounds *bounds, int dim) { + int len = bounds[level].length; + Tcl_Obj *list[len]; + if (level == dim-1) { + for (int i=0; i 1. Result is a Tcl_ListObj +Tcl_Obj* HandleLevel(short *res, int &count, int level, cdevBounds *bounds, int dim) { + int len = bounds[level].length; + Tcl_Obj *list[len]; + if (level == dim-1) { + for (int i=0; i 1. Result is a Tcl_ListObj +Tcl_Obj* HandleLevel(unsigned short *res, int &count, int level, cdevBounds *bounds, int dim) { + int len = bounds[level].length; + Tcl_Obj *list[len]; + if (level == dim-1) { + for (int i=0; i 1. Result is a Tcl_ListObj +Tcl_Obj* HandleLevel(long *res, int &count, int level, cdevBounds *bounds, int dim) { + int len = bounds[level].length; + Tcl_Obj *list[len]; + if (level == dim-1) { + for (int i=0; i 1. Result is a Tcl_ListObj +Tcl_Obj* HandleLevel(unsigned long *res, int &count, int level, cdevBounds *bounds, int dim) { + int len = bounds[level].length; + Tcl_Obj *list[len]; + if (level == dim-1) { + for (int i=0; i 1. Result is a Tcl_ListObj +Tcl_Obj* HandleLevel(unsigned char *res, int &count, int level, cdevBounds *bounds, int dim) { + int len = bounds[level].length; + Tcl_Obj *list[len]; + if (level == dim-1) { + for (int i=0; i 1. Result is a Tcl_ListObj + Each entry is a list of length 2 (seconds / nseconds) +*/ +Tcl_Obj* HandleLevel(cdev_TS_STAMP *res, int &count, int level, cdevBounds *bounds, int dim) { + int len = bounds[level].length; + Tcl_Obj *list[len]; + Tcl_Obj *ts[2]; + if (level == dim-1) { + for (int i=0; i 1. Result is a Tcl_ListObj +Tcl_Obj* HandleLevel(char **res, int &count, int level, cdevBounds *bounds, int dim) { + int len = bounds[level].length; + Tcl_Obj *list[len]; + if (level == dim-1) { + for (int i=0; igetType(tag); + if (type == CDEV_INVALID) { + Tcl_Obj* obj = Tcl_NewObj(); + Tcl_AppendStringsToObj(obj,NULL); + return obj; + } + size_t dim; + data->getDim(tag, &dim); +if (dim == 0) { + if (type == CDEV_DOUBLE || type == CDEV_FLOAT) { + double res; + data->get(tag, &res); + return Tcl_NewDoubleObj(res); + } else if (type == CDEV_INT32) { + long res; + data->get(tag, &res); + return Tcl_NewLongObj(res); + } else if (type == CDEV_STRING) { + char *s; + data->find(tag, (void*&) s); + return Tcl_NewStringObj(s,-1); + } else if (type == CDEV_INT16) { + int res; + data->get(tag, &res); + return Tcl_NewIntObj(res); + } else if (type == CDEV_UINT16) { + int res; + data->get(tag, &res); + return Tcl_NewIntObj(res); + } else if (type == CDEV_UINT32) { + unsigned long res; + data->get(tag, &res); + return Tcl_NewLongObj((long)res); + } else if (type == CDEV_BYTE) { + unsigned char res; + data->get(tag, &res); + return Tcl_NewIntObj((int)res); + } else if (type == CDEV_TIMESTAMP) { + cdev_TS_STAMP t; + data->get(tag, &t); + Tcl_Obj *ts[2]; + ts[0] = Tcl_NewLongObj(t.secPastEpoch); + ts[1] = Tcl_NewLongObj(t.nsec); + return Tcl_NewListObj(2, ts); + } else { + Tcl_Obj *obj = Tcl_NewStringObj("unknown tag: ",-1); + char *s; cdevData::tagI2C(tag, s); + Tcl_AppendStringsToObj(obj,s,NULL); + return obj; + } +} else { +// dim > 0 + cdevBounds Bounds[dim]; + data->getBounds(tag, Bounds, dim); + int count = 0; + if (type == CDEV_DOUBLE) { + double *res; + data->find(tag, (void*&)res); + return HandleLevel(res, count, 0, Bounds, dim); + } else if (type == CDEV_FLOAT) { + float *res; + data->find(tag, (void*&)res); + return HandleLevel(res, count, 0, Bounds, dim); + } else if (type == CDEV_INT32) { + long *res; + data->find(tag, (void*&)res); + return HandleLevel(res, count, 0, Bounds, dim); + } else if (type == CDEV_STRING) { + char **res; + data->find(tag, (void*&) res); + return HandleLevel(res, count, 0, Bounds, dim); + } else if (type == CDEV_INT16) { + short *res; + data->find(tag, (void*&)res); + return HandleLevel(res, count, 0, Bounds, dim); + } else if (type == CDEV_UINT16) { + unsigned short *res; + data->find(tag, (void*&)res); + return HandleLevel(res, count, 0, Bounds, dim); + } else if (type == CDEV_UINT32) { + unsigned long *res; + data->find(tag, (void*&) res); + return HandleLevel(res, count, 0, Bounds, dim); + } else if (type == CDEV_BYTE) { + unsigned char *res; + data->find(tag, (void*&)res); + return HandleLevel(res, count, 0, Bounds, dim); + } else if (type == CDEV_TIMESTAMP) { + cdev_TS_STAMP *res; + data->find(tag, (void*&)res); + return HandleLevel(res, count, 0, Bounds, dim); + } else { + Tcl_Obj *obj = Tcl_NewStringObj("unknown tag: ",-1); + char *s; cdevData::tagI2C(tag, s); + Tcl_AppendStringsToObj(obj,s,NULL); + return obj; + } + } +} +/// Keeps parsed command line data, and contains callback information +class Tcl_cdevData { +public: + Tcl_cdevData(Tcl_Interp*, int, char**); + ~Tcl_cdevData(); + int unroll, status, taglen, *statuss, *taglist; + cdevData *out, *context; + Tcl_Obj *cbtag, *tags, *devices; + int hasContext(), hasData(), isAsynch(); + + static void ObjIniter(); + static Tcl_Obj *arrayname; + static Tcl_Obj *statusname; + static Tcl_Obj *donename; + static Tcl_Interp *interp; + + static Tcl_Obj* getCdevErrorCode(int); +}; + +/// Need to incr the refcount of the static Tcl_Obj, otherwise they may be removed by the tcl memory manager +void Tcl_cdevData::ObjIniter() { + Tcl_IncrRefCount(arrayname); + Tcl_IncrRefCount(statusname); + Tcl_IncrRefCount(donename); +} + +Tcl_Obj *Tcl_cdevData::arrayname = Tcl_NewStringObj("Control",-1); +Tcl_Obj *Tcl_cdevData::statusname = Tcl_NewStringObj("CdevStatus",-1); +Tcl_Obj *Tcl_cdevData::donename = Tcl_NewStringObj("CdevDone",-1); + +Tcl_Interp *Tcl_cdevData::interp; + +Tcl_cdevData::~Tcl_cdevData() { + delete out; + delete context; + delete taglist; + delete statuss; + if (tags != NULL) Tcl_DecrRefCount(tags); + if (cbtag != NULL) Tcl_DecrRefCount(cbtag); + if (devices != NULL) Tcl_DecrRefCount(devices); +} + +/// Convert int into a CDEV error string +Tcl_Obj *Tcl_cdevData::getCdevErrorCode(int code) { + static Tcl_Obj *objm2= Tcl_NewStringObj("CDEV_WARNING",-1); + static Tcl_Obj *objm1= Tcl_NewStringObj("CDEV_ERROR",-1); + static Tcl_Obj *obj0 = Tcl_NewStringObj("CDEV_SUCCESS",-1); + static Tcl_Obj *obj1 = Tcl_NewStringObj("CDEV_INVALIDOBJ",-1); + static Tcl_Obj *obj2 = Tcl_NewStringObj("CDEV_INVALIDARG",-1); + static Tcl_Obj *obj3 = Tcl_NewStringObj("CDEV_INVALIDSVC",-1); + static Tcl_Obj *obj4 = Tcl_NewStringObj("CDEV_INVALIDOP",-1); + static Tcl_Obj *obj5 = Tcl_NewStringObj("CDEV_NOTCONNECTED",-1); + static Tcl_Obj *obj6 = Tcl_NewStringObj("CDEV_IOFAILED",-1); + static Tcl_Obj *obj7 = Tcl_NewStringObj("CDEV_CONFLICT",-1); + static Tcl_Obj *obj8 = Tcl_NewStringObj("CDEV_NOTFOUND",-1); + static Tcl_Obj *obj9 = Tcl_NewStringObj("CDEV_TIMEOUT",-1); + static Tcl_Obj *obj10= Tcl_NewStringObj("CDEV_CONVERT",-1); + static Tcl_Obj *obj11= Tcl_NewStringObj("CDEV_OUTOFRANGE",-1); + static Tcl_Obj *obj12= Tcl_NewStringObj("CDEV_NOACCESS",-1); + static Tcl_Obj *obj13= Tcl_NewStringObj("CDEV_ACCESSCHANGED",-1); + static Tcl_Obj *obj60= Tcl_NewStringObj("CDEV_DISCONNECTED",-1); + static Tcl_Obj *obj61= Tcl_NewStringObj("CDEV_RECONNECTED",-1); + static Tcl_Obj *obj70= Tcl_NewStringObj("CDEV_DELETE_CALLBACK",-1); + static Tcl_Obj *obj80= Tcl_NewStringObj("CDEV_NOTCONSERVER",-1); + static Tcl_Obj *obj81= Tcl_NewStringObj("CDEV_NOTFOUNDSERVER",-1); + static Tcl_Obj *obj82= Tcl_NewStringObj("CDEV_CONN_TIMEOUT",-1); + static Tcl_Obj *obj86= Tcl_NewStringObj("CDEV_BADIO",-1); + static Tcl_Obj *obj87= Tcl_NewStringObj("CDEV_OVERFLOW",-1); + static Tcl_Obj *obj88= Tcl_NewStringObj("CDEV_INCOMPLETE",-1); + static Tcl_Obj *obj89= Tcl_NewStringObj("CDEV_CBK_FINISHED",-1); + static Tcl_Obj *obj90= Tcl_NewStringObj("CDEV_PAUSED",-1); + static Tcl_Obj *obj91= Tcl_NewStringObj("CDEV_MSG_ERR",-1); + static Tcl_Obj *objdefault= Tcl_NewStringObj("UNKNOWN",-1); + + Tcl_Obj *obj; + switch (code) { + case -2: obj = objm2; break; + case -1: obj = objm1; break; + case 0: obj = obj0; break; + case 1: obj = obj1; break; + case 2: obj = obj2; break; + case 3: obj = obj3; break; + case 4: obj = obj4; break; + case 5: obj = obj5; break; + case 6: obj = obj6; break; + case 7: obj = obj7; break; + case 8: obj = obj8; break; + case 9: obj = obj9; break; + case 10: obj = obj10; break; + case 11: obj = obj11; break; + case 12: obj = obj12; break; + case 13: obj = obj13; break; + case 60: obj = obj60; break; + case 61: obj = obj61; break; + case 70: obj = obj70; break; + case 80: obj = obj80; break; + case 81: obj = obj81; break; + case 82: obj = obj82; break; + case 86: obj = obj86; break; + case 87: obj = obj87; break; + case 88: obj = obj88; break; + case 89: obj = obj89; break; + case 90: obj = obj90; break; + case 91: obj = obj91; break; + default: obj = objdefault; + } + Tcl_IncrRefCount(obj); + return obj; +} + +int Tcl_cdevData::hasContext() { + if (context == NULL) return 0; + cdevDataIterator iterator(context); + return iterator.init(); +} + +int Tcl_cdevData::hasData() { + cdevDataIterator iterator(out); + return iterator.init(); +} + +int Tcl_cdevData::isAsynch() { + return (cbtag != NULL); +} + +/// Parses its arguments into a cdevData result, context, and switches +Tcl_cdevData::Tcl_cdevData(Tcl_Interp*, int argc, char** argv) { + int tag, i, j, len, objc; + Tcl_Obj *obj = Tcl_NewObj(); + Tcl_Obj **objv; + out = new cdevData(); + context = NULL; + cdevData *ptr = out; + status = TCL_OK; + statuss = NULL; + taglen = 0; + unroll = 0; + taglist = NULL; + cbtag = NULL; + tags = NULL; + devices = NULL; + for(i=0; iinsert(tag, l); + } else if (Tcl_GetDoubleFromObj(NULL, objv[0], &d) == TCL_OK) { + ptr->insert(tag, d); + } else { + ptr->insert(tag, Tcl_GetStringFromObj(objv[0], &len)); + } + } else if (objc > 1) { + long l; double d; + if (Tcl_GetLongFromObj(NULL, objv[0], &l) == TCL_OK) { + long lv[objc]; + lv[0] = l; + for (int ic=1; icinsert(tag, lv, objc); + } else if (Tcl_GetDoubleFromObj(NULL, objv[0], &d) == TCL_OK) { + double dv[objc]; + dv[0] = d; + for (int ic=1; icinsert(tag, dv, objc); + } else { + char *s[objc]; + for(j=0; jinsert(tag, s, objc); + } + } + } else if (objc == 1) { + char *s = Tcl_GetStringFromObj(obj, &len); + if (strcmp(s, "-context") == 0) { + context = new cdevData(); + ptr = context; + } else if (strcmp(s, "-tags") == 0) { + if (++i == argc) { + Tcl_AppendResult(interp, " expecting tags", NULL); + status = TCL_ERROR; + break; + } + Tcl_SetStringObj(obj, argv[i], -1); + Tcl_ListObjGetElements(interp, obj, &objc, &objv); + taglen = objc; taglist = new int[taglen]; + tags = Tcl_DuplicateObj(obj); + for (j=0; jinsert(tag, Tcl_GetStringFromObj(concat, &len)); + Tcl_DecrRefCount(concat); + } + } + Tcl_DecrRefCount(obj); +} + +/// Based on the list of tags in the Tcl_cdevData, return a Tcl_List with the converted cdevData +Tcl_Obj* Cdev_HandleResult(Tcl_cdevData *data, cdevData &result) { + if (data->taglen == 0) { + return Tcl_ObjFromcdevData(VALUE, &result); + } else { + Tcl_Obj *objv[data->taglen+1]; + objv[0] = Tcl_ObjFromcdevData(VALUE, &result); + for (int i=0; itaglen; ++i) { + objv[i+1] = Tcl_ObjFromcdevData(data->taglist[i], &result); + } + return Tcl_NewListObj(data->taglen+1, objv); + } +} +/** entry point for cdev callbacks + results are put in the global array 'Control' + the '-tags' and '-unroll' options determine what is put it. + the VALUE tag is always returned (even if is empty/not in the result cdevData) +*/ +void Cdev_CallbackFunction(int status, void *userarg, cdevRequestObject&, cdevData &result) { + Tcl_cdevData *data = (Tcl_cdevData *)userarg; + if (data == NULL) return; + if (cdevdebug == 1) { + int lenl; + printf("callback %d %s\n", status, Tcl_GetStringFromObj(data->cbtag, &lenl)); + result.asciiDump(); + } + Tcl_Obj *obj; int len; + if (data->status != status) { + data->status = status; + obj = Tcl_NewObj(); + Tcl_SetIntObj(obj, status); + obj = Tcl_ObjSetVar2(data->interp, data->statusname, data->cbtag, obj, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG); + } + cdevDataIterator iterator(&result); + if (iterator.init()) { // there are entries available + if (data->unroll == 0) { + obj = Cdev_HandleResult( data, result); + obj = Tcl_ObjSetVar2(data->interp, data->arrayname, data->cbtag, obj, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG); + } else if (data->unroll == 1) { + obj = Tcl_ObjFromcdevData(VALUE, &result); + obj = Tcl_ObjSetVar2(data->interp, data->arrayname, data->cbtag, obj, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG); + for (int i=0; itaglen; ++i) { + obj = Tcl_ObjFromcdevData(data->taglist[i], &result); + Tcl_Obj *tag; Tcl_ListObjIndex(data->interp, data->tags, i, &tag); + Tcl_Obj *tagobj = Tcl_DuplicateObj(data->cbtag); + Tcl_AppendStringsToObj(tagobj,".",Tcl_GetStringFromObj(tag, &len),NULL); + obj = Tcl_ObjSetVar2(data->interp, data->arrayname, tagobj, obj, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG); + Tcl_DecrRefCount(tagobj); + } + } else if (data->unroll == 2) { + Tcl_Obj **names, **values, *vtag = Tcl_ObjFromcdevData(VALUE, &result); + int nameslen; + Tcl_ListObjGetElements(data->interp, vtag, &nameslen, &names); + Tcl_ObjSetVar2(data->interp, data->arrayname, data->cbtag, vtag, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG); + for (int i=0; itaglen; ++i) { + Tcl_Obj *tag, *listobj = Tcl_ObjFromcdevData(data->taglist[i], &result); // This better be a list of length len + Tcl_ListObjGetElements(data->interp, listobj, &len, &values); + if (len != nameslen) { Tcl_DecrRefCount(listobj); continue;} + Tcl_ListObjIndex(data->interp, data->tags, i, &tag); + for (int j=0; jcbtag); + Tcl_AppendStringsToObj(tagobj,".",Tcl_GetStringFromObj(names[j], &slen),".",Tcl_GetStringFromObj(tag, &slen),NULL); + Tcl_ObjSetVar2(data->interp, data->arrayname, tagobj, values[j], TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG); + Tcl_DecrRefCount(tagobj); + } + Tcl_DecrRefCount(listobj); + } + } + } + if ((cdevCallback::isTransactionDone() == 1) || (status == CDEV_CBK_FINISHED)) { + Tcl_Obj *sobj = Tcl_NewObj(); + Tcl_SetIntObj(sobj, status); + Tcl_ObjSetVar2(data->interp, data->donename, data->cbtag, sobj, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG); +/// The multi device callback reuses the same data for each request. Do not delete it in that case + if (data->statuss == NULL) delete data; + } +} + +/** Multi device callback, passes work to regular callback function + The index into the device array is carried in the private data of the cdevRequestObject* +*/ +void Cdev_MultiCallbackFunction(int status, void *userarg, cdevRequestObject& req, cdevData &result) { + Tcl_cdevData *data = (Tcl_cdevData *)userarg; + int index = (int) req.getPrivate(); + data->status = data->statuss[index]; + Tcl_Obj *obj, *savecb = data->cbtag; + Tcl_ListObjIndex(data->interp, data->devices, index, &obj); + data->cbtag = Tcl_DuplicateObj(obj); + int len; + Tcl_AppendStringsToObj(data->cbtag,".",Tcl_GetStringFromObj(savecb,&len),NULL); + Cdev_CallbackFunction(status, userarg, req, result); + data->statuss[index] = data->status; + Tcl_DecrRefCount(data->cbtag); + data->cbtag = savecb; +} + +typedef cdevRequestObject *cdevRequestObjectPtr; + +/// Letter/Envelope class for (device/message) and (N devices/message) +class TclRequest { +public: + TclRequest(Tcl_Interp *interp, int argc, char** argv); + virtual ~TclRequest(); +/// forwarded to the letter + virtual int send(Tcl_cdevData *data, Tcl_Obj *&obj) {return Req->send(data, obj);} +/// forwarded to the letter pointer + virtual int sendCallback(Tcl_cdevData *data) {return Req->sendCallback(data);} +/// forwarded to the letter pointer + virtual int getStatus() {return Req->getStatus();} +protected: + TclRequest(Tcl_Obj*, Tcl_Obj*); + Tcl_Obj *device, *message; +/// The pointer to the letter + TclRequest *Req; +}; + +/// device/message for a single device +class TclSingleDeviceRequest : public TclRequest { +public: + TclSingleDeviceRequest(Tcl_Interp *interp, Tcl_Obj *dev, Tcl_Obj* m); + ~TclSingleDeviceRequest(); + int getStatus() {return status;} + int send(Tcl_cdevData *data, Tcl_Obj *&); + int sendCallback(Tcl_cdevData *data); +protected: + int status; + cdevRequestObjectPtr request; +}; + +/** devices/message for multiple devices + If the collection code ever matures, this code would try to use that. +*/ +class TclMultiDeviceRequest : public TclRequest { +public: + TclMultiDeviceRequest(Tcl_Interp *interp, Tcl_Obj *dev, Tcl_Obj* m); + ~TclMultiDeviceRequest(); + int send(Tcl_cdevData *data, Tcl_Obj *&); + int getStatus() {return status;} + int sendCallback(Tcl_cdevData *data); +protected: + int number, status, *statuss; + cdevRequestObjectPtr *requests; +}; + +/// Constructor of the envelope class +/// Create a letter class based on the length of the devices in argv[1] +TclRequest::TclRequest(Tcl_Interp *interp, int argc, char** argv) { + device = Tcl_NewStringObj(argv[1],-1); + message = Tcl_NewStringObj(argv[2],-1); + int objc; + Tcl_ListObjLength(interp, device, &objc); + if (objc == 1) { + Req = new TclSingleDeviceRequest(interp, device, message); + } else { + Req = new TclMultiDeviceRequest(interp, device, message); + } +} + +/// Constructor for the letter class +TclRequest::TclRequest(Tcl_Obj* dev, Tcl_Obj*m) : device(dev), message(m) { + Req = NULL; +} + +TclRequest::~TclRequest() { + delete Req; + if (device != NULL) Tcl_DecrRefCount(device); + if (message != NULL) Tcl_DecrRefCount(message); +} + +TclSingleDeviceRequest::TclSingleDeviceRequest(Tcl_Interp *interp, Tcl_Obj *dev, Tcl_Obj* m) : TclRequest(dev,m) { + int len; + status = CDEV_SUCCESS; + request = cdevRequestObject::attachPtr(Tcl_GetStringFromObj(device, &len), Tcl_GetStringFromObj(message, &len)); + if (request == NULL) { + status = CDEV_INVALIDOBJ; + Tcl_Obj *listv[3]; + listv[0] = Tcl_NewStringObj("Cannot find service for: ",-1); + listv[1] = device; + Tcl_IncrRefCount(device); + listv[2] = message; + Tcl_IncrRefCount(message); + Tcl_SetObjResult(interp, Tcl_NewListObj(3, listv)); + } +} + +TclSingleDeviceRequest::~TclSingleDeviceRequest() { + device = NULL; + message = NULL; +} + +TclMultiDeviceRequest::TclMultiDeviceRequest(Tcl_Interp *interp, Tcl_Obj *dev, Tcl_Obj* m) : TclRequest(dev,m) { + Tcl_Obj *obj, **objv; + Tcl_ListObjGetElements(NULL, device, &number, &objv); + int len; + requests = new cdevRequestObjectPtr[number]; + statuss = new int[number]; + status = CDEV_SUCCESS; + for (int i=0; ihasContext()) request->setContext(*(data->context)); + cdevData result; + status = request->send(data->out, result); + obj = Cdev_HandleResult( data, result); + return status; +} + +/// asynchronous send +int TclSingleDeviceRequest::sendCallback(Tcl_cdevData *data) { + if (status == CDEV_INVALIDOBJ) { + Tcl_Obj *sobj = Tcl_NewObj(); + Tcl_SetIntObj(sobj, status); + sobj = Tcl_ObjSetVar2(data->interp, data->statusname, data->cbtag, sobj, TCL_GLOBAL_ONLY); + return status; + } + if (data->hasContext()) request->setContext(*(data->context)); + int len; + cdevCallback *cb; + data->status = 1000; // preset it to "UNKNOWN" +// initialize the status + Tcl_Obj *sobj = Tcl_NewObj(); + Tcl_SetIntObj(sobj, data->status); + sobj = Tcl_ObjSetVar2(data->interp, data->statusname, data->cbtag, sobj, TCL_GLOBAL_ONLY); + if (strncmp(Tcl_GetStringFromObj(message, &len), "monitorOff", 10) == 0) { + cb = new cdevCallback(Cdev_CallbackFunction, NULL); + } else { + cb = new cdevCallback(Cdev_CallbackFunction, (void *) data); + } + if (request->sendCallback(data->out, *cb) != CDEV_SUCCESS) { + return CDEV_ERROR; + } + return CDEV_SUCCESS; +} + +/// synchronous send +int TclMultiDeviceRequest::send(Tcl_cdevData *data, Tcl_Obj *&obj) { + cdevData result; + Tcl_Obj *objv[number]; + int oldstatus = status; + status = CDEV_SUCCESS; + for (int i=0; ihasContext()) requests[i]->setContext(*data->context); + statuss[i] = requests[i]->send(data->out, result); + if (statuss[i] != CDEV_SUCCESS) { + status = statuss[i]; + } + } + objv[i] = Cdev_HandleResult( data, result); + } + obj = Tcl_NewListObj(number, objv); + if (oldstatus != CDEV_SUCCESS) status = oldstatus; + return status; +} + +/// asynchronous send +int TclMultiDeviceRequest::sendCallback(Tcl_cdevData *data) { + Tcl_Obj **objv; + Tcl_ListObjGetElements(NULL, device, &number, &objv); + int len; + cdevCallback *cb; + data->devices = device; + Tcl_IncrRefCount(device); + data->statuss = new int[number]; + for (int j=0; jhasContext()) requests[j]->setContext(*(data->context)); + requests[j]->setPrivate((void*) j); + data->statuss[j] = 1000; // preset it to "UNKNOWN" + Tcl_Obj *sobj = Tcl_NewObj(); + Tcl_SetIntObj(sobj, data->statuss[j]); + Tcl_Obj *st = Tcl_DuplicateObj(objv[j]); + Tcl_AppendStringsToObj(st, ".", Tcl_GetStringFromObj(data->cbtag,&len), NULL); + Tcl_ObjSetVar2(data->interp, data->statusname, st, sobj, TCL_GLOBAL_ONLY); + Tcl_DecrRefCount(st); + if (strncmp(Tcl_GetStringFromObj(message, &len), "monitorOff", 10) == 0) { + cb = new cdevCallback(Cdev_MultiCallbackFunction, NULL); + } else { + cb = new cdevCallback(Cdev_MultiCallbackFunction, (void *) data); + } + if (requests[j]->sendCallback(data->out, *cb) != CDEV_SUCCESS) { + } + } else { // RequestObj was invalid + Tcl_Obj *sobj = Tcl_NewObj(); + Tcl_SetIntObj(sobj, statuss[j]); + Tcl_Obj *st = Tcl_DuplicateObj(objv[j]); + Tcl_AppendStringsToObj(st, ".", Tcl_GetStringFromObj(data->cbtag,&len), NULL); + Tcl_ObjSetVar2(data->interp, data->statusname, st, sobj, TCL_GLOBAL_ONLY); + Tcl_DecrRefCount(st); + } + } + return CDEV_SUCCESS; +} + +static int Finished = 0; + +void Cdev_FileProc(ClientData clientData, int mask) { + int fd = (int) clientData; + if (mask == TCL_EXCEPTION) { + Tcl_DeleteFileHandler(fd); + return; + } + cdevSystem::defaultSystem().poll(); +} + +void Cdev_RegisterFD(int fd, int condition, void *) { + if (Finished == 1) { + return; + } + if (condition == 1) { + Tcl_CreateFileHandler(fd, TCL_READABLE|TCL_EXCEPTION, Cdev_FileProc, (ClientData) fd); + } else { + Tcl_DeleteFileHandler(fd); + } +} + +void Cdev_ExitProc(ClientData) { + Finished = 1; // cdev filehandler crashes when its deleted twice (at least that what I think is the problem) +} + +/** + Entry point for tcl command + Steps: + Attach to a RequestObject. Return TCL_ERROR if not valid (attachPtr returns NULL). + Parse the command line arguments into a cdevData and switches. + send or sendCallback the request. +*/ +int CdevCmd(ClientData, Tcl_Interp *interp, int argc, char **argv) { + if (argc < 3) { + Tcl_AppendResult(interp,"usage: cdev $device $message \"$tag $value\" ...", NULL); + return TCL_ERROR; + } + TclRequest request(interp, argc, argv); + + if (request.getStatus() != CDEV_SUCCESS) { + return TCL_ERROR; + } + Tcl_cdevData *data = new Tcl_cdevData(interp, argc-3, argv+3); + if (data->status != TCL_OK) { + delete data; + return TCL_ERROR; + } + Tcl_Obj *obj; + if (data->isAsynch()) { + request.sendCallback(data); + cdevSystem::defaultSystem().flush(); + cdevSystem::defaultSystem().poll(); + // keep data around + } else { + request.send(data, obj); + } + if (request.getStatus() != CDEV_SUCCESS) { + delete data; + if (!data->isAsynch()) { + Tcl_SetObjResult(interp, obj); + } + return TCL_ERROR; + } + if (!data->isAsynch()) { + Tcl_SetObjResult(interp, obj); + delete data; + } + return TCL_OK; +} + +int CdevErrorCodeCmd(ClientData, Tcl_Interp *interp, int argc, char **argv) { + if (argc < 2) { + Tcl_AppendResult(interp,"usage: cdeverrorcode $error", NULL); + return TCL_ERROR; + } + Tcl_Obj *obj = Tcl_NewStringObj(argv[1], -1); + int status; + if (Tcl_GetIntFromObj(interp, obj, &status) != TCL_OK) { + return TCL_ERROR; + } + Tcl_DecrRefCount(obj); + Tcl_SetObjResult(interp, Tcl_cdevData::getCdevErrorCode(status)); + return TCL_OK; +} + +int CdevDebugCmd(ClientData, Tcl_Interp *, int, char **) { + if (cdevdebug == 0) { + cdevdebug = 1; + } else { + cdevdebug = 0; + } + return TCL_OK; +} + +#ifdef SUN +#include +#endif +// Old way of polling, superseded by FileHandler calls, but since FD's are not working yet, still in use + +void Cdev_UpdateProc(ClientData dummy) { + cdevSystem::defaultSystem().poll(); + Tcl_CreateTimerHandler(200, Cdev_UpdateProc, dummy); +} + +//extern "C" int Cdev_Init(Tcl_Interp *interp) { +extern"C"int Tclcdev_Init(Tcl_Interp *interp) { + int i, numFD = 20; + int fds[numFD]; +#ifdef SUN + cdevCnsInit(); // Hook into the BNL ADO Nameserver +#endif + Tcl_cdevData::interp = interp; + Tcl_cdevData::ObjIniter(); + +// This installs cdev into the tcl FD select. + cdevSystem::defaultSystem().getFd(fds, numFD); + for (i=0;i +#include "blt.h" + +#include +#include +#include +#include +//#include + +// cdev includes +#include +#include +#include +#include +#include + +static int VALUE_TAG_ID =- 1; +#define VALUE_TAG ((VALUE_TAG_ID<0 && cdevData::tagC2I("value", &VALUE_TAG_ID)!= CDEV_SUCCESS)?-1:VALUE_TAG_ID) +static int STATUS_TAG_ID =- 1; +#define STATUS_TAG ((STATUS_TAG_ID<0 && cdevData::tagC2I("status", &STATUS_TAG_ID)!= CDEV_SUCCESS)?-1:STATUS_TAG_ID) +static int SEVERITY_TAG_ID =- 1; +#define SEVERITY_TAG ((SEVERITY_TAG_ID<0 && cdevData::tagC2I("severity", &SEVERITY_TAG_ID)!= CDEV_SUCCESS)?-1:SEVERITY_TAG_ID) + +typedef cdevRequestObject *cdevRequestObjectPtr; + +// class DeviceEntry { +// public: +// DeviceEntry(char*); +// ~DeviceEntry(); +// +// cdevRequestObject *request; +// cdevData result; +// int status; +// }; + + +class TclCdevCollection { +public: + TclCdevCollection(int, char**); + ~TclCdevCollection(); + + char *getAttrib(); + void setAttrib(char*); + + void getDevices(Tcl_Interp *); + void getStatus(Tcl_Interp *); + void getResult(Tcl_Interp *); + void getCallback(Tcl_Interp *); + int getLength() { return ndevices;} + void getVector(double*); + + static void deleteCollection(ClientData); + + int send(); + int sendCallback(Tcl_Interp*, char*); + int checkCallback(); + + static void callbackFunction(int, void *, cdevRequestObject&, cdevData &); + static void TimerHandler(ClientData); + +private: + cdevRequestObjectPtr *requests; + cdevData *results; + char **devices; + int ndevices; + char *attrib; + int *status, *callbacks; +}; + +TclCdevCollection::TclCdevCollection(int n, char** s) : ndevices(0), devices(NULL), attrib(NULL) { + if (n < 0) return; + + ndevices = n; + devices = new char*[ndevices]; + for (int i = 0; iptr; + c->status[info->index] = stat; + c->results[info->index] = result; + c->callbacks[info->index] = 1; +} + +int TclCdevCollection::checkCallback() { + int stat = 0; + for (int i = 0; i < ndevices; i++) { + if (callbacks[i] == 0) return 0; + } + return 1; +} + +void TclCdevCollection::TimerHandler(ClientData dummy) { + cdevSystem::defaultSystem().poll(); + callbackInfo2 *info = (callbackInfo2 *) dummy; + if (info->ptr->checkCallback()) { + // set something + Tcl_SetVar2(info->interp, "Control", info->s, "1", TCL_GLOBAL_ONLY); + delete info; + } else { /// try again later + Tcl_CreateTimerHandler(50, TclCdevCollection::TimerHandler, dummy); + } +} + +void TclCdevCollection::setAttrib(char* a) { + char message[256]; + delete attrib; + attrib = new char[strlen(a)+1]; + strcpy(attrib, a); + strcpy(message,"get "); + strcat(message, attrib); + for(int i = 0; i < ndevices; i++) { + requests[i] = cdevRequestObject::attachPtr(devices[i], message); + } +} + +char* TclCdevCollection::getAttrib() { + return attrib; +} + +void TclCdevCollection::getDevices(Tcl_Interp *interp) { + int i; + for (i = 0; i < ndevices; i++) { + Tcl_AppendElement(interp, devices[i]); + } +} + +void TclCdevCollection::getStatus(Tcl_Interp *interp) { + int i; + char res[256]; + for (i = 0; i < ndevices; i++) { + sprintf(res, "%d", status[i]); + Tcl_AppendElement(interp, res); + } +} + +void TclCdevCollection::getCallback(Tcl_Interp *interp) { + int i; + char res[256]; + for (i = 0; i < ndevices; i++) { + sprintf(res, "%d", callbacks[i]); + Tcl_AppendElement(interp, res); + } +} + +void TclCdevCollection::getResult(Tcl_Interp *interp) { + int i; + char res[300]; + for (i = 0; i < ndevices; i++) { + results[i].get(VALUE_TAG, res, 255); + Tcl_AppendElement(interp, res); + } +} + +void TclCdevCollection::getVector(double *res) { + for (int i = 0; i < ndevices; i++) { + results[i].get(VALUE_TAG, &res[i]); + } +} + +int TclCdevCollection::send() { + int stat = CDEV_SUCCESS; + int i; + for (i = 0; i < ndevices; i++) { + results[i].remove(); + status[i] = requests[i]->send(NULL, results[i]); + if ((status[i] != CDEV_SUCCESS) && (stat == CDEV_SUCCESS)) { + stat = CDEV_ERROR; + } + } + return stat; +} + +int TclCdevCollection::sendCallback(Tcl_Interp* interp, char* v) { + int stat = CDEV_SUCCESS; + for (int i = 0; i < ndevices; i++) { + results[i].remove(); + callbacks[i] = 0; + callbackInfo1* info1 = new callbackInfo1(this, i); + cdevCallback* cb = new cdevCallback(TclCdevCollection::callbackFunction, (void *) info1); + status[i] = requests[i]->sendCallback(NULL, *cb); + if ((status[i] != CDEV_SUCCESS) && (stat == CDEV_SUCCESS)) { + stat = CDEV_ERROR; + } + } + callbackInfo2 *info2 = new callbackInfo2(interp, this, v); + Tcl_SetVar2(interp, "Control", v, "0", TCL_GLOBAL_ONLY); + Tcl_CreateTimerHandler(50, TclCdevCollection::TimerHandler, (ClientData) info2); + return stat; +} + +void TclCdevCollection::deleteCollection(ClientData clientData) { + TclCdevCollection *collectionPtr; + collectionPtr = (TclCdevCollection *) clientData; + delete collectionPtr; +} + +int CollectionCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ + TclCdevCollection *collectionPtr; + collectionPtr = (TclCdevCollection *) clientData; + + if (strcmp(argv[1], "get") == 0) { + if (argc == 2) { // send it out to cdev // get + if (collectionPtr->getAttrib() == NULL) { + interp->result = "did not set attrib"; + return TCL_ERROR; + } + if (collectionPtr->send() == CDEV_SUCCESS) { + collectionPtr->getResult(interp); + return TCL_OK; + } + interp->result = "encountered cdev error"; + return TCL_ERROR; + } + if (strcmp(argv[2], "attrib") == 0) { // get attrib + Tcl_SetResult(interp, collectionPtr->getAttrib(), TCL_STATIC); + return TCL_OK; + } + if (strcmp(argv[2], "devices") == 0) { // get devices + collectionPtr->getDevices(interp); + return TCL_OK; + } + if (strcmp(argv[2], "status") == 0) { // get status + collectionPtr->getStatus(interp); + return TCL_OK; + } + if (strcmp(argv[2], "callback") == 0) { // get status + collectionPtr->getCallback(interp); + return TCL_OK; + } + if (strcmp(argv[2], "vector") == 0) { // get vector + if (argc != 4) return TCL_ERROR; + Blt_Vector vecInfo; + + if (!Blt_VectorExists(interp, argv[3])) { + interp->result = "vector does not exist"; + return TCL_ERROR; + } + if (collectionPtr->send() != CDEV_SUCCESS) { + interp->result = "encountered cdev error"; + return TCL_ERROR; + } + if (vecInfo.arraySize < collectionPtr->getLength()) { // resize if necc. + if (Blt_ResizeVector(interp, argv[3], collectionPtr->getLength()) != TCL_OK) return TCL_ERROR; + } + + if (Blt_GetVector(interp, argv[3], &vecInfo) != TCL_OK) return TCL_ERROR; + + vecInfo.numValues = collectionPtr->getLength(); + vecInfo.valueArr = (double *) malloc(sizeof(double) * collectionPtr->getLength()); + + collectionPtr->getVector(vecInfo.valueArr); + if (Blt_ResetVector(interp, argv[3], &vecInfo, TCL_DYNAMIC) != TCL_OK) { + return TCL_ERROR; + } + return TCL_OK; + } + } + + if (strcmp(argv[1], "set") == 0) { + if (argc != 4) return TCL_ERROR; + if (strcmp(argv[2], "attrib") == 0) { // set attrib $value + collectionPtr->setAttrib(argv[3]); + return TCL_OK; + } + } + + if (strcmp(argv[1], "sendcallback") == 0) { + if (strcmp(argv[2], "vector") == 0) { // sendcallback vector $v + if (argc != 4) return TCL_ERROR; + Blt_Vector vecInfo; + + if (!Blt_VectorExists(interp, argv[3])) { + interp->result = "vector does not exist"; + return TCL_ERROR; + } + if (collectionPtr->sendCallback(interp, argv[3]) != CDEV_SUCCESS) { + interp->result = "encountered cdev error"; + return TCL_ERROR; + } + return TCL_OK; + } + return TCL_ERROR; + } + + if (strcmp(argv[1], "checkcallback") == 0) { + if (collectionPtr->checkCallback()) { + interp->result = "1"; + } else { + interp->result = "0"; + } + return TCL_OK; + } + + if (strcmp(argv[1], "getcallback") == 0) { + if (strcmp(argv[2], "vector") == 0) { // getcallback vector $v + if (argc != 4) return TCL_ERROR; + Blt_Vector vecInfo; + + if (!Blt_VectorExists(interp, argv[3])) { + interp->result = "vector does not exist"; + return TCL_ERROR; + } + + if (!collectionPtr->checkCallback()) { + interp->result = "callbacks not ready"; + return TCL_ERROR; + } + + if (vecInfo.arraySize < collectionPtr->getLength()) { // resize if necc. + if (Blt_ResizeVector(interp, argv[3], collectionPtr->getLength()) != TCL_OK) return TCL_ERROR; + } + + if (Blt_GetVector(interp, argv[3], &vecInfo) != TCL_OK) return TCL_ERROR; + + vecInfo.numValues = collectionPtr->getLength(); + vecInfo.valueArr = (double *) malloc(sizeof(double) * collectionPtr->getLength()); + + collectionPtr->getVector(vecInfo.valueArr); + if (Blt_ResetVector(interp, argv[3], &vecInfo, TCL_DYNAMIC) != TCL_OK) { + return TCL_ERROR; + } + return TCL_OK; + } + } + + interp->result = "unknown command"; + return TCL_ERROR; +} + +int MakeCollectionCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ + TclCdevCollection *collectionPtr; + static int id = 0; + int c1; + char** s1; + + if (argc < 2 || argc >3) { + interp->result = "wrong # args"; + return TCL_ERROR; + } + + if(Tcl_SplitList(interp, argv[1], &c1, &s1) != TCL_OK) { + return TCL_ERROR; + } + + collectionPtr = new TclCdevCollection(c1,s1); + free ((char*) s1); + + sprintf(interp->result, "col%d", id); + id++; + + Tcl_CreateCommand(interp, interp->result, CollectionCmd, (ClientData) collectionPtr, TclCdevCollection::deleteCollection); + + if (argc == 3) { + collectionPtr->setAttrib(argv[2]); + } + + return TCL_OK; +} + + +extern "C" int Cdevcollection_Init(Tcl_Interp *interp) { + + Tcl_PkgRequire(interp, "BLT", "2.4", 0); + Tcl_PkgRequire(interp, "Cdev", "", 0); + + if(Tcl_PkgProvide(interp, "Cdevcollection", "1.0") != TCL_OK) { + return TCL_ERROR; + } + + Tcl_CreateCommand(interp, "cdevcollection", MakeCollectionCmd, (ClientData *) NULL, (Tcl_CmdDeleteProc *) NULL); + return TCL_OK; +} + + diff --git a/extensions/tclnew/tcl_cdevcollections.o b/extensions/tclnew/tcl_cdevcollections.o new file mode 100644 index 0000000..0b24eb9 Binary files /dev/null and b/extensions/tclnew/tcl_cdevcollections.o differ diff --git a/extensions/tclnew/tcl_cdevvector.cc b/extensions/tclnew/tcl_cdevvector.cc new file mode 100644 index 0000000..435c77b --- /dev/null +++ b/extensions/tclnew/tcl_cdevvector.cc @@ -0,0 +1,435 @@ +// March, 97, start +// cdev $vector $device $message ... .. + +#include +#include "blt.h" + +#include +#include +#include +#include +//#include + +// cdev includes +#include +#include +#include +#include +#include + +static int VALUE_TAG_ID =- 1; +#define VALUE_TAG ((VALUE_TAG_ID<0 && cdevData::tagC2I("value", &VALUE_TAG_ID)!= CDEV_SUCCESS)?-1:VALUE_TAG_ID) +// static int STATUS_TAG_ID =- 1; +// #define STATUS_TAG ((STATUS_TAG_ID<0 && cdevData::tagC2I("status", &STATUS_TAG_ID)!= CDEV_SUCCESS)?-1:STATUS_TAG_ID) +// static int SEVERITY_TAG_ID =- 1; +// #define SEVERITY_TAG ((SEVERITY_TAG_ID<0 && cdevData::tagC2I("severity", &SEVERITY_TAG_ID)!= CDEV_SUCCESS)?-1:SEVERITY_TAG_ID) + +static int cdevdebug = 0; + +class tclCdevDataV { + public: + tclCdevDataV(); + void parse(Tcl_Interp*, char* *, int); + ~tclCdevDataV(); + + cdevData out, context; + int hascontext; + + int tagn, *taglist; + char *callbacktag; + + int state, async; +}; + +tclCdevDataV::~tclCdevDataV() { + delete taglist; +} + +tclCdevDataV::tclCdevDataV():hascontext(0), tagn(0), taglist(NULL), async(0), state(TCL_ERROR) { +}; + +// Parses command line, fills up the outgoing cdevData and the context (if any) +void tclCdevDataV::parse(Tcl_Interp *interp, char **argv, int argc) { + int i, c1, c2; + cdevData *ptr; + char **s1 = NULL; + char **s2 = NULL; + + // Point to 'out' cdevData until we hit the context (if any) + ptr = &out; + for(i = 3; i < argc; i++) { + // skip 'cdev' '$device' and '$message' + if(Tcl_SplitList(interp, argv[i], &c1, &s1) != TCL_OK) { + return; + } + if(c1 == 2) { + // {tag value} pair, check if the value is a scalar + if(Tcl_SplitList(interp, s1[1], &c2, &s2) != TCL_OK) { + free((char *) s1); + return; + } + if(c2 == 1) { + // we have a scalar + ptr->insert(s1[0], s1[1]); + // insert scalar + } + else { + ptr->insert(s1[0], s2, c2); + // insert vector of scalars, does not handle matrices + } + free((char *) s2); + } + else if(c1 == 1) { + // can be one of "-context" , "-tags" or a callbacktag + if(strcmp(argv[i], "-context") == 0) { + // all remaining 'tag value' pairs go in the context + ptr = &context; + hascontext = 1; + } + else if(strcmp(argv[i], "-tags") == 0) { + // get the list of tags to print out from the result data + i++; + // points to next entry in argv + if(i == argc) { + interp->result = "expected tag names"; + free((char *) s1); + return; + } + if(Tcl_SplitList(interp, argv[i], &tagn, &s2) != TCL_OK) { + interp->result = "tag problem"; + free((char *) s1); + return; + } + else { + taglist = new int[tagn]; + for(int j = 0; j < tagn; j++) { + if(cdevData::tagC2I(s2[j], &taglist[j]) != CDEV_SUCCESS) { + interp->result = "unknown tag"; + free((char *) s2); + free((char *) s1); + return; + } + } + } + free((char *) s2); + } + else { + // single entry, a callbacktag, better be at end of input + if(i != argc-1) { + interp->result = "expecting callbacktag at end"; + free((char *) s1); + return; + } + // Here we have a callback tag, hence we want to send asynchronously + callbacktag = argv[i]; + async = 1; + } + } + else { + // c1 > 2 + // tag / string pair (i.e. "value this is a string with spaces embedded" + char **av = s1; + av++; + char *concat = Tcl_Concat(c1-1, av); + ptr->insert(s1[0], concat); + if(cdevdebug == 1) { + fprintf(stderr, "inserted: %s, with value: %s\n", s1[0], concat); + } + free(concat); + } + free((char *) s1); + } + state = TCL_OK; +} + +class callbackInfoV { + public: + callbackInfoV(Tcl_Interp*, char *, Blt_Vector); // vectorname + callbackInfoV(Tcl_Interp*, char *, Blt_Vector, int); // vectorname + ~callbackInfoV(); + Tcl_Interp *interp; + cdevCallback *callback; + Blt_Vector vecInfo; + char *vecName; + int index; +}; + +callbackInfoV::callbackInfoV(Tcl_Interp *e, char *arg, Blt_Vector i) { + interp = e; + vecName = new char[strlen(arg)+1]; + vecInfo = i; + strcpy(vecName, arg); + callback = NULL; + index = -1; +} + +callbackInfoV::callbackInfoV(Tcl_Interp *e, char *arg, Blt_Vector i, int ind) { + interp = e; + vecName = new char[strlen(arg)+1]; + vecInfo = i; + strcpy(vecName, arg); + callback = NULL; + index = ind; +} + +callbackInfoV::~callbackInfoV() { + delete vecName; +} + +cdevBounds *BoundsV; +int DimV; + +int HandleTagV(Tcl_Interp *interp, cdevData &result, Blt_Vector *vecInfo, char* vecname, int index) { + int i, len; + size_t dim; + + if(result.getDim(VALUE_TAG, &dim) != CDEV_SUCCESS) { + return TCL_ERROR; + } + + if( ((dim == 0) && (index < 0)) || ((dim == 1) && (index >= 0)) ) { + return TCL_ERROR; + } + + if (dim == 0) { + if (vecInfo->numValues <= index) { + return TCL_ERROR; + } + vecInfo->valueArr[index] = (double)result; + return Blt_ResetVector(interp, vecname, vecInfo, TCL_DYNAMIC); + } + + // dim = 1 + DimV = (int) dim; + BoundsV = new cdevBounds[DimV]; + result.getBounds(VALUE_TAG, BoundsV, DimV); + len = 1; + for(i = 0; i < DimV; i++) { + len *= BoundsV[i].length; + } + + if (vecInfo->arraySize < len) { // resize if necc. + if (Blt_ResizeVector(interp, vecname, len) != TCL_OK) return TCL_ERROR; + Blt_GetVector(interp, vecname, vecInfo); + } + + result.get(VALUE_TAG, vecInfo->valueArr); + + delete BoundsV; + if (Blt_ResetVector(interp, vecname, vecInfo, TCL_DYNAMIC) != TCL_OK) { + return TCL_ERROR; + } + return TCL_OK; +} + +// executes inside poll() whenever 'file' is readable +void Cdev_CallbackFunctionV(int, void *userarg, cdevRequestObject&, cdevData &result) { + // could check status and do appropriate action like: set Error(info->s) ??? + callbackInfoV *info = (callbackInfoV *) userarg; + HandleTagV(info->interp, result, &info->vecInfo, info->vecName, info->index); +} + +// same as above, plus removes callbackinfo +void Cdev_CallbackFunctionOnceV(int, void *userarg, cdevRequestObject&, cdevData &result) { + callbackInfoV *info = (callbackInfoV *) userarg; + HandleTagV(info->interp, result, &info->vecInfo, info->vecName, info->index); + delete info; +} + +typedef cdevRequestObject *cdevRequestObjectPtr; + +int CdevVectorCmd(ClientData, Tcl_Interp *interp, int argc, char **argv) { + // cdevvector vector device message {tag value} {..} cb + + cdevData result; + cdevCallback *cb = NULL; + callbackInfoV *info; + tclCdevDataV data; + int n, delinfo = 0; + Blt_Vector vecInfo; + char **devices = NULL; + cdevRequestObjectPtr request, *requests; + + if(argc < 4) { + Tcl_AppendResult(interp, "cdevvector: wrong # args", (char *) NULL); + return TCL_ERROR; + } + + if (!Blt_VectorExists(interp, argv[1])) { + if (Blt_CreateVector(interp, argv[1], 64, &vecInfo) != TCL_OK) { + interp->result = "vector creation error"; + return TCL_ERROR; + } + } else { + if (Blt_GetVector(interp, argv[1], &vecInfo) != TCL_OK) { + return TCL_ERROR; + } + } + + int ndevices = 0; + + if(Tcl_SplitList(interp, argv[2], &ndevices, &devices) != TCL_OK) { + return TCL_ERROR; + } + + if (ndevices == 1) { + request = cdevRequestObject::attachPtr(argv[2], argv[3]); + free((char*)devices); + } else { + requests = new cdevRequestObjectPtr[ndevices]; + for(n = 0; n < ndevices; n++) { + requests[n] = cdevRequestObject::attachPtr(devices[n], argv[3]); + } + if (vecInfo.arraySize < ndevices) { // resize if necc. + if (Blt_ResizeVector(interp, argv[1], ndevices) != TCL_OK) return TCL_ERROR; + Blt_GetVector(interp, argv[1], &vecInfo); + } + free((char *) devices); + } + + data.parse(interp, argv+1, argc-1); + + if(data.state != TCL_OK) { + return TCL_ERROR; + } + + if(strncmp(argv[3], "monitorOn", 9) == 0) data.async = 1; + + if(data.async) { + // we want to sent it async + + if (ndevices == 1) { + info = new callbackInfoV(interp, argv[1], vecInfo); + + if(strncmp(argv[3], "monitorOn", 9) == 0) { + cb = new cdevCallback(Cdev_CallbackFunctionV, (void *) info); + } + else if(strncmp(argv[3], "monitorOff", 10) == 0) { + delinfo = 1; + cb = new cdevCallback(NULL, NULL); + } + else { + cb = new cdevCallback(Cdev_CallbackFunctionOnceV, (void *) info); + } + + info->callback = cb; + + if(data.hascontext) { + if(request->setContext(data.context) != CDEV_SUCCESS) { + interp->result = "setContext error"; + delete info; + return TCL_ERROR; + } + } + + if(request->sendCallback(data.out, *cb) != CDEV_SUCCESS) { + delete info; + return TCL_ERROR; + } else { + if(delinfo) delete info; + return TCL_OK; + } + } else { // ndevices > 1 + int j = 0; + + if(strncmp(argv[3], "monitorOn", 9) == 0) { + j = 1; + } + else if(strncmp(argv[3], "monitorOff", 10) == 0) { + j = 2; + } + + for(n = 0; n < ndevices; n++) { + info = new callbackInfoV(interp, argv[1], vecInfo, n); + + if(j == 1) { + cb = new cdevCallback(Cdev_CallbackFunctionV, (void *) info); + } + else if(j == 2) { + delinfo = 1; + cb = new cdevCallback(NULL, NULL); + } + else { + cb = new cdevCallback(Cdev_CallbackFunctionOnceV, (void *) info); + } + + info->callback = cb; + + if(data.hascontext) { + if(requests[n]->setContext(data.context) != 0) { + interp->result = "setContext error"; + delete [] requests; + delete info; + return TCL_ERROR; + } + } + if(requests[n]->sendCallback(data.out, *cb) != CDEV_SUCCESS) { + delete [] requests; + delete info; + return TCL_ERROR; + } else { + if(delinfo) delete info; + } + } + delete [] requests; + return TCL_OK; + } + } + + // send it sync + if (ndevices == 1) { + if(data.hascontext) { + if(request->setContext(data.context) != CDEV_SUCCESS) { + interp->result = "setContext error"; + return TCL_ERROR; + } + } + + if(request->send(data.out, result) != CDEV_SUCCESS) { + sprintf(interp->result, "error in send: %s %s", argv[2], argv[3]); + return TCL_ERROR; + } + + HandleTagV(interp, result, &vecInfo, argv[1], -1); + + return TCL_OK; + } else { + for(n = 0; n < ndevices; n++) { + if(data.hascontext) { + if(requests[n]->setContext(data.context) != 0) { + interp->result = "setContext error"; + delete [] requests; + delete info; + return TCL_ERROR; + } + } + if(requests[n]->send(data.out, result) != CDEV_SUCCESS) { + delete [] requests; + delete info; + return TCL_ERROR; + } else { + if(delinfo) delete info; + HandleTagV(interp, result, &vecInfo, argv[1], n); + } + } + delete [] requests; + return TCL_OK; + } +} + +extern "C" int Cdevvector_Init(Tcl_Interp *interp) { + + Tcl_PkgRequire(interp, "BLT", "2.4", 0); + Tcl_PkgRequire(interp, "Cdev", "", 0); + + if(Tcl_PkgProvide(interp, "Cdevvector", "1.0") != TCL_OK) { + return TCL_ERROR; + } + + Tcl_CreateCommand(interp, "cdevvector", CdevVectorCmd, (ClientData *) NULL, (Tcl_CmdDeleteProc *) NULL); + + return TCL_OK; +} + + + diff --git a/extensions/tclnew/tcl_cdevvector.o b/extensions/tclnew/tcl_cdevvector.o new file mode 100644 index 0000000..f23503c Binary files /dev/null and b/extensions/tclnew/tcl_cdevvector.o differ diff --git a/extensions/tclnew/tcltest.cc b/extensions/tclnew/tcltest.cc new file mode 100644 index 0000000..54ae5ed --- /dev/null +++ b/extensions/tclnew/tcltest.cc @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +//#include + +// cdev includes +#include +#include +#include +#include +#include + +#include + +typedef cdevRequestObject *cdevRequestObjectPtr; + +int TcltestCmd(ClientData, Tcl_Interp *interp, int argc, char **argv) { + + char **devices = NULL; + int i, n, ndevices; + Tcl_DString ds; + cdevData result; + cdevCallback *cb = NULL; + cdevRequestObjectPtr request, *requests; + int delinfo = 0; + void *handle; + + printf("TcltestCmd: \n"); + + handle = dlopen ("/home/pss060/sls/hunt/cdev-1.6/lib/linux/1.6/caService.so", RTLD_LAZY); + if (!handle) { + fputs (dlerror(), stderr); + exit(1); + } + + +/* + printf("TcltestCmd: ndevices=1 argv[1]= %s argv[2]=%s\n",argv[1],argv[2]); + request = cdevRequestObject::attachPtr(argv[1], argv[2]); + return TCL_OK; +// free((char*)devices); + + printf("have got request object\n"); + + // send it sync + + if(request->send(NULL, result) != CDEV_SUCCESS) { + sprintf(interp->result, "error in send: %s %s", argv[1], argv[2]); + return TCL_ERROR; + } else { + result.asciiDump(stdout); + } +*/ + + return TCL_OK; +} + +extern"C"int Tcltest_Init(Tcl_Interp *interp) { + + printf("This is Tcltest_Init \n"); + + + if(Tcl_PkgProvide(interp, "Tcltest", TCLCDEV_VERSION) != TCL_OK) { + return TCL_ERROR; + } + Tcl_CreateCommand(interp,"tcltest", TcltestCmd, (ClientData *) NULL, (Tcl_CmdDeleteProc *) NULL); + printf("end of Tcltest_Init \n"); + return TCL_OK; +} + + + diff --git a/extensions/tclnew/test_cout.cc b/extensions/tclnew/test_cout.cc new file mode 100644 index 0000000..a2be570 --- /dev/null +++ b/extensions/tclnew/test_cout.cc @@ -0,0 +1,11 @@ + +#include +#include +#include +#include + +main () { + + cout << "hello world"; + +} diff --git a/extensions/tclnew/testit b/extensions/tclnew/testit new file mode 100755 index 0000000..b17a8ba --- /dev/null +++ b/extensions/tclnew/testit @@ -0,0 +1,22 @@ +#!/usr/bin/wish8.0 +load libtclcdev.so + +cdev hunt:ai001 "set VAL" "value 123.5" +cdev hunt:ai001 "get VAL" + +label .l -textvariable Control(hunt:ai001.VAL) -width 10 +pack .l +cdev hunt:ai001 "monitorOn VAL" hunt:ai001.VAL + +scale .s -variable dummy -command {cdev hunt:ai001 "set VAL" "value $dummy"} +pack .s + +cdev hunt:bi001 "set VAL" "value 1" +cdev hunt:bi001 "get VAL" + +label .l -textvariable Control(sls_bi0:b1.VAL) -width 10 +pack .l +cdev sls_bi0:b1 "monitorOn VAL" sls_bi0:b1.VAL + + + diff --git a/extensions/tclnew/tkAppInit.cc b/extensions/tclnew/tkAppInit.cc new file mode 100644 index 0000000..aaeb3c6 --- /dev/null +++ b/extensions/tclnew/tkAppInit.cc @@ -0,0 +1,119 @@ +/* + * tkAppInit.c -- + * + * Provides a default version of the Tcl_AppInit procedure for + * use in wish and similar Tk-based applications. + * + * Copyright (c) 1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#ifndef lint +static char sccsid[] = "@(#) tkAppInit.c 1.15 95/06/28 13:14:28"; +#endif /* not lint */ + +#include "tk.h" +#include + +/* + * The following variable is a special hack that is needed in order for + * Sun shared libraries to be used for Tcl. + */ + +//extern int matherr(); +//int *tclDummyMathPtr = (int *) matherr; + +/* + *---------------------------------------------------------------------- + * + * main -- + * + * This is the main program for the application. + * + * Results: + * None: Tk_Main never returns here, so this procedure never + * returns either. + * + * Side effects: + * Whatever the application does. + * + *---------------------------------------------------------------------- + */ + +int main(int argc, char **argv) +{ + Tk_Main(argc, argv, Tcl_AppInit); + return 0; /* Needed only to prevent compiler warning. */ +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_AppInit -- + * + * This procedure performs application-specific initialization. + * Most applications, especially those that incorporate additional + * packages, will have their own version of this procedure. + * + * Results: + * Returns a standard Tcl completion code, and leaves an error + * message in interp->result if an error occurs. + * + * Side effects: + * Depends on the startup script. + * + *---------------------------------------------------------------------- + */ + +extern "C" Extension_Init(Tcl_Interp* interp); +extern "C" Cdev_Init (Tcl_Interp *interp); + +int +Tcl_AppInit(Tcl_Interp *interp) +{ + /* + * Tk_Window main; + */ + + if (Tcl_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + if (Tk_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + + /* + * Call the init procedures for included packages. Each call should + * look like this: + * + * if (Mod_Init(interp) == TCL_ERROR) { + * return TCL_ERROR; + * } + * + * where "Mod" is the name of the module. + */ + + Extension_Init(interp); + + if (Cdev_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + + /* + * Call Tcl_CreateCommand for application-specific commands, if + * they weren't already created by the init procedures called above. + */ + + /* + * Specify a user-specific startup file to invoke if the application + * is run interactively. Typically the startup file is "~/.apprc" + * where "app" is the name of the application. If this line is deleted + * then no user-specific startup file will be run under any conditions. + */ + + tcl_RcFileName = "~/.wishrc"; + return TCL_OK; +} diff --git a/extensions/tclnew/tmp b/extensions/tclnew/tmp new file mode 100644 index 0000000..df28222 --- /dev/null +++ b/extensions/tclnew/tmp @@ -0,0 +1,9 @@ +CDEVDDL=/home/pss060/sls/ubash/cdev_lin/PACKAGES/cdev/cdev_psi_1.7/ddl/master.bdd +CDEVINCLUDE=/home/pss060/sls/ubash/cdev_lin/PACKAGES/cdev/cdev_psi_1.7/include +CDEVSHOBJ=/home/pss060/sls/ubash/cdev_lin/PACKAGES/cdev/cdev_psi_1.7/lib/Linux +CDEVVERSION=1.7 +CDEV_NAME_SERVER=localhost +CDEV=/home/pss060/sls/ubash/cdev_lin/PACKAGES/cdev/cdev_psi_1.7 +CDEVLIB=/home/pss060/sls/ubash/cdev_lin/PACKAGES/cdev/cdev_psi_1.7/lib/Linux +CDEVBIN=/home/pss060/sls/ubash/cdev_lin/PACKAGES/cdev/cdev_psi_1.7/bin/Linux +CDEV_ACCOUNT_FILE=/home/pss060/sls/ubash/cdev_lin/PACKAGES/cdev/cdev_psi_1.7/ddl/cdevAccount.txt diff --git a/include/StringHash.h b/include/StringHash.h new file mode 100644 index 0000000..afdfb40 --- /dev/null +++ b/include/StringHash.h @@ -0,0 +1,235 @@ +#ifndef _VAR_STRING_HASH_H_ +#define _VAR_STRING_HASH_H_ 1 + +#include +#include +#include + +class StringHashNode +{ +friend class StringHash; +friend class StringHashIterator; + +private: + int copyKeyFlag; + char * hashString; + void * hashData; + StringHashNode * next; + + StringHashNode ( char * HashString, void * HashData, int copyKey=1); + ~StringHashNode ( void ); +}; + + +class StringHash +{ +friend class StringHashIterator; + +private: + int tableSize; + int copyKeyFlag; + StringHashNode ** nodes; + +public: + StringHash (int copyKey = 1, int TableSize = 255 ); + ~StringHash ( void ); + + inline unsigned int stringHash ( char * hashString ); + + inline void insert ( char * hashString, void * hashData ); + inline void remove ( char * hashString ); + inline void * find ( char * hashString ); +}; + + +class StringHashIterator +{ +private: + StringHash * hashTbl; + StringHashNode * node; + int idx; + +public: + StringHashIterator( StringHash * HashTbl ); + ~StringHashIterator( void ); + + inline void * first ( void ); + inline void * operator ++ ( void ); + inline void * operator ++ ( int x ); + inline char * key ( void ); + inline void * data ( void ); +}; + + +inline StringHashNode::StringHashNode ( char * HashString, void * HashData, int copyKey ) + : next(NULL), copyKeyFlag(copyKey) + { + if(copyKeyFlag) hashString = strdup(HashString); + else hashString = HashString; + hashData = HashData; + } + + +inline StringHashNode::~StringHashNode ( void ) + { + if(copyKeyFlag) delete hashString; + } + + +inline StringHash::StringHash ( int copyKey, int TableSize ) + : copyKeyFlag(copyKey), tableSize (TableSize) + { + nodes = new StringHashNode * [tableSize]; + memset(nodes, 0, sizeof(StringHashNode *) * tableSize ); + } + + +inline StringHash::~StringHash ( void ) + { + for(int i=0; inext; + delete node; + } + } + delete nodes; + } + +inline unsigned int StringHash::stringHash ( char * hashString ) + { + unsigned int hash = 0, g; + + for (int i = 0; hashString[i] != '\0'; i++) + { + hash = (hash << 4) + hashString[i]; + if (g = hash & 0xf0000000) + { + hash ^= g >> 24; + hash ^= g; + } + } + return (hash % tableSize); + } + +inline void StringHash::insert (char * hashString, void * hashData ) + { + unsigned int idx = stringHash(hashString); + StringHashNode * prev = NULL, * node = nodes[idx]; + StringHashNode * newNode = new StringHashNode(hashString, hashData, copyKeyFlag); + + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + newNode->next = node->next; + delete node; + } + if(prev!=NULL) prev->next = newNode; + else nodes[idx] = newNode; + } + +inline void StringHash::remove ( char * hashString ) + { + unsigned int idx = stringHash(hashString); + StringHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + if(prev!=NULL) prev->next = node->next; + else nodes[idx] = node->next; + delete node; + } + } + +inline void * StringHash::find ( char * hashString ) + { + unsigned int idx = stringHash(hashString); + StringHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + return node!=NULL?node->hashData:NULL; + } + + +inline StringHashIterator::StringHashIterator(StringHash * HashTbl) + : hashTbl(HashTbl), idx(0), node(NULL) + { + } + +inline StringHashIterator::~StringHashIterator( void ) + { + } + +inline void * StringHashIterator::first ( void ) + { + if(hashTbl!=NULL) + { + for(idx = 0; idxtableSize && + (node = hashTbl->nodes[idx])==NULL; idx++); + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * StringHashIterator::operator ++ ( void ) + { + if(hashTbl!=NULL) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxtableSize && + (node = hashTbl->nodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * StringHashIterator::operator ++ ( int x ) + { + if(hashTbl!=NULL && x==0) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxtableSize && + (node = hashTbl->nodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline char * StringHashIterator::key ( void ) + { + return (node!=NULL)?node->hashString:(char *)NULL; + } + +inline void * StringHashIterator::data ( void ) + { + return (node!=NULL)?node->hashData:NULL; + } + +#endif /* _VAR_STRING_HASH_H_ */ diff --git a/include/cdev.h b/include/cdev.h new file mode 100644 index 0000000..3875332 --- /dev/null +++ b/include/cdev.h @@ -0,0 +1,393 @@ +/*----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + *----------------------------------------------------------------------------- + * + * Description: + * C public interface for CDEV + * + * Authors: Danjin Wu & Jie Chen + * + * Revision History: + * cdev.h,v + * Revision 1.3 1997/08/27 18:24:18 chen + * include cdevVersion.h + * + * Revision 1.2 1996/03/22 17:56:51 chen + * add cdevFdChangedCallback + * + * Revision 1.1 1995/12/14 19:09:16 chen + * cdev C interface for C programs + * + * + */ +#ifndef _CDEV_CBINDING_H +#define _CDEV_CBINDING_H + +#include +#include +#include +#include +#include + +typedef long cdev_data_t; +typedef long cdev_request_t; +typedef long cdev_system_t; +typedef long cdev_group_t; + +/************************************************************************* + * User error reporting function * + *************************************************************************/ +typedef void (*cdevErrHandler) (int severity, + char* text, + cdev_request_t req); + +/************************************************************************* + * User fd changed callback function * + *************************************************************************/ +typedef void (*cdevFdChangedCallback) (int fd, + int opened, + void* arg); + +/************************************************************************** + * User callback function * + *************************************************************************/ +typedef void (*cdevCbkFunc) (int status, + void* userarg, + cdev_request_t req, + cdev_data_t data); + +typedef struct _cbk_t_ +{ + cdevCbkFunc func; + void* arg; + /* the following element is not for public use */ + void* cxxpart; +}cdev_cbk, *cdev_cbk_t; + +/************************************************************************** + * HPUX C call C++ convention * + * User must call this before any other routines to * + * Initialize all static objects * + **************************************************************************/ +#ifdef __hpux +#define CDEV_INIT() (_main () ) +#endif + +/************************************************************************** + * CDEV supported data types inside cdev_data_t * + **************************************************************************/ +#define CDEV_BYTE_ 0 /* unsigned character */ +#define CDEV_INT_16 1 /* 16 bits integer */ +#define CDEV_UINT_16 2 /* unsigned 16 bits integer */ +#define CDEV_INT_32 3 /* 32 bits integer */ +#define CDEV_UINT_32 4 /* unsigned 32 bits integer */ +#define CDEV_FLT 5 /* float */ +#define CDEV_DBL 6 /* double */ +#define CDEV_STR 7 /* character string */ +#define CDEV_TS 8 /* structured time stamp with sec and nsec */ +#define CDEV_INVALID_TYPE 9 /* not belongs to any type above */ + +#define CDEV_IMMEDIATE 0 /* cdev group exection immediately */ +#define CDEV_DEFERRED 1 /* cdev group exection deferred */ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************** + * C interface for cdev_data_t * + *************************************************************************/ + +/* create and allocate for cdev_data_t */ +extern CDEVAPI int cdevDataAllocate (cdev_data_t *id); + +/* free memory associated with cdev_data_t */ +extern CDEVAPI void cdevDataFree (cdev_data_t id); + +/* convert a character string tag to an integer tag */ +extern CDEVAPI int cdevDataTagC2I (char *tag, int *tagid); + +/* convert an integer tag to a character string tag. */ +/* the return tag is a pointer to internal char string. */ +/* do not free the tag !!! */ +extern CDEVAPI int cdevDataTagI2C (int tagid, char **tag); + +/* insert an new tag to cdev_data_t data */ +extern CDEVAPI void cdevDataInsertTag (int tagid, char *tag); + +/* insert a new data with data type 'type' pointed by data */ +extern CDEVAPI int cdevDataInsert (cdev_data_t id, int tagid, + int type, void *data); + +/* insert an array of data into cdev_data_t */ +extern CDEVAPI int cdevDataInsertArray (cdev_data_t id, int tagid, + int type, void *data, + size_t len, size_t ndim); + +/* retrieve data with tag 'tagid' to memory pointed by 'data' */ +extern CDEVAPI int cdevDataGet (cdev_data_t id, int tagid, + int type, void *data); + +/* return the memory address of data with tag 'tagid' */ +extern CDEVAPI int cdevDataFind (cdev_data_t id, int tagid, void **data); + +/* return data type associated with tag 'tagid' */ +extern CDEVAPI int cdevDataGetType (cdev_data_t id, int tagid, int *type); + +/* return dimention information with tag 'tagid' */ +extern CDEVAPI int cdevDataGetDim (cdev_data_t id, int tagid, size_t *dim); + +/* get number of elements associated with tag 'tagid' */ +extern CDEVAPI int cdevDataGetElems (cdev_data_t id, int tagid, size_t *elems); + +/* get information about where to start/end inside the multiple */ +/* dimentional array of data for this tag 'tagid' */ +extern CDEVAPI int cdevDataGetBounds (cdev_data_t id, int tagid, + size_t *bounds, size_t bsize); + +/* set information about where to start/end inside the multiple */ +/* dimentional array of data for this tag 'tagid' */ +extern CDEVAPI int cdevDataSetBounds (cdev_data_t id, int tagid, + size_t *bounds, size_t bsize); + +/* remove all data inside cdev_data_t 'id' */ +extern CDEVAPI void cdevDataRemoveAll (cdev_data_t id); + +/* remove a single data item from a cdev_data_t with tag 'tagid' */ +extern CDEVAPI void cdevDataRemove (cdev_data_t id, int tagid); + +/* change tag associated with a data item from 'tagid' to 'newtagid' */ +extern CDEVAPI int cdevDataChangeTag (cdev_data_t id, int tagid, int newtagid); + +/* print out ASCII representation of all internal data of 'id' */ +#ifdef _WIN32 +extern CDEVAPI void cdevDataAsciiDump (cdev_data_t id); +#else +extern CDEVAPI void cdevDataAsciiDump (cdev_data_t id, FILE *fp); +#endif + +/* copy cdev_data_t from 'from' to 'to' */ +extern CDEVAPI void cdevDataCopy (cdev_data_t from, cdev_data_t *to); + +/************************************************************************* + * C interface for setting up user callback routines * + ************************************************************************/ + +/* create cdev_cbk_t structure with 'func' and 'arg' */ +extern CDEVAPI int cdevCbkAllocate (cdevCbkFunc func, void* arg, cdev_cbk_t* id); + +/* destroy/free cdev_cbk_t structure pointed by id */ +extern CDEVAPI void cdevCbkFree (cdev_cbk_t id); + +/************************************************************************ + * C interface for cdev global system * + ***********************************************************************/ + +/* get a handle on the default system, do not use it now :-) */ +extern CDEVAPI int cdevDefaultSystem (cdev_system_t* sys); + +/* return all file descriptors inside the cdev. caller provide */ +/* buffer for fds and intial value of numFds should be the buffer */ +/* size. e.g. int fds[10], numFds = 10, cdevGetFds (fds, &numFds) */ +/* If success, numFds has real number of fd */ +extern CDEVAPI int cdevGetFds (int fds[], int* numFds); + +/* add a callback function which will be called when file */ +/* descriptors monitored by the system closed/opend */ +/* Note: service dependent. Underlying cdevService must provide */ +/* some mechanism to notify the system (see caService) */ +extern CDEVAPI int addFdChangedCallback (cdevFdChangedCallback cbk, void* arg); + +/* flush out all network requests */ +extern CDEVAPI int cdevFlush (void); + +/* wait for network requests to come back for upto 'seconds' */ +/* long. If seconds = 0.0, wait forever */ +extern CDEVAPI int cdevPend (double seconds); + +/* poll the network to see whether there are outstanding I/O */ +/* events on all communication channels. */ +extern CDEVAPI int cdevPoll (void); + +/* turn automatic error reporting mechanism on: system error */ +/* reporting function will be in charge */ +extern CDEVAPI int cdevAutoErrorOn (void); + +/* turn automatic error reporting mechanism off: user error */ +/* reporting function will be in charge (if there is one) */ +extern CDEVAPI int cdevAutoErrorOff (void); + +/* set error reporting threshold. check cdev_error_code.h to see */ +/* all available threshold values. */ +extern CDEVAPI void cdevSetThreshold (int errorThreshold); + +/* set your own error reporting function. If func = 0, default */ +/* system error reporting function will be used */ +extern CDEVAPI void cdevSetErrorHandler (cdevErrHandler func); + +/* printf like error reporting interface */ +extern CDEVAPI int cdevReportError (int severity, char* name, + cdev_request_t req, char* format, ...); + +/********************************************************************** + * cdev high level I/O operations * + *********************************************************************/ + +/* synchronous send with device/msg pair + out/in data */ +extern CDEVAPI int cdevSend (char* device, char* msg, + cdev_data_t out, cdev_data_t result); + +/* asynchronous send with device/msg pair + out/in data */ +/* caller has to use synchronization mechanism to retrieve */ +/* result by cdevGroupPend or cdevPend methods */ +extern CDEVAPI int cdevSendNoBlock (char* device, char* msg, + cdev_data_t out, cdev_data_t result); + +/* asynchronous send with device/msg pair + out data and a */ +/* user provided callback. */ +/* caller has to use synchronization mechanism to retrieve */ +/* result by cdevGroupPend or cdevPend methods */ +extern CDEVAPI int cdevSendCallback (char* device, char* msg, + cdev_data_t out, cdev_cbk_t cbk); + +/* get context associcated with a device 'device' */ +extern CDEVAPI int cdevGetContext (char* device, cdev_data_t* data); + +/* set context for the device 'device' */ +extern CDEVAPI int cdevSetContext (char* device, cdev_data_t data); + +/* set private data for device 'device' */ +extern CDEVAPI int cdevSetPrivate (char* device, void* data); + +/* get private data associated with this 'device' */ +extern CDEVAPI int cdevGetPrivate (char* device, void** data); + +/********************************************************************* + * Efficient cdev I/O handle routines * + ********************************************************************/ + +/* Create/Allocate cdev_request_t object */ +extern CDEVAPI int cdevRequestAllocate (char* device, char* msg, + cdev_request_t* id); + +/* Destroy/Free a cdev_request_t object */ +extern CDEVAPI void cdevRequestFree (cdev_request_t id); + +/* synchronous send by a cdev_request_t object */ +extern CDEVAPI int cdevRequestSend (cdev_request_t id, + cdev_data_t out, + cdev_data_t result); + +/* asynchronous send. user has use synchronization routines */ +/* such as cdevGroupPend or cdevPend etc to get result */ +extern CDEVAPI int cdevRequestSendNoBlock (cdev_request_t id, + cdev_data_t out, + cdev_data_t result); + +/* asynchronous send with callback. user has use synchronization */ +/* routines such as cdevGroupPend or cdevPend etc to get result */ +extern CDEVAPI int cdevRequestSendCallback(cdev_request_t id, + cdev_data_t out, + cdev_cbk_t cbk); + +/* get current communication state of cdev_request_t. e.g. */ +/* connected or disconnected */ +extern CDEVAPI int cdevRequestState (cdev_request_t id); + +/* get access right of this cdev_request_t. e.g. readonly */ +extern CDEVAPI int cdevRequestAccess (cdev_request_t id); + +/* get device name associated with this cdev_request_t. caller */ +/* has control of memory of 'device'. */ +/* e.g. char *device; cdevRequestDevice (id, &device); */ +/* free (device); */ +extern CDEVAPI int cdevRequestDevice (cdev_request_t id, char** device); + +/* get message associated with this cdev_request_t. caller */ +/* has control of memory of 'msg'. */ +/* e.g. char *msg; cdevRequestMessage (id, &msg); */ +/* free (msg); */ +extern CDEVAPI int cdevRequestMessage (cdev_request_t id, char** msg); + +/* get context associated with this request. caller has */ +/* control of memory of return 'cxt'. */ +/* e.g. cdev_data_t data; cdevRequestGetContext (id, &data); */ +/* cdevDataFree (data); */ +extern CDEVAPI int cdevRequestGetContext (cdev_request_t id, cdev_data_t* cxt); + +/* set context for this I/O request */ +extern CDEVAPI int cdevRequestSetContext (cdev_request_t id, cdev_data_t cxt); + +/* get private data associated with this request. returned */ +/* data is just a pointer */ +extern CDEVAPI int cdevRequestGetPrivate (cdev_request_t id, void** data); + +/* set private data to this request */ +extern CDEVAPI int cdevRequestSetPrivate (cdev_request_t id, void* data); + +/******************************************************************** + * cdev group routines useful for synchronization of multiple * + * asynchronous I/O requests * + *******************************************************************/ + +/* create/allocate a new cdev group */ +extern CDEVAPI int cdevGroupAllocate (cdev_group_t* id); + +/* destroy/free a cdev group */ +extern CDEVAPI void cdevGroupFree (cdev_group_t id); + +/* start a cdev group, all I/O requests will be registered */ +/* this group */ +extern CDEVAPI int cdevGroupStart (cdev_group_t id); + +/* end a cdev group */ +extern CDEVAPI int cdevGroupEnd (cdev_group_t id); + +/* poll the network to see whether there are outstanding */ +/* I/O events pending for this group */ +extern CDEVAPI int cdevGroupPoll (cdev_group_t id); + +/* wait for all I/O requests upto 'seconds'. If seconds = 0.0 */ +/* wait until all I/O requests of this group have come back */ +extern CDEVAPI int cdevGroupPend (cdev_group_t id, double seconds); + +/* flush all I/O requests */ +extern CDEVAPI int cdevGroupFlush (cdev_group_t id); + +/* check whether all I/O requests inside this group have come */ +/* back. return 1: yes, return 0: no */ +extern CDEVAPI int cdevGroupAllFinished (cdev_group_t id); + +/* check all I/O requests status inside the group. caller */ +/* provide large enough integer buffer and initial size of */ +/* buffer. It returns with real number of I/O requests and */ +/* status[i] = 0 stands for a finished I/O, status[i] = 1 */ +/* stands for a unfinished I/O. */ +/* e.g. int status[100], nstatus = 100; */ +/* cdevGroupStatus (id, status, &nstatus); */ +/* for (i = 0; i < nstatus; i++) */ +/* if (status[i] == 0) do something */ +extern CDEVAPI int cdevGroupStatus (cdev_group_t id, + int status[], int* nstatus); + +/* do not buffer I/O requests. send them out immediatly. */ +/* This is the default mode */ +extern CDEVAPI int cdevGroupExecImmediate (cdev_group_t id); + +/* defer execution of all I/O requests inside the group until */ +/* cdevGroup flush is called */ +extern CDEVAPI int cdevGroupExecDeferred (cdev_group_t id); + +/* return the execution mode of this group */ +extern CDEVAPI int cdevGroupExecutionMode (cdev_group_t id, int* mode); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/include/cdevAccount.h b/include/cdevAccount.h new file mode 100644 index 0000000..384d464 --- /dev/null +++ b/include/cdevAccount.h @@ -0,0 +1,154 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevAccount classes: These classes provide the basic functionality +// for CDEV accounting. +// +// Author: Walt Akers +//----------------------------------------------------------------------------- + +#ifndef _CDEV_ACCOUNT_H_ +#define _CDEV_ACCOUNT_H_ 1 + +#include + +// ***************************************************************************** +// * class cdevAccountRecord : +// * The cdevAccountRecord class is used to store information about a single +// * CDEV application. This class contains the mechanisms necessary to write +// * this information to a disk file and then read entries back in sequentially +// ***************************************************************************** +class cdevAccountRecord +{ +public: + enum {MAX_TEMP_BUF=4096}; + + cdevAccountRecord ( void ); + ~cdevAccountRecord ( void ); + + void reset ( void ); + int streamIn ( FILE * fp ); + int streamIn ( int fd ); + char * streamIn ( char * ptr ); + int streamOut ( FILE * fp ); + int streamOut ( int fd ); + + void asciiDump ( FILE * fp = stdout ); + + cdevAccountRecord * getNext ( void ); + void setNext ( cdevAccountRecord * Next ); + + pid_t getProcessID ( void ); + void setProcessID ( pid_t ProcessID ); + char * getStartTime ( void ); + void setStartTime ( time_t StartTime ); + char * getAppName ( void ); + void setAppName ( char * AppName ); + char ** getArguments ( void ); + void setArguments ( char ** args, int nArgs); + char * getUserName ( void ); + void setUserName ( char * UserName ); + char * getHostName ( void ); + void setHostName ( char * HostName ); + char * getSystemName ( void ); + void setSystemName ( char * OSName ); + char * getSystemRelease ( void ); + void setSystemRelease ( char * OSRelease ); + char * getCDEVVersion ( void ); + void setCDEVVersion ( char * CDEVVersion ); + char ** getServiceList ( void ); + void setServiceList ( char ** ServiceList, int nServices ); + void addService ( char * ServiceName ); + +protected: + // ********************************************************************* + // * This is the pointer to the next cdevAccountRecord object that may + // * be stored in a cdevAccountTable + // ********************************************************************* + cdevAccountRecord * next; + + // ********************************************************************* + // * This is a static buffer that will be used to perform reads + // * whenever the size of the data to be read does not exceed the + // * basic size. + // ********************************************************************* + static char tempBuf[MAX_TEMP_BUF]; + + // ********************************************************************* + // * This is the process ID of the running CDEV application. + // ********************************************************************* + pid_t processID; + + // ********************************************************************* + // * This is the time that the application was started. + // ********************************************************************* + char startTime [20]; + + // ********************************************************************* + // * This is the name of the application and the arguments that were + // * provided when it was started. + // ********************************************************************* + char appName [256]; + int argCnt; + char ** argList; + + // ********************************************************************* + // * This is the name of the user that started the application. + // ********************************************************************* + char userName [128]; + + // ********************************************************************* + // * This is the name of the host where the application was started + // * and pertinent information about the operating system. + // ********************************************************************* + char hostName [128]; + char osName [32]; + char osRelease [32]; + + // ********************************************************************* + // * This is the version of CDEV that the application is using. + // * Includes the suffix (SHARED) or (ARCHIVE). + // ********************************************************************* + char cdevVersion[64]; + + // ********************************************************************* + // * These are the services that the application has loaded. + // ********************************************************************* + int serviceCnt; + int serviceMax; + char ** serviceList; +}; + + +// ***************************************************************************** +// * class cdevAccountEntry: +// * This class is used to create a single instance of a cdevAccountRecord +// * that will be associated with a CDEV application. This class instance +// * will be called to write accounting information to the CDEV Accounting +// * file whenever a significant event (start-up, service load, shutdown) +// * occurs. +// ***************************************************************************** +class cdevAccountEntry : public cdevAccountRecord +{ +public: + cdevAccountEntry ( char * OutputFile = NULL ); + ~cdevAccountEntry ( void ); + int updateRecord ( void ); + int removeRecord ( void ); + void initialize ( void ); + void addService ( char * service ); + +private: + char outputFile[256]; +}; + +extern cdevAccountEntry * cdevGlobalAccountEntry; + +#endif /* _CDEV_ACCOUNT_H_ */ diff --git a/include/cdevAliasDefinition.h b/include/cdevAliasDefinition.h new file mode 100644 index 0000000..e6fa268 --- /dev/null +++ b/include/cdevAliasDefinition.h @@ -0,0 +1,117 @@ +#ifndef _CDEV_ALIAS_DEFINITION_H_ +#define _CDEV_ALIAS_DEFINITION_H_ + +#ifndef _CDEV_DIRECTORY_TABLE_H_ + #error "You must include cdevDirectoryTable.h to load cdevAliasDefinition.h" +#endif + +#include + +// ***************************************************************************** +// * class cdevAliasDefinition : +// * This class stores the name of an alias and a reference to the device +// * definition that it is associated with. +// * +// * This class maintains a variety of internal data items for the following +// * purposes... +// * +// * alias - This is the name of the alias. +// * device - This is the cdevDeviceDefinition for the device that it +// * references. +// * next - This is the next alias in the list. +// ***************************************************************************** +class cdevAliasDefinition +{ +private: + char * name; + cdevDeviceDefinition & device; + cdevAliasDefinition * next; + +public: + inline cdevAliasDefinition ( char * Name, cdevDeviceDefinition & Device ); + inline ~cdevAliasDefinition ( void ); + inline void asciiDump ( FILE * fp = stdout ); + + // ********************************************************************* + // * Member access methods. + // ********************************************************************* + inline char * getName ( void ); + inline cdevDeviceDefinition & getDevice ( void ); + inline cdevAliasDefinition * getNext ( void ); + inline void setNext ( cdevAliasDefinition * Next ); + +}; + + + +// ***************************************************************************** +// * cdevAliasDefinition::cdevAliasDefinition : +// * This is the constructor for the cdevAliasDefinition class. The Name +// * pointer becomes the property of the class and should not be accessed +// * by the caller after it has been provided to this constructor. +// ***************************************************************************** +inline cdevAliasDefinition::cdevAliasDefinition + ( char * Name, cdevDeviceDefinition & Device ) + : name(Name), device(Device), next(NULL) + { + } + + +// ***************************************************************************** +// * cdevAliasDefinition::~cdevAliasDefinition : +// * This is the destructor faor the cdevAliasDefinition class. +// ***************************************************************************** +inline cdevAliasDefinition::~cdevAliasDefinition ( void ) + { + delete name; + } + +// ***************************************************************************** +// * cdevAliasDefinition::~cdevAliasDefinition : +// * This is the destructor for the cdevAliasDefinition class. +// ***************************************************************************** +inline void cdevAliasDefinition::asciiDump ( FILE * fp ) + { + fprintf(fp, "alias %s %s\n", name, device.getName()); + } + + +// ***************************************************************************** +// * cdevAliasDefinition::getName : +// * This method allows the caller to obtain the name of the alias. +// ***************************************************************************** +inline char * cdevAliasDefinition::getName ( void ) + { + return name; + } + +// ***************************************************************************** +// * cdevAliasDefinition::getDevice : +// * This method allows the caller to retrieve the device definition +// * associated with the object. +// ***************************************************************************** +inline cdevDeviceDefinition & cdevAliasDefinition::getDevice ( void ) + { + return device; + } + +// ***************************************************************************** +// * cdevAliasDefinition::getNext : +// * This method allows the caller to get the next alias in the list. +// ***************************************************************************** +inline cdevAliasDefinition * cdevAliasDefinition::getNext ( void ) + { + return next; + } + +// ***************************************************************************** +// * cdevAliasDefinition::setNext : +// * This method allows the caller to set the next alias in the list. +// ***************************************************************************** +inline void cdevAliasDefinition::setNext ( cdevAliasDefinition * Next ) + { + next = Next; + } + + +#endif /* _CDEV_ALIAS_DEFINITION_H_ */ diff --git a/include/cdevBlockList.h b/include/cdevBlockList.h new file mode 100644 index 0000000..d2fc6aa --- /dev/null +++ b/include/cdevBlockList.h @@ -0,0 +1,169 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Linked list of blocks of void pointer +// +// Not safe C++ practice because of void*. +// Reason: It is very difficult to do instantiation inside +// a shared library. +// +// Author: Jie Chen +// +// Revision History: +// cdevBlockList.h,v +// Revision 1.1 1995/12/08 15:33:31 chen +// linked block list +// +// Revision 1.1.1.1 1995/06/16 17:14:07 epics +// initial import of cdev +// +// +#ifndef _CDEV_XOBJ_LIST_H +#define _CDEV_XOBJ_LIST_H + +#include +#include +#include + +typedef void* blockListItem; + +//=========================================================================== +// class tranObjBlockList +// List of blocks each with size +//=========================================================================== +const int DEFAULT_BLOCK_SIZE = 64; + +class cdevBlockListIterator; + +//=========================================================================== +// class cdevBlockLink +// Node for the cdevBlockList class (private) +//============================================================================= +class CDEV_CLASS_SPEC cdevBlockLink +{ + private: + //constructors + // create a single block with all unset value in it + cdevBlockLink (cdevBlockLink * nextPtr, cdevBlockLink *prevPtr, + unsigned int size = DEFAULT_BLOCK_SIZE); + // create a single block with default value in it + cdevBlockLink (cdevBlockLink * nextPtr, cdevBlockLink *prevPtr, + const blockListItem& defVal, + unsigned int size = DEFAULT_BLOCK_SIZE); + // create a single block with some value in it + cdevBlockLink (cdevBlockLink * nextPtr, cdevBlockLink *prevPtr, + blockListItem *date, + unsigned int size = DEFAULT_BLOCK_SIZE); + // copy constructor, copy all lists + cdevBlockLink (const cdevBlockLink& link); + // assignment operator + cdevBlockLink& operator = (const cdevBlockLink &link); + // destructor + virtual ~cdevBlockLink (void); + + // operations + // duplicate whole list + cdevBlockLink* duplicate (void); + // duplicate list starting here to the right + cdevBlockLink* duplicate (int type); // type 0. goes to right, 1 left + // insert a new block after + cdevBlockLink* addNewBlock (void); + cdevBlockLink* addNewBlock (const blockListItem & defValue); + // free all memory associated with the list + void freeAllMemory (void); + + // data area + blockListItem *value_; + unsigned int blockSize_; + // default value stored in the block + // keep track how many slots are occupied + cdevBlockLink *ptrToNextLink_; + cdevBlockLink *ptrToPrevLink_; + + // friends + friend class cdevBlockList; + friend class cdevBlockListIterator; +}; + +class CDEV_CLASS_SPEC cdevBlockList +{ + public: + // constructors and destructor + cdevBlockList (unsigned int blockSize = DEFAULT_BLOCK_SIZE); + cdevBlockList (const blockListItem& defVal, + unsigned int blockSize = DEFAULT_BLOCK_SIZE); + cdevBlockList (const cdevBlockList &rsc); + cdevBlockList& operator = (const cdevBlockList &rsc); + virtual ~cdevBlockList (void); + + // operations + // access elements via subscript + virtual blockListItem & operator [] (unsigned int ) const; + // free all memory + virtual void deleteAll (void); + // just clean out value + virtual void clearAll (void); + virtual cdevBlockList * duplicate (void) const; + virtual int includes (blockListItem value) const; + virtual int length (void) const; + + protected: + // data filed + cdevBlockLink firstBlock_; + unsigned int blockSize_; + unsigned int size_; + blockListItem* defValue_; + + private: + // return how many steps a particular pointer away from + // the beginning of the first block + unsigned int entryNumber (blockListItem *ptr); + cdevBlockLink* blockPointer (blockListItem *ptr); + blockListItem* entryPointer (unsigned int steps); + friend class cdevBlockListIterator; +}; + +//========================================================================= +// class cdevBlockListIterator +// Iterator class used to loop over all list elements +//========================================================================= +class CDEV_CLASS_SPEC cdevBlockListIterator +{ + public: + // constructor + cdevBlockListIterator (cdevBlockList &l); + + // iterator protocol + virtual int init (void); + virtual blockListItem operator () (); + virtual int operator !(); + // prefix + virtual int operator ++(); + virtual void operator = (blockListItem newValue); + + // new method for blockList + int forcePut (blockListItem value); + blockListItem * currentPosition(); + // prefix + int operator --(); + // move cursor to the end of the list + virtual int end (void); + + protected: + // data fields + cdevBlockList &data; + blockListItem* currEntry_; + blockListItem* blockEnd_; + blockListItem* blockStart_; + blockListItem* listEnd_; + unsigned int curPos_; +}; +#endif + diff --git a/include/cdevCallback.h b/include/cdevCallback.h new file mode 100644 index 0000000..ac225ff --- /dev/null +++ b/include/cdevCallback.h @@ -0,0 +1,154 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// general cdev callback class +// +// Author: Jie Chen and Walt Akers +// +// Revision History: +// cdevCallback.h,v +// Revision 1.10 1998/01/29 15:20:05 akers +// Ongoing development +// +// Revision 1.9 1997/07/16 18:38:41 akers +// Testing for function_ in fireCallback +// +// Revision 1.8 1997/03/03 17:35:35 chen +// add buffering to channel access connection +// +// Revision 1.7 1996/12/19 15:22:33 akers +// Ongoing development +// +// Revision 1.6 1996/12/18 13:32:28 akers +// Added support for incomplete transactions and fireCallback method +// +// Revision 1.4 1995/09/05 17:18:23 chen +// add freelist and overload new/delete +// +// Revision 1.3 1995/07/05 19:28:50 chen +// minor changes +// +// Revision 1.2 1995/07/05 18:36:39 chen +// Allow inheritance +// +// Revision 1.1.1.1 1995/06/16 17:14:10 epics +// initial import of cdev +// +// +#ifndef _CDEV_CALLBACK_H +#define _CDEV_CALLBACK_H + +#include +#include +#include + +class cdevRequestObject; +class cdevData; + +typedef void(*cdevCallbackFunction) (int status, +void *userarg, +cdevRequestObject &obj, +cdevData &result); + +class CDEV_CLASS_SPEC cdevCallback +{ +public: + // constructor and destructor + cdevCallback(void); + cdevCallback(cdevCallbackFunction, void *userarg); + cdevCallback(const cdevCallback &callback); + cdevCallback &operator=(const cdevCallback &callback); + virtual~cdevCallback(void); + + virtual cdevCallbackFunction callbackFunction(void) const; + // PURPOSE: return user callback function + // REQUIRE: nothing + // PROMISE: return 0 if there nothing + + virtual void *userarg(void) const; + // PURPUSE: return user arguments + // REQUIRE: nothing + // PROMISE: a user argument pointer + + int operator == (const cdevCallback &callback); + int operator != (const cdevCallback &callback); + // PURPOSE: if two cdevCallbacks have the same user function and user + // arguments, == return true + // REQUIRE: nothing + // PROMISE: + + void *operator new(size_t size); + void operator delete(void *p, size_t size); + // PURPOSE: overloaded new and delete operator. + // REQUIRE: none + // PROMISE: + + // ********************************************************************* + // * The fireCallback method is allows the developer to execute the + // * callback function that is specified in the cdevCallback object + // * and set the incomplete_ flag to the appropriate value prior to + // * execution, and then restore it to its default value before + // * returning. + // * + // * The value provided in the "partial" parameter will be used to set + // * the incomplete_ flag. + // ********************************************************************* + void fireCallback ( int status, + void * userarg, + cdevRequestObject & req, + cdevData & data, + int partial) + { + if(function_!=NULL) + { + incomplete_ = partial; + (*function_)(status, userarg, req, data); + incomplete_ = 0; + } + } + + // ********************************************************************* + // * The isTransactionDone method allows the caller to discover if the + // * transaction that executed the callback method is finished or + // * ongoing. + // ********************************************************************* + static int isTransactionDone ( void ) { return !incomplete_; } + +protected: + // data area + cdevCallbackFunction function_; + void *userarg_; + +private: + // Free List for all cdevCallback + // Reason: cdevCallback is a very small object (8 byte). Using free list + // can speed up a program by an order of magnitude over the + // default malloc-based memory allocation primitives. It can also + // be less wasteful of memory, eliminating malloc's overheade of + // four to eight bytes per allocation + static cdevCallback *newlist; + union + { + cdevCallback *freePtr; + char *rep; + }; + + // ********************************************************************* + // * The incomplete_ flag is used to indicate that the transaction that + // * has called this callback method is or is not finished. + // * + // * The incomplete_ flag may have the following values... + // * 0 - The transaction is finished + // * 1 - The transaction is ongoing and more callbacks may be + // * expected. + // ********************************************************************* + static int incomplete_; +}; +#endif diff --git a/include/cdevClassDefinition.h b/include/cdevClassDefinition.h new file mode 100644 index 0000000..0fc6320 --- /dev/null +++ b/include/cdevClassDefinition.h @@ -0,0 +1,697 @@ +#ifndef _CDEV_CLASS_DEFINITION_H_ +#define _CDEV_CLASS_DEFINITION_H_ + +#ifndef _CDEV_DIRECTORY_TABLE_H_ + #error "You must include cdevDirectoryTable.h to load cdevClassDefinition.h" +#endif + +// ***************************************************************************** +// * class cdevClassDefinition : +// * This class stores the definition of a single CDEV DDL class and all +// * of its associated verbs, attributes and messages. +// * +// * This class maintains a variety of internal data items for the following +// * purposes... +// * +// * directory - This is the cdevDirectoryTable that the class definition +// * is a member of... +// * +// * name - This is the name of the class as defined in the CDEV DDL +// * file. +// * +// * verbs - This is a list of cdevElementDefinitions that identify +// * each verb that was defined within the class definition. +// * +// * attributes - This is a list of cdevElementDefinitions that identify +// * each attribute that was defined within the class +// * definition. +// * +// * messages - This is a list of cdevElementDefinitions that identify +// * each messages that was defined within the class defintion. +// * +// * parent - This is the class definition for the class that this one +// * inherited from - if any. +// * +// * deviceHead - This is a list of device definitions for all devices that +// * deviceTail were created from this class. +// * +// * redirector - This is a table of all complete messages that this class +// * will support. This table is only generated if devices are +// * instanciated from the class - and it includes the message +// * contents from all parent classes. +// * +// * next - This is the next class definition that occurs... This list +// * is maintained in the cdevDirectoryTable object. +// ***************************************************************************** +class cdevClassDefinition +{ +private: + cdevDirectoryTable & directory; + cdevClassDefinition * next; + char * name; + cdevElementDefinition * verbs; + cdevElementDefinition * attributes; + cdevElementDefinition * messages; + cdevClassDefinition * parent; + cdevDeviceDefinition * deviceHead; + cdevDeviceDefinition * deviceTail; + StringHash redirector; + +public: + inline cdevClassDefinition(cdevDirectoryTable &Master, + char *Name = NULL, + cdevClassDefinition *Parent = NULL, + cdevElementDefinition *Verbs = NULL, + cdevElementDefinition *Attributes = NULL, + cdevElementDefinition *Messages = NULL); + inline ~cdevClassDefinition ( void ); + inline int addElement (cdevElementDefinition *&target, + cdevElementDefinition * element ); + inline int addElement (cdevElementDefinition *& target, + char * eleName, + cdevServiceDefinition * service, + char ** serviceData, + int nItems); + inline int addDevice (char * device, char * substName = NULL ); + inline int addVerb (char * eleName, cdevServiceDefinition *service, char ** serviceData, int nItems ); + inline int addVerb (cdevElementDefinition * element ); + inline int addAttribute (char * eleName, cdevServiceDefinition *service, char ** serviceData, int nItems ); + inline int addAttribute (cdevElementDefinition * element ); + inline int addMessage (char * eleName, cdevServiceDefinition *service, char ** serviceData, int nItems ); + inline int addMessage (cdevElementDefinition * element ); + inline int isA (char * className ); + inline void asciiDump (FILE * fp = stdout ); + inline void asciiDumpInstances ( FILE * fp = stdout ); + inline void asciiDumpRedirector ( FILE * fp = stdout ); + inline void createRedirectionTable ( void ); + + // ********************************************************************* + // * Member access functions: + // ********************************************************************* + inline char * getName ( void ); + inline cdevDirectoryTable & getDirectory ( void ); + inline cdevClassDefinition * getParent ( void ); + inline cdevElementDefinition * getVerbs ( void ); + inline cdevElementDefinition * getAttributes ( void ); + inline cdevElementDefinition * getMessages ( void ); + inline cdevDeviceDefinition * getDevices ( void ); + inline StringHash & getRedirector ( void ); + inline int getElements ( cdevDirectoryTable::ElementType type, + cdevElementDefinition ** &def, + int &nItems ); + inline cdevClassDefinition * getNext ( void ); + inline void setNext ( cdevClassDefinition * Next ); + +}; + + +// ***************************************************************************** +// * cdevClassDefinition::cdevClassDefinition : +// * This is the constructor for the class definition object. I +// ***************************************************************************** +inline cdevClassDefinition::cdevClassDefinition + ( cdevDirectoryTable &Master, + char *Name, + cdevClassDefinition *Parent, + cdevElementDefinition *Verbs, + cdevElementDefinition *Attributes, + cdevElementDefinition *Messages) + : directory (Master), + name (Name), + parent (Parent), + verbs (Verbs), + attributes (Attributes), + messages (Messages), + deviceHead (NULL), + deviceTail (NULL), + next (NULL) + { + } + +// ***************************************************************************** +// * cdevClassDefinition::~cdevClassDefinition : +// * This is the descructor for the cdevClassDefinition object. It will +// * delete the class name and each item from the elements list. +// ***************************************************************************** +inline cdevClassDefinition::~cdevClassDefinition ( void ) + { + cdevElementDefinition * ptr; + cdevDeviceDefinition * dPtr; + cdevRedirectorDefinition * rPtr; + StringHashIterator iter(&redirector); + + delete name; + + while(verbs!=NULL) + { + ptr = verbs; + verbs = verbs->getNext(); + delete ptr; + } + while(messages!=NULL) + { + ptr = messages; + messages = messages->getNext(); + delete ptr; + } + while(attributes!=NULL) + { + ptr = attributes; + attributes = attributes->getNext(); + delete ptr; + } + while(deviceHead!=NULL) + { + dPtr = deviceHead; + deviceHead = deviceHead->getNext(); + directory.getDeviceHash().remove(dPtr->getName()); + delete dPtr; + } + for(iter.first(); (rPtr = (cdevRedirectorDefinition *)iter.data())!=NULL; ) + { + iter++; + redirector.remove(rPtr->getName()); + delete rPtr; + } + } + +// ***************************************************************************** +// * cdevClassDefinition::addElement : +// * This method is used to add an element (verb, attribute, or message) to +// * the cdevClassDefinition. The target parameter is a reference to the +// * list that will receive the incoming element. +// ***************************************************************************** +inline int cdevClassDefinition::addElement + ( cdevElementDefinition *&target, + cdevElementDefinition * element ) + { + cdevElementDefinition *curr, *prev; + int result = CDEV_SUCCESS; + + for(curr=target, prev=NULL; + curr!=NULL && strcmp(curr->getName(), element->getName()); + curr=curr->getNext()) + { + prev = curr; + } + if(curr == NULL) + { + if(prev) prev->setNext(new cdevElementDefinition(element)); + else target = new cdevElementDefinition(element); + } + else result = CDEV_ERROR; + return result; + } + +// ***************************************************************************** +// * cdevClassDefinition::addElement : +// * This method will create a new element and add it to the list of elements +// * that is reference by the target paremeter. +// ***************************************************************************** +inline int cdevClassDefinition::addElement + (cdevElementDefinition *& target, + char * eleName, + cdevServiceDefinition * service, + char ** serviceData, + int nItems) + { + cdevElementDefinition *curr, *prev; + int result = CDEV_SUCCESS; + + for(curr=target, prev=NULL; + curr!=NULL && strcmp(curr->getName(), eleName); + curr=curr->getNext()) + { + prev = curr; + } + if(curr == NULL) + { + if(prev) prev->setNext(new cdevElementDefinition(eleName, service, serviceData, nItems)); + else target = new cdevElementDefinition(eleName, service, serviceData, nItems); + } + else result = CDEV_ERROR; + return result; + } + +// ***************************************************************************** +// * cdevClassDefinition::addDevice : +// * This method will add a new device to the device list. This device name +// * will also be placed in the hashTable in the cdevDirectoryTable object +// * specified by directory. +// * +// * Note the device name becomes the property of the cdevDeviceDefinition +// * class and should not be deleted. +// * +// * The redirection table for this device will also be created as the +// * first device is instanciated. +// ***************************************************************************** +inline int cdevClassDefinition::addDevice ( char * device, char * substName ) + { + int result = CDEV_SUCCESS; + + if(device!=NULL && directory.getDeviceHash().find(device)==NULL) + { + cdevDeviceDefinition * def = + new cdevDeviceDefinition(directory, device, substName, *this); + + if(deviceTail==NULL) + { + deviceHead = def; + deviceTail = def; + createRedirectionTable(); + directory.addClassInstance(this); + } + else { + deviceTail->setNext( def ); + deviceTail = def; + } + + directory.addDevice(def); + } + else result = CDEV_ERROR; + + return result; + } + +// ***************************************************************************** +// * cdevClassDefinition::addVerb : +// * This method will add a verb to the verbs element definition list. +// ***************************************************************************** +inline int cdevClassDefinition::addVerb + ( char * eleName, cdevServiceDefinition *service, char ** serviceData, int nItems ) + { + return addElement(verbs, eleName, service, serviceData, nItems); + } + +// ***************************************************************************** +// * cdevClassDefinition::addVerb : +// * This method will add a verb to the verbs element definition list. +// ***************************************************************************** +inline int cdevClassDefinition::addVerb ( cdevElementDefinition * element ) + { + return addElement(verbs, element); + } + +// ***************************************************************************** +// * cdevClassDefinition::addAttribute : +// * This method will add an attribute to the attributes element +// * definition list. +// ***************************************************************************** +inline int cdevClassDefinition::addAttribute + ( char * eleName, cdevServiceDefinition * service, char ** serviceData, int nItems ) + { + return addElement(attributes, eleName, service, serviceData, nItems); + } + +// ***************************************************************************** +// * cdevClassDefinition::addAttribute : +// * This method will add an attribute to the attributes element +// * definition list. +// ***************************************************************************** +inline int cdevClassDefinition::addAttribute ( cdevElementDefinition * element ) + { + return addElement(attributes, element); + } + +// ***************************************************************************** +// * cdevClassDefinition::addMessage : +// * This method will add a message to the messages element definition list. +// ***************************************************************************** +inline int cdevClassDefinition::addMessage + ( char * eleName, cdevServiceDefinition * service, char ** serviceData, int nItems ) + { + return addElement(messages, eleName, service, serviceData, nItems); + } + +// ***************************************************************************** +// * cdevClassDefinition::addMessage : +// * This method will add a message to the messages element definition list. +// ***************************************************************************** +inline int cdevClassDefinition::addMessage ( cdevElementDefinition * element ) + { + return addElement(messages, element); + } + +// ***************************************************************************** +// * cdevClassDefinition::isA : +// * This method will ascend the class hierarchy attempting to locate a +// * class with the name specified in className. It will return TRUE if this +// * class is or inherits from the specified className, or FALSE if not. +// ***************************************************************************** +inline int cdevClassDefinition::isA ( char * className ) + { + int result; + if(strcmp(name, className)==0) result = 1; + else if(parent!=NULL) result = parent->isA(className); + else result = 0; + return result; + } + +// ***************************************************************************** +// * cdevClassDefinition::asciiDump : +// * This method dumps the contents of the cdevClassDefinition to the user +// * specified file descriptor. +// ***************************************************************************** +inline void cdevClassDefinition::asciiDump ( FILE * fp ) + { + if(name) + { + fprintf(fp, "\nclass %s", name); + if(parent) fprintf(fp, " : %s", parent->name); + fprintf(fp, "\n\t{\n"); + + if(verbs!=NULL) verbs->asciiDumpList(fp, "verbs"); + if(attributes!=NULL) attributes->asciiDumpList(fp, "attributes"); + if(messages!=NULL) messages->asciiDumpList(fp, "messages"); + + fprintf(fp, "\t}\n"); + } + } + + +// ***************************************************************************** +// * cdevClassDefinition::asciiDumpInstances : +// * This method dumps the instance data of the class definition to the +// * caller specified file descriptor. +// ***************************************************************************** +inline void cdevClassDefinition::asciiDumpInstances ( FILE * fp ) + { + if(deviceHead!=NULL) + { + cdevDeviceDefinition * device = deviceHead; + + fprintf(fp, "\n%s : \n", name); + while(device!=NULL) + { + if(device->getName()!=device->getSubstituteName()) + { + fprintf(fp, "\t%s {%s}\n", device->getName(), device->getSubstituteName()); + } + else fprintf(fp, "\t%s\n", device->getName()); + device = device->getNext(); + } + fprintf(fp, "\t;\n"); + } + } + + +// ***************************************************************************** +// * cdevClassDefinition::asciiDumpRedirector : +// * This method dumps the contents of the redirection table that is used +// * to route messages to their intended service. +// ***************************************************************************** +inline void cdevClassDefinition::asciiDumpRedirector ( FILE * fp ) + { + StringHashIterator iter(&redirector); + cdevRedirectorDefinition * def; + + fprintf(fp, "\n/* Redirection table for class %s */\n", name); + fprintf(fp, "class %s\n\t{\n\tmessages\n\t\t{\n", name); + for(iter.first(); + (def = (cdevRedirectorDefinition *)iter.data())!=NULL; + iter++) + { + def->asciiDump(fp); + } + fprintf(fp, "\t\t}\n\t}\n"); + } + + +// ***************************************************************************** +// * cdevClassDefinition::createRedirectionTable : +// * This method will read the verbs, attributes and messages and will +// * generate a redirection table that will allow the cdevDirectoryTable +// * to route requests to the correct service using the proper serviceData. +// ***************************************************************************** +inline void cdevClassDefinition::createRedirectionTable ( void ) + { + cdevRedirectorDefinition * def; + cdevElementDefinition ** msgPtr, ** vrbPtr, **atrPtr; + int msgCnt, vrbCnt, atrCnt; + int msgIdx, vrbIdx, atrIdx; + + // ********************************************************************* + // * Get a pointer to all of the verbs that are in use by the class. + // ********************************************************************* + getElements(cdevDirectoryTable::MESSAGE, msgPtr, msgCnt); + getElements(cdevDirectoryTable::VERB, vrbPtr, vrbCnt); + getElements(cdevDirectoryTable::ATTRIBUTE, atrPtr, atrCnt); + + // ********************************************************************* + // * Process through all of the messages and add them to the + // * redirection list first. Display a warning if they are already + // * present. + // ********************************************************************* + for(msgIdx=0; msgIdxgetName() && msgPtr[msgIdx]->getService()) + { + if(redirector.find(msgPtr[msgIdx]->getName())!=NULL) + { + cdevReportError(CDEV_SEVERITY_INFO, "CDEV Directory", NULL, + "Message %s already defined for class %s", + msgPtr[msgIdx]->getName(), name); + } + else { + def = new cdevRedirectorDefinition(strdup(msgPtr[msgIdx]->getName()), *msgPtr[msgIdx]); + redirector.insert(def->getName(), def); + } + } + } + + // ********************************************************************* + // * Walk through the verb list and combine them with each attribute... + // * For each verb that has a service associated with it, use the verbs + // * element definition... If the verb does not have a service, then + // * use the attributes element definition. + // ********************************************************************* + for(vrbIdx=0; vrbIdxgetName()) + { + // ***************************************************** + // * Using the verbs service. + // ***************************************************** + if(vrbPtr[vrbIdx]->getService()) + { + for(atrIdx=0; atrIdxgetName()!=NULL) + { + char * temp = new char[strlen(vrbPtr[vrbIdx]->getName())+strlen(atrPtr[atrIdx]->getName())+2]; + sprintf(temp, "%s %s", vrbPtr[vrbIdx]->getName(), atrPtr[atrIdx]->getName()); + if(redirector.find(temp)!=NULL) + { + cdevReportError(CDEV_SEVERITY_INFO, "CDEV Directory", NULL, + "Message %s already defined for class %s", + temp, name); + delete temp; + } + else { + def = new cdevRedirectorDefinition(temp, *vrbPtr[vrbIdx]); + redirector.insert(def->getName(), def); + } + } + } + } + // ***************************************************** + // * Using the attributes service. + // ***************************************************** + else for(atrIdx=0; atrIdxgetName() && atrPtr[atrIdx]->getService()) + { + char * temp = new char[strlen(vrbPtr[vrbIdx]->getName())+strlen(atrPtr[atrIdx]->getName())+2]; + sprintf(temp, "%s %s", vrbPtr[vrbIdx]->getName(), atrPtr[atrIdx]->getName()); + if(redirector.find(temp)!=NULL) + { + cdevReportError(CDEV_SEVERITY_INFO, "CDEV Directory", NULL, + "Message %s already defined for class %s", + temp, name); + delete temp; + } + else { + def = new cdevRedirectorDefinition(temp, *atrPtr[atrIdx]); + redirector.insert(def->getName(), def); + } + } + else { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Neither the verb nor the message for \"%s %s\" has a service", + vrbPtr[vrbIdx]->getName(), atrPtr[atrIdx]->getName()); + } + } + } + } + + // ********************************************************************* + // * Release the memory used to store the pointers. + // ********************************************************************* + if(msgPtr) delete msgPtr; + if(vrbPtr) delete vrbPtr; + if(atrPtr) delete atrPtr; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getElements : +// * This method allows the caller to retrieve a list of all element +// * definitions of a particular type from all subclasses of the current +// * class. +// ***************************************************************************** +inline int cdevClassDefinition::getElements ( cdevDirectoryTable::ElementType type, + cdevElementDefinition ** &def, + int &nItems ) + { + StringHash tempHash; + cdevClassDefinition * classDef = this; + + def = NULL; + nItems = 0; + + do + { + cdevElementDefinition * el = + type==cdevDirectoryTable::VERB?classDef->verbs: + (type==cdevDirectoryTable::ATTRIBUTE?classDef->attributes: + classDef->messages); + + for(; el!=NULL; el = el->getNext()) + { + if(tempHash.find(el->getName())==NULL) + { + tempHash.insert(el->getName(), el); + nItems++; + } + } + classDef = classDef->parent; + } while(classDef!=NULL); + + if(nItems!=0) + { + StringHashIterator iter(&tempHash); + + def = new cdevElementDefinition * [nItems]; + nItems = 0; + + for(iter.first(); iter.key()!=NULL; iter++) + { + def[nItems++] = (cdevElementDefinition *)iter.data(); + } + } + + return nItems; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getName : +// * This method allows the caller to retrieve the name of the class. +// ***************************************************************************** +inline char * cdevClassDefinition::getName ( void ) + { + return name; + } + + +// ***************************************************************************** +// * cdevClassDefinition:: : +// * This method allows the caller to retrieve the directory table that +// * owns this device. +// ***************************************************************************** +inline cdevDirectoryTable & cdevClassDefinition::getDirectory ( void ) + { + return directory; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getParent : +// * This method allows the caller to retrieve the class definition that +// * this class inherits from. +// ***************************************************************************** +inline cdevClassDefinition * cdevClassDefinition::getParent ( void ) + { + return parent; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getVerbs : +// * This method allows the caller to retrieve the lement definition list +// * containing all of the classes verbs. +// ***************************************************************************** +inline cdevElementDefinition * cdevClassDefinition::getVerbs ( void ) + { + return verbs; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getAttributes : +// * This method allows the caller to retrieve the element definition list +// * containing all of the classes verbs. +// ***************************************************************************** +inline cdevElementDefinition * cdevClassDefinition::getAttributes ( void ) + { + return attributes; + } + + + +// ***************************************************************************** +// * cdevClassDefinition::getMessages : +// * This method allows the caller to retrieve the element definition list +// * containing all of the classes messages. +// ***************************************************************************** +inline cdevElementDefinition * cdevClassDefinition::getMessages ( void ) + { + return messages; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getDevices : +// * This method allows the caller to retrieve the device definition list +// * containing all of the instances of the class. +// ***************************************************************************** +inline cdevDeviceDefinition * cdevClassDefinition::getDevices ( void ) + { + return deviceHead; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getRedirector : +// * This method allows the caller to retrieve the redirection list for +// * the class. +// ***************************************************************************** +inline StringHash & cdevClassDefinition::getRedirector ( void ) + { + return redirector; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getNext : +// * This method allows the caller to retrieve the next class definition in +// * the list. +// ***************************************************************************** +inline cdevClassDefinition * cdevClassDefinition::getNext ( void ) + { + return next; + } + + +// ***************************************************************************** +// * cdevClassDefinition::setNext : +// * This method allows the caller to set the next class definition in the +// * list. +// ***************************************************************************** +inline void cdevClassDefinition::setNext ( cdevClassDefinition * Next ) + { + next = Next; + } + + +#endif /* _CDEV_CLASS_DEFINITION_H_ */ diff --git a/include/cdevClock.h b/include/cdevClock.h new file mode 100644 index 0000000..90046ac --- /dev/null +++ b/include/cdevClock.h @@ -0,0 +1,81 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevClock Class Header File. +// +// Author: Jie Chen +// +// Revision History: +// cdevClock.h,v +// Revision 1.2 1998/02/10 18:04:56 chen +// add cdevSystem timer handler +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#ifndef _CDEV_CLOCK_H +#define _CDEV_CLOCK_H + +#include +#include +#include + +#include + +class CDEV_CLASS_SPEC cdevClock +{ + public: + // constructor and destructor + cdevClock (void); + virtual ~cdevClock(void); + + int isEmpty (void) const; + // PURPOSE: check whether this clock is set or not + // REQUIRE: nothing + // PROMISE: return 1: empty, return 0: not empty + + const cdevTimeValue &scheduledTime (void) const; + // PURPOSE: return scheduled timer value + // REQUIRE: nothing + // PROMISE: return time_value ZERO if empty + + static cdevTimeValue currentTime (void); + // PURPOSE: return current time + // REQUIRE: static function + // PROMISE: return current time (unix only) + + int schedule (const void *a, const cdevTimeValue &); + // PURPOSE: schedule a timer + // REQUIRE: nothing + // PROMISE: your timer will be remembered + + int cancel (void); + // PURPOSE: cancel a shceduled timer + // REQUIRE: nothing + // PROMISE: there will be no timer + + int expired (void); + // PURPOSE: check whether the timer is expired or not + // REQUIRE: nothing + // PROMISE: return 1: expired, return 0: not expired + + protected: + static const cdevTimeValue zero; + + private: + cdevTimeValue clock_value_; + const void *usr_arg_; + // deny access to copy and assignment operation + // no reason to create two clocks with same time value + cdevClock (const cdevClock&); + cdevClock& operator = (const cdevClock&); +}; +#endif diff --git a/include/cdevCollection.h b/include/cdevCollection.h new file mode 100644 index 0000000..79c4258 --- /dev/null +++ b/include/cdevCollection.h @@ -0,0 +1,135 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * Description: + * cdevCollection class implementation + * + * Author: Walt Akers, Chip Watson & Jie Chen + * + * Revision History: + * cdevCollection.h,v + * Revision 1.3 1998/08/03 16:24:25 chen + * AIX porting + * + * Revision 1.2 1997/12/12 16:35:43 chen + * add VMS fix + * + * Revision 1.1 1996/11/12 20:32:11 akers + * New collection device source code + * + * ----------------------------------------------------------------------------- + */ + +#ifndef _CDEV_COLLECTION_H +#define _CDEV_COLLECTION_H + +#include +#include + +#if defined(__VMS) || defined (AIX) +typedef char* va_list; +#undef va_start +#define va_start(ap,v) ((void)((ap)=(char*)(&v + 1))) +#undef va_arg +#define va_arg(ap,type) (((type *)((ap)+=sizeof(type)))[-1]) +#undef va_end +#define va_end(ap) ((void)0) +#endif + +class cdevCollectionRequest; + +class CDEV_CLASS_SPEC cdevCollection: public cdevDevice +{ + friend class cdevDevice; + + public: + //=================================================================== + // Public Interface for Clients + //=================================================================== + static cdevCollection& attachRef (char *name); + static cdevCollection* attachPtr (char *name); + // PURPOSE: create a reference or pointer for device of a given name + // within the default system + // REQUIRE: name != 0 + // PROMISE: a cdevCollection + + static void detach (cdevCollection& dev); + static void detach (cdevCollection* dev); + // PURPOSE: destroy a cdevCollection + // REQUIRE: dev != 0 + // PROMISE: memory will be freed if no more attachment on this device + + //======================================================================== + // Public Interface for cdevRequestObject + //======================================================================== + virtual cdevRequestObject *getRequestObject (char * msg ); + virtual int getRequestObject (char *msg, cdevRequestObject* &reqobj); + // PURPOSE: get right requestObject based on its name + // REQUIRE: name != 0, callers provide pointer only. + // PROMISE: always return CDEV_SUCCESS. reqobj may be an errorRequestObject + + //======================================================================== + // Public Interface for RTTI + //======================================================================== + virtual const char *className (void) const {return "cdevCollection";} + + //======================================================================== + // Public Interface for list manipulation + //======================================================================== + char ** getList(); + // PURPOSE: obtain a null terminated array of device names + // REQUIRE: caller is responsible for freeing list + // PROMISE: if collection is empty, returns NULL + + int add(char* name); // add a single device + int add(int num, char* name, ...); // add multiple devices + int add(int num, char** names); // add array of names of length num + int add(char** names); // add a null terminated array of names + int addRegexp(char* regexp); // add by regular expression + int remove(char* name); + int remove(int num, char* name, ...); + int remove(int num, char** names); + int remove(char** names); // remove a null terminated array of names + int removeRegexp(char* regexp); + // PURPOSE: add(remove) a (list of/regexp of) names to the collection + // REQUIRE: nothing + // PROMISE: merged list will have no duplicates + // return CDEV_SUCCESS: no duplicates/missing found, CDEV_WARNING: + // at least one duplicate name was dropped during add or + // at least one name was not found during remove + + protected: + //constructors and destructor + cdevCollection (char *name, + cdevSystem& system = cdevSystem::defaultSystem() ); + virtual ~cdevCollection (void); + + // attach pointer or reference with system as second argument + static cdevCollection& attachRef (char *name, cdevSystem& system); + static cdevCollection* attachPtr (char *name, cdevSystem& system); + // PURPOSE: create a reference or pointer for device of a given name + // REQUIRE: name != 0 + // PROMISE: a cdevCollection + + private: + cdevSlist nameList_; + + // hide assignment and copy operator since the collection is + // a memory manager for collectionRequests and lists of devices + cdevCollection& operator = (const cdevCollection &); + cdevCollection (const cdevCollection &); + + // friend class declaration + friend class cdevCollectionRequest; +}; +#endif + + + + diff --git a/include/cdevCollectionDefinition.h b/include/cdevCollectionDefinition.h new file mode 100644 index 0000000..0bae254 --- /dev/null +++ b/include/cdevCollectionDefinition.h @@ -0,0 +1,144 @@ +#ifndef _CDEV_COLLECTION_DEFINITION_H_ +#define _CDEV_COLLECTION_DEFINITION_H_ + +#ifndef _CDEV_DIRECTORY_TABLE_H_ + #error "You must include cdevDirectoryTable.h to load cdevCollectionDefinition.h" +#endif + +// ***************************************************************************** +// * class cdevCollectionDefinition : +// * This class stores information that identifies a specific device name +// * and associates it with a collection of devices. +// * +// * This class maintains a variety of internal data items for the following +// * purposes... +// * +// * name - This is the name of the device as specified in the DDL file. +// * directory - This is the cdevDirectoryTable object where the device was +// * registered. +// * cdevClass - This is the definition object for the class that the device +// * belongs to (collection). +// * devices - This is the list of devices that make up the collection. +// * deviceCnt - This is the number of devices in the list. +// * next - This is the next device in the linked list of +// * cdevCollectionDefinition objects. This list is maintained +// * as part of the cdevClassDefinition object. +// ***************************************************************************** +class cdevCollectionDefinition +{ +private: + char * name; + char ** devices; + int deviceCnt; + cdevCollectionDefinition * next; + +public: + inline cdevCollectionDefinition ( char * Name, + char ** Devices = NULL, + int DeviceCnt = 0 ); + inline ~cdevCollectionDefinition ( void ); + + inline void asciiDump ( FILE * fp = stdout ); + + // ********************************************************************* + // * Member access methods. + // ********************************************************************* + inline char * getName ( void ); + inline char ** getDevices ( void ); + inline int getDeviceCnt ( void ); + inline cdevCollectionDefinition * getNext ( void ); + inline void setNext ( cdevCollectionDefinition * Next ); +}; + + +// ***************************************************************************** +// * cdevCollectionDefinition::cdevCollectionDefinition : +// * This is the constructor for the cdevCollectionDefinition class. +// ***************************************************************************** +inline cdevCollectionDefinition::cdevCollectionDefinition + ( char * Name, char ** Devices, int DeviceCnt ) + : next(NULL), name(Name), devices(Devices), deviceCnt(DeviceCnt) + { + } + +// ***************************************************************************** +// * cdevCollectionDefinition::~cdevCollectionDefinition : +// * This is the destructor for the cdevCollectionDefinition class. +// ***************************************************************************** +inline cdevCollectionDefinition::~cdevCollectionDefinition ( void ) + { + if(name) delete name; + if(devices && deviceCnt) + { + while((--deviceCnt)>=0) delete devices[deviceCnt]; + } + if(devices) delete devices; + } + +// ***************************************************************************** +// * cdevCollectionDefinition::asciiDump : +// * Write the formatted output of the collection to the specified file +// * pointer. +// ***************************************************************************** +inline void cdevCollectionDefinition::asciiDump ( FILE * fp ) + { + if(devices && deviceCnt) + { + fprintf(fp, "\ncollection %s :\n", name); + for(int i=0; i +#include +#include + +// ***************************************************************************** +// * cdevCollectionRequest: +// * This is the cdevCollectionRequest class. It is the master type for +// * all service derived cdevCollectionRequest objects. +// ***************************************************************************** +class CDEV_CLASS_SPEC cdevCollectionRequest: public cdevRequestObject +{ +friend class cdevCollection; +friend class cdevGrpCollectionRequest; + +public: + // ********************************************************************* + // * Returns the name of the class. + // ********************************************************************* + const char *className (void) const {return "cdevCollectionRequest";} + + // ********************************************************************* + // * Returns the RESULT_CODE_TAG identifier. + // ********************************************************************* + static int resultCodeTag(void) { return RESULT_CODE_TAG; } + +protected: + // ********************************************************************* + // * Constructor and destructor for the class. + // ********************************************************************* + cdevCollectionRequest (char **devices, int nDevices, char *msg, cdevSystem& sys); + virtual ~cdevCollectionRequest (void); + + // ********************************************************************* + // * Factory used to generate cdevCollectionRequest objects. + // ********************************************************************* + static cdevCollectionRequest * attachPtr(cdevCollection &device, char *msg, cdevSystem &system); + + // ********************************************************************* + // * This is the integer that wil be used to store the cdevData tag that + // * will contain the completion code. + // ********************************************************************* + static int RESULT_CODE_TAG; +}; + +#endif diff --git a/include/cdevCommon.h b/include/cdevCommon.h new file mode 100644 index 0000000..b86f4a4 --- /dev/null +++ b/include/cdevCommon.h @@ -0,0 +1,44 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Utility prototypes and inline functions for cdev. +// +// Author: Walt Akers +// +// Revision History: +// cdevCommon.h,v +// Revision 1.2 1995/10/30 13:33:16 akers +// Added cdev specific version of strncpy +// +// +// +#ifndef _CDEV_COMMON_H +#define _CDEV_COMMON_H + +#include +#include + +// ***************************************************************************** +// * cdevStrncpy: +// * This is an alternative to the strncpy routine. This function will +// * always NULL terminate the resulting string, strncpy does not. +// ***************************************************************************** +inline char * cdevStrncpy(char *s1, const char *s2, size_t n) + { + char * result = s1; + if(s1!=NULL) + { + while(s2!=NULL && *s2 && (n--)>1) *(s1++) = *(s2++); + *s1=0; + } + return result; + } + +#endif /* _CDEV_COMMON_H */ diff --git a/include/cdevConfigFinder.h b/include/cdevConfigFinder.h new file mode 100644 index 0000000..6f2bbfc --- /dev/null +++ b/include/cdevConfigFinder.h @@ -0,0 +1,95 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// CDEV Configuration Loader for different site +// +// Author: Jie Chen +// +// Revision History: +// cdevConfigFinder.h,v +// Revision 1.1 1997/08/27 18:23:30 chen +// Change error reporting to site specific scheme +// +// +// +#ifndef _CDEV_CONFIG_FINDER_H +#define _CDEV_CONFIG_FINDER_H + +#if defined (_WIN32) + +#ifndef SHOBJ +#define SHOBJ 1 +#endif + +#endif /* WIN 32 */ + +#ifdef SHOBJ + +#include +#include +#include + +#define _CDEV_CONFIG_FILENAME "cdevSiteConfig.so" +#define _CDEV_CONFIG_ROUTINE "_cdev_site_config" + +class shObjLoader; + +class cdevConfigFinder +{ +public: + // constructor and destructor + cdevConfigFinder (cdevSystem& system = cdevSystem::defaultSystem ()); + ~cdevConfigFinder (void); + + + int loadConfig (void); + // PURPOSE: load a site defined configuration file with routine name + // _cdev_site_config (cdevSystem& system) + // REQUIRE: none + // PROMISE: return 0: configuration loaded. return -1: failed + +protected: + + // flag that denotes whether the system has tried load config or not + static int tloadconfig_; + +private: + // deny assignment and copy operations + cdevConfigFinder (const cdevConfigFinder& finder); + cdevConfigFinder& operator = (const cdevConfigFinder& finder); + + // data area + shObjLoader* loader_; + cdevSystem& system_; +}; + +#else + +#include +#include +#include + +class cdevConfigFinder +{ +public: + // constructor + cdevConfigFinder (cdevSystem& system = cdevSystem::defaultSystem ()); + + int loadConfig (void) {return 0;} +private: + // deny assignment and copy operations + cdevConfigFinder (const cdevConfigFinder& finder); + cdevConfigFinder& operator = (const cdevConfigFinder& finder); +}; +#endif + +#endif + + diff --git a/include/cdevData.h b/include/cdevData.h new file mode 100644 index 0000000..498fe63 --- /dev/null +++ b/include/cdevData.h @@ -0,0 +1,578 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: cdevData.h +// Self descibing data structure to manage the storage and transport +// of data between local cdev functions, as well as remote client and +// server applications. +// +// Author: Walt Akers and Danjin Wu +// +// Revision History: +// cdevData.h,v +// Revision 1.24 1997/12/22 13:47:02 akers +// Made changeTag method virtual +// +// Revision 1.23 1997/08/01 19:06:29 akers +// Added addTag and tagExists feature to the library +// +// Revision 1.22 1997/01/14 19:39:39 chen +// add += operator +// +// Revision 1.21 1997/01/09 16:32:39 akers +// Corrected anachronism +// +// Revision 1.20 1996/11/21 17:02:57 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.19 1996/10/01 13:58:19 akers +// Changes to support AIX +// +// Revision 1.18 1996/09/20 19:33:11 akers +// Changed protection in cdevDataEntryStorage, cdevDataEntry and cdevData in order to support subclassing of the cdevData object +// +// Revision 1.17 1996/09/20 15:41:51 akers +// Made xdr methods virual +// +// Revision 1.16 1996/08/26 19:14:05 akers +// Adding cdevData.inserttag callback capabilities +// +// Revision 1.15 1996/08/23 15:34:07 akers +// Added comparison operator to cdevData +// +// Revision 1.14 1996/07/12 18:08:52 chen +// change copy and assignment to const cdevData& +// +// Revision 1.13 1996/04/12 13:40:04 akers +// Added char * cast operator +// +// Revision 1.12 1996/02/27 20:50:05 danjin +// add assignment operator from various typed data to cdevData object +// +// Revision 1.11 1995/11/01 15:43:42 akers +// Corrected INLINE definition +// +// Revision 1.10 1995/10/06 20:09:47 chen +// add stdio +// +// Revision 1.9 1995/10/06 19:38:34 chen +// Seperate inline functions +// +// Revision 1.8 1995/10/03 19:36:34 chen +// Use new cdevGlobalTagTable Class +// +// Revision 1.7 1995/09/22 21:04:24 danjin +// added cdevDataIterator mechanism +// +// Revision 1.6 1995/09/13 15:27:10 danjin +// added changeTagName func +// +// Revision 1.5 1995/09/06 18:34:16 danjin +// added time stamp structure and related func +// +// Revision 1.4 1995/07/20 14:36:52 akers +// Mispelling in header +// +// Revision 1.3 1995/07/19 20:34:06 akers +// CVS +// +// Revision 1.2 1995/07/14 13:20:09 akers +// Updated cdevData header file supporting changes specified at June 95 Review +// +// +// +//-------------------------------------------------------------------------- + +#ifndef _CDEV_DATA_H +#define _CDEV_DATA_H + +#include + +#ifdef _WIN32 +#include +#include +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __hpux +extern char* ltoa (long val); +extern char* ultoa (unsigned long val); +#endif + +#ifndef _WIN32 + extern "C" char *ctime (__const time_t *__timer) __THROW; +#endif + +class CDEV_CLASS_SPEC cdevData + { + friend class cdevDataIterator; + protected: + cdevDataEntry *entries; + + // ********************************************************************* + // * copy: + // * This function copies the contents of the cdevData object + // * specified by data into this cdevData object. It is used by + // * both the copy constructor and by the assignment operator. + // ********************************************************************* + cdevData & copy (const cdevData & data); + + // ********************************************************************* + // * lookupTag: + // * This function is for internal use and allows a cdevData object + // * to locate and optionally create a tagged data item. + // ********************************************************************* + cdevDataEntry * lookupTag(int tag, int create = 0); + cdevDataEntry * lookupTag(char * ctag, int create = 0); + + // ********************************************************************* + // * setupTag: + // * This function is for internal use and is used to prepare a new + // * cdevDataEntry object prior to inserting data into it. + // ********************************************************************* + cdevDataEntry * setupTag ( + int tag, cdevDataTypes type, size_t elemSize, + size_t numElems, size_t numDims ); + + public: + // ********************************************************************* + // * This group of static functions allows the user an interface to the + // * database of tagged data items that is stored in the + // * cdevGlobalTagTable object. + // ********************************************************************* + static int tagC2I (char *ctag, int *tag); + static int tagI2C (int tag, char * &ctag); + static void insertTag(int tag, char *ctag); + static int tagExists(char * ctag); + static int tagExists(int tag); + static int addTag (char * ctag); + + // *************************************************************************** + // * addTagCallback : + // * This method will add a cdevTagTableCallback object to the list of + // * classes that should be notified each time a tag is added to the + // * cdevTagTable. + // *************************************************************************** + static void addTagCallback ( cdevTagTableCallback * cb ); + + // *************************************************************************** + // * delTagCallback : + // * This method will remote a cdevTagTableCallback object that was + // * previously added to the list of callback classes. + // * + // * Note: This method does not actually delete the cdevTagTableCallback + // * object, it merely removes it from the list. It is the + // * responsibility of the owner to delete the object when it is + // * no longer needed. + // *************************************************************************** + static void delTagCallback ( cdevTagTableCallback * cb ); + + // ***************************************************************************** + // * readTagTable : + // * This method allows the caller to obtain a list of tag names and + // * integers that are currently stored in this tag table. + // * + // * Note: This method will allocate an array of integers and an array of + // * character string pointers. The strings that are stored in the + // * string array will be the actual strings from within the + // * tag table and should not be deleted... + // * + // * The data allocated becomes the property of the caller and must + // * be deleted when it is no longer needed... the correct syntax to + // * delete these items is... + // * + // * delete tags; + // * delete ctags; + // * + // * This will delete the array, however, it will leave the + // * individual array elements intact. + // ***************************************************************************** + static int readTagTable ( int * &tags, char ** &ctags, int &ntags ); + + // ********************************************************************* + // * cdevData: + // * This is the default constructor, it simply initializes + // * variables within the cdevData object. + // ********************************************************************* + cdevData ( void ); + + // ********************************************************************* + // * cdevData: + // * Copy constructor. This constructor duplicates the cdevData + // * object that it has been passed as a parameter. + // ********************************************************************* + cdevData ( const cdevData & data ); + + // ********************************************************************* + // * ~cdevData: + // * This is the default destructor for the cdevData object. It + // * frees any memory allocated for storage and deletes the object. + // ********************************************************************* + ~cdevData( void ); + + // ********************************************************************* + // * Assignment operator: + // * This function copies the contents of a cdevData object to this + // * object. + // ********************************************************************* + cdevData & operator = (const cdevData & data); + + // ********************************************************************* + // * Casting operators: + // * These operators provide convenience methods for the user to + // * obtain the value tagged data item from the cdevData object. + // ********************************************************************* + operator char ( void ); + operator short ( void ); + operator unsigned short ( void ); + operator int ( void ); + operator unsigned int ( void ); + operator long ( void ); + operator unsigned long ( void ); + operator float ( void ); + operator double ( void ); + operator char * ( void ); + + // ********************************************************************* + // * Assignment operators: + // * These operators provide convenience methods for the user to + // * obtain the value tagged cdevData object from various typed data. + // ********************************************************************* + cdevData& operator= (unsigned char x); + cdevData& operator= (short x); + cdevData& operator= (unsigned short x); + cdevData& operator= (int x); + cdevData& operator= (unsigned int x); + cdevData& operator= (long x); + cdevData& operator= (unsigned long x); + cdevData& operator= (float x); + cdevData& operator= (double x); + + // ********************************************************************* + // * Append operation: + // * This operation will append a cdevData onto an existing cdevData + // * and return this object. If there is confilicts among tags, the + // * appended one wins + // ********************************************************************* + cdevData& operator += (const cdevData& data); + + // ********************************************************************* + // * asciiDump: + // * Performs a diagnostic dump of the entire contents of the + // * cdevData object to the specified file pointer. + // ********************************************************************* +#ifdef _WIN32 + inline void asciiDump ( FILE * fp = stdout ) + { + int fd = _fileno(fp); + long osfHandle = _get_osfhandle(fd); + asciiDump(osfHandle); + _lseek(fd, 0L, SEEK_END); + } + void asciiDump ( long osfHandle ); +#else + void asciiDump ( FILE * fp = stdout ); +#endif + + // ********************************************************************* + // * XDR Utilities: + // * These functions provide the mechanisms for converting a cdevData + // * object into a network portable bninary stream, and then + // * reconstructing them after transport. + // ********************************************************************* + virtual int xdrSize (size_t * bufLen, size_t * elementCount); + virtual int xdrExport ( char ** buf, size_t * bufLen ); + virtual int xdrExport ( char * buf, size_t bufLen, size_t count); + virtual int xdrImport ( char * buf, size_t bufLen); + + // ********************************************************************* + // * remove: + // * Removes cdevDataEntry objects from the cdevData object by tag + // * integer or by tag string. If no tag is specified, then all + // * cdevDataEntry objects will be removed. + // ********************************************************************* + void remove( void ); + void remove( int tag ); + void remove( char * ctag ); + + // ********************************************************************* + // * changeTag: + // * Replace a new tag with the old one within the + // * cdevData object. If the old one can not be not found, + // * CDEV_NOTFOUND is returned. If the new tag has already + // * been found in that cdevData object, CDEV_ERROR is returned. + // ********************************************************************* + virtual int changeTag(int oldTag, int newTag); + int changeTag(int oldTag, char *c_newTag); + int changeTag(char *c_oldTag, int newTag); + int changeTag(char *c_oldTag, char *c_newTag); + + // ********************************************************************* + // * getType: + // * Retrieves the cdevDataTypes of the referenced tagged data item. + // * If no item with that tag is within the cdevData object, then + // * CDEV_INVALID is returned. + // ********************************************************************* + cdevDataTypes getType(int tag); + cdevDataTypes getType(char *ctag); + + + // ********************************************************************* + // * getDim: + // * Obtains the number of dimensions in the specified tagged data + // * item. Returns CDEV_SUCCESS if the tagged item exists, otherwise, + // * CDEV_NOTFOUND is returned. + // ********************************************************************** + int getDim(int tag, size_t *dim); + int getDim(char *ctag, size_t *dim); + + // ********************************************************************* + // * getElems: + // * Obtains the number of elements in the specified tagged data + // * item. Returns CDEV_SUCCESS if the tagged item exists, otherwise, + // * CDEV_NOTFOUND is returned. + // ********************************************************************** + int getElems(int tag, size_t *elems); + int getElems(char *ctag, size_t *elems); + + // ********************************************************************* + // * getBounds: + // * Obtains the bounding dimensions of a cdevDataEntry array. The + // * integer array passed as the bounds parameter must be allocated + // * by the caller. The number of integers required is 2 times the + // * number of dimensions, the first being the offset and the second + // * being the length of the dimension. The len parameter specifies + // * the actual number of integers allocated. + // ********************************************************************* + int getBounds(int tag, size_t * bounds, size_t len); + int getBounds(char * ctag, size_t * bounds, size_t len); + + // ********************************************************************* + // * getBounds: + // * Obtains the bounding dimensions of a cdevDataEntry array. The + // * cdevBounds structure passed as the bounds parameter must be + // * allocated by the caller. The numBounds variable indicates the + // * number of cdevBounds structures allocated by the caller. + // ********************************************************************* + int getBounds(int tag, cdevBounds * bounds, size_t numBounds); + int getBounds(char * ctag, cdevBounds * bounds, size_t numBounds); + + // ********************************************************************* + // * setBounds: + // * Allows the caller to set the dimensions of a multidimensional + // * tagged data item. The number of integers required is 2 times the + // * number of dimensions, the first being the offset and the second + // * being the length of the dimension. The len parameter specifies + // * the actual number of integers submitted. + // ********************************************************************* + int setBounds(int tag, size_t * bounds, size_t len); + int setBounds(char * ctag, size_t * bounds, size_t len); + + // ********************************************************************* + // * setBounds: + // * Allows the caller to set the dimensions of a multidimensional + // * tagged data item. The numBounds variable indicates the number + // * of cdevBounds structures submitted by the user. + // ********************************************************************* + int setBounds(int tag, cdevBounds * bounds, size_t numBounds); + int setBounds(char * ctag, cdevBounds * bounds, size_t numBounds); + + // ********************************************************************* + // * insert: + // * The following functions allow the insertion of scalar data into + // * a cdevData object. + // ********************************************************************* + int insert ( int tag, BYTE data ); + int insert ( int tag, short data ); + int insert ( int tag, unsigned short data ); + int insert ( int tag, long data ); + int insert ( int tag, unsigned long data ); + int insert ( int tag, float data ); + int insert ( int tag, double data ); + int insert ( int tag, cdev_TS_STAMP data ); + + // ********************************************************************* + // * Overloaded character tag based insertion mechanism + // ********************************************************************* + int insert ( char * ctag, BYTE data); + int insert ( char * ctag, short data); + int insert ( char * ctag, unsigned short data); + int insert ( char * ctag, long data); + int insert ( char * ctag, unsigned long data); + int insert ( char * ctag, float data); + int insert ( char * ctag, double data); + int insert ( char * ctag, cdev_TS_STAMP data); + + // ******************************************************************** + // * insert: + // * The following functions allow the insertion of arrays of data + // * into a cdevData object. The len variable contains the total + // * number of elements to be inserted, the ndim variable indicates + // * the number of dimensions in the array. + // ******************************************************************** + int insert (int tag, BYTE * data, size_t len, size_t ndim = 1); + int insert (int tag, short * data, size_t len, size_t ndim = 1); + int insert (int tag, unsigned short * data, size_t len, size_t ndim = 1); + int insert (int tag, long * data, size_t len, size_t ndim = 1); + int insert (int tag, unsigned long * data, size_t len, size_t ndim = 1); + int insert (int tag, float * data, size_t len, size_t ndim = 1); + int insert (int tag, double * data, size_t len, size_t ndim = 1); + int insert ( int tag, cdev_TS_STAMP *data, size_t len, size_t ndim = 1); + + // ********************************************************************* + // * Overloaded character tag based insertion mechanism + // ********************************************************************* + int insert (char * ctag, BYTE * data, size_t len, size_t ndim = 1); + int insert (char * ctag, short * data, size_t len, size_t ndim = 1); + int insert (char * ctag, unsigned short * data, size_t len, size_t ndim = 1); + int insert (char * ctag, long * data, size_t len, size_t ndim = 1); + int insert (char * ctag, unsigned long * data, size_t len, size_t ndim = 1); + int insert (char * ctag, float * data, size_t len, size_t ndim = 1); + int insert (char * ctag, double * data, size_t len, size_t ndim = 1); + int insert (char * ctag, cdev_TS_STAMP *data, size_t len, size_t ndim =1 ); + + // ********************************************************************* + // * insert: + // * The following functions explicitly call the long functions when + // * dealing with integer data. On a system with 16 bit integers, + // * the short functions should be called. + // ********************************************************************* +#ifdef DEFAULT_16_BIT_INTEGER + int insert ( int tag, int data ); + int insert ( int tag, unsigned int data ); + int insert ( char * ctag, int data); + int insert ( char * ctag, unsigned int data); + int insert (int tag, int * data, size_t len, size_t ndim = 1); + int insert (int tag, unsigned int * data, size_t len, size_t ndim = 1); + int insert (char * ctag, int * data, size_t len, size_t ndim = 1); + int insert (char * ctag, unsigned int * data, size_t len, size_t ndim = 1); +#else + int insert ( int tag, int data ); + int insert ( int tag, unsigned int data ) ; + int insert ( char * ctag, int data); + int insert ( char * ctag, unsigned int data); + int insert (int tag, int * data, size_t len, size_t ndim = 1); + int insert (int tag, unsigned int * data, size_t len, size_t ndim = 1); + int insert (char * ctag, int * data, size_t len, size_t ndim = 1); + int insert (char * ctag, unsigned int * data, size_t len, size_t ndim = 1); +#endif + + // ********************************************************************* + // * insert: + // * The following functions insert character strings and arrays of + // * character strings. Their treatment is different from the scalar + // * data types. + // ********************************************************************* + int insert ( int tag, char * data ); + int insert ( int tag, char ** data, size_t len = 0, size_t ndim = 1 ); + + // ********************************************************************* + // * Overloaded character tag based insertion mechanism + // ********************************************************************* + int insert ( char * ctag, char * data); + int insert ( char * ctag, char ** data, size_t len = 0, size_t ndim = 1); + + // ********************************************************************* + // * get: + // * This group of functions allows the user to extract scalar and + // * array data from the cdevData object. + // ********************************************************************* + int get(int tag, BYTE * data); + int get(int tag, short * data); + int get(int tag, unsigned short * data); + int get(int tag, long * data); + int get(int tag, unsigned long * data); + int get(int tag, float * data); + int get(int tag, double * data); + int get(int tag, char * data, size_t len); + int get(int tag, char ** data); + int get(int tag, cdev_TS_STAMP * data); + // ********************************************************************* + // * Overloaded character tag based extraction mechanism + // ********************************************************************* + int get(char * ctag, BYTE * data); + int get(char * ctag, short * data); + int get(char * ctag, unsigned short * data); + int get(char * ctag, long * data); + int get(char * ctag, unsigned long * data); + int get(char * ctag, float * data); + int get(char * ctag, double * data); + int get(char * ctag, char * data, size_t len); + int get(char * ctag, char ** data); + int get(char * ctag, cdev_TS_STAMP * data); + + // ********************************************************************* + // * get: + // * The following get functions explicitly call the long integer + // * functions unless the user is on a system with 16 bit integers. + // ********************************************************************* +#ifdef DEFAULT_16_BIT_INTEGER + int get(int tag, int * data); + int get(int tag, unsigned int * data); + int get(char *ctag, int * data); + int get(char *ctag, unsigned int * data); +#else + int get(int tag, int * data); + int get(int tag, unsigned int * data); + int get(char *ctag, int * data); + int get(char *ctag, unsigned int * data); +#endif + + // ********************************************************************* + // * find: + // * These functions allow the user to obtain a pointer to data + // * within the actual data variables within the cdevData object. + // ********************************************************************* + int find(int tag, void* &data); + int find(char * ctag, void* &data); + + // ********************************************************************* + // * operator ==, operator !=: + // * These methods provides a fast way for the caller to identify if two + // * cdevData objects contain the identical fields and values... + // ********************************************************************* + int operator == (cdevData & data); + int operator != (cdevData & data) { return !(operator == (data)); } + }; + + +class CDEV_CLASS_SPEC cdevDataIterator + { + public: + cdevDataIterator(cdevData* data); + ~cdevDataIterator() {}; + int init(); + int operator !(); + int operator ++(); + int tag(void); + + protected: + cdevData *dataobj_; + cdevDataEntry *cur_; + }; + +#undef INLINE +#ifndef _CDEV_NO_INLINE +#define INLINE inline +#include "cdevData.i" +#else +#define INLINE +#endif + +#endif diff --git a/include/cdevData.i b/include/cdevData.i new file mode 100644 index 0000000..af9206c --- /dev/null +++ b/include/cdevData.i @@ -0,0 +1,572 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: cdevData.h +// Self descibing data structure to manage the storage and transport +// of data between local cdev functions, as well as remote client and +// server applications. +// +// Author: Walt Akers and Danjin Wu +// +// Revision History: +// cdevData.i,v +// Revision 1.6 1996/11/21 17:02:59 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.5 1996/07/12 18:09:01 chen +// change copy and assignment to const cdevData& +// +// Revision 1.4 1996/04/12 13:40:07 akers +// Added char * cast operator +// +// Revision 1.3 1996/02/27 20:50:13 danjin +// add assignment operator from various typed data to cdevData object +// +// Revision 1.2 1995/10/16 18:14:20 chen +// Fix a bug for SunOs and g++ +// +// Revision 1.1 1995/10/06 19:39:03 chen +// all cdevData inline functions +// +// +INLINE +cdevDataEntry* cdevData::lookupTag(char * ctag, int create) +{ + int tag; + return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + (cdevDataEntry *)0:lookupTag(tag, create); +} + +INLINE +cdevData & +cdevData::operator = (const cdevData & data) +{ + return copy(data); +} + +INLINE +void cdevData::remove( char * ctag ) +{ + int tag; if(!cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)) remove(tag); +} + +INLINE +cdevDataTypes cdevData::getType(char *ctag) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + CDEV_INVALID:getType(tag); +} + +INLINE +int cdevData::getDim(char *ctag, size_t *dim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + CDEV_NOTFOUND:getDim(tag, dim); +} + +INLINE +int cdevData::getElems(char *ctag, size_t *elems) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + CDEV_NOTFOUND:getElems(tag, elems); +} + +INLINE +int cdevData::getBounds(char * ctag, size_t * bounds, size_t len) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + CDEV_NOTFOUND:getBounds(tag, bounds, len); +} + +INLINE +int cdevData::getBounds(char * ctag, cdevBounds * bounds, size_t numBounds) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + CDEV_NOTFOUND:getBounds(tag, bounds, numBounds); +} + +INLINE +int cdevData::setBounds(char * ctag, size_t * bounds, size_t len) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + CDEV_NOTFOUND:setBounds(tag, bounds, len); +} + +INLINE +int cdevData::setBounds(char * ctag, cdevBounds * bounds, size_t numBounds) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + CDEV_NOTFOUND:setBounds(tag, bounds, numBounds); +} + +INLINE +int cdevData::insert ( char * ctag, BYTE data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, short data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, unsigned short data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, long data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, unsigned long data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, float data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, double data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, cdev_TS_STAMP data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert (char * ctag, BYTE * data, size_t len, size_t ndim) +{ +int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, short * data, size_t len, size_t ndim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, unsigned short * data, size_t len, size_t ndim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, long * data, size_t len, size_t ndim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, unsigned long * data, size_t len, size_t ndim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, float * data, size_t len, size_t ndim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, double * data, size_t len, size_t ndim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert ( char * ctag, char * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, char ** data, size_t len, size_t ndim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, cdev_TS_STAMP * data, size_t len, size_t ndim) +{ +int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::get(char * ctag, BYTE * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, short * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, unsigned short * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, long * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, unsigned long * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, float * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, double * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, char * data, size_t len) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data, len); +} + +INLINE +int cdevData::get(char * ctag, char ** data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, cdev_TS_STAMP * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::find(char * ctag, void* &data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:find(tag, data); +} + +#ifdef DEFAULT_16_BIT_INTEGER +INLINE +int cdevData::insert ( int tag, int data ) +{ + return insert(tag, (short)data); +} + +INLINE +int cdevData::insert ( int tag, unsigned int data ) +{ + return insert(tag, (unsigned short)data); +} + +INLINE +int cdevData::insert ( char * ctag, int data) +{ + return insert(ctag, (short)data); +} + +INLINE +int cdevData::insert ( char * ctag, unsigned int data) +{ + return insert(ctag, (unsigned short)data); +} + +INLINE +int cdevData::insert (int tag, int * data, size_t len, size_t ndim) +{ + return insert(tag, (short *)data, len, ndim); +} + +INLINE +int cdevData::insert (int tag, unsigned int * data, size_t len, size_t ndim) +{ + return insert(tag, (unsigned short *)data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, int * data, size_t len, size_t ndim) +{ + return insert(ctag, (short *)data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, unsigned int * data, size_t len, size_t ndim) +{ + return insert(ctag, (unsigned short *)data, len, ndim); +} +#else +INLINE +int cdevData::insert ( int tag, int data ) +{ + return insert(tag, (long)data); +} + +INLINE +int cdevData::insert ( int tag, unsigned int data ) +{ + return insert(tag, (unsigned long)data); +} + +INLINE +int cdevData::insert ( char * ctag, int data) +{ + return insert(ctag, (long)data); +} + +INLINE +int cdevData::insert ( char * ctag, unsigned int data) +{ + return insert(ctag, (unsigned long)data); +} + +INLINE +int cdevData::insert (int tag, int * data, size_t len, size_t ndim) +{ + return insert(tag, (long *)data, len, ndim); +} + +INLINE +int cdevData::insert (int tag, unsigned int * data, size_t len, size_t ndim) +{ + return insert(tag, (unsigned long *)data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, int * data, size_t len, size_t ndim) +{ + return insert(ctag, (long *)data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, unsigned int * data, size_t len, size_t ndim) +{ + return insert(ctag, (unsigned long *)data, len, ndim); +} +#endif + +#ifdef DEFAULT_16_BIT_INTEGER +INLINE +int cdevData::get(int tag, int * data) +{ + return get(tag, (short *)data); +} + +INLINE +int cdevData::get(int tag, unsigned int * data) +{ + return get(tag, (unsigned short *) data); +} + +INLINE +int cdevData::get(char *ctag, int * data) +{ + return get(ctag, (short *)data); +} + +INLINE +int cdevData::get(char *ctag, unsigned int * data) +{ + return get(ctag, (unsigned short *) data); +} +#else +INLINE +int cdevData::get(int tag, int * data) +{ + return get(tag, (long *)data); +} + +INLINE +int cdevData::get(int tag, unsigned int * data) +{ + return get(tag, (unsigned long *) data); +} + +INLINE +int cdevData::get(char *ctag, int * data) +{ + return get(ctag, (long *)data); +} + +INLINE +int cdevData::get(char *ctag, unsigned int * data) +{ + return get(ctag, (unsigned long *) data); +} +#endif + +INLINE +cdevData::operator char( void ) +{ + BYTE x; get("value", &x); return x; +} + +INLINE +cdevData::operator short( void ) +{ + short x; get("value", &x); return x; +} + +INLINE +cdevData::operator unsigned short( void ) +{ + unsigned short x; get("value", &x); return x; +} + +INLINE +cdevData::operator int( void ) +{ + int x; get("value", &x); return x; +} + +INLINE +cdevData::operator unsigned int( void ) +{ + unsigned int x; get("value", &x); return x; +} + +INLINE +cdevData::operator long( void ) +{ + long x; get("value", &x); return x; +} + +INLINE +cdevData::operator unsigned long( void ) +{ + unsigned long x; get("value", &x); return x; +} + +INLINE +cdevData::operator float( void ) +{ + float x; get("value", &x); return x; +} + +INLINE +cdevData::operator double( void ) +{ + double x; get("value", &x); return x; +} + + +INLINE +cdevData::operator char * ( void ) +{ +char * result = NULL; +static char temp[64]; +size_t dim = 0; +int valueTag = 1; +cdevDataTypes dataType = CDEV_INVALID; + +tagC2I("value", &valueTag); +getDim(valueTag, &dim); +if(dim==0) dataType = getType(valueTag); + +switch(dataType) + { + case CDEV_INVALID: + result=NULL; + break; + + case CDEV_STRING: + find("value", (void * &)result); + break; + + default: + get("value", temp, 64); + result = temp; + break; + + } +return result; +} + + +INLINE +cdevData& cdevData::operator= (unsigned char x) +{ + insert("value", x); + return *this; +} + +INLINE cdevData& cdevData::operator= (short x) +{ + insert("value", x); + return *this; +} + +INLINE cdevData& cdevData::operator= (unsigned short x) +{ + insert("value", x); + return *this; +} + +INLINE cdevData& cdevData::operator= (int x) +{ + insert("value", x); + return *this; +} + +INLINE cdevData& cdevData::operator= (unsigned int x) +{ + insert("value", x); + return *this; +} +INLINE cdevData& cdevData::operator= (long x) +{ + insert("value", x); + return *this; +} + +INLINE cdevData& cdevData::operator= (unsigned long x) +{ + insert("value", x); + return *this; +} + +INLINE cdevData& cdevData::operator= (float x) +{ + insert("value", x); + return *this; +} + +INLINE cdevData& cdevData::operator= (double x) +{ + insert("value", x); + return *this; +} + + + diff --git a/include/cdevDataEntry.h b/include/cdevDataEntry.h new file mode 100644 index 0000000..cbccc55 --- /dev/null +++ b/include/cdevDataEntry.h @@ -0,0 +1,365 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//------------------------------------------------------------------------------ +// +// description: cdevDataEntry.h +// This file defines the classes necessary for storage of an individual +// tagged data item within a cdevData class object. +// +// Author: Walt Akers & Danjin Wu +// +// Revision History: +// cdevDataEntry.h,v +// Revision 1.9 1996/11/21 17:03:04 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.8 1996/09/20 19:33:12 akers +// Changed protection in cdevDataEntryStorage, cdevDataEntry and cdevData in order to support subclassing of the cdevData object +// +// Revision 1.7 1996/08/23 21:24:25 akers +// Corrected Problem with operator == +// +// Revision 1.6 1996/08/23 15:34:09 akers +// Added comparison operator to cdevData +// +// Revision 1.5 1995/10/16 18:13:59 chen +// Fix a bug fot sunOs and g++ +// +// Revision 1.4 1995/09/22 21:08:14 danjin +// cdevdataIterator is friend class +// +// Revision 1.3 1995/09/06 18:34:49 danjin +// added time stamp structure type +// +// Revision 1.2 1995/07/14 13:25:30 akers +// Header files added to support the changes specified at June 95 Review +// +// +// +//------------------------------------------------------------------------------ + +#ifndef __CDEV_DATA_ENTRY_H_ +#define __CDEV_DATA_ENTRY_H_ + +#include +#include + +// ############################################################################# +// # cdevDataEntryStorage: +// # This class contains the data elements and methods necessary to store data +// # associated with one tagged data item. +// # +// # Note: Because the cdevData object must actively manipulate the data in +// # this structure - it has been made public to increase access speed +// # and to allow the subclassing of the cdevData object. +// ############################################################################# +class cdevDataEntryStorage + { + public: + // ************************************************************* + // * tag_: + // * This is the integer value that is used to uniquely identify + // * a data element within a cdevData object. + // ************************************************************* + int tag_; + + // ************************************************************* + // * dataType_: + // * This is the data type of the tagged data item that is to be + // * stored in this cdevDataEntryStorage object. + // ************************************************************* + cdevDataTypes dataType_; + + // ************************************************************* + // * size_: + // * This variable is the allocated size of the buffer_ which is + // * used to store both the array data and its associated bounds + // * information. + // ************************************************************* + size_t size_; + + // ************************************************************* + // * dim_: + // * This variable indicates the user specified number of + // * dimensions that the array represents. + // ************************************************************* + size_t dim_; + + // ************************************************************* + // * elems_: + // * This variable contains the maximum number of elements that + // * the array may contain. + // ************************************************************* + size_t elems_; + + // ************************************************************* + // * bytes_: + // * This variable contains the number of bytes per element. + // ************************************************************* + size_t bytes_; + + // ************************************************************* + // * buffer_: + // * This is the buffer that is allocated to store data and + // * bounds information. + // ************************************************************* + unsigned char * buffer_; + + // ************************************************************* + // * data_: + // * This is a union that is used to store scalar data and a + // * pointer to the array data this is stored within this object + // ************************************************************* + union dataUnion { + BYTE cval; + short sval; + unsigned short usval; + long lval; + unsigned long ulval; + float fval; + double dval; + void * vptr; + BYTE * cptr; + short * sptr; + unsigned short * usptr; + long * lptr; + unsigned long * ulptr; + float * fptr; + double * dptr; + char * str; + char ** strarr; + cdev_TS_STAMP ts; + cdev_TS_STAMP * tsptr; + } data_; + + // ************************************************************* + // * cdevDataEntryStorage: + // * Default constructor for the cdevDataEntryStorage class. It sets + // * the buffer_ pointer to NULL to prevent deletion of non- + // * allocated memory, and then calls the clear method to + // * initialize all data variables. + // ************************************************************* + cdevDataEntryStorage ( void ) : buffer_(NULL) + { + clear(); + } + + // ************************************************************* + // * ~cdevDataEntryStorage: + // * Default destructor for the cdevDaaEntry class. It calls + // * the clear method to release and reinitialize all data + // * elements. + // ************************************************************* + ~cdevDataEntryStorage ( void ) + { + clear(); + } + + // ************************************************************* + // * clear: + // * Releases and reinitializes all data variables. + // ************************************************************* + void clear ( void ) + { + deallocate(); + tag_ = 0; + dataType_ = CDEV_INVALID; + } + + // ************************************************************* + // * allocate: + // * Allocates a block of memory sufficient to store a caller + // * specified number of cdevBounds structures and a caller + // * specified number of bytes. If sufficient space has already + // * been allocated, then it will be used, otherwise, a new + // * block will be created to service the request. + // ************************************************************* + void allocate ( size_t dimensions, size_t elems, size_t bytesPerElem ) + { + size_t newBlockSize = + (dimensions*sizeof(cdevBounds))+(elems * bytesPerElem); + + if(buffer_==NULL || newBlockSize>size_) + { + deallocate(); + buffer_ = ::new unsigned char[newBlockSize]; + size_ = newBlockSize; + } + dim_ = dimensions; + elems_ = elems; + bytes_ = bytesPerElem; + data_.vptr = &buffer_[dim_ * sizeof(cdevBounds)]; + memset (buffer_, 0, newBlockSize); + } + + // ************************************************************* + // * deallocate: + // * Deallocates any memory previously allocated to the buffer + // * and reinitializes the size_, dim_, bytes_ and buffer_ + // * variables. Any references to the previously allocated + // * block is cleared. + // ************************************************************* + void deallocate ( void ) + { + if(buffer_ != NULL) + { + ::delete buffer_; + buffer_ = NULL; + } + size_ = 0; + dim_ = 0; + elems_ = 0; + bytes_ = 0; + data_.dval = 0.00; + // memset(&data_, 0, sizeof(data_)); + } + + // ************************************************************* + // * bounds: + // * Returns a pointer to the cdevBounds object if the data + // * is multidimensional, otherwise, a NULL is returned. + // ************************************************************* + cdevBounds * bounds ( void ) + { + return (dim_>0)?(cdevBounds *)buffer_:(cdevBounds *)0; + } + + // ************************************************************* + // * operator ==: + // * This operator allows you to directly and rapidly + // * compare two cdevDataEntryStorage objects... + // ************************************************************* + int operator == (cdevDataEntryStorage & entry); + + // ************************************************************* + // * operator !=: + // * This operator allows the caller to directly and rapidly + // * comapre two cdevDataEntryStorage objects. + // ************************************************************* + int operator != (cdevDataEntryStorage & entry) + { + return !(operator == (entry)); + } + + }; + + +// ############################################################################# +// # cdevDataEntry: +// # This class is used to define the node attributes necessary to support +// # linked lists of cdevDataEntryStorage objects. It also provides an internal +// # freelist of cdevDataEntry objects. +// # +// # Note: Because the cdevData object must actively manipulate the data in +// # this structure - it has been made public to increase access speed +// # and to allow the subclassing of the cdevData object. +// ############################################################################# +class cdevDataEntry : public cdevDataEntryStorage + { + public: + // ************************************************************* + // * freeList_: + // * This is a pointer to a list of currently allocated + // * cdevDataEntrys that will be provided to the user + // * upon request. This technique should reduce the number of + // * mallocs called to allocated cdevDataEntrys. + // ************************************************************* + static cdevDataEntry * freeList_; + + // ************************************************************* + // * ALLOCATION_COUNT: + // * This is the minimum number of cdevDataEntrys that will + // * be allocated when the freeList_ becomes empty. + // ************************************************************* + enum { ALLOCATION_COUNT = 16 }; + + // ************************************************************* + // * next_ : + // * This is the pointer to the next element in the list of + // * cdevDataEntry objects. + // ************************************************************* + cdevDataEntry * next_; + + // ************************************************************* + // * cdevDataEntry: + // * Constructor for the class. It serves only to set the next_ + // * pointer to NULL. + // ************************************************************* + cdevDataEntry ( void ) : next_(NULL), cdevDataEntryStorage() + { + } + + // ************************************************************* + // * ~cdevDataEntry: + // * Destructor for the class. It is a placeholder that + // * does nothing when called. + // ************************************************************* + ~cdevDataEntry ( void ) + { + } + + // ************************************************************* + // * next: + // * Retrieves a pointer to the next_ cdevDataEntry object. + // * Incorporation of this function into a list object is the + // * responsibility of the caller. + // ************************************************************* + cdevDataEntry * &next ( void ) + { + return next_; + } + + // ************************************************************* + // * new: + // * Allocation function for the object. It will get the next + // * preallocated cdevDataEntry object from the freeList_, + // * or, if none are available, refill the freeList_ and then + // * return a new cdevDataEntry object. + // ************************************************************* + void * operator new ( size_t size ); + + // ************************************************************* + // * delete: + // * Rather than deallocating the cdevDataEntry object, this + // * function returns it to the freeList_ where it may be + // * retrieved by a later call of new. + // ************************************************************* + void operator delete ( void * ptr ) + { + cdevDataEntry * node = (cdevDataEntry *)ptr; + if(node != NULL) { + node->next_ = freeList_; + freeList_ = node; + } + } + + // ************************************************************* + // * operator ==: + // * This operator allows you to directly and rapidly + // * compare two cdevDataEntry objects... + // ************************************************************* + int operator == (cdevDataEntry & entry) + { + cdevDataEntryStorage *storage = &entry; + + return cdevDataEntryStorage::operator == (*storage); + } + + // ************************************************************* + // * operator !=: + // * This operator allows the caller to directly and rapidly + // * comapre two cdevDataEntry objects. + // ************************************************************* + int operator != (cdevDataEntry & entry) + { + cdevDataEntryStorage *storage = &entry; + return !(cdevDataEntryStorage::operator == (*storage)); + } + + }; + +#endif /* __CDEV_DATA_ENTRY_H_ */ diff --git a/include/cdevDefCollectionRequest.h b/include/cdevDefCollectionRequest.h new file mode 100644 index 0000000..21d0c00 --- /dev/null +++ b/include/cdevDefCollectionRequest.h @@ -0,0 +1,192 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * cdevDefCollectionRequest.h : This is the default class that will be used + * to support collection operations for services. + * + * Author: Walt Akers + * + * Revision History: + * cdevDefCollectionRequest.h,v + * Revision 1.2 1998/10/22 17:57:41 chen + * fix a bug on setting collection values + * + * Revision 1.1 1996/11/12 20:32:25 akers + * New collection device source code + * + * ----------------------------------------------------------------------------- + */ +#ifndef _CDEV_DEF_COLLECTION_REQUEST_H +#define _CDEV_DEF_COLLECTION_REQUEST_H + +#include + +class CDEV_CLASS_SPEC cdevDefCollectionRequest: public cdevCollectionRequest +{ +friend class cdevCollectionRequest; +friend class cdevService; + +public: + // ********************************************************************* + // * This structure is provided as the void * argument to the default + // * callback whenever the synchronous send is used. The checkSum is + // * used to detect if the result returned after the send method stopped + // * waiting for it. + // ********************************************************************* + typedef struct + { + int completionCode; + int finished; + cdevData *data; + } SendStatus; + + // ********************************************************************* + // * These methods get state and access information for the underlying + // * cdevRequestObjects. + // ********************************************************************* + virtual int getState (void); + virtual int getAccess (void); + + // ********************************************************************* + // * This method sets the context of each of the underlying + // * cdevRequestObjects. + // ********************************************************************* + virtual int setContext (cdevData &ctx); + + // ********************************************************************* + // * cdevClientRequestObject::send : + // * The send interface is used to provide synchronous I/O with the + // * service. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int send ( cdevData & in, cdevData & out ) + { return send(&in, &out); } + virtual int send ( cdevData * in, cdevData & out ) + { return send(in, &out); } + virtual int send ( cdevData & in, cdevData * out ) + { return send(&in, out); } + virtual int send ( cdevData * in, cdevData * out ); + + // ********************************************************************* + // * sendNoBlock : + // * The sendNoBlock interface is used in conjunction with cdevGroup + // * or cdevSystem to execute a series of operations. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int sendNoBlock (cdevData & in, cdevData & out) + { return sendNoBlock(&in, &out); } + virtual int sendNoBlock (cdevData * in, cdevData & out) + { return sendNoBlock(in, &out); } + virtual int sendNoBlock (cdevData & in, cdevData * out) + { return sendNoBlock(&in, out); } + virtual int sendNoBlock (cdevData * in, cdevData * out); + + // ********************************************************************* + // * sendCallback : + // * The sendCallback interface provides asynchronous communications + // * with the service. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int sendCallback (cdevData & in, cdevCallback & callback) + { return sendCallback(&in, callback); } + virtual int sendCallback (cdevData * in, cdevCallback & callback); + + // ********************************************************************* + // * This method returns the name of the class. + // ********************************************************************* + const char *className (void) const {return "cdevDefCollectionRequest";} + +protected: + // ********************************************************************* + // * These are the protected constructor and destructor for this object. + // ********************************************************************* + cdevDefCollectionRequest (char **devices, int nDevices, char *msg, cdevSystem& sys); + virtual ~cdevDefCollectionRequest (void); + + // ********************************************************************* + // * This is the syncCallback method. It will be used by the send + // * method in order to detect the completion of the operation. + // ********************************************************************* + static void syncCallback (int status, void * user, cdevRequestObject &, cdevData &data); + + // ********************************************************************* + // * This callback function is used to receive the individual callbacks + // * from the underlying cdevRequestObjects and is used by sendCallback. + // ********************************************************************* + static void asyncCallback (int, void *, cdevRequestObject &, cdevData &); + + // ********************************************************************* + // * This is the asyncNoBlockCallback method. It will be used by the + // * sendNoBlock method in order to detect the completion of the + // * operation. + // ********************************************************************* + static void asyncNoBlockCallback (int status, void * user, cdevRequestObject &, cdevData &data); + + + // ********************************************************************* + // * This is routine set scaler value to array of cdevData with a + // * specified tag + // ********************************************************************* + static int setScalerDataValue (cdevData& data, int tag, + cdevData* res, int num); + + // ********************************************************************* + // * This is routine set vector value to array of cdevData with a + // * specified tag + // ********************************************************************* + static int setVectorDataValue (cdevData& data, int tag, size_t dim, + cdevData* res, int num); + + // ********************************************************************* + // * This is routine split a input cdevData into an array of cdevData. + // * The input data is either a scaler value which will be duplicated + // * to all splited data values, or a array of data whose bound[0].length + // * must be the same as the 'num'. This works for a single tag + // ********************************************************************* + static int splitDataItem (cdevData& data, int tag, + cdevData* res, int num); + + + // ********************************************************************* + // * This is routine split a input cdevData into an array of cdevData. + // * The input data is either a scaler value which will be duplicated + // * to all splited data values, or a array of data whose bound[0].length + // * must be the same as the 'num' + // * caller must free return cdevData array if it is not zero. + // ********************************************************************* + static cdevData *splitData (cdevData& data, int splitnum); + +private: + static SendStatus sendStatus; + static int sendCheckSum; + + // ********************************************************************* + // * These are the cdevRequestObjects that are addressed by each call + // * to this cdevDefCollectionRequest. The nRequests variable contains + // * the number of cdevRequestObjects that are represented. + // ********************************************************************* + cdevRequestObject **requests; + int nRequests; + + // ********************************************************************* + // * This is the master data structure. It contains no actual data, + // * however, it identifies the data structure that should exist when + // * the request has been executed. + // * + // * This structure is inspected and updated at the completion of each + // * callback, and is used to initially create the cdevData objects that + // * are used for interim data storage. + // ********************************************************************* + cdevData format; +}; + +#endif diff --git a/include/cdevDevice.h b/include/cdevDevice.h new file mode 100644 index 0000000..0c687b9 --- /dev/null +++ b/include/cdevDevice.h @@ -0,0 +1,161 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevDevice: a virtual control device +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevDevice.h,v +// Revision 1.4 1996/11/21 17:03:13 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.3 1995/07/05 18:39:43 chen +// change interface +// +// Revision 1.2 1995/06/30 15:59:27 chen +// remove all unnecessary files +// +// Revision 1.1.1.1 1995/06/16 17:14:06 epics +// initial import of cdev +// +// +#ifndef _CDEV_DEVICE_H +#define _CDEV_DEVICE_H + +#include +#include +#include +#include +#include +#include + +class cdevRequestObject; + +class CDEV_CLASS_SPEC cdevDevice: public cdevIOcontext +{ + public: + //=================================================================== + // Public Interface for Clients + //=================================================================== + static cdevDevice& attachRef (char *name); + static cdevDevice* attachPtr (char *name); + // PURPOSE: create a reference or pointer for device of a given name + // within the default system + // REQUIRE: name != 0 + // PROMISE: a cdevDevice + + static void detach (cdevDevice& dev); + static void detach (cdevDevice* dev); + // PURPOSE: destroy a cdevDevice + // REQUIRE: dev != 0 + // PROMISE: memory will be freed if no more attachment on this device + + const char *name (void) const; + // PURPOSE: return device name + // REQUIRE: nothing + // PROMISE: a name + + cdevSystem& system (void) const; + // PURPOSE: return system associated with this device + // REQUIRE: nothing + // PROMISE: return reference of the system + + virtual int send (char *msg, cdevData &out, cdevData& result); + virtual int send (char *msg, cdevData *out, cdevData& result); + virtual int send (char *msg, cdevData &out, cdevData* result); + virtual int send (char *msg, cdevData *out, cdevData* result); + // PURPOSE: synchronous IO operations + // REQUIRE: when set, provide out, when get, provide result + // PROMISE: return CDEV_SUCCESS: success. Check cdevErrCode.h for error info + + virtual int sendNoBlock (char *msg, cdevData &out, cdevData &result); + virtual int sendNoBlock (char *msg, cdevData *out, cdevData &result); + virtual int sendNoBlock (char *msg, cdevData &out, cdevData *result); + virtual int sendNoBlock (char *msg, cdevData *out, cdevData *result); + // PURPOSE: asynchronous IO operations + // REQUIRE: same as the above and one may use cdevGroup to group these + // PROMISE: return CDEV_SUCCESS: success. Check cdevErrCode.h for error info + + virtual int sendCallback (char *msg, cdevData &out, cdevCallback &callback); + virtual int sendCallback (char *msg, cdevData *out, cdevCallback &callback); + // PURPOSE: asynchronous IO operations with user supplied callback function + // REQUIRE: out != 0 + // PROMISE: return CDEV_SUCCESS: request sendout success. + // check cdevErrCode.h for error info + + // setIOcontext function, pass cxt to requestObject int the list + virtual int setContext (cdevData& cxt); + // PURPOSE: set context to this device + // REQUIRE: nothing + // PROMISE: always return 0, set constext to all request objects + // in this device + + //======================================================================== + // Public Interface for cdevRequestObject + //======================================================================== + virtual cdevRequestObject* getRequestObject (char *msg); + // PURPOSE: get a requestObject based on message 'msg' + // REQUIRE: msg != 0 + // PROMISE: return a pointer to requestObject + + virtual int getRequestObject (char *msg, cdevRequestObject* &reqobj); + // PURPOSE: get right requestObject + // REQUIRE: msg != 0, callers provide pointer only. + // PROMISE: always return CDEV_SUCCESS. reqobj may be an errorRequestObject + + virtual int registerReqObject (cdevRequestObject *obj); + // PURPOSE: register a requestObject into this device + // REQUIRE: obj != 0 + // PROMISE: return CDEV_SUCCESS: success, CDEV_ERROR: already here + + virtual int removeReqObject (cdevRequestObject *obj); + // PURPOSE: remove a requestObject from the device + // REQUIRE: obj != 0 + // PROMISE: return CDEV_SUCCESS: success, CDEV_ERROR: not here + + virtual const char *className (void) const {return "cdevDevice";} + + protected: + //constructors and destructor + cdevDevice (char *name, cdevSystem& system = cdevSystem::defaultSystem() ); + virtual ~cdevDevice (void); + + // attach pointer or reference with system as second argument + // protected to prevent application from using multiple systems + static cdevDevice& attachRef (char *name, cdevSystem& system); + static cdevDevice* attachPtr (char *name, cdevSystem& system); + // PURPOSE: create a reference or pointer for device of a given name + // REQUIRE: name != 0 + // PROMISE: a cdevDevice + + cdevRequestObject* findRequestObject(char *msg); + // PURPOSE: find an existing requestObject + // REQUIRE: name != 0, callers provide pointer only. + // PROMISE: return valid request object or NULL if not found + + // Protected data items + char *deviceName_; + cdevSystem& system_; + cdevSlist reqObjList_; + int unregOn_; // unregister self from system on delete + int refCount_; + + private: + // hide assignment and copy operator since the device is + // a memory manager for requestObject + cdevDevice& operator = (const cdevDevice &); + cdevDevice (const cdevDevice &); + + // friend class declaration + friend class cdevSystem; + friend class cdevRequestObject; +}; +#endif diff --git a/include/cdevDeviceDefinition.h b/include/cdevDeviceDefinition.h new file mode 100644 index 0000000..2f0116c --- /dev/null +++ b/include/cdevDeviceDefinition.h @@ -0,0 +1,134 @@ +#ifndef _CDEV_DEVICE_DEFINITION_H_ +#define _CDEV_DEVICE_DEFINITION_H_ + +#ifndef _CDEV_DIRECTORY_TABLE_H_ + #error "You must include cdevDirectoryTable.h to load cdevDeviceDefinition.h" +#endif + +// ***************************************************************************** +// * class cdevDeviceDefinition : +// * This class stores information that identifies a specific device name +// * and associates it with a class. +// * +// * This class maintains a variety of internal data items for the following +// * purposes... +// * +// * name - This is the name of the device as specified in the DDL file. +// * directory - This is the cdevDirectoryTable object where the device was +// * registered. +// * cdevClass - This is the definition object for the class that the device +// * belongs to. +// * next - This is the next device in the linked list of cdevDevice +// * Definition objects. This list is maintained as part of the +// * cdevClassDefinition object. +// ***************************************************************************** +class cdevDeviceDefinition +{ +private: + char * name; + char * substName; + class cdevDirectoryTable & directory; + class cdevClassDefinition & cdevClass; + cdevDeviceDefinition * next; + +public: + inline cdevDeviceDefinition ( cdevDirectoryTable & Directory, + char * Name, + char * SubstName, + cdevClassDefinition & CdevClass ); + inline ~cdevDeviceDefinition ( void ); + + // ********************************************************************* + // * Member access methods. + // ********************************************************************* + inline char * getName ( void ); + inline char * getSubstituteName ( void ); + inline cdevDirectoryTable & getDirectory ( void ); + inline cdevClassDefinition & getClass ( void ); + inline cdevDeviceDefinition * getNext ( void ); + inline void setNext ( cdevDeviceDefinition * Next ); +}; + + +// ***************************************************************************** +// * cdevDeviceDefinition::cdevDeviceDefinition : +// * This is the constructor for the cdevDeviceDefinition class. +// ***************************************************************************** +inline cdevDeviceDefinition::cdevDeviceDefinition + ( cdevDirectoryTable & Directory, + char * Name, + char * SubstName, + cdevClassDefinition & CdevClass ) + : directory(Directory), next(NULL), name(Name), + substName(SubstName), cdevClass(CdevClass) + { + } + +// ***************************************************************************** +// * cdevDeviceDefinition::~cdevDeviceDefinition : +// * This is the destructor for the cdevDeviceDefinition class. +// ***************************************************************************** +inline cdevDeviceDefinition::~cdevDeviceDefinition ( void ) + { + if(name) delete name; + if(substName) delete substName; + } + + +// ***************************************************************************** +// * cdevDeviceDefinition::getName : +// * This method allows the caller to retrieve the device name. +// ***************************************************************************** +inline char * cdevDeviceDefinition::getName ( void ) + { + return name; + } + +// ***************************************************************************** +// * cdevDeviceDefinition::getSubstituteName : +// * This method allows the caller to retrieve the device name. +// ***************************************************************************** +inline char * cdevDeviceDefinition::getSubstituteName ( void ) + { + return substName==NULL?name:substName; + } + +// ***************************************************************************** +// * cdevDeviceDefinition::getDirectory : +// * This method allows the caller to retrieve the directory object that +// * owns this device. +// ***************************************************************************** +inline cdevDirectoryTable & cdevDeviceDefinition::getDirectory ( void ) + { + return directory; + } + +// ***************************************************************************** +// * cdevDeviceDefinition::getClass : +// * This method allows the caller to retrieve the class object that +// * owns this device. +// ***************************************************************************** +inline cdevClassDefinition & cdevDeviceDefinition::getClass ( void ) + { + return cdevClass; + } + +// ***************************************************************************** +// * cdevDeviceDefinition::getNext : +// * This method allows the caller to retrieve the next device in the list. +// ***************************************************************************** +inline cdevDeviceDefinition * cdevDeviceDefinition::getNext ( void ) + { + return next; + } + +// ***************************************************************************** +// * cdevDeviceDefinition::setNext : +// * This method allows the caller to set the next device in the list. +// ***************************************************************************** +inline void cdevDeviceDefinition::setNext ( cdevDeviceDefinition * Next ) + { + next = Next; + } + +#endif diff --git a/include/cdevDirRequestObj.h b/include/cdevDirRequestObj.h new file mode 100644 index 0000000..653208b --- /dev/null +++ b/include/cdevDirRequestObj.h @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevRequestObject for cdevDirectory Class +// +// Author: Jie Chen +// +// Revision History: +// cdevDirRequestObj.h,v +// Revision 1.1 1998/02/13 14:01:45 chen +// enable request object for cdevDirectory +// +// +#ifndef _CDEV_DIR_REQUEST_OBJ_H +#define _CDEV_DIR_REQUEST_OBJ_H + +#include +#include +#include + +class CDEV_CLASS_SPEC cdevDirRequestObj: public cdevRequestObject +{ +public: + // constructor and destructor + cdevDirRequestObj (cdevDevice& device, char* msg, + cdevSystem& system = cdevSystem::defaultSystem ()); + + ~cdevDirRequestObj (void); + + int send (cdevData& out, cdevData& result); + int send (cdevData *out, cdevData& result); + int send (cdevData& out, cdevData* result); + int send (cdevData *out, cdevData* result); + + + int sendNoBlock (cdevData& out, cdevData& result); + int sendNoBlock (cdevData* out, cdevData& result); + int sendNoBlock (cdevData& out, cdevData* result); + int sendNoBlock (cdevData* out, cdevData* result); + + int sendCallback (cdevData& out, cdevCallback& callback); + int sendCallback (cdevData* out, cdevCallback& callback); + + const char *className (void) const {return "cdevDirRequestObj";} +}; +#endif + + diff --git a/include/cdevDirectory.h b/include/cdevDirectory.h new file mode 100644 index 0000000..8601365 --- /dev/null +++ b/include/cdevDirectory.h @@ -0,0 +1,88 @@ +#ifndef _CDEV_DIRECTORY_H +#define _CDEV_DIRECTORY_H + +#include +#include +#include +#include + +class cdevDirectoryTable; +class StringHash; + +class CDEV_CLASS_SPEC cdevDirectory : public cdevDevice +{ +public: + cdevDirectory(cdevSystem &system=cdevSystem::defaultSystem()); + ~cdevDirectory(void); + + int addNameSvc(cdevDevice *svc); + int removeNameSvc(cdevDevice *svc); + + int send(char *msg, cdevData &data, cdevData &result); + int send(char *msg, cdevData *data, cdevData &result); + int send(char *msg, cdevData &data, cdevData *result); + int send(char *msg, cdevData *data, cdevData *result); + + int sendNoBlock(char *msg, cdevData &out, cdevData &result); + int sendNoBlock(char *msg, cdevData *out, cdevData &result); + int sendNoBlock(char *msg, cdevData &out, cdevData *result); + int sendNoBlock(char *msg, cdevData *out, cdevData *result); + + int sendCallback(char *msg, cdevData &out, cdevCallback &callback); + int sendCallback(char *msg, cdevData *out, cdevCallback &callback); + + cdevRequestObject *getRequestObject (char *msg); + int getRequestObject (char *msg, cdevRequestObject* &reqobj); + + virtual const char *className(void) const { return "cdevDirectory"; } + +private: + typedef int (*QueryFunction) ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + + static int query ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int queryClass ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int queryClasses ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int queryCollection ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int queryVerbs ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int queryAttributes ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int queryMessages ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int service ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int resolveService ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int serviceData ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int resolveServiceData ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int validate ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int update ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int writeAscii ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int writeBinary ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + + class cdevDirectoryNode + { + public: + cdevDirectoryNode ( cdevDevice * svc = NULL ) : next(NULL), device(svc) {} + ~cdevDirectoryNode( void ) {} + cdevDirectoryNode * next; + cdevDevice * device; + }; + + cdevDirectoryNode * node; + class cdevDirectoryTable * table; + class StringHash * commandHash; +}; + +#endif diff --git a/include/cdevDirectoryTable.h b/include/cdevDirectoryTable.h new file mode 100644 index 0000000..58e9372 --- /dev/null +++ b/include/cdevDirectoryTable.h @@ -0,0 +1,722 @@ +#ifndef _CDEV_DIRECTORY_TABLE_H_ +#define _CDEV_DIRECTORY_TABLE_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __VMS +typedef unsigned long u_long; +typedef unsigned short u_short; +#endif + + +class cdevElementDefinition; +class cdevClassDefinition; +class cdevServiceDefinition; +class cdevAliasDefinition; +class cdevDeviceDefinition; +class cdevCollectionDefinition; + +int CDEV_CLASS_SPEC cdevReportError(int severity, char *name, void *, char *formatString, ...); + +// ***************************************************************************** +// * class cdevDirectoryTable : +// * This is the master class that is used to collect and maintain +// * information associated with the CDEV Device Definition Language file. +// * +// * This class maintains a number of tables and lists for the following +// * purposes... +// * +// * collectionClass - This is the single instance of the cdevClassDefinition +// * for the collection class. +// * +// * serviceHead - This is a list of all of the services that have been +// * serviceTail read from the DDL file in the order in which they +// * were loaded. +// * +// * classHead - This is a list of all of the classes that have been +// * classTail read from the DDL file in the order in which they +// * were loaded. +// * +// * aliasHead - This is a list of aliases that are defined within +// * aliasTail the DDL file. +// * +// * collectionHead - This is a list of collection devices that are +// * collectionTail defined within the DDL file. +// * +// * serviceHash - This is a hash table that allows for fast lookup of +// * each of the services that were loaded into the +// * service list. +// * +// * classHash - This is a hash table that allows fast lookup by name +// * of any of the classes that were loaded into the +// * class list. +// * +// * classInstanceHash - This is a hash table that contains only the names +// * and addresses of classes that have been used to +// * instanciate a device. +// * +// * deviceHash - This is a hash table that allows the caller to +// * quickly locate any device that has been defined in +// * the DDL file. +// * +// * collectionHash - This is a hash table that allows the caller to +// * quickly locate a collection device definition. +// ***************************************************************************** +class CDEV_CLASS_SPEC cdevDirectoryTable +{ +public: + static long BinaryMagic_1_4; + static long BinaryMagic_1_5; + static long BinaryMagic; + + typedef enum {VERB=0, ATTRIBUTE, MESSAGE} ElementType; + +private: + cdevClassDefinition * collectionClass; + + cdevServiceDefinition * serviceHead; + cdevServiceDefinition * serviceTail; + cdevClassDefinition * classHead; + cdevClassDefinition * classTail; + cdevAliasDefinition * aliasHead; + cdevAliasDefinition * aliasTail; + cdevCollectionDefinition * collectionHead; + cdevCollectionDefinition * collectionTail; + StringHash serviceHash; + StringHash classHash; + StringHash classInstanceHash; + StringHash deviceHash; + StringHash collectionHash; + +public: + inline cdevDirectoryTable ( void ); + inline ~cdevDirectoryTable ( void ); + + inline int addService ( cdevServiceDefinition *def ); + inline int addService ( char *name, + char **tags=NULL, + int nTags=0); + + inline int addClass ( cdevClassDefinition *def ); + inline int addClass ( char *name, + cdevClassDefinition *parent = NULL, + cdevElementDefinition *verbs = NULL, + cdevElementDefinition *attributes = NULL, + cdevElementDefinition *messages = NULL); + + inline int addClassInstance ( cdevClassDefinition * def ); + inline int addDevice ( cdevDeviceDefinition * def ); + inline int addAlias ( cdevAliasDefinition * def ); + inline int addAlias ( char * name, cdevDeviceDefinition & def ); + inline int addCollection ( cdevCollectionDefinition * def ); + inline int addCollection ( char * name, char ** devices, int nDevices ); + + inline void asciiDump ( FILE * fp = stdout ); + inline void asciiDumpRedirector ( FILE * fp = stdout ); + + inline cdevServiceDefinition * findService ( char * name ); + inline cdevClassDefinition * findClass ( char * name ); + + // ********************************************************************* + // * Member access methods. + // ********************************************************************* + inline cdevServiceDefinition * getServices ( void ); + inline cdevClassDefinition * getClasses ( void ); + inline cdevAliasDefinition * getAliases ( void ); + inline StringHash & getServiceHash ( void ); + inline StringHash & getClassHash ( void ); + inline StringHash & getInstanceHash ( void ); + inline StringHash & getDeviceHash ( void ); + inline StringHash & getCollectionHash (void ); + + // ********************************************************************* + // * External data load/dump methods. + // ********************************************************************* + int load ( char * inputFile ); + int asciiLoad ( char * inputFile ); + int asciiBufferLoad ( char * buffer ); + void binaryDump ( char * outputFile ); + int binaryLoad ( char * inputFile ); + int loadText ( char * includePath, char * filename, char * &buf, int &buflen, int &cursor); + void readServices ( char * buf ); + void readClasses ( char * buf ); + void readElements ( cdevClassDefinition &def, ElementType type, char *start, char *end ); + void readDevices ( char * buf ); + void readAliases ( char * buf ); + void readCollections ( char * buf ); + void compressComments ( char * filename, char * buf ); + void compressSpaces ( char * filename, char * buf ); +}; + +#include +#include +#include +#include +#include +#include +#include + +// ***************************************************************************** +// * cdevDirectoryTable::cdevDirectoryTable : +// * Constructor for the cdevDirectoryTable class. +// ***************************************************************************** +inline cdevDirectoryTable::cdevDirectoryTable ( void ) + : serviceHead(NULL), serviceTail(NULL), classHead(NULL), classTail(NULL), + aliasHead(NULL), aliasTail(NULL), collectionHead(NULL), + collectionTail(NULL), serviceHash(0), classHash(0), + deviceHash(0, 9973), classInstanceHash(0), collectionHash(0) + { + // ********************************************************************* + // * Note, by creating a collection class to hold all collection devices + // * I am preventing the developer from creating his own collection + // * class. + // ********************************************************************* + collectionClass = new cdevClassDefinition(*this, strdup("collection")); + addClass(collectionClass); + } + + +// ***************************************************************************** +// * cdevDirectoryTable::~cdevDirectoryTable : +// * This is the destructor for the cdevDirectoryTable class. +// ***************************************************************************** +inline cdevDirectoryTable::~cdevDirectoryTable ( void ) + { + while(serviceHead!=NULL) + { + cdevServiceDefinition *ptr = serviceHead; + serviceHead = ptr->getNext(); + serviceHash.remove(ptr->getName()); + delete ptr; + } + while(classHead!=NULL) + { + cdevClassDefinition *ptr = classHead; + classHead = ptr->getNext(); + classHash.remove(ptr->getName()); + classInstanceHash.remove(ptr->getName()); + delete ptr; + } + while(aliasHead!=NULL) + { + cdevAliasDefinition *ptr = aliasHead; + aliasHead = ptr->getNext(); + deviceHash.remove(ptr->getName()); + delete ptr; + } + while(collectionHead!=NULL) + { + cdevCollectionDefinition *ptr = collectionHead; + collectionHead = ptr->getNext(); + collectionHash.remove(ptr->getName()); + delete ptr; + } + } + + +// ***************************************************************************** +// * cdevDirectoryTable::addService : +// * Adds a new service to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addService ( cdevServiceDefinition * def ) + { + int result = CDEV_SUCCESS; + + if(def!=NULL && def->getName() && *def->getName()) + { + if(serviceHash.find(def->getName())!=NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Service \"%s\" is already defined", def->getName()); + result = CDEV_ERROR; + } + else + { + serviceHash.insert(def->getName(), def); + if(serviceTail==NULL) + { + serviceTail = def; + serviceHead = def; + } + else { + serviceTail->setNext(def); + serviceTail = def; + } + } + } + else result = CDEV_ERROR; + + return result; + } + + + +// ***************************************************************************** +// * cdevDirectoryTable::addService : +// * Adds a new service to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addService ( char * name, char ** tags, int nTags ) + { + int result = CDEV_SUCCESS; + + if(name!=NULL && *name) + { + if(serviceHash.find(name)!=NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Service \"%s\" is already defined", name); + result = CDEV_ERROR; + } + else + { + cdevServiceDefinition *def = new cdevServiceDefinition + (name, tags, nTags); + + serviceHash.insert(name, def); + if(serviceTail==NULL) + { + serviceTail = def; + serviceHead = def; + } + else { + serviceTail->setNext(def); + serviceTail = def; + } + } + } + else result = CDEV_ERROR; + + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::addClass : +// * Adds a new class to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addClass ( cdevClassDefinition * def ) + { + int result = CDEV_SUCCESS; + if(def!=NULL && def->getName() && *def->getName()) + { + if(classHash.find(def->getName())!=NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Class \"%s\" is already defined", def->getName()); + result = CDEV_ERROR; + } + else + { + classHash.insert(def->getName(), def); + if(classTail==NULL) + { + classTail = def; + classHead = def; + } + else { + classTail->setNext(def); + classTail = def; + } + } + } + else result = CDEV_ERROR; + + return result; + } + +// ***************************************************************************** +// * cdevDirectoryTable::addClass : +// * Adds a new class to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addClass + ( char *name, + cdevClassDefinition *parent, + cdevElementDefinition *verbs, + cdevElementDefinition *attributes, + cdevElementDefinition *messages) + { + int result = CDEV_SUCCESS; + + if(name!=NULL && *name) + { + if(classHash.find(name)!=NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Class \"%s\" is already defined", name); + result = CDEV_ERROR; + } + else + { + cdevClassDefinition *def = new cdevClassDefinition + (*this, name, parent, verbs, attributes, messages); + + classHash.insert(name, def); + if(classTail==NULL) + { + classTail = def; + classHead = def; + } + else { + classTail->setNext(def); + classTail = def; + } + } + } + else result = CDEV_ERROR; + + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::addClassInstance : +// * Adds a new class instance to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addClassInstance ( cdevClassDefinition * def ) + { + int result = CDEV_SUCCESS; + if(def!=NULL && def->getName() && *def->getName()) + { + if(classHash.find(def->getName())==NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Class \"%s\" has not been defined", def->getName()); + result = CDEV_ERROR; + } + else if(classInstanceHash.find(def->getName())==NULL) + { + classInstanceHash.insert(def->getName(), def); + } + } + else result = CDEV_ERROR; + + return result; + } + +// ***************************************************************************** +// * cdevDirectoryTable::addDevice : +// * Adds a new device to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addDevice ( cdevDeviceDefinition * def ) + { + int result = CDEV_SUCCESS; + if(def!=NULL && def->getName()!=NULL && *def->getName()) + { + if(deviceHash.find(def->getName())!=NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Device \"%s\" has already been defined", def->getName()); + result = CDEV_ERROR; + } + else deviceHash.insert(def->getName(), def); + } + else result = CDEV_ERROR; + + return result; + } + +// ***************************************************************************** +// * cdevDirectoryTable::addAlias : +// * Adds a new alias to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addAlias ( cdevAliasDefinition * def ) + { + int result = CDEV_SUCCESS; + if(def!=NULL && def->getName() && *def->getName()) + { + if(deviceHash.find(def->getName())!=NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Alias \"%s\" has already been defined", def->getName()); + result = CDEV_ERROR; + } + else { + if(aliasTail==NULL) + { + aliasHead = def; + aliasTail = def; + } + else { + aliasTail->setNext(def); + aliasTail = def; + } + deviceHash.insert(def->getName(), &def->getDevice()); + } + } + else result = CDEV_ERROR; + + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::addAlias : +// * Adds a new alias to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addAlias + ( char * name, cdevDeviceDefinition & device ) + { + cdevAliasDefinition *def = new cdevAliasDefinition(name, device); + int result = addAlias(def); + if(result!=CDEV_SUCCESS) delete def; + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::addCollection : +// * Adds a new collection to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addCollection ( cdevCollectionDefinition * def ) + { + int result = CDEV_SUCCESS; + if(def!=NULL && def->getName()!=NULL && *def->getName()) + { + if(deviceHash.find(def->getName())!=NULL || + collectionHash.find(def->getName())!=NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Collection device \"%s\" has already been defined", def->getName()); + result = CDEV_ERROR; + } + else { + if(collectionTail==NULL) + { + collectionTail = def; + collectionHead = def; + } + else { + collectionTail->setNext(def); + collectionTail = def; + } + collectionHash.insert(def->getName(), def); + collectionClass->addDevice (strdup(def->getName())); + } + } + else result = CDEV_ERROR; + + return result; + } + +// ***************************************************************************** +// * cdevDirectoryTable::addCollection : +// * Adds a new collection to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addCollection ( char * name, char ** devices, int nDevices ) + { + int result; + + cdevCollectionDefinition * def = + new cdevCollectionDefinition(name, devices, nDevices); + + if((result = addCollection(def))!=CDEV_SUCCESS) delete def; + + return result; + } +// ***************************************************************************** +// * cdevDirectoryTable::findService : +// * Allows the caller to locate a service by name. +// ***************************************************************************** +inline cdevServiceDefinition * cdevDirectoryTable::findService ( char * name ) + { + return (cdevServiceDefinition *)serviceHash.find(name); + } + + +// ***************************************************************************** +// * cdevDirectoryTable::findClass : +// * Allows the caller to locate a class by name. +// ***************************************************************************** +inline cdevClassDefinition * cdevDirectoryTable::findClass ( char * name ) + { + return (cdevClassDefinition *)classHash.find(name); + } + +// ***************************************************************************** +// * cdevDirectoryTable::asciiDump : +// * This method will write the contents of the cdevDirectory object to +// * the user provided file pointer. +// ***************************************************************************** +inline void cdevDirectoryTable::asciiDump ( FILE * fp ) + { + cdevServiceDefinition *sPtr = serviceHead; + if(sPtr) + { + fprintf(fp, "\n// ******************************************\n"); + fprintf(fp, "// * Table of service definitions... *\n"); + fprintf(fp, "// ******************************************\n"); + } + while(sPtr!=NULL) + { + sPtr->asciiDump(fp); + sPtr = sPtr->getNext(); + } + + cdevClassDefinition *cPtr = classHead; + if(cPtr) + { + fprintf(fp, "\n// ******************************************\n"); + fprintf(fp, "// * Table of class definitions... *\n"); + fprintf(fp, "// ******************************************\n"); + } + while(cPtr!=NULL) + { + if(cPtr!=collectionClass) cPtr->asciiDump(fp); + cPtr = cPtr->getNext(); + } + + cPtr = classHead; + if(cPtr) + { + fprintf(fp, "\n// ******************************************\n"); + fprintf(fp, "// * Table of class instance definitions... *\n"); + fprintf(fp, "// ******************************************\n"); + } + while(cPtr!=NULL) + { + if(cPtr!=collectionClass) cPtr->asciiDumpInstances(fp); + cPtr = cPtr->getNext(); + } + + cdevAliasDefinition *aPtr = aliasHead; + if(aPtr) + { + fprintf(fp, "\n\n// ******************************************\n"); + fprintf(fp, "// * Table of alias definitions... *\n"); + fprintf(fp, "// ******************************************\n"); + } + while(aPtr!=NULL) + { + aPtr->asciiDump(fp); + aPtr = aPtr->getNext(); + } + + cdevCollectionDefinition * clPtr = collectionHead; + if(clPtr) + { + fprintf(fp, "\n\n// ******************************************\n"); + fprintf(fp, "// * Table of collection definitions... *\n"); + fprintf(fp, "// ******************************************\n"); + } + while(clPtr!=NULL) + { + clPtr->asciiDump(fp); + clPtr = clPtr->getNext(); + } + } + +// ***************************************************************************** +// * cdevDirectoryTable::asciiDumpRedirector : +// * This is a diagnostic method that allows the caller to dump the contents +// * of the redirection table for each class that has been instanciated. +// ***************************************************************************** +inline void cdevDirectoryTable::asciiDumpRedirector ( FILE * fp ) + { + int cnt = 0; + + cdevClassDefinition *def; + for(def = classHead; def!=NULL; def = def->getNext()) + { + if(classInstanceHash.find(def->getName())!=NULL) + { + def->asciiDumpRedirector(fp); + cnt++; + } + } + if(!cnt) cdevReportError(CDEV_SEVERITY_WARN, "CDEV Directory", NULL, + "No devices have been instanciated"); + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getServices : +// * Returns the list of services that are defined within the directory. +// ***************************************************************************** +inline cdevServiceDefinition * cdevDirectoryTable::getServices ( void ) + { + return serviceHead; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getClasses : +// * Returns the list of classes that are defined within the directory. +// ***************************************************************************** +inline cdevClassDefinition * cdevDirectoryTable::getClasses ( void ) + { + return classHead; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getAliases : +// * Returns the list of aliases that are defined within the directory. +// ***************************************************************************** +inline cdevAliasDefinition * cdevDirectoryTable::getAliases ( void ) + { + return aliasHead; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getServiceHash : +// * Return a hash table of services that are defined within the directory. +// ***************************************************************************** +inline StringHash & cdevDirectoryTable::getServiceHash ( void ) + { + return serviceHash; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getClassHash : +// * Return a hash table of classes that are defined within the directory. +// ***************************************************************************** +inline StringHash & cdevDirectoryTable::getClassHash ( void ) + { + return classHash; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getInstanceHash : +// * Return a hash table of classes that have been instanciated within the +// * directory. +// ***************************************************************************** +inline StringHash & cdevDirectoryTable::getInstanceHash ( void ) + { + return classInstanceHash; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getDeviceHash : +// * Return a hash table of device names that have been instanciated in all +// * classes within the directory. This hash-table includes aliases that +// * have been instanciated. +// ***************************************************************************** +inline StringHash & cdevDirectoryTable::getDeviceHash ( void ) + { + return deviceHash; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getCollectionHash : +// * Return a hash table of collection names that have been instanciated in +// * the DDL file. Each collection definition contains the list of devices +// * that it contains. +// ***************************************************************************** +inline StringHash & cdevDirectoryTable::getCollectionHash ( void ) + { + return collectionHash; + } + + +#endif /* _CDEV_DIRECTORY_TABLE_H_ */ diff --git a/include/cdevDirectoryTool.h b/include/cdevDirectoryTool.h new file mode 100644 index 0000000..b51c78b --- /dev/null +++ b/include/cdevDirectoryTool.h @@ -0,0 +1,28 @@ +#include +#include + +class CDEV_CLASS_SPEC cdevDirectoryTool : public cdevDirectoryTable +{ +public: + cdevDirectoryTool ( void ); + ~cdevDirectoryTool ( void ); + + static int query ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int queryClass ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int queryClasses ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int queryCollection ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int queryVerbs ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int queryAttributes ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int queryMessages ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int service ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int serviceData ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int validate ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int update ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int writeAscii ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int writeBinary ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + +protected: + static int queryElements ( cdevDirectoryTable &table, cdevDirectoryTable::ElementType type, + cdevData *in, cdevData *out); + +}; diff --git a/include/cdevElementDefinition.h b/include/cdevElementDefinition.h new file mode 100644 index 0000000..65d6560 --- /dev/null +++ b/include/cdevElementDefinition.h @@ -0,0 +1,260 @@ +#ifndef _CDEV_ELEMENT_DEFINITION_H_ +#define _CDEV_ELEMENT_DEFINITION_H_ + +#ifndef _CDEV_DIRECTORY_TABLE_H_ + #error "You must include cdevDirectoryTable.h to load cdevElementDefinition.h" +#endif + +#include +#include + +// ***************************************************************************** +// * class cdevElementDefinition : +// * This class is used to store the information that describes the contents +// * of a single element of a CDEV DDL class definition (verb, attribute, +// * or message. +// * +// * This class maintains a variety of internal data items for the following +// * purposes... +// * +// * name - This is the name of the verb, attribute, or message that +// * is represented by this element definition. +// * service - This is the service that this element direct the request +// * to. +// * serviceData - These are the values that will be palcded in the tags +// * that were specified in the service definition. +// * nItems - This is the number of tagged data items that were +// * specified in the serviceData. +// * next - This is the next element item in the list. Lists of +// * elements are maintained in the cdevClassDefinition objects +// ***************************************************************************** +class cdevElementDefinition +{ +private: + cdevElementDefinition * next; + char * name; + cdevServiceDefinition * service; + char ** serviceData; + int nItems; + +public: + inline cdevElementDefinition ( cdevElementDefinition *def ); + inline cdevElementDefinition ( char * Name = NULL, + cdevServiceDefinition * Service = NULL, + char ** ServiceData = NULL, + int NItems = 0); + inline virtual ~cdevElementDefinition ( void ); + inline void asciiDump ( FILE * fp = stdout); + inline void asciiDumpList ( FILE * fp = stdout, char * keyword = "UNKNOWN"); + + // ********************************************************************* + // * Member access methods. + // ********************************************************************* + inline char * getName ( void ); + inline cdevServiceDefinition * getService ( void ); + inline char ** getServiceData ( void ); + inline int getDataCnt ( void ); + inline cdevElementDefinition * getNext ( void ); + inline void setNext ( cdevElementDefinition * Next ); +}; + + + +// ***************************************************************************** +// * cdevElementDefinition::cdevElementDefinition : +// * This is the constructor for the cdevElementDefintion class. This +// * constructor copies the contents from a pre-existing +// * cdevElementDefinition object, and assumes that the data should be +// * deleted by the originating class. +// ***************************************************************************** +inline cdevElementDefinition::cdevElementDefinition ( cdevElementDefinition *def ) + : next (NULL), + name (def->name), + service (def->service), + serviceData (def->serviceData), + nItems (def->nItems) + { + } + +// ***************************************************************************** +// * cdevElementDefinition::cdevElementDefinition : +// * This is the constructor for the cdevElementDefinition class and it +// * uses literal values that are provoded by the caller. It assumes that it +// * it responsible for deleteing these data items when the instance of the +// * class is deleted. +// ***************************************************************************** +inline cdevElementDefinition::cdevElementDefinition + ( char * Name, + cdevServiceDefinition * Service, + char ** ServiceData, + int NItems) + : next (NULL), + name (Name), + service (Service), + serviceData (ServiceData), + nItems (NItems) + { + } + +// ***************************************************************************** +// * cdevElementDefinition::~cdevElementDefinition : +// * This is the destructor for the cdevElementDefinition class. +// ***************************************************************************** +inline cdevElementDefinition::~cdevElementDefinition ( void ) + { + if(name) delete name; + while((--nItems)>=0) delete serviceData[nItems]; + if(serviceData) delete serviceData; + } + +// ***************************************************************************** +// * cdevElementDefinition::asciiDump : +// * This method will dump the contents of the cdevElementDefinition class +// * class to the user specified file pointer. +// ***************************************************************************** +inline void cdevElementDefinition::asciiDump ( FILE * fp ) + { + if(name) + { + fprintf(fp, "\t\t%s", name); + + if(service) + { + fprintf(fp, " %s", service->getName()); + + for(int i=0; inext) + { + int n = def->name==NULL?0:strlen(def->name); + int s = def->service==NULL?0:strlen(def->service->getName()); + if(n>nameLen) nameLen = n; + if(s>serviceLen) serviceLen = s; + } + if(serviceLen) + { + fprintf(fp, "\t%s\n\t\t{\n", keyword); + for(def = this; def!=NULL; def = def->next) + { + if(nameLen>0 && def->service) + fprintf(fp, "\t\t%-*s", nameLen, def->name); + else fprintf(fp, "\t\t%s", def->name); + + if(def->service) + { + if(serviceLen>0 && def->nItems) + fprintf(fp, " %-*s", serviceLen, def->service->getName()); + else fprintf(fp, " %s", def->service->getName()); + + for(int i=0; inItems; i++) + { + if(i==0) fprintf(fp, " {"); + fprintf(fp, "%s", def->serviceData[i]); + if(inItems-1) fprintf(fp, ", "); + else fprintf(fp, "}"); + } + } + fprintf(fp, ";\n"); + } + fprintf(fp, "\t\t}\n"); + } + else { + int cnt = 0; + char prefix[25]; + sprintf(prefix, "%s {", keyword); + fprintf(fp, "\t%s", prefix); + for(def = this; def!=NULL; def = def->next, cnt++) + { + if(def->next) + { + fprintf(fp, " %s,", def->name); + if(cnt==3) + { + fprintf(fp, "\n\t%*c", strlen("prefix")+1, 32); + cnt=-1; + } + } + else fprintf(fp, " %s ", def->name); + } + fprintf(fp, "}\n"); + } + } + + +// ***************************************************************************** +// * cdevElementDefinition::getName : +// * This method allows the caller to retrieve the name of the element. +// ***************************************************************************** +inline char * cdevElementDefinition::getName ( void ) + { + return name; + } + +// ***************************************************************************** +// * cdevElementDefinition::getService : +// * This method allows the caller to retrieve the service definition +// ***************************************************************************** +inline cdevServiceDefinition * cdevElementDefinition::getService ( void ) + { + return service; + } + +// ***************************************************************************** +// * cdevElementDefinition::getServiceData : +// * This method allows the caller to retrieve the service data. +// ***************************************************************************** +inline char ** cdevElementDefinition::getServiceData ( void ) + { + return serviceData; + } + +// ***************************************************************************** +// * cdevElementDefinition::getDataCnt : +// * This method allows the caller to retrieve the number of strings that +// * are stored in the serviceData. +// ***************************************************************************** +inline int cdevElementDefinition::getDataCnt ( void ) + { + return nItems; + } + +// ***************************************************************************** +// * cdevElementDefinition::getNext : +// * This method allows the caller to retrieve the next element in the list. +// ***************************************************************************** +inline cdevElementDefinition * cdevElementDefinition::getNext ( void ) + { + return next; + } + +// ***************************************************************************** +// * cdevElementDefinition::setNext : +// * This method allows the caller to set the next element in the list. +// ***************************************************************************** +inline void cdevElementDefinition::setNext ( cdevElementDefinition * Next ) + { + next = Next; + } + +#endif /* _CDEV_ELEMENT_DEFINITION_H_ */ diff --git a/include/cdevErrCode.h b/include/cdevErrCode.h new file mode 100644 index 0000000..cd617ce --- /dev/null +++ b/include/cdevErrCode.h @@ -0,0 +1,99 @@ +/* +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// CDEV error codes +// +// Author: Jie Chen +// +// Revision History: +// cdevErrCode.h,v +// Revision 1.8 1998/01/14 17:49:48 chen +// add msg error +// +// Revision 1.7 1998/01/14 13:47:10 chen +// add more status code +// +// Revision 1.6 1996/12/16 20:48:51 akers +// Support for additional cdevCallback features +// +// Revision 1.5 1996/11/21 17:03:29 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.4 1995/10/17 17:33:57 akers +// Updated error, status, access and severity codes +// +// Revision 1.3 1995/10/03 20:07:13 chen +// add connection event type +// +// Revision 1.2 1995/07/05 18:44:05 chen +// change to C code callable style +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +*/ +#ifndef _CDEV_ERROR_CODE_H +#define _CDEV_ERROR_CODE_H + +/* Error and status values */ +#define CDEV_WARNING -2 /* Failure of function is non-consequential */ +#define CDEV_ERROR -1 /* Errors that are not in any categories */ +#define CDEV_SUCCESS 0 /* cdev success */ +#define CDEV_INVALIDOBJ 1 /* invalid cdev objects */ +#define CDEV_INVALIDARG 2 /* invalid argument passed to cdev calls */ +#define CDEV_INVALIDSVC 3 /* wrong service during dynamic loading */ +#define CDEV_INVALIDOP 4 /* operation is unsupported (collection) */ + +#define CDEV_NOTCONNECTED 5 /* not connected to low network service */ +#define CDEV_IOFAILED 6 /* low level network service IO failed */ +#define CDEV_CONFLICT 7 /* conflicts of data types or tags */ +#define CDEV_NOTFOUND 8 /* cdev cannot find user request (cdevData) */ + +#define CDEV_TIMEOUT 9 /* time out */ +#define CDEV_CONVERT 10 /* cdevData conversion error */ +#define CDEV_OUTOFRANGE 11 /* value out of range for device attribute */ +#define CDEV_NOACCESS 12 /* insufficient access to perform request */ +#define CDEV_ACCESSCHANGED 13 /* change in access permission of device */ + +#define CDEV_DISCONNECTED 60 /* channel has been disconnected */ +#define CDEV_RECONNECTED 61 /* channel has been reconnected */ + +#define CDEV_DELETE_CALLBACK 70 /* the callback object will be deleted */ + +/* status related to callback status and more */ +#define CDEV_NOTCONSERVER 80 /* can not connect to server/ not connected */ +#define CDEV_NOTFOUNDSERVER 81 /* can not find server */ +#define CDEV_CONN_TIMEOUT 82 /* connection timeout */ +#define CDEV_BADIO 86 /* TCP io is bad file descriptor */ +#define CDEV_OVERFLOW 87 /* overflow buffer */ +#define CDEV_INCOMPLETE 88 /* data flow will coming (unfinished) */ +#define CDEV_CBK_FINISHED 89 /* callback finished (monitor off) */ +#define CDEV_PAUSED 90 /* callback is paused */ +#define CDEV_MSG_ERR 91 /* query message syntax error */ + +/* Request object state values */ +#define CDEV_STATE_CONNECTED 0 /* request object is connected to device */ +#define CDEV_STATE_NOTCONNECTED 1 /* request object is not connected */ +#define CDEV_STATE_INVALID 2 /* request object is invalid */ + +/* Request object access values */ +#define CDEV_ACCESS_NONE 0 /* no access to specified attribute */ +#define CDEV_ACCESS_READONLY 1 /* read-only access to attribute */ +#define CDEV_ACCESS_WRITE 2 /* read-write access to attribute */ + +/* cdevError class severity codes */ +#define CDEV_SEVERITY_INFO 0 /* informative message */ +#define CDEV_SEVERITY_WARN 1 /* warning message */ +#define CDEV_SEVERITY_ERROR 2 /* error message */ +#define CDEV_SEVERITY_SEVERE 3 /* severe or fatal error message */ + +#endif diff --git a/include/cdevErrReqObject.h b/include/cdevErrReqObject.h new file mode 100644 index 0000000..62f9fb2 --- /dev/null +++ b/include/cdevErrReqObject.h @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevRequestObject Error Handler Object (User Cannot Access this) +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevErrReqObject.h,v +// Revision 1.2 1998/03/09 18:51:37 chen +// redefine getState/getAccess for errReqObject +// +// Revision 1.1.1.1 1995/06/16 17:14:06 epics +// initial import of cdev +// +// +#ifndef _CDEV_ERR_REQOBJ_H +#define _CDEV_ERR_REQOBJ_H + +#include + +class cdevErrReqObject: public cdevRequestObject +{ + public: + // destructor + ~cdevErrReqObject (void); + + int send (cdevData& out, cdevData& result); + int send (cdevData* out, cdevData& result); + int send (cdevData& out, cdevData* result); + int send (cdevData* out, cdevData* result); + + int sendNoBlock (cdevData& out, cdevData& result); + int sendNoBlock (cdevData* out, cdevData& result); + int sendNoBlock (cdevData& out, cdevData* result); + int sendNoBlock (cdevData* out, cdevData* result); + + int sendCallback (cdevData& out, cdevCallback& callback); + int sendCallback (cdevData* out, cdevCallback& callback); + + int getState (void); + int getAccess (void); + + const char *className (void) const {return "cdevErrReqObject";} + + private: + // constructor + cdevErrReqObject (cdevSystem& system = cdevSystem::defaultSystem()); + friend class cdevSystem; +}; +#endif diff --git a/include/cdevErrSvc.h b/include/cdevErrSvc.h new file mode 100644 index 0000000..828d272 --- /dev/null +++ b/include/cdevErrSvc.h @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevService Error Handler Class +// +// Author: Jie Chen +// +// Revision History: +// cdevErrSvc.h,v +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#ifndef _CDEV_ERR_SVC_H +#define _CDEV_ERR_SVC_H + +#include "cdevService.h" + +class cdevErrSvc: public cdevService +{ + public: + cdevErrSvc (cdevSystem& system = cdevSystem::defaultSystem()); + // PURPOSE: constructor + // REQUIRE: nothing + // PROMISE: a cdevErrSvc + + ~cdevErrSvc (void); + // PURPOSE: Destructor + // REQUIRE: nothing + // PROMISE: free all memory + + int getFd (int * &fd, int &numFd); + // PURPOSE: get service file descriptors + // REQUIRE: callers provide no memory, caller don't free memory + // PROMISE: numFd gives number of file descriptors, numFd >= 0 + + int flush (void); + // PURPOSE: flush network request + // REQUIRE: nothing + // PROMISE: return 0 + + int poll (void); + // PURPOSE: Service Polling Method + // REQURIE: nothing + // PROMISE: return 0 + + int pend (int fd = -1); + // PURPOSE: Service Pending Method + // REQUIRE: nothing + // PROMISE: return 0 + + int pend (double seconds, int fd = -1); + // PURPOSE: Service Pending Method For Upto 'seconds' + // REQUIRE: nothing + // PROMISE: return 0 + + int getRequestObject (char *deviceName, char *msg, + cdevRequestObject * &reqObj); + // PURPOSE: get requestobject + // REQUIRE: nothing + // PROMISE: return 0, reqobj = 0; + + int getNameServer (cdevDevice * &ns); + // PURPOSE: get name server + // REQUIRE: nothing + // PROMISE: return 0, ns = 0 + + const char *className (void) const {return "cdevErrSvc";} +}; +#endif diff --git a/include/cdevError.h b/include/cdevError.h new file mode 100644 index 0000000..b22ecd3 --- /dev/null +++ b/include/cdevError.h @@ -0,0 +1,135 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevError class (abstract base class) +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevError.h,v +// Revision 1.5 1997/08/27 18:23:31 chen +// Change error reporting to site specific scheme +// +// Revision 1.4 1995/12/14 19:11:14 chen +// add support to C interface +// +// Revision 1.3 1995/10/17 17:44:13 akers +// Added setThreshold functionality and made data items protected +// +// Revision 1.2 1995/10/17 15:29:45 chen +// change reportError interface +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#ifndef _CDEV_ERROR_H +#define _CDEV_ERROR_H + +#include +#include + +#define _CDEV_MAX_ERR_HANDLERS 5 +#define CDEV_SEVERITY_VOID_DATA 0xcde5da2a + +class cdevRequestObject; + +typedef void (*cdevErrorHandler)(int severity, + char *text, + cdevRequestObject* obj); + +class CDEV_CLASS_SPEC cdevError +{ + public: + // destructor + virtual ~cdevError (void); + + virtual int autoErrorOn (void); + // PURPOSE: turn on flag which enables auto error on + // REQUIRE: derived class can implement diffrently + // PROMISE: return 0 + + virtual int autoErrorOff (void); + // PURPOSE: turn on flag which disables auto error on + // REQUIRE: derived class can implement diffrently + // PROMISE: return 0 + + virtual int vreportError (int severity, + char * name, + cdevRequestObject * obj, + char * formatString, + va_list argp); + + // PURPOSE: report error to somewhere + // REQUIRE: formatString can have anything that works in printf + // PROMISE: same as printf + + virtual int reportError (int severity, + char *name, + cdevRequestObject* obj, + char *formatString,...); + // PURPOSE: report error to somewhere + // REQUIRE: formatString can have anything that works in printf + // PROMISE: same as printf + + virtual void reportError (int severity, + char *message, + cdevRequestObject* obj); + // PURPOSE: report error to somewhere with a whole string + // REQUIRE: user whole string + // PROMISE: + + + virtual void setErrorHandler (cdevErrorHandler handler = 0); + // PURPOSE: allow caller to set up his/her own error Handler + // REQUIRE: handle > 0 stands for a real function pointer + // PROMISE: next time error will be handled by new error handler + + virtual void setThreshold ( int errorThreshold ); + // PURPOSE: allow the caller to specify the minimum severity to report + // REQUIRE: errorThreshold >=0 + // PROMISE: errors with severity < errorThreshold wil not be reported + + virtual int attachErrorHandler (cdevErrorHandler handler); + // PURPOSE: allow caller to attach error handler to trap error messages + // REQUIRE: handler > 0 + // PROMISE: return CDEV_SUCCESS if this handler is attached to trap messgaes + + virtual int detachErrorHandler (cdevErrorHandler handler); + // PURPOSE: allow caller to dettach error handler + // REQUIRE: handler > 0 + // PROMISE: return CDEV_SUCCESS if this handler is removed. + + virtual void reportError (void *data, + cdevRequestObject* obj); + // PURPOSE: report error to somewhere with user defined data object. + // This routine is intended for site developer use only to + // support site wide error logging system. + // REQUIRE: user whole string + // PROMISE: + + virtual const char *className(void) const {return "cdevError";} + + protected: + // constructers, avoiding direct instantation + cdevError (void); + cdevError (cdevErrorHandler handler); + + // data areas + cdevErrorHandler errorHandler_; + static cdevErrorHandler defaultErrorHandler_; + int autoErrorOn_; + int threshold_; + + // list of error handlers + int numhandlers_; + cdevErrorHandler handlers_[_CDEV_MAX_ERR_HANDLERS]; +}; +#endif diff --git a/include/cdevErrorCollection.h b/include/cdevErrorCollection.h new file mode 100644 index 0000000..0049107 --- /dev/null +++ b/include/cdevErrorCollection.h @@ -0,0 +1,75 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * Description: + * cdevErrorCollection class implementation + * + * Author: Walt Akers, Chip Watson & Jie Chen + * + * Revision History: + * cdevErrorCollection.h,v + * Revision 1.1 1996/11/12 20:32:30 akers + * New collection device source code + * + * ----------------------------------------------------------------------------- + */ + +#ifndef _CDEV_ERRORCOLLECTION_H +#define _CDEV_ERRORCOLLECTION_H + +#include + +class cdevErrReqObject; + +class CDEV_CLASS_SPEC cdevErrorCollection: public cdevCollection +{ + public: + //======================================================================== + // Public Interface for cdevRequestObject + //======================================================================== + virtual cdevRequestObject *getRequestObject (char * msg ); + virtual int getRequestObject (char *msg, cdevRequestObject* &reqobj); + // PURPOSE: get a requestObject + // REQUIRE: name != 0, callers provide pointer only. + // PROMISE: always return CDEV_INVALIDOBJ + + //======================================================================== + // Public Interface for RTTI + //======================================================================== + virtual const char *className (void) const {return "cdevErrorCollection";} + + //======================================================================== + // Public Interface for list manipulation + //======================================================================== + int add(char* name, ...); + int add(char** list, int len); + int addRegexp(char* regexp); + int remove(char* name, ...); + int remove(char** list, int len); + int removeRegexp(char* regexp); + // PURPOSE: add(remove) a (list of/regexp of) names to the collection + // REQUIRE: nothing + // PROMISE: always return CDEV_INVALIDOBJ + + protected: + //constructors and destructor + //constructors will initialize list from directory service + cdevErrorCollection (char *name); + ~cdevErrorCollection (void); + + private: + // hide assignment and copy operator since the collection is + // a memory manager for collectionRequests and lists of devices + cdevErrorCollection& operator = (const cdevCollection &); + cdevErrorCollection (const cdevCollection &); + + // friend class declaration + friend class cdevCollection; +}; +#endif diff --git a/include/cdevExecGroup.h b/include/cdevExecGroup.h new file mode 100644 index 0000000..8f748e4 --- /dev/null +++ b/include/cdevExecGroup.h @@ -0,0 +1,138 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevExecGroup: handle buffering mechanism for multiple +// executions +// +// For service layer only +// +// Author: Jie Chen +// +// Revision History: +// cdevExecGroup.h,v +// Revision 1.1 1997/03/03 17:36:00 chen +// add buffering to channel access connection +// +// +// +#ifndef _CDEV_EXEC_GROUP_H +#define _CDEV_EXEC_GROUP_H + +#include + +class cdevExecObj; + +class CDEV_CLASS_SPEC cdevExecGroup: public cdevGroup +{ +public: + // constructors and destructor + cdevExecGroup (cdevService* service, + unsigned int blockSize = DEFAULT_BLOCK_SIZE, + cdevSystem& system = cdevSystem::defaultSystem()); + ~cdevExecGroup (void); + + int flush (void); + // PURPOSE: flush all network requests inside this group + // REQUIRE: nothing + // PROMISE: all network requests of this group will be sent out + // return CDEV_SUCCESS + + virtual const char *className (void) const {return "cdevExecGroup";} + +protected: + + int start (void); + // PURPOSE: start this group. (see next) + // REQUIRE: nothing + // PROMISE: group stared, return CDEV_SUCCESS + + int end (void); + // PURPOSE: end this group, all async IO between + // start and end will be in the group + // REQUIRE: nothing + // PROMISE: group ended, return CDEV_SUCCESS + + int poll (void); + // PURPOSE: polling all outstanding IO events of this group + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS + + int pend (int fd = -1); + // PURPOSE: do network pending for IO events forever until all + // network requests of this group have come back + // REQUIRE: nothing + // PROMISE: all come back or block forever (return CDEV_SUCCESS) + + int pend (double seconds, int fd = -1); + // PURPOSE: do network pending for IO events for upto 'seconds' long or + // all network requests of this group have come back + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS: finished, return CDEV_TIMEOUT: timeout + + int allFinished (void); + // PURPOSE: check all transaction finished of this group + // REQUIRE: after pend call + // PROMISE: return 1: all finished, 0: not yet + + int status (int status[], int &numTransactions); + // PURPOSE: check status of all transactions + // REQURIE: transaction status will be in the integer array returned + // by this call. Element of the array = 0 finished. + // Callers provide integer array buffer with buffer size + // PROMISE: return CDEV_SUCCESS on success and numTransaction will be + // real number of trasanctions. return CDEV_INVALIDARG + // when the integer buffer is not big enough. + + void execDeferred (void); + void execImmediate (void); + // PURPOSE: change behaviour of execution of command inside the group + // execDeferred will buffer all commands until pend or poll or + // flush is called + // execImmediate will flush commands to underlying services + // immediately + // REQUIRE: none + // PROMISE: execution mode changed + + int executionMode (void) const; + // PURPOSE: return execution mode + // REQUIRE: none + // PROMISE: CDEV_EXEC_DEFERRED or CDEV_EXEC_IMMEDIATE + + int readyToExec (void) const; + // PURPOSE: for deferred mode group only. Return execution stage. + // REQUIRE: none + // PROMISE: 0: the deferred group is still in the buffered stage + // 1: the deferred group is ready to flush all buffered + // commands + + // get underlying service + void getServices (void); + + // send out all buffered commands + int execAllCommands (void); + + // find out which service is ready + cdevService *pendingService (int handle); + // handle events inherited from cdevSync + int handleEvents (cdevTimeValue *tv); + // notify one partucular service + void notifyService (int fd); + +private: + // data member + // deny access of copy and assignment since the group is a manager + cdevExecGroup (const cdevExecGroup& ); + cdevExecGroup& operator = (const cdevExecGroup&); + + // friend class + friend class cdevExecObj; +}; +#endif + diff --git a/include/cdevExecObj.h b/include/cdevExecObj.h new file mode 100644 index 0000000..c158979 --- /dev/null +++ b/include/cdevExecObj.h @@ -0,0 +1,100 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdev deferred execution object (for service developer only) +// +// deferred execution object is registered into one and only one +// opened group which is the outmost deferred one +// +// Author: Jie Chen +// +// Revision History: +// cdevExecObj.h,v +// Revision 1.2 1997/03/03 17:36:03 chen +// add buffering to channel access connection +// +// Revision 1.1 1995/12/08 15:34:50 chen +// execution object +// +// +#ifndef _CDEV_EXEC_OBJ_H +#define _CDEV_EXEC_OBJ_H + +#include +#include +#include +#include +#include + +class cdevGroup; +class cdevRequestObject; + +class CDEV_CLASS_SPEC cdevExecObj +{ +public: + // constructor and destructor + cdevExecObj (void); + cdevExecObj (cdevSystem* sys, + cdevRequestObject* reqobj, + cdevData* out, + cdevData* result, + cdevCallback* callback, + cdevGroup* execg = 0, + void* arg = 0); + // Important note: + // No objects pointed by the pointers will be deleted from this object + ~cdevExecObj (void); + + int status (void) const; + // PURPOSE: return status of transaction object + // REQUIRE: nothing + // PROMISE: -1: not registered into any group, 1: registered into groups + + int removeFromGrps (void); + // PURPOSE: remove this transaction object from all groups + // REQUIRE: nothing + // PROMISE: status = -1 + + // data area for requestObject to access + cdevSystem *system_; + cdevRequestObject *reqObj_; + cdevData *outData_; + cdevData *resultData_; + cdevCallback *userCallback_; + int status_; + cdevGroup *deferredGroup_; + // pointer entries to the entry inside deferred group + cdevExecObj **entryPtr_; + // any user provided argument + void *arg_; + + virtual const char *className (void) const {return "cdevExecObj";} + +private: + // deny copy and assignment operation + // It makes no sense for two identical transaction objects + cdevExecObj (const cdevExecObj& rsc); + cdevExecObj& operator = (const cdevExecObj& rsc); + + // friend class + friend class cdevGroup; +}; +#endif + + + + + + + + + + + diff --git a/include/cdevFdSet.h b/include/cdevFdSet.h new file mode 100644 index 0000000..7713ff0 --- /dev/null +++ b/include/cdevFdSet.h @@ -0,0 +1,181 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// File Descriptor Mask Class (Based On ACE Handler_Set) +// +// Author: Jie Chen +// +// Revision History: +// cdevFdSet.h,v +// Revision 1.6 1997/03/26 18:34:58 akers +// Ongoing development +// +// Revision 1.5 1996/10/01 13:58:23 akers +// Changes to support AIX +// +// Revision 1.4 1996/09/19 18:50:06 akers +// Included time.h in order to match redefinition of fd_set to __fd_set. +// +// Revision 1.3 1995/12/15 15:08:06 chen +// Add VMS Fix +// +// Revision 1.2 1995/10/05 16:30:12 chen +// Fix for VMS +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#ifndef _CDEV_FDSET_H +#define _CDEV_FDSET_H + +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#else +#include + +#ifdef __VMS +#ifdef _TGV_MULTINET +// Under TGV multinet and VMS, if you want sys/types.h you need to have +// types.h already pulled in because sys/types.h makes it look like types.h +// is loaded. Then when types.h does get loaded, it is ignored because it +// looks like it is already loaded -- Mr. Danial Van Olst +#include +#endif +#endif + +#ifdef __VMS +#ifdef _TGV_MULTINET +// Under TGV Multinet and VMS, the file sys/param.h does not define +// NOFILE (max number of open files per process). +// FD_SETSIZE seems to be the correct value for NOFILE. +// See Multinet's sys/types.h file for more info on FD_SETSIZE. +// - Daniel Van Olst +#ifndef NOFILE +#define NOFILE FD_SETSIZE +#endif /* NOFILE not defined. */ + +#endif /* _TGV_MULTINET defined. */ +#endif /* __VMS defined. */ + +#include +#include + +/* The header sys/select.h must be included on AIX machines */ +/* in order to define the FD_ZERO macro. */ +#ifdef _AIX + #include +#endif + +/* This wrapper design is not very portable to DEC OSF/1 */ +/* I had to redefine NFDBITS to 32. On OSF/1 NFDBITS is a */ +/* macro that expands to (sizeof(fd_mask)*8) which is 4096 by */ +/* default. This was an inappropriate value for defining the */ +/* MSB_MASK default value. Any ideas? The workaround is a */ +/* pretty severe restriction for OSF/1. DJT */ +/*#if defined (__osf__) */ +/*#define NFDBITS 32 */ +/*#endif */ + +#endif + +class CDEV_CLASS_SPEC cdevFdSet +{ + // = TITLE + // C++ wrapper for the BSD fd_set abstraction. + // + // = DESCRIPTION + // + + friend class cdevFdSet_Iterator; + public: + // = Initialization and termination. + + cdevFdSet (void); + cdevFdSet (const fd_set &mask); + + // = Methods for manipulating bitsets. + void reset (void); + int is_set (int) const; + void set_bit (int); + void clr_bit (int); + int num_set (void) const; + int max_set (void) const; + int pr_mask ( FILE * fp = stdout ); + void sync (int max = FD_SETSIZE); + operator fd_set *( void ) { return &mask_; } + +private: + int size_; + int max_handle_; + fd_set mask_; + + enum + { +#ifdef _WIN32 + MAX_SIZE = FD_SETSIZE, +#else + MAX_SIZE = NOFILE, + WORD_SIZE = NFDBITS, + NUM_WORDS = howmany (NOFILE, NFDBITS), +#ifdef __DECCXX + // DECC warns about integer overflow if 1 used because 1 is signed + MSB_MASK = ~(1U << (NFDBITS - 1)) +#elif defined (CDEV_HAS_64BIT_LONGS) + MSB_MASK = ~(1UL << (NFDBITS - 1)) +#else + MSB_MASK = ~(1 << (NFDBITS - 1)) +#endif + +#endif + }; + + int count_bits (unsigned long n) const; + void set_max (int max); + + static const char nbits_[256]; +}; + +class cdevFdSet_Iterator + // = TITLE + // Iterator for the cdevFdSet abstraction. + // + // = DESCRIPTION + // +{ +public: + cdevFdSet_Iterator (cdevFdSet &); + int operator ()(void); + void operator++ (void); + +private: + cdevFdSet &fds_; +#ifdef _WIN32 + /* index into fd_array[FD_SETSIZE] */ + unsigned int index_; +#else + /* index into fd_mask array */ + int index_; +#endif + /* current FD value = bit number in the long mask */ + /* not used in the WIN32 platform */ + int num_; + +#ifndef _WIN32 + fd_mask val_; +#endif +}; + +#endif diff --git a/include/cdevGlobalTagTable.h b/include/cdevGlobalTagTable.h new file mode 100644 index 0000000..112daa2 --- /dev/null +++ b/include/cdevGlobalTagTable.h @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdev global tag table +// +// Author: Jie Chen +// +// Revision History: +// cdevGlobalTagTable.h,v +// Revision 1.1 1995/10/03 19:54:40 chen +// single instance of cdevTagTable +// +// +#ifndef _CDEV_GBL_TAG_TABLE_H +#define _CDEV_GBL_TAG_TABLE_H + +// Use singleton design pattern to ensure that there is only +// one tag table in the system without using global variable +// which is not desirable in C++ + +#include + +class CDEV_CLASS_SPEC cdevGlobalTagTable +{ +public: + static cdevTagTable* tagTable (void); + +protected: + // constructor + cdevGlobalTagTable (void); + virtual ~cdevGlobalTagTable (void); + +private: + static cdevTagTable* instance_; +}; +#endif diff --git a/include/cdevGroup.h b/include/cdevGroup.h new file mode 100644 index 0000000..c562ad8 --- /dev/null +++ b/include/cdevGroup.h @@ -0,0 +1,201 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevGroup: handle multiple asynchronous operations +// +// Author: Jie Chen +// +// Revision History: +// cdevGroup.h,v +// Revision 1.5 1997/03/03 17:36:05 chen +// add buffering to channel access connection +// +// Revision 1.4 1995/12/08 15:35:37 chen +// handle deferred mode +// +// Revision 1.3 1995/07/05 18:42:44 chen +// change status interface +// +// Revision 1.2 1995/06/30 16:03:36 chen +// use generic list +// +// Revision 1.1.1.1 1995/06/16 17:14:07 epics +// initial import of cdev +// +// +#ifndef _CDEV_GROUP_H +#define _CDEV_GROUP_H + +#include +#include +#include +#include +#include +#include +#include + +#include "cdevBlockList.h" + +#define CDEV_EXEC_IMMEDIATE 0 +#define CDEV_EXEC_DEFERRED 1 + + +class CDEV_CLASS_SPEC cdevGroup: public cdevSync +{ +public: + // constructors and destructor + cdevGroup (unsigned int blockSize = DEFAULT_BLOCK_SIZE, + cdevSystem& system = cdevSystem::defaultSystem()); + virtual ~cdevGroup (void); + + virtual int start (void); + // PURPOSE: start this group. (see next) + // REQUIRE: nothing + // PROMISE: group stared, return CDEV_SUCCESS + + virtual int end (void); + // PURPOSE: end this group, all async IO between + // start and end will be in the group + // REQUIRE: nothing + // PROMISE: group ended, return CDEV_SUCCESS + + virtual int flush (void); + // PURPOSE: flush all network requests inside this group + // REQUIRE: nothing + // PROMISE: all network requests of this group will be sent out + // return CDEV_SUCCESS + + virtual int poll (void); + // PURPOSE: polling all outstanding IO events of this group + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS + + virtual int pend (int fd = -1); + // PURPOSE: do network pending for IO events forever until all + // network requests of this group have come back + // REQUIRE: nothing + // PROMISE: all come back or block forever (return CDEV_SUCCESS) + + virtual int pend (double seconds, int fd = -1); + // PURPOSE: do network pending for IO events for upto 'seconds' long or + // all network requests of this group have come back + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS: finished, return CDEV_TIMEOUT: timeout + + int allFinished (void); + // PURPOSE: check all transaction finished of this group + // REQUIRE: after pend call + // PROMISE: return 1: all finished, 0: not yet + + int status (int status[], int &numTransactions); + // PURPOSE: check status of all transactions + // REQURIE: transaction status will be in the integer array returned + // by this call. Element of the array = 0 finished. + // Callers provide integer array buffer with buffer size + // PROMISE: return CDEV_SUCCESS on success and numTransaction will be + // real number of trasanctions. return CDEV_INVALIDARG + // when the integer buffer is not big enough. + + void execDeferred (void); + void execImmediate (void); + // PURPOSE: change behaviour of execution of command inside the group + // execDeferred will buffer all commands until pend or poll or + // flush is called + // execImmediate will flush commands to underlying services + // immediately + // REQUIRE: none + // PROMISE: execution mode changed + + int executionMode (void) const; + // PURPOSE: return execution mode + // REQUIRE: none + // PROMISE: CDEV_EXEC_DEFERRED or CDEV_EXEC_IMMEDIATE + + int readyToExec (void) const; + // PURPOSE: for deferred mode group only. Return execution stage. + // REQUIRE: none + // PROMISE: 0: the deferred group is still in the buffered stage + // 1: the deferred group is ready to flush all buffered + // commands + + virtual const char *className (void) const {return "cdevGroup";} + +protected: + // all add and remove operation on the transaction object + cdevTranObj **addTranObj (cdevTranObj* obj); + // clean out all transaction objects + void cleanAll (void); + // get all services associaed with transaction objects + // only used when one about to call IO operations + void getServices (void); + // find out which service is ready + cdevService *pendingService (int handle); + // handle events inherited from cdevSync + virtual int handleEvents (cdevTimeValue *tv); + // notify one partucular service + virtual void notifyService (int fd); + // quick polling underlying services + virtual void qpoll (void); + + // setup file read mask + void setupFdMask (void); + + // add execution object to the list + cdevExecObj **addExecObj (cdevExecObj* eobj); + // cleanout all execution objects + void cleanAllEobjs (void); + // send out all buffered commands + int execAllCommands (void); + +protected: + // data member + // transaction object list + cdevBlockList objList_; + // order dependent, careful!!! + cdevBlockListIterator ite_; + // execution object list + cdevBlockList eobjList_; + // order dependent, careful!!! + cdevBlockListIterator eite_; + // service list associcated with this group + cdevSlist serviceList_; + cdevSystem &system_; + // flag to tell whether one unregister itself from the system + int unregOn_; + // flag to see whether this group is created successfully + int errBit_; + // flag to see whether transaction object should remove itself + // from the object list + int remXobj_; + // flag to lock the execution object list + int remEobj_; + // how many transaction objects are in this group + int hwMark_; + // group active flag + int active_; + // operation mode of group + int mode_; + // number of execution objects + int numEobjs_; + // stage of deferred execution: buffer mode or execution mode + // 0: buffer stage, 1: execution stage + int execStage_; + + // deny access of copy and assignment since the group is a manager + cdevGroup (const cdevGroup& ); + cdevGroup& operator = (const cdevGroup&); + + // friend class + friend class cdevSystem; + friend class cdevTranObj; + friend class cdevExecObj; +}; +#endif + diff --git a/include/cdevGrpCollectionRequest.h b/include/cdevGrpCollectionRequest.h new file mode 100644 index 0000000..71c31c7 --- /dev/null +++ b/include/cdevGrpCollectionRequest.h @@ -0,0 +1,167 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * cdevGrpCollectionRequest.h : This class is used to collect the results that + * are generated by numerous service-specific + * cdevCollectionRequest objects. When all of the + * component collections have responded to this + * object, the data will be consolidated and + * returned to the caller. + * + * Author: Walt Akers + * + * Revision History: + * cdevGrpCollectionRequest.h,v + * Revision 1.1 1996/11/12 20:32:34 akers + * New collection device source code + * + * ----------------------------------------------------------------------------- + */ +#ifndef _CDEV_GRP_COLLECTION_REQUEST_H +#define _CDEV_GRP_COLLECTION_REQUEST_H + +#include + +class CDEV_CLASS_SPEC cdevGrpCollectionRequest: public cdevCollectionRequest +{ +friend class cdevCollectionRequest; + +public: + // ********************************************************************* + // * This structure is provided as the void * argument to the default + // * callback whenever the synchronous send is used. The checkSum is + // * used to detect if the result returned after the send method stopped + // * waiting for it. + // ********************************************************************* + typedef struct + { + int completionCode; + int finished; + cdevData *data; + } SendStatus; + + // ********************************************************************* + // * These methods get state and access information for the underlying + // * cdevRequestObjects. + // ********************************************************************* + virtual int getState (void); + virtual int getAccess (void); + + // ********************************************************************* + // * This method sets the context of each of the underlying + // * cdevRequestObjects. + // ********************************************************************* + virtual int setContext (cdevData &ctx); + + // ********************************************************************* + // * send : + // * The send interface is used to provide synchronous I/O with the + // * service. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int send ( cdevData & in, cdevData & out ) + { return send(&in, &out); } + virtual int send ( cdevData * in, cdevData & out ) + { return send(in, &out); } + virtual int send ( cdevData & in, cdevData * out ) + { return send(&in, out); } + virtual int send ( cdevData * in, cdevData * out ); + + // ********************************************************************* + // * sendNoBlock : + // * The sendNoBlock interface is used in conjunction with cdevGroup + // * or cdevSystem to execute a series of operations. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int sendNoBlock (cdevData & in, cdevData & out) + { return sendNoBlock(&in, &out); } + virtual int sendNoBlock (cdevData * in, cdevData & out) + { return sendNoBlock(in, &out); } + virtual int sendNoBlock (cdevData & in, cdevData * out) + { return sendNoBlock(&in, out); } + virtual int sendNoBlock (cdevData * in, cdevData * out); + + // ********************************************************************* + // * sendCallback : + // * The sendCallback interface provides asynchronous communications + // * with the service. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int sendCallback (cdevData & in, cdevCallback & callback) + { return sendCallback(&in, callback); } + virtual int sendCallback (cdevData * in, cdevCallback & callback); + + // ********************************************************************* + // * This method returns the name of the class. + // ********************************************************************* + const char *className (void) const {return "cdevGrpCollectionRequest";} + +protected: + // ********************************************************************* + // * These are the protected constructor and destructor for this object. + // ********************************************************************* + cdevGrpCollectionRequest (char **devices, int nDevices, char *msg, cdevSystem& sys); + virtual ~cdevGrpCollectionRequest (void); + + // ********************************************************************* + // * This is the syncCallback method. It will be used by the send + // * method in order to detect the completion of the operation. + // ********************************************************************* + static void syncCallback (int status, void * user, cdevRequestObject &, cdevData &data); + + // ********************************************************************* + // * This callback function is used to receive the individual callbacks + // * from the underlying cdevRequestObjects and is used by sendCallback. + // ********************************************************************* + static void asyncCallback (int, void *, cdevRequestObject &, cdevData &); + + // ********************************************************************* + // * This is the asyncNoBlockCallback method. It will be used by the + // * sendNoBlock method in order to detect the completion of the + // * operation. + // ********************************************************************* + static void asyncNoBlockCallback (int status, void * user, cdevRequestObject &, cdevData &data); + +private: + static SendStatus sendStatus; + static int sendCheckSum; + + // ********************************************************************* + // * These are the cdevCollectionRequest objects that are addressed by + // * each call to this cdevGrpCollectionRequest. The nCollections + // * variable contains the number of cdevRequestObjects that are + // * represented. + // ********************************************************************* + cdevCollectionRequest **collections; + int nCollections; + + // ********************************************************************* + // * This is a table of integers that identifies the order in which + // * results from the incoming collections should be distributed to + // * the outbound data. + // ********************************************************************* + int * requestOrder; + int nRequests; + + // ********************************************************************* + // * This is the master data structure. It contains no actual data, + // * however, it identifies the data structure that should exist when + // * the request has been executed. + // * + // * This structure is inspected and updated at the completion of each + // * callback, and is used to initially create the cdevData objects that + // * are used for interim data storage. + // ********************************************************************* + cdevData format; +}; + +#endif diff --git a/include/cdevIOcontext.h b/include/cdevIOcontext.h new file mode 100644 index 0000000..7d34d25 --- /dev/null +++ b/include/cdevIOcontext.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevIOcontext header +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevIOcontext.h,v +// Revision 1.1.1.1 1995/06/16 17:14:06 epics +// initial import of cdev +// +// +#ifndef _CDEV_IO_CONTEXT_H +#define _CDEV_IO_CONTEXT_H + +#include +#include +#include +#include + +class CDEV_CLASS_SPEC cdevIOcontext +{ + public: + // constructors and destructor + virtual ~cdevIOcontext (void); + + cdevData& getContext (void); + // PURPOSE: get context represented by a cdevData + + virtual int setContext (cdevData& ctx); + // PURPOSE: set context from a cdevData + // derived class may provide different setContext function + // eg. channel access requestObject will use this function + // to provide right request data type + // REQUIRE: nothing + // PROMISE: return 0 + + void setPrivate (void *userdata); + // PURPOSE: set user provided data + // REQUIRE: nothing. user handle memory management of userdata + // PROMISE: user data will not be freeed when this is destroyed + + void * getPrivate (void); + // PURPOSE: get user provided data + // REQUIRE: nothing + // PROMISE: something + + virtual const char *className(void) const {return "cdevIOcontext";} + + protected: + // constructor, to prevent from direct instantiation + cdevIOcontext (void); + cdevData data_; + void *userData_; +}; +#endif + diff --git a/include/cdevIntHash.h b/include/cdevIntHash.h new file mode 100644 index 0000000..84f72f0 --- /dev/null +++ b/include/cdevIntHash.h @@ -0,0 +1,117 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevIntHash: cdev hash table keyed by an integer +// Open Hash with buckets implemented by single linked lists +// +// Note: void *s are stored inside the table. This class +// will not manage these pointers. Callers have to +// manage these pointers +// +// Author: Danjin Wu (Modified from cdevStrHash class) +// +// Revision History: +// cdevIntHash.h,v +// Revision 1.2 1996/08/26 21:12:35 akers +// Added getData method to iterator +// +// Revision 1.1 1995/08/21 15:45:36 danjin +// integer hash table +// +// +// +#ifndef _CDEV_INT_HASH_H +#define _CDEV_INT_HASH_H + +#include + +//====================================================================== +// One simple integer hash function +// This hash function is used in cdevData. +// It returns integer value between 0 to table size +//====================================================================== + +typedef int cdevIntKeyItem; +typedef void* cdevHashItem; +//====================================================================== +// class cdevIntHash +// collection of buckets indexed by hashed values +//====================================================================== +class cdevIntHashIterator; + +class CDEV_CLASS_SPEC cdevIntHash +{ +public: + // constructor, construct a table with entry max + cdevIntHash (unsigned int max); + // destructor + virtual ~cdevIntHash (void); + + // operations + + // is the table empty: return 1: yes. return 0: no + virtual int isEmpty(); + + // clear the elements of the set + virtual void deleteAllValues(); + + // add an element to the collection + virtual void add (cdevIntKeyItem key, cdevHashItem ele); + + // test to see whether this hash table includes one particular element + virtual int find (cdevIntKeyItem key, cdevHashItem ele) const; + + // remove an element. return 0: ele is not inside table. return 1: success + virtual int remove (cdevIntKeyItem key, cdevHashItem ele); + + // return a reference to a particular bucket according to the key + cdevSlist& bucketRef (cdevIntKeyItem key); + + protected: + friend class cdevIntHashIterator; + + // the actual table itself is a vector of buckets + const unsigned int tablesize; + cdevSlist* buckets; + + // convert key into unsigned integer value in range + unsigned int hash(const cdevIntKeyItem key) const; + +}; + +//====================================================================== +// class cdevIntHashIterator +// iterator protocol for hash tables +//====================================================================== +class CDEV_CLASS_SPEC cdevIntHashIterator +{ +public: + // constructor and destructor + cdevIntHashIterator (cdevIntHash& v); + ~cdevIntHashIterator (void); + + // iterator protocol + int init (void); + cdevHashItem operator ()(void); + cdevHashItem getData (void); + int operator ! (void); + int operator ++(void); + void operator = (cdevHashItem value); + +protected: + cdevIntHash& base; + unsigned int currentIndex; + // Single iterator within a bucket + cdevSlistIterator* itr; + // getNextIterator used to set internal iterator pointer + // return 1: got it. return 0: no more iterator + int getNextIterator (void); +}; +#endif diff --git a/include/cdevMonitorObj.h b/include/cdevMonitorObj.h new file mode 100644 index 0000000..23c5130 --- /dev/null +++ b/include/cdevMonitorObj.h @@ -0,0 +1,92 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdev Monitoring Object class (for service developer only) +// +// This class is for services that support monitoring capabilities. +// It is very much like transanaction object but without being registered +// in the groups. The transaction objects will be deleted after the first +// callbacks. The monitor objects will stay around as long as the monitors +// are on. +// +// Service developers may have to derive from this class to handle +// service specific monitoring +// +// Author: Jie Chen +// +// Revision History: +// cdevMonitorObj.h,v +// Revision 1.4 1998/02/06 15:29:08 chen +// cosmatic change +// +// Revision 1.3 1998/01/30 14:25:18 akers +// Ongoing development +// +// Revision 1.2 1998/01/30 13:49:19 akers +// Ongoing development +// +// Revision 1.1 1998/01/14 14:26:39 chen +// add cdevMonitorObj +// +// +// +#ifndef _CDEV_MONITOR_OBJ_H +#define _CDEV_MONITOR_OBJ_H + +#include + +class cdevMonitorObj +{ +public: + // constructor and destructor + cdevMonitorObj(cdevTranObj &tranObj):system_(tranObj.system_), + reqObj_(tranObj.reqObj_), resultData_(tranObj.resultData_), + userCallback_(tranObj.userCallback_), tobj_(&tranObj) + { +#ifdef _TRACE_OBJECTS + printf("Create cdevMonitorObj Class Object\n"); +#endif + // disable transaction from deleting the callback + tobj_->disableDeleteCbk(); + } + + virtual ~cdevMonitorObj(void) + { +#ifdef _TRACE_OBJECTS + printf("Delete cdevMonitorObj Class Object\n"); +#endif + if(userCallback_ != 0) + { +#ifdef _CMLOG_DEBUG + printf("Delete userCallback inside cdevMonitorObj\n"); +#endif + delete userCallback_; + } + userCallback_=0; + } + + virtual const char *className(void) const {return"cdevMonitorObj";} + + // data area for requestObject to access + cdevSystem *system_; + cdevRequestObject *reqObj_; + cdevData *resultData_; + cdevCallback *userCallback_; + + // pointer to transaction object + cdevTranObj *tobj_; + +private: + // deny access to copy and assignment + cdevMonitorObj(const cdevMonitorObj &); + cdevMonitorObj &operator=(const cdevMonitorObj &); +}; + +#endif diff --git a/include/cdevRedirectorDefinition.h b/include/cdevRedirectorDefinition.h new file mode 100644 index 0000000..15e103b --- /dev/null +++ b/include/cdevRedirectorDefinition.h @@ -0,0 +1,127 @@ +#ifndef _CDEV_REDIRECTOR_DEFINITION_H_ +#define _CDEV_REDIRECTOR_DEFINITION_H_ + +#ifndef _CDEV_DIRECTORY_TABLE_H_ + #error "You must include cdevDirectoryTable.h to load cdevRedirectorDefinition.h" +#endif + +#include + +// ***************************************************************************** +// * class cdevRedirectorDefinition : +// * This class is used to store the information that identifies the +// * service and service data that is associated with a specific message. +// * This class is only instanciated in a cdevClassDefinition that has +// * been instanciated. +// * +// * To reduce the number of copies of extraneous data, this class will +// * use the service data that is stored in the cdevElementDefinition. +// ***************************************************************************** +class cdevRedirectorDefinition +{ +private: + char * name; + cdevServiceDefinition * service; + char ** serviceData; + int nItems; + +public: + inline cdevRedirectorDefinition ( char *Name, cdevElementDefinition &def); + inline ~cdevRedirectorDefinition ( void ); + inline void asciiDump ( FILE * fp = stdout ); + + // ********************************************************************* + // * Member access methods + // ********************************************************************* + inline char * getName ( void ); + inline cdevServiceDefinition * getService ( void ); + inline char ** getServiceData ( void ); + inline int getDataCnt ( void ); +}; + + +// ***************************************************************************** +// * cdevRedirectorDefinition::cdevRedirectorDefinition : +// * This is the constructor for the cdevRedirectorDefinition class... The +// * message parameter becomes the property of the class and should not +// * be accessed again by the caller... +// ***************************************************************************** +inline cdevRedirectorDefinition::cdevRedirectorDefinition + ( char *Name, cdevElementDefinition &def) + : name (Name), + service (def.getService()), + serviceData(def.getServiceData()), + nItems (def.getDataCnt()) + { + } + + +// ***************************************************************************** +// * cdevRedirectorDefinition::~cdevRedirectorDefinition : +// * This is the destructor for the cdevRedirectorDefinition object. +// ***************************************************************************** +inline cdevRedirectorDefinition::~cdevRedirectorDefinition ( void ) + { + delete name; + } + + +// ***************************************************************************** +// * cdevRedirectorDefinition::asciiDump : +// * This is a diagnostic method that allows the caller to dump the contents +// * of the class redirection table that identifies which service will +// * be used for each message. +// ***************************************************************************** +inline void cdevRedirectorDefinition::asciiDump ( FILE * fp ) + { + fprintf(fp, "\t\t\"%s\" %s", name, service->getName()); + if(serviceData!=NULL && nItems>0) + { + fprintf(fp, " {"); + for(int i=0; i +#include +#include + +#include +#include +#include +#include +#include +#include + +class cdevExecGroup; + +//======================================================================= +// some useful bit mask manipulation routines +//======================================================================= +#define NUMBITS_PER_BYTE 8 + +#ifdef _CDEV_NO_INLINE +//======================================================================= +// clear a long mask, set every bit to 0 +//======================================================================= +extern void cdevMaskZero (long& p); + +//======================================================================= +// turn on a bit at position n inside the mask p +//======================================================================= +extern void cdevMaskSet (long n, long& p); + +//======================================================================= +// turn off a bit at position n inside the mask p +//======================================================================= +extern void cdevMaskClr (long n, long& p); + +//======================================================================= +// check whether a bit n is set or not +//======================================================================= +extern int cdevMaskIsSet (long n, long p); +#endif + + +class CDEV_CLASS_SPEC cdevRequestObject: public cdevIOcontext +{ + public: + //====================================================================== + // Public Interface for Clients + //====================================================================== + static cdevRequestObject& attachRef (char *deviceName, char *msg); + static cdevRequestObject* attachPtr (char *deviceName, char *msg); + + // PURPOSE: Create or Attach Pointer or reference to a requestObject + // inside the default system + // REQUIRE: deviceName != 0, msg != 0. + // PROMISE: return a cdevRequestObject which may be an errorRequestObject + // depending on the device and message pair + + static void detach (cdevRequestObject& objRef); + static void detach (cdevRequestObject* objPtr); + // PURPOSE: Detach from a cdevRequestObject + // REQUIRE: objPtr != 0 + // PROMISE: If objPtr is the last one attached to a cdevRequestObject, + // the cdevRequestObject will be destroyed + + char *message (void) const; + // PURPOSE: return message of this requestObject + // REQUIRE: nothing + // PROMISE: a message + + cdevDevice& device (void) const; + // PURPOSE: return a refence a device holding this request object + // REQUIRE: nothing + // PROMISE: reference of a device + + cdevSystem& system (void) const; + // PURPOSE: return a reference of a system associated with this object + // REQUIRE: nothing + // PROMISE: reference of a system + + cdevService& service (void) const; + // PURPOSE: return a reference of a service associated with this object + // REQUIRE: nothing + // PROMISE: reference of a service + + virtual int getState (void); + // PURPOSE: return status information, derived classes implement this + // REQUIRE: nothing + // PROMISE: + + virtual int getAccess (void); + // PURPOSE: return access control information, derived classes implement this + // REQUIRE: nothing + // PROMISE: + + virtual int send (cdevData& out, cdevData& result) = 0; + virtual int send (cdevData *out, cdevData& result) = 0; + virtual int send (cdevData& out, cdevData* result) = 0; + virtual int send (cdevData *out, cdevData* result) = 0; + // PURPOSE: pure virtual functions for synchronous IO operations + // REQUIRE: derived classes implement those + // PROMISE: return CDEV_SUCCESS: success. See cdevErrCode.h for detail + + virtual int sendNoBlock (cdevData& out, cdevData& result) = 0; + virtual int sendNoBlock (cdevData *out, cdevData& result) = 0; + virtual int sendNoBlock (cdevData& out, cdevData* result) = 0; + virtual int sendNoBlock (cdevData* out, cdevData* result) = 0; + // PURPOSE: pure virtual functions for asynchronous IO operations + // REQUIRE: + // PROMISE: return CDEV_SUCCESS: success. See cdevErrCode.h for detail + + virtual int sendCallback (cdevData& out, cdevCallback& callback) = 0; + virtual int sendCallback (cdevData *out, cdevCallback& callback) = 0; + // PURPOSE: pure virtual functions for asynchronous IO operations with + // user provided callback functions + // REQUIRE: + // PROMISE: return CDEV_SUCCESS: success. See cdevErrCode.h for detail + + virtual int setContext (cdevData& cxt); + // PURPOSE: set context from a cdevData. Check longMask + // tag to set the bit monitoring mask + // derived class may provide different setContext function + // eg. channel access requestObject will use this function + // to provide right request data type. + // REQUIRE: nothing + // PROMISE: return 0 + + + // for subclasss of cdevDevice use only + void ref (void); + // PURPOSE: Increase reference count of this requestobject by one + // REQUIRE: none + // PROMISE: refcount will go up by 1 + + void deref (void); + // PURPOSE: decrease reference count of this requestobject by one + // REQUIRE: none + // PROMISE: refcount will go down by 1 + + + virtual const char *className (void) const {return "cdevRequestObject";} + +protected: + //constructors and destructors + cdevRequestObject (char *device, char *msg, + cdevSystem& system = cdevSystem::defaultSystem() ); + cdevRequestObject (cdevDevice &device, char *msg, + cdevSystem& system = cdevSystem::defaultSystem() ); + virtual ~cdevRequestObject (void); + + // protected version of send for service layer + virtual int execNoBlock (cdevData* out, cdevData* result, void* arg); + virtual int execCallback (cdevData* out, cdevCallback& callback, void* arg); + + // protected to prevent use of multiple systems for now + static cdevRequestObject& attachRef (char *deviceName, + char *msg, cdevSystem& system); + // PURPOSE: Create reference to a requestObject within a given system + // REQUIRE: deviceName != 0, msg != 0. + // PROMISE: return a cdevRequestObject which may be an errorRequestObject + // depending on the device and message pair + static cdevRequestObject* attachPtr (char *deviceName, + char *msg, cdevSystem& system); + // PURPOSE: Create pointer to a requestObject within a given system + // REQUIRE: deviceName != 0, msg != 0. + // PROMISE: return a cdevRequestObject or NULL if not a valid combination + + // following routine used only by cdevDevice, and is the real factory + static cdevRequestObject* attachPtr (cdevDevice& dev, + char *msg, cdevSystem& system); + // PURPOSE: Create pointer to a NEW requestObject within a given system + // REQUIRE: dev != 0, msg != 0. + // PROMISE: return a cdevRequestObject or NULL if not a valid combination + + virtual int bitValuesChanged (long value, long mask); + // PURPOSE: Check any bit values of 'value' changed or not according + // to the mask 'mask'. Any derived classes of cdevRequestObject + // may use this routine to monitor any set of bits in a long + // integer value. + // REQUIRE: none + // PROMISE: if any bit values changed, return 1, else return 0 + + // assign device to the object + void device (cdevDevice *dev); + // assign service to the object + void service (cdevService *service); + + // internal functions for service developer who wants to support + // deferred execution mode inside groups + + // callback will be duplicated if indeed one needs to do defferred ops + int deferExecution (cdevData* out, cdevData* result); + int deferExecution (cdevData* out, cdevCallback* callback); + int executionMode (void); + + // internal functions for service developer who wants to support + // buffering mechanism to improve performance + // note: buffer must be derived class of cdevGroup + + // callback will be duplicated + void bufferExecution (cdevData* out, cdevData* result, + cdevGroup* buffer, void* arg); + void bufferExecution (cdevData* out, cdevCallback* result, + cdevGroup* buffer, void* arg); + + // device pointer + cdevDevice *device_; + // system reference + cdevSystem& system_; + // device name + char *deviceName_; + // message name + char *message_; + // service pointer + cdevService *service_; + // flag to tell whether to unregister from a device on delete + int unregOn_; + // bit monitoring mask + long longMask_; + +private: + // copy and assignment + cdevRequestObject& operator = (const cdevRequestObject& object); + cdevRequestObject (const cdevRequestObject& object); + + // reference counting + int refCount_; + + // friend class declaration + friend class cdevDevice; + friend class cdevSystem; + friend class cdevExecGroup; +}; + +#undef INLINE +#ifndef _CDEV_NO_INLINE +#define INLINE inline +#include "cdevRequestObject.i" +#else +#define INLINE +#endif + +#endif diff --git a/include/cdevRequestObject.i b/include/cdevRequestObject.i new file mode 100644 index 0000000..ecfffde --- /dev/null +++ b/include/cdevRequestObject.i @@ -0,0 +1,154 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevRequestObject implementation (abstract class) +// inline functions +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevRequestObject.i,v +// Revision 1.3 1998/02/13 14:00:44 chen +// add ref and deref +// +// Revision 1.2 1997/03/03 17:52:28 chen +// add buffering mechanism to caService +// +// Revision 1.1 1995/12/08 15:39:43 chen +// inline functions +// +// + +// Note: How to determine to buffer an exeution object? +// If an execution object belongs to a group with +// an immediate execution mode, this object will not be +// buffered. If an execution object belongs to a group +// with a deferred execution mode, this execution object +// will be buffered + +INLINE +int +cdevRequestObject::deferExecution (cdevData* out, cdevData* result) +{ + if (executionMode () == CDEV_EXEC_DEFERRED) { + // create a transaction object + cdevExecObj* obj = new cdevExecObj (&system_, this, out, result, 0); + return 1; + } + else + return 0; +} + +INLINE +int +cdevRequestObject::deferExecution (cdevData* out, cdevCallback* callback) +{ + if (executionMode () == CDEV_EXEC_DEFERRED) { + // create a transaction object with new copy of callback + // must clone the data, as the caller did not + cdevCallback *ccbk = new cdevCallback (*callback); + cdevData *cloned = new cdevData(*out); + cdevExecObj* obj = new cdevExecObj (&system_, this, cloned, 0, ccbk); + return 1; + } + else + return 0; +} + +INLINE +void +cdevRequestObject::bufferExecution (cdevData* out, cdevData* result, + cdevGroup* group, void* arg) +{ + // create an execution object that is registered to the group + // caller has already cloned the data, so don't need to + cdevExecObj* obj = new cdevExecObj (&system_, this, out, result, 0, + group, arg); +} + +INLINE +void +cdevRequestObject::bufferExecution (cdevData* out, cdevCallback* callback, + cdevGroup* group, void* arg) +{ + // create an execution object that is registered to the group + // caller has already cloned the data, so don't need to + cdevExecObj* obj = new cdevExecObj (&system_, this, out, 0, callback, + group, arg); +} + +INLINE +int +cdevRequestObject::execNoBlock (cdevData*, cdevData*, void* ) +{ + // empty: derived class handles this + return CDEV_SUCCESS; +} + +INLINE +int +cdevRequestObject::execCallback (cdevData*, cdevCallback&, void* ) +{ + // empty: derived class handles this + return CDEV_SUCCESS; +} + +//======================================================================= +// clear a long mask, set every bit to 0 +//======================================================================= +INLINE +void cdevMaskZero (long& p) +{ + ::memset ((char *)&p, (char)0, sizeof (long)); +} + +//======================================================================= +// turn on a bit at position n inside the mask p +//======================================================================= +INLINE +void cdevMaskSet (long n, long& p) +{ + assert ((n >= 0) && (n < sizeof (long) * NUMBITS_PER_BYTE)); + p |= 1 << n; +} + +//======================================================================= +// turn off a bit at position n inside the mask p +//======================================================================= +INLINE +void cdevMaskClr (long n, long& p) +{ + assert ((n >= 0) && (n < sizeof (long) * NUMBITS_PER_BYTE)); + p &= ~(1 << n); +} + +//======================================================================= +// check whether a bit n is set or not +//======================================================================= +INLINE +int cdevMaskIsSet (long n, long p) +{ + assert ((n >= 0) && (n < sizeof (long) * NUMBITS_PER_BYTE)); + return (p & (1 << n)); +} + +INLINE +void cdevRequestObject::ref (void) +{ + refCount_ ++; +} + +INLINE +void cdevRequestObject::deref (void) +{ + refCount_ --; +} + + diff --git a/include/cdevSelector.h b/include/cdevSelector.h new file mode 100644 index 0000000..5ca2140 --- /dev/null +++ b/include/cdevSelector.h @@ -0,0 +1,253 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: cdevSelector.h +// The cdevSelector class provides a mechanism for cdevServices to provide +// a locally changable file descriptor to the cdevSystem for select +// operations. +// +// If the service does not support or require file descriptors to operate, +// it may make one of these objects in its constructor and then provide +// the 'readfd' to the cdevSystem when it calls the services getFD method. +// The service may then 'insertEvents' into the object, which will in-turn +// cause the cdevSystems select mechanism to call the service. Once the +// service has responded to the events it should call 'removeEvents' to +// prevent the select mechanism from being triggered again. +// +// Author: Walt Akers +// +// Revision History: +// cdevSelector.h,v +// Revision 1.3 1996/12/05 21:10:49 akers +// Changes to support multiple CDEV DDL versions +// +// Revision 1.2 1995/10/19 20:16:55 akers +// Added capability to test the read file descriptor for data before reading +// +// Revision 1.1 1995/08/18 16:23:41 akers +// Mechanism for providing file descriptor selection for services. +// +// + +#ifndef _CDEV_SELECTOR_H_ +#define _CDEV_SELECTOR_H_ + +#include +#include +#include +#include +#include + +#if defined(solaris) || defined(SunOS) + #include +#endif + +class cdevSelector +{ +private: + typedef struct + { + int readfd; + int writefd; + } SocketPair; + SocketPair sp; + char cbuf[21]; + +public: + cdevSelector ( void ); + ~cdevSelector ( void ); + int insertEvent ( int numEvents = 1 ); + int removeEvent ( int numEvents = 1 ); + void purge ( void ); + int writefd ( void ); + int readfd ( void ); +}; + + + +// ***************************************************************************** +// * cdevSelector::cdevSelector : +// * Constructor for the cdevSelector class. +// ***************************************************************************** +inline cdevSelector::cdevSelector ( void ) + { + if(pipe((int *)&sp)!=0) + { + sp.readfd = -1; + sp.writefd = -1; + } + else + { + int val; + + val = ::fcntl(sp.readfd, F_GETFL, 0); + if(val>0) ::fcntl(sp.readfd, F_SETFL, val|O_NONBLOCK); + + val = ::fcntl(sp.writefd, F_GETFL, 0); + if(val>0) ::fcntl(sp.writefd, F_SETFL, val|O_NONBLOCK); + } + } + + + +// ***************************************************************************** +// * cdevSelector::~cdevSelector : +// * Destructor for the cdevSelector class. +// ***************************************************************************** +inline cdevSelector::~cdevSelector ( void ) + { + if(sp.readfd != -1) close(sp.readfd); + if(sp.writefd != -1) close(sp.writefd); + } + + + +// ***************************************************************************** +// * cdevSelector::insertEvent : +// * Adds one or more bytes (indicating events) to the pipe +// ***************************************************************************** +inline int cdevSelector::insertEvent ( int numEvents ) + { + int result = 0; + char *cptr = cbuf; + + // ********************************************************************* + // * If the write file descriptor is valid + // ********************************************************************* + if(sp.writefd>0) + { + // ************************************************************* + // * If the user wants to add more bytes than the buffer can + // * handle, allocated a sufficient buffer to hold the data. + // ************************************************************* + if(numEvents>20) cptr = new char[numEvents]; + + // ************************************************************* + // * Write the specified number of bytes to the buffer. + // ************************************************************* + write(sp.writefd, cptr, numEvents); + + // ************************************************************* + // * Delete the buffer if it was allocated locally. + // ************************************************************* + if(cptr!=cbuf) delete cptr; + } + else result = -1; + return result; + } + + + +// ***************************************************************************** +// * cdevSelector::removeEvent : +// * Removes one or more bytes (indicating events) from the pipe. +// ***************************************************************************** +inline int cdevSelector::removeEvent ( int numEvents ) + { + int result = 0; + char *cptr = cbuf; + + // ********************************************************************* + // * If the read file descriptor is valid. + // ********************************************************************* + if(sp.readfd>0) + { + int count; + // ************************************************************* + // * Find out how many bytes are ready to read. + // ************************************************************* + ioctl(sp.readfd, FIONREAD, &count); + if(numEvents>count) numEvents = count; + + if(numEvents>0) + { + // ***************************************************** + // * If the user wants to remove more bytes than the + // * buffer can handle, allocated a sufficient buffer to + // * hold the data. + // ***************************************************** + if(numEvents>20) cptr = new char[numEvents]; + + // ***************************************************** + // * Read the specified number of bytes from the pipe. + // ***************************************************** + read(sp.readfd, cptr, numEvents); + + // ***************************************************** + // * Delete the buffer if it was allocated locally. + // ***************************************************** + if(cptr!=cbuf) delete cptr; + } + } + else result = -1; + return result; + } + + + +// ***************************************************************************** +// * cdevSelector::purge : +// * This function removes all bytes from the pipe. +// ***************************************************************************** +inline void cdevSelector::purge ( void ) + { + int count; + char * cptr = cbuf; + + if(sp.readfd>0) + { + // ************************************************************* + // * Find out how many bytes are ready to read. + // ************************************************************* + ioctl(sp.readfd, FIONREAD, &count); + + if(count>0) + { + // ***************************************************** + // * If the user wants to remove more bytes than the + // * buffer can handle, allocated a sufficient buffer to + // * hold the data. + // ***************************************************** + if(count>20) cptr = new char[count]; + + // ***************************************************** + // * Read the specified number of bytes from the pipe. + // ***************************************************** + read(sp.readfd, cptr, count); + + // ***************************************************** + // * Delete the buffer if it was allocated locally. + // ***************************************************** + if(cptr!=cbuf) delete cptr; + } + } + } + + + +// ***************************************************************************** +// * cdevSelector::writefd +// * Returns the write file descriptor associated with the pipe. +// ***************************************************************************** +inline int cdevSelector::writefd ( void ) + { + return sp.writefd; + } + + + +// ***************************************************************************** +// * cdevSelector::readfd +// * Returns the read file descriptor associated with the pipe. +// ***************************************************************************** +inline int cdevSelector::readfd ( void ) + { + return sp.readfd; + } + +#endif /* _CDEV_SELECTOR_H_ */ diff --git a/include/cdevService.h b/include/cdevService.h new file mode 100644 index 0000000..d7cac28 --- /dev/null +++ b/include/cdevService.h @@ -0,0 +1,92 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevSerice class (Abstract class ) +// +// Author: Jie Chen, Chip Watson & Walt Akers +// +// Revision History: +// cdevService.h,v +// Revision 1.3 1997/08/27 18:23:32 chen +// Change error reporting to site specific scheme +// +// Revision 1.2 1996/11/21 17:03:32 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#ifndef _CDEV_SERVICE_H +#define _CDEV_SERVICE_H + +#include "cdevSystemBase.h" +#include "cdevSystem.h" + +class cdevCollectionRequest; + +class cdevDevice; + +class CDEV_CLASS_SPEC cdevService: public cdevSystemBase +{ +public: + virtual int getFd (int* &fd, int &numFd) = 0; + // PURPOSE: get service's IO file descriptors + // REQUIRE: callers provide pointer (eg. int *fd = 0;) no memory. callers + // should never free memory pointed by fd. fd should be cached + // inside derived class for easy/quick access + // PROMISE: numFd >= 0 + + virtual int getNameServer (cdevDevice* &server) = 0; + // PURPOSE: get right name server associated with this service + // REQUIRE: caller provide pointer only, derived class provides + // an empty function for now + // PROMISE: not implemented yet + + virtual int registerFd (int fd, int opened = 1); + // PURPOSE: updating file descriptor mask + // REQUIRE: opend = 1 for adding, else removing + // PROMISE: return 0 + + virtual char *name (void) const; + // PURPOSE: return name of this service + // REQUIRE: name must be unique in one system + // PROMISE: name + + virtual int getCollectionRequest (char ** devices, int nDevices, + char * msg, cdevCollectionRequest * &req); + // PURPOSE: return collection requestobject + // REQUIRE: devices != NULL, ndevices > 0 + // PROMISE: CDEV_SUCCESS on success, CDEV_ERROR no request object + + const int version (void) const; + // PURPOSE: return version of service + // REQUIRE: none + // PROMISE: version number of this service + + virtual const char *className (void) const {return "cdevService";} + +protected: + // constructor: deny access for direct instantiation + cdevService (char *name, cdevSystem &system = cdevSystem::defaultSystem ()); + // destructor, all services must be created and destroyed by system + virtual ~cdevService (void); + + // data area + cdevSystem &system_; + char *serviceName_; + // flag to tell whether one unregister itself from system + int unregOn_; + // friend class decleration + friend class cdevSystem; +}; +#endif + + diff --git a/include/cdevServiceDefinition.h b/include/cdevServiceDefinition.h new file mode 100644 index 0000000..99c02a9 --- /dev/null +++ b/include/cdevServiceDefinition.h @@ -0,0 +1,144 @@ +#ifndef _CDEV_SERVICE_DEFINITION_H_ +#define _CDEV_SERVICE_DEFINITION_H_ + +#ifndef _CDEV_DIRECTORY_TABLE_H_ + #error "You must include cdevDirectoryTable.h to load cdevServiceDefinition.h" +#endif + +#include + +// ***************************************************************************** +// * class cdevServiceDefinition : +// * This class stores a single CDEV service definition as defined in the +// * DDL file. This data is managed by the cdevServiceList. +// * +// * This class maintains a variety of internal data items for the following +// * purposes... +// * +// * name - This is the name of the service as specified in the +// * CDEV DDL file. +// * tags - These are the tags that will be used as service data when +// * loading elements that use this service. +// * nTags - This is the number of tags in the tags array. +// * next - This is the next service that was loaded from the CDEV DDL +// * file. This list is maintained in the cdevDirectoryTable +// * object. +// ***************************************************************************** +class cdevServiceDefinition +{ +private: + cdevServiceDefinition * next; + char * name; + char ** tags; + int nTags; +public: + inline cdevServiceDefinition ( char *Name=NULL, char ** Tags=NULL, int NTags=0); + inline ~cdevServiceDefinition ( void ); + inline void asciiDump ( FILE * fp = stdout ); + + // ********************************************************************* + // * Member access methods. + // ********************************************************************* + inline char * getName ( void ); + inline char ** getTags ( void ); + inline int getTagCnt ( void ); + inline cdevServiceDefinition * getNext ( void ); + inline void setNext ( cdevServiceDefinition * Next ); +}; + + +// ***************************************************************************** +// * cdevServiceDefinition::cdevServiceDefinition : +// * This is the constructor for the cdevService defintion. It uses the +// * following parameters: +// * +// * Name - the name of the service being added. +// * Tags - the service data tags that will be used by each device. +// * NTags - the number of tags in the list. +// ***************************************************************************** +inline cdevServiceDefinition::cdevServiceDefinition ( char *Name, char ** Tags, int NTags) + : next(NULL), name(Name), tags(Tags), nTags(NTags) + { + } + +// ***************************************************************************** +// * cdevServiceDefinition::cdevServiceDefinition : +// * This is the destructor for the cdevServiceDefinition class. It will +// * delete all data items that were provided to the constructor. +// ***************************************************************************** +inline cdevServiceDefinition::~cdevServiceDefinition ( void ) + { + if(name) delete name; + while(--nTags>=0) delete tags[nTags]; + if(tags) delete tags; + } + +// ***************************************************************************** +// * cdevServiceDefinition::asciiDump : +// * This method is used to write the contents of the service definition +// * object to an ouput file. +// ***************************************************************************** +inline void cdevServiceDefinition::asciiDump ( FILE * fp ) + { + fprintf(fp, "\nservice %s\n\t{\n\t", name); + if(tags && nTags) + { + int idx; + fprintf(fp, "tags {"); + for(idx=0; idx +#include + +typedef void* cdevSlistItem; + +//====================================================================== +// class cdevGenSlist +// Single Linked List for void* pointer +//====================================================================== +class cdevSlistLink; +class cdevSlistIterator; +class cdevSlistCursor; + +class CDEV_CLASS_SPEC cdevSlist +{ +public: + // constructors + cdevSlist (void); + cdevSlist (const cdevSlist & source); + virtual ~cdevSlist (void); + + // operations + + // add list item to the beginning of the list + virtual void add(cdevSlistItem value); + + // remove a list item from the list + // return 0: nothing to remove + // return 1: remove success + virtual int remove (cdevSlistItem value); + + // clean up the list. + virtual void deleteAllValues(); + + // return first element of the list + virtual cdevSlistItem firstElement() const; + + // return last element of the list + virtual cdevSlistItem lastElement() const; + + // duplicate ths whole list + virtual cdevSlist* duplicate() const; + + // check whether this list contains a particular item + // return 1: yes. return 0: no + virtual int includes(cdevSlistItem value) const; + + // Is list empty + // return 1: yes. return 0: no + virtual int isEmpty() const; + + // remove first element of the list + virtual void removeFirst(); + + // return number of elements inside the list + virtual int count() const; + + protected: + // data field + cdevSlistLink* ptrToFirstLink; + + // friends + friend class cdevSlistIterator; + // cannot modify list in anyways + friend class cdevSlistCursor; +}; + +//====================================================================== +// class cdevSlistLink +// Single linked list link node +//====================================================================== +class CDEV_CLASS_SPEC cdevSlistLink +{ + public: + // insert a new element following the current value + cdevSlistLink* insert (cdevSlistItem val); + + private: + // constructor + cdevSlistLink (cdevSlistItem linkValue, cdevSlistLink * nextPtr); + + // duplicate + cdevSlistLink* duplicate (void); + + // data areas + cdevSlistItem value; + cdevSlistLink* ptrToNextLink; + + // friends + friend class cdevSlist; + friend class cdevSlistIterator; + friend class cdevSlistCursor; +}; + +//=================================================================== +// class cdevSlistIterator +// implements iterator protocol for linked lists +// also permits removal and addition of elements +//=================================================================== +class CDEV_CLASS_SPEC cdevSlistIterator +{ +public: + // constructor + cdevSlistIterator (cdevSlist& aList); + + // iterator protocol + virtual int init (void); + virtual cdevSlistItem operator () (void); + virtual int operator ! (void); + virtual int operator ++ (void); + virtual void operator = (cdevSlistItem value); + + // new methods specific to list iterators + + // remove current item pointed by the iterator from the list + void removeCurrent(void); + + // add an item to the list before the position pointed by the iterator + void addBefore(cdevSlistItem newValue); + + // add an item to the list after the position pointed by the iterator + void addAfter(cdevSlistItem newValue); + + // search an item and move the iterator to that position + int searchSame(cdevSlistItem &value); + +protected: + // data areas + cdevSlistLink * currentLink; + cdevSlistLink * previousLink; + cdevSlist& theList; +}; + +//=================================================================== +// class cdevSlistCursor +// implements cursor protocol for linked lists +//=================================================================== +class CDEV_CLASS_SPEC cdevSlistCursor +{ +public: + // constructor + cdevSlistCursor (const cdevSlist& aList); + + // iterator protocol + virtual int init (void); + virtual cdevSlistItem operator () (void); + virtual int operator ! (void); + virtual int operator ++ (void); + virtual void operator = (cdevSlistItem value); + + int searchSame (cdevSlistItem &value); + + protected: + // data areas + cdevSlistLink * currentLink; + cdevSlistLink * previousLink; + const cdevSlist& theList; +}; + +//====================================================================== +// class doubleEndedList +// Not only keeps a pointer to first node +// but also keeps a pointer to last node +//====================================================================== +class CDEV_CLASS_SPEC cdevDoubleEndedSlist: public cdevSlist{ + public: + //constructor + cdevDoubleEndedSlist (void); + cdevDoubleEndedSlist (const cdevDoubleEndedSlist &v); + + // override the following methods from the cdevSlist + virtual void add (cdevSlistItem value); + virtual void deleteAllValues (void); + virtual void removeFirst (void); + + // add new element to the end of the list + virtual void addToEnd (cdevSlistItem value); + + protected: + cdevSlistLink *ptrToLastLink; +}; +#endif + + + + + + diff --git a/include/cdevSpec.h b/include/cdevSpec.h new file mode 100644 index 0000000..f5bd917 --- /dev/null +++ b/include/cdevSpec.h @@ -0,0 +1,73 @@ +/*----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + *----------------------------------------------------------------------------- + * + * Description: + * Cdev and API Specification + * + * Every class header file and C interface header should include + * this header + * + * Authors: Jie Chen + * + * Revision History: + * $Log: cdevSpec.h,v $ + * Revision 1.1.1.1 2000/05/23 15:13:04 pal + * cdev_psi_1.7.2 + * + * Revision 1.2 1999/01/15 17:30:20 akers + * Adjustment + * + * Revision 1.1 1999/01/14 17:21:24 chen + * CDEV Class and API Spec Class for WIN32 + * + * + */ +#ifndef _CDEV_SPEC_H +#define _CDEV_SPEC_H + +#if defined (_WIN32) + +#if !defined (DLLIMPORT) +#define DLLIMPORT __declspec(dllimport) +#endif + +#if !defined (DLLEXPORT) +#define DLLEXPORT __declspec(dllexport) +#endif + +#if defined (_CDEV_CORE_EXPORTS_) +#define CDEVAPI DLLEXPORT +#define CDEV_CLASS_SPEC DLLEXPORT +#define CDEVSVC_CLASS_SPEC +#define CDEVSVCAPI +#elif defined (_CDEV_BUILD_SVC) +#define CDEVAPI DLLIMPORT +#define CDEV_CLASS_SPEC DLLIMPORT +#define CDEVSVC_CLASS_SPEC DLLEXPORT +#define CDEVSVCAPI DLLEXPORT +#else +#define CDEVAPI DLLIMPORT +#define CDEV_CLASS_SPEC DLLIMPORT +#define CDEVSVC_CLASS_SPEC +#define CDEVSVCAPI +#endif + +#else /* WIN32 */ + +#define CDEVAPI +#define DLLIMPORT +#define DLLEXPORT +#define CDEV_CLASS_SPEC +#define CDEVSVC_CLASS_SPEC +#define CDEVSVCAPI + +#endif + +#endif + diff --git a/include/cdevStrHash.h b/include/cdevStrHash.h new file mode 100644 index 0000000..bde8d6f --- /dev/null +++ b/include/cdevStrHash.h @@ -0,0 +1,138 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606 +// Email: coda@cebaf.gov Tel: (804) 249-7101 Fax: (804) 249-7363 +//----------------------------------------------------------------------------- +// +// Description: +// cdevStrHash: cdev hash table keyed by a variable length string +// Open Hash with buckets implemented by single linked lists +// +// Note: void *s are stored inside the table. This class +// will not manage these pointers. Callers have to +// manage these pointers +// +// Note: this is unsafe C++ practice. Use at your own risk +// +// Reason: It is so difficult to use a template class inside +// a shared library. (Cfront based C++ compiler cannot +// instantiate a template class during compilation time +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// Revision History: +// cdevStrHash.h,v +// Revision 1.3 1996/08/26 21:12:38 akers +// Added getData method to iterator +// +// Revision 1.2 1995/07/05 18:38:30 chen +// add simple str hash function +// +// Revision 1.1 1995/06/30 15:08:42 chen +// string hash table +// +// +#ifndef _CDEV_STR_HASH_H +#define _CDEV_STR_HASH_H + +#include + +//====================================================================== +// One simple string hash function +// This hash function is used in cdevDevice and caChannel. +// It returns integer value between 0 to MAX_INTEGER_VALUE +// and this value will be moded with the size of the hash +// table. +// It may be changed to a different hash function in +// release 1.1 +//====================================================================== +extern CDEVAPI unsigned int cdevStrHashFunc (char *str); + +typedef char* cdevKeyItem; +typedef void* cdevHashItem; + +//====================================================================== +// class cdevStrHash +// collection of buckets indexed by hashed values +//====================================================================== +class cdevStrHashIterator; + +class CDEV_CLASS_SPEC cdevStrHash +{ +public: + // constructor + // construct a table with entry max and hash function *f + // hash function return any integer from 0 to MAX_INT_VALUE + cdevStrHash (unsigned int max, unsigned int (*f)(cdevKeyItem)); + // destructor + virtual ~cdevStrHash (void); + + // operations + + // is the table empty: return 1: yes. return 0: no + virtual int isEmpty(); + + // clear the elements of the set + virtual void deleteAllValues(); + + // add an element to the collection + virtual void add (cdevKeyItem key, cdevHashItem ele); + + // test to see whether this hash table includes one particular element + virtual int find (cdevKeyItem key, cdevHashItem ele) const; + + // remove an element. return 0: ele is not inside table. return 1: success + virtual int remove (cdevKeyItem key, cdevHashItem ele); + + // return a reference to a particular bucket according to the key + cdevSlist& bucketRef (cdevKeyItem key); + + protected: + friend class cdevStrHashIterator; + + // the actual table itself is a vector of buckets + const unsigned int tablesize; + cdevSlist* buckets; + + // convert key into unsigned integer value in range + unsigned int hash(const cdevKeyItem& key) const; + + private: + unsigned int (*hashCode_)(cdevKeyItem); +}; + +//====================================================================== +// class cdevStrHashIterator +// iterator protocol for hash tables +//====================================================================== +class CDEV_CLASS_SPEC cdevStrHashIterator +{ +public: + // constructor and destructor + cdevStrHashIterator (cdevStrHash& v); + ~cdevStrHashIterator (void); + + // iterator protocol + int init (void); + cdevHashItem operator ()(void); + cdevHashItem getData (void); + int operator ! (void); + int operator ++(void); + void operator = (cdevHashItem value); + +protected: + cdevStrHash& base; + unsigned int currentIndex; + // Single iterator within a bucket + cdevSlistIterator* itr; + // getNextIterator used to set internal iterator pointer + // return 1: got it. return 0: no more iterator + int getNextIterator (void); +}; +#endif diff --git a/include/cdevSvcFinder.h b/include/cdevSvcFinder.h new file mode 100644 index 0000000..871983e --- /dev/null +++ b/include/cdevSvcFinder.h @@ -0,0 +1,67 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevSvcFinder class (Bind a service from a service name) +// +// Author: Jie Chen +// +// Revision History: +// cdevSvcFinder.h,v +// Revision 1.5 1997/08/18 14:16:31 akers +// Ongoing development of CDEV accounting +// +// Revision 1.4 1997/08/15 18:08:33 akers +// Addition of CDEV Accounting +// +// Revision 1.3 1995/09/20 16:22:21 chen +// Change findService to virtual +// +// Revision 1.2 1995/06/30 16:01:35 chen +// use generic list +// +// Revision 1.1.1.1 1995/06/16 17:14:07 epics +// initial import of cdev +// +// +#ifndef _CDEV_SVC_FINDER_H +#define _CDEV_SVC_FINDER_H + +#include +#include +#include + +class CDEV_CLASS_SPEC cdevSvcFinder +{ + public: + //constructor and destrcutor + cdevSvcFinder(cdevSystem & system = cdevSystem::defaultSystem()); + ~cdevSvcFinder (void); + + int getService(char *serviceName, cdevService* &service); + // PURPOSE: get or load a service into system + // REQUIRE: serviceName != 0 and callers provide pointer service + // PROMISE: return 0: service loaded. return -1: failure + + private: + // deny assignment and copy + cdevSvcFinder (const cdevSvcFinder& src); + cdevSvcFinder& operator = (const cdevSvcFinder& src); + // internal functions + +#ifdef SHOBJ + cdevService *loadService (char *serviceName); +#else + virtual cdevService *findService (char *serviceName); +#endif + // data area + cdevSlist ldList_; + cdevSystem& system_; +}; +#endif diff --git a/include/cdevSync.h b/include/cdevSync.h new file mode 100644 index 0000000..7751454 --- /dev/null +++ b/include/cdevSync.h @@ -0,0 +1,139 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevSync class (abstract base class) +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevSync.h,v +// Revision 1.3 1997/02/18 15:45:43 chen +// port to linux 2.0.x + addUserFdCallback +// +// Revision 1.2 1996/03/22 17:57:45 chen +// change attach/detach ReadFd to virtual +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#ifndef _CDEV_SYNC_H +#define _CDEV_SYNC_H + +#include +#include +#include +#include +#include + +class CDEV_CLASS_SPEC cdevSync{ + public: + // destructors + virtual ~cdevSync (void); + + virtual int flush (void) = 0; + // PURPOSE: pure virtual function to define intreface for net flush + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS + + virtual int poll (void) = 0; + // PURPOSE: pure virtual function to define intreface for polling method + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS: OK. return -1: network error + + virtual int pend (int fd = -1) = 0; + // PURPOSR: pure virtual function to define interface for pending method + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS, OK, return -1: network error + + virtual int pend (double seconds, int fd = -1) = 0; + // PURPOSR: pure virtual function to define interface for pending method + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS, OK, return CDEV_TIMEOUT: timeout. + // -1: network error + + virtual const char *className (void) const {return "cdevSync";} + + protected: + // constructor + cdevSync (void); + + virtual int attachReadFd (int fd); + // PURPOSE: add a new file descriptor to mask + // REQURIE: fd > 3. You know what I mean + // PROMISE: return 0 success + + virtual int detachReadFd (int fd); + // PURPOSE: remove a file descriptor from the mask + // REQUIRE: fd > 3 + // PROMISE: return 0 success + + int handleEvents (void); + // PURPOSE: wait until IO events arrive and dispatch IO events + // REQUIRE: nothing + // PROMISE: return 0: success, -1: error + + virtual int handleEvents (cdevTimeValue *tv); + // PURPOSE: handle IO events for upto 'tv' long + // REQUIRE: nothing + // PROMISE: return 0: success at least one IO event occured, 1: timeout + + int waitFor (cdevFdSet &rmaskret, + cdevFdSet &wmaskret, + cdevFdSet &emaskret, + cdevTimeValue *how_long); + // PURPOSE: Wait for IO events to occur upto time 'how_long' + // REQUIRE: nothing + // PROMISE: >0 IO event ready. 0 nothing, timeout + + void dispatch (int nfound, + cdevFdSet &rmaskret, + cdevFdSet &wmaskret, + cdevFdSet &emaskret); + // PURPOSE: dispath IO events to the appropriate service + // REQUIRE: nothing + // PROMISE: dispatched + + virtual void notifyService (int handle); + // PURPOSE: notify low level service there are IO events + // REQUIRE: derived class does real implementation + // PROMISE: nothing + + int handleError (void); + // PURPOSE: handle interrupt error while waiting for IO events + // REQUIRE: nothing + // PROMISE: return 1: interrupt or bad file descriptor, return -1: error + + int checkFds (void); + // PURPOSE: check whether file descriptors are valid + // REQUIRE: nothing + // PROMISE: return 1 always + + int checkFd (int fd); + // PURPOSE: check whether file descriptor fd is valid + // REQUIRE: nothing + // PROMISE: return 0 success, -1, failure + + int maxHandle (int i, int j, int k); + // PURPOSE: utility to calculate maximum of there integers + // REQUIRE: nothing + // PROMISE: maximum of there integers + + // File Descriptor Mask for IO Multiplexing + cdevFdSet rdMask_; + cdevFdSet wrMask_; + cdevFdSet exMask_; +}; +#endif + + + + + diff --git a/include/cdevSystem.h b/include/cdevSystem.h new file mode 100644 index 0000000..e894d6b --- /dev/null +++ b/include/cdevSystem.h @@ -0,0 +1,466 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevSystem class +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevSystem.h,v +// Revision 1.18 1998/02/13 14:23:06 chen +// add fall through service behaviour +// +// Revision 1.17 1998/02/10 18:05:47 chen +// add add/removeTimer to the system +// +// Revision 1.16 1997/12/12 16:39:42 chen +// add fix for VMS +// +// Revision 1.15 1997/08/27 18:23:33 chen +// Change error reporting to site specific scheme +// +// Revision 1.14 1997/08/07 13:36:33 akers +// Converted CDEV_MAJOR_VERSION and CDEV_MINOR_VERSION to strings to support adding minor revision numbers +// +// Revision 1.13 1997/03/25 22:24:43 akers +// Development in support of a new cdevDirectory +// +// Revision 1.12 1997/03/03 17:35:47 chen +// add buffering to channel access connection +// +// Revision 1.10 1997/01/29 17:39:38 akers +// Removed assertion from cdevSystem +// +// Revision 1.9 1996/11/21 17:03:34 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.8 1996/09/20 12:24:58 akers +// Changes added for Release 1.4 +// +// Revision 1.7 1996/04/05 22:02:24 chen +// fix static enum problem with gcc +// +// Revision 1.6 1996/03/27 16:03:10 akers +// Added CDEV_MAJOR_VERSION and CDEV_MINOR_VERSION to the cdevSystem object +// +// Revision 1.5 1996/03/22 17:57:00 chen +// add cdevFdChangedCallback +// +// Revision 1.4 1995/10/05 18:40:45 chen +// Move destructor to public, static needs it +// +// Revision 1.3 1995/07/05 18:45:41 chen +// allow access to devices etc... +// +// Revision 1.2 1995/06/30 16:06:26 chen +// remove all unnecessary files and use a genric list and hash +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#ifndef _CDEV_SYSTEM_H +#define _CDEV_SYSTEM_H + +#include +#include +#include +#include +#include +#include + +#ifdef __VMS +extern "C" { +char* strdup (char *s); +char* mkstemp (char *s); +int htonl (int a); +int ntohl (int a); +}; +#endif + +class cdevService; +class cdevDevice; +class cdevRequestObject; +class cdevErrReqObject; +class cdevDirectory; +class cdevGroup; +class cdevExecGroup; +class cdevSvcFinder; +class cdevTranObj; +class cdevCallback; +class cdevErrSvc; +class cdevConfigFinder; + +// maximum number of groups inside a system +const int MAX_NUM_GROUPS = 5; + +// file descriptor changed callback +// opened = 1, newly opend fd, opened = 0, closed fd +typedef void (*cdevFdChangedCallback) (int fd, int opened, + void *arg); + +// arbitrary user fd callback (user let cdev to minitor his/her's fd) +// opened = 1, ok, opened = 0, fd is bad fd +// user should return 0: for success reading, -1: for failure +typedef int (*cdevUserFdCallback) (int opened, int fd, void *arg); + +// define user fd callback handler id +typedef long cdevUserFdCbkId; + + +class CDEV_CLASS_SPEC cdevSystem: public cdevSystemBase +{ +public: + // *************************************************************************** + // * The CDEV_MAJOR_VERSION and CDEV_MINOR_VERSION variables are used to + // * identify the version of CDEV shared objects that should be used. + // *************************************************************************** + + // WARNING: these two strings are deprecated in 1.7.x, and will be + // removed in 1.8, and replace with a single version string. + + static const char *CDEV_MAJOR_VERSION; + static const char *CDEV_MINOR_VERSION; + + //============================================================== + // Public interface for clients + //============================================================== + static cdevSystem& attachRef (char *name, char *prefix = 0); + static cdevSystem* attachPtr (char *name, char *prefix = 0); + // PURPOSE: cdevSystem creation factory + // REQUIRE: nothing + // PROMISE: return system reference or pointer + + cdevDevice* getDevice (char *device); + // PURPOSE: create a cdevDevice + // REQUIRE: device != 0 + // PROMISE: return a pointer to a cdevDevice + + char *name (void) const; + // PURPOSE: return name of this system + // REQUIRE: callers don't free memory + // PROMISE: name of this system + + char *prefix (void) const; + // PURPOSE: return prefix of this system + // REQUIRE: callers don't free memory + // PROMISE: prefix of this syste, + + void prefix (char *pre); + // PURPOSE: set prefix to this system + // REQUIRE: pre != 0 + // PROMISE: old prefix will be overwritten by new one + + virtual int flush (void); + // PURPOSE: flush all network request to all services + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS + + virtual int poll (void); + // PURPOSE: poll all network services + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS + + virtual int pend (int fd = -1); + // PURPOSE: pend all network services and dispatch IO event to right services + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS + + virtual int pend (double seconds, int fd = -1); + // PURPOSE: pend all network services for 'seconds' time long. + // Dispatch IO event to right services + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS or CDEV_TIMEOUT + + static cdevSystem &defaultSystem (void); + // PURPOSE: Caller access to default system which is created automatically + // REQUIRE: nothing + // PROMISE: return the same system everytime one calls this + + void finalize (void); + // PURPOSE: clean up all system resources + // REQUIRE: last routine to call before quitting + // PROMISE: nothing + + int getFd (int fd[], int &numFD); + // PURPOSE: provide file descriptors to other system such as X window + // REQUIRE: user provide big enough integer buffer and buffer size + // PROMISE: numFD is real number of fds of success return CDEV_SUCCESS. + // return CDEV_INVALIDARG: not big enoght buffer + + int addFdChangedCallback (cdevFdChangedCallback cbk, void* arg); + // PURPOSE: provide file descriptor callback mechanism + // REQUIRE: none + // PROMISE: if lower cdevServices provide system any notification of + // fd changes, the system will call all registered callbacks + + int addUserFdCallback (int fd, cdevUserFdCallback cbk, void* arg, + cdevUserFdCbkId& id); + // PURPOSE: add user fd to system fd list, when there is something + // to be read at this fd, the user callback will be executed + // REQUIRE: none + // PROMISE: if fd is already inside the managed fd list, returns + // CDEV_INVALIDARG. if fd is a bad fd, returns CDEV_IOFAILED. + // CDEV_SUCCESS and valid id will denote a success + + int removeUserFdCallback (cdevUserFdCbkId id); + // PURPOSE: remove a user register fd callback with callback id + // REQUIRE: none + // PROMISE: return CDEV_NOTFOUND, if id is not found. return CDEV_SUCCESS + // if id has been removed (system will close associated fd if it + // is a not bad fd) + + int addTimer (cdevTimerHandler* handler, + const void* arg, + double delay, double interval = 0.0); + // PURPOSE: register a 'handler' that will expire + // after delay amount of seconds. If it expires then is + // passed in the function of handler. If + // interval != 0.0, then this timer becomes a repetitive timer + // with timer interval 'interval'. + // REQUIRE: handler must have a real timerCallback function + // PROMISE: A unique id will be returned. Callers can use this id + // to cancel timer before it expires. + + int removeTimer (cdevTimerHandler* handler); + // PURPOSE: remove timers associated with a 'handler' + // REQUIRE: none + // PROMISE: return CDEV_SUCCESS if all timers are removed. return CDEV_ERROR + // if there is no timer associated with this handler + + int removeTimer (int timerid); + // PURPOSE: remove a timer with timer id 'timerid' + // REQUIRE: none + // PROMISE: return CDEV_SUCCESS if the timer is removed. return CDEV_ERROR + // if this timer is not registered. + + void enableDefaultSvc (void); + void disableDefaultSvc (void); + // PURPOSE: enable/disable using default service if a device msg pair cannot + // match to any services + // REQUIRE: none + // PROMISE: + + int defaultSvc (void) const; + // PURPOSE: check whether a default service in used if a device msg pair + // cannot match any services + // REQUIRE: none + // PROMISE: return 1 true. return 0 false + + //=================================================================== + // Public interface for internal implementation use + //=================================================================== + virtual int registerService (cdevService *service); + // PURPOSE: register a service to the system + // REQUIRE: service != 0 + // PROMISE: service only be registered once + + virtual int removeService (cdevService *service); + // PURPOSE: remove this service from the system + // REQUIRE: service != 0 + // PROMISE: service will be removed, but service is sitll valid + + virtual int serviceCreated (char *serviceName); + // PURPOSE: check a service inside the system by name + // REQUIRE: serviceName != 0 + // PROMISE: return 1: found, 0: not found + + cdevService *service (char *serviceName); + // PURPOSE: return a service pointer inside system by name + // REQUIRE: serviceName != 0 + // PROMISE: return cdevService* != 0 on success, return 0: failure + + cdevService *loadService (char *serviceName); + // PURPOSE: load a new service by service name (shared library) + // REQUIRE: serviceName != 0 + // PROMISE: return cdevService* != 0 on success, return 0: failure + + virtual int suspendService (cdevService *service); + // PURPOSE: temprarily suspend service + // REQUIRE: nothing + // PROMISE: not implemented yet + + virtual int resumeService (cdevService *service); + // PURPOSE: resume a suspended service + // REQUIRE: nothing + // PROMISE: not implemented yet + + int registerDevice (cdevDevice *device); + // PURPOSE: register a cdevDevice to the system + // REQUIRE: device != 0 + // PROMISE: device will be registered once, CDEV_SUCCESS: success. + // CDEV_ERROR: already here + + int removeDevice (cdevDevice *); + // PURPOSE: remove a device from the system + // REQUIRE: device != 0 + // PROMISE: return CDEV_SUCCESS: rmoval success. + // return CDEV_ERROR: not here + + int deviceCreated (char *deviceName); + // PURPOSE: check a device created in the system by name + // REQUIRE: deviceName != 0 + // PROMISE: return 1: device is here, return 0: not here + + cdevDevice *device (char *deviceName); + // PURPOSE: return a device in the system by name + // REQUIRE: deviceName != 0 + // PROMISE: return device !=0 on success, return 0: failure + + virtual int getRequestObject (char *deviceName, + char *msg, + cdevRequestObject * &req); + // PURPOSE: get a cdevRequestObject from system by devicename and message + // REQUIRE: deviceName != 0 and msg != 0 + // PROMISE: return CDEV_SUCCESS: success. + // return CDEV_ERROR: failure + + int registerGroup (cdevGroup *grp); + // PURPOSE: register a group into the system + // REQUIRE: grp != 0 + // PROMISE: return CDEV_SUCCESS: success, CDEV_ERROR: already here + + int removeGroup (cdevGroup *grp); + // PURPOSE: remove a group from the system + // REQUIRE: grp != 0 + // PROMISE: return CDEV_SUCCESS: removal success. + // return CDEV_ERROR: not here. grp is still valid. + + int registerActiveGroup (cdevGroup *grp); + // PURPOSE: register an active group (group stared) + // REQUIRE: grp != 0 + // PROMISE: return CDEV_SUCCESS: success, + // CDEV_ERROR: already here + + int removeActiveGroup (cdevGroup *grp); + // PURPOSE: remove an active group + // REQUIRE: grp != 0 + // PROMISE: return CDEV_SUCCESS: success. + // return CDEV_ERROR: not here. grp is still valid + + int activeGroups (cdevGroup **grps, int& numGroups); + // PURPOSE: return active groups inside the system + // REQUIRE: callers provide memory for grps (eg. grps = new cdevGroup*[5]) + // or cdevGroup grps[5]. numGroups is the buffer size of grps. + // callers don't free grps[i] which is a pointer to internal rep. + // PROMISE: numGrps is the real number of active groups + + int activeGroups (void) const; + // PURPOSE: check whether there are any active groups + // REQUIRE: nothing + // PROMISE: 1: yes, 0: no + + cdevDirectory& nameServer (void); + // PURPOSE: default name server + // REQUIRE: nothing + // PROMISE: always here + + cdevRequestObject *errorRequestObject (void); + // PURPOSE: return default error request object in case of error + // REQUIRE: nothing + // PROMISE: return error request object + + void errorRequestObject (cdevRequestObject *obj); + // PURPOSE: set default error request object in case of error + // REQUIRE: nothing + // PROMISE: default error request object will be set + + virtual ~cdevSystem (void); + +protected: + // constructor and destructor + cdevSystem (char *systemName, char *prefix = 0); + + // redefine attach/detach file descriptor to notify callback if there + // any of them + virtual int attachReadFd (int fd); + virtual int detachReadFd (int fd); + + // setup the read mask in preparation for pend operation. + void setupMask ( void ); + + // free all memory + void freeMemory (void); + // interface to system collection + static int remove (cdevSystem *); + + // handle network I/O events + virtual int handleEvents (cdevTimeValue* tv); + + // calculate time out according to user request maximum timeout + // and timer queue earliest timeout + // returned pointer is a pointer to a static value + cdevTimeValue* calculateTimeOut (cdevTimeValue* maxtimeout); + + // notify lower level service object + virtual void notifyService (int handle); + // get individul service from file descriptor + cdevService *getService (int handle); + +private: + // data area + cdevSlist serviceList_; + // hash table keep track all devices which are keyed by device name + cdevStrHash deviceList_; + // group list inside the system + cdevSlist groupList_; + // active group list inside the system + cdevSlist activeGroupList_; + // system list + static cdevSlist& systemList_ (void); + // flag to denote there are some active groups + int activeGrps_; + // this system name + char *systemName_; + // prefix name for this system + char *prefix_; + // default name server, cdevDirectory for now + cdevDirectory *ns_; + // cdevService name binding mechanism + cdevSvcFinder *svcFinder_; + // cdev site configuraton loader + cdevConfigFinder *configFinder_; + // Reference counting + int refCount_; + // callback list for fdChangedCallback + cdevSlist fdCbkList_; + cdevSlist fdCbkArgList_; + // timer queue + cdevTimerQueue timerQueue_; + // fall through to a default service or not if no service is found + int defaultSvc_; + + //==================================================== + // The followings are for linked editor. + // Try to trick the link editor to load those symbols + // which otherwise will not be exported to library + //==================================================== + // default cdevServiceError handler object + cdevService *errSvcObj_; + // touch cdevTranObj class and alot of more + cdevTranObj *defXobj_; + // touch cdevCallback class + cdevCallback *defCallbackObj_; + // default requestobject error handle object + cdevRequestObject *errObj_; + // an empty cdevExecGroup object + cdevExecGroup* egroup_; + //=================================================== + // Deny access since memeber-wise copy will not work + // since this system is actually a memory manager + //=================================================== + cdevSystem (const cdevSystem &); + cdevSystem& operator = (const cdevSystem &); + // friend class declaration + friend class cdevService; + friend class cdevErrReqObject; +}; + +#endif diff --git a/include/cdevSystemBase.h b/include/cdevSystemBase.h new file mode 100644 index 0000000..786efa3 --- /dev/null +++ b/include/cdevSystemBase.h @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevSystemBase class (abstract class) +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevSystemBase.h,v +// Revision 1.2 1996/05/28 13:00:12 chen +// minor changes +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#ifndef _CDEV_SYSTEM_BASE +#define _CDEV_SYSTEM_BASE + +#include "cdevError.h" +#include "cdevSync.h" + +class CDEV_CLASS_SPEC cdevSystemBase: public cdevSync, public cdevError +{ + public: + virtual ~cdevSystemBase (void); + // PURPOSE: destructor for cdevSystemBase + // REQUIRE: nothing + // PROMISE: it will be gone + + virtual char *name (void) const = 0; + // PURPOSE: pure virtual function + // REQUIRE: derived class provides real implementation + // PROMISE: nothing + + virtual int getRequestObject (char *deviceName, + char *msg, + cdevRequestObject* &req) = 0; + // PURPOSE: pure virtual function + // REQUIRE: callers provide pointer to cdevRequestObject only, no memory + // PROMISE: nothing + virtual const char *className (void) const {return "cdevSystemBase";} + + protected: + //constructor, deny direct instantiation + cdevSystemBase (void); +}; +#endif + diff --git a/include/cdevTagTable.h b/include/cdevTagTable.h new file mode 100644 index 0000000..c8c2de5 --- /dev/null +++ b/include/cdevTagTable.h @@ -0,0 +1,191 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//------------------------------------------------------------------------------ +// +// description: cdevTagTable.h +// cdevTagTable class manages tags within the cdev system. +// +// Author: Danjin Wu & Walt Akers +// +// Revision History: +// cdevTagTable.h,v +// Revision 1.12 1997/08/01 19:06:30 akers +// Added addTag and tagExists feature to the library +// +// Revision 1.11 1996/10/25 20:10:02 chen +// add asciiDump +// +// Revision 1.10 1996/08/26 19:14:07 akers +// Adding cdevData.inserttag callback capabilities +// +// Revision 1.9 1996/07/17 13:57:56 chen +// using CDEVTAGTABLE to find tags +// +// Revision 1.8 1995/10/03 19:37:11 chen +// Change back to object instead of pointers +// +// Revision 1.7 1995/09/29 15:25:55 danjin +// declare hash entry as pointer +// +// Revision 1.6 1995/09/28 19:01:48 danjin +// change: declare a ptr to list -> declare a list +// +// Revision 1.5 1995/08/21 18:02:48 danjin +// empty message +// +// Revision 1.3 1995/08/21 16:40:23 danjin +// modify comment +// +// Revision 1.2 1995/08/21 16:38:10 danjin +// modified big partion of this file +// +// Revision 1.1 1995/08/21 15:47:24 danjin +// merge Slist and hash into one for cdev +// +// +// +#ifndef _CDEV_TAG_TABLE_H +#define _CDEV_TAG_TABLE_H + +#include +#include +#include +#include + + +// ***************************************************************************** +// * class cdevTagTableCallback : +// * This class is used by the caller to post a callback to be notified +// * when changes are posted to a cdevTagTable. The class also has +// * a next pointer to allow it to be placed in a linked list within the +// * cdevTagTable... +// * +// * Note: Since this is a abstract base class, the caller must create a +// * class based on this class that has the callback method defined... +// * Also the destructor here is defined as virtual to force the delete +// * mechanism to work its way up the class hierarchy to the top level +// * before calling the destructor... +// ***************************************************************************** +class CDEV_CLASS_SPEC cdevTagTableCallback +{ +friend class cdevTagTable; +private: + cdevTagTableCallback *next_; +public: + cdevTagTableCallback ( void ) : next_(NULL) {} + virtual ~cdevTagTableCallback (void) {} + virtual void callback (int newTag, char *newName) = 0; +}; + + +struct cdevTagEle { + char *tagName; + int tagId; +}; +typedef struct cdevTagEle cdevTagEle; + +class CDEV_CLASS_SPEC cdevTagTable +{ +public: + cdevTagTable ( void ); + + ~cdevTagTable ( void ) + { + freeMemory (); +#ifdef _CDEV_DEBUG + printf("Destroying a cdevTagTable object\n"); +#endif + } + + int tagC2I (char* ctag, int* tag); + int tagI2C (int tag, char* &ctag); + void insertTag (int tag, char* ctag); + int tagExists (char *ctag); + int tagExists (int tag); + int addTag (char *ctag); + + // ************************************************* + // * addTagCallback : + // * This method will add a cdevTagTableCallback + // * object to the list of classes that should be + // * notified each time a tag is added to the + // * cdevTagTable. + // ************************************************* + void addTagCallback ( cdevTagTableCallback * cb ); + + // ************************************************* + // * delTagCallback : + // * This method will remote a cdevTagTableCallback + // * object that was previously added to the list + // * of callback classes. + // * + // * Note: This method does not actually delete + // * the cdevTagTableCallback object, it + // * merely removes it from the list. It + // * is the responsibility of the owner to + // * delete the object when it is no longer + // * needed. + // ************************************************* + void delTagCallback ( cdevTagTableCallback * cb ); + + // ************************************************* + // * readTagTable : + // * This method allows the caller to obtain a list + // * of tag names and integers that are currently + // * stored in this tag table. + // * + // * Note: This method will allocate an array of + // * integers and an array of character + // * string pointers. The strings that + // * are stored in the string array will be + // * the actual strings from within the + // * tag table and should not be deleted... + // * + // * The data allocated becomes the property + // * of the caller and must be deleted when + // * it is no longer needed... the correct + // * syntax to delete these items is... + // * + // * delete tags; + // * delete ctags; + // * + // * This will delete the array, however, + // * it will leave the individual array + // * elements intact. + // ************************************************* + int readTagTable ( int * &tags, char ** &ctags, int &ntags ); + + // ************************************************* + // * asciiDump (FILE* fp = stdout); + // * dump information of tag table to a file with two columns + // * left column is tag value, right column is tag string + // ************************************************* + void asciiDump (FILE* fp = stdout); + +protected: + void freeMemory (void); + void initialize ( void ); + // data area + cdevIntHash itagList_; + cdevStrHash stagList_; + cdevTagTableCallback * callbacks_; + int highestTag; + +private: + // default tag name if there is no tag file + static char* defaultTags[]; + static unsigned int numberDefTags; + static char* defaultTagTableLocation; + static char* tagTableEnv; + + // parse tag table file, return 0: failure, return 1: success + // caller free all memory upon success + static int parseTagTable (char* file, char** &tags, int* &tagvalues, + unsigned int &numTags); +}; +#endif /* _CDEV_TAG_TABLE_H */ + diff --git a/include/cdevTimeValue.h b/include/cdevTimeValue.h new file mode 100644 index 0000000..57cc03c --- /dev/null +++ b/include/cdevTimeValue.h @@ -0,0 +1,86 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// C++ Class for timeval structure +// +// Author: Jie Chen +// +// Revision History: +// cdevTimeValue.h,v +// Revision 1.2 1998/02/10 18:04:57 chen +// add cdevSystem timer handler +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#ifndef _CDEV_TIME_VALUE_H +#define _CDEV_TIME_VALUE_H + +#include +#include + +#ifdef _WIN32 + #include + #include + #include +#else + #include +#endif + +class CDEV_CLASS_SPEC cdevTimeValue +{ + public: + cdevTimeValue (long sec = 0, long usec = 0); + cdevTimeValue (double sec); +#ifdef _WIN32 + cdevTimeValue (const struct _timeb &t); +#endif + cdevTimeValue (const timeval &t); + cdevTimeValue (const cdevTimeValue &tv); + cdevTimeValue& operator = (const cdevTimeValue& tv); + +#ifdef _WIN32 + void set (const struct _timeb &t); +#endif + + void set (const timeval &t); + long sec (void) const; + void sec (long sec); + long usec (void) const; + void usec (long usec); + operator double () const; +#ifdef _WIN32 + operator struct _timeb () const; +#endif + operator timeval () const; + + void operator += (const cdevTimeValue& val); + void operator -= (const cdevTimeValue& val); + + friend cdevTimeValue operator + (cdevTimeValue tv1, cdevTimeValue tv2); + friend cdevTimeValue operator - (cdevTimeValue tv1, cdevTimeValue tv2); + friend int operator < (cdevTimeValue tv1, cdevTimeValue tv2); + friend int operator > (cdevTimeValue tv1, cdevTimeValue tv2); + friend int operator <= (cdevTimeValue tv1, cdevTimeValue tv2); + friend int operator >= (cdevTimeValue tv1, cdevTimeValue tv2); + friend int operator == (cdevTimeValue tv1, cdevTimeValue tv2); + friend int operator != (cdevTimeValue tv1, cdevTimeValue tv2); + + static const cdevTimeValue zero; + static cdevTimeValue currentTime (void); + + private: + void normalize (void); + + long tv_sec_; + long tv_usec_; +}; +#endif diff --git a/include/cdevTimerHandler.h b/include/cdevTimerHandler.h new file mode 100644 index 0000000..23a5fc0 --- /dev/null +++ b/include/cdevTimerHandler.h @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevTimerHandler Class +// +// This class is a base class for handling timer based event. +// Derived classes implement the real function. +// +// Author: Jie Chen +// +// Revision History: +// cdevTimerHandler.h,v +// Revision 1.1 1998/02/10 18:04:57 chen +// add cdevSystem timer handler +// +// +// +#ifndef _CDEV_TIMER_HANDLER_H +#define _CDEV_TIMER_HANDLER_H + +#include + +class cdevTimerHandler +{ +public: + // constructor + cdevTimerHandler (void) {} + // destructor + virtual ~cdevTimerHandler (void) {} + + virtual int timerCallback (double /* time */, + const void* /* arg */ = 0) {return 0;} + // PURPOSE: this function is called when timer is expired + // REQUIRE: none + // PROMISE: if return -1: all timers associated with this handler + // will be removed. return 0: everything is ok. + + virtual const char* className (void) const {return "cdevTimerHandler";} + +private: + // deny access to copy and assignment operator + cdevTimerHandler (const cdevTimerHandler& handler); + cdevTimerHandler& operator = (const cdevTimerHandler& handler); + +}; +#endif diff --git a/include/cdevTimerQueue.h b/include/cdevTimerQueue.h new file mode 100644 index 0000000..0718a3d --- /dev/null +++ b/include/cdevTimerQueue.h @@ -0,0 +1,128 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevTimerQueue Class +// +// Author: Jie Chen +// +// Revision History: +// cdevTimerQueue.h,v +// Revision 1.1 1998/02/10 18:04:58 chen +// add cdevSystem timer handler +// +// +// +#ifndef _CDEV_TIMER_QUEUE_H +#define _CDEV_TIMER_QUEUE_H + +#include +#include +#include + +class cdevTimerQueue; + +class cdevTimerQNode +{ +private: + + friend class cdevTimerQueue; + + cdevTimerQNode (cdevTimerHandler* h, + const void* arg, + const cdevTimeValue& t, + const cdevTimeValue& i, + int id); + + // data area + cdevTimerHandler* handler_; + + // user argument + const void* arg_; + + // first time interval to expire + cdevTimeValue timer_; + + // timer interval: if this is not zero this holds the time until the next + // timeout + cdevTimeValue interval_; + + // int timer id + int tid_; +}; + + +class CDEV_CLASS_SPEC cdevTimerQueue +{ +public: + // constructor + cdevTimerQueue (void); + // destructor + virtual ~cdevTimerQueue (void); + + int isEmpty (void) const; + // PURPOSE: check whether this queue is empty or not + // REQUIRE: nothing + // PROMISE: return 1, empty, 0, not empty + + const cdevTimeValue& earliestTime (void) const; + // PURPOSE: return earliestTime in the timer queue + // REQUIRE: nothing + // PROMISE: time value denoted the earliest time in the queue + + int scheduleTimer (cdevTimerHandler* handler, + const void* arg, + const cdevTimeValue& delay, + const cdevTimeValue& interval = cdevTimeValue::zero); + // PURPOSE: Schedule an that will expire after + // amount of time. If it expires then is passed in as the value to + // the 's callback method. If + // is != to then it is used to + // reschedule the automatically. This method + // returns a timer handle that uniquely identifies the + // in an internal list. This timer handle can be + // used to cancel an before it expires. The + // cancellation ensures that timer_ids are unique up to values of + // greater than 2 billion timers. As long as timers don't stay + // around longer than this there should be no problems with + // accidentally deleting the wrong timer. + + int cancel (cdevTimerHandler* handler); + // PURPOSE: cancel all timers associated with handler + // REQUIRE: handler != 0 + // PROMISE: all timer is canceled. return 0 + + int cancel (int id); + // PURPOSE: cancel a single timer with id + // REQUIRE: id must be valid + // PROMISE: if id is found, the timer is canceled. + + int expire (const cdevTimeValue& current_time); + // PURPOSE: run the method for all timers whose values are + // <= current_time + +private: + void reschedule (cdevTimerQNode* node); + // reschedule a "interval" timer + + cdevSlist queue_; + // real linked list as a queue + + int timerId_; + // run time timer id +}; +#endif + + + + + + + + diff --git a/include/cdevTranObj.h b/include/cdevTranObj.h new file mode 100644 index 0000000..6feb196 --- /dev/null +++ b/include/cdevTranObj.h @@ -0,0 +1,112 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdev Transaction Object class (for service developer only) +// +// Author: Jie Chen +// +// Revision History: +// cdevTranObj.h,v +// Revision 1.4 1996/05/02 14:17:44 chen +// handle unfinished transaction +// +// Revision 1.3 1995/12/08 15:35:57 chen +// handle deferred mode +// +// Revision 1.2 1995/10/03 19:34:52 chen +// disable/enable deleting callback +// +// Revision 1.1.1.1 1995/06/16 17:14:07 epics +// initial import of cdev +// +// +#ifndef _CDEV_TRANOBJ_H +#define _CDEV_TRANOBJ_H + +#include +#include +#include +#include +#include +#include + +class cdevGroup; +class cdevRequestObject; + +class CDEV_CLASS_SPEC cdevTranObj +{ +public: + // constructors and destructor + cdevTranObj (void); + cdevTranObj (cdevSystem *sys, + cdevRequestObject *reqObj, + cdevData *data, + cdevCallback *callback); + ~cdevTranObj (void); + + int status (void) const; + // PURPOSE: return status of transaction object + // REQUIRE: nothing + // PROMISE: -1: not registered into any group, 1: registered into groups + + int operator == (const cdevTranObj& rsc); + int operator != (const cdevTranObj& rsc); + // PURPOSE: equality operator + // REQUIRE: nothing + // PROMISE: obvious + + int removeFromGrps (void); + // PURPOSE: remove this transaction object from all groups + // REQUIRE: nothing + // PROMISE: status = -1 + + void disableDeleteCbk (void); + void enableDeleteCbk (void); + // PURPOSE: enable/disable delete callback flag + // REQUIRE: nothing + // PROMISE: you know + + void trash (cdevGroup* grp); + int isTrash (void) const; + // PURPOSE: throw this transaction object into a trash dump + // REQUIRE: nothing; + // PROMISE: this transaction object will not attempt to call any callback + // function + + // data area for requestObject to access + cdevSystem *system_; + cdevRequestObject *reqObj_; + cdevData *resultData_; + cdevCallback *userCallback_; + int status_; + cdevGroup *activeGroups_[MAX_NUM_GROUPS]; + int numGroups_; + // pointer entries to all active groups + cdevTranObj **entryPtr_[MAX_NUM_GROUPS]; + + const char *className (void) const {return "cdevTranObj";} + +private: + // deny copy and assignment operation + // It makes no sense for two identical transaction objects + cdevTranObj (const cdevTranObj& rsc); + cdevTranObj& operator = (const cdevTranObj& rsc); + + // flag of deleting callback or not. + // Reason: callback may need stay after the transaction object goes away + int deleteCallback_; + + // flag of garbage transaction object (do not care any callbacks) + int trash_; + + // friend class + friend class cdevGroup; +}; +#endif diff --git a/include/cdevTypes.h b/include/cdevTypes.h new file mode 100644 index 0000000..2a675cd --- /dev/null +++ b/include/cdevTypes.h @@ -0,0 +1,65 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 1991,1992 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + *---------------------------------------------------------------------------- + * + * description: cdevDataEntry.h + * Self describing data class. Designed to hold individual tagged data + * items within a cdevData class. + * + * Author: Walt Akers & Danjin Wu + * + * Revision History: + * cdevTypes.h,v + * Revision 1.5 1998/03/10 19:57:39 chen + * change to C style comment + * + * Revision 1.4 1998/03/10 18:54:27 chen + * cdevTypes.h + * + * Revision 1.3 1995/09/06 18:35:11 danjin + * added time stamp structure type + * + * Revision 1.2 1995/07/14 13:25:32 akers + * Header files added to support the changes specified at June 95 Review + * + * + * + */ +#ifndef _CDEV_TYPES_H +#define _CDEV_TYPES_H + +#include + +typedef unsigned char BYTE; + +enum cdevDataTypes + { + CDEV_BYTE, + CDEV_INT16, + CDEV_UINT16, + CDEV_INT32, + CDEV_UINT32, + CDEV_FLOAT, + CDEV_DOUBLE, + CDEV_STRING, + CDEV_TIMESTAMP, + CDEV_INVALID + }; + +typedef struct + { + size_t offset; + size_t length; + } cdevBounds; + +/* cdev time struct */ +typedef struct { + unsigned long secPastEpoch; /* seconds since Jan. 1, 1970 */ + unsigned long nsec; /* nanoseconds within second */ +} cdev_TS_STAMP; + +#endif diff --git a/include/cdevUserFdService.h b/include/cdevUserFdService.h new file mode 100644 index 0000000..0af4c40 --- /dev/null +++ b/include/cdevUserFdService.h @@ -0,0 +1,105 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevFdServive (Arbitrary user file descriptor service) +// +// Author: Jie Chen +// +// Revision History: +// cdevUserFdService.h,v +// Revision 1.1 1997/02/18 15:45:48 chen +// port to linux 2.0.x + addUserFdCallback +// +// +// +#ifndef _CDEV_USER_FD_SERVICE_H +#define _CDEV_USER_FD_SERVICE_H + +#include + +class cdevUserFdService: public cdevService +{ +public: + cdevUserFdService (int fd, cdevUserFdCallback cbk, void* arg, + char* name, + cdevSystem& system = cdevSystem::defaultSystem () + ); + // PURPOSE: construction of fdService + // REQUIRE: none + // PROMISE: A fd servive with a unique name + + ~cdevUserFdService (void); + // PURPOSE: destruction of fdService + // REQUIRE: none + // PROMISE: this object is gone forever + + int getFd (int* &fd, int &numFd); + // PURPOSE: get service's IO file descriptors + // REQUIRE: callers provide pointer (eg. int *fd = 0;) no memory. callers + // should never free memory pointed by fd. fd should be cached + // inside derived class for easy/quick access + // PROMISE: numFd >= 0 + + int getNameServer (cdevDevice* &server); + // PURPOSE: get right name server associated with this service + // REQUIRE: caller provide pointer only, derived class provides + // an empty function for now + // PROMISE: not implemented yet + + int flush (void); + // PURPOSE: pure virtual function to define intreface for net flush + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS + + int poll (void); + // PURPOSE: pure virtual function to define intreface for polling method + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS: OK. return -1: network error + + int pend (int fd = -1); + // PURPOSR: pure virtual function to define interface for pending method + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS, OK, return -1: network error + + int pend (double seconds, int fd = -1); + // PURPOSR: pure virtual function to define interface for pending method + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS, OK, return CDEV_TIMEOUT: timeout. + // -1: network error + + static char* prefixName (void); + // PURPOSE: return common prefix name for all services + // REQUIRE: none + // PROMISE: return common prefix name + + const char *className (void) const {return "cdevUserFdService";} + +protected: + // hide request object creation method + int getRequestObject (char *deviceName, + char *msg, + cdevRequestObject* &req); + // PURPOSE: get request object: this service return 0 + // REQUIRE: callers provide pointer to cdevRequestObject only, no memory + // PROMISE: nothing + +private: + // associated fd + int* fd_; + // user function and usr argument + cdevUserFdCallback cbk_; + void* arg_; + + // unique name for fd services + static char* fdsvcname_; +}; +#endif + + diff --git a/include/cdevVersion.h b/include/cdevVersion.h new file mode 100644 index 0000000..0d619f2 --- /dev/null +++ b/include/cdevVersion.h @@ -0,0 +1,42 @@ +/* +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// CDEV VERSION Information +// +// Author: Jie Chen +// +// Revision History: +// cdevVersion.h,v +// Revision 1.3 1997/12/22 18:23:06 akers +// Ongoing development of 1.6.2 +// +// Revision 1.2 1997/10/17 17:27:18 chen +// set right version number +// +// Revision 1.1 1997/08/27 18:23:33 chen +// Change error reporting to site specific scheme +// +// +// +*/ +#ifndef _CDEV_VERSION_H +#define _CDEV_VERSION_H + +#define CDEV_MAJOR_VERS 1 +#define CDEV_MINOR_VERS 7 +#define CDEV_REVISION 2 + +#define CDEV_VERSION (CDEV_MAJOR_VERS*10000 + CDEV_MINOR_VERS*100 + CDEV_REVISION) + +#define CDEV_VERSION_STRING "1.7.2" + +#endif + diff --git a/include/defCallbackCollector.h b/include/defCallbackCollector.h new file mode 100644 index 0000000..385a6ae --- /dev/null +++ b/include/defCallbackCollector.h @@ -0,0 +1,65 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * defCallbackCollector : This class is used to collect the callbacks from a + * a single cdevDefCollectionRequest. This is an + * implementation class that is only associated with the + * default cdevCollectionObject if the developer's + * service does not provide specific support for + * collections. + * + * The cdevCollectionRequest object will obtain the + * cdevData object from this object and will return it + * to the caller or to an interim + * cdevGrpCollectionRequest object. + * + * Author: Walt Akers + * + * Revision History: + * defCallbackCollector.h,v + * Revision 1.1 1996/11/12 20:32:37 akers + * New collection device source code + * + * ----------------------------------------------------------------------------- + */ + +#ifndef _DEF_CALLBACK_COLLECTOR_H_ +#define _DEF_CALLBACK_COLLECTOR_H_ + +#include +#include +#include + +class defCallbackCollector +{ +public: + typedef struct + { + int index; + int processed; + defCallbackCollector * parent; + } Request; + + int counter; + cdevData result; + cdevData & format; + cdevTranObj * xobj; + Request * requests; + int nRequests; + + defCallbackCollector ( int NRequests, cdevData &Format, cdevTranObj &XObj ); + ~defCallbackCollector ( void ); + int finished ( void ); + void processRequest ( int idx, int status, cdevData *data = NULL ); + void mergeData ( cdevData &to, cdevData &from, int arraySize, int idx); + void copyItemToArray ( cdevData &to, cdevData &from, int tag, int idx); + void installEmptyArray ( cdevData &data, int tag, cdevDataTypes type, int size); +}; + +#endif /* _DEF_CALLBACK_COLLECTOR_H_ */ diff --git a/include/grpCallbackCollector.h b/include/grpCallbackCollector.h new file mode 100644 index 0000000..e7b4015 --- /dev/null +++ b/include/grpCallbackCollector.h @@ -0,0 +1,64 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * grpCallbackCollector : This class is used to collect the callbacks from a + * a group of collections and then compile the results + * into a single cdevData object. + * + * The cdevCollectionRequest object will obtain the + * cdevData object from this object and will return it + * to the caller. + * + * Author: Walt Akers + * + * Revision History: + * grpCallbackCollector.h,v + * Revision 1.1 1996/11/12 20:32:41 akers + * New collection device source code + * + * ----------------------------------------------------------------------------- + */ +#ifndef _GRP_CALLBACK_COLLECTOR_H_ +#define _GRP_CALLBACK_COLLECTOR_H_ + +#include +#include +#include + +class grpCallbackCollector +{ +public: + typedef struct + { + int index; + int elements; + int processed; + grpCallbackCollector * parent; + } Request; + + int counter; + cdevData result; + cdevData & format; + cdevTranObj * xobj; + Request * collections; + int nCollections; + int * requestOrder; + int nRequests; + + grpCallbackCollector (int NCollections, int * RequestOrder, int NRequests, + cdevData &Format, cdevTranObj &XObj); + ~grpCallbackCollector ( void ); + int finished ( void ); + void processCollection ( int idx, int status, cdevData *data = NULL ); + void mergeData ( cdevData &to, cdevData &from, int idx ); + void copyItemsToArray ( cdevData &to, cdevData &from, int tag, int idx ); + void installEmptyArray ( cdevData &data, int tag, cdevDataTypes type, int size ); +}; + +#endif /* _GRP_CALLBACK_COLLECTOR_H_ */ diff --git a/include/makeinclude/Makefile.OS b/include/makeinclude/Makefile.OS new file mode 100644 index 0000000..293b2fe --- /dev/null +++ b/include/makeinclude/Makefile.OS @@ -0,0 +1,2 @@ +SHOBJ=YES +include $(CDEV)/include/makeinclude/Makefile.linux diff --git a/include/makeinclude/Makefile.WINNT-4.0 b/include/makeinclude/Makefile.WINNT-4.0 new file mode 100644 index 0000000..0359b5f --- /dev/null +++ b/include/makeinclude/Makefile.WINNT-4.0 @@ -0,0 +1,189 @@ +TARGET = WINNT +OS_MAJOR = 4 +OS_MINOR = 0 +OS_VERSION_DEF = /D "_OS_MAJOR_=$(OS_MAJOR)" /D "_OS_MINOR_=$(OS_MINOR)" + +!IF "$(DEBUG)" == "" +TARGETDIR = $(TARGET)-$(OS_MAJOR).$(OS_MINOR) +!ELSE +TARGETDIR = $(TARGET)-$(OS_MAJOR).$(OS_MINOR)-DEBUG +!ENDIF + +CDEVVERSION = 1.7.2 +CDEVINCLUDES = /I $(CDEV)\include +CDEVLIB = $(CDEV)\lib\$(TARGETDIR) +CDEVBIN = $(CDEV)\bin\$(TARGETDIR) + +!IF "$(BINDIR)" == "" +BINDIR = $(CDEVBIN) +!ENDIF + +!IF "$(LIBDIR)" == "" +LIBDIR = $(CDEVLIB) +!ENDIF + +!IF "$(CDEVSHOBJ)" == "" +CDEVSHOBJ = $(CDEVLIB) +!ENDIF + +!IF "$(SHOBJ)" == "NO" +OBJDIR = .obj\$(TARGETDIR) +!ELSE +SHOBJ = YES +OBJDIR = .shobj\$(TARGETDIR) +!ENDIF + +CC = cl +CXX = cl +LIB32 = link +LINK = link + +CC_ALL_EXE = /nologo /D "WIN32" /D "_WINDOWS" /D "_MBCS" /Fo".exec\$(TARGETDIR)/"\ + $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(OS_VERSION_DEF) /TC /c +CXX_ALL_EXE = /nologo /D "WIN32" /D "_WINDOWS" /D "_MBCS" /Fo".exec\$(TARGETDIR)/"\ + $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(OS_VERSION_DEF) /TP /c +CXX_DEBUG_EXE = /MDd /Z7 /Od /D "_DEBUG" /GZ +CXX_RELEASE_EXE = /MD /O2 /D "NDEBUG" +LINK_ALL_EXE = kernel32.lib user32.lib gdi32.lib winspool.lib \ + comdlg32.lib advapi32.lib shell32.lib ole32.lib \ + oleaut32.lib uuid.lib odbc32.lib odbccp32.lib \ + ws2_32.lib /nologo /subsystem:console /pdb:NONE +LINK_DEBUG_EXE = /debug +LINK_RELEASE_EXE = + +CC_ALL_LIB = /nologo /D "WIN32" /D "_MBCS" /D "_LIB" /Fo"$(OBJDIR)/"\ + $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(OS_VERSION_DEF) /TC /c +CXX_ALL_LIB = /nologo /D "WIN32" /D "_MBCS" /D "_LIB" /Fo"$(OBJDIR)/"\ + $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(OS_VERSION_DEF) /TP /c +CXX_DEBUG_LIB = /MDd /Z7 /Od /D "_DEBUG" /GZ +CXX_RELEASE_LIB = /MD /O2 /D "NDEBUG" +LINK_ALL_LIB = -lib /nologo +LINK_DEBUG_LIB = +LINK_RELEASE_LIB = + +CC_ALL_DLL = /nologo /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /Fo"$(OBJDIR)/"\ + $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(OS_VERSION_DEF) /TC /c +CXX_ALL_DLL = /nologo /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /Fo"$(OBJDIR)/"\ + $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(OS_VERSION_DEF) /TP /c +CXX_DEBUG_DLL = /MDd /Z7 /Od /D "_DEBUG" /GZ +CXX_RELEASE_DLL = /MD /O2 /D "NDEBUG" +LINK_ALL_DLL = kernel32.lib user32.lib gdi32.lib winspool.lib \ + comdlg32.lib advapi32.lib shell32.lib ole32.lib \ + oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib \ + /nologo /dll /pdb:NONE +LINK_DEBUG_DLL = /debug +LINK_RELEASE_DLL = + +!IF "$(DEBUG)" != "" +CC_EXE_FLAGS = $(CC_ALL_EXE) $(CXX_DEBUG_EXE) +CC_LIB_FLAGS = $(CC_ALL_LIB) $(CXX_DEBUG_LIB) +CC_DLL_FLAGS = $(CC_ALL_DLL) $(CXX_DEBUG_DLL) +CXX_EXE_FLAGS = $(CXX_ALL_EXE) $(CXX_DEBUG_EXE) +CXX_LIB_FLAGS = $(CXX_ALL_LIB) $(CXX_DEBUG_LIB) +CXX_DLL_FLAGS = $(CXX_ALL_DLL) $(CXX_DEBUG_DLL) +LINK_EXE_FLAGS = $(LINK_ALL_EXE) $(LINK_DEBUG_EXE) +LINK_LIB_FLAGS = $(LINK_ALL_LIB) $(LINK_DEBUG_LIB) +LINK_DLL_FLAGS = $(LINK_ALL_DLL) $(LINK_DEBUG_DLL) +!ELSE +CC_EXE_FLAGS = $(CC_ALL_EXE) $(CXX_RELEASE_EXE) +CC_LIB_FLAGS = $(CC_ALL_LIB) $(CXX_RELEASE_LIB) +CC_DLL_FLAGS = $(CC_ALL_DLL) $(CXX_RELEASE_DLL) +CXX_EXE_FLAGS = $(CXX_ALL_EXE) $(CXX_RELEASE_EXE) +CXX_LIB_FLAGS = $(CXX_ALL_LIB) $(CXX_RELEASE_LIB) +CXX_DLL_FLAGS = $(CXX_ALL_DLL) $(CXX_RELEASE_DLL) +LINK_EXE_FLAGS = $(LINK_ALL_EXE) $(LINK_RELEASE_EXE) +LINK_LIB_FLAGS = $(LINK_ALL_LIB) $(LINK_RELEASE_LIB) +LINK_DLL_FLAGS = $(LINK_ALL_DLL) $(LINK_RELEASE_DLL) +!ENDIF + +!IF "$(HAIL)" != "NO" +HAILTARGET = hail +!ENDIF + +!IF "$(FAIRWELL)" != "NO" +BYETARGET = fairwell +!ENDIF + +# ****************************************************************************** +# * Master rules for building cdevGenericServer objects +# ****************************************************************************** +all : $(HAILTARGET) targets $(BYETARGET) + +hail: + @echo ---------------------------------------------------------------- + @echo Building $(APPNAME) for Target: $(TARGETDIR) + @echo ---------------------------------------------------------------- + +fairwell: + @echo ---------------------------------------------------------------- + @echo Finished Building $(APPNAME) for Target: $(TARGETDIR) + @echo ---------------------------------------------------------------- + +clean: +!IF "$(HAIL)" != "NO" + @echo =^> Cleaning $(APPNAME) for Target: $(TARGETDIR) +!ENDIF + -@for %x in (.obj\$(TARGET)-$(OS_MAJOR).$(OS_MINOR)-DEBUG \ + .obj\$(TARGET)-$(OS_MAJOR).$(OS_MINOR) \ + .shobj\$(TARGET)-$(OS_MAJOR).$(OS_MINOR)-DEBUG \ + .shobj\$(TARGET)-$(OS_MAJOR).$(OS_MINOR) \ + .exec\$(TARGET)-$(OS_MAJOR).$(OS_MINOR)-DEBUG \ + .exec\$(TARGET)-$(OS_MAJOR).$(OS_MINOR)) DO \ + @if exist %x rmdir /s /q %x + -@for %x in ($(BINARIES) $(TARGETS)) DO @if exist %x erase %x +!IF "$(FAIRWELL)" != "NO" + @echo ^<= Done... +!ENDIF + +purge: +!IF "$(HAIL)" != "NO" + @echo =^> Purging $(APPNAME) for Target: $(TARGETDIR) +!ENDIF + -@for %x in (.shobj .obj .exec) DO @if exist %x rmdir /s /q %x + -@for %x in ($(BINARIES) $(TARGETS) $(TEMPLINKS)) DO @if exist %x erase %x +!IF "$(FAIRWELL)" != "NO" + @echo ^<= Done... +!ENDIF + + +.cc{.obj\$(TARGETDIR)}.obj:: + @echo =^> Compiling $< + -@if not exist .obj\$(TARGETDIR) mkdir .obj\$(TARGETDIR) + -@if not exist $(BINDIR) mkdir $(BINDIR) + -@if not exist $(LIBDIR) mkdir $(LIBDIR) + @$(CXX) $(CXX_LIB_FLAGS) $< + +.cc{.shobj\$(TARGETDIR)}.obj:: + @echo =^> Compiling $< + -@if not exist .shobj\$(TARGETDIR) mkdir .shobj\$(TARGETDIR) + -@if not exist $(BINDIR) mkdir $(BINDIR) + -@if not exist $(LIBDIR) mkdir $(LIBDIR) + @$(CXX) $(CXX_DLL_FLAGS) $< + +.cc{.exec\$(TARGETDIR)}.obj:: + @echo =^> Compiling $< + -@if not exist .exec\$(TARGETDIR) mkdir .exec\$(TARGETDIR) + -@if not exist $(BINDIR) mkdir $(BINDIR) + -@if not exist $(LIBDIR) mkdir $(LIBDIR) + @$(CXX) $(CXX_EXE_FLAGS) $< + +.c{.obj\$(TARGETDIR)}.obj:: + @echo =^> Compiling $< + -@if not exist .obj\$(TARGETDIR) mkdir .obj\$(TARGETDIR) + -@if not exist $(BINDIR) mkdir $(BINDIR) + -@if not exist $(LIBDIR) mkdir $(LIBDIR) + @$(CC) $(CC_LIB_FLAGS) $< + +.c{.shobj\$(TARGETDIR)}.obj:: + @echo =^> Compiling $< + -@if not exist .shobj\$(TARGETDIR) mkdir .shobj\$(TARGETDIR) + -@if not exist $(BINDIR) mkdir $(BINDIR) + -@if not exist $(LIBDIR) mkdir $(LIBDIR) + @$(CC) $(CC_DLL_FLAGS) $< + +.c{.exec\$(TARGETDIR)}.obj:: + @echo =^> Compiling $< + -@if not exist .exec\$(TARGETDIR) mkdir .exec\$(TARGETDIR) + -@if not exist $(BINDIR) mkdir $(BINDIR) + -@if not exist $(LIBDIR) mkdir $(LIBDIR) + @$(CC) $(CC_EXE_FLAGS) $< diff --git a/include/makeinclude/Makefile.aix b/include/makeinclude/Makefile.aix new file mode 100644 index 0000000..85042a1 --- /dev/null +++ b/include/makeinclude/Makefile.aix @@ -0,0 +1,55 @@ +# ****************************************************************************** +# * Makefile.hpux : This is the platform specific Makefile for HPUX. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = aix +OS_MAJOR := $(shell uname -v) +OS_MAJOR_NUM := $(shell awk 'BEGIN {VAL=$(OS_MAJOR); print VAL; exit; }') +OS_MINOR := $(shell uname -r) +OS_MINOR_NUM := $(shell awk 'BEGIN {VAL=$(OS_MINOR); print VAL; exit; }') +OS_VERSION_DEF := -D_OS_MAJOR_=$(OS_MAJOR_NUM) -D_OS_MINOR_=$(OS_MINOR_NUM) + +include $(CDEV)/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * All CDEV and service libaries required by archived applications +# ****************************************************************************** +CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only define the DEBUGFLAG if DEBUG has been specified by the caller. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +endif + +CXX = xlC +CC = xlC +CXXFLAGS = $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) \ + $(BASEINCLUDES) $(OS_VERSION_DEF) $(DEBUGFLAG) -DAIX -qNOro +CFLAGS = $(CCEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) \ + $(BASEINCLUDES) $(OS_VERSION_DEF) $(DEBUGFLAG) -DAIX -qNOro +LDFLAGS = +AR = ar +ARFLAGS = ruv +RANLIB = true +OSLIBS = -L/lib -lm + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = @echo "Shared objects not supported on AIX" +COMPILE.c = $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = @echo "Shared objects not supported on AIX" +LINK.cc = $(CXX) $(CXXFLAGS) +LINK.a = $(AR) $(ARFLAGS) diff --git a/include/makeinclude/Makefile.archive b/include/makeinclude/Makefile.archive new file mode 100644 index 0000000..51f3b24 --- /dev/null +++ b/include/makeinclude/Makefile.archive @@ -0,0 +1,9 @@ +# *********************************************************************** +# * Makefile.archive * +# * The ARCHIVELIBS variable should contain a complete list of * +# * all libraries that will be needed by an ARCHIVE cdev program. * +# * The variable should contain the path specification and the * +# * name of the library in the format that is required by your * +# * platform's linker. * +# *********************************************************************** +ARCHIVELIBS = -L$(CDEVLIB) -lcaService diff --git a/include/makeinclude/Makefile.common b/include/makeinclude/Makefile.common new file mode 100644 index 0000000..a85ec4a --- /dev/null +++ b/include/makeinclude/Makefile.common @@ -0,0 +1,94 @@ +# ****************************************************************************** +# * Makefile.common : This is the community makefile for the CDEV distribution. +# * It contains the definitions that are common for all +# * Makefiles in this distribution. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# * CDEVVERSION : The version of cdev being used +# * TARGET : The name of the target platform +# * OS_MAJOR : The major version number of the target OS +# ****************************************************************************** +ifdef OS_MAJOR +TARGETDIR = $(TARGET)-$(OS_MAJOR).$(OS_MINOR) +else +TARGETDIR = $(TARGET) +endif + +CDEVINCLUDES = -I$(CDEV)/include +CDEVLIB = $(CDEV)/lib/$(TARGETDIR) +CDEVBIN = $(CDEV)/bin/$(TARGETDIR) + +# ****************************************************************************** +# * Set the CDEV Version if it has not been specified. +# ****************************************************************************** +ifeq ($(CDEVVERSION), ) + CDEVVERSION = 1.7.2 +endif + +# ****************************************************************************** +# * Set the CDEV shared object directory to a default location if not specified. +# ****************************************************************************** +ifeq ($(CDEVSHOBJ), ) + CDEVSHOBJ = $(CDEVLIB) +endif + + +# ****************************************************************************** +# * Set the object directory appropriately to the SHOBJ flag (default YES) +# ****************************************************************************** +ifeq ($(SHOBJ), YES) + OBJDIR = .shobj/$(TARGETDIR) +else + SHOBJ = NO + OBJDIR = .obj/$(TARGETDIR) +endif + + +# ****************************************************************************** +# * Rule for compiling archive C++ files. +# ****************************************************************************** +.obj/$(TARGETDIR)/%.o : %.cc + @rm -f $@ + @echo "=> $(CXX) -c $(^F) -o $(@F)" + @mkdir -p .obj/$(TARGETDIR) + @$(COMPILE.cc) + + +# ****************************************************************************** +# * Rule for compiling shared C++ files. +# ****************************************************************************** +.shobj/$(TARGETDIR)/%.o : %.cc + @rm -f $@ + @echo "=> $(CXX) -c $(^F) -o $(@F)" + @mkdir -p .shobj/$(TARGETDIR) + @$(COMPILE.cc.so) + +# ****************************************************************************** +# * Generic rules for makefiles. +# ****************************************************************************** +all: hail targets fairwell + +hail: + @echo + @echo ---------------------------------------------------------------- + @echo Building $(APPNAME) for Target: $(TARGET) + @echo ---------------------------------------------------------------- + +fairwell: + @echo ---------------------------------------------------------------- + @echo Finished Building $(APPNAME) for Target: $(TARGET) + @echo ---------------------------------------------------------------- + @echo + +clean: + @echo "=> Cleaning $(APPNAME) on $(TARGETDIR)" + @rm -rf .o .a core .obj/$(TARGETDIR) .shobj/$(TARGETDIR) .exec/$(TARGETDIR) *.?.? TC.Cache $(BINARIES) $(TARGETS) ./ptrepository + @echo "<= Done...\n" + +purge: + @echo "=> Purging $(APPNAME)" + @rm -rf .shobj .obj .exec $(BINARIES) $(TARGETS) $(TEMPLINKS) .o .a core *.?.? TC.Cache ./ptrepository + @echo "<= Done...\n" diff --git a/include/makeinclude/Makefile.hpux b/include/makeinclude/Makefile.hpux new file mode 100644 index 0000000..de7887d --- /dev/null +++ b/include/makeinclude/Makefile.hpux @@ -0,0 +1,74 @@ +# ****************************************************************************** +# * Makefile.hpux : This is the platform specific Makefile for HPUX. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = hpux +OS_MAJOR := $(shell uname -r | awk -F "." '{print $$2; exit}') +OS_MAJOR_NUM := $(shell awk 'BEGIN {VAL=$(OS_MAJOR); print VAL; exit; }') +OS_MINOR := $(shell uname -r | awk -F "." '{print $$3; exit}') +OS_MINOR_NUM := $(shell awk 'BEGIN {VAL=$(OS_MINOR); print VAL; exit; }') +OS_VERSION_DEF := -D_OS_MAJOR_=$(OS_MAJOR_NUM) -D_OS_MINOR_=$(OS_MINOR_NUM) + +include $(CDEV)/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Due to a change in the operating system, the CXX compiler for HP-UX may +# * be different depending on which platform is used. +# ****************************************************************************** +ifeq ($(OS_MAJOR), 09) + CXX := /usr/bin/CC + HPCXX_FLAGS := -Aa -pta -ptb + HPCXX_SHLIB_PATH := -Wl,+s +else + CXX := /opt/aCC/bin/aCC + HPCXX_FLAGS := +W302,392,469,495,655,829 + HPCXX_SHLIB_PATH := -Wl,+s + + ifeq ($(OS_MAJOR).$(OS_MINOR), 10.10) + HP_FLAGS = -Dvolatile="" + endif +endif + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only define the DEBUGFLAG if DEBUG has been specified by the caller. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +else +DEBUGFLAG = +O2 +endif + +CXXFLAGS = -z $(HPCXX_FLAGS) $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) \ + $(OS_VERSION_DEF) $(DEBUGFLAG) $(HP_FLAGS) +PIC = +z +OSLIBS = -L/lib -lm + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(CXX) -c $(CXXFLAGS) $(PIC) $^ -o $@ +LINK.cc = rm -rf $@; echo "=> $(CXX) -o $(@F) $(^F)";$(CXX) $(CXXFLAGS) $(HPCXX_SHLIB_PATH) $(CXXEXTRA) $^ -o $@ $(CDEVLIBS) $(OSLIBS) + + diff --git a/include/makeinclude/Makefile.hpux-cl b/include/makeinclude/Makefile.hpux-cl new file mode 100644 index 0000000..138ce37 --- /dev/null +++ b/include/makeinclude/Makefile.hpux-cl @@ -0,0 +1,60 @@ +# ****************************************************************************** +# * Makefile.hpux-cl: This is the platform specific Makefile for HPUX using +# * the CenterLine C++ compiler. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = hpux-cl +SHOBJ = NO +OS_MAJOR := $(shell uname -r | awk -F "." '{print $$2; exit}') +OS_MAJOR_NUM := $(shell awk 'BEGIN {VAL=$(OS_MAJOR); print VAL; exit; }') +OS_MINOR := $(shell uname -r | awk -F "." '{print $$3; exit}') +OS_MINOR_NUM := $(shell awk 'BEGIN {VAL=$(OS_MINOR); print VAL; exit; }') +OS_VERSION_DEF := -D_OS_MAJOR_=$(OS_MAJOR_NUM) -D_OS_MINOR_=$(OS_MINOR_NUM) + +include $(CDEV)/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +ifeq ($(OS_MAJOR_NUM), 10) + HP_FLAGS = -Dvolatile="" +endif + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only define the DEBUGFLAG if DEBUG has been specified by the caller. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +endif + +CXX = /usr/csite4/CenterLine/bin/CC +CXXFLAGS = -z -pta -D__CENTERLINE__ $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) \ + $(OS_VERSION_DEF) $(DEBUGFLAG) $(HP_FLAGS) +PIC = +OSLIBS = -lm + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = echo "Shared Object Compilation is NOT Supported by CenterLine" +LINK.cc = rm -rf $@; echo "=> $(CXX) -o $(@F) $(^F)";$(PROOF) $(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -o $@ $(CDEVLIBS) $(OSLIBS) diff --git a/include/makeinclude/Makefile.hpux-cl-sl b/include/makeinclude/Makefile.hpux-cl-sl new file mode 100644 index 0000000..e78154b --- /dev/null +++ b/include/makeinclude/Makefile.hpux-cl-sl @@ -0,0 +1,2 @@ +SHOBJ=YES +include $(CDEV)/include/makeinclude/Makefile.hpux-cl diff --git a/include/makeinclude/Makefile.hpux-sl b/include/makeinclude/Makefile.hpux-sl new file mode 100644 index 0000000..791d9d2 --- /dev/null +++ b/include/makeinclude/Makefile.hpux-sl @@ -0,0 +1,2 @@ +SHOBJ=YES +include $(CDEV)/include/makeinclude/Makefile.hpux diff --git a/include/makeinclude/Makefile.irix5 b/include/makeinclude/Makefile.irix5 new file mode 100644 index 0000000..42a78b3 --- /dev/null +++ b/include/makeinclude/Makefile.irix5 @@ -0,0 +1,47 @@ +# ****************************************************************************** +# * Makefile.hpux : This is the platform specific Makefile for HPUX. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = SGI + +include $(CDEV)/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only define the DEBUGFLAG if DEBUG has been specified by the caller. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +endif + +CXX = CC +CXXFLAGS = $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(OS_VERSION_DEF) $(DEBUGFLAG) +PIC = -DSHM +OSLIBS = -lm + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(CXX) -c $(CXXFLAGS) $(PIC) $^ -o $@ +LINK.cc = rm -rf $@; echo "=> $(CXX) -o $(@F) $(^F)";$(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -o $@ $(CDEVLIBS) $(OSLIBS) diff --git a/include/makeinclude/Makefile.irix5-sl b/include/makeinclude/Makefile.irix5-sl new file mode 100644 index 0000000..e158059 --- /dev/null +++ b/include/makeinclude/Makefile.irix5-sl @@ -0,0 +1,2 @@ +SHOBJ=YES +include $(CDEV)/include/makeinclude/Makefile.irix5 diff --git a/include/makeinclude/Makefile.linux b/include/makeinclude/Makefile.linux new file mode 100644 index 0000000..b9f95d0 --- /dev/null +++ b/include/makeinclude/Makefile.linux @@ -0,0 +1,61 @@ +# ****************************************************************************** +# * Makefile.Linux : This is the platform specific Makefile for Linux. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = Linux + +include $(CDEV)/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only define the DEBUGFLAG if DEBUG has been specified by the caller. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +else +DEBUGFLAG = -O2 +endif + +CXX = g++ +CC = gcc +CXXFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS -fno-for-scope $(DEBUGFLAG) $(CXXEXTRA) $(CXXINCLUDES) \ + $(CDEVINCLUDES) +CFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS $(DEBUGFLAG) $(CEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) +PIC = -fpic +OSLIBS = -lm -ldl + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else +#CDEVLIBS = -Xlinker -rpath -Xlinker $(CDEVLIB) -L$(CDEVLIB) -lcdev + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(CXX) $(CXXFLAGS) $(PIC) -c -o $@ $^ +COMPILE.c = $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = rm -f $@; $(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -o $@ $(CDEVLIBS) $(OSLIBS) + + + + + diff --git a/include/makeinclude/Makefile.linux-redhat5.2-alpha b/include/makeinclude/Makefile.linux-redhat5.2-alpha new file mode 100644 index 0000000..687b345 --- /dev/null +++ b/include/makeinclude/Makefile.linux-redhat5.2-alpha @@ -0,0 +1,55 @@ +# ****************************************************************************** +# * Makefile.Linux : This is the platform specific Makefile for Linux. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = Linux + +include $(CDEV)/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only define the DEBUGFLAG if DEBUG has been specified by the caller. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +else +DEBUGFLAG = -O2 +endif + +CXX = g++ +CC = gcc +CXXFLAGS = -DLinux -DCDEV_HAS_64BIT_LONGS -fno-for-scope $(DEBUGFLAG) $(CXXEXTRA) $(CXXINCLUDES) \ + $(CDEVINCLUDES) +CFLAGS = -DLinux -DCDEV_HAS_64BIT_LONGS $(DEBUGFLAG) $(CEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) +PIC = -fpic +OSLIBS = -lm -ldl + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -Xlinker -rpath -Xlinker $(CDEVLIB) -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(CXX) $(CXXFLAGS) $(PIC) -c -o $@ $^ +COMPILE.c = $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = rm -f $@; $(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -o $@ $(CDEVLIBS) $(OSLIBS) diff --git a/include/makeinclude/Makefile.linux-redhat5.2-x86 b/include/makeinclude/Makefile.linux-redhat5.2-x86 new file mode 100644 index 0000000..e420b6e --- /dev/null +++ b/include/makeinclude/Makefile.linux-redhat5.2-x86 @@ -0,0 +1,56 @@ +# ****************************************************************************** +# * Makefile.Linux : This is the platform specific Makefile for Linux. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = Linux + +include $(CDEV)/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only define the DEBUGFLAG if DEBUG has been specified by the caller. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +else +DEBUGFLAG = -O2 +endif + +CXX = g++ +CC = gcc +CXXFLAGS = -DLinux -fno-for-scope $(DEBUGFLAG) $(CXXEXTRA) $(CXXINCLUDES) \ + $(CDEVINCLUDES) +CFLAGS = -DLinux $(DEBUGFLAG) $(CEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) +PIC = -fpic +OSLIBS = -lm -ldl + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else +#CDEVLIBS = -Xlinker -rpath -Xlinker $(CDEVLIB) -L$(CDEVLIB) -lcdev + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(CXX) $(CXXFLAGS) $(PIC) -c -o $@ $^ +COMPILE.c = $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = rm -f $@; $(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -o $@ $(CDEVLIBS) $(OSLIBS) diff --git a/include/makeinclude/Makefile.linux-redhat6.0-alpha b/include/makeinclude/Makefile.linux-redhat6.0-alpha new file mode 100644 index 0000000..827ee6a --- /dev/null +++ b/include/makeinclude/Makefile.linux-redhat6.0-alpha @@ -0,0 +1,55 @@ +# ****************************************************************************** +# * Makefile.Linux : This is the platform specific Makefile for Linux. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = Linux + +include $(CDEV)/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only define the DEBUGFLAG if DEBUG has been specified by the caller. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +else +DEBUGFLAG = -O2 +endif + +CXX = g++ +CC = gcc +CXXFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS -DCDEV_HAS_64BIT_LONGS -fno-for-scope $(DEBUGFLAG) $(CXXEXTRA) $(CXXINCLUDES) \ + $(CDEVINCLUDES) +CFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS -DCDEV_HAS_64BIT_LONGS $(DEBUGFLAG) $(CEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) +PIC = -fpic +OSLIBS = -lm -ldl + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -Xlinker -rpath -Xlinker $(CDEVLIB) -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(CXX) $(CXXFLAGS) $(PIC) -c -o $@ $^ +COMPILE.c = $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = rm -f $@; $(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -o $@ $(CDEVLIBS) $(OSLIBS) diff --git a/include/makeinclude/Makefile.linux-redhat6.0-x86 b/include/makeinclude/Makefile.linux-redhat6.0-x86 new file mode 100644 index 0000000..b9f95d0 --- /dev/null +++ b/include/makeinclude/Makefile.linux-redhat6.0-x86 @@ -0,0 +1,61 @@ +# ****************************************************************************** +# * Makefile.Linux : This is the platform specific Makefile for Linux. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = Linux + +include $(CDEV)/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only define the DEBUGFLAG if DEBUG has been specified by the caller. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +else +DEBUGFLAG = -O2 +endif + +CXX = g++ +CC = gcc +CXXFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS -fno-for-scope $(DEBUGFLAG) $(CXXEXTRA) $(CXXINCLUDES) \ + $(CDEVINCLUDES) +CFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS $(DEBUGFLAG) $(CEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) +PIC = -fpic +OSLIBS = -lm -ldl + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else +#CDEVLIBS = -Xlinker -rpath -Xlinker $(CDEVLIB) -L$(CDEVLIB) -lcdev + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(CXX) $(CXXFLAGS) $(PIC) -c -o $@ $^ +COMPILE.c = $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = rm -f $@; $(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -o $@ $(CDEVLIBS) $(OSLIBS) + + + + + diff --git a/include/makeinclude/Makefile.linux-redhat6.2-x86 b/include/makeinclude/Makefile.linux-redhat6.2-x86 new file mode 100644 index 0000000..b9f95d0 --- /dev/null +++ b/include/makeinclude/Makefile.linux-redhat6.2-x86 @@ -0,0 +1,61 @@ +# ****************************************************************************** +# * Makefile.Linux : This is the platform specific Makefile for Linux. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = Linux + +include $(CDEV)/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only define the DEBUGFLAG if DEBUG has been specified by the caller. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +else +DEBUGFLAG = -O2 +endif + +CXX = g++ +CC = gcc +CXXFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS -fno-for-scope $(DEBUGFLAG) $(CXXEXTRA) $(CXXINCLUDES) \ + $(CDEVINCLUDES) +CFLAGS = -DLinux -DCDEV_HAS_UNDERSCORE_FDBITS $(DEBUGFLAG) $(CEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) +PIC = -fpic +OSLIBS = -lm -ldl + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. The developer +# * is required to add the list of service specific libraries. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else +#CDEVLIBS = -Xlinker -rpath -Xlinker $(CDEVLIB) -L$(CDEVLIB) -lcdev + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(CXX) $(CXXFLAGS) $(PIC) -c -o $@ $^ +COMPILE.c = $(CC) -c $(CFLAGS) $^ -o $@ +COMPILE.c.so = $(CC) -c $(CFLAGS) $(PIC) $^ -o $@ +LINK.cc = rm -f $@; $(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -o $@ $(CDEVLIBS) $(OSLIBS) + + + + + diff --git a/include/makeinclude/Makefile.linux-sl b/include/makeinclude/Makefile.linux-sl new file mode 100644 index 0000000..293b2fe --- /dev/null +++ b/include/makeinclude/Makefile.linux-sl @@ -0,0 +1,2 @@ +SHOBJ=YES +include $(CDEV)/include/makeinclude/Makefile.linux diff --git a/include/makeinclude/Makefile.solaris b/include/makeinclude/Makefile.solaris new file mode 100644 index 0000000..5eeb692 --- /dev/null +++ b/include/makeinclude/Makefile.solaris @@ -0,0 +1,47 @@ +# ****************************************************************************** +# * Makefile.hpux : This is the platform specific Makefile for HPUX. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = solaris + +include $(CDEV)/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only define the DEBUGFLAG if DEBUG has been specified by the caller. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +endif + +CXX = CC +CXXFLAGS = $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(OS_VERSION_DEF) $(DEBUGFLAG) -Dsolaris -DSYSV -DSVR4 +PIC = -Kpic +OSLIBS = -lsocket -lnsl -lm + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -R$(CDEVLIB) -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(CXX) -c $(CXXFLAGS) $(PIC) $^ -o $@ +LINK.cc = rm -rf $@; echo "=> $(CXX) -o $(@F) $(^F)";$(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -o $@ $(CDEVLIBS) $(OSLIBS) diff --git a/include/makeinclude/Makefile.solaris-gcc b/include/makeinclude/Makefile.solaris-gcc new file mode 100644 index 0000000..bd6f972 --- /dev/null +++ b/include/makeinclude/Makefile.solaris-gcc @@ -0,0 +1,47 @@ +# ****************************************************************************** +# * Makefile.hpux : This is the platform specific Makefile for HPUX. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = solaris-gnu + +include $(CDEV)/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only define the DEBUGFLAG if DEBUG has been specified by the caller. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +endif + +CXX = g++ +CXXFLAGS = $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(OS_VERSION_DEF) $(DEBUGFLAG) +PIC = -fpic +OSLIBS = -lsocket -lnsl -lm + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(CXX) -c $(CXXFLAGS) $(PIC) $^ -o $@ +LINK.cc = rm -rf $@; echo "=> $(CXX) -o $(@F) $(^F)";$(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -o $@ $(CDEVLIBS) $(OSLIBS) diff --git a/include/makeinclude/Makefile.solaris-gcc-sl b/include/makeinclude/Makefile.solaris-gcc-sl new file mode 100644 index 0000000..fdff4b8 --- /dev/null +++ b/include/makeinclude/Makefile.solaris-gcc-sl @@ -0,0 +1,2 @@ +SHOBJ=YES +include $(CDEV)/include/makeinclude/Makefile.solaris-gcc diff --git a/include/makeinclude/Makefile.solaris-sl b/include/makeinclude/Makefile.solaris-sl new file mode 100644 index 0000000..d95f74d --- /dev/null +++ b/include/makeinclude/Makefile.solaris-sl @@ -0,0 +1,2 @@ +SHOBJ=YES +include $(CDEV)/include/makeinclude/Makefile.solaris diff --git a/include/makeinclude/Makefile.sunos4-gcc b/include/makeinclude/Makefile.sunos4-gcc new file mode 100644 index 0000000..0e25659 --- /dev/null +++ b/include/makeinclude/Makefile.sunos4-gcc @@ -0,0 +1,47 @@ +# ****************************************************************************** +# * Makefile.hpux : This is the platform specific Makefile for HPUX. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = SunOs-gnu + +include $(CDEV)/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only define the DEBUGFLAG if DEBUG has been specified by the caller. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +endif + +CXX = g++ +CXXFLAGS = $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(OS_VERSION_DEF) $(DEBUGFLAG) +PIC = -fpic +OSLIBS = -lm + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = $(CXX) -c $(CXXFLAGS) $(PIC) $^ -o $@ +LINK.cc = rm -rf $@; echo "=> $(CXX) -o $(@F) $(^F)";$(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -o $@ $(CDEVLIBS) $(OSLIBS) diff --git a/include/makeinclude/Makefile.sunos4-gcc-sl b/include/makeinclude/Makefile.sunos4-gcc-sl new file mode 100644 index 0000000..0b21701 --- /dev/null +++ b/include/makeinclude/Makefile.sunos4-gcc-sl @@ -0,0 +1,2 @@ +SHOBJ=YES +include $(CDEV)/include/makeinclude/Makefile.sunos4-gcc diff --git a/include/makeinclude/Makefile.ultrix-gcc b/include/makeinclude/Makefile.ultrix-gcc new file mode 100644 index 0000000..0c7f6aa --- /dev/null +++ b/include/makeinclude/Makefile.ultrix-gcc @@ -0,0 +1,47 @@ +# ****************************************************************************** +# * Makefile.hpux : This is the platform specific Makefile for HPUX. +# * +# * Externals : This Makefile relies on the developer defining the +# * following external definitions... +# * +# * CDEV : The base directory of the CDEV distribution +# ****************************************************************************** +TARGET = ULTRIX + +include $(CDEV)/include/makeinclude/Makefile.common +include $(CDEV)/include/makeinclude/Makefile.archive + +# ****************************************************************************** +# * Platform specific compile and link options. +# ****************************************************************************** + +# ****************************************************************************** +# * Only define the DEBUGFLAG if DEBUG has been specified by the caller. +# ****************************************************************************** +ifdef DEBUG +DEBUGFLAG = -g +endif + +CXX = g++ +CXXFLAGS = $(CXXEXTRA) $(CXXINCLUDES) $(CDEVINCLUDES) $(OS_VERSION_DEF) $(DEBUGFLAG) +PIC = +OSLIBS = -lm + + +# ****************************************************************************** +# * These definitions define the names and locations of libraries that are +# * required by CDEV for a shared and archive applications. +# ****************************************************************************** +ifeq ($(SHOBJ), NO) + CDEVLIBS = $(CDEVLIB)/libcdev.a $(ARCHIVELIBS) +else + CDEVLIBS = -L$(CDEVLIB) -lcdev +endif + + +# ****************************************************************************** +# * Platform specific compile and link macros. +# ****************************************************************************** +COMPILE.cc = $(CXX) -c $(CXXFLAGS) $^ -o $@ +COMPILE.cc.so = @echo "Shared Object Compilation is NOT Supported on ULTRIX" +LINK.cc = rm -rf $@; echo "=> $(CXX) -o $(@F) $(^F)";$(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -o $@ $(CDEVLIBS) $(OSLIBS) diff --git a/include/shObjLoader.h b/include/shObjLoader.h new file mode 100644 index 0000000..3144695 --- /dev/null +++ b/include/shObjLoader.h @@ -0,0 +1,169 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// shObjLoader class (for hp ,sun (SunOs 4.x) , sgi (irix), +// solaris 2.x and linux only) +// +// Author: Jie Chen +// +// Revision History: +// shObjLoader.h,v +// Revision 1.6 1996/03/22 16:32:09 chen +// support solaris +// +// Revision 1.5 1995/11/14 17:35:17 chen +// better header +// +// Revision 1.4 1995/11/14 17:33:37 chen +// fix to work under irix5.3 +// +// Revision 1.3 1995/10/18 17:45:06 chen +// To work under SunOs +// +// Revision 1.2 1995/10/17 13:25:18 chen +// Change load (int flag) to load (void) +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#ifndef _SH_OBJ_LOADER_H +#define _SH_OBJ_LOADER_H + +#include +#include + +#ifdef __hpux + #ifdef _CENTERLINE + #include + #define HP_SHOBJ_LOADER ::shl_load + #define HP_SHOBJ_UNLOADER ::shl_unload + #elif (_OS_MAJOR==9 || (_OS_MAJOR==10 && _OS_MINOR==10)) + #include + #define HP_SHOBJ_LOADER ::cxxshl_load + #define HP_SHOBJ_UNLOADER ::cxxshl_unload + #else + #include + #define HP_SHOBJ_LOADER ::shl_load + #define HP_SHOBJ_UNLOADER ::shl_unload + #endif +#endif + +#ifdef sunos4 +// sun header file dlfunc.h is not defined for cplusplus +extern "C" +{ +void *dlopen (char* path, int mode); +void *dlsym (void* handle, char* symbol); +char *dlerror (void); +int dlclose (void* handle); +}; +#define RTLD_LAZY 1 +#endif + +#if defined (sgi) || defined (solaris) || defined (aix) || defined (__linux) +#include +#endif + +#if defined (_WIN32) +#include + +#ifndef SHOBJ +#define SHOBJ 1 +#endif + +#endif + +#include + +class shObjLoader +{ +public: + //constructors and destructor + shObjLoader (char *path); + virtual ~shObjLoader (void); + + virtual int open (char *name); + // PURPOSE: open a shared library by a given name + // REQUIRE: name != 0 + // PROMISE: library path name will be stored + + virtual int load (void); + // PURPOSE: load a shared library in verbose mode if possible + // REQUIRE: call open first + // PROMISE: return 0: success loaded. return -1: load failed + + virtual int findProcedureSym (const char * sym, void** value); + // PURPOSE: find procedure address given by symbol + // REQUIRE: call load first + // PROMISE: value will be the address. return 0: success, -1: failure + +#ifdef __hpux + virtual int findDataSym (const char * sym, void * value); + // PURPOSE: find data address given by symbol + // REQUIRE: call load first + // PROMISE: value will be the address + + virtual int findSym (const char * sym, void * value); + // PURPOSE: find address given by symbol + // REQUIRE: call load first + // PROMISE: value will be the address. return 0: success, -1: failure + + unsigned long textStartAddr (void); + // PURPOSE: find text section start address + // REQUIRE: call load first + // PROMISE: return address, 0: failure + + unsigned long textEndAddr (void); + // PURPOSE: find text section end address + // REQUIRE: call load first + // PROMISE: return address, 0: failure + + unsigned long dataStartAddr (void); + // PURPOSE: find data section start address + // REQUIRE: call load first + // PROMISE: return address, 0: failure + + unsigned long dataEndAddr (void); + // PURPOSE: find data section end address + // REQUIRE: call load first + // PROMISE: return address, 0: failure +#endif // end __hpux + + const char *filename (void); + // PURPOSE: loaded shared library path name + // REQUIRE: nothing + // PROMISE: 0: means nothing loaded + + virtual int close (void); + // PURPOSE: remove shared library from memory + // REQUIRE: nothing + // PROMISE: Shared library will be removed from memory + // filename () return 0 + + virtual const char *className (void) const {return "shObjLoader";} + +private: +#ifdef __hpux + shl_t libHandler_; + struct shl_descriptor *desc_; +#endif // endif __hpux + +#if defined (sunos4) || defined (sgi) || defined (solaris) || defined (aix) || defined (__linux) + void* libHandler_; +#endif // endif sun or sgi + +#if defined (_WIN32) + HINSTANCE libHandler_; +#endif + + char *libName_; +}; +#endif diff --git a/include/xdrClass.h b/include/xdrClass.h new file mode 100644 index 0000000..d24d1ed --- /dev/null +++ b/include/xdrClass.h @@ -0,0 +1,450 @@ +#ifndef _XDR_CLASS_H_ +#define _XDR_CLASS_H_ + +#include +#include +#include +#if defined (ultrix) || defined (sgi) || defined (solaris) +#include +#endif + +// Under TGV Multinet and VMS, before you can #include rpc/xdr.h (below), +// rpc/types.h must be included, so that bool_t is defined and sys/types.h is +// #included. +// +// Under TGV Multinet and VMS, if you want sys/types.h, you need to have +// types.h already pulled in because sys/types.h makes it look like types.h +// is loaded. Then when types.h does get loaded, it is ignored because it +// looks like it is already loaded. +// +// rpc/types.h defines bool_t, required by rpc/xdr.h +// rpc/types.h #includes sys/types.h +// sys/types.h defines caddr_t, required by rpc/xdr.h and +// defines u_int,u_short required by netinet/in.h +// --Mr. Daniel Van Olst at SLAC vanolst@slc.slac.stanford.edu + +#ifdef __VMS +#ifdef _TGV_MULTINET +#include +#include +#include +#include +#endif +#include +#endif + +#ifdef _WIN32 +#include "xdr.h" +#else +#include +#include +#endif +#include + +static bool_t xdr_timestamp( XDR * xdrs, cdev_TS_STAMP * ts) { + if ( xdr_u_long (xdrs, &ts->secPastEpoch) == 0) return 0; + return (xdr_u_long (xdrs, &ts->nsec)); +} + +// ***************************************************************************** +// * XDR_Size_of : +// * Functions used to determine the size of a data element once translated +// * and placed into an XDR stream. +// ***************************************************************************** +#if !defined( NO_TEMPLATES ) + template inline unsigned XDR_Sizeof( T t ) { + return (RNDUP(sizeof(t))); } +#else + inline unsigned XDR_Sizeof(char x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(unsigned char x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(short x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(unsigned short x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(int x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(unsigned int x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(long x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(unsigned long x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(float x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(double x) { return (RNDUP(sizeof(x))); } + +#endif + +inline unsigned XDR_Sizeof( char * s ) { + return (RNDUP(strlen(s)) + BYTES_PER_XDR_UNIT); } + +inline unsigned XDR_Sizeof( char *, unsigned len ) { + return (RNDUP(len) + BYTES_PER_XDR_UNIT); } + +inline unsigned XDR_Sizeof( void *, unsigned len ) { + return (RNDUP(len) + BYTES_PER_XDR_UNIT); } + +inline unsigned XDR_Sizeof( cdev_TS_STAMP ts ) { + return (RNDUP(sizeof(ts))); } + +typedef struct + { + unsigned bufLen; + char * buf; + } XDR_DataBlock; + + +// ***************************************************************************** +// * This is the XDR_Data class. It allows the user to pass the data associated +// * with the XDR_Writer and XDR_Reader classes in a format that is not +// * restricted to XDR read or XDR write. +// ***************************************************************************** +class XDR_Data : public XDR_DataBlock + { + public: + XDR_Data ( void ) + { buf = NULL; bufLen = 0; } + + XDR_Data ( char * Buf, unsigned Len ) + { buf = NULL; bufLen = 0; assign(Buf, Len); } + + XDR_Data ( XDR_Data & x ) + { buf = NULL; bufLen = 0; assign(x.buf, x.bufLen); } + + ~XDR_Data ( void ) { deallocate(); } + unsigned & size ( void ) { return bufLen; } + char * & buffer ( void ) { return buf; } + int ready ( void ) { return (buf!=NULL && bufLen>0)?1:0; } + + void allocate ( unsigned Len ) + { + if(Len==0) XDR_Data::deallocate(); + else if(Len!=bufLen || buf==NULL) + { + XDR_Data::deallocate(); + bufLen = Len; + buf = new char[bufLen]; + XDR_Data::clear(); + } + else XDR_Data::clear(); + } + + void deallocate ( void ) + { + if(buf!=NULL) + { + delete buf; + buf = NULL; + } + bufLen = 0; + } + + void assign ( char * Buf, unsigned Len) + { + XDR_Data::allocate(Len); + memcpy(buf, Buf, bufLen); + } + + void clear ( void ) + { + memset(buf, 0, bufLen); + } + + void attachData ( XDR_Data & data ) + { + attachData(data.buf, data.bufLen); + } + + void attachData ( char * Buf, unsigned BufLen ) + { + XDR_Data::deallocate(); + buf = Buf; + bufLen = BufLen; + } + + void detachData ( void ) + { + buf = 0; + bufLen = 0; + } + }; + + +// ***************************************************************************** +// * This is the XDR_Base class. It provides the basic mechanism for generating +// * character streams that contain XDR data storage. +// ***************************************************************************** +class XDR_Base : public XDR_Data + { + protected: + XDR xdrs; + const enum xdr_op op; + + XDR_Base (enum xdr_op xop ) : XDR_Data(), op(xop) {} + XDR_Base (XDR_Data & xdrData, enum xdr_op xop) : op(xop) + { + allocate(xdrData.size()); + memcpy(buf, xdrData.buffer(), xdrData.size()); + xdr_setpos(xdr(), 0); + } + ~XDR_Base ( void ) { deallocate(); } + + public: + XDR * xdr ( void ) { return &xdrs; } + unsigned position ( void ) { return ready()?xdr_getpos(&xdrs):0L; } + + void allocate ( unsigned Len) + { + if(Len==0) XDR_Base::deallocate(); + else if(Len!=bufLen || buf==NULL) + { + XDR_Base::deallocate(); + XDR_Data::allocate(Len); + xdrmem_create(&xdrs, buf, bufLen, op); + } + else XDR_Data::clear(); + } + + void deallocate ( void ) + { + if(ready()) + { + xdr_destroy(&xdrs); + XDR_Data::deallocate(); + } + } + + void clear ( void ) + { + if(ready()) + { + XDR_Data::clear(); + xdr_setpos(&xdrs, 0); + } + } + + void attachData ( XDR_Data & data ) + { + XDR_Base::attachData(data.buf, data.bufLen); + } + + void attachData ( char * Buf, unsigned BufLen ) + { + XDR_Base::deallocate(); + XDR_Data::attachData(Buf, BufLen); + xdrmem_create(&xdrs, buf, bufLen, op); + } + + void detachData ( void ) + { + XDR_Data::detachData(); + XDR_Base::deallocate(); + } + }; + + + +// ***************************************************************************** +// * This is the XDR_Writer class. It provides the mechanisms for creating and +// * managing an outgoing stream of XDR data. +// ***************************************************************************** +class XDR_Writer : public XDR_Base + { + public: + XDR_Writer (unsigned len = 0) : XDR_Base(XDR_ENCODE) { XDR_Base::allocate(len); } + XDR_Writer (XDR_Data & xdrData ) : XDR_Base(xdrData, XDR_ENCODE) {} + + int put_char ( char x ) + { return ready()?xdr_char(&xdrs, &x):0; } + + int put_u_char ( unsigned char x ) +#ifndef sunos4 + { return ready()?xdr_u_char(&xdrs, &x):0; } +#else + { return ready()?xdr_u_char(&xdrs, (char *)&x):0; } +#endif + + int put_int ( int x ) + { return ready()?xdr_int(&xdrs, &x):0; } + + int put_u_int ( unsigned int x ) + { return ready()?xdr_u_int(&xdrs, &x):0; } + + int put_short ( short x ) + { return ready()?xdr_short(&xdrs, &x):0; } + + int put_u_short( unsigned short x ) + { return ready()?xdr_u_short(&xdrs, &x):0; } + + int put_long ( long x ) + { return ready()?xdr_long(&xdrs, &x):0; } + + int put_u_long ( unsigned long x ) + { return ready()?xdr_u_long(&xdrs, &x):0; } + + int put_float ( float x ) + { return ready()?xdr_float(&xdrs, &x):0; } + + int put_double ( double x ) + { return ready()?xdr_double(&xdrs, &x):0; } + + int put_bytes ( char ** bytes, unsigned int num ) + { return ready()? + xdr_bytes(&xdrs, bytes, &num, size()-position()): + 0; } + + int put_string ( char * str ) + { return ready()? + xdr_string(&xdrs, &str, size()-position()): + 0; } + + int put_opaque ( void * data, unsigned len ) + { int status = 0; + if(ready()) + { + status=xdr_u_int (&xdrs, &len); + if(status) status=xdr_opaque(&xdrs, (char *)data, len); + } + return status; + } + + int put_timestamp ( cdev_TS_STAMP ts ) + { return ready()?xdr_timestamp(&xdrs, &ts):0; } + + int put ( char x ) { return put_char(x); } + int put ( unsigned char x ) { return put_u_char(x); } + int put ( int x ) { return put_int(x); } + int put ( unsigned int x ) { return put_u_int(x); } + int put ( short x ) { return put_short(x); } + int put ( unsigned short x ) { return put_u_short(x); } + int put ( long x ) { return put_long(x); } + int put ( unsigned long x ) { return put_u_long(x); } + int put ( float x ) { return put_float(x); } + int put ( double x ) { return put_double(x); } + int put ( char * str ) { return put_string(str); } + int put ( void * x, unsigned len ) { return put_opaque(x, len); } + int put ( cdev_TS_STAMP ts ) { return put_timestamp(ts); } + }; + + +// ***************************************************************************** +// * This is the XDR_Reader class. It provides the mechanisms for creating and +// * managing an incoming stream of XDR data. +// ***************************************************************************** +class XDR_Reader : public XDR_Base + { + public: + XDR_Reader (unsigned len = 0) : XDR_Base(XDR_DECODE) { XDR_Base::allocate(len); } + XDR_Reader (XDR_Data & xdrData ) : XDR_Base(xdrData, XDR_DECODE) {} + + int get_char ( char & x ) + { return ready()?xdr_char(&xdrs, &x):0; } + + int get_u_char ( unsigned char & x ) +#ifndef sunos4 + { return ready()?xdr_u_char(&xdrs, &x):0; } +#else + { return ready()?xdr_u_char(&xdrs, (char *)&x):0; } +#endif + + int get_int ( int & x ) + { return ready()?xdr_int(&xdrs, &x):0; } + + int get_u_int ( unsigned int & x ) + { return ready()?xdr_u_int(&xdrs, &x):0; } + + int get_short ( short & x ) + { return ready()?xdr_short(&xdrs, &x):0; } + + int get_u_short ( unsigned short & x ) + { return ready()?xdr_u_short(&xdrs, &x):0; } + + int get_long ( long & x ) + { return ready()?xdr_long(&xdrs, &x):0; } + + int get_u_long ( unsigned long & x ) + { return ready()?xdr_u_long(&xdrs, &x):0; } + + int get_float ( float & x ) + { return ready()?xdr_float(&xdrs, &x):0; } + + int get_double ( double & x ) + { return ready()?xdr_double(&xdrs, &x):0; } + + int get_bytes ( char ** bytes, unsigned int & num, unsigned int max ) + { return ready()?xdr_bytes(&xdrs, bytes, &num, max):0; } + + int get_string_len ( void ) + { return ready()?ntohl(*(long *)((char *)buf+xdr_getpos(&xdrs))):0; } + + int get_string ( char ** str, unsigned int max = -1U ) + { + int result = 0; + int slen = get_string_len()+1; + char * s = new char[slen]; + if(ready()) + { + result = xdr_string(&xdrs, &s, slen); + if(str!=NULL) + { + if(max==-1U || *str==NULL) + { + *str = s; + s = NULL; + } + else + { + strncpy(*str, s, max); + str[max-1] = 0; + } + } + } + if(s!=NULL) delete s; + return result; + } + + int get_opaque ( void ** data, unsigned int * len, unsigned int max = -1U) + { + int result = 0; + + if(ready()) + { + unsigned int slen; + char * s; + + if((result=xdr_u_int(&xdrs, &slen))!=0) + { + s = new char[slen]; + result=xdr_opaque(&xdrs, s, slen); + } + if(result!=0) + { + if(*data==NULL || max==-1U) + { + *len = slen; + *data = s; + s = NULL; + } + else { + *len = (slen>/var/log/cdevGateway.log 2>&1 & + echo -n $! +fi + +exit 0 diff --git a/sbin/cdevGateway.sh- b/sbin/cdevGateway.sh- new file mode 100755 index 0000000..d6c607b --- /dev/null +++ b/sbin/cdevGateway.sh- @@ -0,0 +1,12 @@ +#!/bin/sh + +[ -f `which cdevGateway` ] || exit 0 +[ -f /var/log/cdevGateway.log ] || exit 0 + +if [ "`whoami`" = "nobody" ] ;then + export CDEV_NAME_SERVER=`hostname -s` + cdevGateway >/var/log/cdevGateway.log 2>&1 & + echo -n $! +fi + +exit 0 diff --git a/sbin/rsvcServer.sh b/sbin/rsvcServer.sh new file mode 100755 index 0000000..cc007e5 --- /dev/null +++ b/sbin/rsvcServer.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +[ -f /usr/local/epics/base/lib/epics-setup.sh ] || exit 0 +. /usr/local/epics/base/lib/epics-setup.sh + +[ -f /usr/local/i386-glibc22-linux/cdev-1.7.2n/lib/cdev-setup.sh ] || exit 0 +. /usr/local/i386-glibc22-linux/cdev-1.7.2n/lib/cdev-setup.sh + +PATH=$CDEV/bin/$SYSNAME:$CDEV/sbin:/usr/bin:/usr/sbin:/bin:/sbin:$PATH +export PATH + +[ -f `which rsvcServer` ] || exit 0 +[ -f /var/log/cdevGateway.log ] || exit 0 + +if [ "`whoami`" = "nobody" ] ;then + export CDEV_NAME_SERVER=`hostname -s` + rsvcServer >/var/log/cdevGateway.log 2>&1 & + echo -n $! +fi + +exit 0 diff --git a/sbin/rsvcServer.sh- b/sbin/rsvcServer.sh- new file mode 100755 index 0000000..61d4912 --- /dev/null +++ b/sbin/rsvcServer.sh- @@ -0,0 +1,12 @@ +#!/bin/sh + +[ -f `which rsvcServer` ] || exit 0 +[ -f /var/log/cdevGateway.log ] || exit 0 + +if [ "`whoami`" = "nobody" ] ;then + export CDEV_NAME_SERVER=`hostname -s` + rsvcServer >/var/log/cdevGateway.log 2>&1 & + echo -n $! +fi + +exit 0 diff --git a/src/CA_TEST/Makefile b/src/CA_TEST/Makefile new file mode 100755 index 0000000..debe3cf --- /dev/null +++ b/src/CA_TEST/Makefile @@ -0,0 +1,46 @@ +######################################################################## +# Makefile for shared object +######################################################################## +.suffix: .cc .o .so +CDEVSRCROOT = $(CDEVROOT)/src +EPICSVER = r3_12 +TARGET = hp700 +#TARGET = hp + +EPICSINCLUDES = -I$(EPICS)/base/include +EPICSLIBS = -L$(EPICS)/base/lib/$(TARGET) -lca -lAs -lCom + +#EPICSINCLUDES = -I$(EPICS)/$(EPICSVER)/share/epicsH +#EPICSLIBS = -L$(EPICS)/$(EPICSVER)/Unix/$(TARGET)/bin -lca -lUnix -lCom -lPW + +ifeq ($(SHOBJ), NO) +CXX = /usr/bin/CC +A +LIBS = -L$(CDEVROOT)/lib/$(TARGET) -lEpicsCC -lEpicsCa \ + $(EPICSLIBS) -ly -ll -lm +else +CXX = /usr/bin/CC +LIBS = -L$(CDEVROOT)/lib/$(TARGET) -lEpicsCC -ly -ll -lm +endif + +CXXFLAGS = -I$(CDEVROOT)/include -g -DHP_UX + +OBJS = catest.o +OBJS1 = detachTest.o + + +.cc.o: + rm -f $@ + $(CXX) $(CXXFLAGS) -c $< -o $@ + +all: catest detachTest + +catest: $(OBJS) + rm -f $@ + $(CXX) $(CXXFLAGS) $(OBJS) $(LIBS) -o $@ + +detachTest: $(OBJS1) + rm -f $@ + $(CXX) $(CXXFLAGS) $(OBJS1) $(LIBS) -o $@ + +clean: + rm -rf *.o *.a *~ core catest detachTest ptrepository diff --git a/src/CA_TEST/a.ddl b/src/CA_TEST/a.ddl new file mode 100755 index 0000000..c7fcb51 --- /dev/null +++ b/src/CA_TEST/a.ddl @@ -0,0 +1,20 @@ +service ca { + tags {PV} + } + +class magnet { + verbs {set, get } + attributes { + memfree ca {PV=<>:memfree}; + bdl ca {PV = <>.BDL}; + bnom ca {PV = <>.BNOM }; + status ca {PV = <>R.VAL }; + } +} +magnet : +iocnl1 +MQA1C01 +MQA1C02 +MQA1C03 +MBC1C01H +; diff --git a/src/CA_TEST/catest.cc b/src/CA_TEST/catest.cc new file mode 100755 index 0000000..0ed262d --- /dev/null +++ b/src/CA_TEST/catest.cc @@ -0,0 +1,191 @@ +// test program for channel access + +#include +#include +#include +#include +#include +#include + + +static void +mycallback (int status, void *userarg, + cdevRequestObject &obj, cdevData& result) +{ + printf("user callback called+++++++++++++++++++++++++++++++++++++++\n"); + printf("call status is %d\n",status); + float fval; + result.get ("value",&fval); + printf("return value from callback is %f\n",fval); +} + +static void checkDevice() +{ + cdevData cxt; + + cxt.insert("time", 1); + cxt.insert("status", 1); + cxt.insert("displayHigh", 1); + cxt.insert("displayLow", 1); + + cdevDevice& device1 = cdevDevice::attachRef ("cdev_ai0"); + cdevDevice& device2 = cdevDevice::attachRef ("cdev_aout0"); + cdevDevice& device3 = cdevDevice::attachRef ("cdev_strin0"); + cdevData out; + cdevData result; + + device1.setContext (cxt); + int st = device1.send ("get", 0, result); + if (st != CDEV_SUCCESS) + printf("Cannot send out, database not found \n"); + double dval, dispHi, dispLo; + result.get ("value", &dval); + result.get ("displayHigh",&dispHi); + result.get ("displayLow", &dispLo); + printf("get cdev_ai0 value %f displayHigh %f displayLow %f \n",dval, + dispHi, dispLo); + st = device2.send ("get", 0, result); + result.get ("value", &dval); + printf("get cdev_aout0 value %f \n",dval); + + st = device3.send ("get", 0, result); + char temp[40]; + result.get ("value", temp, sizeof (temp)); + printf ("value from string field is < %s > \n", temp); + + st = device2.send ("get SCAN", 0, result); + + result.get ("value", temp, sizeof (temp)); + printf("result get from scan field is %s \n",temp); + + result.cleanup(); + result.insert ("value", "10 second"); + st = device2.send ("set SCAN", result, 0); + + cdevDevice::detach (device2); + cdevDevice& device5 = cdevDevice::attachRef ("cdev_aout0"); + device5.send ("get SCAN", 0, result); + result.get ("value", temp, sizeof (temp)); + printf("result get from scan field is %s \n",temp); +} + +main (int argc, char **argv) +{ + cdevSystem& system = cdevSystem::defaultSystem(); + cdevData cxt; + + checkDevice(); + + printf("finished subroutines>>>>>>>>>>>>>>>>>>>\n"); + cxt.insert("time", 1); + cxt.insert("status", 1); + cxt.insert("displayHigh", 1); + cxt.insert("displayLow", 1); + + cdevDevice& device1 = cdevDevice::attachRef ("cdev_ai0"); + cdevDevice& device2 = cdevDevice::attachRef ("cdev_aout0"); + cdevDevice& device3 = cdevDevice::attachRef ("cdev_strin0"); + cdevDevice* device10 = system.getDevice ("cdev_aout1"); + + cdevData out; + cdevData result; + + device1.setContext (cxt); + int st = device1.send ("get", 0, result); + if (st == CDEV_SUCCESS) + printf("device1 sendout success\n"); + st = device2.send ("get", 0, result); + if (st == CDEV_SUCCESS) + printf("device2 sendout success\n"); + st = device3.send ("get", 0, result); + if (st == CDEV_SUCCESS) + printf("device3 sendout success\n"); + st = device10->send ("get", 0, result); + printf ("st fro device10 is %d\n",st); + if (st == CDEV_SUCCESS) + printf("device10 sendout success\n"); + + out.cleanup(); + out.insert ("value",8723.22); + st = device2.send ("set", out, 0); + if (st == CDEV_SUCCESS) + printf("send set sync success+++++++\n"); + else + printf("send set sync failed\n"); + + device1.sendNoBlock ("get", 0, result); + device2.sendNoBlock ("get", 0, result); + + cdevCallback callback(mycallback, 0); + + device2.sendCallback ("get", out, callback); + + // youe have no way to find out whether there are something pending + // you can either do this or do system.pend () + +// int j = 0; +// while (j < 1000){ +// system.poll (); +// j++; +// } + system.pend (2.0); + + printf("###############################################\n"); + + cdevGroup g1(10), g2(5); + g1.start(); + int i; + for (i = 0; i < 1; i++) + device1.sendNoBlock ("get",out, result); + g2.start(); + device1.sendNoBlock ("get",out, result); + device2.sendNoBlock ("get",out, result); + device3.sendNoBlock ("get",0, result); + out.cleanup(); + out.insert ("value", (float)3456.78); + device2.sendNoBlock ("set", out, 0); + device2.sendNoBlock ("get HOPR", 0, result); +// device2.sendNoBlock ("get TIME", 0, result); + g1.end(); + device1.sendNoBlock ("get",out, result); + for (i = 0; i < 1; i++) + device2.sendCallback ("get", out, callback); + g2.end(); + g1.pend(10.0); + if (g1.allFinished()){ + printf("g1 transaction all finished\n"); + } + else{ + printf("g1 has unfinished transactions\n"); + } + g2.pend (10.0); + if (g2.allFinished()){ + printf("g2 transaction all finished\n"); + } + else{ + printf("g2 has unfinished transactions\n"); + } + int status[100]; + int numx = 100; + g2.status (status, numx); + for (i = 0; i < numx; i++){ + printf("status[%d] is %d\n",i, status[i]); + } + + cdevDevice::detach (device3); + + // test monitor on + g1.start (); + device1.sendCallback ("monitorOn", 0, callback); + device2.sendCallback ("monitorOn", 0, callback); +// g1.end(); + g1.pend (10.0); + if (g1.allFinished()){ + printf("g1 again finished all transaction\n"); + } + + system.pend (10.0); + + return 0; +} + diff --git a/src/CA_TEST/detachTest.cc b/src/CA_TEST/detachTest.cc new file mode 100755 index 0000000..c2dc982 --- /dev/null +++ b/src/CA_TEST/detachTest.cc @@ -0,0 +1,333 @@ +// test program for detach mechanasim + +#include +#include +#include +#include +#include +#ifndef _WIN32 + #include +#endif + +static int insertData (cdevData& out, int type, int count) +{ + int dataStatus = 0; + if (count == 1){ + switch (type){ + case 0: + { + char temp[40]; + printf ("Enter char string\n"); + scanf ("%s",temp); + dataStatus = out.insert ("value", temp); + } + break; + case 1: + case 5: + { + int val; + printf ("Enter Integer Value \n"); + scanf ("%d", &val); + dataStatus = out.insert ("value", val); + } + break; + case 2: + { + float fval; + printf ("Enter double value \n"); + scanf ("%f", &fval); + dataStatus = out.insert ("value", fval); + } + case 6: + { + double val; + float fval; + printf ("Enter double value \n"); + scanf ("%f", &fval); + val = (double)fval; + dataStatus = out.insert ("value", val); + } + break; + default: + printf ("unsupported data type %d\n", type); + break; + } + } + else { + switch (type){ + case 0: + { + static counter = 0; + char **temp = new char* [count]; + for (int i = 0; i < count; i++){ + temp[i] = new char[40]; + sprintf (temp[i], "Hello again there %d", i * counter); + } + dataStatus = out.insert ("value",temp, count); + for (i = 0; i < count; i++) + delete []temp[i]; + delete []temp; + counter++; + if (counter > 10) + counter = 0; + } + break; + case 1: + case 5: + { + static counter = 1; + int *temp = new int[count]; + for (int i = 0; i < count; i++) + temp[i] = i*counter; + dataStatus = out.insert ("value",temp, count); + delete []temp; + counter++; + if (counter > 3) + counter = 1; + } + break; + case 6: + { + static counter = 1; + double *temp = new double[count]; + for (int i = 0; i < count; i++) + temp[i] = i*(counter); + dataStatus = out.insert ("value",temp, count); + delete []temp; + counter++; + if (counter > 3) + counter = 1; + } + break; + default: + break; + } + } + return dataStatus; +} + +static void printValue (cdevData& result) +{ + size_t len1, dim, type; + int tag; + result.tagC2I ("value", &tag); + int st = result.getDim (tag, &dim); + if (dim != 0) + { + // *********************************************************************** + // * cdevBounds support added for support of arbitrary dimensional data + // *********************************************************************** + cdevBounds bounds; + st = result.getBounds (tag, &bounds, 1); + len1 = bounds.length; + } + else + len1 = 1; + printf ("Length is %d\n", len1); + type = result.getType (tag); + printf ("data type is %d\n",type); + float lval, hval; + st = result.get ("displayHigh", &hval); + if (st == CDEV_SUCCESS) + printf ("Display High limit is %f\n", hval); + st = result.get ("displayLow", &lval); + if (st == CDEV_SUCCESS) + printf ("Display Low Limit is %f\n", lval); + switch (type){ + case CDEV_INT32: + if (len1 == 1){ + int retVal; + result.get (tag, &retVal); + printf ("result is %d\n",retVal); + } + else{ + int *retVal = new int[len1]; + result.get (tag, retVal); + printf ("result is \n"); + for (int i = 0; i < len1; i++) + printf ("%d\n", retVal[i]); + printf ("__________________\n"); + delete []retVal; + } + break; + case CDEV_FLOAT: + if (len1 == 1) { + float dval; + result.get (tag, &dval); + printf ("result is %f\n", dval); + } + else { + float *dval = new float[len1]; + result.get (tag, dval); + for (int i = 0; i < len1; i++) + printf ("%f\n", dval[i]); + printf ("__________________\n"); + delete []dval; + } + break; + case CDEV_DOUBLE: + if (len1 == 1) { + double dval; + result.get (tag, &dval); + printf ("result is %f\n", dval); + } + else { + double *dval = new double[len1]; + result.get (tag, dval); + for (int i = 0; i < len1; i++) + printf ("%f\n", dval[i]); + printf ("__________________\n"); + delete []dval; + } + break; + case CDEV_STRING: + if (len1 == 1){ + char temp[40]; + result.get (tag,temp, sizeof (temp)); + printf ("result is %s\n", temp); + } + else{ + char **temp; + temp = new char* [len1]; + + result.get (tag, temp); + + printf ("Strings are \n"); + for (int i = 0; i < len1; i++){ + printf ("%s\n",temp[i]); + delete []temp[i]; + } + delete []temp; + } + break; + default: + printf ("Something is wrong\n"); + break; + } +} + +static void myCallback (int status, void *userarg, + cdevRequestObject &obj, cdevData& result) +{ + printf ("user get callback called++++++++\n"); + printValue (result); +} + +static void mySetCallback (int status, void *userarg, + cdevRequestObject &obj, cdevData& result) +{ + printf ("user set callback called======================\n"); +} + +static int done = 0; + +main (int argc, char **argv) +{ + cdevSystem& system = cdevSystem::defaultSystem (); + cdevCallback getCallback(myCallback, 0); + cdevCallback setCallback(mySetCallback, 0); + + char command[40]; + char deviceName[40], messageName[64], attname[30]; + cdevData result; + cdevData cxt; + int st = cxt.insert ("value", 100); + st = cxt.insert ("displayHigh", 1); + cxt.insert ("displayLow", 1); + + while (!done){ + fprintf (stdout, "cdevTest Command>"); + scanf ("%s", command); + if (::strcmp (command, "get") == 0){ + printf ("cdevTest devicename attribute> \n"); + scanf ("%s %s",deviceName, attname); + ::strcpy (messageName, command); + ::strcat (messageName, " "); + ::strcat (messageName, attname); + cdevDevice *dev = system.getDevice (deviceName); + cdevRequestObject *req = dev->getRequestObject (messageName); +// cdevRequestObject& req = +// cdevRequestObject::attachRef (deviceName, messageName); + req->setContext (cxt); +// cdevGroup grp; +// grp.start (); +// int st = req->sendCallback (0, getCallback); +// int st = req->sendNoBlock (0, result); + result.remove (); + int st = req->send (0, result); + if (st == CDEV_SUCCESS){ +// grp.end (); +// st = grp.pend (); +// if (grp.allFinished ()) +// printf ("All transaction finished\n"); + if (st == CDEV_SUCCESS) + result.asciiDump(); + else{ + printf("send failed-----\n"); + } + } + else + printf ("Send failed immedaitely\n"); + // detach device + cdevRequestObject::detach (req); + } + else if (::strcmp (command, "set") == 0){ + printf ("cdevTest devicename attribute> \n"); + scanf ("%s %s",deviceName, attname); + ::strcpy (messageName, command); + ::strcat (messageName, " "); + ::strcat (messageName, attname); + cdevRequestObject& req = + cdevRequestObject::attachRef (deviceName, messageName); + int type, count; + printf ("Supported type are: \n"); + printf ("0: string. 1: short. 2: float, 5: long, 6: double\n"); + printf ("Enter type and count for this channel\n"); + scanf ("%d %d",&type, &count); + cdevData out; + int dataStatus = insertData (out, type, count); + if (dataStatus == CDEV_SUCCESS){ + cdevGroup grp; + grp.start (); +// int st = req.sendCallback (out, setCallback); + int st = req.sendNoBlock (out, 0); +// int st = req.send (out, 0); + grp.end (); + st = grp.pend (); + if (grp.allFinished ()) +// if (st == CDEV_SUCCESS) + printf ("Set success\n"); + else + printf ("Set failed\n"); + cdevRequestObject::detach (req); + } + else + printf ("Data Insersion Error\n"); + } + else if (::strcmp (command, "monitorOn") == 0){ + printf ("cdevTest devicename attribute> \n"); + scanf ("%s %s",deviceName, attname); + ::strcpy (messageName, command); + ::strcat (messageName, " "); + ::strcat (messageName, attname); + cdevRequestObject& req = + cdevRequestObject::attachRef (deviceName, messageName); + cdevGroup grp; + grp.start (); + int st = req.sendCallback (0, getCallback); + grp.end (); + st = grp.pend (10.0); + if (grp.allFinished ()) + printf ("Monitor On success\n"); + else + printf ("MonitorOn failed\n"); + system.pend (50.0); + } + else if (::strcmp (command, "quit") == 0) + done = 1; + else { + printf ("Legal commands are: get, quit\n"); + } + } + +} diff --git a/src/CA_TEST/in b/src/CA_TEST/in new file mode 100755 index 0000000..bf5f062 --- /dev/null +++ b/src/CA_TEST/in @@ -0,0 +1,4 @@ + +service ca { + tags{ PV default } + } diff --git a/src/CA_TEST/t1 b/src/CA_TEST/t1 new file mode 100755 index 0000000..8c9abb9 --- /dev/null +++ b/src/CA_TEST/t1 @@ -0,0 +1,35 @@ +#include "in" + +class defaultcls + { + verbs{monitorOn, monitorOff} + } + +class magnet : defaultcls { + verbs {set, get } + attributes { + bdl ca {PV = <>.VAL}; + current ca {PV = <>.VAL, default = 1}; + kk_kl ca; + } + + messages { + "junk" dummy; + on ca {default = 3}; + "weird/something" somewhere; + } +} + +magnet : +cdev_ai0 +cdev_aout0 +cdev_aout1 +cdev_aout2 +cdev_wavef0 +cdev_wavef1 +cdev_wavef2 +cdev_wavef3 +cdev_strin0 +cdev_strout0; + + diff --git a/src/Makefile b/src/Makefile new file mode 100755 index 0000000..8acb944 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,91 @@ +CDEVSRC = $(shell pwd) +CDEVINC = $(CDEVSRC)/../include + +ifneq ("$(VERBOSE)", "YES") + MAKE := $(MAKE) -s VERBOSE=NO +endif + +DIRS = $(CDEVSRC)/callback \ + $(CDEVSRC)/cdevIO \ + $(CDEVSRC)/common \ + $(CDEVSRC)/directory \ + $(CDEVSRC)/collection \ + $(CDEVSRC)/group \ + $(CDEVSRC)/system \ + $(CDEVSRC)/device \ + $(CDEVSRC)/regexp \ + $(CDEVSRC)/c_interface \ + $(CDEVSRC)/ca + +# add your own service directory or comment ca +# $(CDEVSRC)/skeleton +# $(CDEVSRC)/ca + +BINDIRS = $(CDEVSRC)/utility +LIBDIRS = $(CDEVSRC)/lib + +default: + @echo "Type one of the following:" + @echo " make hpux for HP systems" + @echo " make hpux-sl for HP systems building shared library" + @echo " make hpux-cl for HP systems with CenterLine" + @echo " make hpux-cl-sl for HP systems with CenterLine Building shared library" + @echo " make irix5 for SGI running irix5" + @echo " make irix5-sl for SGI running irix5 building shared library" + @echo " make sunos4-gcc for SunOs 4.x and gcc" + @echo " make sunos4-gcc-sl for SunOs 4.x and gcc building shared library" + @echo " make solaris for Solaris2.x" + @echo " make solaris-sl for Solaris2.x and building shared library" + @echo " make solaris-gcc for Solaris2.x and gcc" + @echo " make solaris-gcc-sl for Solaris2.x and gcc building shared library" + @echo " make ultrix-gcc for ultrix 4.x and gcc" + @echo " make aix for IBM AIX 4.x" + @echo " make linux-sl for linux shared library" + @echo " make linux for linux archived library" + @echo " make clean" + +hpux hpux-sl hpux-cl hpux-cl-sl irix5 irix5-sl sunos4-gcc sunos4-gcc-sl solaris solaris-sl solaris-gcc solaris-gcc-sl ultrix-gcc aix linux-sl linux: + @echo "---------------------------------------------------------------" + @echo "Building CDEV Libraries for Target : $@" + @echo "---------------------------------------------------------------" + @mkdir -p $(CDEVINC) + @mkdir -p ../lib/$(TARGETDIR) + @mkdir -p ./lib/.obj + @mkdir -p ./lib/.shobj + @for dir in $(DIRS) $(LIBDIRS) $(BINDIRS); \ + do \ + echo "=> Compiling directory $$dir"; \ + $(MAKE) -C $$dir ARCH=$@ $@; \ + echo "<= Done...\n"; \ + done + @echo "---------------------------------------------------------------" + @echo "CDEV Libraries Have Been Built for Target : $@" + @echo "---------------------------------------------------------------" + +clean: + @echo "=> Cleaning source directories..." + @for dir in $(DIRS); \ + do \ + $(MAKE) -C $$dir ARCH=common clean; \ + echo " Done..."; \ + done + @echo "<= Done...\n" + @echo "=> Cleaning library directories" + @for dir in $(LIBDIRS); \ + do \ + cd $$dir; \ + rm -rf *.o *.a *.sl *.so .shobj .obj; \ + cd $(CDEVSRC); \ + done + @echo "<= Done...\n" + @for dir in $(BINDIRS); \ + do \ + $(MAKE) -C $$dir ARCH=common purge; \ + done + +purge: clean + @echo "=>Purging binary directories..." + @rm -rf ../bin + @rm -rf ../lib + @rm -f ../include/*.h ../include/*.i + @echo "<= Done...\n" diff --git a/src/Makefile.config b/src/Makefile.config new file mode 100755 index 0000000..c967ed6 --- /dev/null +++ b/src/Makefile.config @@ -0,0 +1,629 @@ +# +# The following variables are passed to each Makefile: +# +# CDEV_LIB the name of the cdev library file (usually libcdev.a) +# CXX the name of C++ compiler (CC or g++) +# CXXFLAGS the C++ compiler flags +# CC the name of c compiler (cc or gcc) +# CFLAGS the c compiler flags +# MAKELIB the command and flags for building library +# RANLIB "ranlib" = use ranlib, "true" = don't use ranlib +# XTRACXXFLAGS extra c++ flags +# XTRACFLAGS extra c flags +# OS_TYPE SYSV or BSD +# LEX the command for lex +# YACC the command for yacc +# TARGET the name of target machine +# SHOBJ building shared library or not. (SHOBJ = YES/NO) +# OBJDIR tempary objects directory for library (../lib) +# LIBLIB final library diretory (../../lib/$(TARGET)) +# INCDIR include directory for header file (../../include) +# BINDIR binary directory for executables (../../bin/$(TARGET)) + +.suffix: .o .C .c .cc .i .so + +# ****************************************************************************** +# * This section was added in order to support the same version of cdev across +# * multiple versions of an operating system. +# ****************************************************************************** +OS := $(shell uname -s) + +# ****************************************************************************** +# * Only define the DEBUGFLAG if DEBUG has been specified by the user. +# ****************************************************************************** +ifdef DEBUG + DEBUGFLAG = -g +else + ifeq ($(OS), HP_UX) + DEBUGFLAG = +O2 + else + ifeq ($(OS), Linux) + DEBUGFLAG = -O2 + endif + endif +endif + +# ****************************************************************************** +# * This is the compressed command echo mechanism +# ****************************************************************************** +ifeq ("$(VERBOSE)", "") + VERBOSE = NO + MAKE := $(MAKE) -s VERBOSE=NO +endif + +ifeq ("$(VERBOSE)", "NO") + CXX_CMD_ECHO = @echo " => $(CXX) -c $( $(CC) -c $( Cleaning $(shell pwd)" + +ifeq ($(OS), HP-UX) +OS_VERSION_DEF := -D_OS_MAJOR_=$(OS_MAJOR_NUM) -D_OS_MINOR_=$(OS_MINOR_NUM) +endif + +# Rules + +# ***************************************************** +# * RULES FOR BUILDING ARCHIVE OBJECT FILES +# ***************************************************** +.obj/$(TARGETDIR)/%.o : %.cc + rm -f $@ + $(CXX_CMD_ECHO) + $(CXX) $(CXXFLAGS) $(XTRACXXFLAGS) $(OS_VERSION_DEF) -c $< -o $@ + + +.obj/$(TARGETDIR)/%.o : %.C + rm -f $@ + $(CXX_CMD_ECHO) + $(CXX) $(CXXFLAGS) $(XTRACXXFLAGS) $(OS_VERSION_DEF) -c $< -o $@ + +.obj/$(TARGETDIR)/%.o : %.c + rm -f $@ + $(CC_CMD_ECHO) + $(CC) $(CFLAGS) $(XTRACFLAGS) $(OS_VERSION_DEF) -c $< -o $@ + + +# ***************************************************** +# * RULES FOR BUILDING SHARED OBJECT FILES +# ***************************************************** +.shobj/$(TARGETDIR)/%.o : %.cc + rm -f $@ + $(CXX_CMD_ECHO) + $(CXX) $(CXXFLAGS) $(XTRACXXFLAGS) $(OS_VERSION_DEF) -c $< -o $@ + + +.shobj/$(TARGETDIR)/%.o : %.C + rm -f $@ + $(CXX_CMD_ECHO) + $(CXX) $(CXXFLAGS) $(XTRACXXFLAGS) $(OS_VERSION_DEF) -c $< -o $@ + + +.shobj/$(TARGETDIR)/%.o : %.c + rm -f $@ + $(CC_CMD_ECHO) + $(CC) $(CFLAGS) $(XTRACFLAGS) $(OS_VERSION_DEF) -c $< -o $@ + + +# ***************************************************** +# * GENERIC RULES +# ***************************************************** +.cc.o: + rm -f $@ + $(CXX_CMD_ECHO) + $(CXX) $(CXXFLAGS) $(XTRACXXFLAGS) $(OS_VERSION_DEF) -c $< -o $@ + + +.C.o: + rm -f $@ + $(CXX_CMD_ECHO) + $(CXX) $(CXXFLAGS) $(XTRACXXFLAGS) $(OS_VERSION_DEF) -c $< -o $@ + + +.c.o: + rm -f $@ + $(CC_CMD_ECHO) + $(CC) $(CFLAGS) $(XTRACFLAGS) $(OS_VERSION_DEF) -c $< -o $@ + diff --git a/src/NMakefile.config b/src/NMakefile.config new file mode 100644 index 0000000..f0c307c --- /dev/null +++ b/src/NMakefile.config @@ -0,0 +1,13 @@ +.SUFFIXES: .cc .obj + +ARCH = WINNT-4.0 +SHOBJ = YES +HAIL = NO +FAIRWELL = NO + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +CXXINCLUDES = /I ..\collection /I ..\device /I ..\system /I ..\cdevIO \ + /I ..\group /I ..\directory /I ..\common /I ..\callback \ + /I ..\xdr /I ..\regexp +CXXEXTRA = /D "_CDEV_CORE_EXPORTS_=1" /D "_HAS_CA" diff --git a/src/NMakefile.mak b/src/NMakefile.mak new file mode 100644 index 0000000..6563cd2 --- /dev/null +++ b/src/NMakefile.mak @@ -0,0 +1,48 @@ +DIRS = callback\ + cdevIO\ + common\ + directory\ + collection\ + group\ + system\ + device\ + regexp\ + xdr\ + c_interface + +BINDIRS = utility +LIBDIRS = lib ca + +all : + @echo --------------------------------------------------------------- + @echo Building CDEV Libraries for Target : WINNT-4.0 + @echo --------------------------------------------------------------- + -@if not exist ..\include mkdir ..\include + @for %x in ($(DIRS) $(LIBDIRS) $(BINDIRS)) DO @$(MAKE) /NOLOGO /f NMakefile.mak SUBTARGETDIR=%x SUBTARGET=all subtarget + @echo --------------------------------------------------------------- + @echo CDEV Libraries Have Been Built for Target : WINNT-4.0 + @echo --------------------------------------------------------------- + +clean : + @for %x in ($(DIRS) $(LIBDIRS) $(BINDIRS)) DO @$(MAKE) /NOLOGO /f NMakefile.mak SUBTARGETDIR=%x SUBTARGET=clean subtarget + -@for %x in (..\include\*.h ..\include\*.i) DO @erase %x + +purge : + @for %x in ($(DIRS) $(LIBDIRS) $(BINDIRS)) DO @$(MAKE) /NOLOGO /f NMakefile.mak SUBTARGETDIR=%x SUBTARGET=purge subtarget + -@for %x in (..\include\*.h ..\include\*.i) DO @erase %x + -@rmdir /s /q ..\lib + -@rmdir /s /q ..\bin + +!IF "$(SUBTARGETDIR)" == "" +subtarget : + -@echo SUBTARGETDIR variable must be defined to build subtargets +!ELSE +!IF "$(SUBTARGET)" == "" +SUBTARGET = all +!ENDIF +subtarget : + -@echo =^> Building target $(SUBTARGET) in directory $(SUBTARGETDIR) + @cd $(SUBTARGETDIR) + @$(MAKE) /NOLOGO /f NMakefile.mak $(SUBTARGET) + @echo ^<= Done... +!ENDIF diff --git a/src/bin/Makefile b/src/bin/Makefile new file mode 100755 index 0000000..d3867bc --- /dev/null +++ b/src/bin/Makefile @@ -0,0 +1,7 @@ +include $(CDEVROOT)/src/Makefile.common + +all: + @echo Binaries executables have been generated + +clean: clean_hail + cd $(HOSTBIN); rm -rf *.o *.a *~ core ptrepository cdevUtil diff --git a/src/c_interface/.shobj/Linux/cdev.o b/src/c_interface/.shobj/Linux/cdev.o new file mode 100644 index 0000000..b5a1ab4 Binary files /dev/null and b/src/c_interface/.shobj/Linux/cdev.o differ diff --git a/src/c_interface/Makefile b/src/c_interface/Makefile new file mode 100755 index 0000000..2bee3bc --- /dev/null +++ b/src/c_interface/Makefile @@ -0,0 +1,50 @@ +# Makefile for C interface directory +# +# cdev C interface directory +# +# Makefile,v +# Revision 1.4 1998/08/17 14:04:44 akers +# Added 'Minor Version Number' to TARGETDIR in Makefiles +# +# Revision 1.3 1996/06/26 15:54:05 akers +# Modifications to support multiple OS Versions +# +# Revision 1.2 1996/05/14 20:37:59 akers +# Makefile modifications +# +# Revision 1.1 1995/12/14 19:06:24 chen +# Makefile for C interface +# +# +# +include ../Makefile.config + + +ifeq ($(SHOBJ),YES) + OBJTYPE=.shobj/$(TARGETDIR) +else + OBJTYPE=.obj/$(TARGETDIR) +endif + +ifeq ($(INCDIR), ) + INCDIR = ../.. +endif + +OBJS = $(OBJTYPE)/cdev.o + +targets: $(OBJTYPE) $(OBJDIR)/$(OBJTYPE) copyobjs copyincs + +$(OBJTYPE) : + @mkdir -p $(OBJTYPE) + +$(OBJDIR)/$(OBJTYPE) : + @mkdir -p $(OBJDIR)/$(OBJTYPE) + +copyobjs: $(OBJS) + @cp -f $(OBJS) $(OBJDIR)/$(OBJTYPE) + +copyincs: + @cp -f *.h $(INCDIR) + +clean: clean_hail + @rm -rf *.o .obj .shobj core *~ diff --git a/src/c_interface/NMakefile.mak b/src/c_interface/NMakefile.mak new file mode 100755 index 0000000..b334d1b --- /dev/null +++ b/src/c_interface/NMakefile.mak @@ -0,0 +1,13 @@ +include ..\NMakefile.config + +OBJS = $(OBJDIR)\cdev.obj + +targets : copyobjs copyincs + +copyobjs : $(OBJS) + -@if not exist ..\lib\$(OBJDIR) mkdir ..\lib\$(OBJDIR) + -@for %x in ($(OBJDIR)\*.obj) DO @copy %x ..\lib\$(OBJDIR) > nul + +copyincs : + -@for %x in (*.h *.i) DO @copy %x $(CDEV)\include > nul + diff --git a/src/c_interface/cdev.cc b/src/c_interface/cdev.cc new file mode 100755 index 0000000..ce31f0d --- /dev/null +++ b/src/c_interface/cdev.cc @@ -0,0 +1,650 @@ +/*----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + *----------------------------------------------------------------------------- + * + * Description: + * C interface for CDEV (internal implementation) + * + * Authors: Danjin Wu & Jie Chen + * + * Revision History: + * cdev.cc,v + * Revision 1.3 1998/03/10 20:25:09 chen + * change lower bound for waiting forever inside cdevPend routine + * + * Revision 1.2 1996/03/22 17:56:45 chen + * add cdevFdChangedCallback + * + * Revision 1.1 1995/12/14 19:07:27 chen + * C interface implementation of CDEV + * + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cdev.h" + +//==================================================================== +// C interface for cdevData +//==================================================================== +int cdevDataAllocate (cdev_data_t * id) { + cdevData* tmp = new cdevData; + *id = (cdev_data_t) tmp; + return *id == 0 ? CDEV_INVALIDOBJ : CDEV_SUCCESS; +} + +void cdevDataFree (cdev_data_t id) { + delete (cdevData *)id; +} + +int cdevDataTagC2I (char *tag, int *tagid) { + return cdevData::tagC2I(tag, tagid); +} + +int cdevDataTagI2C (int tagid, char **tag) { + return cdevData::tagI2C(tagid, (char* &)tag); +} + +void cdevDataInsertTag (int tagid, char *tag) { + cdevData::insertTag(tagid, tag); +} + +int cdevDataInsert (cdev_data_t id, int tagid, int type, void *data) { + int status=CDEV_ERROR; + cdevData* dataObj = (cdevData *) id; + if (dataObj == NULL) return status; + switch(type) + { + case CDEV_BYTE: + status = dataObj->insert(tagid, *(BYTE *)data); + break; + case CDEV_INT16: + status = dataObj->insert(tagid, *(short *)data); + break; + case CDEV_UINT16: + status = dataObj->insert(tagid, *(unsigned short *)data); + break; + case CDEV_INT32: + status = dataObj->insert(tagid, *(long *)data); + break; + case CDEV_UINT32: + status = dataObj->insert(tagid, *(unsigned long *)data); + break; + case CDEV_FLOAT: + status = dataObj->insert(tagid, *(float *)data); + break; + case CDEV_DOUBLE: + status = dataObj->insert(tagid, *(double *)data); + break; + case CDEV_STRING: + status = dataObj->insert(tagid, (char *)data); + break; + case CDEV_TIMESTAMP: + status = dataObj->insert(tagid, *(cdev_TS_STAMP *)data); + break; + default: + break; + } + return status; +} + +int cdevDataInsertArray (cdev_data_t id, int tagid, int type, void *data, + size_t len, size_t ndim) +{ + int status=CDEV_ERROR; + cdevData* dataObj = (cdevData *) id; + if (dataObj == NULL) return status; + switch(type) + { + case CDEV_BYTE: + if(ndim == 0) + status = dataObj->insert(tagid, *(BYTE *)data); + else if (ndim > 0) + status = dataObj->insert(tagid, (BYTE *)data, len, ndim); + break; + case CDEV_INT16: + if(ndim == 0) + status = dataObj->insert(tagid, *(short *)data); + else if (ndim > 0) + status = dataObj->insert(tagid, (short *)data, len, ndim); + break; + case CDEV_UINT16: + if(ndim == 0) + status = dataObj->insert(tagid, *(unsigned short *)data); + else if (ndim > 0) + status = dataObj->insert(tagid, (unsigned short *)data, len, ndim); + break; + case CDEV_INT32: + if(ndim == 0) + status = dataObj->insert(tagid, *(long *)data); + else if (ndim > 0) + status = dataObj->insert(tagid, (long *)data, len, ndim); + break; + case CDEV_UINT32: + if(ndim == 0) + status = dataObj->insert(tagid, *(unsigned long *)data); + else if (ndim > 0) + status = dataObj->insert(tagid, (unsigned long *)data, len, ndim); + break; + case CDEV_FLOAT: + if(ndim == 0) + status = dataObj->insert(tagid, *(float *)data); + else if (ndim > 0) + status = dataObj->insert(tagid, (float *)data, len, ndim); + break; + case CDEV_DOUBLE: + if(ndim == 0) + status = dataObj->insert(tagid, *(double *)data); + else if (ndim > 0) + status = dataObj->insert(tagid, (double *)data, len, ndim); + break; + case CDEV_STRING: + if(ndim == 0) + status = dataObj->insert(tagid, (char *)data); + else if (ndim > 0) + dataObj->insert(tagid, (char **)data, len, ndim); + break; + case CDEV_TIMESTAMP: + if(ndim == 0) + status = dataObj->insert(tagid, *(cdev_TS_STAMP *)data); + break; + default: + break; + } + return status; +} + +int cdevDataGet (cdev_data_t id, int tagid, int type, void *data) { + cdevData* dataObj = (cdevData *) id; + int status = CDEV_NOTFOUND; + if (dataObj == NULL) return status; + switch(type) + { + case CDEV_BYTE: + status = dataObj->get(tagid, (BYTE *)data); + break; + case CDEV_INT16: + status = dataObj->get(tagid, (short *)data); + break; + case CDEV_UINT16: + status = dataObj->get(tagid, (unsigned short *)data); + break; + case CDEV_INT32: + status = dataObj->get(tagid, (long *)data); + break; + case CDEV_UINT32: + status = dataObj->get(tagid, (unsigned long *)data); + break; + case CDEV_FLOAT: + status = dataObj->get(tagid, (float *)data); + break; + case CDEV_DOUBLE: + status = dataObj->get(tagid, (double *)data); + break; + case CDEV_STRING: + status = dataObj->get(tagid, (char **)data); + break; + case CDEV_TIMESTAMP: + status = dataObj->get(tagid, (cdev_TS_STAMP *)data); + break; + default: + break; + } + return status; +} + +int cdevDataFind (cdev_data_t id, int tagid, void **data) { + cdevData* dataObj = (cdevData *) id; + if (dataObj == NULL) return CDEV_NOTFOUND; + return dataObj->find(tagid, (void* &)data); +} + +int cdevDataGetType (cdev_data_t id, int tagid, int *type) { + cdevData* dataObj = (cdevData *) id; + if (dataObj == NULL) return CDEV_NOTFOUND; + *type = dataObj->getType(tagid); + if (*type == CDEV_INVALID) return CDEV_NOTFOUND; + else return CDEV_SUCCESS; +} + +int cdevDataGetDim (cdev_data_t id, int tagid, size_t *dim) { + cdevData* dataObj = (cdevData *) id; + if (dataObj == NULL) return CDEV_NOTFOUND; + return dataObj->getDim(tagid, dim); +} + +int cdevDataGetElems (cdev_data_t id, int tagid, size_t *elems) { + cdevData* dataObj = (cdevData *) id; + if (dataObj == NULL) return CDEV_NOTFOUND; + return dataObj->getElems(tagid, elems); +} + +int cdevDataGetBounds (cdev_data_t id, int tagid, size_t *bounds, size_t bsize) +{ + cdevData* dataObj = (cdevData *) id; + if (dataObj == NULL) return CDEV_NOTFOUND; + return dataObj->getBounds(tagid, bounds, bsize); +} + +int cdevDataSetBounds (cdev_data_t id, int tagid, size_t *bounds, size_t bsize) +{ + cdevData* dataObj = (cdevData *) id; + if (dataObj == NULL) return CDEV_ERROR; + return dataObj->setBounds(tagid, bounds, bsize); +} + +void cdevDataRemoveAll (cdev_data_t id) { + cdevData* dataObj = (cdevData *) id; + if (dataObj != NULL) dataObj->remove(); +} + +void cdevDataRemove (cdev_data_t id, int tagid) { + cdevData* dataObj = (cdevData *) id; + if (dataObj != NULL) dataObj->remove(tagid); +} + +int cdevDataChangeTag (cdev_data_t id, int tagid, int newtagid) { + cdevData* dataObj = (cdevData *) id; + if (dataObj == NULL) return CDEV_ERROR; + return dataObj->changeTag(tagid, newtagid); +} + +#ifdef _WIN32 +void cdevDataAsciiDump (cdev_data_t id) { + cdevData* dataObj = (cdevData *) id; + if (dataObj != NULL) dataObj->asciiDump(); +} +#else +void cdevDataAsciiDump (cdev_data_t id, FILE *fp) { + cdevData* dataObj = (cdevData *) id; + if (dataObj != NULL) dataObj->asciiDump(fp); +} +#endif + +void cdevDataCopy (cdev_data_t from, cdev_data_t *to) { + cdevData* tmp = (cdevData *)from ; + *to = (cdev_data_t)tmp; +} + +//========================================================================== +// cdevCallback C interface +//========================================================================== +static void cdevTempCallback (int status, + void* userarg, + cdevRequestObject& obj, + cdevData& data) +{ + cdev_cbk_t cbkid = (cdev_cbk_t)userarg; + cdevCbkFunc func = cbkid->func; + void* arg = cbkid->arg; + (*func)(status, arg, (cdev_request_t)&obj, (cdev_data_t)&data); +} + +int cdevCbkAllocate (cdevCbkFunc func, void* arg, cdev_cbk_t* id) +{ + cdev_cbk_t cbk = (cdev_cbk_t)::malloc (sizeof (cdev_cbk)); + *id = cbk; + if (cbk) { + cbk->func = func; + cbk->arg = arg; + cdevCallback* cxxcbk = new cdevCallback (cdevTempCallback, (void *)cbk); + cbk->cxxpart = (void *)cxxcbk; + } + return *id == 0 ? CDEV_INVALIDOBJ : CDEV_SUCCESS; +} + +void cdevCbkFree (cdev_cbk_t id) +{ + cdevCallback *cxxcbk = (cdevCallback *)(id->cxxpart); + delete cxxcbk; + ::free (id); +} + +//========================================================================== +// cdevSystem C interface +//========================================================================== +int cdevDefaultSystem (cdev_system_t *id) +{ + cdevSystem& system = cdevSystem::defaultSystem (); + *id = (cdev_system_t)&system; + return CDEV_SUCCESS; +} + +int cdevGetFds (int fds[], int* numFds) +{ + cdevSystem& system = cdevSystem::defaultSystem (); + return system.getFd (fds, *numFds); +} + +int addFdChangedCallback (cdevFdChangedCallback cbk, void* arg) +{ + cdevSystem& system = cdevSystem::defaultSystem (); + return system.addFdChangedCallback (cbk, arg); +} + +int cdevFlush (void) +{ + cdevSystem& system = cdevSystem::defaultSystem (); + return system.flush (); +} + +int cdevPend (double seconds) +{ + assert (seconds >= 0); + cdevSystem& system = cdevSystem::defaultSystem (); + if (seconds > 0.000000001) + return system.pend (seconds); + else { + while (1) + system.pend (); + } +} + +int cdevPoll (void) +{ + cdevSystem& system = cdevSystem::defaultSystem (); + return system.poll (); +} + +int cdevAutoErrorOn (void) +{ + cdevSystem& system = cdevSystem::defaultSystem (); + return system.autoErrorOn (); +} + +int cdevAutoErrorOff (void) +{ + cdevSystem& system = cdevSystem::defaultSystem (); + return system.autoErrorOff (); +} + +void cdevSetThreshold (int errorThreshold) +{ + cdevSystem& system = cdevSystem::defaultSystem (); + system.setThreshold (errorThreshold); +} + +void cdevSetErrorHandler (cdevErrHandler func) +{ + cdevSystem& system = cdevSystem::defaultSystem (); + system.setErrorHandler ((cdevErrorHandler)func); +} + +int cdevReportError (int severity, char* name, + cdev_request_t req, char* format, ...) +{ + va_list argp; + char msg[1024]; + char *p = msg; + int status = 0; + + sprintf(msg,"%-10s %d > ",name, severity); + p += ::strlen (msg); + + va_start (argp, format); + status = vsprintf(p, format, argp); + va_end (argp); + + cdevSystem& system = cdevSystem::defaultSystem (); + system.reportError (severity, msg, (cdevRequestObject *)req); + return status; +} + + +//========================================================================= +// C interface for device +//========================================================================= +int cdevSend (char* device, char* msg, + cdev_data_t out, cdev_data_t result) +{ + cdevRequestObject *obj = cdevRequestObject::attachPtr (device, msg); + if (obj) + return obj->send ((cdevData *)out, (cdevData *)result); + else + return CDEV_ERROR; +} + +int cdevSendNoBlock (char* device, char* msg, + cdev_data_t out, cdev_data_t result) +{ + cdevRequestObject *obj = cdevRequestObject::attachPtr (device, msg); + if (obj) + return obj->sendNoBlock ((cdevData *)out, (cdevData *)result); + else + return CDEV_ERROR; +} + +int cdevSendCallback (char* device, char* msg, + cdev_data_t out, cdev_cbk_t cbk) +{ + cdevRequestObject *obj = cdevRequestObject::attachPtr (device, msg); + if (obj) { + cdevCallback* cxxcbk = (cdevCallback *)(cbk->cxxpart); + return obj->sendCallback ((cdevData *)out, *cxxcbk); + } + else + return CDEV_ERROR; +} + +int cdevGetContext (char* device, cdev_data_t* cxt) +{ + cdevDevice *dev = cdevDevice::attachPtr (device); + if (dev) { + cdevData& data = dev->getContext (); + cdevData* ncxt = new cdevData (data); + *cxt = (cdev_data_t)ncxt; + } + else + *cxt = 0; + return *cxt == 0 ? CDEV_INVALIDOBJ : CDEV_SUCCESS; +} + +int cdevSetContext (char* device, cdev_data_t cxt) +{ + cdevData* data = (cdevData *)cxt; + cdevDevice *dev = cdevDevice::attachPtr (device); + if (dev) + return dev->setContext (*data); + else + return CDEV_ERROR; +} + +int cdevSetPrivate (char* device, void* data) +{ + cdevDevice *dev = cdevDevice::attachPtr (device); + if (dev) { + dev->setPrivate (data); + return CDEV_SUCCESS; + } + else + return CDEV_ERROR; +} + +int cdevGetPrivate (char* device, void** data) +{ + cdevDevice *dev = cdevDevice::attachPtr (device); + if (dev) { + *data = dev->getPrivate (); + return CDEV_SUCCESS; + } + else + return CDEV_ERROR; +} + + +//========================================================================= +// cdevRequestObject C interface +//========================================================================= +int cdevRequestAllocate (char* device, char *msg, + cdev_request_t* id) +{ + cdevRequestObject* obj = cdevRequestObject::attachPtr (device, msg); + *id = (cdev_request_t)obj; + return *id == 0 ? CDEV_INVALIDOBJ : CDEV_SUCCESS; +} + +void cdevRequestFree (cdev_request_t id) +{ + cdevRequestObject::detach ((cdevRequestObject *)id); +} + +int cdevRequestSend (cdev_request_t id, + cdev_data_t out, + cdev_data_t result) +{ + return ((cdevRequestObject *)id)->send ((cdevData *)out, (cdevData *)result); +} + +int cdevRequestSendNoBlock (cdev_request_t id, + cdev_data_t out, + cdev_data_t result) +{ + return ((cdevRequestObject *)id)->sendNoBlock ((cdevData *)out, + (cdevData *)result); +} + +int cdevRequestSendCallback (cdev_request_t id, + cdev_data_t out, + cdev_cbk_t cbk) +{ + cdevCallback* cxxcbk = (cdevCallback *)(cbk->cxxpart); + return ((cdevRequestObject *)id)->sendCallback ((cdevData *)out, + *cxxcbk); +} + +int cdevRequestState (cdev_request_t id) +{ + return ((cdevRequestObject *)id)->getState (); +} + +int cdevRequestAccess (cdev_request_t id) +{ + return ((cdevRequestObject *)id)->getAccess (); +} + +int cdevRequestDevice (cdev_request_t id, char** device) +{ + cdevRequestObject* obj = (cdevRequestObject *)id; + *device = new char[::strlen (obj->device().name()) + 1]; + ::strcpy (*device, obj->device().name()); + return CDEV_SUCCESS; +} + +int cdevRequestMessage (cdev_request_t id, char** message) +{ + cdevRequestObject* obj = (cdevRequestObject *)id; + *message = new char[::strlen (obj->message()) + 1]; + ::strcpy (*message, obj->message ()); + return CDEV_SUCCESS; +} + +int cdevRequestGetContext (cdev_request_t id, cdev_data_t* cxt) +{ + cdevData& data = ((cdevRequestObject *)id)->getContext (); + cdevData* ncxt = new cdevData (data); + *cxt = (cdev_data_t)ncxt; + return *cxt == 0 ? CDEV_INVALIDOBJ : CDEV_SUCCESS; +} + +int cdevRequestSetContext (cdev_request_t id, cdev_data_t cxt) +{ + return ((cdevRequestObject *)id)->setContext (*(cdevData *)cxt); +} + +int cdevRequestGetPrivate (cdev_request_t id, void** data) +{ + *data = ((cdevRequestObject *)id)->getPrivate (); + return CDEV_SUCCESS; +} + +int cdevRequestSetPrivate (cdev_request_t id, void* data) +{ + ((cdevRequestObject *)id)->setPrivate (data); + return CDEV_SUCCESS; +} + +//======================================================================== +// C Interface for cdevGroup +//======================================================================== +int cdevGroupAllocate (cdev_group_t* id) +{ + cdevGroup* grp = new cdevGroup (); + *id = (cdev_group_t)grp; + return *id == 0 ? CDEV_INVALIDOBJ : CDEV_SUCCESS; +} + +void cdevGroupFree (cdev_group_t id) +{ + delete (cdevGroup *)id; +} + +int cdevGroupStart (cdev_group_t id) +{ + return ((cdevGroup *)id)->start (); +} + +int cdevGroupEnd (cdev_group_t id) +{ + return ((cdevGroup *)id)->end (); +} + +int cdevGroupPoll (cdev_group_t id) +{ + return ((cdevGroup *)id)->poll (); +} + +int cdevGroupPend (cdev_group_t id, double seconds) +{ + assert (seconds >= 0); + if (seconds > 0.0000001) + return ((cdevGroup *)id)->pend (seconds); + else + return ((cdevGroup *)id)->pend (); +} + +int cdevGroupFlush (cdev_group_t id) +{ + return ((cdevGroup *)id)->flush (); +} + +int cdevGroupAllFinished (cdev_group_t id) +{ + return ((cdevGroup *)id)->allFinished (); +} + +int cdevGroupStatus (cdev_group_t id, int status[], int* nstatus) +{ + return ((cdevGroup *)id)->status (status, *nstatus); +} + +int cdevGroupExecDeferred (cdev_group_t id) +{ + ((cdevGroup *)id)->execDeferred (); + return CDEV_SUCCESS; +} + +int cdevGroupExecImmediate (cdev_group_t id) +{ + ((cdevGroup *)id)->execImmediate (); + return CDEV_SUCCESS; +} + +int cdevGroupExecutionMode (cdev_group_t id, int* mode) +{ + *mode = ((cdevGroup *)id)->executionMode (); + return CDEV_SUCCESS; +} + + diff --git a/src/c_interface/cdev.h b/src/c_interface/cdev.h new file mode 100755 index 0000000..3875332 --- /dev/null +++ b/src/c_interface/cdev.h @@ -0,0 +1,393 @@ +/*----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + *----------------------------------------------------------------------------- + * + * Description: + * C public interface for CDEV + * + * Authors: Danjin Wu & Jie Chen + * + * Revision History: + * cdev.h,v + * Revision 1.3 1997/08/27 18:24:18 chen + * include cdevVersion.h + * + * Revision 1.2 1996/03/22 17:56:51 chen + * add cdevFdChangedCallback + * + * Revision 1.1 1995/12/14 19:09:16 chen + * cdev C interface for C programs + * + * + */ +#ifndef _CDEV_CBINDING_H +#define _CDEV_CBINDING_H + +#include +#include +#include +#include +#include + +typedef long cdev_data_t; +typedef long cdev_request_t; +typedef long cdev_system_t; +typedef long cdev_group_t; + +/************************************************************************* + * User error reporting function * + *************************************************************************/ +typedef void (*cdevErrHandler) (int severity, + char* text, + cdev_request_t req); + +/************************************************************************* + * User fd changed callback function * + *************************************************************************/ +typedef void (*cdevFdChangedCallback) (int fd, + int opened, + void* arg); + +/************************************************************************** + * User callback function * + *************************************************************************/ +typedef void (*cdevCbkFunc) (int status, + void* userarg, + cdev_request_t req, + cdev_data_t data); + +typedef struct _cbk_t_ +{ + cdevCbkFunc func; + void* arg; + /* the following element is not for public use */ + void* cxxpart; +}cdev_cbk, *cdev_cbk_t; + +/************************************************************************** + * HPUX C call C++ convention * + * User must call this before any other routines to * + * Initialize all static objects * + **************************************************************************/ +#ifdef __hpux +#define CDEV_INIT() (_main () ) +#endif + +/************************************************************************** + * CDEV supported data types inside cdev_data_t * + **************************************************************************/ +#define CDEV_BYTE_ 0 /* unsigned character */ +#define CDEV_INT_16 1 /* 16 bits integer */ +#define CDEV_UINT_16 2 /* unsigned 16 bits integer */ +#define CDEV_INT_32 3 /* 32 bits integer */ +#define CDEV_UINT_32 4 /* unsigned 32 bits integer */ +#define CDEV_FLT 5 /* float */ +#define CDEV_DBL 6 /* double */ +#define CDEV_STR 7 /* character string */ +#define CDEV_TS 8 /* structured time stamp with sec and nsec */ +#define CDEV_INVALID_TYPE 9 /* not belongs to any type above */ + +#define CDEV_IMMEDIATE 0 /* cdev group exection immediately */ +#define CDEV_DEFERRED 1 /* cdev group exection deferred */ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************** + * C interface for cdev_data_t * + *************************************************************************/ + +/* create and allocate for cdev_data_t */ +extern CDEVAPI int cdevDataAllocate (cdev_data_t *id); + +/* free memory associated with cdev_data_t */ +extern CDEVAPI void cdevDataFree (cdev_data_t id); + +/* convert a character string tag to an integer tag */ +extern CDEVAPI int cdevDataTagC2I (char *tag, int *tagid); + +/* convert an integer tag to a character string tag. */ +/* the return tag is a pointer to internal char string. */ +/* do not free the tag !!! */ +extern CDEVAPI int cdevDataTagI2C (int tagid, char **tag); + +/* insert an new tag to cdev_data_t data */ +extern CDEVAPI void cdevDataInsertTag (int tagid, char *tag); + +/* insert a new data with data type 'type' pointed by data */ +extern CDEVAPI int cdevDataInsert (cdev_data_t id, int tagid, + int type, void *data); + +/* insert an array of data into cdev_data_t */ +extern CDEVAPI int cdevDataInsertArray (cdev_data_t id, int tagid, + int type, void *data, + size_t len, size_t ndim); + +/* retrieve data with tag 'tagid' to memory pointed by 'data' */ +extern CDEVAPI int cdevDataGet (cdev_data_t id, int tagid, + int type, void *data); + +/* return the memory address of data with tag 'tagid' */ +extern CDEVAPI int cdevDataFind (cdev_data_t id, int tagid, void **data); + +/* return data type associated with tag 'tagid' */ +extern CDEVAPI int cdevDataGetType (cdev_data_t id, int tagid, int *type); + +/* return dimention information with tag 'tagid' */ +extern CDEVAPI int cdevDataGetDim (cdev_data_t id, int tagid, size_t *dim); + +/* get number of elements associated with tag 'tagid' */ +extern CDEVAPI int cdevDataGetElems (cdev_data_t id, int tagid, size_t *elems); + +/* get information about where to start/end inside the multiple */ +/* dimentional array of data for this tag 'tagid' */ +extern CDEVAPI int cdevDataGetBounds (cdev_data_t id, int tagid, + size_t *bounds, size_t bsize); + +/* set information about where to start/end inside the multiple */ +/* dimentional array of data for this tag 'tagid' */ +extern CDEVAPI int cdevDataSetBounds (cdev_data_t id, int tagid, + size_t *bounds, size_t bsize); + +/* remove all data inside cdev_data_t 'id' */ +extern CDEVAPI void cdevDataRemoveAll (cdev_data_t id); + +/* remove a single data item from a cdev_data_t with tag 'tagid' */ +extern CDEVAPI void cdevDataRemove (cdev_data_t id, int tagid); + +/* change tag associated with a data item from 'tagid' to 'newtagid' */ +extern CDEVAPI int cdevDataChangeTag (cdev_data_t id, int tagid, int newtagid); + +/* print out ASCII representation of all internal data of 'id' */ +#ifdef _WIN32 +extern CDEVAPI void cdevDataAsciiDump (cdev_data_t id); +#else +extern CDEVAPI void cdevDataAsciiDump (cdev_data_t id, FILE *fp); +#endif + +/* copy cdev_data_t from 'from' to 'to' */ +extern CDEVAPI void cdevDataCopy (cdev_data_t from, cdev_data_t *to); + +/************************************************************************* + * C interface for setting up user callback routines * + ************************************************************************/ + +/* create cdev_cbk_t structure with 'func' and 'arg' */ +extern CDEVAPI int cdevCbkAllocate (cdevCbkFunc func, void* arg, cdev_cbk_t* id); + +/* destroy/free cdev_cbk_t structure pointed by id */ +extern CDEVAPI void cdevCbkFree (cdev_cbk_t id); + +/************************************************************************ + * C interface for cdev global system * + ***********************************************************************/ + +/* get a handle on the default system, do not use it now :-) */ +extern CDEVAPI int cdevDefaultSystem (cdev_system_t* sys); + +/* return all file descriptors inside the cdev. caller provide */ +/* buffer for fds and intial value of numFds should be the buffer */ +/* size. e.g. int fds[10], numFds = 10, cdevGetFds (fds, &numFds) */ +/* If success, numFds has real number of fd */ +extern CDEVAPI int cdevGetFds (int fds[], int* numFds); + +/* add a callback function which will be called when file */ +/* descriptors monitored by the system closed/opend */ +/* Note: service dependent. Underlying cdevService must provide */ +/* some mechanism to notify the system (see caService) */ +extern CDEVAPI int addFdChangedCallback (cdevFdChangedCallback cbk, void* arg); + +/* flush out all network requests */ +extern CDEVAPI int cdevFlush (void); + +/* wait for network requests to come back for upto 'seconds' */ +/* long. If seconds = 0.0, wait forever */ +extern CDEVAPI int cdevPend (double seconds); + +/* poll the network to see whether there are outstanding I/O */ +/* events on all communication channels. */ +extern CDEVAPI int cdevPoll (void); + +/* turn automatic error reporting mechanism on: system error */ +/* reporting function will be in charge */ +extern CDEVAPI int cdevAutoErrorOn (void); + +/* turn automatic error reporting mechanism off: user error */ +/* reporting function will be in charge (if there is one) */ +extern CDEVAPI int cdevAutoErrorOff (void); + +/* set error reporting threshold. check cdev_error_code.h to see */ +/* all available threshold values. */ +extern CDEVAPI void cdevSetThreshold (int errorThreshold); + +/* set your own error reporting function. If func = 0, default */ +/* system error reporting function will be used */ +extern CDEVAPI void cdevSetErrorHandler (cdevErrHandler func); + +/* printf like error reporting interface */ +extern CDEVAPI int cdevReportError (int severity, char* name, + cdev_request_t req, char* format, ...); + +/********************************************************************** + * cdev high level I/O operations * + *********************************************************************/ + +/* synchronous send with device/msg pair + out/in data */ +extern CDEVAPI int cdevSend (char* device, char* msg, + cdev_data_t out, cdev_data_t result); + +/* asynchronous send with device/msg pair + out/in data */ +/* caller has to use synchronization mechanism to retrieve */ +/* result by cdevGroupPend or cdevPend methods */ +extern CDEVAPI int cdevSendNoBlock (char* device, char* msg, + cdev_data_t out, cdev_data_t result); + +/* asynchronous send with device/msg pair + out data and a */ +/* user provided callback. */ +/* caller has to use synchronization mechanism to retrieve */ +/* result by cdevGroupPend or cdevPend methods */ +extern CDEVAPI int cdevSendCallback (char* device, char* msg, + cdev_data_t out, cdev_cbk_t cbk); + +/* get context associcated with a device 'device' */ +extern CDEVAPI int cdevGetContext (char* device, cdev_data_t* data); + +/* set context for the device 'device' */ +extern CDEVAPI int cdevSetContext (char* device, cdev_data_t data); + +/* set private data for device 'device' */ +extern CDEVAPI int cdevSetPrivate (char* device, void* data); + +/* get private data associated with this 'device' */ +extern CDEVAPI int cdevGetPrivate (char* device, void** data); + +/********************************************************************* + * Efficient cdev I/O handle routines * + ********************************************************************/ + +/* Create/Allocate cdev_request_t object */ +extern CDEVAPI int cdevRequestAllocate (char* device, char* msg, + cdev_request_t* id); + +/* Destroy/Free a cdev_request_t object */ +extern CDEVAPI void cdevRequestFree (cdev_request_t id); + +/* synchronous send by a cdev_request_t object */ +extern CDEVAPI int cdevRequestSend (cdev_request_t id, + cdev_data_t out, + cdev_data_t result); + +/* asynchronous send. user has use synchronization routines */ +/* such as cdevGroupPend or cdevPend etc to get result */ +extern CDEVAPI int cdevRequestSendNoBlock (cdev_request_t id, + cdev_data_t out, + cdev_data_t result); + +/* asynchronous send with callback. user has use synchronization */ +/* routines such as cdevGroupPend or cdevPend etc to get result */ +extern CDEVAPI int cdevRequestSendCallback(cdev_request_t id, + cdev_data_t out, + cdev_cbk_t cbk); + +/* get current communication state of cdev_request_t. e.g. */ +/* connected or disconnected */ +extern CDEVAPI int cdevRequestState (cdev_request_t id); + +/* get access right of this cdev_request_t. e.g. readonly */ +extern CDEVAPI int cdevRequestAccess (cdev_request_t id); + +/* get device name associated with this cdev_request_t. caller */ +/* has control of memory of 'device'. */ +/* e.g. char *device; cdevRequestDevice (id, &device); */ +/* free (device); */ +extern CDEVAPI int cdevRequestDevice (cdev_request_t id, char** device); + +/* get message associated with this cdev_request_t. caller */ +/* has control of memory of 'msg'. */ +/* e.g. char *msg; cdevRequestMessage (id, &msg); */ +/* free (msg); */ +extern CDEVAPI int cdevRequestMessage (cdev_request_t id, char** msg); + +/* get context associated with this request. caller has */ +/* control of memory of return 'cxt'. */ +/* e.g. cdev_data_t data; cdevRequestGetContext (id, &data); */ +/* cdevDataFree (data); */ +extern CDEVAPI int cdevRequestGetContext (cdev_request_t id, cdev_data_t* cxt); + +/* set context for this I/O request */ +extern CDEVAPI int cdevRequestSetContext (cdev_request_t id, cdev_data_t cxt); + +/* get private data associated with this request. returned */ +/* data is just a pointer */ +extern CDEVAPI int cdevRequestGetPrivate (cdev_request_t id, void** data); + +/* set private data to this request */ +extern CDEVAPI int cdevRequestSetPrivate (cdev_request_t id, void* data); + +/******************************************************************** + * cdev group routines useful for synchronization of multiple * + * asynchronous I/O requests * + *******************************************************************/ + +/* create/allocate a new cdev group */ +extern CDEVAPI int cdevGroupAllocate (cdev_group_t* id); + +/* destroy/free a cdev group */ +extern CDEVAPI void cdevGroupFree (cdev_group_t id); + +/* start a cdev group, all I/O requests will be registered */ +/* this group */ +extern CDEVAPI int cdevGroupStart (cdev_group_t id); + +/* end a cdev group */ +extern CDEVAPI int cdevGroupEnd (cdev_group_t id); + +/* poll the network to see whether there are outstanding */ +/* I/O events pending for this group */ +extern CDEVAPI int cdevGroupPoll (cdev_group_t id); + +/* wait for all I/O requests upto 'seconds'. If seconds = 0.0 */ +/* wait until all I/O requests of this group have come back */ +extern CDEVAPI int cdevGroupPend (cdev_group_t id, double seconds); + +/* flush all I/O requests */ +extern CDEVAPI int cdevGroupFlush (cdev_group_t id); + +/* check whether all I/O requests inside this group have come */ +/* back. return 1: yes, return 0: no */ +extern CDEVAPI int cdevGroupAllFinished (cdev_group_t id); + +/* check all I/O requests status inside the group. caller */ +/* provide large enough integer buffer and initial size of */ +/* buffer. It returns with real number of I/O requests and */ +/* status[i] = 0 stands for a finished I/O, status[i] = 1 */ +/* stands for a unfinished I/O. */ +/* e.g. int status[100], nstatus = 100; */ +/* cdevGroupStatus (id, status, &nstatus); */ +/* for (i = 0; i < nstatus; i++) */ +/* if (status[i] == 0) do something */ +extern CDEVAPI int cdevGroupStatus (cdev_group_t id, + int status[], int* nstatus); + +/* do not buffer I/O requests. send them out immediatly. */ +/* This is the default mode */ +extern CDEVAPI int cdevGroupExecImmediate (cdev_group_t id); + +/* defer execution of all I/O requests inside the group until */ +/* cdevGroup flush is called */ +extern CDEVAPI int cdevGroupExecDeferred (cdev_group_t id); + +/* return the execution mode of this group */ +extern CDEVAPI int cdevGroupExecutionMode (cdev_group_t id, int* mode); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/src/ca/.shobj/Linux/caChannel.o b/src/ca/.shobj/Linux/caChannel.o new file mode 100644 index 0000000..6f5fe34 Binary files /dev/null and b/src/ca/.shobj/Linux/caChannel.o differ diff --git a/src/ca/.shobj/Linux/caMisc.o b/src/ca/.shobj/Linux/caMisc.o new file mode 100644 index 0000000..e1b232d Binary files /dev/null and b/src/ca/.shobj/Linux/caMisc.o differ diff --git a/src/ca/.shobj/Linux/caMonObj.o b/src/ca/.shobj/Linux/caMonObj.o new file mode 100644 index 0000000..19cdc9c Binary files /dev/null and b/src/ca/.shobj/Linux/caMonObj.o differ diff --git a/src/ca/.shobj/Linux/caNameSvc.o b/src/ca/.shobj/Linux/caNameSvc.o new file mode 100644 index 0000000..1a481bb Binary files /dev/null and b/src/ca/.shobj/Linux/caNameSvc.o differ diff --git a/src/ca/.shobj/Linux/caRequestObject.o b/src/ca/.shobj/Linux/caRequestObject.o new file mode 100644 index 0000000..3bcc9ba Binary files /dev/null and b/src/ca/.shobj/Linux/caRequestObject.o differ diff --git a/src/ca/.shobj/Linux/caService.o b/src/ca/.shobj/Linux/caService.o new file mode 100644 index 0000000..ccb7437 Binary files /dev/null and b/src/ca/.shobj/Linux/caService.o differ diff --git a/src/ca/Makefile b/src/ca/Makefile new file mode 100755 index 0000000..168da6a --- /dev/null +++ b/src/ca/Makefile @@ -0,0 +1,134 @@ +# Makefile for channel access service of CDEV +# +# channel access service +# +# Makefile,v +# Revision 1.22 1998/08/17 14:04:46 akers +# Added 'Minor Version Number' to TARGETDIR in Makefiles +# +# Revision 1.21 1998/02/10 18:25:01 chen +# add solaris-gnu +# +# Revision 1.20 1997/12/22 18:23:05 akers +# Ongoing development of 1.6.2 +# +# Revision 1.19 1997/12/17 15:06:55 akers +# *** empty log message *** +# +# Revision 1.17 1997/08/11 13:35:13 akers +# Ongoing development in support of CDEV version 1.6.1 +# +# Revision 1.16 1997/03/25 22:24:33 akers +# Development in support of a new cdevDirectory +# +# Revision 1.15 1997/03/04 17:15:08 chen +# fix for Linux shared library +# +# Revision 1.14 1996/11/18 17:07:13 chen +# add support for diffrent arch for caService.so +# +# Revision 1.13 1996/09/30 15:58:47 akers +# Changed Destination Directories +# +# Revision 1.12 1996/06/26 15:54:07 akers +# Modifications to support multiple OS Versions +# +# Revision 1.11 1996/05/15 16:25:49 akers +# Changes made to support epics shared libraries +# +# Revision 1.10 1996/05/15 15:08:02 akers +# Removed old library files and started using shared libraries. +# +# Revision 1.9 1996/05/14 20:38:01 akers +# Makefile modifications +# +# Revision 1.8 1995/11/20 15:20:09 chen +# add target +# +# Revision 1.7 1995/11/14 17:20:11 chen +# new makefile +# +# +# +include ../Makefile.config + +ifeq ($(SHOBJ),YES) + OBJTYPE=.shobj/$(TARGETDIR) +else + OBJTYPE=.obj/$(TARGETDIR) +endif + +EPICSINCLUDES = -I$(EPICS)/base/include + +XTRACXXFLAGS = $(EPICSINCLUDES) -D_EPICS_3_12 +XTRACFLAGS = -D_NO_PROTO -DACCESS_SECURITY -I. -DUNIX $(EPICSINCLUDES) +#-D_CDEV_DEBUG +#-D_CA_SYNC_CONN +#-D_TRACE_OBJECTS + +OBJS = $(OBJTYPE)/caChannel.o \ + $(OBJTYPE)/caNameSvc.o \ + $(OBJTYPE)/caRequestObject.o \ + $(OBJTYPE)/caService.o \ + $(OBJTYPE)/caMonObj.o \ + $(OBJTYPE)/caMisc.o + +ifeq ($(SHOBJ),YES) + TARGETLIB=$(CDEVSHOBJ)/$(CDEVVERSION)/caService.so +else + TARGETLIB=$(LIBDIR)/libcaService.a +endif + +# Different machine defines different ways to build shared library for ca service +ifeq ($(TARGET), solaris) + HOWMKCA = YES +endif + +ifeq ($(TARGET), hpux) + HOWMKCA = YES +endif + +ifeq ($(TARGET), Linux) + HOWMKCA = YES +endif + +ifeq ($(TARGET), solaris-gnu) + HOWMKCA = YES +endif + +targets: $(OBJTYPE) $(TARGETLIB) + +$(OBJTYPE) : + @mkdir -p $(OBJTYPE) + +$(CDEVSHOBJ)/$(CDEVVERSION)/caService.so: $(OBJS) + @mkdir -p $(CDEVSHOBJ)/$(CDEVVERSION) +ifdef HOWMKCA +ifeq ($(TARGET), solaris) + $(MAKELIB) $@ $(OBJS) -L$(EPICS)/base/lib/$(TARGET) -lca -lCom +endif +ifeq ($(TARGET), hpux) + $(MAKELIB) $@ $(OBJS) $(HPCXX_SHLIB_PATH) -L$(EPICSLIB) -lca -lCom -lDb +endif +ifeq ($(TARGET), Linux) + $(MAKELIB) $@ $(OBJS) -L$(EPICSLIB) -lca -lCom +endif +ifeq ($(TARGET), solaris-gnu) + $(MAKELIB) $@ $(OBJS) -L$(EPICS)/base/lib/solaris -lca -lCom +endif +else + @echo "Do not know how to make shared library for channel access service" + @echo "on your host machine." + @echo "Please check your programmer's mannual and edit this makefile," + @echo "and send new makefile to cdev@cebaf.gov. Thank you." +endif + + +$(LIBDIR)/libcaService.a: $(OBJS) + rm -f $@ + @mkdir -p $(LIBDIR) + $(MAKELIB) $@ $(OBJS) + $(RANLIB) $@ + +clean: clean_hail + @rm -rf *.o *.a *~ .obj .shobj core ptrepository diff --git a/src/ca/NMakefile.mak b/src/ca/NMakefile.mak new file mode 100755 index 0000000..2513677 --- /dev/null +++ b/src/ca/NMakefile.mak @@ -0,0 +1,33 @@ +.SUFFIXES: .cc .obj + +ARCH = WINNT-4.0 +SHOBJ = YES +HAIL = NO +FAIRWELL = NO + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +EPICSINCLUDES = /I $(EPICS)\base\include +CXXEXTRA = /w $(EPICSINCLUDES) /D _EPICS_3_12 /D "_CDEV_BUILD_SVC" + +OBJS = $(OBJDIR)\caChannel.obj\ + $(OBJDIR)\caNameSvc.obj\ + $(OBJDIR)\caRequestObject.obj\ + $(OBJDIR)\caService.obj\ + $(OBJDIR)\caMonObj.obj\ + $(OBJDIR)\caMisc.obj + +TARGETS = $(CDEVSHOBJ)\$(CDEVVERSION)\caService.dll + +targets : $(TARGETS) + +$(CDEVSHOBJ)\$(CDEVVERSION)\caService.dll: $(OBJS) + @echo =^> Building $(@F) + @echo =^> Objects: $(?F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(CDEVLIB)\cdev.lib $(EPICS)\base\lib\ca.lib $(EPICS)\base\lib\com.lib \ + $(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $(OBJS) + @echo ^<= Done... + + diff --git a/src/ca/caChannel.cc b/src/ca/caChannel.cc new file mode 100755 index 0000000..41b2569 --- /dev/null +++ b/src/ca/caChannel.cc @@ -0,0 +1,549 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Channel Access Channel Class (Implementation) +// +// Author: Jie Chen +// +// Revision History: +// caChannel.cc,v +// Revision 1.11 1998/04/10 17:02:20 chen +// get access information to all monitor callbacks +// +// Revision 1.10 1998/04/10 13:55:39 chen +// add access information to caService +// +// Revision 1.9 1998/03/05 18:49:11 chen +// fix a bug on context == 2 on property channels +// +// Revision 1.8 1998/03/04 13:22:29 chen +// fix minor bug +// +// Revision 1.7 1998/03/03 19:51:50 chen +// fix a bug for get string buffer of enum type +// +// Revision 1.6 1997/03/03 17:36:24 chen +// add buffering to channel access connection +// +// Revision 1.5 1996/09/18 14:46:45 chen +// Channel holds multiple monitor objects +// +// Revision 1.4 1995/10/03 19:56:00 chen +// contain property channels +// +// Revision 1.3 1995/09/05 17:20:47 chen +// Handle multiple callback correctly +// +// Revision 1.2 1995/08/28 18:06:16 chen +// allow multiple cdevCallbacks +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#include +#include +#include +#include "caRequestObject.h" +#include "caService.h" +#include "caChannel.h" +#include "caMonObj.h" + + +caChannel::caChannel (char *channelName, caService* svc) +:numConnT_ (0), count_ (0), readonly_ (0), + numElements_ (1), numMonitorObjs_ (0), accessBuffer_ (0), + pchannels_ (0), pinited_ (0), egrp_ (0), service_ (svc) +{ +#ifdef _TRACE_OBJECTS + printf(" Create caChannel Class Object\n"); +#endif + + channelName_ = new char[::strlen (channelName) + 1]; + ::strcpy (channelName_, channelName); + + // create group + egrp_ = new cdevExecGroup (svc); + + connected_ = 0; + + // send out connection request + execConnection (); +} + +caChannel::~caChannel (void) +{ +#ifdef _TRACE_OBJECTS + printf(" Delete caChannel Class Object\n"); +#endif + // remove all monitor objects +#ifdef _CDEV_DEBUG + printf ("There are %d monitorObjects\n", numMonitorObjs_); +#endif + if (numMonitorObjs_) { + for (int i = 0; i < numMonitorObjs_; i++) + delete monitorObjs_[i]; + delete []monitorObjs_; + } + monitorObjs_ = 0; + numMonitorObjs_ = 0; + + // close this channel + ::ca_clear_channel (cId_); + if (connected_){ + ::ca_flush_io (); + connected_ = 0; + } + + // clean up access buffer + if (accessBuffer_) + delete accessBuffer_; + delete []channelName_; + count_ = 0; + cId_ = 0; + + // clean out children list + if (pinited_) { + for (int i = 0; i < MAX_NUM_PCHANNELS; i++) + if (pchannels_[i].channel != 0) + delete pchannels_[i].channel; + delete []pchannels_; + pchannels_ = 0; + pinited_ = 0; + } + // clean out buffer + delete egrp_; +} + + +#ifdef _CA_SYNC_CONN +void +caChannel::connect (void) +{ + if (numConnT_ <= MAX_NUM_RETRIES){ + int caStatus = ::ca_search (channelName_, &cId_); + caStatus = ::ca_pend_io (1.0); + if (caStatus != ECA_NORMAL){ +#ifdef _CDEV_DEBUG + printf ("error on search for %s\n", channelName_); +#endif + numConnT_ ++; + } + else{ + numConnT_ = 0; + connected_ = 1; + type_ = ca_field_type (cId_); + // add disconnection and access right callback + ::ca_change_connection_event (cId_, &(caChannel::discCallback)); + ::ca_replace_access_rights_event (cId_, &(caChannel::accessRightCallback)); + if (type_ == DBR_ENUM){ + accessBuffer_ = new db_access_val; + ::ca_array_get (DBR_CTRL_ENUM, 1, cId_, accessBuffer_); + if (::ca_pend_io (4.0) != ECA_NORMAL) // error: set number of string 0 + accessBuffer_->cenmval.no_str = 0; + } + } + } + else { + service_->reportError( CDEV_SEVERITY_ERROR, channelName_, NULL, + "Cannot connect to channel after %d attempts.\n", MAX_NUM_RETRIES); + } +} +#else +int +caChannel::asyncConnect (void) +{ + if (!connected_){ // channel not connected + if (numConnT_ > MAX_NUM_RETRIES){ + service_->reportError( CDEV_SEVERITY_ERROR, channelName_, NULL, + "Cannot connect to channel after %d attempts.\n", MAX_NUM_RETRIES); + return CDEV_NOTCONNECTED; + } + numConnT_ ++; +#ifdef _CDEV_DEBUG + printf("before doing ca_pend_event (1.0) at channel %s\n", + channelName_); +#endif + int i = 0; + int numLoops = DEFAULT_TIMEOUT*DEFAULT_CONN_FREQ; + float stimev = 1.0/DEFAULT_CONN_FREQ; + while (i < numLoops && !connected_){ + ::ca_pend_event (stimev); + i++; + } + } + return CDEV_SUCCESS; +} +#endif + +char * +caChannel::channelName (void) const +{ + return channelName_; +} + + +int +caChannel::execConnection (void) +{ + numConnT_ ++; +#ifndef _CA_SYNC_CONN +#ifndef _EPICS_3_12 + //epics 3.11 version + int caStatus = ::ca_build_and_connect (channelName_, + TYPENOTCONN, + 0, + &cId_, + 0, + &(caChannel::connectCallback), + (void *)this); + + if (caStatus != ECA_NORMAL) { +#ifdef _CDEV_DEBUG + printf("Cannot do ca_build_and_connect \n"); +#endif + } +#else + int caStatus = ::ca_search_and_connect (channelName_, + &cId_, + &(caChannel::connectCallback), + (void *)this); + if (caStatus != ECA_NORMAL){ +#ifdef _CDEV_DEBUG + printf("Cannot do ca_search_and_connect \n"); +#endif + } +#endif +#else + int caStatus = ::ca_search (channelName, &cId_); + caStatus = ::ca_pend_io (1.0); + if (caStatus != ECA_NORMAL){ +#ifdef _CDEV_DEBUG + printf ("error on search for %s\n", channelName); +#endif + numConnT_ ++; + } + else{ + connected_ = 1; + // get channel type + type_ = ca_field_type (cId_); + // get number of elements of this channel + numElements_ = ca_element_count (cId_); + // register connection change event handler + ::ca_change_connection_event (cId_, &(caChannel::discCallback)); + ::ca_replace_access_rights_event (cId_, &(caChannel::accessRightCallback)); + // cache string values. cdev will return string value instead of + // short integer + if (type_ == DBR_ENUM){ + accessBuffer_ = new db_access_val; + ::ca_array_get (DBR_CTRL_ENUM, 1, cId_, accessBuffer_); + if (::ca_pend_io (4.0) != ECA_NORMAL) // error: set number of string 0 + accessBuffer_->cenmval.no_str = 0; + } + } +#endif + if (numConnT_ % 5 == 0) { + service_->reportError (CDEV_SEVERITY_WARN, channelName_, 0, + "Trying to connect to channel\n"); +#ifdef _CDEV_DEBUG + printf ("Trying to connect to %s at least 5 times...\n", channelName_); +#endif + } + + return CDEV_SUCCESS; +} + + +int +caChannel::addMonitorObj (caMonObj *newObj) +{ + caMonObj **newList; + // allocate a list large enough for one more element + newList = new caMonObj*[numMonitorObjs_ + 1]; + // copy the contents of the previous list to the new list + for (int i = 0; i < numMonitorObjs_; i++) + newList[i] = monitorObjs_[i]; + newList[i] = newObj; + // free the old list + if (numMonitorObjs_ > 0) + delete []monitorObjs_; + // make the new list as the current list + monitorObjs_ = newList; + numMonitorObjs_ ++; +#ifdef _CDEV_DEBUG + printf ("add monitorObject to list: %d objects\n",numMonitorObjs_); +#endif + return 1; +} + +int +caChannel::removeCallback (cdevCallback* callback) +{ + int i = 0; + + if (callback->callbackFunction() == 0) { // remove everything and event ID + if (numMonitorObjs_) { + for (i = 0; i < numMonitorObjs_; i++) + delete monitorObjs_[i]; + delete []monitorObjs_; + numMonitorObjs_ = 0; + } + return 1; + } + + // remove one particular callback + for (i = 0; i < numMonitorObjs_; i++) { + if (monitorObjs_[i]->removeCallback (callback)) + return 1; + } + return 0; + +} + +int +caChannel::removeMonitorObj (caMonObj* obj) +{ + int found = 0; + + for (int i = 0; i < numMonitorObjs_; i++) { + if (obj == monitorObjs_[i]) { + found = 1; + break; + } + } + + if (found) { + // Detroy the monitor object. +#ifdef _CDEV_DEBUG + printf ("remove a monitor callback object 0x%x\n", monitorObjs_[i]); +#endif + delete monitorObjs_[i]; + if (numMonitorObjs_ > 1) { + caMonObj **newList = new caMonObj*[numMonitorObjs_ - 1]; + int k = 0; + for (int j = 0; j < numMonitorObjs_; j++) { + if (j != i) + newList[k++] = monitorObjs_[j]; + } + delete []monitorObjs_; + monitorObjs_ = newList; + numMonitorObjs_ --; + } + else { + delete []monitorObjs_; + numMonitorObjs_ = 0; + } +#ifdef _CDEV_DEBUG + printf ("remove a monitorObject:%d left \n", numMonitorObjs_); +#endif + return 1; + } + else + return 0; +} + +int +caChannel::hasSameCallback (cdevCallback& cbk) +{ + int found = 0; + for (int i = 0; i < numMonitorObjs_; i++) { + if (monitorObjs_[i]->hasSameCallback (cbk)) { +#ifdef _CDEV_DEBUG + printf ("Found a monobject with the same callback\n"); +#endif + found = 1; + break; + } + } + return found; +} + +caMonObj * +caChannel::hasSameCallingCxt (int type, int mask) +{ + for (int i = 0; i < numMonitorObjs_; i++) { + if (type == monitorObjs_[i]->reqType_ && + mask == monitorObjs_[i]->reqMask_) { +#ifdef _CDEV_DEBUG + printf ("Found a monobject with the same calling context\n"); +#endif + return monitorObjs_[i]; + } + } + return 0; +} + +caMonObj * +caChannel::firstMonitorObj (void) +{ + if (numMonitorObjs_ > 0) + return monitorObjs_[0]; + return 0; +} + +caPchannel * +caChannel::createPchannels (void) +{ + caPchannel* pchannels = new caPchannel[MAX_NUM_PCHANNELS]; + + int i = 0; + pchannels[i++].tag = caService::CA_TAG_STATUS; + pchannels[i++].tag = caService::CA_TAG_SEVERITY; + pchannels[i++].tag = caService::CA_TAG_PRECISION; + pchannels[i++].tag = caService::CA_TAG_DISPHI; + pchannels[i++].tag = caService::CA_TAG_DISPLO; + pchannels[i++].tag = caService::CA_TAG_ALRMHI; + pchannels[i++].tag = caService::CA_TAG_ALRMLO; + pchannels[i++].tag = caService::CA_TAG_WRNHI; + pchannels[i++].tag = caService::CA_TAG_WRNLO; + pchannels[i++].tag = caService::CA_TAG_CTRLHI; + pchannels[i++].tag = caService::CA_TAG_CTRLLO; + for (i = 0; i < MAX_NUM_PCHANNELS; i++) { + pchannels[i].channel = 0; + pchannels[i].monitored = 0; + } + return pchannels; +} + +void +caChannel::propertyChannels (caPchannel* pch) +{ + if (!pinited_) { + pinited_ = 1; + pchannels_ = pch; + } +} + +void +caChannel::connectCallback (struct connection_handler_args conn) +{ + caChannel *obj = (caChannel *)ca_puser (conn.chid); +#ifdef _CDEV_DEBUG + printf("Connect %s callback called\n", obj->channelName_); +#endif + + if (ca_field_type (conn.chid) == TYPENOTCONN){ + obj->connected_ = 0; + obj->numConnT_ ++; + if (obj->numConnT_ > MAX_NUM_RETRIES){ +#ifdef _CDEV_DEBUG + printf ("Error: Cannot connect to the channel %s\n", obj->channelName_); +#endif + } + } + else{ + obj->numConnT_ = 0; + obj->connected_ = 1; + ::ca_change_connection_event (conn.chid, + &(caChannel::discCallback)); + ::ca_replace_access_rights_event (conn.chid, + &(caChannel::accessRightCallback)); + obj->type_ = ca_field_type (conn.chid); + obj->numElements_ = ca_element_count (conn.chid); +#ifdef _CDEV_DEBUG + printf("type is 0x%x and num elements is %d\n", obj->type_, + obj->numElements_); +#endif + // cache string values. CDEV return string instead of short integer + // for DBR_ENUM + if (obj->type_ == DBR_ENUM){ + obj->accessBuffer_ = new db_access_val; + obj->accessBuffer_->cenmval.no_str = 0; + ::ca_array_get_callback (DBR_CTRL_ENUM, 1, conn.chid, + &(caChannel::enumGetCallback), + (void *)obj); + } + else + // flush out all buffered exections + obj->egrp_->flush (); + } +} + +void +caChannel::discCallback (struct connection_handler_args conn) +{ + int status; + caChannel *obj = (caChannel *)ca_puser (conn.chid); + + if (obj->connected_){ +#ifdef _CDEV_DEBUG + printf("disconnected for channel %s\n", obj->channelName_); +#endif + obj->connected_ = 0; + status = CDEV_DISCONNECTED; + } + else{ +#ifdef _CDEV_DEBUG + printf("reconnected for channel %s\n", obj->channelName_); +#endif + obj->connected_ = 1; + status = CDEV_RECONNECTED; + } + cdevData result; + for (int i = 0; i < obj->numMonitorObjs_; i++) { + cdevRequestObject *reqObj = obj->monitorObjs_[i]->reqObj_; + obj->monitorObjs_[i]->callCallbacks (status, reqObj, result); + } +} + +void +caChannel::accessRightCallback (struct access_rights_handler_args args) +{ + caChannel *obj = (caChannel *)ca_puser (args.chid); + + int readaccess = ca_read_access (args.chid); + int writeaccess = ca_write_access (args.chid); + int acflag = 0; + + if (!readaccess) + acflag = CDEV_ACCESS_NONE; + else if (readaccess && !writeaccess) + acflag = CDEV_ACCESS_READONLY; + else if (writeaccess) + acflag = CDEV_ACCESS_WRITE; + + + if (acflag != obj->readonly_) { + obj->readonly_ = acflag; + // call all monitor callbacks to notify access right is changed + cdevData result; + for (int i = 0; i < obj->numMonitorObjs_; i++) { + cdevRequestObject *reqObj = obj->monitorObjs_[i]->reqObj_; + obj->monitorObjs_[i]->callCallbacks (CDEV_ACCESSCHANGED, reqObj, result); + } + } +} + +void +caChannel::enumGetCallback (struct event_handler_args args) +{ + caChannel *obj = (caChannel *)ca_puser (args.chid); + + if (args.count > 0 && args.dbr != 0) { + struct dbr_ctrl_enum *retValue = 0; + retValue = (struct dbr_ctrl_enum *)args.dbr; + + memcpy (&(obj->accessBuffer_->cenmval), + retValue, sizeof (struct dbr_ctrl_enum)); +#ifdef _CDEV_DEBUG + printf ("Enum has %d number of strings\n", (obj->accessBuffer_)->cenmval.no_str); + for (int i = 0; i < (obj->accessBuffer_)->cenmval.no_str; i++) + printf ("String[%d] is %s\n", i, (obj->accessBuffer_)->cenmval.strs[i]); +#endif + } + else { +#ifdef _CDEV_DEBUG + printf ("enum get callback failed\n"); +#endif + (obj->accessBuffer_)->cenmval.no_str = 0; + } + // now flush out callbacks + obj->egrp_->flush (); +} diff --git a/src/ca/caChannel.h b/src/ca/caChannel.h new file mode 100755 index 0000000..48f0e99 --- /dev/null +++ b/src/ca/caChannel.h @@ -0,0 +1,243 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Channel Access Channel Class (accessed by caRequestObject only) +// +// Author: Jie Chen +// +// Revision History: +// caChannel.h,v +// Revision 1.9 1998/04/10 13:55:40 chen +// add access information to caService +// +// Revision 1.8 1998/03/05 18:49:12 chen +// fix a bug on context == 2 on property channels +// +// Revision 1.7 1998/03/03 19:51:51 chen +// fix a bug for get string buffer of enum type +// +// Revision 1.6 1997/03/03 17:36:25 chen +// add buffering to channel access connection +// +// Revision 1.5 1996/09/18 14:46:46 chen +// Channel holds multiple monitor objects +// +// Revision 1.4 1996/09/10 19:20:36 chen +// change C++ include header +// +// Revision 1.3 1995/10/03 19:56:05 chen +// contain property channels +// +// Revision 1.2 1995/08/28 18:06:23 chen +// allow multiple cdevCallbacks +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#ifndef _CDEV_CA_CHANNEL_H +#define _CDEV_CA_CHANNEL_H + +//============================================================================= +// This class acts as an internal agent for caRequestObject class. +// It contains a connection to an IOC server. +// It also contains event ID which is used to monitor value. +// It allows multiple callbacks to attach to the event ID +// It also contains the reference counting mechanism +// +// The channel also contains multiple children which represents +// property channels of this channel +// +//============================================================================= +#include +#include +#include + +// epics stuff +#if !defined (_EPICS_3_12) +#define __STDC__ +extern "C"{ +#endif + +#include +#include + +#if !defined (_EPICS_3_12) +}; +#undef __STDC__ +#endif + + +#include +#include +#include + +// number of times one tries to establish connection before giving up +#define MAX_NUM_RETRIES 3 +// default timeout value in channel access in seconds +#define DEFAULT_TIMEOUT 4 +// default frequency to call ca_pend_event for initial connection +#define DEFAULT_CONN_FREQ 10 +// maximum number of channels which monitoring the value properties +#define MAX_NUM_PCHANNELS 11 + +class caRequestObject; +class caService; +class caMonObj; +class caChannel; + +//=================================================================== +// Property channel structure +// When a caller tries to monitor not only an attribute +// he/she sepecified but also the properties, caRequestObject +// has to establish more than one channels +//=================================================================== +class caPchannel +{ +public: + int tag; + int monitored; + caChannel* channel; +}; + +class caChannel +{ +public: + // destructor + ~caChannel (void); + +#ifdef _CA_SYNC_CONN + void connect (void); + // PURPOSE: establish network connection to IOC server + // REQUIRE: nothing + // PROMISE: internal knowledge of connection +#else + int asyncConnect (void); + // PURPOSE: send out network connection request asynchronously + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS if the request is sent out ok +#endif + + char *channelName (void) const; + // PURPOSE: return channel name + // REQUIRE: nothing + // PROMISE: channel name + + int addMonitorObj (caMonObj *newObj); + // PURPOSE: add this monitor object when callers call monitorOn + // REQUIRE: newObj != 0 + // PROMISE: return 1: new object will be added on + // return 0: this object has the same callback with one of the + // existing objects + + int removeCallback (cdevCallback* callback); + // PURPOSE: remove a monitorCallback by cdevCallback + // REQUIRE: callback != 0 + // PROMISE: return 1: one of the callback has been removed + // return 0: nothing has been removed + + int removeMonitorObj (caMonObj* obj); + // PURPOSE: remove a monitorCallback by cdevCallback + // REQUIRE: obj != 0 + // PROMISE: return 1: one of the monitor object has been removed + // return 0: nothing has been removed + + caMonObj* firstMonitorObj (void); + // PURPOSE: return first monitor object on the list + // REQUIRE: none + // PROMISE: return non-null pointer to the first object if there + // are any. return 0 if there are none + + int monObjWithSameCbk (caMonObj* &extobj, caMonObj* newobj); + // PURPOSE: find a caMonObj having the same callback as the new + // caMonObj 'newobj' has. + // REQUIRE: newobj != 0 + // PROMISE: return 1: found one and result is extobj. return 0: not found + + int hasSameCallback (cdevCallback& cbk); + // PURPOSE: find whether a monitor object in the list + // having the same callback as cbk + // REQUIRE: none + // PROMISE: return 1: found one. return 0: not found + + caMonObj* hasSameCallingCxt (int reqtype, int reqmask); + // PURPOSE: find whether a monitor object in the list + // having the same calling context as specified by type/mask + // REQUIRE: none + // PROMISE: return first object pointer that has the same context + // otherwise 0 pointer returned + +protected: + // deny direct instantiation. Only caRequestObject can access + caChannel (char *channelName, caService* svc); + + // execut connection request + int execConnection (void); + + // some standard callback function for epics + static void connectCallback (struct connection_handler_args conn); + static void discCallback (struct connection_handler_args conn); + static void accessRightCallback (struct access_rights_handler_args arg); + + // get array callback for enum channel type + static void enumGetCallback (struct event_handler_args arg); + + // create property channels + static caPchannel* createPchannels (void); + + // assign property pchannels to this channel + void propertyChannels (caPchannel *ch); + +private: + // deny access to copy and assignment + caChannel (const caChannel &s); + caChannel& operator = (const caChannel &s); + // data area + // number of times one has tries to connect this channel + int numConnT_; + // svcData has one to one to channel ID mapping + char *channelName_; + // refrence counter : accessed by caRequestObject + int count_; + // channel ID + chid cId_; + // type field + chtype type_; + // number of elements of this channel + int numElements_; + // connection flag + int connected_; + // readonly flag + int readonly_; + // channel monitoring transaction objects + // these transaction objects initially will be inside a group + // then they will be registered here + caMonObj **monitorObjs_; + int numMonitorObjs_; + // pointer to data access buffer. Most of time this pointer is NULL. + // It will not be so when chtype is ENUM, since one has to access + // internal string representations + union db_access_val *accessBuffer_; + + // property channel list + caPchannel* pchannels_; + int pinited_; + + // buffer for executions + cdevExecGroup* egrp_; + + // service pointer + caService* service_; + + // friend class + friend class caRequestObject; + friend class caService; +}; +#endif diff --git a/src/ca/caMisc.cc b/src/ca/caMisc.cc new file mode 100755 index 0000000..dda26d9 --- /dev/null +++ b/src/ca/caMisc.cc @@ -0,0 +1,81 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Some useful functions for caService and caRequestObject +// +// Author: Jie Chen +// +// Revision History: +// caMisc.cc,v +// Revision 1.4 1995/11/10 20:07:32 chen +// Relax restriction on data matching +// +// Revision 1.3 1995/07/14 11:49:42 akers +// Modifications to support the new cdevData class +// +// Revision 1.2 1995/06/29 18:51:26 akers +// Updated cdevData Type +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#include "caService.h" +#include "caMisc.h" +#include + +int +dataMatch (cdevData& data, int type, int count) +{ + int dtype; + int dim = 0, len = 0; + int status = CDEV_SUCCESS; + dtype = data.getType (caService::CA_TAG_VALUE); + switch (type){ + case DBR_STRING: + if (dtype != CDEV_STRING) + status = CDEV_ERROR; + break; + case DBR_ENUM: // user will use string + if (dtype != CDEV_STRING) + status = CDEV_ERROR; + break; + case DBR_SHORT: // allow cdevData to do conversion + case DBR_LONG: + case DBR_FLOAT: + case DBR_DOUBLE: + break; + default: + status = CDEV_ERROR; + break; + } + if (status == CDEV_SUCCESS){ + int st = data.getDim (caService::CA_TAG_VALUE, (size_t *)&dim); + if (count == 1) { + if (dim != 0) + return CDEV_ERROR; + } + else { + if (dim != 1) + return CDEV_ERROR; + + // *********************************************************************** + // * cdevBounds support added for support of arbitrary dimensional data + // *********************************************************************** + cdevBounds bounds; + st = data.getBounds (caService::CA_TAG_VALUE, &bounds, 1); + len = bounds.length; + + if (len != count) + status = CDEV_ERROR; + } + } + return status; +} diff --git a/src/ca/caMisc.h b/src/ca/caMisc.h new file mode 100755 index 0000000..bc14976 --- /dev/null +++ b/src/ca/caMisc.h @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Utility functions for caService and caRequestObject +// +// Author: Jie Chen +// +// Revision History: +// caMisc.h,v +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#ifndef _CDEV_CA_MISC_H +#define _CDEV_CA_MISC_H + +#include + +extern int dataMatch (cdevData& data, int type, int count); +// PURPOSE: check whether a cdevData 'data' matches data type 'type' +// and number of elements 'count' +// REQUIRE: type must be one of the supported. count >= 1 +// PROMISE: 0: matched, -1: no match + +#endif + diff --git a/src/ca/caMonObj.cc b/src/ca/caMonObj.cc new file mode 100755 index 0000000..2b2a06c --- /dev/null +++ b/src/ca/caMonObj.cc @@ -0,0 +1,402 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of caMonObj Class +// +// Author: Jie Chen +// +// Revision History: +// caMonObj.cc,v +// Revision 1.6 1998/03/05 18:49:12 chen +// fix a bug on context == 2 on property channels +// +// Revision 1.5 1998/01/20 19:47:02 chen +// use cdev_cbk_finished to signal end of monitor off +// +// Revision 1.4 1997/08/08 16:41:35 chen +// add char type and fix dbr== null +// +// Revision 1.3 1997/03/03 17:36:26 chen +// add buffering to channel access connection +// +// Revision 1.2 1996/09/18 14:46:47 chen +// Channel holds multiple monitor objects +// +// Revision 1.1 1995/10/03 19:58:02 chen +// channel monitoring class +// +// +#include +#include "caService.h" +#include "caChannel.h" +#include "caMonObj.h" + +//========================================================================= +// Implementation of caMonData +//========================================================================= +caMonData::caMonData (void) +:value (0), status (0), severity (0), tstamp (0), precision (0), + disphi (0), displo (0), warnhi (0), warnlo (0), + alrmhi (0), alrmlo (0), ctrlhi (0), ctrllo (0) +{ + // empty +} + +caMonData::~caMonData (void) +{ + // empty all pointers points a cdevData internal buffer +} + + +//========================================================================= +// Implementation of caMonCbk +//========================================================================= +caMonCbk::caMonCbk (cdevCallback* cbk, cdevData* out, caMonCbk* next) +:cbk_ (cbk), out_ (out), cached_ (0), next_ (next) +{ +#ifdef _TRACE_OBJECTS + printf ("Create caMonCbk Class Object\n"); +#endif + // empty +} + +caMonCbk::caMonCbk (cdevCallback& cbk, cdevData* out, caMonCbk* next) +:out_ (out), cached_ (0), next_ (next) +{ +#ifdef _TRACE_OBJECTS + printf ("Create caMonCbk Class Object\n"); +#endif + cbk_ = new cdevCallback (cbk); +} + +caMonCbk::~caMonCbk (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete caMonCbk Class Object\n"); +#endif + if (cbk_) + delete cbk_; + if (next_) + delete next_; +} + +void +caMonCbk::enableCache (void) +{ + cached_ = 1; +} + +void +caMonCbk::disableCache (void) +{ + cached_ = 0; +} + +//========================================================================= +// Implementation of caMonObjR +//========================================================================= +caMonObj::caMonObj (cdevTranObj& obj) +:system_ (obj.system_), reqObj_ (obj.reqObj_), + tag_ (0), cbkStatus_ (CDEV_SUCCESS), reqMask_ (0x1), + reqType_ (0), channel_ (0), cache_ (), data_ (), cacheInited_ (0), + mEvId_ (0), count_ (1) +{ +#ifdef _TRACE_OBJECTS + printf ("Create caMonObj Class Object\n"); +#endif + cbks_ = new caMonCbk (obj.userCallback_, obj.resultData_); + tobj_ = &obj; + +} + +caMonObj::caMonObj (const caMonObj& obj, cdevCallback* cbk, cdevData* out) +:system_ (obj.system_), reqObj_ (obj.reqObj_), + tag_ (0), cbkStatus_ (CDEV_SUCCESS), reqMask_ (0x1), + reqType_ (0), channel_ (0), cache_ (), data_ (), cacheInited_ (0), + mEvId_ (0), count_ (1) +{ +#ifdef _TRACE_OBJECTS + printf ("Create caMonObj Class Object\n"); +#endif + cbks_ = new caMonCbk (*cbk, out); + tobj_ = obj.tobj_; + +} + +caMonObj::~caMonObj (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete caMonObj Class Object\n"); +#endif + + count_ = 0; + if (mEvId_) { +#ifdef _CDEV_DEBUG + printf ("Clear event id %d\n", mEvId_); +#endif + ::ca_clear_event (mEvId_); + mEvId_ = 0; + } + + // notify all callbacks that this monitor is over + caMonCbk* p = 0; + cdevData unused; + + for (p = cbks_; p != 0; p = p->next_) { + if (!p->cached_) { + cdevCallback *cbkobj = p->cbk_; + cbkobj->fireCallback (CDEV_CBK_FINISHED, cbkobj->userarg (), + *reqObj_, unused, 0); + } + } + if (cbks_) + delete cbks_; + + // leave channel pointer alone + + tobj_ = 0; +} + +void +caMonObj::setMonitorInfo (int tag, int status, caChannel* arg, + int type, int mask) +{ + tag_ = tag; + cbkStatus_ = status; + channel_ = arg; + reqType_ = type; + reqMask_ = mask; +} + + +int +caMonObj::hasSameCallback (cdevCallback& cbk) +{ + caMonCbk* p = 0; + + for (p = cbks_; p != 0; p = p->next_) { + if (cbk == *(p->cbk_)) + return 1; + } + return 0; +} + +int +caMonObj::addCallback (caMonCbk* cbk) +{ + caMonCbk* p = 0; + + for (p = cbks_; p != 0; p = p->next_) { + if (*(cbk->cbk_) == *(p->cbk_)) + return 0; + } + // add to the head + cbk->next_ = cbks_; + cbks_ = cbk; + + count_ ++; +#ifdef _CDEV_DEBUG + printf ("Add a new callback, callback list has %d callbacks\n", count_); +#endif + return 1; +} + +int +caMonObj::removeCallback (cdevCallback* cbk) +{ + int found = 0; + caMonCbk* p = 0; + caMonCbk* q = 0; + + if (cbk->callbackFunction() == 0) { // remove everything and event ID + channel_->removeMonitorObj (this); + return 1; + } + + // remove one particular callback + q = cbks_; + for (p = cbks_; p != 0; p = p->next_) { + if (*cbk == *(p->cbk_)) { + found = 1; + break; + } + q = p; // remeber the previous one + } + if (found && count_ == 1) { + // Detroy the monitor object. +#ifdef _CDEV_DEBUG + printf ("remove a monitor object since this is last callback\n"); +#endif + channel_->removeMonitorObj (this); + return 1; + } + else if (found) { +#ifdef _CDEV_DEBUG + printf ("remove a single callback leave monitor object\n"); +#endif + if (p == cbks_) { // delete the first one + cbks_ = p->next_; + // set next pointer to null otherwise destructor will delete next + p->next_ = 0; + delete p; + count_ --; + } + else { + q->next_ = p->next_; + p->next_ = 0; + delete p; + count_ --; + } + return 1; + } + else { +#ifdef _CDEV_DEBUG + printf ("Cannot find a single callback to remove\n"); +#endif + return 0; + } +} + +void +caMonObj::callCallbacks (int status, cdevRequestObject* req, cdevData& data) +{ + caMonCbk* p = 0; + + for (p = cbks_; p != 0; p = p->next_) { + if (!p->cached_) { + cdevCallback *cbkobj = p->cbk_; + cbkobj->fireCallback (status, cbkobj->userarg (), + *req, data, 1); + } + else { +#ifdef _CDEV_DEBUG + printf ("Call cached callback without calling user callback\n"); +#endif + } + } +} + +void +caMonObj::callCallback (caMonCbk* cbk) +{ + cdevCallback* cbkobj = cbk->cbk_; + + cbkobj->fireCallback (CDEV_SUCCESS, cbkobj->userarg (), + *reqObj_, cache_, 1); +} + +int +caMonObj::setupMonitorBuffer (int tagval, + cdevData& data, + caMonData& monData, + int type) +{ + int status[20]; + + switch (type) { + case CDEV_INT32: + data.insert (tagval, (int)1); + break; + case CDEV_FLOAT: + data.insert (tagval, (float)10.0); + break; + case CDEV_DOUBLE: + data.insert (tagval, (double)10.0); + break; + case CDEV_BYTE: + data.insert (tagval, (BYTE)1); + break; + default: + break; + } + data.insert (caService::CA_TAG_STATUS, (int)0); + data.insert (caService::CA_TAG_SEVERITY, (int)0); + cdev_TS_STAMP tsmp; + + tsmp.secPastEpoch = 0L; + tsmp.nsec = 0L; + + data.insert (caService::CA_TAG_TIME, tsmp); + data.insert (caService::CA_TAG_PRECISION, (int)0); + data.insert (caService::CA_TAG_DISPHI, (float)0.0); + data.insert (caService::CA_TAG_DISPLO, (float)0.0); + data.insert (caService::CA_TAG_ALRMHI, (float)0.0); + data.insert (caService::CA_TAG_ALRMLO, (float)0.0); + data.insert (caService::CA_TAG_WRNHI, (float)0.0); + data.insert (caService::CA_TAG_WRNLO, (float)0.0); + data.insert (caService::CA_TAG_CTRLHI, (float)0.0); + data.insert (caService::CA_TAG_CTRLLO, (float)0.0); + + // get all pointers inside the cdevData + int i = 0; + status[i++] = data.find (tagval, monData.value); + + void *dataPtr = 0; + status[i++] = data.find (caService::CA_TAG_STATUS, dataPtr); + monData.status = (int *)dataPtr; + + dataPtr = 0; + status[i++] = data.find (caService::CA_TAG_SEVERITY, dataPtr); + monData.severity = (int *)dataPtr; + + dataPtr = 0; + status[i++] = data.find (caService::CA_TAG_TIME, dataPtr); + monData.tstamp = (cdev_TS_STAMP *)dataPtr; + + dataPtr = 0; + status[i++] = data.find (caService::CA_TAG_PRECISION, dataPtr); + monData.precision = (int *)dataPtr; + + dataPtr = 0; + status[i++] = data.find (caService::CA_TAG_DISPHI, dataPtr); + monData.disphi = (float *)dataPtr; + + dataPtr = 0; + status[i++] = data.find (caService::CA_TAG_DISPLO, dataPtr); + monData.displo = (float *)dataPtr; + + dataPtr = 0; + status[i++] = data.find (caService::CA_TAG_WRNHI, dataPtr); + monData.warnhi = (float *)dataPtr; + + dataPtr = 0; + status[i++] = data.find (caService::CA_TAG_WRNLO, dataPtr); + monData.warnlo = (float *)dataPtr; + + dataPtr = 0; + status[i++] = data.find (caService::CA_TAG_ALRMHI, dataPtr); + monData.alrmhi = (float *)dataPtr; + + dataPtr = 0; + status[i++] = data.find (caService::CA_TAG_ALRMLO, dataPtr); + monData.alrmlo = (float *)dataPtr; + + dataPtr = 0; + status[i++] = data.find (caService::CA_TAG_CTRLHI, dataPtr); + monData.ctrlhi = (float *)dataPtr; + + dataPtr = 0; + status[i++] = data.find (caService::CA_TAG_CTRLLO, dataPtr); + monData.ctrllo = (float *)dataPtr; + + for (i = 0; i < 13; i++) { + if (status[i] != CDEV_SUCCESS) { +#ifdef _CDEV_DEBUG + printf ("Fatal Error: Cannot insert and find int\n"); + printf ("inside setup monitor buffer \n"); +#endif + return CDEV_ERROR; + } + } + return CDEV_SUCCESS; +} + + + diff --git a/src/ca/caMonObj.h b/src/ca/caMonObj.h new file mode 100755 index 0000000..f8bc71f --- /dev/null +++ b/src/ca/caMonObj.h @@ -0,0 +1,206 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Channel Access Channel Monitoring Object +// +// Author: Jie Chen +// +// Revision History: +// caMonObj.h,v +// Revision 1.3 1998/03/05 18:49:12 chen +// fix a bug on context == 2 on property channels +// +// Revision 1.2 1996/09/18 14:46:49 chen +// Channel holds multiple monitor objects +// +// Revision 1.1 1995/10/03 19:58:08 chen +// channel monitoring class +// +// +// +#ifndef _CA_MON_OBJ_H +#define _CA_MON_OBJ_H + +#include + +// epics stuff +#if !defined (_EPICS_3_12) +#define __STDC__ +extern "C"{ +#endif + +#include +#include + +#if !defined (_EPICS_3_12) +}; +#undef __STDC__ +#endif + +// class caMonObj is a monitor object that is very similar to +// the cdevTranObj except no group information. It will be used +// in the case of monitoring a particular channel which the user +// callback need to be around after the transaction object goes away. +// +// each monitor object has unique request mask/type + evid information with +// multiple different callbacks + +//==================================================================== +// connected channel monitoring data buffer +// When a caChannel is connected, the caMonData will be created +// to accept new data from remote IOC +//===================================================================== +class caMonData +{ +public: + // constrcutor and destructor + caMonData (void); + ~caMonData (void); + + void *value; + int *status; + int *severity; + cdev_TS_STAMP *tstamp; + int *precision; + float *disphi; + float *displo; + float *warnhi; + float *warnlo; + float *alrmhi; + float *alrmlo; + float *ctrlhi; + float *ctrllo; + +private: + // deny access to copy and assignment + caMonData (const caMonData& data); + caMonData& operator = (const caMonData& data); +}; + + +class caMonObj; +class caChannel; + +class caMonCbk +{ +public: + // constructor and destructor + + // just copy pointer for callback + caMonCbk (cdevCallback* cbk, cdevData* out, caMonCbk* next = 0); + // duplicate callback + caMonCbk (cdevCallback& cbk, cdevData* out, caMonCbk* next = 0); + + ~caMonCbk (void); + + void enableCache (void); + void disableCache (void); + + const char* className (void) const {return "caMonCbk";} + + // data area + cdevCallback* cbk_; + cdevData* out_; + int cached_; + + // pointer to next + caMonCbk* next_; + +private: + // denay access to copy and assignment operator + caMonCbk (const caMonCbk& cbk); + caMonCbk& operator = (const caMonCbk& cbk); +}; + + +class caMonObj +{ +public: + // constructor and destructor + caMonObj (cdevTranObj& obj); + + // create new caMonObj with duplicated callback + caMonObj (const caMonObj& obj, cdevCallback* cbk, cdevData* out); + ~caMonObj (void); + + // check whether this monitor object has the same callback already + // return 1: yes, return 0: no + int hasSameCallback (cdevCallback& cbk); + + // add a new callback to the list + // return 1: success, return 0: failed, already there + int addCallback (caMonCbk* cbk); + + // remove a callback from the list + // if the callback has function 0 and usrarg 0, we will rmove everything + // and stop monitoring. otherwise we will remove a single callback + // return 1: success, 0: not found + int removeCallback (cdevCallback* cbk); + + // call all callbacks + void callCallbacks (int status, cdevRequestObject* req, cdevData& data); + + // call a single callback denoted by caMonCbk 'cbk' + // this is used when one adds a callback which has the same context + // as this moinitor object + void callCallback (caMonCbk* cbk); + + // set monitor object information + void setMonitorInfo (int tag, int status, caChannel* arg, + int type, int mask); + + // setup monitoring data buffers which point to various cdevData + // object internal buffers + static int setupMonitorBuffer (int tag, + cdevData& data, + caMonData& monData, + int dataType); + + const char *className (void) const {return "caMonObj";} + + // pointer to transaction object + cdevTranObj* tobj_; + + // data area that is from transaction object + cdevSystem *system_; + cdevRequestObject *reqObj_; + + // tag and callback status associated with this monitor object + int tag_; + int cbkStatus_; + + // request mask and type of this monitoring object + int reqMask_; + int reqType_; + + // user arg to remember which channel this monitor object belongs to + caChannel* channel_; + + // cached value + cdevData cache_; + caMonData data_; + int cacheInited_; + + + // channel access event id + evid mEvId_; + // number of callbacks + int count_; + + // head to list of caMonCbk s + caMonCbk* cbks_; + +private: + // deny access to copy and assignment + + caMonObj& operator = (const caMonObj&); +}; + +#endif diff --git a/src/ca/caNameSvc.cc b/src/ca/caNameSvc.cc new file mode 100755 index 0000000..a3292dd --- /dev/null +++ b/src/ca/caNameSvc.cc @@ -0,0 +1,194 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Channel Access Name Service +// This will be used when there is no DDL file presented +// +// Author: Jie Chen +// +// Revision History: +// caNameSvc.cc,v +// Revision 1.6 1997/08/27 18:16:58 chen +// fix compile warning +// +// Revision 1.5 1997/05/30 19:10:42 chen +// cosmatic touch +// +// Revision 1.4 1997/03/25 22:24:33 akers +// Development in support of a new cdevDirectory +// +// Revision 1.3 1996/01/05 18:39:36 chen +// Fix a potential bug for gcc +// +// Revision 1.2 1995/07/05 18:31:54 chen +// minor changes +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#include +#include +#include "caService.h" +#include "caNameSvc.h" + +caNameSvc::caNameSvc(cdevSystem &system) +:cdevDevice("caNameService", system) +{ +#ifdef _TRACE_OBJECTS + printf(" Create caNameSvc class object\n"); +#endif + system.nameServer().addNameSvc(this); +} + +caNameSvc::~caNameSvc(void) +{ +#ifdef _TRACE_OBJECTS + printf(" Delete caNameSvc class object\n"); +#endif + // no need to delete from the directory list + // system_.nameServer().removeNameSvc (this); +} + +// return service data in the form of "dvcName.attribute" +int +caNameSvc::send(char *msg, cdevData*, cdevData *result) +{ + int errCode = CDEV_SUCCESS; + char token[64], deviceName[64], message[256], attr[64]; + char svcData[128]; + +#ifdef __GNUC__ + char buffer[400]; + ::strncpy(buffer, msg, sizeof(buffer)); + int status=sscanf(buffer, "%s %s %s", token, deviceName, message); +#else + int status=sscanf(msg, "%s %s %s", token, deviceName, message); +#endif + + if(status < 3) errCode = CDEV_INVALIDARG; + else if(::strcmp(token, "resolveServiceData") == 0) + { + // check svc data +#ifdef __GNUC__ + status=sscanf(buffer, "%s %s %s %s", token, deviceName, message, attr); +#else + status=sscanf(msg, "%s %s %s %s", token, deviceName, message, attr); +#endif + if(status < 4) + ::strcpy(attr, "VAL"); + sprintf(svcData, "%s.%s", deviceName, attr); + if(result->insert(caService::CA_TAG_PV, svcData) != CDEV_SUCCESS) + { + errCode = CDEV_ERROR; + } + } + else if(::strcmp(token, "resolveService") == 0) + { +#ifdef __GNUC__ + status=sscanf(buffer, "%s %s %s %s", token, deviceName, message, attr); +#else + status=sscanf(msg, "%s %s %s %s", token, deviceName, message, attr); +#endif + if(status < 4) + ::strcpy(attr, "VAL"); + + system_.reportError + (CDEV_SEVERITY_WARN, "CDEV Directory", 0, + "No service matches \"%s\" - \"%s %s\", default to caService", + deviceName, message, attr); + if(result->insert("value", "caService") != CDEV_SUCCESS) + { + errCode = CDEV_ERROR; + } + } + else errCode = CDEV_NOTFOUND; + + return errCode; +} + +int +caNameSvc::send(char *msg, cdevData &out, cdevData &result) +{ + return send(msg, &out, &result); +} + +int +caNameSvc::send(char *msg, cdevData &out, cdevData *result) +{ + return send(msg, &out, result); +} + +int +caNameSvc::send(char *msg, cdevData *out, cdevData &result) +{ + return send(msg, out, &result); +} + +int +caNameSvc::sendNoBlock(char*, cdevData&, cdevData &) +{ + return CDEV_ERROR; +} + +int +caNameSvc::sendNoBlock(char*, cdevData*, cdevData &) +{ + return CDEV_ERROR; +} + +int +caNameSvc::sendNoBlock(char*, cdevData&, cdevData *) +{ + return CDEV_ERROR; +} + +int +caNameSvc::sendNoBlock(char*, cdevData*, cdevData *) +{ + return CDEV_ERROR; +} + +int +caNameSvc::sendCallback(char*, cdevData&, cdevCallback &) +{ + return CDEV_ERROR; +} + +int +caNameSvc::sendCallback(char*, cdevData*, cdevCallback &) +{ + return CDEV_ERROR; +} + +int +caNameSvc::getRequestObject(char*, cdevRequestObject* &reqobj) +{ + reqobj=0; + return CDEV_ERROR; +} + +cdevRequestObject * +caNameSvc::getRequestObject(char *) +{ + return 0; +} + +int +caNameSvc::registerReqObject(cdevRequestObject *) +{ + return CDEV_ERROR; +} + +int +caNameSvc::removeReqObject(cdevRequestObject *) +{ + return CDEV_ERROR; +} diff --git a/src/ca/caNameSvc.h b/src/ca/caNameSvc.h new file mode 100755 index 0000000..c5d750c --- /dev/null +++ b/src/ca/caNameSvc.h @@ -0,0 +1,79 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Channel Access Name Service (Used when there is no DDL file) +// Accessed by caService Only +// +// Author: Jie Chen +// +// Revision History: +// caNameSvc.h,v +// Revision 1.3 1997/08/27 18:16:59 chen +// fix compile warning +// +// Revision 1.2 1995/07/05 18:31:48 chen +// minor changes +// +// Revision 1.1.1.1 1995/06/16 17:14:03 epics +// initial import of cdev +// +// +#ifndef _CDEV_CANAME_SVC_H +#define _CDEV_CANAME_SVC_H + +#include +#include +#include +#include +#include +#include +#include + +class caNameSvc: public cdevDevice +{ + public: + // constructor and destructor + caNameSvc (cdevSystem& system = cdevSystem::defaultSystem()); + ~caNameSvc (void); + + int send (char *msg, cdevData& data, cdevData &result); + int send (char *msg, cdevData* data, cdevData &result); + int send (char *msg, cdevData& data, cdevData *result); + int send (char *msg, cdevData* data, cdevData *result); + // PURPOSE: find service data + // REQUIRE: msg must be "resolveServiceData deviceName message [attr] + // RPOMISE: service data will be returned from result as deviceName.attr + + const char *className (void) const {return "caNameSvc";} + + protected: + // hide all those unnecessary member functions + int sendNoBlock (char *msg, cdevData& out, cdevData& result); + int sendNoBlock (char *msg, cdevData* out, cdevData& result); + int sendNoBlock (char *msg, cdevData& out, cdevData* result); + int sendNoBlock (char *msg, cdevData* out, cdevData* result); + + int sendCallback (char *msg, cdevData& out, cdevCallback& callback); + int sendCallback (char *msg, cdevData* out, cdevCallback& callback); + + int getRequestObject (char *msg, cdevRequestObject* &reqobj); + cdevRequestObject* getRequestObject (char *msg); + + int registerReqObject (cdevRequestObject *obj); + int removeReqObject (cdevRequestObject *obj); + + private: + // deny access to copy and assignment operations since there will be + // only one caNameSvc + caNameSvc (const caNameSvc& ); + caNameSvc& operator = (const caNameSvc& ); +}; +#endif + diff --git a/src/ca/caRequestObject.cc b/src/ca/caRequestObject.cc new file mode 100755 index 0000000..25d11c4 --- /dev/null +++ b/src/ca/caRequestObject.cc @@ -0,0 +1,2945 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Channel Access RequestObject Class +// +// Author: Jie Chen +// +// Revision History: +// caRequestObject.cc,v +// Revision 1.34 1998/04/10 13:55:41 chen +// add access information to caService +// +// Revision 1.33 1998/04/08 20:19:05 chen +// fix set problem +// +// Revision 1.32 1998/03/30 19:39:53 chen +// bug fix for channel_ null pointer inside destructor +// +// Revision 1.31 1998/03/23 21:17:18 chen +// Fix a bug related to prop channels: found on solaris +// +// Revision 1.30 1998/03/09 15:45:40 chen +// Install ENUM no_str into displayHigh for ENUM type +// +// Revision 1.29 1998/03/05 18:49:13 chen +// fix a bug on context == 2 on property channels +// +// Revision 1.28 1998/03/03 20:50:21 chen +// Return array of strings if one asks about display information on DBR_ENUM channel +// +// Revision 1.27 1998/02/18 19:48:26 chen +// fix ca set access error +// +// Revision 1.26 1997/08/08 16:41:36 chen +// add char type and fix dbr == null +// +// Revision 1.25 1997/07/18 14:24:44 chen +// remove one printf +// +// Revision 1.24 1997/03/03 17:36:28 chen +// add buffering to channel access connection +// +// Revision 1.23 1996/09/18 14:46:50 chen +// Channel holds multiple monitor objects +// +// Revision 1.22 1996/07/23 15:59:14 chen +// send with monitorOff will remove all monitored callbacks +// +// Revision 1.21 1996/05/02 14:18:26 chen +// Fix monitorOn and unfinished transaction bug +// +// Revision 1.20 1996/01/05 18:40:05 chen +// Fix a bug for gcc and a bug for monitoring enum values +// +// Revision 1.19 1995/12/08 15:42:28 chen +// fix double/float set value and add deferred execution mode +// +// Revision 1.18 1995/11/07 14:26:57 akers +// Added CTRLLO and CTRLHI to populateMonitor +// +// Revision 1.17 1995/10/30 13:33:05 akers +// Added cdev specific version of strncpy +// +// Revision 1.16 1995/10/26 14:33:14 akers +// Removal of Warnings +// +// Revision 1.15 1995/10/17 20:20:51 chen +// redefine getState +// +// Revision 1.14 1995/10/13 14:42:37 chen +// add debug flag in the monitorProperty +// +// Revision 1.13 1995/10/03 19:56:25 chen +// add monitoring properties +// +// Revision 1.12 1995/09/19 16:06:36 chen +// minor change on bit monitoring +// +// Revision 1.11 1995/09/18 18:22:49 chen +// add monitoring bit pattern capability for long/short integer +// +// Revision 1.10 1995/09/15 19:27:28 chen +// Fix a bug of array of doubles +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#include +#include +#include +#include +#include "caRequestObject.h" +#include "caNameSvc.h" +#include "caService.h" +#include "caChannel.h" +#include "caMisc.h" + +#ifndef TS_EPOCH_SEC_PAST_1970 +/* 1/1/90 20 yr (5 leap) of seconds */ +#define TS_EPOCH_SEC_PAST_1970 7305*86400 +#endif + +int caRequestObject::numAttributes = 14; + +caAttr caRequestObject::caAttributes[]= +{ + {"value", 0x00000001}, + {"status", 0x00000002}, + {"severity", 0x00000004}, + {"time", 0x00000008}, + {"precision", 0x00000010}, + {"units", 0x00000020}, + {"displayHigh", 0x00000040}, + {"displayLow", 0x00000080}, + {"alarmHigh", 0x00000100}, + {"alarmLow", 0x00000200}, + {"warningHigh", 0x00000400}, + {"warningLow", 0x00000800}, + {"controlHigh", 0x00001000}, + {"controlLow", 0x00002000}, +}; + +//========================================================================= +// Implementation of caRequestObject +//========================================================================= +caRequestObject::caRequestObject (char *device, char *msg, + caService *, + cdevSystem& system) +:cdevRequestObject (device, msg, system), cache_ (0), prop_ (0), readonly_ (0), + reqType_ (caRequestObject::VALUE), reqMask_ (0x1), channel_ (0) +{ +#ifdef _TRACE_OBJECTS + printf (" Create caRequestObject class \n"); +#endif + caRequestObject::findAction (msg, action_); +} + +caRequestObject::~caRequestObject (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete caRequestObject class \n"); +#endif + caService *svc = (caService *)service_; + if (channel_ && --channel_->count_ <= 0){// no more reference to the channel + svc->removeChannel (channel_->channelName_, channel_); + delete channel_; + } + // reset the pointer of cached properties to zero + if (cache_) { + delete cache_; + cache_ = 0; + } + if (prop_) { + delete prop_; + prop_ = 0; + } +} + +void +caRequestObject::attachChannel (void) +{ + int status; + caService* svc = (caService *)service_; + caPchannel* pchs = 0; + + // caller may need to monitor properties, setup properties cache buffer + // order of calls is important: We have to create property channel before + // we create main channel + if (reqType_ != caRequestObject::VALUE + && action_ == caRequestObject::MONITOR_ON) { + setPropCache (); + pchs = caChannel::createPchannels (); + // create all pchannels + initPropChannels (pchs); + + // flush out the property channel connection requests + svc->flush (); + } + + // get service data first + char svcData[64]; + status = findSvcData (deviceName_, message_, system_, + svcData, sizeof (svcData)); + + status = svc->channelPtr (svcData, channel_); + + if (status != 0){ // the channel has not created yet +#ifdef _CDEV_DEBUG + printf("channel %s not created \n", svcData); +#endif + channel_ = new caChannel (svcData, svc); + svc->addChannel (svcData, channel_); + channel_->count_ = 1; + } + else{ +#ifdef _CDEV_DEBUG + printf("channel %s is created \n", svcData); +#endif + channel_->count_ += 1; +#ifdef _CA_SYNC_CONN + if (!channel_->connected_){ // channel not connected + channel_->connect (); + } +#endif + } + + // assign pchannels to this channel + if (pchs) + channel_->propertyChannels (pchs); +} + +int +caRequestObject::getState (void) +{ + if (channel_->connected_) + return CDEV_STATE_CONNECTED; + else + return CDEV_STATE_NOTCONNECTED; +} + +int +caRequestObject::getAccess (void) +{ + return channel_->readonly_; +} + +int +caRequestObject::setContext (cdevData &cxt) +{ + int temp; + + // clean the mask + reqMask_ = 0x0; + reqType_ = caRequestObject::VALUE; + // get bitmask from cdev requestobject layer + (void)cdevRequestObject::setContext (cxt); + + for (int i = 0; i < caRequestObject::numAttributes; i++){ + if (cxt.get ((caRequestObject::caAttributes[i]).attrName, &temp) == CDEV_SUCCESS){ + reqMask_ |= (caRequestObject::caAttributes[i]).attrValue; + } + } + + if (reqMask_ == 0x0) + reqType_ = caRequestObject::VALUE; + else if (reqMask_ >= caRequestObject::VALUE && + reqMask_ < caRequestObject::STATUS) + reqType_ = caRequestObject::VALUE; + else if (reqMask_ >= caRequestObject::STATUS && + reqMask_ < caRequestObject::TIMESTMP) + reqType_ = caRequestObject::STATUS; + else if (reqMask_ >= caRequestObject::TIMESTMP && + reqMask_ < caRequestObject::GRINFO) + reqType_ = caRequestObject::TIMESTMP; + else if (reqMask_ >= caRequestObject::GRINFO && + reqMask_ < caRequestObject::CTRLINFO) + reqType_ = caRequestObject::GRINFO; + else + reqType_ = caRequestObject::CTRLINFO; +#ifdef _CDEV_DEBUG + printf("reqType_ is %d mask is 0x%x \n", reqType_, reqMask_); +#endif + return CDEV_SUCCESS; +} + +int +caRequestObject::getValueCbk (caChannel* channel, cdevTranObj *obj) +{ + int status; + chtype reqType; + + if (reqType_ > caRequestObject::TIMESTMP && channel->type_ != DBR_STRING) + reqType = dbf_type_to_DBR_CTRL (channel->type_); + else + reqType = dbf_type_to_DBR_TIME (channel->type_); + + status = ::ca_array_get_callback (reqType, channel->numElements_, + channel->cId_, + &(caRequestObject::defaultGetCallback), + (void *)obj); + if (status == ECA_NORMAL) + return CDEV_SUCCESS; + else { + // no callback will be called, remove transaction object + // otherwise group will block + cdevCallback *cbkobj = obj->userCallback_; + cdevRequestObject *reqobj = obj->reqObj_; + cdevData result; + + // T. Straumann: added check if user supplied a callbackFunction. + if (cbkobj && cbkobj->callbackFunction() ) // has callback + (*cbkobj->callbackFunction())(CDEV_IOFAILED, cbkobj->userarg(), + *reqobj, result); + delete obj; + return CDEV_IOFAILED; + } +} + +int +caRequestObject::send (cdevData& out, cdevData& result) +{ + return send (&out, &result); +} + +int +caRequestObject::send (cdevData* out, cdevData& result) +{ + return send (out, &result); +} + +int +caRequestObject::send (cdevData& out, cdevData* result) +{ + return send (&out, result); +} + +int +caRequestObject::send (cdevData* out, cdevData* result) +{ + int status = CDEV_ERROR; + + // check channel has been created or not + if (!channel_) + attachChannel (); + +#ifndef _CA_SYNC_CONN + int st = channel_->asyncConnect (); + if (st != CDEV_SUCCESS) + return st; +#endif + if (channel_->connected_){ + switch (action_){ + case caRequestObject::GET: + if (result == 0) + return CDEV_INVALIDARG; + { + cdevGroup getGrp (2, system_); + getGrp.start(); + sendNoBlock (out, result); + getGrp.end (); + // wait for maximum DEFAULT_TIMEOUT + getGrp.pend ((double)DEFAULT_TIMEOUT); + if (getGrp.allFinished ()) + status = CDEV_SUCCESS; + else + status = CDEV_TIMEOUT; + } + break; + case caRequestObject::SET: + case caRequestObject::PUT: + if (out == 0) + return CDEV_INVALIDARG; + if (readonly_) + return CDEV_INVALIDARG; + // synchronous set need group + { + cdevGroup setGrp (2, system_); + setGrp.start(); + sendNoBlock (out, result); + setGrp.end (); + // wait for maximum DEFAULT_TIMEOUT + setGrp.pend ((double)DEFAULT_TIMEOUT); + if (setGrp.allFinished ()) { + if (out->get (caService::CA_TAG_RESULT_CODE, &status)!= CDEV_SUCCESS) + status = CDEV_SUCCESS; + else + out->remove (caService::CA_TAG_RESULT_CODE); + } + else + status = CDEV_TIMEOUT; + } + break; + case caRequestObject::MONITOR_ON: + status = CDEV_INVALIDARG; + break; + case caRequestObject::MONITOR_OFF: + { + // remove every monitor callbacks + // remove a monitor object from all the channels + cdevCallback userCallback (0, 0); + channel_->removeCallback (&userCallback); + if (channel_->pinited_) { + caPchannel* pch = channel_->pchannels_; + + for (int i = 0; i < MAX_NUM_PCHANNELS; i++) { + if (pch[i].channel != 0) + pch[i].channel->removeCallback (&userCallback); + } + } + } + status = CDEV_SUCCESS; + break; + default: +#ifdef _CDEV_DEBUG + printf("Unsupported action message %s\n", action_); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject does not support message %d\n", + deviceName_, message_, action_); + status = CDEV_INVALIDARG; + break; + } + } + else{ +#ifdef _CDEV_DEBUG + printf("channel disconnected\n"); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject is not connected\n", + deviceName_, message_); + status = CDEV_NOTCONNECTED; + } + return status; +} + +void +caRequestObject::updateResult (int reqMask, int type, + struct dbr_time_short& value, + caMonData &result, + caMonData* cache) +{ + int *val = (int *)(result.value); + *val = value.value; + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + *(result.status) = (int)(value.status); + if (reqMask & (0x1 << i++)) + *(result.severity) = (int)(value.severity); + + cdev_TS_STAMP* tval = result.tstamp; + tval->secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval->nsec = value.stamp.nsec; + + // timeStmp skipped epics fault + unit tag + precision tag + i += 3; + + if (reqMask & (0x1 << i++)) + *(result.disphi) = *(cache->disphi); + if (reqMask & (0x1 << i++)) + *(result.displo) = *(cache->displo); + if (reqMask & (0x1 << i++)) + *(result.alrmhi) = *(cache->alrmhi); + if (reqMask & (0x1 << i++)) + *(result.alrmlo) = *(cache->alrmlo); + if (reqMask & (0x1 << i++)) + *(result.warnhi) = *(cache->warnhi); + if (reqMask & (0x1 << i++)) + *(result.warnlo) = *(cache->warnlo); + if (reqMask & (0x1 << i++)) + *(result.ctrlhi) = *(cache->ctrlhi); + if (reqMask & (0x1 << i++)) + *(result.ctrllo) = *(cache->ctrllo); + } +} + + +void +caRequestObject::updateResult (int reqMask, int type, + struct dbr_time_char& value, + caMonData &result, + caMonData* cache) +{ + BYTE *val = (BYTE *)(result.value); + *val = (BYTE)value.value; + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + *(result.status) = (int)(value.status); + if (reqMask & (0x1 << i++)) + *(result.severity) = (int)(value.severity); + + cdev_TS_STAMP* tval = result.tstamp; + tval->secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval->nsec = value.stamp.nsec; + + // timeStmp skipped epics fault + unit tag + precision + i += 3; + + if (reqMask & (0x1 << i++)) + *(result.disphi) = *(cache->disphi); + if (reqMask & (0x1 << i++)) + *(result.displo) = *(cache->displo); + if (reqMask & (0x1 << i++)) + *(result.alrmhi) = *(cache->alrmhi); + if (reqMask & (0x1 << i++)) + *(result.alrmlo) = *(cache->alrmlo); + if (reqMask & (0x1 << i++)) + *(result.warnhi) = *(cache->warnhi); + if (reqMask & (0x1 << i++)) + *(result.warnlo) = *(cache->warnlo); + if (reqMask & (0x1 << i++)) + *(result.ctrlhi) = *(cache->ctrlhi); + if (reqMask & (0x1 << i++)) + *(result.ctrllo) = *(cache->ctrllo); + } +} + +void +caRequestObject::updateResult (int reqMask, int type, + struct dbr_time_long& value, + caMonData &result, + caMonData* cache) +{ + int *val = (int *)(result.value); + *val = value.value; + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + *(result.status) = (int)(value.status); + if (reqMask & (0x1 << i++)) + *(result.severity) = (int)(value.severity); + + cdev_TS_STAMP* tval = result.tstamp; + tval->secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval->nsec = value.stamp.nsec; + + // timeStmp skipped epics fault + unit tag + precision + i += 3; + + if (reqMask & (0x1 << i++)) + *(result.disphi) = *(cache->disphi); + if (reqMask & (0x1 << i++)) + *(result.displo) = *(cache->displo); + if (reqMask & (0x1 << i++)) + *(result.alrmhi) = *(cache->alrmhi); + if (reqMask & (0x1 << i++)) + *(result.alrmlo) = *(cache->alrmlo); + if (reqMask & (0x1 << i++)) + *(result.warnhi) = *(cache->warnhi); + if (reqMask & (0x1 << i++)) + *(result.warnlo) = *(cache->warnlo); + if (reqMask & (0x1 << i++)) + *(result.ctrlhi) = *(cache->ctrlhi); + if (reqMask & (0x1 << i++)) + *(result.ctrllo) = *(cache->ctrllo); + } +} + +void +caRequestObject::updateResult (int reqMask, int type, + struct dbr_time_float& value, + caMonData &result, + caMonData* cache) +{ + float *val = (float *)(result.value); + *val = value.value; + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + *(result.status) = (int)(value.status); + if (reqMask & (0x1 << i++)) + *(result.severity) = (int)(value.severity); + + cdev_TS_STAMP* tval = result.tstamp; + tval->secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval->nsec = value.stamp.nsec; + + // timeStmp skipped epics fault + unit tag + i += 2; + + if (reqMask & (0x1 << i++)) + *(result.precision) = *(cache->precision); + if (reqMask & (0x1 << i++)) + *(result.disphi) = *(cache->disphi); + if (reqMask & (0x1 << i++)) + *(result.displo) = *(cache->displo); + if (reqMask & (0x1 << i++)) + *(result.alrmhi) = *(cache->alrmhi); + if (reqMask & (0x1 << i++)) + *(result.alrmlo) = *(cache->alrmlo); + if (reqMask & (0x1 << i++)) + *(result.warnhi) = *(cache->warnhi); + if (reqMask & (0x1 << i++)) + *(result.warnlo) = *(cache->warnlo); + if (reqMask & (0x1 << i++)) + *(result.ctrlhi) = *(cache->ctrlhi); + if (reqMask & (0x1 << i++)) + *(result.ctrllo) = *(cache->ctrllo); + } +} + +void +caRequestObject::updateResult (int reqMask, int type, + struct dbr_time_double& value, + caMonData &result, + caMonData* cache) +{ + double *val = (double *)(result.value); + *val = value.value; + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + *(result.status) = (int)(value.status); + if (reqMask & (0x1 << i++)) + *(result.severity) = (int)(value.severity); + + cdev_TS_STAMP* tval = result.tstamp; + tval->secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval->nsec = value.stamp.nsec; + + // timeStmp skipped epics fault + unit tag + i += 2; + + if (reqMask & (0x1 << i++)) + *(result.precision) = *(cache->precision); + if (reqMask & (0x1 << i++)) + *(result.disphi) = *(cache->disphi); + if (reqMask & (0x1 << i++)) + *(result.displo) = *(cache->displo); + if (reqMask & (0x1 << i++)) + *(result.alrmhi) = *(cache->alrmhi); + if (reqMask & (0x1 << i++)) + *(result.alrmlo) = *(cache->alrmlo); + if (reqMask & (0x1 << i++)) + *(result.warnhi) = *(cache->warnhi); + if (reqMask & (0x1 << i++)) + *(result.warnlo) = *(cache->warnlo); + if (reqMask & (0x1 << i++)) + *(result.ctrlhi) = *(cache->ctrlhi); + if (reqMask & (0x1 << i++)) + *(result.ctrllo) = *(cache->ctrllo); + } +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_string& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_short& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_char& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (short)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (short)value.severity); + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_long& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_float& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_STATUS, (int)value.status); + } + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_double& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_STATUS, (int)value.status); + } + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_enum& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_STATUS, (int)value.status); + } + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_short& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + // timeStmp skipped epics fault :- + i++; + i++; // no precision information + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_UNITS, value.units); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (int)value.upper_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (int)value.lower_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMHI, (int)value.upper_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMLO, (int)value.lower_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNHI, (int)value.upper_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNLO, (int)value.lower_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLHI, (int)value.upper_ctrl_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLLO, (int)value.lower_ctrl_limit); + } +} + + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_char& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (short)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (short)value.severity); + // timeStmp skipped epics fault :- + i++; + i++; // no precision information + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_UNITS, value.units); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (BYTE)value.upper_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (BYTE)value.lower_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMHI, (BYTE)value.upper_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMLO, (BYTE)value.lower_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNHI, (BYTE)value.upper_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNLO, (BYTE)value.lower_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLHI, (BYTE)value.upper_ctrl_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLLO, (BYTE)value.lower_ctrl_limit); + } +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_long& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + // timeStmp skipped epics fault :- + i++; + i++; // no precision information + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_UNITS, value.units); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (int)value.upper_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (int)value.lower_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMHI, (int)value.upper_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMLO, (int)value.lower_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNHI, (int)value.upper_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNLO, (int)value.lower_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLHI, (int)value.upper_ctrl_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLLO, (int)value.lower_ctrl_limit); + } +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_float& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + // timeStamp skipped epics fault :- + i++; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_PRECISION, value.precision); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_UNITS, value.units); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (float)value.upper_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (float)value.lower_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMHI, (float)value.upper_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMLO, (float)value.lower_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNHI,(float)value.upper_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNLO,(float)value.lower_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLHI, (float)value.upper_ctrl_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLLO, (float)value.lower_ctrl_limit); + } +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_double& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + // timeStmp skipped epics fault :- + i++; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_PRECISION, value.precision); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_UNITS, value.units); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (double)value.upper_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (double)value.lower_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMHI, (double)value.upper_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMLO, (double)value.lower_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNHI,(double)value.upper_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNLO,(double)value.lower_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLHI, (double)value.upper_ctrl_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLLO, (double)value.lower_ctrl_limit); + } +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_enum& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + // timeStmp skipped epics fault :- + i++; + // no precision information + i++; + // no units information + i++; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (int)value.no_str - 1); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (int)0); + } +} + +int +caRequestObject::sendNoBlock (cdevData& out, cdevData& result) +{ + return sendNoBlock (&out, &result); +} + +int +caRequestObject::sendNoBlock (cdevData& out, cdevData *result) +{ + return sendNoBlock (&out, result); +} + +int +caRequestObject::sendNoBlock (cdevData* out, cdevData& result) +{ + return sendNoBlock (out, &result); +} + +int +caRequestObject::sendNoBlock (cdevData* out, cdevData* result) +{ + if (!channel_) + attachChannel (); + + // first check whether this is deferred mode + if (deferExecution (out, result)) + return CDEV_SUCCESS; + + int status = CDEV_ERROR; + cdevTranObj *xobj = 0; + + switch (action_){ + case caRequestObject::GET: + if (result == 0) + return CDEV_INVALIDARG; + xobj = new cdevTranObj (&system_, this, result, 0); + // if channel is not connected, put all executions in the buffer + if (!channel_->connected_) { + bufferExecution (0, result, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = getValueCbk (channel_, xobj); + break; + case caRequestObject::SET: + case caRequestObject::PUT: + if (out == 0) + return CDEV_INVALIDARG; + if (readonly_) + return CDEV_INVALIDARG; + + // if channel is not connected, put all executions in the buffer + // must clone the data as the caller may delete it + if (!channel_->connected_) { + cdevData *cloned = new cdevData(*out); + xobj = new cdevTranObj (&system_, this, cloned, 0); + bufferExecution (cloned, result, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } else { + xobj = new cdevTranObj (&system_, this, out, 0); + } + status = setValueCbk (channel_, xobj); + break; + case caRequestObject::MONITOR_ON: + status = CDEV_INVALIDARG; + break; + case caRequestObject::MONITOR_OFF: + { + // remove every monitor callbacks + // remove a monitor object from all the channels + cdevCallback userCallback (0, 0); + channel_->removeCallback (&userCallback); + if (channel_->pinited_) { + caPchannel* pch = channel_->pchannels_; + + for (int i = 0; i < MAX_NUM_PCHANNELS; i++) { + if (pch[i].channel != 0) + pch[i].channel->removeCallback (&userCallback); + } + } + } + status = CDEV_SUCCESS; + break; + default: +#ifdef _CDEV_DEBUG + printf("Unsupported action message %s\n", action_); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject does not support message %d\n", + deviceName_, message_, action_); + status = CDEV_INVALIDARG; + break; + } + return status; +} + + +int +caRequestObject::execNoBlock (cdevData* out, cdevData* result, void* arg) +{ + // arg is a cdevTranObj + cdevTranObj* xobj = (cdevTranObj *)arg; + + // first check whether this is deferred mode + if (deferExecution (out, result)) { + delete xobj; + return CDEV_SUCCESS; + } + + int status = CDEV_ERROR; + + switch (action_){ + case caRequestObject::GET: + // if channel is not connected, put all executions in the buffer + if (!channel_->connected_) { + bufferExecution (0, result, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = getValueCbk (channel_, xobj); + break; + case caRequestObject::SET: + case caRequestObject::PUT: + // if channel is not connected, put all executions in the buffer + if (!channel_->connected_) { + cdevData *cloned = new cdevData(*out); + bufferExecution (cloned, result, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = setValueCbk (channel_, xobj); + break; + default: +#ifdef _CDEV_DEBUG + printf("Unsupported action message %s\n", action_); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject does not support message %d\n", + deviceName_, message_, action_); + status = CDEV_INVALIDARG; + break; + } + return status; +} + + +// T. Straumann: added 'putOnly' flag which causes +// ca_array_put() to be used instead of a ca_array_put_callback() + +int +caRequestObject::setValueCbk (caChannel* channel, cdevTranObj *xobj) +{ + int caStatus = -1; + int dataStatus = CDEV_SUCCESS; + int ioStatus = CDEV_SUCCESS; + + cdevData *out = xobj->resultData_; + cdevData result; + cdevCallback *cbkobj = xobj->userCallback_; + cdevRequestObject *reqObj = xobj->reqObj_; + cdevCallbackFunction userFcn; + int putOnly = (action_ == caRequestObject::PUT); + + if (dataMatch (*out, (int)channel->type_, + (int)(channel_->numElements_)) != CDEV_SUCCESS){ + // I have to delete this transaction object + // T. Straumann: added check if user supplied a callbackFunction. + if (cbkobj && (userFcn = cbkobj->callbackFunction()) ) { // has callback + (*userFcn)(CDEV_ERROR, cbkobj->userarg(), *reqObj, result); + } + delete xobj; + return CDEV_INVALIDARG; + } + + switch (channel->type_){ + case DBR_STRING: + if (channel->numElements_ == 1){ + char temp[MAX_STRING_SIZE]; + dataStatus = out->get (caService::CA_TAG_VALUE, temp, sizeof(temp)); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 has no ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_STRING, channel->numElements_, + channel->cId_, temp) + : ::ca_array_put_callback (DBR_STRING, channel->numElements_, + channel->cId_, temp, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_STRING, channel->numElements_, + channel->cId_, temp); +#endif + } + } + else { + char **temp = new char*[channel->numElements_]; + // each item will be allocated by the following + dataStatus = out->get (caService::CA_TAG_VALUE, temp); + int count = (int)channel->numElements_; + dataStatus = out->getElems (caService::CA_TAG_VALUE, (size_t *)&count); + if (dataStatus == CDEV_SUCCESS){ + char *cbuf = new char[channel->numElements_*MAX_STRING_SIZE]; + int j = 0; + for (int i = 0; i < channel->numElements_; i++){ + ::cdevStrncpy (&(cbuf[j]), temp[i], MAX_STRING_SIZE); + j += MAX_STRING_SIZE; + } + // epics 3.11 has no ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_STRING, channel->numElements_, + channel->cId_, cbuf) + : ::ca_array_put_callback (DBR_STRING, channel->numElements_, + channel->cId_, cbuf, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_STRING, channel->numElements_, + channel->cId_, cbuf); +#endif + for (i = 0; i < count; i++) + delete []temp[i]; + delete []temp; + delete []cbuf; + } + } + break; + case DBR_ENUM: + if (channel->numElements_ == 1){ + char temp[MAX_STRING_SIZE]; + char temp2[MAX_STRING_SIZE]; + int tind; + dataStatus = out->get (caService::CA_TAG_VALUE, temp, sizeof(temp)); + if (dataStatus == CDEV_SUCCESS){ + int i = 0; + sscanf (temp, "%d", &tind); + // if a caller supplies (only) an integer, it will be treated as an index + if (sscanf (temp, "%d%s", &tind, temp2) == 1 && + tind >= 0 && + tind < channel->accessBuffer_->cenmval.no_str) + i = tind; + else { + for (i = 0; i < channel->accessBuffer_->cenmval.no_str; i++) { + if (::strcmp (temp, channel->accessBuffer_->cenmval.strs[i]) == 0) + break; + } + if (i >= channel->accessBuffer_->cenmval.no_str){ +#ifdef _CDEV_DEBUG + printf("Unmatched string %s to enum record\n", temp); + printf("The following are the string values\n"); + for (i = 0; i < channel->accessBuffer_->cenmval.no_str; i++) + printf(" %s ",channel->accessBuffer_->cenmval.strs[i]); + printf("\n"); +#endif + return CDEV_INVALIDARG; + } + } + short desiredIndex = i; +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_ENUM, channel->numElements_, + channel->cId_, &desiredIndex) + : ::ca_array_put_callback (DBR_ENUM, channel->numElements_, + channel->cId_, &desiredIndex, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_ENUM, channel->numElements_, + channel->cId_, &desiredIndex); +#endif + } + } + else { +#ifdef _CDEV_DEBUG + printf ("Multiple elements of DBR_ENUM is not supported in CDEV\n"); +#endif + return CDEV_INVALIDARG; + } + break; + case DBR_SHORT: + if (channel->numElements_ == 1){ + int value; + dataStatus = out->get (caService::CA_TAG_VALUE, &value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, &value) + : ::ca_array_put_callback (DBR_LONG, channel->numElements_, + channel->cId_, &value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, &value); +#endif + } + } + else{ + int *value = new int[channel->numElements_]; + dataStatus = out->get (caService::CA_TAG_VALUE, value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, value) + : ::ca_array_put_callback (DBR_LONG, channel->numElements_, + channel->cId_, value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, value); +#endif + delete []value; + } + } + break; + case DBR_CHAR: + if (channel->numElements_ == 1){ + BYTE value; + dataStatus = out->get (caService::CA_TAG_VALUE, &value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_CHAR, channel->numElements_, + channel->cId_, &value) + : ::ca_array_put_callback (DBR_CHAR, channel->numElements_, + channel->cId_, &value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_CHAR, channel->numElements_, + channel->cId_, &value); +#endif + } + } + else{ + BYTE *value = new BYTE[channel->numElements_]; + dataStatus = out->get (caService::CA_TAG_VALUE, value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_CHAR, channel->numElements_, + channel->cId_, value) + : ::ca_array_put_callback (DBR_CHAR, channel->numElements_, + channel->cId_, value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_CHAR, channel->numElements_, + channel->cId_, value); +#endif + delete []value; + } + } + break; + case DBR_LONG: + if (channel->numElements_ == 1){ + int value; + dataStatus = out->get (caService::CA_TAG_VALUE, &value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, &value) + : ::ca_array_put_callback (DBR_LONG, channel->numElements_, + channel->cId_, &value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, &value); +#endif + } + } + else { + int *value = new int[channel->numElements_]; + dataStatus = out->get (caService::CA_TAG_VALUE, value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, value) + : ::ca_array_put_callback (DBR_LONG, channel->numElements_, + channel->cId_, value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, value); +#endif + delete []value; + } + } + break; + case DBR_FLOAT: + case DBR_DOUBLE: + if (channel->numElements_ == 1) { + double fval; + dataStatus = out->get (caService::CA_TAG_VALUE, &fval); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have put callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_DOUBLE, channel->numElements_, + channel->cId_, &fval) + : ::ca_array_put_callback(DBR_DOUBLE, channel->numElements_, + channel->cId_, &fval, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_DOUBLE, channel->numElements_, + channel->cId_, &fval); +#endif + } + } + else { + double *fval = new double[channel->numElements_]; + dataStatus = out->get (caService::CA_TAG_VALUE, fval); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have put callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_DOUBLE, channel->numElements_, + channel->cId_, fval) + : ::ca_array_put_callback(DBR_DOUBLE, channel->numElements_, + channel->cId_, fval, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_DOUBLE, channel->numElements_, + channel->cId_, fval); +#endif + delete []fval; + } + } + break; + default: +#ifdef _CDEV_DEBUG + printf("unsupported data type \n"); +#endif + return CDEV_INVALIDARG; + // Break not needed because of return statement + // break; + } + // check data status first + if (dataStatus != CDEV_SUCCESS) { + // remove transaction objecyt so a group will not block + if (cbkobj && (userFcn = cbkobj->callbackFunction()) ) { + (*userFcn)(dataStatus, cbkobj->userarg(), *reqObj, result); + + dataStatus = CDEV_SUCCESS; // problem now handled, no more to report + } + else { + // use user outbound data as result code + out->insert (caService::CA_TAG_RESULT_CODE, dataStatus); + } + delete xobj; + return dataStatus; + } + + // check channel access status + if (caStatus != ECA_NORMAL){ +#ifdef _CDEV_DEBUG + printf("ca_array_put_callback failed\n"); +#endif + // remove transaction objecyt so a group will not block + if (cbkobj && (userFcn = cbkobj->callbackFunction()) ) { + (*userFcn)(CDEV_IOFAILED, cbkobj->userarg(), *reqObj, result); + + ioStatus = CDEV_SUCCESS; // problem now handled, no more to report + } + else { + // use user outbound data as result code + out->insert (caService::CA_TAG_RESULT_CODE, CDEV_IOFAILED); + ioStatus = CDEV_IOFAILED; + } + delete xobj; + return ioStatus; + } + + // trasaction object will be removed from default callback function + // for epics 3.11 I have no idea when put will finish + // so I have to delete this transaction object +#ifdef _EPICS_3_12 + if (putOnly) { +#endif + // so what I do, just call callback :--- + // T. Straumann: added check if user supplied a callbackFunction. + if (cbkobj && (userFcn = cbkobj->callbackFunction()) ) { + (*userFcn)(CDEV_SUCCESS, cbkobj->userarg(), *reqObj, result); + } + else { + // use user outbound data as result code + out->insert (caService::CA_TAG_RESULT_CODE, CDEV_SUCCESS); + } + + delete xobj; +#ifdef _EPICS_3_12 + } +#endif + return CDEV_SUCCESS; +} +int +caRequestObject::sendCallback (cdevData& out, cdevCallback& callback) +{ + return sendCallback (&out, callback); +} + +int +caRequestObject::sendCallback (cdevData* out, cdevCallback& userCallback) +{ + if (!channel_) + attachChannel (); + + if (deferExecution (out, &userCallback)) + return CDEV_SUCCESS; + + int status = CDEV_ERROR; + cdevTranObj *xobj = 0; + caMonObj* obj = 0; + + // copy userCallback into the following callback, which will free + // user from taking care cdevCallback object. + // Note: cdevCallback's new operator is an overloaded operator + cdevCallback* callback = 0; + + switch (action_){ + case caRequestObject::GET: + callback = new cdevCallback (userCallback); + xobj = new cdevTranObj (&system_, this, 0, callback); + if (!channel_->connected_) { + bufferExecution (0, callback, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = getValueCbk (channel_, xobj); + break; + case caRequestObject::SET: + case caRequestObject::PUT: + if (out == 0) + return CDEV_INVALIDARG; + if (readonly_) + return CDEV_INVALIDARG; + callback = new cdevCallback (userCallback); + + // if deferred execution, clone the data as caller may delete it + if (!channel_->connected_) { + cdevData *cloned = new cdevData(*out); + xobj = new cdevTranObj (&system_, this, cloned, callback); + bufferExecution (cloned, callback, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } else { + xobj = new cdevTranObj (&system_, this, out, callback); + } + status = setValueCbk (channel_, xobj); + break; + case caRequestObject::MONITOR_ON: + { + // copy user callback + callback = new cdevCallback (userCallback); + // create a new transaction object + xobj = new cdevTranObj (&system_, this, 0, callback); + + //================================================== + // if there is one callback is the same as the new + // one user wants, discard the new one + //================================================= + if (channel_->hasSameCallback (*callback)) { + delete xobj; + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s dislikes the same callbacks\n", + deviceName_, message_); + return CDEV_ERROR; + } + + // if channel is not connected, buffer this up + if (!channel_->connected_) { + bufferExecution (0, callback, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + + //================================================== + // if this requests has the same context i.e. + // or the same req type and request mask, use the + // same channel access event Id to get network + // response from the server. + //================================================= + caMonObj* eobj = 0; + if ((eobj = channel_->hasSameCallingCxt (reqType_, reqMask_)) != 0) { + // create new callback object and add to the list + caMonCbk* cbk = new caMonCbk (*xobj->userCallback_, xobj->resultData_); + eobj->addCallback (cbk); + // immediately call user callback now + eobj->callCallback (cbk); + + // call monitor properties which will add more monitor + // objects to the appropriate property channels + addCbksToPChannels (channel_, *xobj->userCallback_, + xobj->resultData_); + delete xobj; + + return CDEV_SUCCESS; + } + // get monitor object from transaction object + // and disable the transaction object from deleting + // the callback object + obj = new caMonObj (*xobj); + // set up associated arguments + obj->setMonitorInfo (caService::CA_TAG_VALUE, + CDEV_SUCCESS, + channel_, + reqType_, + reqMask_); + xobj->disableDeleteCbk (); + + monitorProperties (channel_, obj); + status = monitorValue (channel_, obj); + } + break; + case caRequestObject::MONITOR_OFF: + { + // remove a monitor object from all the channels + // monitor objects' destructor will call all monitor + // monitor callbacks to denote caller that monitor + // is over + channel_->removeCallback (&userCallback); + if (channel_->pinited_) { + caPchannel* pch = channel_->pchannels_; + + for (int i = 0; i < MAX_NUM_PCHANNELS; i++) { + if (pch[i].channel != 0) + pch[i].channel->removeCallback (&userCallback); + } + } + } + status = CDEV_SUCCESS; + break; + default: +#ifdef _CDEV_DEBUG + printf("Unsupported action message %s\n", action_); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject does not support message %d\n", + deviceName_, message_, action_); + status = CDEV_INVALIDARG; + break; + } + return status; +} + + +int +caRequestObject::execCallback (cdevData* out, + cdevCallback& userCallback, + void* arg) +{ + // arg is actually a transcation object + cdevTranObj* xobj = (cdevTranObj *)arg; + if (deferExecution (out, &userCallback)) { + // the above code will make copy of user callback, so it is safe + // to delete xobj that has userCallback in it here + delete xobj; + return CDEV_SUCCESS; + } + + int status = CDEV_ERROR; + caMonObj* obj = 0; + + // copy userCallback into the following callback, which will free + // user from taking care cdevCallback object. + // Note: cdevCallback's new operator is an overloaded operator + cdevCallback* callback = 0; + + switch (action_){ + case caRequestObject::GET: + if (!channel_->connected_) { + bufferExecution (0, xobj->userCallback_, + (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = getValueCbk (channel_, xobj); + break; + case caRequestObject::SET: + case caRequestObject::PUT: + if (!channel_->connected_) { + cdevData *cloned = new cdevData(*out); + bufferExecution (cloned, xobj->userCallback_, + (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = setValueCbk (channel_, xobj); + break; + case caRequestObject::MONITOR_ON: + { + if (!channel_->connected_) { + bufferExecution (0, xobj->userCallback_, + (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + + //================================================== + // if this requests has the same context i.e. + // or the same req type and request mask, use the + // same channel access event Id to get network + // response from the server. + //================================================= + caMonObj* eobj = 0; + if ((eobj = channel_->hasSameCallingCxt (reqType_, reqMask_)) != 0) { + // create new callback object and add to the list + caMonCbk* cbk = new caMonCbk (*xobj->userCallback_, xobj->resultData_); + eobj->addCallback (cbk); + // immediately call user callback now + eobj->callCallback (cbk); + + // call monitor properties which will add more monitor + // objects to the appropriate property channels + addCbksToPChannels (channel_, *xobj->userCallback_, + xobj->resultData_); + delete xobj; + + return CDEV_SUCCESS; + } + // get monitor object from transaction object + // and disable the transaction object from deleting + // the callback object + obj = new caMonObj (*xobj); + // set up associated arguments + obj->setMonitorInfo (caService::CA_TAG_VALUE, + CDEV_SUCCESS, + channel_, + reqType_, + reqMask_); + xobj->disableDeleteCbk (); + + monitorProperties (channel_, obj); + status = monitorValue (channel_, obj); + } + break; + default: +#ifdef _CDEV_DEBUG + printf("Unsupported action message %s\n", action_); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject does not support message %d\n", + deviceName_, message_, action_); + status = CDEV_INVALIDARG; + break; + } + return status; +} + +void +caRequestObject::initPropChannels (caPchannel* pch) +{ + cdevData& cxt = getContext (); + int val; + char svcData[64]; + caService* svc = (caService *)service_; + + // scan through all property channels to establish connection if necessary + for (int i = 2; i < MAX_NUM_PCHANNELS; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS) + // caller specify a trigger or I am going to setup channel + // for those properties which are not changed rapidly + if (val == 2 || i >= 2) { + // construct channel access record.attr + ::strcpy (svcData, device_->name()); + ::strcat (svcData, "."); + ::strcat (svcData, svc->attr (pch[i].tag)); + + if (pch[i].channel == 0) { +#ifdef _CDEV_DEBUG + printf ("property channel %s is not created, do it now\n", svcData); +#endif + caChannel* ch = 0; + + if (svc->channelPtr (svcData, ch) != 0) { + // the channel has not created yet +#ifdef _CDEV_DEBUG + printf("property channel %s not created \n", svcData); +#endif + ch = new caChannel (svcData, svc); + svc->addChannel (svcData, ch); + ch->count_ = 1; + } + else{ +#ifdef _CDEV_DEBUG + printf("property channel %s created \n", svcData); +#endif + ch->count_ += 1; +#ifdef _CA_SYNC_CONN + if (!ch->connected_){ // channel not connected + channel_->connect (); + } +#endif + } + pch[i].channel = ch; + } + } + } +} + +void +caRequestObject::initPropChannels (caChannel* parent) +{ + cdevData& cxt = getContext (); + int val; + char svcData[64]; + caService* svc = (caService *)service_; + + caPchannel* pch = parent->pchannels_; + + if (!pch) + return; + + // scan through all property channels to establish connection if necessary + for (int i = 2; i < MAX_NUM_PCHANNELS; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS) + // caller specify a trigger or I am going to setup channel + // for those properties which are not changed rapidly + if (val == 2 || i >= 2) { + // construct channel access record.attr + ::strcpy (svcData, device_->name()); + ::strcat (svcData, "."); + ::strcat (svcData, svc->attr (pch[i].tag)); + + if (pch[i].channel == 0) { +#ifdef _CDEV_DEBUG + printf ("property channel %s is not created, do it now\n", svcData); +#endif + caChannel* ch = 0; + + if (svc->channelPtr (svcData, ch) != 0) { + // the channel has not created yet +#ifdef _CDEV_DEBUG + printf("property channel %s not created \n", ch->channelName_); +#endif + ch = new caChannel (svcData, svc); + svc->addChannel (svcData, ch); + ch->count_ = 1; + } + else{ +#ifdef _CDEV_DEBUG + printf("property channel %s created \n", svcData); +#endif + ch->count_ += 1; +#ifdef _CA_SYNC_CONN + if (!ch->connected_){ // channel not connected + channel_->connect (); + } +#endif + } + pch[i].channel = ch; + } + } + } +} + +void +caRequestObject::monitorProperties (caChannel* parent, caMonObj *obj) +{ + cdevData& cxt = getContext (); + int val; + char svcData[64]; + caService* svc = (caService *)service_; + + // get property channel pointer + caPchannel* pch = parent->pchannels_; + + if (!pch) /* no property channel, return */ + return; + + // scan through all property channels to establish connection if necessary + for (int i = 2; i < MAX_NUM_PCHANNELS; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS) + // caller specify a trigger or I am going to setup channel + // for those properties which are not changed rapidly + if (val == 2 || i >= 2) { + // construct channel access record.attr + if (pch[i].channel && pch[i].channel->connected_){ + if (!pch[i].monitored) { + caMonObj *newobj = new caMonObj (*obj, obj->cbks_->cbk_, + obj->cbks_->out_); + newobj->tobj_ = 0; + newobj->tag_ = pch[i].tag; + newobj->cbkStatus_ = CDEV_SUCCESS; + newobj->channel_ = pch[i].channel; + + // sep-27-1995 -- Jie chen + // if this context value == 1, we cache its value instead of + // calling user callback directly + if (val == 1) + newobj->cbks_->enableCache (); + + if (monitorPropValue (pch[i].channel, newobj) == CDEV_SUCCESS) { + pch[i].channel->addMonitorObj (newobj); + pch[i].monitored = 1; + } + else { + delete pch[i].channel; + pch[i].channel = 0; + } + } + else { + // get first monitor object pointer from this property + // channel: it should never return 0 + caMonObj* fobj = pch[i].channel->firstMonitorObj (); + if (!fobj) { + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s has bad property channel\n", + deviceName_, message_); + return; + } + + // create a new callback object with dupliate user callback + // information in it + caMonCbk* cbkobj = new caMonCbk (*obj->cbks_->cbk_, + obj->cbks_->out_); + if (val == 1) + cbkobj->enableCache (); + + fobj->addCallback (cbkobj); + } + } + } + } +} + + +void +caRequestObject::addCbksToPChannels (caChannel* parent, + cdevCallback& cbk, + cdevData* out) +{ + cdevData& cxt = getContext (); + int val; + char svcData[64]; + caService* svc = (caService *)service_; + + // get property channel pointer + caPchannel* pch = parent->pchannels_; + if (!pch) + return; + + // scan through all property channels to establish connection if necessary + for (int i = 2; i < MAX_NUM_PCHANNELS; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS) + // caller specify a trigger or I am going to setup channel + // for those properties which are not changed rapidly + + if ((val == 2 || i >= 2) && pch[i].channel != 0 && + pch[i].channel->connected_ && pch[i].monitored) { +#ifdef _CDEV_DEBUG + printf ("property channel %s is created already\n", svcData); +#endif + // get first monitor object pointer from this property + // channel: it should never return 0 + caMonObj* fobj = pch[i].channel->firstMonitorObj (); + if (!fobj) { + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s has bad property channel\n", + deviceName_, message_); + return; + } + + // create a new callback object with dupliate user callback + // information in it + caMonCbk* cbkobj = new caMonCbk (cbk, out); + + if (val == 1) + cbkobj->enableCache (); + else + // call callbak right away + fobj->callCallback (cbkobj); + + fobj->addCallback (cbkobj); + } + } +} + +int +caRequestObject::monitorValue (caChannel* channel, caMonObj *xobj) +{ + // check value context + cdevData& cxt = getContext (); + int val; + int mask = DBE_VALUE | DBE_ALARM; + + if (cxt.get (caService::CA_TAG_VALUE, &val) == CDEV_SUCCESS) { + if (val == 0) // if 0: no monitor on value + mask = 0; + } + + // get property channel pointer + caPchannel* pch = channel->pchannels_; + + if (pch) { + // scan first two property channels to change monitor mask if necessary + for (int i = 0; i < 2; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS){ + if (val >=2) + mask = mask | DBE_ALARM; + } + } + } + + if (mask == 0) { // we have nothing to do + // no callback will be called, remove transaction object + // otherwise group will block + cdevCallback *cbkobj = xobj->cbks_->cbk_; + cdevRequestObject *reqobj = xobj->reqObj_; + cdevData result; + + cbkobj->fireCallback (CDEV_IOFAILED, cbkobj->userarg (), + *reqobj, result, 0); + + if (xobj->tobj_) { + delete xobj->tobj_; + xobj->tobj_ = 0; + } + delete xobj; + return CDEV_IOFAILED; + } + + int status, caStatus; + int reqType; + // get everything of status and severity and timestamp + reqType = (int)dbf_type_to_DBR_TIME (channel->type_); + + caStatus = ::ca_add_masked_array_event (reqType, + channel->numElements_, + channel->cId_, + &(caRequestObject::callMonitorCallback), + (void *)(xobj), + 0, 0, 0, + &(xobj->mEvId_), + mask); + if (caStatus != ECA_NORMAL) { + // no callback will be called, remove transaction object + // otherwise group will block + cdevCallback *cbkobj = xobj->cbks_->cbk_; + cdevRequestObject *reqobj = xobj->reqObj_; + cdevData result; + + cbkobj->fireCallback (CDEV_IOFAILED, cbkobj->userarg (), + *reqobj, result, 0); + if (xobj->tobj_) { + delete xobj->tobj_; + xobj->tobj_ = 0; + } + delete xobj; + status = CDEV_IOFAILED; + } + else + status = CDEV_SUCCESS; + + return status; +} + +int +caRequestObject::monitorPropValue (caChannel* channel, caMonObj *xobj) +{ + int status = ::ca_add_masked_array_event (channel->type_, + channel->numElements_, + channel->cId_, + &(caRequestObject::callPropMonitorCallback), + (void *)(xobj), + 0, 0, 0, + &(xobj->mEvId_), + DBE_VALUE); + if (status != ECA_NORMAL) + return CDEV_IOFAILED; + else + return CDEV_SUCCESS; +} + +void +caRequestObject::convertData (int chtype, + int tag, + int reqMask, + int reqType, + struct event_handler_args& args, + cdevData& resData) +{ + switch (chtype){ + case DBR_STRING: + { + struct dbr_time_string *retValue = 0; + retValue = (struct dbr_time_string *)args.dbr; + if (args.count == 1){ + resData.insert (tag, retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else{ + char **insertBuf = new char* [args.count]; + insertBuf[0] = new char[MAX_STRING_SIZE]; + ::cdevStrncpy (insertBuf[0], retValue->value, MAX_STRING_SIZE); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_string); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = new char[MAX_STRING_SIZE]; + ::cdevStrncpy (insertBuf[i], &(buffer[j]), MAX_STRING_SIZE); + j += MAX_STRING_SIZE; + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + + for (i = 0; i < args.count; i++) + delete []insertBuf[i]; + delete []insertBuf; + } + } + break; + case DBR_ENUM: + if (args.count == 1){ + if (reqType > caRequestObject::TIMESTMP){ + struct dbr_ctrl_enum *retValue = 0; + retValue = (struct dbr_ctrl_enum *)args.dbr; + if (reqType >= caRequestObject::GRINFO) { + int i = 0; + // we want display information + char **strs = 0; + if (retValue->no_str > 0) { + strs = new char*[retValue->no_str]; + for (i = 0; i < retValue->no_str; i++) { + strs[i] = new char[strlen (retValue->strs[i]) + 1]; + strcpy (strs[i], retValue->strs[i]); + } + } + resData.insert (tag, strs, retValue->no_str); + + // free memory + for (i = 0; i < retValue->no_str; i++) + delete []strs[i]; + delete []strs; + } + else { + unsigned short index = retValue->value; + // If this string is a null string, we return index value + if (!strlen (retValue->strs[index])) + resData.insert (tag, index); + else + resData.insert (tag, retValue->strs[index]); + } + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else{ + struct dbr_time_enum *retValue = 0; + retValue = (struct dbr_time_enum *)args.dbr; + // since dbr_time_enum has no string in it's structure + // it is impossible to find corresponding strings + resData.insert (tag, retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + } + else{ +#ifdef _CDEV_DEBUG + printf ("Multiple elements of DBR_ENUM is not supported in CDEV\n"); +#endif + } + break; + case DBR_SHORT: + if (reqType > caRequestObject::TIMESTMP){ + struct dbr_ctrl_short *retValue = 0; + retValue = (struct dbr_ctrl_short *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (int)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + int* insertBuf = new int[args.count]; + insertBuf[0] = (int)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_ctrl_short); + short tmp; + for (int i = 1; i < args.count; i++){ + tmp = *(short *)&(buffer[j]); + insertBuf[i] = (int)tmp; + j += sizeof (short); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + + delete []insertBuf; + } + } + else{ + struct dbr_time_short *retValue = 0; + retValue = (struct dbr_time_short *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (int)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + int* insertBuf = new int[args.count]; + insertBuf[0] = (int)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_short); + short tmp; + for (int i = 1; i < args.count; i++){ + tmp = *(short *)&(buffer[j]); + insertBuf[i] = (int)tmp; + j += sizeof (short); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + break; + case DBR_CHAR: + if (reqType > caRequestObject::TIMESTMP){ + struct dbr_ctrl_char *retValue = 0; + retValue = (struct dbr_ctrl_char *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (BYTE)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + BYTE* insertBuf = new BYTE[args.count]; + insertBuf[0] = (BYTE)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_ctrl_char); + char tmp; + for (int i = 1; i < args.count; i++){ + tmp = *(char *)&(buffer[j]); + insertBuf[i] = (BYTE)tmp; + j += sizeof (char); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + + delete []insertBuf; + } + } + else{ + struct dbr_time_char *retValue = 0; + retValue = (struct dbr_time_char *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (BYTE)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + BYTE* insertBuf = new BYTE[args.count]; + insertBuf[0] = (BYTE)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_char); + char tmp; + for (int i = 1; i < args.count; i++){ + tmp = *(char *)&(buffer[j]); + insertBuf[i] = (BYTE)tmp; + j += sizeof (char); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + break; + case DBR_LONG: + if (reqType > caRequestObject::TIMESTMP){ + struct dbr_ctrl_long *retValue = 0; + retValue = (struct dbr_ctrl_long *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (int)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + int* insertBuf = new int[args.count]; + insertBuf[0] = (int)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_ctrl_long); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(int *)&(buffer[j]); + j += sizeof (long); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + else{ + struct dbr_time_long *retValue = 0; + retValue = (struct dbr_time_long *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (int)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + int* insertBuf = new int[args.count]; + insertBuf[0] = (int)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_long); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(int *)&(buffer[j]); + j += sizeof (long); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + break; + case DBR_FLOAT: + if (reqType > caRequestObject::TIMESTMP){ + struct dbr_ctrl_float *retValue = 0; + retValue = (struct dbr_ctrl_float *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (float)retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else{ + float* insertBuf = new float[args.count]; + insertBuf[0] = (float)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_ctrl_float); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(float *)&(buffer[j]); + j += sizeof (float); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + else{ + struct dbr_time_float *retValue = 0; + retValue = (struct dbr_time_float *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (float)retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + float* insertBuf = new float[args.count]; + insertBuf[0] = (float)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_float); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(float *)&(buffer[j]); + j += sizeof (float); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + break; + case DBR_DOUBLE: + if (reqType > caRequestObject::TIMESTMP){ + struct dbr_ctrl_double *retValue = 0; + retValue = (struct dbr_ctrl_double *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (double)retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + double* insertBuf = new double[args.count]; + insertBuf[0] = (double)retValue->value; + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_ctrl_double); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(double *)&(buffer[j]); + j += sizeof (double); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + else{ + struct dbr_time_double *retValue = 0; + retValue = (struct dbr_time_double *)args.dbr; + if (args.count == 1) { + resData.insert (tag, (double)retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + double* insertBuf = new double[args.count]; + insertBuf[0] = (double)retValue->value; + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_double); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(double *)&(buffer[j]); + j += sizeof (double); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + break; + default: + printf("Fatal Error: Unsupported data type\n"); + break; + } +} + +void +caRequestObject::defaultGetCallback (struct event_handler_args args) +{ +#ifdef _CDEV_DEBUG + printf("get callback called\n"); +#endif + cdevTranObj *xobj = (cdevTranObj *)args.usr; + + if (xobj->isTrash ()) { + // this transaction object is deleted already + delete xobj; + return; + } + + //========================================================= + // One must know the requestObject from transaction + // is caRequestObject. So no vialation here + //========================================================= + caRequestObject *reqObj = (caRequestObject *)xobj->reqObj_; + //========================================================= + // Check data type + //========================================================= + cdevData *resData = xobj->resultData_; + cdevCallback *cbkobj = xobj->userCallback_; + cdevData result; + + if (resData) // send no block + resData->remove(); + else // send callback + resData = &result; + + if (args.count > 0 && args.dbr != 0) { + // convert data from channel access type to cdevData type + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqObj->reqMask_, + reqObj->reqType_, + args, *resData); + + // T. Straumann: added check if user supplied a callbackFunction. + if (cbkobj && cbkobj->callbackFunction() ) { // from sendCallback + (*cbkobj->callbackFunction ()) (CDEV_SUCCESS, cbkobj->userarg (), + *reqObj, result); + } + } + else { + // T. Straumann: added check if user supplied a callbackFunction. + if (cbkobj && cbkobj->callbackFunction() ) { // called from sendCallback + (*cbkobj->callbackFunction ()) (CDEV_IOFAILED, cbkobj->userarg (), + *reqObj, result); + } + } + delete xobj; +} + +void +caRequestObject::defaultSetCallback (struct event_handler_args args) +{ + // for now just remove transaction object +#ifdef _CDEV_DEBUG + printf("default set callback called\n"); +#endif + int status = CDEV_SUCCESS; + + cdevTranObj *xobj = (cdevTranObj *)args.usr; + + if (xobj->isTrash ()) { + // this transaction object is deleted already + delete xobj; + return; + } + + //========================================================= + // One must know the requestObject from transaction + // is caRequestObject. So no vialation here + //========================================================= + caRequestObject *reqObj = (caRequestObject *)xobj->reqObj_; + cdevData result; + + cdevCallback *cbkobj = xobj->userCallback_; + // T. Straumann: added check if user supplied a callbackFunction. + if (cbkobj && cbkobj->callbackFunction() ) { // from sendCallback + if (args.status != ECA_NORMAL) + status = CDEV_IOFAILED; + (*cbkobj->callbackFunction())(status, cbkobj->userarg(), + *reqObj, result); + } + delete xobj; +} + +void +caRequestObject::callPropMonitorCallback (struct event_handler_args args) +{ + caMonObj *xobj = (caMonObj *)args.usr; + caChannel* ch = xobj->channel_; + + // get tag value associated with this channel + int tagval = xobj->tag_; + // get callback status value assocaited with this channel + int cbkst = xobj->cbkStatus_; + + int status = CDEV_ERROR; + + if (args.count > 0 && args.dbr != 0) { + // clean out old information + xobj->cache_.remove (); + switch (ch->type_){ + case DBR_STRING: + { + char *retValue; + retValue = (char *)args.dbr; + xobj->cache_.insert (tagval, (char *)(retValue)); + } + break; + case DBR_ENUM: + { + // get index value + unsigned short index = *(unsigned short *)args.dbr; + if (ch->accessBuffer_) + status = xobj->cache_.insert (tagval, + ch->accessBuffer_->cenmval.strs[index]); + else + status = xobj->cache_.insert (tagval, index); + } + break; + case DBR_SHORT: + { + short tmp = *(short *)(args.dbr); + status = xobj->cache_.insert (tagval, (int)tmp); + } + break; + case DBR_CHAR: + { + BYTE tmp = *(BYTE *)(args.dbr); + status = xobj->cache_.insert (tagval, (BYTE)tmp); + } + break; + case DBR_LONG: + { + int tmp = *(int *)(args.dbr); + status = xobj->cache_.insert (tagval, tmp); + } + break; + case DBR_FLOAT: + { + float tmp = *(float *)(args.dbr); + status = xobj->cache_.insert (tagval, tmp); + } + break; + case DBR_DOUBLE: + { + double tmp = *(double *)(args.dbr); + status = xobj->cache_.insert (tagval, tmp); + } + break; + default: + cdevSystem::defaultSystem().reportError + (CDEV_SEVERITY_ERROR, + "caRequestObject", NULL, + "Unsupported data type %d\n", + ch->type_); + break; + } + } + + if (status == CDEV_SUCCESS) { + updatePropCache ((caRequestObject *)xobj->reqObj_, + tagval, + xobj->cache_); + xobj->callCallbacks (cbkst, xobj->reqObj_, xobj->cache_); + } + else + xobj->callCallbacks (CDEV_ERROR, xobj->reqObj_, xobj->cache_); +} + +void +caRequestObject::callMonitorCallback (struct event_handler_args args) +{ + static caRequestObject *reqObj = 0; + caMonObj *xobj = (caMonObj *)args.usr; + + // get request object + reqObj = (caRequestObject *)xobj->reqObj_; + // get channel object + caChannel* ch = xobj->channel_; + + // get tag value associated with this channel + int tagval = xobj->tag_; + // get callback status value assocaited with this channel + int cbkst = xobj->cbkStatus_; + + if (xobj->tobj_ != 0) { + // remove transaction object so that pend will give back right result + if (xobj->tobj_->isTrash ()) { + // if this transaction object is trash, return + delete xobj->tobj_; + xobj->tobj_ = 0; + return; + } + else { + delete xobj->tobj_; + xobj->tobj_ = 0; + } + // create monitor object from trasanction object + reqObj->channel_->addMonitorObj (xobj); + } + + if (args.count > 0 && args.dbr != 0) { + // get type and mask + int reqType = xobj->reqType_; + int reqMask = xobj->reqMask_; + switch (reqObj->channel_->type_){ + case DBR_STRING: + // since monitor value always use DBR_TIME strcuture + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + break; + case DBR_ENUM: + { + // since monitor value always use DBR_TIME strcuture which + // has no no_str and str information, the corresponding + // channel information about no_str and strs are used here + xobj->cache_.remove (); + struct dbr_time_enum *retValue = 0; + retValue = (struct dbr_time_enum *)args.dbr; + unsigned short index = retValue->value; + + if (ch->accessBuffer_ && ch->accessBuffer_->cenmval.no_str && + index < ch->accessBuffer_->cenmval.no_str && + strlen (ch->accessBuffer_->cenmval.strs[index])) + xobj->cache_.insert (caService::CA_TAG_VALUE, + ch->accessBuffer_->cenmval.strs[index]); + else + xobj->cache_.insert (caService::CA_TAG_VALUE, index); + caRequestObject::fillResult (reqMask, reqType, *retValue, xobj->cache_); + + // call user callbacks + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + case DBR_SHORT: + if (!xobj->cacheInited_) { + // setup internal buffer pointer + caMonObj::setupMonitorBuffer (tagval, xobj->cache_, xobj->data_, + CDEV_INT32); + xobj->cacheInited_ = 1; + } + + if (args.count == 1){ + struct dbr_time_short *retValue = 0; + retValue = (struct dbr_time_short *)args.dbr; + caRequestObject::updateResult (reqMask, reqType, + *retValue, xobj->data_, + reqObj->propCache() ); + + if (reqObj->longMask_ != 0) { + if (reqObj->bitValuesChanged (*(int *)(xobj->data_.value), + reqObj->longMask_)) + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else { + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + case DBR_CHAR: + if (!xobj->cacheInited_) { + // setup internal buffer pointer + caMonObj::setupMonitorBuffer (tagval, xobj->cache_, xobj->data_, + CDEV_BYTE); + xobj->cacheInited_ = 1; + } + + if (args.count == 1){ + struct dbr_time_char *retValue = 0; + retValue = (struct dbr_time_char *)args.dbr; + caRequestObject::updateResult (reqMask, reqType, + *retValue, xobj->data_, + reqObj->propCache() ); + + if (reqObj->longMask_ != 0) { + BYTE vtmp = *(BYTE *)(xobj->data_.value); + if (reqObj->bitValuesChanged ((int)vtmp, + reqObj->longMask_)) + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else { + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + case DBR_LONG: + if (!xobj->cacheInited_) { + // setup internal buffer pointer + caMonObj::setupMonitorBuffer (tagval, xobj->cache_, xobj->data_, + CDEV_INT32); + xobj->cacheInited_ = 1; + } + + if (args.count == 1) { + struct dbr_time_long *retValue = 0; + retValue = (struct dbr_time_long *)args.dbr; + caRequestObject::updateResult (reqMask, reqType, + *retValue, xobj->data_, + reqObj->propCache() ); + + if (reqObj->longMask_ != 0) { + if (reqObj->bitValuesChanged (*(int *)(xobj->data_.value), + reqObj->longMask_)) + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else { + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + case DBR_FLOAT: + if (!xobj->cacheInited_) { + // setup internal buffer pointer + caMonObj::setupMonitorBuffer (tagval, xobj->cache_, xobj->data_, + CDEV_FLOAT); + xobj->cacheInited_ = 1; + } + + if (args.count == 1) { + struct dbr_time_float *retValue = 0; + retValue = (struct dbr_time_float *)args.dbr; + caRequestObject::updateResult (reqMask, reqType, *retValue, + xobj->data_, + reqObj->propCache() ); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else { + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + case DBR_DOUBLE: + if (!xobj->cacheInited_) { + // setup internal buffer pointer + caMonObj::setupMonitorBuffer (tagval, xobj->cache_, xobj->data_, + CDEV_DOUBLE); + xobj->cacheInited_ = 1; + } + + if (args.count == 1) { + struct dbr_time_double *retValue = 0; + retValue = (struct dbr_time_double *)args.dbr; + caRequestObject::updateResult (reqMask, reqType, + *retValue, xobj->data_, + reqObj->propCache() ); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else { + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + default: + printf("Fatal Error: Unsupported data type\n"); + break; + } + } + else + xobj->callCallbacks (CDEV_IOFAILED, reqObj, xobj->cache_); +} + +int +caRequestObject::findSvcData (char *device, + char *msg, + cdevSystem& system, + char *svcData, + int dataLen) +{ + char message[256], fullname[128]; + + if (system.prefix()) + ::sprintf (fullname, "%s%s",system.prefix(),device); + else + ::strcpy (fullname, device); + + ::sprintf (message,"resolveServiceData %s %s", fullname, msg); + + cdevData result; + int status = (system.nameServer()).send (message, 0, result); + if (status == CDEV_SUCCESS){ + result.get (caService::CA_TAG_PV, svcData, dataLen); + int rd; + int dataStatus = result.get (caService::CA_TAG_RO, &rd); + if (dataStatus == CDEV_SUCCESS){ // channel is readonly + readonly_ = 1; + } +#ifdef _CDEV_DEBUG + printf("Service data is %s\n",svcData); +#endif + return status; + } + else + return CDEV_ERROR; +} + +int +caRequestObject::findAction (char *msg, int& action) +{ + char token0[64], token1[64], token2[64]; + int status; + +#ifdef __GNUC__ + // some version of gcc demand a memory location for msg + char buffer[256]; + strncpy (buffer, msg, sizeof (buffer)); + status = ::sscanf (buffer, "%s %s",token0, token1); +#else + status = ::sscanf (msg, "%s %s", token0, token1); +#endif + + if (::strcmp (token0, "get") == 0) + action = caRequestObject::GET; + else if (::strcmp (token0, "set") == 0) + action = caRequestObject::SET; + else if (::strcmp (token0, "monitorOn") == 0) + action = caRequestObject::MONITOR_ON; + else if (::strcmp (token0, "monitorOff") == 0) + action = caRequestObject::MONITOR_OFF; + else if (::strcmp (token0, "put") == 0) + action = caRequestObject::PUT; + else + action = caRequestObject::UNKNOWN; + + return CDEV_SUCCESS; +} + +int +caRequestObject::newTriggerSource (void) +{ + cdevData& cxt = getContext (); + int val = 0; + if (cxt.get (caService::CA_TAG_VALUE, &val) == CDEV_SUCCESS) { + if (val == 0) { + caPchannel* pch = channel_->pchannels_; + for (int i = 2; i < MAX_NUM_PCHANNELS; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS){ + // caller specify a trigger or I am going to setup channel + // for those properties which are not changed rapidly + if (val >= 2) + return 1; + } + } + } + } + return 0; +} + +void +caRequestObject::setPropCache (void) +{ + if (cache_ == 0) { + prop_ = new cdevData (); + cache_ = new caMonData (); + int status = caMonObj::setupMonitorBuffer (caService::CA_TAG_VALUE, + *prop_, *cache_, CDEV_FLOAT); + if (status != CDEV_SUCCESS) { + delete cache_; + delete prop_; + cache_ = 0; + prop_ = 0; + } + } +} + +caMonData* +caRequestObject::propCache (void) const +{ + return cache_; +} + +void +caRequestObject::updatePropCache (caRequestObject* obj, + int tag, + cdevData& data) +{ + caMonData* cache = obj->propCache (); + + if (cache != 0) { + if (tag == caService::CA_TAG_STATUS) + data.get (tag, cache->status); + else if (tag == caService::CA_TAG_SEVERITY) + data.get (tag, cache->severity); + else if (tag == caService::CA_TAG_PRECISION) + data.get (tag, cache->precision); + else if (tag == caService::CA_TAG_DISPHI) + data.get (tag, cache->disphi); + else if (tag == caService::CA_TAG_DISPLO) + data.get (tag, cache->displo); + else if (tag == caService::CA_TAG_ALRMHI) + data.get (tag, cache->alrmhi); + else if (tag == caService::CA_TAG_ALRMLO) + data.get (tag, cache->alrmlo); + else if (tag == caService::CA_TAG_WRNHI) + data.get (tag, cache->warnhi); + else if (tag == caService::CA_TAG_WRNLO) + data.get (tag, cache->warnlo); + else if (tag == caService::CA_TAG_CTRLHI) + data.get (tag, cache->ctrlhi); + else if (tag == caService::CA_TAG_CTRLLO) + data.get (tag, cache->ctrllo); + else + cdevSystem::defaultSystem().reportError + (CDEV_SEVERITY_ERROR, "caRequestObject", obj, + "Warning: property cache buffers does not have this tag %d\n", + tag); + } +} diff --git a/src/ca/caRequestObject.cc.orig b/src/ca/caRequestObject.cc.orig new file mode 100755 index 0000000..d412be9 --- /dev/null +++ b/src/ca/caRequestObject.cc.orig @@ -0,0 +1,2904 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Channel Access RequestObject Class +// +// Author: Jie Chen +// +// Revision History: +// caRequestObject.cc,v +// Revision 1.34 1998/04/10 13:55:41 chen +// add access information to caService +// +// Revision 1.33 1998/04/08 20:19:05 chen +// fix set problem +// +// Revision 1.32 1998/03/30 19:39:53 chen +// bug fix for channel_ null pointer inside destructor +// +// Revision 1.31 1998/03/23 21:17:18 chen +// Fix a bug related to prop channels: found on solaris +// +// Revision 1.30 1998/03/09 15:45:40 chen +// Install ENUM no_str into displayHigh for ENUM type +// +// Revision 1.29 1998/03/05 18:49:13 chen +// fix a bug on context == 2 on property channels +// +// Revision 1.28 1998/03/03 20:50:21 chen +// Return array of strings if one asks about display information on DBR_ENUM channel +// +// Revision 1.27 1998/02/18 19:48:26 chen +// fix ca set access error +// +// Revision 1.26 1997/08/08 16:41:36 chen +// add char type and fix dbr == null +// +// Revision 1.25 1997/07/18 14:24:44 chen +// remove one printf +// +// Revision 1.24 1997/03/03 17:36:28 chen +// add buffering to channel access connection +// +// Revision 1.23 1996/09/18 14:46:50 chen +// Channel holds multiple monitor objects +// +// Revision 1.22 1996/07/23 15:59:14 chen +// send with monitorOff will remove all monitored callbacks +// +// Revision 1.21 1996/05/02 14:18:26 chen +// Fix monitorOn and unfinished transaction bug +// +// Revision 1.20 1996/01/05 18:40:05 chen +// Fix a bug for gcc and a bug for monitoring enum values +// +// Revision 1.19 1995/12/08 15:42:28 chen +// fix double/float set value and add deferred execution mode +// +// Revision 1.18 1995/11/07 14:26:57 akers +// Added CTRLLO and CTRLHI to populateMonitor +// +// Revision 1.17 1995/10/30 13:33:05 akers +// Added cdev specific version of strncpy +// +// Revision 1.16 1995/10/26 14:33:14 akers +// Removal of Warnings +// +// Revision 1.15 1995/10/17 20:20:51 chen +// redefine getState +// +// Revision 1.14 1995/10/13 14:42:37 chen +// add debug flag in the monitorProperty +// +// Revision 1.13 1995/10/03 19:56:25 chen +// add monitoring properties +// +// Revision 1.12 1995/09/19 16:06:36 chen +// minor change on bit monitoring +// +// Revision 1.11 1995/09/18 18:22:49 chen +// add monitoring bit pattern capability for long/short integer +// +// Revision 1.10 1995/09/15 19:27:28 chen +// Fix a bug of array of doubles +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#include +#include +#include +#include +#include "caRequestObject.h" +#include "caNameSvc.h" +#include "caService.h" +#include "caChannel.h" +#include "caMisc.h" + +#ifndef TS_EPOCH_SEC_PAST_1970 +/* 1/1/90 20 yr (5 leap) of seconds */ +#define TS_EPOCH_SEC_PAST_1970 7305*86400 +#endif + +int caRequestObject::numAttributes = 14; + +caAttr caRequestObject::caAttributes[]= +{ + {"value", 0x00000001}, + {"status", 0x00000002}, + {"severity", 0x00000004}, + {"time", 0x00000008}, + {"precision", 0x00000010}, + {"units", 0x00000020}, + {"displayHigh", 0x00000040}, + {"displayLow", 0x00000080}, + {"alarmHigh", 0x00000100}, + {"alarmLow", 0x00000200}, + {"warningHigh", 0x00000400}, + {"warningLow", 0x00000800}, + {"controlHigh", 0x00001000}, + {"controlLow", 0x00002000}, +}; + +//========================================================================= +// Implementation of caRequestObject +//========================================================================= +caRequestObject::caRequestObject (char *device, char *msg, + caService *, + cdevSystem& system) +:cdevRequestObject (device, msg, system), cache_ (0), prop_ (0), readonly_ (0), + reqType_ (caRequestObject::VALUE), reqMask_ (0x1), channel_ (0) +{ +#ifdef _TRACE_OBJECTS + printf (" Create caRequestObject class \n"); +#endif + caRequestObject::findAction (msg, action_); +} + +caRequestObject::~caRequestObject (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete caRequestObject class \n"); +#endif + caService *svc = (caService *)service_; + if (channel_ && --channel_->count_ <= 0){// no more reference to the channel + svc->removeChannel (channel_->channelName_, channel_); + delete channel_; + } + // reset the pointer of cached properties to zero + if (cache_) { + delete cache_; + cache_ = 0; + } + if (prop_) { + delete prop_; + prop_ = 0; + } +} + +void +caRequestObject::attachChannel (void) +{ + int status; + caService* svc = (caService *)service_; + caPchannel* pchs = 0; + + // caller may need to monitor properties, setup properties cache buffer + // order of calls is important: We have to create property channel before + // we create main channel + if (reqType_ != caRequestObject::VALUE + && action_ == caRequestObject::MONITOR_ON) { + setPropCache (); + pchs = caChannel::createPchannels (); + // create all pchannels + initPropChannels (pchs); + + // flush out the property channel connection requests + svc->flush (); + } + + // get service data first + char svcData[64]; + status = findSvcData (deviceName_, message_, system_, + svcData, sizeof (svcData)); + + status = svc->channelPtr (svcData, channel_); + + if (status != 0){ // the channel has not created yet +#ifdef _CDEV_DEBUG + printf("channel %s not created \n", svcData); +#endif + channel_ = new caChannel (svcData, svc); + svc->addChannel (svcData, channel_); + channel_->count_ = 1; + } + else{ +#ifdef _CDEV_DEBUG + printf("channel %s is created \n", svcData); +#endif + channel_->count_ += 1; +#ifdef _CA_SYNC_CONN + if (!channel_->connected_){ // channel not connected + channel_->connect (); + } +#endif + } + + // assign pchannels to this channel + if (pchs) + channel_->propertyChannels (pchs); +} + +int +caRequestObject::getState (void) +{ + if (channel_->connected_) + return CDEV_STATE_CONNECTED; + else + return CDEV_STATE_NOTCONNECTED; +} + +int +caRequestObject::getAccess (void) +{ + return channel_->readonly_; +} + +int +caRequestObject::setContext (cdevData &cxt) +{ + int temp; + + // clean the mask + reqMask_ = 0x0; + reqType_ = caRequestObject::VALUE; + // get bitmask from cdev requestobject layer + (void)cdevRequestObject::setContext (cxt); + + for (int i = 0; i < caRequestObject::numAttributes; i++){ + if (cxt.get ((caRequestObject::caAttributes[i]).attrName, &temp) == CDEV_SUCCESS){ + reqMask_ |= (caRequestObject::caAttributes[i]).attrValue; + } + } + + if (reqMask_ == 0x0) + reqType_ = caRequestObject::VALUE; + else if (reqMask_ >= caRequestObject::VALUE && + reqMask_ < caRequestObject::STATUS) + reqType_ = caRequestObject::VALUE; + else if (reqMask_ >= caRequestObject::STATUS && + reqMask_ < caRequestObject::TIMESTMP) + reqType_ = caRequestObject::STATUS; + else if (reqMask_ >= caRequestObject::TIMESTMP && + reqMask_ < caRequestObject::GRINFO) + reqType_ = caRequestObject::TIMESTMP; + else if (reqMask_ >= caRequestObject::GRINFO && + reqMask_ < caRequestObject::CTRLINFO) + reqType_ = caRequestObject::GRINFO; + else + reqType_ = caRequestObject::CTRLINFO; +#ifdef _CDEV_DEBUG + printf("reqType_ is %d mask is 0x%x \n", reqType_, reqMask_); +#endif + return CDEV_SUCCESS; +} + +int +caRequestObject::getValueCbk (caChannel* channel, cdevTranObj *obj) +{ + int status; + chtype reqType; + + if (reqType_ != caRequestObject::TIMESTMP && channel->type_ != DBR_STRING) + reqType = dbf_type_to_DBR_CTRL (channel->type_); + else + reqType = dbf_type_to_DBR_TIME (channel->type_); + + status = ::ca_array_get_callback (reqType, channel->numElements_, + channel->cId_, + &(caRequestObject::defaultGetCallback), + (void *)obj); + if (status == ECA_NORMAL) + return CDEV_SUCCESS; + else { + // no callback will be called, remove transaction object + // otherwise group will block + cdevCallback *cbkobj = obj->userCallback_; + cdevRequestObject *reqobj = obj->reqObj_; + cdevData result; + + if (cbkobj) + (*cbkobj->callbackFunction())(CDEV_IOFAILED, cbkobj->userarg(), + *reqobj, result); + delete obj; + return CDEV_IOFAILED; + } +} + +int +caRequestObject::send (cdevData& out, cdevData& result) +{ + return send (&out, &result); +} + +int +caRequestObject::send (cdevData* out, cdevData& result) +{ + return send (out, &result); +} + +int +caRequestObject::send (cdevData& out, cdevData* result) +{ + return send (&out, result); +} + +int +caRequestObject::send (cdevData* out, cdevData* result) +{ + int status = CDEV_ERROR; + + // check channel has been created or not + if (!channel_) + attachChannel (); + +#ifndef _CA_SYNC_CONN + int st = channel_->asyncConnect (); + if (st != CDEV_SUCCESS) + return st; +#endif + if (channel_->connected_){ + switch (action_){ + case caRequestObject::GET: + if (result == 0) + return CDEV_INVALIDARG; + { + cdevGroup getGrp (2, system_); + getGrp.start(); + sendNoBlock (out, result); + getGrp.end (); + // wait for maximum DEFAULT_TIMEOUT + getGrp.pend ((double)DEFAULT_TIMEOUT); + if (getGrp.allFinished ()) + status = CDEV_SUCCESS; + else + status = CDEV_TIMEOUT; + } + break; + case caRequestObject::SET: + if (out == 0) + return CDEV_INVALIDARG; + if (readonly_) + return CDEV_INVALIDARG; + // synchronous set need group + { + cdevGroup setGrp (2, system_); + setGrp.start(); + sendNoBlock (out, result); + setGrp.end (); + // wait for maximum DEFAULT_TIMEOUT + setGrp.pend ((double)DEFAULT_TIMEOUT); + if (setGrp.allFinished ()) { + if (out->get (caService::CA_TAG_RESULT_CODE, &status)!= CDEV_SUCCESS) + status = CDEV_SUCCESS; + else + out->remove (caService::CA_TAG_RESULT_CODE); + } + else + status = CDEV_TIMEOUT; + } + break; + case caRequestObject::MONITOR_ON: + status = CDEV_INVALIDARG; + break; + case caRequestObject::MONITOR_OFF: + { + // remove every monitor callbacks + // remove a monitor object from all the channels + cdevCallback userCallback (0, 0); + channel_->removeCallback (&userCallback); + if (channel_->pinited_) { + caPchannel* pch = channel_->pchannels_; + + for (int i = 0; i < MAX_NUM_PCHANNELS; i++) { + if (pch[i].channel != 0) + pch[i].channel->removeCallback (&userCallback); + } + } + } + status = CDEV_SUCCESS; + break; + default: +#ifdef _CDEV_DEBUG + printf("Unsupported action message %s\n", action_); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject does not support message %d\n", + deviceName_, message_, action_); + status = CDEV_INVALIDARG; + break; + } + } + else{ +#ifdef _CDEV_DEBUG + printf("channel disconnected\n"); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject is not connected\n", + deviceName_, message_); + status = CDEV_NOTCONNECTED; + } + return status; +} + +void +caRequestObject::updateResult (int reqMask, int type, + struct dbr_time_short& value, + caMonData &result, + caMonData* cache) +{ + int *val = (int *)(result.value); + *val = value.value; + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + *(result.status) = (int)(value.status); + if (reqMask & (0x1 << i++)) + *(result.severity) = (int)(value.severity); + + cdev_TS_STAMP* tval = result.tstamp; + tval->secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval->nsec = value.stamp.nsec; + + // timeStmp skipped epics fault + unit tag + precision tag + i += 3; + + if (reqMask & (0x1 << i++)) + *(result.disphi) = *(cache->disphi); + if (reqMask & (0x1 << i++)) + *(result.displo) = *(cache->displo); + if (reqMask & (0x1 << i++)) + *(result.alrmhi) = *(cache->alrmhi); + if (reqMask & (0x1 << i++)) + *(result.alrmlo) = *(cache->alrmlo); + if (reqMask & (0x1 << i++)) + *(result.warnhi) = *(cache->warnhi); + if (reqMask & (0x1 << i++)) + *(result.warnlo) = *(cache->warnlo); + if (reqMask & (0x1 << i++)) + *(result.ctrlhi) = *(cache->ctrlhi); + if (reqMask & (0x1 << i++)) + *(result.ctrllo) = *(cache->ctrllo); + } +} + + +void +caRequestObject::updateResult (int reqMask, int type, + struct dbr_time_char& value, + caMonData &result, + caMonData* cache) +{ + BYTE *val = (BYTE *)(result.value); + *val = (BYTE)value.value; + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + *(result.status) = (int)(value.status); + if (reqMask & (0x1 << i++)) + *(result.severity) = (int)(value.severity); + + cdev_TS_STAMP* tval = result.tstamp; + tval->secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval->nsec = value.stamp.nsec; + + // timeStmp skipped epics fault + unit tag + precision + i += 3; + + if (reqMask & (0x1 << i++)) + *(result.disphi) = *(cache->disphi); + if (reqMask & (0x1 << i++)) + *(result.displo) = *(cache->displo); + if (reqMask & (0x1 << i++)) + *(result.alrmhi) = *(cache->alrmhi); + if (reqMask & (0x1 << i++)) + *(result.alrmlo) = *(cache->alrmlo); + if (reqMask & (0x1 << i++)) + *(result.warnhi) = *(cache->warnhi); + if (reqMask & (0x1 << i++)) + *(result.warnlo) = *(cache->warnlo); + if (reqMask & (0x1 << i++)) + *(result.ctrlhi) = *(cache->ctrlhi); + if (reqMask & (0x1 << i++)) + *(result.ctrllo) = *(cache->ctrllo); + } +} + +void +caRequestObject::updateResult (int reqMask, int type, + struct dbr_time_long& value, + caMonData &result, + caMonData* cache) +{ + int *val = (int *)(result.value); + *val = value.value; + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + *(result.status) = (int)(value.status); + if (reqMask & (0x1 << i++)) + *(result.severity) = (int)(value.severity); + + cdev_TS_STAMP* tval = result.tstamp; + tval->secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval->nsec = value.stamp.nsec; + + // timeStmp skipped epics fault + unit tag + precision + i += 3; + + if (reqMask & (0x1 << i++)) + *(result.disphi) = *(cache->disphi); + if (reqMask & (0x1 << i++)) + *(result.displo) = *(cache->displo); + if (reqMask & (0x1 << i++)) + *(result.alrmhi) = *(cache->alrmhi); + if (reqMask & (0x1 << i++)) + *(result.alrmlo) = *(cache->alrmlo); + if (reqMask & (0x1 << i++)) + *(result.warnhi) = *(cache->warnhi); + if (reqMask & (0x1 << i++)) + *(result.warnlo) = *(cache->warnlo); + if (reqMask & (0x1 << i++)) + *(result.ctrlhi) = *(cache->ctrlhi); + if (reqMask & (0x1 << i++)) + *(result.ctrllo) = *(cache->ctrllo); + } +} + +void +caRequestObject::updateResult (int reqMask, int type, + struct dbr_time_float& value, + caMonData &result, + caMonData* cache) +{ + float *val = (float *)(result.value); + *val = value.value; + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + *(result.status) = (int)(value.status); + if (reqMask & (0x1 << i++)) + *(result.severity) = (int)(value.severity); + + cdev_TS_STAMP* tval = result.tstamp; + tval->secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval->nsec = value.stamp.nsec; + + // timeStmp skipped epics fault + unit tag + i += 2; + + if (reqMask & (0x1 << i++)) + *(result.precision) = *(cache->precision); + if (reqMask & (0x1 << i++)) + *(result.disphi) = *(cache->disphi); + if (reqMask & (0x1 << i++)) + *(result.displo) = *(cache->displo); + if (reqMask & (0x1 << i++)) + *(result.alrmhi) = *(cache->alrmhi); + if (reqMask & (0x1 << i++)) + *(result.alrmlo) = *(cache->alrmlo); + if (reqMask & (0x1 << i++)) + *(result.warnhi) = *(cache->warnhi); + if (reqMask & (0x1 << i++)) + *(result.warnlo) = *(cache->warnlo); + if (reqMask & (0x1 << i++)) + *(result.ctrlhi) = *(cache->ctrlhi); + if (reqMask & (0x1 << i++)) + *(result.ctrllo) = *(cache->ctrllo); + } +} + +void +caRequestObject::updateResult (int reqMask, int type, + struct dbr_time_double& value, + caMonData &result, + caMonData* cache) +{ + double *val = (double *)(result.value); + *val = value.value; + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + *(result.status) = (int)(value.status); + if (reqMask & (0x1 << i++)) + *(result.severity) = (int)(value.severity); + + cdev_TS_STAMP* tval = result.tstamp; + tval->secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval->nsec = value.stamp.nsec; + + // timeStmp skipped epics fault + unit tag + i += 2; + + if (reqMask & (0x1 << i++)) + *(result.precision) = *(cache->precision); + if (reqMask & (0x1 << i++)) + *(result.disphi) = *(cache->disphi); + if (reqMask & (0x1 << i++)) + *(result.displo) = *(cache->displo); + if (reqMask & (0x1 << i++)) + *(result.alrmhi) = *(cache->alrmhi); + if (reqMask & (0x1 << i++)) + *(result.alrmlo) = *(cache->alrmlo); + if (reqMask & (0x1 << i++)) + *(result.warnhi) = *(cache->warnhi); + if (reqMask & (0x1 << i++)) + *(result.warnlo) = *(cache->warnlo); + if (reqMask & (0x1 << i++)) + *(result.ctrlhi) = *(cache->ctrlhi); + if (reqMask & (0x1 << i++)) + *(result.ctrllo) = *(cache->ctrllo); + } +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_string& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_short& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_char& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (short)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (short)value.severity); + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_long& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_float& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_STATUS, (int)value.status); + } + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_double& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_STATUS, (int)value.status); + } + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_enum& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_STATUS, (int)value.status); + } + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_short& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + // timeStmp skipped epics fault :- + i++; + i++; // no precision information + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_UNITS, value.units); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (int)value.upper_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (int)value.lower_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMHI, (int)value.upper_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMLO, (int)value.lower_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNHI, (int)value.upper_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNLO, (int)value.lower_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLHI, (int)value.upper_ctrl_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLLO, (int)value.lower_ctrl_limit); + } +} + + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_char& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (short)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (short)value.severity); + // timeStmp skipped epics fault :- + i++; + i++; // no precision information + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_UNITS, value.units); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (BYTE)value.upper_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (BYTE)value.lower_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMHI, (BYTE)value.upper_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMLO, (BYTE)value.lower_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNHI, (BYTE)value.upper_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNLO, (BYTE)value.lower_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLHI, (BYTE)value.upper_ctrl_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLLO, (BYTE)value.lower_ctrl_limit); + } +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_long& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + // timeStmp skipped epics fault :- + i++; + i++; // no precision information + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_UNITS, value.units); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (int)value.upper_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (int)value.lower_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMHI, (int)value.upper_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMLO, (int)value.lower_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNHI, (int)value.upper_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNLO, (int)value.lower_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLHI, (int)value.upper_ctrl_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLLO, (int)value.lower_ctrl_limit); + } +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_float& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + // timeStamp skipped epics fault :- + i++; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_PRECISION, value.precision); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_UNITS, value.units); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (float)value.upper_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (float)value.lower_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMHI, (float)value.upper_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMLO, (float)value.lower_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNHI,(float)value.upper_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNLO,(float)value.lower_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLHI, (float)value.upper_ctrl_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLLO, (float)value.lower_ctrl_limit); + } +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_double& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + // timeStmp skipped epics fault :- + i++; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_PRECISION, value.precision); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_UNITS, value.units); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (double)value.upper_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (double)value.lower_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMHI, (double)value.upper_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMLO, (double)value.lower_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNHI,(double)value.upper_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNLO,(double)value.lower_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLHI, (double)value.upper_ctrl_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLLO, (double)value.lower_ctrl_limit); + } +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_enum& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + // timeStmp skipped epics fault :- + i++; + // no precision information + i++; + // no units information + i++; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (int)value.no_str - 1); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (int)0); + } +} + +int +caRequestObject::sendNoBlock (cdevData& out, cdevData& result) +{ + return sendNoBlock (&out, &result); +} + +int +caRequestObject::sendNoBlock (cdevData& out, cdevData *result) +{ + return sendNoBlock (&out, result); +} + +int +caRequestObject::sendNoBlock (cdevData* out, cdevData& result) +{ + return sendNoBlock (out, &result); +} + +int +caRequestObject::sendNoBlock (cdevData* out, cdevData* result) +{ + if (!channel_) + attachChannel (); + + // first check whether this is deferred mode + if (deferExecution (out, result)) + return CDEV_SUCCESS; + + int status = CDEV_ERROR; + cdevTranObj *xobj = 0; + + switch (action_){ + case caRequestObject::GET: + if (result == 0) + return CDEV_INVALIDARG; + xobj = new cdevTranObj (&system_, this, result, 0); + // if channel is not connected, put all executions in the buffer + if (!channel_->connected_) { + bufferExecution (0, result, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = getValueCbk (channel_, xobj); + break; + case caRequestObject::SET: + if (out == 0) + return CDEV_INVALIDARG; + if (readonly_) + return CDEV_INVALIDARG; + + // if channel is not connected, put all executions in the buffer + // must clone the data as the caller may delete it + if (!channel_->connected_) { + cdevData *cloned = new cdevData(*out); + xobj = new cdevTranObj (&system_, this, cloned, 0); + bufferExecution (cloned, result, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } else { + xobj = new cdevTranObj (&system_, this, out, 0); + } + status = setValueCbk (channel_, xobj); + break; + case caRequestObject::MONITOR_ON: + status = CDEV_INVALIDARG; + break; + case caRequestObject::MONITOR_OFF: + { + // remove every monitor callbacks + // remove a monitor object from all the channels + cdevCallback userCallback (0, 0); + channel_->removeCallback (&userCallback); + if (channel_->pinited_) { + caPchannel* pch = channel_->pchannels_; + + for (int i = 0; i < MAX_NUM_PCHANNELS; i++) { + if (pch[i].channel != 0) + pch[i].channel->removeCallback (&userCallback); + } + } + } + status = CDEV_SUCCESS; + break; + default: +#ifdef _CDEV_DEBUG + printf("Unsupported action message %s\n", action_); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject does not support message %d\n", + deviceName_, message_, action_); + status = CDEV_INVALIDARG; + break; + } + return status; +} + + +int +caRequestObject::execNoBlock (cdevData* out, cdevData* result, void* arg) +{ + // arg is a cdevTranObj + cdevTranObj* xobj = (cdevTranObj *)arg; + + // first check whether this is deferred mode + if (deferExecution (out, result)) { + delete xobj; + return CDEV_SUCCESS; + } + + int status = CDEV_ERROR; + + switch (action_){ + case caRequestObject::GET: + // if channel is not connected, put all executions in the buffer + if (!channel_->connected_) { + bufferExecution (0, result, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = getValueCbk (channel_, xobj); + break; + case caRequestObject::SET: + // if channel is not connected, put all executions in the buffer + if (!channel_->connected_) { + cdevData *cloned = new cdevData(*out); + bufferExecution (cloned, result, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = setValueCbk (channel_, xobj); + break; + default: +#ifdef _CDEV_DEBUG + printf("Unsupported action message %s\n", action_); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject does not support message %d\n", + deviceName_, message_, action_); + status = CDEV_INVALIDARG; + break; + } + return status; +} + + +int +caRequestObject::setValueCbk (caChannel* channel, cdevTranObj *xobj) +{ + int caStatus = -1; + int dataStatus = CDEV_SUCCESS; + int ioStatus = CDEV_SUCCESS; + + cdevData *out = xobj->resultData_; + cdevData result; + cdevCallback *cbkobj = xobj->userCallback_; + cdevRequestObject *reqObj = xobj->reqObj_; + + if (dataMatch (*out, (int)channel->type_, + (int)(channel_->numElements_)) != CDEV_SUCCESS){ + // I have to delete this transaction object + if (cbkobj) { // has callback + (*cbkobj->callbackFunction())(CDEV_ERROR, cbkobj->userarg(), + *reqObj, result); + } + delete xobj; + return CDEV_INVALIDARG; + } + + switch (channel->type_){ + case DBR_STRING: + if (channel->numElements_ == 1){ + char temp[MAX_STRING_SIZE]; + dataStatus = out->get (caService::CA_TAG_VALUE, temp, sizeof(temp)); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 has no ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = ::ca_array_put_callback (DBR_STRING, channel->numElements_, + channel->cId_, temp, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_STRING, channel->numElements_, + channel->cId_, temp); +#endif + } + } + else { + char **temp = new char*[channel->numElements_]; + // each item will be allocated by the following + dataStatus = out->get (caService::CA_TAG_VALUE, temp); + int count = (int)channel->numElements_; + dataStatus = out->getElems (caService::CA_TAG_VALUE, (size_t *)&count); + if (dataStatus == CDEV_SUCCESS){ + char *cbuf = new char[channel->numElements_*MAX_STRING_SIZE]; + int j = 0; + for (int i = 0; i < channel->numElements_; i++){ + ::cdevStrncpy (&(cbuf[j]), temp[i], MAX_STRING_SIZE); + j += MAX_STRING_SIZE; + } + // epics 3.11 has no ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = ::ca_array_put_callback (DBR_STRING, channel->numElements_, + channel->cId_, cbuf, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_STRING, channel->numElements_, + channel->cId_, cbuf); +#endif + for (i = 0; i < count; i++) + delete []temp[i]; + delete []temp; + delete []cbuf; + } + } + break; + case DBR_ENUM: + if (channel->numElements_ == 1){ + char temp[MAX_STRING_SIZE]; + char temp2[MAX_STRING_SIZE]; + int tind; + dataStatus = out->get (caService::CA_TAG_VALUE, temp, sizeof(temp)); + if (dataStatus == CDEV_SUCCESS){ + int i = 0; + sscanf (temp, "%d", &tind); + // if a caller supplies (only) an integer, it will be treated as an index + if (sscanf (temp, "%d%s", &tind, temp2) == 1 && + tind >= 0 && + tind < channel->accessBuffer_->cenmval.no_str) + i = tind; + else { + for (i = 0; i < channel->accessBuffer_->cenmval.no_str; i++) { + if (::strcmp (temp, channel->accessBuffer_->cenmval.strs[i]) == 0) + break; + } + if (i >= channel->accessBuffer_->cenmval.no_str){ +#ifdef _CDEV_DEBUG + printf("Unmatched string %s to enum record\n", temp); + printf("The following are the string values\n"); + for (i = 0; i < channel->accessBuffer_->cenmval.no_str; i++) + printf(" %s ",channel->accessBuffer_->cenmval.strs[i]); + printf("\n"); +#endif + return CDEV_INVALIDARG; + } + } + short desiredIndex = i; +#ifdef _EPICS_3_12 + caStatus = ::ca_array_put_callback (DBR_ENUM, channel->numElements_, + channel->cId_, &desiredIndex, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_ENUM, channel->numElements_, + channel->cId_, &desiredIndex); +#endif + } + } + else { +#ifdef _CDEV_DEBUG + printf ("Multiple elements of DBR_ENUM is not supported in CDEV\n"); +#endif + return CDEV_INVALIDARG; + } + break; + case DBR_SHORT: + if (channel->numElements_ == 1){ + int value; + dataStatus = out->get (caService::CA_TAG_VALUE, &value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = ::ca_array_put_callback (DBR_LONG, channel->numElements_, + channel->cId_, &value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, &value); +#endif + } + } + else{ + int *value = new int[channel->numElements_]; + dataStatus = out->get (caService::CA_TAG_VALUE, value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = ::ca_array_put_callback (DBR_LONG, channel->numElements_, + channel->cId_, value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, value); +#endif + delete []value; + } + } + break; + case DBR_CHAR: + if (channel->numElements_ == 1){ + BYTE value; + dataStatus = out->get (caService::CA_TAG_VALUE, &value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = ::ca_array_put_callback (DBR_CHAR, channel->numElements_, + channel->cId_, &value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_CHAR, channel->numElements_, + channel->cId_, &value); +#endif + } + } + else{ + BYTE *value = new BYTE[channel->numElements_]; + dataStatus = out->get (caService::CA_TAG_VALUE, value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = ::ca_array_put_callback (DBR_CHAR, channel->numElements_, + channel->cId_, value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_CHAR, channel->numElements_, + channel->cId_, value); +#endif + delete []value; + } + } + break; + case DBR_LONG: + if (channel->numElements_ == 1){ + int value; + dataStatus = out->get (caService::CA_TAG_VALUE, &value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = ::ca_array_put_callback (DBR_LONG, channel->numElements_, + channel->cId_, &value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, &value); +#endif + } + } + else { + int *value = new int[channel->numElements_]; + dataStatus = out->get (caService::CA_TAG_VALUE, value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = ::ca_array_put_callback (DBR_LONG, channel->numElements_, + channel->cId_, value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, value); +#endif + delete []value; + } + } + break; + case DBR_FLOAT: + case DBR_DOUBLE: + if (channel->numElements_ == 1) { + double fval; + dataStatus = out->get (caService::CA_TAG_VALUE, &fval); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have put callback +#ifdef _EPICS_3_12 + caStatus = ::ca_array_put_callback (DBR_DOUBLE, channel->numElements_, + channel->cId_, &fval, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_DOUBLE, channel->numElements_, + channel->cId_, &fval); +#endif + } + } + else { + double *fval = new double[channel->numElements_]; + dataStatus = out->get (caService::CA_TAG_VALUE, fval); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have put callback +#ifdef _EPICS_3_12 + caStatus = ::ca_array_put_callback (DBR_DOUBLE, channel->numElements_, + channel->cId_, fval, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_DOUBLE, channel->numElements_, + channel->cId_, fval); +#endif + delete []fval; + } + } + break; + default: +#ifdef _CDEV_DEBUG + printf("unsupported data type \n"); +#endif + return CDEV_INVALIDARG; + // Break not needed because of return statement + // break; + } + // check data status first + if (dataStatus != CDEV_SUCCESS) { + // remove transaction objecyt so a group will not block + if (cbkobj) { + (*cbkobj->callbackFunction())(dataStatus, cbkobj->userarg(), + *reqObj, result); + dataStatus = CDEV_SUCCESS; // problem now handled, no more to report + } + else { + // use user outbound data as result code + out->insert (caService::CA_TAG_RESULT_CODE, dataStatus); + } + delete xobj; + return dataStatus; + } + + // check channel access status + if (caStatus != ECA_NORMAL){ +#ifdef _CDEV_DEBUG + printf("ca_array_put_callback failed\n"); +#endif + // remove transaction objecyt so a group will not block + if (cbkobj) { + (*cbkobj->callbackFunction())(CDEV_IOFAILED, cbkobj->userarg(), + *reqObj, result); + ioStatus = CDEV_SUCCESS; // problem now handled, no more to report + } + else { + // use user outbound data as result code + out->insert (caService::CA_TAG_RESULT_CODE, CDEV_IOFAILED); + ioStatus = CDEV_IOFAILED; + } + delete xobj; + return ioStatus; + } + + // trasaction object will be removed from default callback function + // for epics 3.11 I have no idea when put will finish + // so I have to delete this transaction object +#ifndef _EPICS_3_12 + // so what I do, just call callback :--- + if (cbkobj) { + (*cbkobj->callbackFunction())(CDEV_SUCCESS, cbkobj->userarg(), + *reqObj, result); + } + else { + // use user outbound data as result code + out->insert (caService::CA_TAG_RESULT_CODE, CDEV_SUCCESS); + } + + delete xobj; +#endif + return CDEV_SUCCESS; +} + +int +caRequestObject::sendCallback (cdevData& out, cdevCallback& callback) +{ + return sendCallback (&out, callback); +} + +int +caRequestObject::sendCallback (cdevData* out, cdevCallback& userCallback) +{ + if (!channel_) + attachChannel (); + + if (deferExecution (out, &userCallback)) + return CDEV_SUCCESS; + + int status = CDEV_ERROR; + cdevTranObj *xobj = 0; + caMonObj* obj = 0; + + // copy userCallback into the following callback, which will free + // user from taking care cdevCallback object. + // Note: cdevCallback's new operator is an overloaded operator + cdevCallback* callback = 0; + + switch (action_){ + case caRequestObject::GET: + callback = new cdevCallback (userCallback); + xobj = new cdevTranObj (&system_, this, 0, callback); + if (!channel_->connected_) { + bufferExecution (0, callback, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = getValueCbk (channel_, xobj); + break; + case caRequestObject::SET: + if (out == 0) + return CDEV_INVALIDARG; + if (readonly_) + return CDEV_INVALIDARG; + callback = new cdevCallback (userCallback); + + // if deferred execution, clone the data as caller may delete it + if (!channel_->connected_) { + cdevData *cloned = new cdevData(*out); + xobj = new cdevTranObj (&system_, this, cloned, callback); + bufferExecution (cloned, callback, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } else { + xobj = new cdevTranObj (&system_, this, out, callback); + } + status = setValueCbk (channel_, xobj); + break; + case caRequestObject::MONITOR_ON: + { + // copy user callback + callback = new cdevCallback (userCallback); + // create a new transaction object + xobj = new cdevTranObj (&system_, this, 0, callback); + + //================================================== + // if there is one callback is the same as the new + // one user wants, discard the new one + //================================================= + if (channel_->hasSameCallback (*callback)) { + delete xobj; + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s dislikes the same callbacks\n", + deviceName_, message_); + return CDEV_ERROR; + } + + // if channel is not connected, buffer this up + if (!channel_->connected_) { + bufferExecution (0, callback, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + + //================================================== + // if this requests has the same context i.e. + // or the same req type and request mask, use the + // same channel access event Id to get network + // response from the server. + //================================================= + caMonObj* eobj = 0; + if ((eobj = channel_->hasSameCallingCxt (reqType_, reqMask_)) != 0) { + // create new callback object and add to the list + caMonCbk* cbk = new caMonCbk (*xobj->userCallback_, xobj->resultData_); + eobj->addCallback (cbk); + // immediately call user callback now + eobj->callCallback (cbk); + + // call monitor properties which will add more monitor + // objects to the appropriate property channels + addCbksToPChannels (channel_, *xobj->userCallback_, + xobj->resultData_); + delete xobj; + + return CDEV_SUCCESS; + } + // get monitor object from transaction object + // and disable the transaction object from deleting + // the callback object + obj = new caMonObj (*xobj); + // set up associated arguments + obj->setMonitorInfo (caService::CA_TAG_VALUE, + CDEV_SUCCESS, + channel_, + reqType_, + reqMask_); + xobj->disableDeleteCbk (); + + monitorProperties (channel_, obj); + status = monitorValue (channel_, obj); + } + break; + case caRequestObject::MONITOR_OFF: + { + // remove a monitor object from all the channels + // monitor objects' destructor will call all monitor + // monitor callbacks to denote caller that monitor + // is over + channel_->removeCallback (&userCallback); + if (channel_->pinited_) { + caPchannel* pch = channel_->pchannels_; + + for (int i = 0; i < MAX_NUM_PCHANNELS; i++) { + if (pch[i].channel != 0) + pch[i].channel->removeCallback (&userCallback); + } + } + } + status = CDEV_SUCCESS; + break; + default: +#ifdef _CDEV_DEBUG + printf("Unsupported action message %s\n", action_); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject does not support message %d\n", + deviceName_, message_, action_); + status = CDEV_INVALIDARG; + break; + } + return status; +} + + +int +caRequestObject::execCallback (cdevData* out, + cdevCallback& userCallback, + void* arg) +{ + // arg is actually a transcation object + cdevTranObj* xobj = (cdevTranObj *)arg; + if (deferExecution (out, &userCallback)) { + // the above code will make copy of user callback, so it is safe + // to delete xobj that has userCallback in it here + delete xobj; + return CDEV_SUCCESS; + } + + int status = CDEV_ERROR; + caMonObj* obj = 0; + + // copy userCallback into the following callback, which will free + // user from taking care cdevCallback object. + // Note: cdevCallback's new operator is an overloaded operator + cdevCallback* callback = 0; + + switch (action_){ + case caRequestObject::GET: + if (!channel_->connected_) { + bufferExecution (0, xobj->userCallback_, + (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = getValueCbk (channel_, xobj); + break; + case caRequestObject::SET: + if (!channel_->connected_) { + cdevData *cloned = new cdevData(*out); + bufferExecution (cloned, xobj->userCallback_, + (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = setValueCbk (channel_, xobj); + break; + case caRequestObject::MONITOR_ON: + { + if (!channel_->connected_) { + bufferExecution (0, xobj->userCallback_, + (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + + //================================================== + // if this requests has the same context i.e. + // or the same req type and request mask, use the + // same channel access event Id to get network + // response from the server. + //================================================= + caMonObj* eobj = 0; + if ((eobj = channel_->hasSameCallingCxt (reqType_, reqMask_)) != 0) { + // create new callback object and add to the list + caMonCbk* cbk = new caMonCbk (*xobj->userCallback_, xobj->resultData_); + eobj->addCallback (cbk); + // immediately call user callback now + eobj->callCallback (cbk); + + // call monitor properties which will add more monitor + // objects to the appropriate property channels + addCbksToPChannels (channel_, *xobj->userCallback_, + xobj->resultData_); + delete xobj; + + return CDEV_SUCCESS; + } + // get monitor object from transaction object + // and disable the transaction object from deleting + // the callback object + obj = new caMonObj (*xobj); + // set up associated arguments + obj->setMonitorInfo (caService::CA_TAG_VALUE, + CDEV_SUCCESS, + channel_, + reqType_, + reqMask_); + xobj->disableDeleteCbk (); + + monitorProperties (channel_, obj); + status = monitorValue (channel_, obj); + } + break; + default: +#ifdef _CDEV_DEBUG + printf("Unsupported action message %s\n", action_); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject does not support message %d\n", + deviceName_, message_, action_); + status = CDEV_INVALIDARG; + break; + } + return status; +} + +void +caRequestObject::initPropChannels (caPchannel* pch) +{ + cdevData& cxt = getContext (); + int val; + char svcData[64]; + caService* svc = (caService *)service_; + + // scan through all property channels to establish connection if necessary + for (int i = 2; i < MAX_NUM_PCHANNELS; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS) + // caller specify a trigger or I am going to setup channel + // for those properties which are not changed rapidly + if (val == 2 || i >= 2) { + // construct channel access record.attr + ::strcpy (svcData, device_->name()); + ::strcat (svcData, "."); + ::strcat (svcData, svc->attr (pch[i].tag)); + + if (pch[i].channel == 0) { +#ifdef _CDEV_DEBUG + printf ("property channel %s is not created, do it now\n", svcData); +#endif + caChannel* ch = 0; + + if (svc->channelPtr (svcData, ch) != 0) { + // the channel has not created yet +#ifdef _CDEV_DEBUG + printf("property channel %s not created \n", svcData); +#endif + ch = new caChannel (svcData, svc); + svc->addChannel (svcData, ch); + ch->count_ = 1; + } + else{ +#ifdef _CDEV_DEBUG + printf("property channel %s created \n", svcData); +#endif + ch->count_ += 1; +#ifdef _CA_SYNC_CONN + if (!ch->connected_){ // channel not connected + channel_->connect (); + } +#endif + } + pch[i].channel = ch; + } + } + } +} + +void +caRequestObject::initPropChannels (caChannel* parent) +{ + cdevData& cxt = getContext (); + int val; + char svcData[64]; + caService* svc = (caService *)service_; + + caPchannel* pch = parent->pchannels_; + + if (!pch) + return; + + // scan through all property channels to establish connection if necessary + for (int i = 2; i < MAX_NUM_PCHANNELS; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS) + // caller specify a trigger or I am going to setup channel + // for those properties which are not changed rapidly + if (val == 2 || i >= 2) { + // construct channel access record.attr + ::strcpy (svcData, device_->name()); + ::strcat (svcData, "."); + ::strcat (svcData, svc->attr (pch[i].tag)); + + if (pch[i].channel == 0) { +#ifdef _CDEV_DEBUG + printf ("property channel %s is not created, do it now\n", svcData); +#endif + caChannel* ch = 0; + + if (svc->channelPtr (svcData, ch) != 0) { + // the channel has not created yet +#ifdef _CDEV_DEBUG + printf("property channel %s not created \n", ch->channelName_); +#endif + ch = new caChannel (svcData, svc); + svc->addChannel (svcData, ch); + ch->count_ = 1; + } + else{ +#ifdef _CDEV_DEBUG + printf("property channel %s created \n", svcData); +#endif + ch->count_ += 1; +#ifdef _CA_SYNC_CONN + if (!ch->connected_){ // channel not connected + channel_->connect (); + } +#endif + } + pch[i].channel = ch; + } + } + } +} + +void +caRequestObject::monitorProperties (caChannel* parent, caMonObj *obj) +{ + cdevData& cxt = getContext (); + int val; + char svcData[64]; + caService* svc = (caService *)service_; + + // get property channel pointer + caPchannel* pch = parent->pchannels_; + + if (!pch) /* no property channel, return */ + return; + + // scan through all property channels to establish connection if necessary + for (int i = 2; i < MAX_NUM_PCHANNELS; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS) + // caller specify a trigger or I am going to setup channel + // for those properties which are not changed rapidly + if (val == 2 || i >= 2) { + // construct channel access record.attr + if (pch[i].channel && pch[i].channel->connected_){ + if (!pch[i].monitored) { + caMonObj *newobj = new caMonObj (*obj, obj->cbks_->cbk_, + obj->cbks_->out_); + newobj->tobj_ = 0; + newobj->tag_ = pch[i].tag; + newobj->cbkStatus_ = CDEV_SUCCESS; + newobj->channel_ = pch[i].channel; + + // sep-27-1995 -- Jie chen + // if this context value == 1, we cache its value instead of + // calling user callback directly + if (val == 1) + newobj->cbks_->enableCache (); + + if (monitorPropValue (pch[i].channel, newobj) == CDEV_SUCCESS) { + pch[i].channel->addMonitorObj (newobj); + pch[i].monitored = 1; + } + else { + delete pch[i].channel; + pch[i].channel = 0; + } + } + else { + // get first monitor object pointer from this property + // channel: it should never return 0 + caMonObj* fobj = pch[i].channel->firstMonitorObj (); + if (!fobj) { + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s has bad property channel\n", + deviceName_, message_); + return; + } + + // create a new callback object with dupliate user callback + // information in it + caMonCbk* cbkobj = new caMonCbk (*obj->cbks_->cbk_, + obj->cbks_->out_); + if (val == 1) + cbkobj->enableCache (); + + fobj->addCallback (cbkobj); + } + } + } + } +} + + +void +caRequestObject::addCbksToPChannels (caChannel* parent, + cdevCallback& cbk, + cdevData* out) +{ + cdevData& cxt = getContext (); + int val; + char svcData[64]; + caService* svc = (caService *)service_; + + // get property channel pointer + caPchannel* pch = parent->pchannels_; + if (!pch) + return; + + // scan through all property channels to establish connection if necessary + for (int i = 2; i < MAX_NUM_PCHANNELS; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS) + // caller specify a trigger or I am going to setup channel + // for those properties which are not changed rapidly + + if ((val == 2 || i >= 2) && pch[i].channel != 0 && + pch[i].channel->connected_ && pch[i].monitored) { +#ifdef _CDEV_DEBUG + printf ("property channel %s is created already\n", svcData); +#endif + // get first monitor object pointer from this property + // channel: it should never return 0 + caMonObj* fobj = pch[i].channel->firstMonitorObj (); + if (!fobj) { + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s has bad property channel\n", + deviceName_, message_); + return; + } + + // create a new callback object with dupliate user callback + // information in it + caMonCbk* cbkobj = new caMonCbk (cbk, out); + + if (val == 1) + cbkobj->enableCache (); + else + // call callbak right away + fobj->callCallback (cbkobj); + + fobj->addCallback (cbkobj); + } + } +} + +int +caRequestObject::monitorValue (caChannel* channel, caMonObj *xobj) +{ + // check value context + cdevData& cxt = getContext (); + int val; + int mask = DBE_VALUE | DBE_ALARM; + + if (cxt.get (caService::CA_TAG_VALUE, &val) == CDEV_SUCCESS) { + if (val == 0) // if 0: no monitor on value + mask = 0; + } + + // get property channel pointer + caPchannel* pch = channel->pchannels_; + + if (pch) { + // scan first two property channels to change monitor mask if necessary + for (int i = 0; i < 2; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS){ + if (val >=2) + mask = mask | DBE_ALARM; + } + } + } + + if (mask == 0) { // we have nothing to do + // no callback will be called, remove transaction object + // otherwise group will block + cdevCallback *cbkobj = xobj->cbks_->cbk_; + cdevRequestObject *reqobj = xobj->reqObj_; + cdevData result; + + cbkobj->fireCallback (CDEV_IOFAILED, cbkobj->userarg (), + *reqobj, result, 0); + + if (xobj->tobj_) { + delete xobj->tobj_; + xobj->tobj_ = 0; + } + delete xobj; + return CDEV_IOFAILED; + } + + int status, caStatus; + int reqType; + // get everything of status and severity and timestamp + reqType = (int)dbf_type_to_DBR_TIME (channel->type_); + + caStatus = ::ca_add_masked_array_event (reqType, + channel->numElements_, + channel->cId_, + &(caRequestObject::callMonitorCallback), + (void *)(xobj), + 0, 0, 0, + &(xobj->mEvId_), + mask); + if (caStatus != ECA_NORMAL) { + // no callback will be called, remove transaction object + // otherwise group will block + cdevCallback *cbkobj = xobj->cbks_->cbk_; + cdevRequestObject *reqobj = xobj->reqObj_; + cdevData result; + + cbkobj->fireCallback (CDEV_IOFAILED, cbkobj->userarg (), + *reqobj, result, 0); + if (xobj->tobj_) { + delete xobj->tobj_; + xobj->tobj_ = 0; + } + delete xobj; + status = CDEV_IOFAILED; + } + else + status = CDEV_SUCCESS; + + return status; +} + +int +caRequestObject::monitorPropValue (caChannel* channel, caMonObj *xobj) +{ + int status = ::ca_add_masked_array_event (channel->type_, + channel->numElements_, + channel->cId_, + &(caRequestObject::callPropMonitorCallback), + (void *)(xobj), + 0, 0, 0, + &(xobj->mEvId_), + DBE_VALUE); + if (status != ECA_NORMAL) + return CDEV_IOFAILED; + else + return CDEV_SUCCESS; +} + +void +caRequestObject::convertData (int chtype, + int tag, + int reqMask, + int reqType, + struct event_handler_args& args, + cdevData& resData) +{ + switch (chtype){ + case DBR_STRING: + { + struct dbr_time_string *retValue = 0; + retValue = (struct dbr_time_string *)args.dbr; + if (args.count == 1){ + resData.insert (tag, retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else{ + char **insertBuf = new char* [args.count]; + insertBuf[0] = new char[MAX_STRING_SIZE]; + ::cdevStrncpy (insertBuf[0], retValue->value, MAX_STRING_SIZE); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_string); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = new char[MAX_STRING_SIZE]; + ::cdevStrncpy (insertBuf[i], &(buffer[j]), MAX_STRING_SIZE); + j += MAX_STRING_SIZE; + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + + for (i = 0; i < args.count; i++) + delete []insertBuf[i]; + delete []insertBuf; + } + } + break; + case DBR_ENUM: + if (args.count == 1){ + if (reqType != caRequestObject::TIMESTMP){ + struct dbr_ctrl_enum *retValue = 0; + retValue = (struct dbr_ctrl_enum *)args.dbr; + if (reqType >= caRequestObject::GRINFO) { + int i = 0; + // we want display information + char **strs = 0; + if (retValue->no_str > 0) { + strs = new char*[retValue->no_str]; + for (i = 0; i < retValue->no_str; i++) { + strs[i] = new char[strlen (retValue->strs[i]) + 1]; + strcpy (strs[i], retValue->strs[i]); + } + } + resData.insert (tag, strs, retValue->no_str); + + // free memory + for (i = 0; i < retValue->no_str; i++) + delete []strs[i]; + delete []strs; + } + else { + unsigned short index = retValue->value; + // If this string is a null string, we return index value + if (!strlen (retValue->strs[index])) + resData.insert (tag, index); + else + resData.insert (tag, retValue->strs[index]); + } + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else{ + struct dbr_time_enum *retValue = 0; + retValue = (struct dbr_time_enum *)args.dbr; + // since dbr_time_enum has no string in it's structure + // it is impossible to find corresponding strings + resData.insert (tag, retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + } + else{ +#ifdef _CDEV_DEBUG + printf ("Multiple elements of DBR_ENUM is not supported in CDEV\n"); +#endif + } + break; + case DBR_SHORT: + if (reqType != caRequestObject::TIMESTMP){ + struct dbr_ctrl_short *retValue = 0; + retValue = (struct dbr_ctrl_short *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (int)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + int* insertBuf = new int[args.count]; + insertBuf[0] = (int)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_ctrl_short); + short tmp; + for (int i = 1; i < args.count; i++){ + tmp = *(short *)&(buffer[j]); + insertBuf[i] = (int)tmp; + j += sizeof (short); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + + delete []insertBuf; + } + } + else{ + struct dbr_time_short *retValue = 0; + retValue = (struct dbr_time_short *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (int)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + int* insertBuf = new int[args.count]; + insertBuf[0] = (int)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_short); + short tmp; + for (int i = 1; i < args.count; i++){ + tmp = *(short *)&(buffer[j]); + insertBuf[i] = (int)tmp; + j += sizeof (short); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + break; + case DBR_CHAR: + if (reqType != caRequestObject::TIMESTMP){ + struct dbr_ctrl_char *retValue = 0; + retValue = (struct dbr_ctrl_char *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (BYTE)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + BYTE* insertBuf = new BYTE[args.count]; + insertBuf[0] = (BYTE)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_ctrl_char); + char tmp; + for (int i = 1; i < args.count; i++){ + tmp = *(char *)&(buffer[j]); + insertBuf[i] = (BYTE)tmp; + j += sizeof (char); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + + delete []insertBuf; + } + } + else{ + struct dbr_time_char *retValue = 0; + retValue = (struct dbr_time_char *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (BYTE)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + BYTE* insertBuf = new BYTE[args.count]; + insertBuf[0] = (BYTE)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_char); + char tmp; + for (int i = 1; i < args.count; i++){ + tmp = *(char *)&(buffer[j]); + insertBuf[i] = (BYTE)tmp; + j += sizeof (char); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + break; + case DBR_LONG: + if (reqType != caRequestObject::TIMESTMP){ + struct dbr_ctrl_long *retValue = 0; + retValue = (struct dbr_ctrl_long *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (int)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + int* insertBuf = new int[args.count]; + insertBuf[0] = (int)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_ctrl_long); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(int *)&(buffer[j]); + j += sizeof (long); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + else{ + struct dbr_time_long *retValue = 0; + retValue = (struct dbr_time_long *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (int)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + int* insertBuf = new int[args.count]; + insertBuf[0] = (int)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_long); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(int *)&(buffer[j]); + j += sizeof (long); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + break; + case DBR_FLOAT: + if (reqType != caRequestObject::TIMESTMP){ + struct dbr_ctrl_float *retValue = 0; + retValue = (struct dbr_ctrl_float *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (float)retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else{ + float* insertBuf = new float[args.count]; + insertBuf[0] = (float)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_ctrl_float); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(float *)&(buffer[j]); + j += sizeof (float); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + else{ + struct dbr_time_float *retValue = 0; + retValue = (struct dbr_time_float *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (float)retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + float* insertBuf = new float[args.count]; + insertBuf[0] = (float)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_float); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(float *)&(buffer[j]); + j += sizeof (float); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + break; + case DBR_DOUBLE: + if (reqType != caRequestObject::TIMESTMP){ + struct dbr_ctrl_double *retValue = 0; + retValue = (struct dbr_ctrl_double *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (double)retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + double* insertBuf = new double[args.count]; + insertBuf[0] = (double)retValue->value; + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_ctrl_double); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(double *)&(buffer[j]); + j += sizeof (double); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + else{ + struct dbr_time_double *retValue = 0; + retValue = (struct dbr_time_double *)args.dbr; + if (args.count == 1) { + resData.insert (tag, (double)retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + double* insertBuf = new double[args.count]; + insertBuf[0] = (double)retValue->value; + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_double); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(double *)&(buffer[j]); + j += sizeof (double); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + break; + default: + printf("Fatal Error: Unsupported data type\n"); + break; + } +} + +void +caRequestObject::defaultGetCallback (struct event_handler_args args) +{ +#ifdef _CDEV_DEBUG + printf("get callback called\n"); +#endif + cdevTranObj *xobj = (cdevTranObj *)args.usr; + + if (xobj->isTrash ()) { + // this transaction object is deleted already + delete xobj; + return; + } + + //========================================================= + // One must know the requestObject from transaction + // is caRequestObject. So no vialation here + //========================================================= + caRequestObject *reqObj = (caRequestObject *)xobj->reqObj_; + //========================================================= + // Check data type + //========================================================= + cdevData *resData = xobj->resultData_; + cdevCallback *cbkobj = xobj->userCallback_; + cdevData result; + + if (resData) // send no block + resData->remove(); + else // send callback + resData = &result; + + if (args.count > 0 && args.dbr != 0) { + // convert data from channel access type to cdevData type + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqObj->reqMask_, + reqObj->reqType_, + args, *resData); + + if (cbkobj) { // called from sendCallback + (*cbkobj->callbackFunction ()) (CDEV_SUCCESS, cbkobj->userarg (), + *reqObj, result); + } + } + else { + if (cbkobj) { // called from sendCallback + (*cbkobj->callbackFunction ()) (CDEV_IOFAILED, cbkobj->userarg (), + *reqObj, result); + } + } + delete xobj; +} + +void +caRequestObject::defaultSetCallback (struct event_handler_args args) +{ + // for now just remove transaction object +#ifdef _CDEV_DEBUG + printf("default set callback called\n"); +#endif + int status = CDEV_SUCCESS; + + cdevTranObj *xobj = (cdevTranObj *)args.usr; + + if (xobj->isTrash ()) { + // this transaction object is deleted already + delete xobj; + return; + } + + //========================================================= + // One must know the requestObject from transaction + // is caRequestObject. So no vialation here + //========================================================= + caRequestObject *reqObj = (caRequestObject *)xobj->reqObj_; + cdevData result; + + cdevCallback *cbkobj = xobj->userCallback_; + if (cbkobj) { // from sendCallback + if (args.status != ECA_NORMAL) + status = CDEV_IOFAILED; + (*cbkobj->callbackFunction())(status, cbkobj->userarg(), + *reqObj, result); + } + delete xobj; +} + +void +caRequestObject::callPropMonitorCallback (struct event_handler_args args) +{ + caMonObj *xobj = (caMonObj *)args.usr; + caChannel* ch = xobj->channel_; + + // get tag value associated with this channel + int tagval = xobj->tag_; + // get callback status value assocaited with this channel + int cbkst = xobj->cbkStatus_; + + int status = CDEV_ERROR; + + if (args.count > 0 && args.dbr != 0) { + // clean out old information + xobj->cache_.remove (); + switch (ch->type_){ + case DBR_STRING: + { + char *retValue; + retValue = (char *)args.dbr; + xobj->cache_.insert (tagval, (char *)(retValue)); + } + break; + case DBR_ENUM: + { + // get index value + unsigned short index = *(unsigned short *)args.dbr; + if (ch->accessBuffer_) + status = xobj->cache_.insert (tagval, + ch->accessBuffer_->cenmval.strs[index]); + else + status = xobj->cache_.insert (tagval, index); + } + break; + case DBR_SHORT: + { + short tmp = *(short *)(args.dbr); + status = xobj->cache_.insert (tagval, (int)tmp); + } + break; + case DBR_CHAR: + { + BYTE tmp = *(BYTE *)(args.dbr); + status = xobj->cache_.insert (tagval, (BYTE)tmp); + } + break; + case DBR_LONG: + { + int tmp = *(int *)(args.dbr); + status = xobj->cache_.insert (tagval, tmp); + } + break; + case DBR_FLOAT: + { + float tmp = *(float *)(args.dbr); + status = xobj->cache_.insert (tagval, tmp); + } + break; + case DBR_DOUBLE: + { + double tmp = *(double *)(args.dbr); + status = xobj->cache_.insert (tagval, tmp); + } + break; + default: + cdevSystem::defaultSystem().reportError + (CDEV_SEVERITY_ERROR, + "caRequestObject", NULL, + "Unsupported data type %d\n", + ch->type_); + break; + } + } + + if (status == CDEV_SUCCESS) { + updatePropCache ((caRequestObject *)xobj->reqObj_, + tagval, + xobj->cache_); + xobj->callCallbacks (cbkst, xobj->reqObj_, xobj->cache_); + } + else + xobj->callCallbacks (CDEV_ERROR, xobj->reqObj_, xobj->cache_); +} + +void +caRequestObject::callMonitorCallback (struct event_handler_args args) +{ + static caRequestObject *reqObj = 0; + caMonObj *xobj = (caMonObj *)args.usr; + + // get request object + reqObj = (caRequestObject *)xobj->reqObj_; + // get channel object + caChannel* ch = xobj->channel_; + + // get tag value associated with this channel + int tagval = xobj->tag_; + // get callback status value assocaited with this channel + int cbkst = xobj->cbkStatus_; + + if (xobj->tobj_ != 0) { + // remove transaction object so that pend will give back right result + if (xobj->tobj_->isTrash ()) { + // if this transaction object is trash, return + delete xobj->tobj_; + xobj->tobj_ = 0; + return; + } + else { + delete xobj->tobj_; + xobj->tobj_ = 0; + } + // create monitor object from trasanction object + reqObj->channel_->addMonitorObj (xobj); + } + + if (args.count > 0 && args.dbr != 0) { + // get type and mask + int reqType = xobj->reqType_; + int reqMask = xobj->reqMask_; + switch (reqObj->channel_->type_){ + case DBR_STRING: + // since monitor value always use DBR_TIME strcuture + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + break; + case DBR_ENUM: + { + // since monitor value always use DBR_TIME strcuture which + // has no no_str and str information, the corresponding + // channel information about no_str and strs are used here + xobj->cache_.remove (); + struct dbr_time_enum *retValue = 0; + retValue = (struct dbr_time_enum *)args.dbr; + unsigned short index = retValue->value; + + if (ch->accessBuffer_ && ch->accessBuffer_->cenmval.no_str && + index < ch->accessBuffer_->cenmval.no_str && + strlen (ch->accessBuffer_->cenmval.strs[index])) + xobj->cache_.insert (caService::CA_TAG_VALUE, + ch->accessBuffer_->cenmval.strs[index]); + else + xobj->cache_.insert (caService::CA_TAG_VALUE, index); + caRequestObject::fillResult (reqMask, reqType, *retValue, xobj->cache_); + + // call user callbacks + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + case DBR_SHORT: + if (!xobj->cacheInited_) { + // setup internal buffer pointer + caMonObj::setupMonitorBuffer (tagval, xobj->cache_, xobj->data_, + CDEV_INT32); + xobj->cacheInited_ = 1; + } + + if (args.count == 1){ + struct dbr_time_short *retValue = 0; + retValue = (struct dbr_time_short *)args.dbr; + caRequestObject::updateResult (reqMask, reqType, + *retValue, xobj->data_, + reqObj->propCache() ); + + if (reqObj->longMask_ != 0) { + if (reqObj->bitValuesChanged (*(int *)(xobj->data_.value), + reqObj->longMask_)) + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else { + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + case DBR_CHAR: + if (!xobj->cacheInited_) { + // setup internal buffer pointer + caMonObj::setupMonitorBuffer (tagval, xobj->cache_, xobj->data_, + CDEV_BYTE); + xobj->cacheInited_ = 1; + } + + if (args.count == 1){ + struct dbr_time_char *retValue = 0; + retValue = (struct dbr_time_char *)args.dbr; + caRequestObject::updateResult (reqMask, reqType, + *retValue, xobj->data_, + reqObj->propCache() ); + + if (reqObj->longMask_ != 0) { + BYTE vtmp = *(BYTE *)(xobj->data_.value); + if (reqObj->bitValuesChanged ((int)vtmp, + reqObj->longMask_)) + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else { + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + case DBR_LONG: + if (!xobj->cacheInited_) { + // setup internal buffer pointer + caMonObj::setupMonitorBuffer (tagval, xobj->cache_, xobj->data_, + CDEV_INT32); + xobj->cacheInited_ = 1; + } + + if (args.count == 1) { + struct dbr_time_long *retValue = 0; + retValue = (struct dbr_time_long *)args.dbr; + caRequestObject::updateResult (reqMask, reqType, + *retValue, xobj->data_, + reqObj->propCache() ); + + if (reqObj->longMask_ != 0) { + if (reqObj->bitValuesChanged (*(int *)(xobj->data_.value), + reqObj->longMask_)) + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else { + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + case DBR_FLOAT: + if (!xobj->cacheInited_) { + // setup internal buffer pointer + caMonObj::setupMonitorBuffer (tagval, xobj->cache_, xobj->data_, + CDEV_FLOAT); + xobj->cacheInited_ = 1; + } + + if (args.count == 1) { + struct dbr_time_float *retValue = 0; + retValue = (struct dbr_time_float *)args.dbr; + caRequestObject::updateResult (reqMask, reqType, *retValue, + xobj->data_, + reqObj->propCache() ); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else { + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + case DBR_DOUBLE: + if (!xobj->cacheInited_) { + // setup internal buffer pointer + caMonObj::setupMonitorBuffer (tagval, xobj->cache_, xobj->data_, + CDEV_DOUBLE); + xobj->cacheInited_ = 1; + } + + if (args.count == 1) { + struct dbr_time_double *retValue = 0; + retValue = (struct dbr_time_double *)args.dbr; + caRequestObject::updateResult (reqMask, reqType, + *retValue, xobj->data_, + reqObj->propCache() ); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else { + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + default: + printf("Fatal Error: Unsupported data type\n"); + break; + } + } + else + xobj->callCallbacks (CDEV_IOFAILED, reqObj, xobj->cache_); +} + +int +caRequestObject::findSvcData (char *device, + char *msg, + cdevSystem& system, + char *svcData, + int dataLen) +{ + char message[256], fullname[128]; + + if (system.prefix()) + ::sprintf (fullname, "%s%s",system.prefix(),device); + else + ::strcpy (fullname, device); + + ::sprintf (message,"resolveServiceData %s %s", fullname, msg); + + cdevData result; + int status = (system.nameServer()).send (message, 0, result); + if (status == CDEV_SUCCESS){ + result.get (caService::CA_TAG_PV, svcData, dataLen); + int rd; + int dataStatus = result.get (caService::CA_TAG_RO, &rd); + if (dataStatus == CDEV_SUCCESS){ // channel is readonly + readonly_ = 1; + } +#ifdef _CDEV_DEBUG + printf("Service data is %s\n",svcData); +#endif + return status; + } + else + return CDEV_ERROR; +} + +int +caRequestObject::findAction (char *msg, int& action) +{ + char token0[64], token1[64], token2[64]; + int status; + +#ifdef __GNUC__ + // some version of gcc demand a memory location for msg + char buffer[256]; + strncpy (buffer, msg, sizeof (buffer)); + status = ::sscanf (buffer, "%s %s",token0, token1); +#else + status = ::sscanf (msg, "%s %s", token0, token1); +#endif + + if (::strcmp (token0, "get") == 0) + action = caRequestObject::GET; + else if (::strcmp (token0, "set") == 0) + action = caRequestObject::SET; + else if (::strcmp (token0, "monitorOn") == 0) + action = caRequestObject::MONITOR_ON; + else if (::strcmp (token0, "monitorOff") == 0) + action = caRequestObject::MONITOR_OFF; + else + action = caRequestObject::UNKNOWN; + + return CDEV_SUCCESS; +} + +int +caRequestObject::newTriggerSource (void) +{ + cdevData& cxt = getContext (); + int val = 0; + if (cxt.get (caService::CA_TAG_VALUE, &val) == CDEV_SUCCESS) { + if (val == 0) { + caPchannel* pch = channel_->pchannels_; + for (int i = 2; i < MAX_NUM_PCHANNELS; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS){ + // caller specify a trigger or I am going to setup channel + // for those properties which are not changed rapidly + if (val >= 2) + return 1; + } + } + } + } + return 0; +} + +void +caRequestObject::setPropCache (void) +{ + if (cache_ == 0) { + prop_ = new cdevData (); + cache_ = new caMonData (); + int status = caMonObj::setupMonitorBuffer (caService::CA_TAG_VALUE, + *prop_, *cache_, CDEV_FLOAT); + if (status != CDEV_SUCCESS) { + delete cache_; + delete prop_; + cache_ = 0; + prop_ = 0; + } + } +} + +caMonData* +caRequestObject::propCache (void) const +{ + return cache_; +} + +void +caRequestObject::updatePropCache (caRequestObject* obj, + int tag, + cdevData& data) +{ + caMonData* cache = obj->propCache (); + + if (cache != 0) { + if (tag == caService::CA_TAG_STATUS) + data.get (tag, cache->status); + else if (tag == caService::CA_TAG_SEVERITY) + data.get (tag, cache->severity); + else if (tag == caService::CA_TAG_PRECISION) + data.get (tag, cache->precision); + else if (tag == caService::CA_TAG_DISPHI) + data.get (tag, cache->disphi); + else if (tag == caService::CA_TAG_DISPLO) + data.get (tag, cache->displo); + else if (tag == caService::CA_TAG_ALRMHI) + data.get (tag, cache->alrmhi); + else if (tag == caService::CA_TAG_ALRMLO) + data.get (tag, cache->alrmlo); + else if (tag == caService::CA_TAG_WRNHI) + data.get (tag, cache->warnhi); + else if (tag == caService::CA_TAG_WRNLO) + data.get (tag, cache->warnlo); + else if (tag == caService::CA_TAG_CTRLHI) + data.get (tag, cache->ctrlhi); + else if (tag == caService::CA_TAG_CTRLLO) + data.get (tag, cache->ctrllo); + else + cdevSystem::defaultSystem().reportError + (CDEV_SEVERITY_ERROR, "caRequestObject", obj, + "Warning: property cache buffers does not have this tag %d\n", + tag); + } +} diff --git a/src/ca/caRequestObject.cc.rej b/src/ca/caRequestObject.cc.rej new file mode 100644 index 0000000..feacaaa --- /dev/null +++ b/src/ca/caRequestObject.cc.rej @@ -0,0 +1,42 @@ +*************** +*** 1403,1411 **** + // check data status first + if (dataStatus != CDEV_SUCCESS) { + // remove transaction objecyt so a group will not block +- if (cbkobj) { +- (*cbkobj->callbackFunction())(dataStatus, cbkobj->userarg(), +- *reqObj, result); + } + else { + // use user outbound data as result code +--- 1434,1442 ---- + // check data status first + if (dataStatus != CDEV_SUCCESS) { + // remove transaction objecyt so a group will not block ++ // T. Straumann: added check if user supplied a callbackFunction. ++ if (cbkobj && (userFcn = cbkobj->callbackFunction()) ) { ++ (*userFcn)(dataStatus, cbkobj->userarg(), *reqObj, result); + } + else { + // use user outbound data as result code +*************** +*** 1421,1429 **** + printf("ca_array_put_callback failed\n"); + #endif + // remove transaction objecyt so a group will not block +- if (cbkobj) { +- (*cbkobj->callbackFunction())(CDEV_IOFAILED, cbkobj->userarg(), +- *reqObj, result); + } + else { + // use user outbound data as result code +--- 1452,1460 ---- + printf("ca_array_put_callback failed\n"); + #endif + // remove transaction objecyt so a group will not block ++ // T. Straumann: added check if user supplied a callbackFunction. ++ if (cbkobj && (userFcn = cbkobj->callbackFunction()) ) { ++ (*userFcn)(CDEV_IOFAILED, cbkobj->userarg(), *reqObj, result); + } + else { + // use user outbound data as result code diff --git a/src/ca/caRequestObject.cc_new b/src/ca/caRequestObject.cc_new new file mode 100755 index 0000000..25d11c4 --- /dev/null +++ b/src/ca/caRequestObject.cc_new @@ -0,0 +1,2945 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Channel Access RequestObject Class +// +// Author: Jie Chen +// +// Revision History: +// caRequestObject.cc,v +// Revision 1.34 1998/04/10 13:55:41 chen +// add access information to caService +// +// Revision 1.33 1998/04/08 20:19:05 chen +// fix set problem +// +// Revision 1.32 1998/03/30 19:39:53 chen +// bug fix for channel_ null pointer inside destructor +// +// Revision 1.31 1998/03/23 21:17:18 chen +// Fix a bug related to prop channels: found on solaris +// +// Revision 1.30 1998/03/09 15:45:40 chen +// Install ENUM no_str into displayHigh for ENUM type +// +// Revision 1.29 1998/03/05 18:49:13 chen +// fix a bug on context == 2 on property channels +// +// Revision 1.28 1998/03/03 20:50:21 chen +// Return array of strings if one asks about display information on DBR_ENUM channel +// +// Revision 1.27 1998/02/18 19:48:26 chen +// fix ca set access error +// +// Revision 1.26 1997/08/08 16:41:36 chen +// add char type and fix dbr == null +// +// Revision 1.25 1997/07/18 14:24:44 chen +// remove one printf +// +// Revision 1.24 1997/03/03 17:36:28 chen +// add buffering to channel access connection +// +// Revision 1.23 1996/09/18 14:46:50 chen +// Channel holds multiple monitor objects +// +// Revision 1.22 1996/07/23 15:59:14 chen +// send with monitorOff will remove all monitored callbacks +// +// Revision 1.21 1996/05/02 14:18:26 chen +// Fix monitorOn and unfinished transaction bug +// +// Revision 1.20 1996/01/05 18:40:05 chen +// Fix a bug for gcc and a bug for monitoring enum values +// +// Revision 1.19 1995/12/08 15:42:28 chen +// fix double/float set value and add deferred execution mode +// +// Revision 1.18 1995/11/07 14:26:57 akers +// Added CTRLLO and CTRLHI to populateMonitor +// +// Revision 1.17 1995/10/30 13:33:05 akers +// Added cdev specific version of strncpy +// +// Revision 1.16 1995/10/26 14:33:14 akers +// Removal of Warnings +// +// Revision 1.15 1995/10/17 20:20:51 chen +// redefine getState +// +// Revision 1.14 1995/10/13 14:42:37 chen +// add debug flag in the monitorProperty +// +// Revision 1.13 1995/10/03 19:56:25 chen +// add monitoring properties +// +// Revision 1.12 1995/09/19 16:06:36 chen +// minor change on bit monitoring +// +// Revision 1.11 1995/09/18 18:22:49 chen +// add monitoring bit pattern capability for long/short integer +// +// Revision 1.10 1995/09/15 19:27:28 chen +// Fix a bug of array of doubles +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#include +#include +#include +#include +#include "caRequestObject.h" +#include "caNameSvc.h" +#include "caService.h" +#include "caChannel.h" +#include "caMisc.h" + +#ifndef TS_EPOCH_SEC_PAST_1970 +/* 1/1/90 20 yr (5 leap) of seconds */ +#define TS_EPOCH_SEC_PAST_1970 7305*86400 +#endif + +int caRequestObject::numAttributes = 14; + +caAttr caRequestObject::caAttributes[]= +{ + {"value", 0x00000001}, + {"status", 0x00000002}, + {"severity", 0x00000004}, + {"time", 0x00000008}, + {"precision", 0x00000010}, + {"units", 0x00000020}, + {"displayHigh", 0x00000040}, + {"displayLow", 0x00000080}, + {"alarmHigh", 0x00000100}, + {"alarmLow", 0x00000200}, + {"warningHigh", 0x00000400}, + {"warningLow", 0x00000800}, + {"controlHigh", 0x00001000}, + {"controlLow", 0x00002000}, +}; + +//========================================================================= +// Implementation of caRequestObject +//========================================================================= +caRequestObject::caRequestObject (char *device, char *msg, + caService *, + cdevSystem& system) +:cdevRequestObject (device, msg, system), cache_ (0), prop_ (0), readonly_ (0), + reqType_ (caRequestObject::VALUE), reqMask_ (0x1), channel_ (0) +{ +#ifdef _TRACE_OBJECTS + printf (" Create caRequestObject class \n"); +#endif + caRequestObject::findAction (msg, action_); +} + +caRequestObject::~caRequestObject (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete caRequestObject class \n"); +#endif + caService *svc = (caService *)service_; + if (channel_ && --channel_->count_ <= 0){// no more reference to the channel + svc->removeChannel (channel_->channelName_, channel_); + delete channel_; + } + // reset the pointer of cached properties to zero + if (cache_) { + delete cache_; + cache_ = 0; + } + if (prop_) { + delete prop_; + prop_ = 0; + } +} + +void +caRequestObject::attachChannel (void) +{ + int status; + caService* svc = (caService *)service_; + caPchannel* pchs = 0; + + // caller may need to monitor properties, setup properties cache buffer + // order of calls is important: We have to create property channel before + // we create main channel + if (reqType_ != caRequestObject::VALUE + && action_ == caRequestObject::MONITOR_ON) { + setPropCache (); + pchs = caChannel::createPchannels (); + // create all pchannels + initPropChannels (pchs); + + // flush out the property channel connection requests + svc->flush (); + } + + // get service data first + char svcData[64]; + status = findSvcData (deviceName_, message_, system_, + svcData, sizeof (svcData)); + + status = svc->channelPtr (svcData, channel_); + + if (status != 0){ // the channel has not created yet +#ifdef _CDEV_DEBUG + printf("channel %s not created \n", svcData); +#endif + channel_ = new caChannel (svcData, svc); + svc->addChannel (svcData, channel_); + channel_->count_ = 1; + } + else{ +#ifdef _CDEV_DEBUG + printf("channel %s is created \n", svcData); +#endif + channel_->count_ += 1; +#ifdef _CA_SYNC_CONN + if (!channel_->connected_){ // channel not connected + channel_->connect (); + } +#endif + } + + // assign pchannels to this channel + if (pchs) + channel_->propertyChannels (pchs); +} + +int +caRequestObject::getState (void) +{ + if (channel_->connected_) + return CDEV_STATE_CONNECTED; + else + return CDEV_STATE_NOTCONNECTED; +} + +int +caRequestObject::getAccess (void) +{ + return channel_->readonly_; +} + +int +caRequestObject::setContext (cdevData &cxt) +{ + int temp; + + // clean the mask + reqMask_ = 0x0; + reqType_ = caRequestObject::VALUE; + // get bitmask from cdev requestobject layer + (void)cdevRequestObject::setContext (cxt); + + for (int i = 0; i < caRequestObject::numAttributes; i++){ + if (cxt.get ((caRequestObject::caAttributes[i]).attrName, &temp) == CDEV_SUCCESS){ + reqMask_ |= (caRequestObject::caAttributes[i]).attrValue; + } + } + + if (reqMask_ == 0x0) + reqType_ = caRequestObject::VALUE; + else if (reqMask_ >= caRequestObject::VALUE && + reqMask_ < caRequestObject::STATUS) + reqType_ = caRequestObject::VALUE; + else if (reqMask_ >= caRequestObject::STATUS && + reqMask_ < caRequestObject::TIMESTMP) + reqType_ = caRequestObject::STATUS; + else if (reqMask_ >= caRequestObject::TIMESTMP && + reqMask_ < caRequestObject::GRINFO) + reqType_ = caRequestObject::TIMESTMP; + else if (reqMask_ >= caRequestObject::GRINFO && + reqMask_ < caRequestObject::CTRLINFO) + reqType_ = caRequestObject::GRINFO; + else + reqType_ = caRequestObject::CTRLINFO; +#ifdef _CDEV_DEBUG + printf("reqType_ is %d mask is 0x%x \n", reqType_, reqMask_); +#endif + return CDEV_SUCCESS; +} + +int +caRequestObject::getValueCbk (caChannel* channel, cdevTranObj *obj) +{ + int status; + chtype reqType; + + if (reqType_ > caRequestObject::TIMESTMP && channel->type_ != DBR_STRING) + reqType = dbf_type_to_DBR_CTRL (channel->type_); + else + reqType = dbf_type_to_DBR_TIME (channel->type_); + + status = ::ca_array_get_callback (reqType, channel->numElements_, + channel->cId_, + &(caRequestObject::defaultGetCallback), + (void *)obj); + if (status == ECA_NORMAL) + return CDEV_SUCCESS; + else { + // no callback will be called, remove transaction object + // otherwise group will block + cdevCallback *cbkobj = obj->userCallback_; + cdevRequestObject *reqobj = obj->reqObj_; + cdevData result; + + // T. Straumann: added check if user supplied a callbackFunction. + if (cbkobj && cbkobj->callbackFunction() ) // has callback + (*cbkobj->callbackFunction())(CDEV_IOFAILED, cbkobj->userarg(), + *reqobj, result); + delete obj; + return CDEV_IOFAILED; + } +} + +int +caRequestObject::send (cdevData& out, cdevData& result) +{ + return send (&out, &result); +} + +int +caRequestObject::send (cdevData* out, cdevData& result) +{ + return send (out, &result); +} + +int +caRequestObject::send (cdevData& out, cdevData* result) +{ + return send (&out, result); +} + +int +caRequestObject::send (cdevData* out, cdevData* result) +{ + int status = CDEV_ERROR; + + // check channel has been created or not + if (!channel_) + attachChannel (); + +#ifndef _CA_SYNC_CONN + int st = channel_->asyncConnect (); + if (st != CDEV_SUCCESS) + return st; +#endif + if (channel_->connected_){ + switch (action_){ + case caRequestObject::GET: + if (result == 0) + return CDEV_INVALIDARG; + { + cdevGroup getGrp (2, system_); + getGrp.start(); + sendNoBlock (out, result); + getGrp.end (); + // wait for maximum DEFAULT_TIMEOUT + getGrp.pend ((double)DEFAULT_TIMEOUT); + if (getGrp.allFinished ()) + status = CDEV_SUCCESS; + else + status = CDEV_TIMEOUT; + } + break; + case caRequestObject::SET: + case caRequestObject::PUT: + if (out == 0) + return CDEV_INVALIDARG; + if (readonly_) + return CDEV_INVALIDARG; + // synchronous set need group + { + cdevGroup setGrp (2, system_); + setGrp.start(); + sendNoBlock (out, result); + setGrp.end (); + // wait for maximum DEFAULT_TIMEOUT + setGrp.pend ((double)DEFAULT_TIMEOUT); + if (setGrp.allFinished ()) { + if (out->get (caService::CA_TAG_RESULT_CODE, &status)!= CDEV_SUCCESS) + status = CDEV_SUCCESS; + else + out->remove (caService::CA_TAG_RESULT_CODE); + } + else + status = CDEV_TIMEOUT; + } + break; + case caRequestObject::MONITOR_ON: + status = CDEV_INVALIDARG; + break; + case caRequestObject::MONITOR_OFF: + { + // remove every monitor callbacks + // remove a monitor object from all the channels + cdevCallback userCallback (0, 0); + channel_->removeCallback (&userCallback); + if (channel_->pinited_) { + caPchannel* pch = channel_->pchannels_; + + for (int i = 0; i < MAX_NUM_PCHANNELS; i++) { + if (pch[i].channel != 0) + pch[i].channel->removeCallback (&userCallback); + } + } + } + status = CDEV_SUCCESS; + break; + default: +#ifdef _CDEV_DEBUG + printf("Unsupported action message %s\n", action_); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject does not support message %d\n", + deviceName_, message_, action_); + status = CDEV_INVALIDARG; + break; + } + } + else{ +#ifdef _CDEV_DEBUG + printf("channel disconnected\n"); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject is not connected\n", + deviceName_, message_); + status = CDEV_NOTCONNECTED; + } + return status; +} + +void +caRequestObject::updateResult (int reqMask, int type, + struct dbr_time_short& value, + caMonData &result, + caMonData* cache) +{ + int *val = (int *)(result.value); + *val = value.value; + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + *(result.status) = (int)(value.status); + if (reqMask & (0x1 << i++)) + *(result.severity) = (int)(value.severity); + + cdev_TS_STAMP* tval = result.tstamp; + tval->secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval->nsec = value.stamp.nsec; + + // timeStmp skipped epics fault + unit tag + precision tag + i += 3; + + if (reqMask & (0x1 << i++)) + *(result.disphi) = *(cache->disphi); + if (reqMask & (0x1 << i++)) + *(result.displo) = *(cache->displo); + if (reqMask & (0x1 << i++)) + *(result.alrmhi) = *(cache->alrmhi); + if (reqMask & (0x1 << i++)) + *(result.alrmlo) = *(cache->alrmlo); + if (reqMask & (0x1 << i++)) + *(result.warnhi) = *(cache->warnhi); + if (reqMask & (0x1 << i++)) + *(result.warnlo) = *(cache->warnlo); + if (reqMask & (0x1 << i++)) + *(result.ctrlhi) = *(cache->ctrlhi); + if (reqMask & (0x1 << i++)) + *(result.ctrllo) = *(cache->ctrllo); + } +} + + +void +caRequestObject::updateResult (int reqMask, int type, + struct dbr_time_char& value, + caMonData &result, + caMonData* cache) +{ + BYTE *val = (BYTE *)(result.value); + *val = (BYTE)value.value; + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + *(result.status) = (int)(value.status); + if (reqMask & (0x1 << i++)) + *(result.severity) = (int)(value.severity); + + cdev_TS_STAMP* tval = result.tstamp; + tval->secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval->nsec = value.stamp.nsec; + + // timeStmp skipped epics fault + unit tag + precision + i += 3; + + if (reqMask & (0x1 << i++)) + *(result.disphi) = *(cache->disphi); + if (reqMask & (0x1 << i++)) + *(result.displo) = *(cache->displo); + if (reqMask & (0x1 << i++)) + *(result.alrmhi) = *(cache->alrmhi); + if (reqMask & (0x1 << i++)) + *(result.alrmlo) = *(cache->alrmlo); + if (reqMask & (0x1 << i++)) + *(result.warnhi) = *(cache->warnhi); + if (reqMask & (0x1 << i++)) + *(result.warnlo) = *(cache->warnlo); + if (reqMask & (0x1 << i++)) + *(result.ctrlhi) = *(cache->ctrlhi); + if (reqMask & (0x1 << i++)) + *(result.ctrllo) = *(cache->ctrllo); + } +} + +void +caRequestObject::updateResult (int reqMask, int type, + struct dbr_time_long& value, + caMonData &result, + caMonData* cache) +{ + int *val = (int *)(result.value); + *val = value.value; + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + *(result.status) = (int)(value.status); + if (reqMask & (0x1 << i++)) + *(result.severity) = (int)(value.severity); + + cdev_TS_STAMP* tval = result.tstamp; + tval->secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval->nsec = value.stamp.nsec; + + // timeStmp skipped epics fault + unit tag + precision + i += 3; + + if (reqMask & (0x1 << i++)) + *(result.disphi) = *(cache->disphi); + if (reqMask & (0x1 << i++)) + *(result.displo) = *(cache->displo); + if (reqMask & (0x1 << i++)) + *(result.alrmhi) = *(cache->alrmhi); + if (reqMask & (0x1 << i++)) + *(result.alrmlo) = *(cache->alrmlo); + if (reqMask & (0x1 << i++)) + *(result.warnhi) = *(cache->warnhi); + if (reqMask & (0x1 << i++)) + *(result.warnlo) = *(cache->warnlo); + if (reqMask & (0x1 << i++)) + *(result.ctrlhi) = *(cache->ctrlhi); + if (reqMask & (0x1 << i++)) + *(result.ctrllo) = *(cache->ctrllo); + } +} + +void +caRequestObject::updateResult (int reqMask, int type, + struct dbr_time_float& value, + caMonData &result, + caMonData* cache) +{ + float *val = (float *)(result.value); + *val = value.value; + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + *(result.status) = (int)(value.status); + if (reqMask & (0x1 << i++)) + *(result.severity) = (int)(value.severity); + + cdev_TS_STAMP* tval = result.tstamp; + tval->secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval->nsec = value.stamp.nsec; + + // timeStmp skipped epics fault + unit tag + i += 2; + + if (reqMask & (0x1 << i++)) + *(result.precision) = *(cache->precision); + if (reqMask & (0x1 << i++)) + *(result.disphi) = *(cache->disphi); + if (reqMask & (0x1 << i++)) + *(result.displo) = *(cache->displo); + if (reqMask & (0x1 << i++)) + *(result.alrmhi) = *(cache->alrmhi); + if (reqMask & (0x1 << i++)) + *(result.alrmlo) = *(cache->alrmlo); + if (reqMask & (0x1 << i++)) + *(result.warnhi) = *(cache->warnhi); + if (reqMask & (0x1 << i++)) + *(result.warnlo) = *(cache->warnlo); + if (reqMask & (0x1 << i++)) + *(result.ctrlhi) = *(cache->ctrlhi); + if (reqMask & (0x1 << i++)) + *(result.ctrllo) = *(cache->ctrllo); + } +} + +void +caRequestObject::updateResult (int reqMask, int type, + struct dbr_time_double& value, + caMonData &result, + caMonData* cache) +{ + double *val = (double *)(result.value); + *val = value.value; + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + *(result.status) = (int)(value.status); + if (reqMask & (0x1 << i++)) + *(result.severity) = (int)(value.severity); + + cdev_TS_STAMP* tval = result.tstamp; + tval->secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval->nsec = value.stamp.nsec; + + // timeStmp skipped epics fault + unit tag + i += 2; + + if (reqMask & (0x1 << i++)) + *(result.precision) = *(cache->precision); + if (reqMask & (0x1 << i++)) + *(result.disphi) = *(cache->disphi); + if (reqMask & (0x1 << i++)) + *(result.displo) = *(cache->displo); + if (reqMask & (0x1 << i++)) + *(result.alrmhi) = *(cache->alrmhi); + if (reqMask & (0x1 << i++)) + *(result.alrmlo) = *(cache->alrmlo); + if (reqMask & (0x1 << i++)) + *(result.warnhi) = *(cache->warnhi); + if (reqMask & (0x1 << i++)) + *(result.warnlo) = *(cache->warnlo); + if (reqMask & (0x1 << i++)) + *(result.ctrlhi) = *(cache->ctrlhi); + if (reqMask & (0x1 << i++)) + *(result.ctrllo) = *(cache->ctrllo); + } +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_string& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_short& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_char& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (short)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (short)value.severity); + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_long& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_float& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_STATUS, (int)value.status); + } + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_double& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_STATUS, (int)value.status); + } + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_time_enum& value, + cdevData &result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_STATUS, (int)value.status); + } + if (reqMask & (0x1 << i++)){ + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + } + } + + cdev_TS_STAMP tval; + tval.secPastEpoch = TS_EPOCH_SEC_PAST_1970 + + (unsigned long)value.stamp.secPastEpoch; + tval.nsec = value.stamp.nsec; + result.insert (caService::CA_TAG_TIME, tval); +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_short& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + // timeStmp skipped epics fault :- + i++; + i++; // no precision information + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_UNITS, value.units); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (int)value.upper_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (int)value.lower_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMHI, (int)value.upper_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMLO, (int)value.lower_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNHI, (int)value.upper_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNLO, (int)value.lower_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLHI, (int)value.upper_ctrl_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLLO, (int)value.lower_ctrl_limit); + } +} + + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_char& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (short)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (short)value.severity); + // timeStmp skipped epics fault :- + i++; + i++; // no precision information + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_UNITS, value.units); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (BYTE)value.upper_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (BYTE)value.lower_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMHI, (BYTE)value.upper_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMLO, (BYTE)value.lower_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNHI, (BYTE)value.upper_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNLO, (BYTE)value.lower_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLHI, (BYTE)value.upper_ctrl_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLLO, (BYTE)value.lower_ctrl_limit); + } +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_long& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + // timeStmp skipped epics fault :- + i++; + i++; // no precision information + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_UNITS, value.units); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (int)value.upper_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (int)value.lower_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMHI, (int)value.upper_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMLO, (int)value.lower_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNHI, (int)value.upper_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNLO, (int)value.lower_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLHI, (int)value.upper_ctrl_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLLO, (int)value.lower_ctrl_limit); + } +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_float& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + // timeStamp skipped epics fault :- + i++; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_PRECISION, value.precision); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_UNITS, value.units); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (float)value.upper_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (float)value.lower_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMHI, (float)value.upper_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMLO, (float)value.lower_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNHI,(float)value.upper_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNLO,(float)value.lower_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLHI, (float)value.upper_ctrl_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLLO, (float)value.lower_ctrl_limit); + } +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_double& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + // timeStmp skipped epics fault :- + i++; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_PRECISION, value.precision); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_UNITS, value.units); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (double)value.upper_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (double)value.lower_disp_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMHI, (double)value.upper_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_ALRMLO, (double)value.lower_alarm_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNHI,(double)value.upper_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_WRNLO,(double)value.lower_warning_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLHI, (double)value.upper_ctrl_limit); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_CTRLLO, (double)value.lower_ctrl_limit); + } +} + +void +caRequestObject::fillResult (int reqMask, int type, + struct dbr_ctrl_enum& value, + cdevData& result) +{ + if (type != caRequestObject::VALUE) { + int i = 1; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_STATUS, (int)value.status); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_SEVERITY, (int)value.severity); + // timeStmp skipped epics fault :- + i++; + // no precision information + i++; + // no units information + i++; + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPHI, (int)value.no_str - 1); + if (reqMask & (0x1 << i++)) + result.insert (caService::CA_TAG_DISPLO, (int)0); + } +} + +int +caRequestObject::sendNoBlock (cdevData& out, cdevData& result) +{ + return sendNoBlock (&out, &result); +} + +int +caRequestObject::sendNoBlock (cdevData& out, cdevData *result) +{ + return sendNoBlock (&out, result); +} + +int +caRequestObject::sendNoBlock (cdevData* out, cdevData& result) +{ + return sendNoBlock (out, &result); +} + +int +caRequestObject::sendNoBlock (cdevData* out, cdevData* result) +{ + if (!channel_) + attachChannel (); + + // first check whether this is deferred mode + if (deferExecution (out, result)) + return CDEV_SUCCESS; + + int status = CDEV_ERROR; + cdevTranObj *xobj = 0; + + switch (action_){ + case caRequestObject::GET: + if (result == 0) + return CDEV_INVALIDARG; + xobj = new cdevTranObj (&system_, this, result, 0); + // if channel is not connected, put all executions in the buffer + if (!channel_->connected_) { + bufferExecution (0, result, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = getValueCbk (channel_, xobj); + break; + case caRequestObject::SET: + case caRequestObject::PUT: + if (out == 0) + return CDEV_INVALIDARG; + if (readonly_) + return CDEV_INVALIDARG; + + // if channel is not connected, put all executions in the buffer + // must clone the data as the caller may delete it + if (!channel_->connected_) { + cdevData *cloned = new cdevData(*out); + xobj = new cdevTranObj (&system_, this, cloned, 0); + bufferExecution (cloned, result, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } else { + xobj = new cdevTranObj (&system_, this, out, 0); + } + status = setValueCbk (channel_, xobj); + break; + case caRequestObject::MONITOR_ON: + status = CDEV_INVALIDARG; + break; + case caRequestObject::MONITOR_OFF: + { + // remove every monitor callbacks + // remove a monitor object from all the channels + cdevCallback userCallback (0, 0); + channel_->removeCallback (&userCallback); + if (channel_->pinited_) { + caPchannel* pch = channel_->pchannels_; + + for (int i = 0; i < MAX_NUM_PCHANNELS; i++) { + if (pch[i].channel != 0) + pch[i].channel->removeCallback (&userCallback); + } + } + } + status = CDEV_SUCCESS; + break; + default: +#ifdef _CDEV_DEBUG + printf("Unsupported action message %s\n", action_); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject does not support message %d\n", + deviceName_, message_, action_); + status = CDEV_INVALIDARG; + break; + } + return status; +} + + +int +caRequestObject::execNoBlock (cdevData* out, cdevData* result, void* arg) +{ + // arg is a cdevTranObj + cdevTranObj* xobj = (cdevTranObj *)arg; + + // first check whether this is deferred mode + if (deferExecution (out, result)) { + delete xobj; + return CDEV_SUCCESS; + } + + int status = CDEV_ERROR; + + switch (action_){ + case caRequestObject::GET: + // if channel is not connected, put all executions in the buffer + if (!channel_->connected_) { + bufferExecution (0, result, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = getValueCbk (channel_, xobj); + break; + case caRequestObject::SET: + case caRequestObject::PUT: + // if channel is not connected, put all executions in the buffer + if (!channel_->connected_) { + cdevData *cloned = new cdevData(*out); + bufferExecution (cloned, result, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = setValueCbk (channel_, xobj); + break; + default: +#ifdef _CDEV_DEBUG + printf("Unsupported action message %s\n", action_); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject does not support message %d\n", + deviceName_, message_, action_); + status = CDEV_INVALIDARG; + break; + } + return status; +} + + +// T. Straumann: added 'putOnly' flag which causes +// ca_array_put() to be used instead of a ca_array_put_callback() + +int +caRequestObject::setValueCbk (caChannel* channel, cdevTranObj *xobj) +{ + int caStatus = -1; + int dataStatus = CDEV_SUCCESS; + int ioStatus = CDEV_SUCCESS; + + cdevData *out = xobj->resultData_; + cdevData result; + cdevCallback *cbkobj = xobj->userCallback_; + cdevRequestObject *reqObj = xobj->reqObj_; + cdevCallbackFunction userFcn; + int putOnly = (action_ == caRequestObject::PUT); + + if (dataMatch (*out, (int)channel->type_, + (int)(channel_->numElements_)) != CDEV_SUCCESS){ + // I have to delete this transaction object + // T. Straumann: added check if user supplied a callbackFunction. + if (cbkobj && (userFcn = cbkobj->callbackFunction()) ) { // has callback + (*userFcn)(CDEV_ERROR, cbkobj->userarg(), *reqObj, result); + } + delete xobj; + return CDEV_INVALIDARG; + } + + switch (channel->type_){ + case DBR_STRING: + if (channel->numElements_ == 1){ + char temp[MAX_STRING_SIZE]; + dataStatus = out->get (caService::CA_TAG_VALUE, temp, sizeof(temp)); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 has no ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_STRING, channel->numElements_, + channel->cId_, temp) + : ::ca_array_put_callback (DBR_STRING, channel->numElements_, + channel->cId_, temp, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_STRING, channel->numElements_, + channel->cId_, temp); +#endif + } + } + else { + char **temp = new char*[channel->numElements_]; + // each item will be allocated by the following + dataStatus = out->get (caService::CA_TAG_VALUE, temp); + int count = (int)channel->numElements_; + dataStatus = out->getElems (caService::CA_TAG_VALUE, (size_t *)&count); + if (dataStatus == CDEV_SUCCESS){ + char *cbuf = new char[channel->numElements_*MAX_STRING_SIZE]; + int j = 0; + for (int i = 0; i < channel->numElements_; i++){ + ::cdevStrncpy (&(cbuf[j]), temp[i], MAX_STRING_SIZE); + j += MAX_STRING_SIZE; + } + // epics 3.11 has no ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_STRING, channel->numElements_, + channel->cId_, cbuf) + : ::ca_array_put_callback (DBR_STRING, channel->numElements_, + channel->cId_, cbuf, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_STRING, channel->numElements_, + channel->cId_, cbuf); +#endif + for (i = 0; i < count; i++) + delete []temp[i]; + delete []temp; + delete []cbuf; + } + } + break; + case DBR_ENUM: + if (channel->numElements_ == 1){ + char temp[MAX_STRING_SIZE]; + char temp2[MAX_STRING_SIZE]; + int tind; + dataStatus = out->get (caService::CA_TAG_VALUE, temp, sizeof(temp)); + if (dataStatus == CDEV_SUCCESS){ + int i = 0; + sscanf (temp, "%d", &tind); + // if a caller supplies (only) an integer, it will be treated as an index + if (sscanf (temp, "%d%s", &tind, temp2) == 1 && + tind >= 0 && + tind < channel->accessBuffer_->cenmval.no_str) + i = tind; + else { + for (i = 0; i < channel->accessBuffer_->cenmval.no_str; i++) { + if (::strcmp (temp, channel->accessBuffer_->cenmval.strs[i]) == 0) + break; + } + if (i >= channel->accessBuffer_->cenmval.no_str){ +#ifdef _CDEV_DEBUG + printf("Unmatched string %s to enum record\n", temp); + printf("The following are the string values\n"); + for (i = 0; i < channel->accessBuffer_->cenmval.no_str; i++) + printf(" %s ",channel->accessBuffer_->cenmval.strs[i]); + printf("\n"); +#endif + return CDEV_INVALIDARG; + } + } + short desiredIndex = i; +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_ENUM, channel->numElements_, + channel->cId_, &desiredIndex) + : ::ca_array_put_callback (DBR_ENUM, channel->numElements_, + channel->cId_, &desiredIndex, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_ENUM, channel->numElements_, + channel->cId_, &desiredIndex); +#endif + } + } + else { +#ifdef _CDEV_DEBUG + printf ("Multiple elements of DBR_ENUM is not supported in CDEV\n"); +#endif + return CDEV_INVALIDARG; + } + break; + case DBR_SHORT: + if (channel->numElements_ == 1){ + int value; + dataStatus = out->get (caService::CA_TAG_VALUE, &value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, &value) + : ::ca_array_put_callback (DBR_LONG, channel->numElements_, + channel->cId_, &value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, &value); +#endif + } + } + else{ + int *value = new int[channel->numElements_]; + dataStatus = out->get (caService::CA_TAG_VALUE, value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, value) + : ::ca_array_put_callback (DBR_LONG, channel->numElements_, + channel->cId_, value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, value); +#endif + delete []value; + } + } + break; + case DBR_CHAR: + if (channel->numElements_ == 1){ + BYTE value; + dataStatus = out->get (caService::CA_TAG_VALUE, &value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_CHAR, channel->numElements_, + channel->cId_, &value) + : ::ca_array_put_callback (DBR_CHAR, channel->numElements_, + channel->cId_, &value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_CHAR, channel->numElements_, + channel->cId_, &value); +#endif + } + } + else{ + BYTE *value = new BYTE[channel->numElements_]; + dataStatus = out->get (caService::CA_TAG_VALUE, value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_CHAR, channel->numElements_, + channel->cId_, value) + : ::ca_array_put_callback (DBR_CHAR, channel->numElements_, + channel->cId_, value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_CHAR, channel->numElements_, + channel->cId_, value); +#endif + delete []value; + } + } + break; + case DBR_LONG: + if (channel->numElements_ == 1){ + int value; + dataStatus = out->get (caService::CA_TAG_VALUE, &value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, &value) + : ::ca_array_put_callback (DBR_LONG, channel->numElements_, + channel->cId_, &value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, &value); +#endif + } + } + else { + int *value = new int[channel->numElements_]; + dataStatus = out->get (caService::CA_TAG_VALUE, value); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have ca_array_put_callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, value) + : ::ca_array_put_callback (DBR_LONG, channel->numElements_, + channel->cId_, value, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_LONG, channel->numElements_, + channel->cId_, value); +#endif + delete []value; + } + } + break; + case DBR_FLOAT: + case DBR_DOUBLE: + if (channel->numElements_ == 1) { + double fval; + dataStatus = out->get (caService::CA_TAG_VALUE, &fval); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have put callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_DOUBLE, channel->numElements_, + channel->cId_, &fval) + : ::ca_array_put_callback(DBR_DOUBLE, channel->numElements_, + channel->cId_, &fval, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_DOUBLE, channel->numElements_, + channel->cId_, &fval); +#endif + } + } + else { + double *fval = new double[channel->numElements_]; + dataStatus = out->get (caService::CA_TAG_VALUE, fval); + if (dataStatus == CDEV_SUCCESS){ + // epics 3.11 does not have put callback +#ifdef _EPICS_3_12 + caStatus = putOnly ? ::ca_array_put (DBR_DOUBLE, channel->numElements_, + channel->cId_, fval) + : ::ca_array_put_callback(DBR_DOUBLE, channel->numElements_, + channel->cId_, fval, + &(caRequestObject::defaultSetCallback), + (void *)xobj); +#else + caStatus = ::ca_array_put (DBR_DOUBLE, channel->numElements_, + channel->cId_, fval); +#endif + delete []fval; + } + } + break; + default: +#ifdef _CDEV_DEBUG + printf("unsupported data type \n"); +#endif + return CDEV_INVALIDARG; + // Break not needed because of return statement + // break; + } + // check data status first + if (dataStatus != CDEV_SUCCESS) { + // remove transaction objecyt so a group will not block + if (cbkobj && (userFcn = cbkobj->callbackFunction()) ) { + (*userFcn)(dataStatus, cbkobj->userarg(), *reqObj, result); + + dataStatus = CDEV_SUCCESS; // problem now handled, no more to report + } + else { + // use user outbound data as result code + out->insert (caService::CA_TAG_RESULT_CODE, dataStatus); + } + delete xobj; + return dataStatus; + } + + // check channel access status + if (caStatus != ECA_NORMAL){ +#ifdef _CDEV_DEBUG + printf("ca_array_put_callback failed\n"); +#endif + // remove transaction objecyt so a group will not block + if (cbkobj && (userFcn = cbkobj->callbackFunction()) ) { + (*userFcn)(CDEV_IOFAILED, cbkobj->userarg(), *reqObj, result); + + ioStatus = CDEV_SUCCESS; // problem now handled, no more to report + } + else { + // use user outbound data as result code + out->insert (caService::CA_TAG_RESULT_CODE, CDEV_IOFAILED); + ioStatus = CDEV_IOFAILED; + } + delete xobj; + return ioStatus; + } + + // trasaction object will be removed from default callback function + // for epics 3.11 I have no idea when put will finish + // so I have to delete this transaction object +#ifdef _EPICS_3_12 + if (putOnly) { +#endif + // so what I do, just call callback :--- + // T. Straumann: added check if user supplied a callbackFunction. + if (cbkobj && (userFcn = cbkobj->callbackFunction()) ) { + (*userFcn)(CDEV_SUCCESS, cbkobj->userarg(), *reqObj, result); + } + else { + // use user outbound data as result code + out->insert (caService::CA_TAG_RESULT_CODE, CDEV_SUCCESS); + } + + delete xobj; +#ifdef _EPICS_3_12 + } +#endif + return CDEV_SUCCESS; +} +int +caRequestObject::sendCallback (cdevData& out, cdevCallback& callback) +{ + return sendCallback (&out, callback); +} + +int +caRequestObject::sendCallback (cdevData* out, cdevCallback& userCallback) +{ + if (!channel_) + attachChannel (); + + if (deferExecution (out, &userCallback)) + return CDEV_SUCCESS; + + int status = CDEV_ERROR; + cdevTranObj *xobj = 0; + caMonObj* obj = 0; + + // copy userCallback into the following callback, which will free + // user from taking care cdevCallback object. + // Note: cdevCallback's new operator is an overloaded operator + cdevCallback* callback = 0; + + switch (action_){ + case caRequestObject::GET: + callback = new cdevCallback (userCallback); + xobj = new cdevTranObj (&system_, this, 0, callback); + if (!channel_->connected_) { + bufferExecution (0, callback, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = getValueCbk (channel_, xobj); + break; + case caRequestObject::SET: + case caRequestObject::PUT: + if (out == 0) + return CDEV_INVALIDARG; + if (readonly_) + return CDEV_INVALIDARG; + callback = new cdevCallback (userCallback); + + // if deferred execution, clone the data as caller may delete it + if (!channel_->connected_) { + cdevData *cloned = new cdevData(*out); + xobj = new cdevTranObj (&system_, this, cloned, callback); + bufferExecution (cloned, callback, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } else { + xobj = new cdevTranObj (&system_, this, out, callback); + } + status = setValueCbk (channel_, xobj); + break; + case caRequestObject::MONITOR_ON: + { + // copy user callback + callback = new cdevCallback (userCallback); + // create a new transaction object + xobj = new cdevTranObj (&system_, this, 0, callback); + + //================================================== + // if there is one callback is the same as the new + // one user wants, discard the new one + //================================================= + if (channel_->hasSameCallback (*callback)) { + delete xobj; + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s dislikes the same callbacks\n", + deviceName_, message_); + return CDEV_ERROR; + } + + // if channel is not connected, buffer this up + if (!channel_->connected_) { + bufferExecution (0, callback, (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + + //================================================== + // if this requests has the same context i.e. + // or the same req type and request mask, use the + // same channel access event Id to get network + // response from the server. + //================================================= + caMonObj* eobj = 0; + if ((eobj = channel_->hasSameCallingCxt (reqType_, reqMask_)) != 0) { + // create new callback object and add to the list + caMonCbk* cbk = new caMonCbk (*xobj->userCallback_, xobj->resultData_); + eobj->addCallback (cbk); + // immediately call user callback now + eobj->callCallback (cbk); + + // call monitor properties which will add more monitor + // objects to the appropriate property channels + addCbksToPChannels (channel_, *xobj->userCallback_, + xobj->resultData_); + delete xobj; + + return CDEV_SUCCESS; + } + // get monitor object from transaction object + // and disable the transaction object from deleting + // the callback object + obj = new caMonObj (*xobj); + // set up associated arguments + obj->setMonitorInfo (caService::CA_TAG_VALUE, + CDEV_SUCCESS, + channel_, + reqType_, + reqMask_); + xobj->disableDeleteCbk (); + + monitorProperties (channel_, obj); + status = monitorValue (channel_, obj); + } + break; + case caRequestObject::MONITOR_OFF: + { + // remove a monitor object from all the channels + // monitor objects' destructor will call all monitor + // monitor callbacks to denote caller that monitor + // is over + channel_->removeCallback (&userCallback); + if (channel_->pinited_) { + caPchannel* pch = channel_->pchannels_; + + for (int i = 0; i < MAX_NUM_PCHANNELS; i++) { + if (pch[i].channel != 0) + pch[i].channel->removeCallback (&userCallback); + } + } + } + status = CDEV_SUCCESS; + break; + default: +#ifdef _CDEV_DEBUG + printf("Unsupported action message %s\n", action_); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject does not support message %d\n", + deviceName_, message_, action_); + status = CDEV_INVALIDARG; + break; + } + return status; +} + + +int +caRequestObject::execCallback (cdevData* out, + cdevCallback& userCallback, + void* arg) +{ + // arg is actually a transcation object + cdevTranObj* xobj = (cdevTranObj *)arg; + if (deferExecution (out, &userCallback)) { + // the above code will make copy of user callback, so it is safe + // to delete xobj that has userCallback in it here + delete xobj; + return CDEV_SUCCESS; + } + + int status = CDEV_ERROR; + caMonObj* obj = 0; + + // copy userCallback into the following callback, which will free + // user from taking care cdevCallback object. + // Note: cdevCallback's new operator is an overloaded operator + cdevCallback* callback = 0; + + switch (action_){ + case caRequestObject::GET: + if (!channel_->connected_) { + bufferExecution (0, xobj->userCallback_, + (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = getValueCbk (channel_, xobj); + break; + case caRequestObject::SET: + case caRequestObject::PUT: + if (!channel_->connected_) { + cdevData *cloned = new cdevData(*out); + bufferExecution (cloned, xobj->userCallback_, + (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + status = setValueCbk (channel_, xobj); + break; + case caRequestObject::MONITOR_ON: + { + if (!channel_->connected_) { + bufferExecution (0, xobj->userCallback_, + (cdevGroup *)channel_->egrp_, + (void *)xobj); + return CDEV_SUCCESS; + } + + //================================================== + // if this requests has the same context i.e. + // or the same req type and request mask, use the + // same channel access event Id to get network + // response from the server. + //================================================= + caMonObj* eobj = 0; + if ((eobj = channel_->hasSameCallingCxt (reqType_, reqMask_)) != 0) { + // create new callback object and add to the list + caMonCbk* cbk = new caMonCbk (*xobj->userCallback_, xobj->resultData_); + eobj->addCallback (cbk); + // immediately call user callback now + eobj->callCallback (cbk); + + // call monitor properties which will add more monitor + // objects to the appropriate property channels + addCbksToPChannels (channel_, *xobj->userCallback_, + xobj->resultData_); + delete xobj; + + return CDEV_SUCCESS; + } + // get monitor object from transaction object + // and disable the transaction object from deleting + // the callback object + obj = new caMonObj (*xobj); + // set up associated arguments + obj->setMonitorInfo (caService::CA_TAG_VALUE, + CDEV_SUCCESS, + channel_, + reqType_, + reqMask_); + xobj->disableDeleteCbk (); + + monitorProperties (channel_, obj); + status = monitorValue (channel_, obj); + } + break; + default: +#ifdef _CDEV_DEBUG + printf("Unsupported action message %s\n", action_); +#endif + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s requestObject does not support message %d\n", + deviceName_, message_, action_); + status = CDEV_INVALIDARG; + break; + } + return status; +} + +void +caRequestObject::initPropChannels (caPchannel* pch) +{ + cdevData& cxt = getContext (); + int val; + char svcData[64]; + caService* svc = (caService *)service_; + + // scan through all property channels to establish connection if necessary + for (int i = 2; i < MAX_NUM_PCHANNELS; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS) + // caller specify a trigger or I am going to setup channel + // for those properties which are not changed rapidly + if (val == 2 || i >= 2) { + // construct channel access record.attr + ::strcpy (svcData, device_->name()); + ::strcat (svcData, "."); + ::strcat (svcData, svc->attr (pch[i].tag)); + + if (pch[i].channel == 0) { +#ifdef _CDEV_DEBUG + printf ("property channel %s is not created, do it now\n", svcData); +#endif + caChannel* ch = 0; + + if (svc->channelPtr (svcData, ch) != 0) { + // the channel has not created yet +#ifdef _CDEV_DEBUG + printf("property channel %s not created \n", svcData); +#endif + ch = new caChannel (svcData, svc); + svc->addChannel (svcData, ch); + ch->count_ = 1; + } + else{ +#ifdef _CDEV_DEBUG + printf("property channel %s created \n", svcData); +#endif + ch->count_ += 1; +#ifdef _CA_SYNC_CONN + if (!ch->connected_){ // channel not connected + channel_->connect (); + } +#endif + } + pch[i].channel = ch; + } + } + } +} + +void +caRequestObject::initPropChannels (caChannel* parent) +{ + cdevData& cxt = getContext (); + int val; + char svcData[64]; + caService* svc = (caService *)service_; + + caPchannel* pch = parent->pchannels_; + + if (!pch) + return; + + // scan through all property channels to establish connection if necessary + for (int i = 2; i < MAX_NUM_PCHANNELS; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS) + // caller specify a trigger or I am going to setup channel + // for those properties which are not changed rapidly + if (val == 2 || i >= 2) { + // construct channel access record.attr + ::strcpy (svcData, device_->name()); + ::strcat (svcData, "."); + ::strcat (svcData, svc->attr (pch[i].tag)); + + if (pch[i].channel == 0) { +#ifdef _CDEV_DEBUG + printf ("property channel %s is not created, do it now\n", svcData); +#endif + caChannel* ch = 0; + + if (svc->channelPtr (svcData, ch) != 0) { + // the channel has not created yet +#ifdef _CDEV_DEBUG + printf("property channel %s not created \n", ch->channelName_); +#endif + ch = new caChannel (svcData, svc); + svc->addChannel (svcData, ch); + ch->count_ = 1; + } + else{ +#ifdef _CDEV_DEBUG + printf("property channel %s created \n", svcData); +#endif + ch->count_ += 1; +#ifdef _CA_SYNC_CONN + if (!ch->connected_){ // channel not connected + channel_->connect (); + } +#endif + } + pch[i].channel = ch; + } + } + } +} + +void +caRequestObject::monitorProperties (caChannel* parent, caMonObj *obj) +{ + cdevData& cxt = getContext (); + int val; + char svcData[64]; + caService* svc = (caService *)service_; + + // get property channel pointer + caPchannel* pch = parent->pchannels_; + + if (!pch) /* no property channel, return */ + return; + + // scan through all property channels to establish connection if necessary + for (int i = 2; i < MAX_NUM_PCHANNELS; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS) + // caller specify a trigger or I am going to setup channel + // for those properties which are not changed rapidly + if (val == 2 || i >= 2) { + // construct channel access record.attr + if (pch[i].channel && pch[i].channel->connected_){ + if (!pch[i].monitored) { + caMonObj *newobj = new caMonObj (*obj, obj->cbks_->cbk_, + obj->cbks_->out_); + newobj->tobj_ = 0; + newobj->tag_ = pch[i].tag; + newobj->cbkStatus_ = CDEV_SUCCESS; + newobj->channel_ = pch[i].channel; + + // sep-27-1995 -- Jie chen + // if this context value == 1, we cache its value instead of + // calling user callback directly + if (val == 1) + newobj->cbks_->enableCache (); + + if (monitorPropValue (pch[i].channel, newobj) == CDEV_SUCCESS) { + pch[i].channel->addMonitorObj (newobj); + pch[i].monitored = 1; + } + else { + delete pch[i].channel; + pch[i].channel = 0; + } + } + else { + // get first monitor object pointer from this property + // channel: it should never return 0 + caMonObj* fobj = pch[i].channel->firstMonitorObj (); + if (!fobj) { + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s has bad property channel\n", + deviceName_, message_); + return; + } + + // create a new callback object with dupliate user callback + // information in it + caMonCbk* cbkobj = new caMonCbk (*obj->cbks_->cbk_, + obj->cbks_->out_); + if (val == 1) + cbkobj->enableCache (); + + fobj->addCallback (cbkobj); + } + } + } + } +} + + +void +caRequestObject::addCbksToPChannels (caChannel* parent, + cdevCallback& cbk, + cdevData* out) +{ + cdevData& cxt = getContext (); + int val; + char svcData[64]; + caService* svc = (caService *)service_; + + // get property channel pointer + caPchannel* pch = parent->pchannels_; + if (!pch) + return; + + // scan through all property channels to establish connection if necessary + for (int i = 2; i < MAX_NUM_PCHANNELS; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS) + // caller specify a trigger or I am going to setup channel + // for those properties which are not changed rapidly + + if ((val == 2 || i >= 2) && pch[i].channel != 0 && + pch[i].channel->connected_ && pch[i].monitored) { +#ifdef _CDEV_DEBUG + printf ("property channel %s is created already\n", svcData); +#endif + // get first monitor object pointer from this property + // channel: it should never return 0 + caMonObj* fobj = pch[i].channel->firstMonitorObj (); + if (!fobj) { + system_.reportError (CDEV_SEVERITY_ERROR, deviceName_, this, + "%s %s has bad property channel\n", + deviceName_, message_); + return; + } + + // create a new callback object with dupliate user callback + // information in it + caMonCbk* cbkobj = new caMonCbk (cbk, out); + + if (val == 1) + cbkobj->enableCache (); + else + // call callbak right away + fobj->callCallback (cbkobj); + + fobj->addCallback (cbkobj); + } + } +} + +int +caRequestObject::monitorValue (caChannel* channel, caMonObj *xobj) +{ + // check value context + cdevData& cxt = getContext (); + int val; + int mask = DBE_VALUE | DBE_ALARM; + + if (cxt.get (caService::CA_TAG_VALUE, &val) == CDEV_SUCCESS) { + if (val == 0) // if 0: no monitor on value + mask = 0; + } + + // get property channel pointer + caPchannel* pch = channel->pchannels_; + + if (pch) { + // scan first two property channels to change monitor mask if necessary + for (int i = 0; i < 2; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS){ + if (val >=2) + mask = mask | DBE_ALARM; + } + } + } + + if (mask == 0) { // we have nothing to do + // no callback will be called, remove transaction object + // otherwise group will block + cdevCallback *cbkobj = xobj->cbks_->cbk_; + cdevRequestObject *reqobj = xobj->reqObj_; + cdevData result; + + cbkobj->fireCallback (CDEV_IOFAILED, cbkobj->userarg (), + *reqobj, result, 0); + + if (xobj->tobj_) { + delete xobj->tobj_; + xobj->tobj_ = 0; + } + delete xobj; + return CDEV_IOFAILED; + } + + int status, caStatus; + int reqType; + // get everything of status and severity and timestamp + reqType = (int)dbf_type_to_DBR_TIME (channel->type_); + + caStatus = ::ca_add_masked_array_event (reqType, + channel->numElements_, + channel->cId_, + &(caRequestObject::callMonitorCallback), + (void *)(xobj), + 0, 0, 0, + &(xobj->mEvId_), + mask); + if (caStatus != ECA_NORMAL) { + // no callback will be called, remove transaction object + // otherwise group will block + cdevCallback *cbkobj = xobj->cbks_->cbk_; + cdevRequestObject *reqobj = xobj->reqObj_; + cdevData result; + + cbkobj->fireCallback (CDEV_IOFAILED, cbkobj->userarg (), + *reqobj, result, 0); + if (xobj->tobj_) { + delete xobj->tobj_; + xobj->tobj_ = 0; + } + delete xobj; + status = CDEV_IOFAILED; + } + else + status = CDEV_SUCCESS; + + return status; +} + +int +caRequestObject::monitorPropValue (caChannel* channel, caMonObj *xobj) +{ + int status = ::ca_add_masked_array_event (channel->type_, + channel->numElements_, + channel->cId_, + &(caRequestObject::callPropMonitorCallback), + (void *)(xobj), + 0, 0, 0, + &(xobj->mEvId_), + DBE_VALUE); + if (status != ECA_NORMAL) + return CDEV_IOFAILED; + else + return CDEV_SUCCESS; +} + +void +caRequestObject::convertData (int chtype, + int tag, + int reqMask, + int reqType, + struct event_handler_args& args, + cdevData& resData) +{ + switch (chtype){ + case DBR_STRING: + { + struct dbr_time_string *retValue = 0; + retValue = (struct dbr_time_string *)args.dbr; + if (args.count == 1){ + resData.insert (tag, retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else{ + char **insertBuf = new char* [args.count]; + insertBuf[0] = new char[MAX_STRING_SIZE]; + ::cdevStrncpy (insertBuf[0], retValue->value, MAX_STRING_SIZE); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_string); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = new char[MAX_STRING_SIZE]; + ::cdevStrncpy (insertBuf[i], &(buffer[j]), MAX_STRING_SIZE); + j += MAX_STRING_SIZE; + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + + for (i = 0; i < args.count; i++) + delete []insertBuf[i]; + delete []insertBuf; + } + } + break; + case DBR_ENUM: + if (args.count == 1){ + if (reqType > caRequestObject::TIMESTMP){ + struct dbr_ctrl_enum *retValue = 0; + retValue = (struct dbr_ctrl_enum *)args.dbr; + if (reqType >= caRequestObject::GRINFO) { + int i = 0; + // we want display information + char **strs = 0; + if (retValue->no_str > 0) { + strs = new char*[retValue->no_str]; + for (i = 0; i < retValue->no_str; i++) { + strs[i] = new char[strlen (retValue->strs[i]) + 1]; + strcpy (strs[i], retValue->strs[i]); + } + } + resData.insert (tag, strs, retValue->no_str); + + // free memory + for (i = 0; i < retValue->no_str; i++) + delete []strs[i]; + delete []strs; + } + else { + unsigned short index = retValue->value; + // If this string is a null string, we return index value + if (!strlen (retValue->strs[index])) + resData.insert (tag, index); + else + resData.insert (tag, retValue->strs[index]); + } + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else{ + struct dbr_time_enum *retValue = 0; + retValue = (struct dbr_time_enum *)args.dbr; + // since dbr_time_enum has no string in it's structure + // it is impossible to find corresponding strings + resData.insert (tag, retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + } + else{ +#ifdef _CDEV_DEBUG + printf ("Multiple elements of DBR_ENUM is not supported in CDEV\n"); +#endif + } + break; + case DBR_SHORT: + if (reqType > caRequestObject::TIMESTMP){ + struct dbr_ctrl_short *retValue = 0; + retValue = (struct dbr_ctrl_short *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (int)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + int* insertBuf = new int[args.count]; + insertBuf[0] = (int)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_ctrl_short); + short tmp; + for (int i = 1; i < args.count; i++){ + tmp = *(short *)&(buffer[j]); + insertBuf[i] = (int)tmp; + j += sizeof (short); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + + delete []insertBuf; + } + } + else{ + struct dbr_time_short *retValue = 0; + retValue = (struct dbr_time_short *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (int)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + int* insertBuf = new int[args.count]; + insertBuf[0] = (int)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_short); + short tmp; + for (int i = 1; i < args.count; i++){ + tmp = *(short *)&(buffer[j]); + insertBuf[i] = (int)tmp; + j += sizeof (short); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + break; + case DBR_CHAR: + if (reqType > caRequestObject::TIMESTMP){ + struct dbr_ctrl_char *retValue = 0; + retValue = (struct dbr_ctrl_char *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (BYTE)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + BYTE* insertBuf = new BYTE[args.count]; + insertBuf[0] = (BYTE)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_ctrl_char); + char tmp; + for (int i = 1; i < args.count; i++){ + tmp = *(char *)&(buffer[j]); + insertBuf[i] = (BYTE)tmp; + j += sizeof (char); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + + delete []insertBuf; + } + } + else{ + struct dbr_time_char *retValue = 0; + retValue = (struct dbr_time_char *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (BYTE)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + BYTE* insertBuf = new BYTE[args.count]; + insertBuf[0] = (BYTE)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_char); + char tmp; + for (int i = 1; i < args.count; i++){ + tmp = *(char *)&(buffer[j]); + insertBuf[i] = (BYTE)tmp; + j += sizeof (char); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + break; + case DBR_LONG: + if (reqType > caRequestObject::TIMESTMP){ + struct dbr_ctrl_long *retValue = 0; + retValue = (struct dbr_ctrl_long *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (int)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + int* insertBuf = new int[args.count]; + insertBuf[0] = (int)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_ctrl_long); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(int *)&(buffer[j]); + j += sizeof (long); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + else{ + struct dbr_time_long *retValue = 0; + retValue = (struct dbr_time_long *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (int)(retValue->value)); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + int* insertBuf = new int[args.count]; + insertBuf[0] = (int)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_long); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(int *)&(buffer[j]); + j += sizeof (long); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + break; + case DBR_FLOAT: + if (reqType > caRequestObject::TIMESTMP){ + struct dbr_ctrl_float *retValue = 0; + retValue = (struct dbr_ctrl_float *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (float)retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else{ + float* insertBuf = new float[args.count]; + insertBuf[0] = (float)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_ctrl_float); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(float *)&(buffer[j]); + j += sizeof (float); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + else{ + struct dbr_time_float *retValue = 0; + retValue = (struct dbr_time_float *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (float)retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + float* insertBuf = new float[args.count]; + insertBuf[0] = (float)(retValue->value); + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_float); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(float *)&(buffer[j]); + j += sizeof (float); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + break; + case DBR_DOUBLE: + if (reqType > caRequestObject::TIMESTMP){ + struct dbr_ctrl_double *retValue = 0; + retValue = (struct dbr_ctrl_double *)args.dbr; + if (args.count == 1){ + resData.insert (tag, (double)retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + double* insertBuf = new double[args.count]; + insertBuf[0] = (double)retValue->value; + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_ctrl_double); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(double *)&(buffer[j]); + j += sizeof (double); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + else{ + struct dbr_time_double *retValue = 0; + retValue = (struct dbr_time_double *)args.dbr; + if (args.count == 1) { + resData.insert (tag, (double)retValue->value); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + } + else { + double* insertBuf = new double[args.count]; + insertBuf[0] = (double)retValue->value; + + char *buffer = (char *)args.dbr; + int j = sizeof (struct dbr_time_double); + for (int i = 1; i < args.count; i++){ + insertBuf[i] = *(double *)&(buffer[j]); + j += sizeof (double); + } + resData.insert (tag, insertBuf, (int)args.count); + caRequestObject::fillResult (reqMask, reqType, *retValue, resData); + delete []insertBuf; + } + } + break; + default: + printf("Fatal Error: Unsupported data type\n"); + break; + } +} + +void +caRequestObject::defaultGetCallback (struct event_handler_args args) +{ +#ifdef _CDEV_DEBUG + printf("get callback called\n"); +#endif + cdevTranObj *xobj = (cdevTranObj *)args.usr; + + if (xobj->isTrash ()) { + // this transaction object is deleted already + delete xobj; + return; + } + + //========================================================= + // One must know the requestObject from transaction + // is caRequestObject. So no vialation here + //========================================================= + caRequestObject *reqObj = (caRequestObject *)xobj->reqObj_; + //========================================================= + // Check data type + //========================================================= + cdevData *resData = xobj->resultData_; + cdevCallback *cbkobj = xobj->userCallback_; + cdevData result; + + if (resData) // send no block + resData->remove(); + else // send callback + resData = &result; + + if (args.count > 0 && args.dbr != 0) { + // convert data from channel access type to cdevData type + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqObj->reqMask_, + reqObj->reqType_, + args, *resData); + + // T. Straumann: added check if user supplied a callbackFunction. + if (cbkobj && cbkobj->callbackFunction() ) { // from sendCallback + (*cbkobj->callbackFunction ()) (CDEV_SUCCESS, cbkobj->userarg (), + *reqObj, result); + } + } + else { + // T. Straumann: added check if user supplied a callbackFunction. + if (cbkobj && cbkobj->callbackFunction() ) { // called from sendCallback + (*cbkobj->callbackFunction ()) (CDEV_IOFAILED, cbkobj->userarg (), + *reqObj, result); + } + } + delete xobj; +} + +void +caRequestObject::defaultSetCallback (struct event_handler_args args) +{ + // for now just remove transaction object +#ifdef _CDEV_DEBUG + printf("default set callback called\n"); +#endif + int status = CDEV_SUCCESS; + + cdevTranObj *xobj = (cdevTranObj *)args.usr; + + if (xobj->isTrash ()) { + // this transaction object is deleted already + delete xobj; + return; + } + + //========================================================= + // One must know the requestObject from transaction + // is caRequestObject. So no vialation here + //========================================================= + caRequestObject *reqObj = (caRequestObject *)xobj->reqObj_; + cdevData result; + + cdevCallback *cbkobj = xobj->userCallback_; + // T. Straumann: added check if user supplied a callbackFunction. + if (cbkobj && cbkobj->callbackFunction() ) { // from sendCallback + if (args.status != ECA_NORMAL) + status = CDEV_IOFAILED; + (*cbkobj->callbackFunction())(status, cbkobj->userarg(), + *reqObj, result); + } + delete xobj; +} + +void +caRequestObject::callPropMonitorCallback (struct event_handler_args args) +{ + caMonObj *xobj = (caMonObj *)args.usr; + caChannel* ch = xobj->channel_; + + // get tag value associated with this channel + int tagval = xobj->tag_; + // get callback status value assocaited with this channel + int cbkst = xobj->cbkStatus_; + + int status = CDEV_ERROR; + + if (args.count > 0 && args.dbr != 0) { + // clean out old information + xobj->cache_.remove (); + switch (ch->type_){ + case DBR_STRING: + { + char *retValue; + retValue = (char *)args.dbr; + xobj->cache_.insert (tagval, (char *)(retValue)); + } + break; + case DBR_ENUM: + { + // get index value + unsigned short index = *(unsigned short *)args.dbr; + if (ch->accessBuffer_) + status = xobj->cache_.insert (tagval, + ch->accessBuffer_->cenmval.strs[index]); + else + status = xobj->cache_.insert (tagval, index); + } + break; + case DBR_SHORT: + { + short tmp = *(short *)(args.dbr); + status = xobj->cache_.insert (tagval, (int)tmp); + } + break; + case DBR_CHAR: + { + BYTE tmp = *(BYTE *)(args.dbr); + status = xobj->cache_.insert (tagval, (BYTE)tmp); + } + break; + case DBR_LONG: + { + int tmp = *(int *)(args.dbr); + status = xobj->cache_.insert (tagval, tmp); + } + break; + case DBR_FLOAT: + { + float tmp = *(float *)(args.dbr); + status = xobj->cache_.insert (tagval, tmp); + } + break; + case DBR_DOUBLE: + { + double tmp = *(double *)(args.dbr); + status = xobj->cache_.insert (tagval, tmp); + } + break; + default: + cdevSystem::defaultSystem().reportError + (CDEV_SEVERITY_ERROR, + "caRequestObject", NULL, + "Unsupported data type %d\n", + ch->type_); + break; + } + } + + if (status == CDEV_SUCCESS) { + updatePropCache ((caRequestObject *)xobj->reqObj_, + tagval, + xobj->cache_); + xobj->callCallbacks (cbkst, xobj->reqObj_, xobj->cache_); + } + else + xobj->callCallbacks (CDEV_ERROR, xobj->reqObj_, xobj->cache_); +} + +void +caRequestObject::callMonitorCallback (struct event_handler_args args) +{ + static caRequestObject *reqObj = 0; + caMonObj *xobj = (caMonObj *)args.usr; + + // get request object + reqObj = (caRequestObject *)xobj->reqObj_; + // get channel object + caChannel* ch = xobj->channel_; + + // get tag value associated with this channel + int tagval = xobj->tag_; + // get callback status value assocaited with this channel + int cbkst = xobj->cbkStatus_; + + if (xobj->tobj_ != 0) { + // remove transaction object so that pend will give back right result + if (xobj->tobj_->isTrash ()) { + // if this transaction object is trash, return + delete xobj->tobj_; + xobj->tobj_ = 0; + return; + } + else { + delete xobj->tobj_; + xobj->tobj_ = 0; + } + // create monitor object from trasanction object + reqObj->channel_->addMonitorObj (xobj); + } + + if (args.count > 0 && args.dbr != 0) { + // get type and mask + int reqType = xobj->reqType_; + int reqMask = xobj->reqMask_; + switch (reqObj->channel_->type_){ + case DBR_STRING: + // since monitor value always use DBR_TIME strcuture + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + break; + case DBR_ENUM: + { + // since monitor value always use DBR_TIME strcuture which + // has no no_str and str information, the corresponding + // channel information about no_str and strs are used here + xobj->cache_.remove (); + struct dbr_time_enum *retValue = 0; + retValue = (struct dbr_time_enum *)args.dbr; + unsigned short index = retValue->value; + + if (ch->accessBuffer_ && ch->accessBuffer_->cenmval.no_str && + index < ch->accessBuffer_->cenmval.no_str && + strlen (ch->accessBuffer_->cenmval.strs[index])) + xobj->cache_.insert (caService::CA_TAG_VALUE, + ch->accessBuffer_->cenmval.strs[index]); + else + xobj->cache_.insert (caService::CA_TAG_VALUE, index); + caRequestObject::fillResult (reqMask, reqType, *retValue, xobj->cache_); + + // call user callbacks + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + case DBR_SHORT: + if (!xobj->cacheInited_) { + // setup internal buffer pointer + caMonObj::setupMonitorBuffer (tagval, xobj->cache_, xobj->data_, + CDEV_INT32); + xobj->cacheInited_ = 1; + } + + if (args.count == 1){ + struct dbr_time_short *retValue = 0; + retValue = (struct dbr_time_short *)args.dbr; + caRequestObject::updateResult (reqMask, reqType, + *retValue, xobj->data_, + reqObj->propCache() ); + + if (reqObj->longMask_ != 0) { + if (reqObj->bitValuesChanged (*(int *)(xobj->data_.value), + reqObj->longMask_)) + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else { + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + case DBR_CHAR: + if (!xobj->cacheInited_) { + // setup internal buffer pointer + caMonObj::setupMonitorBuffer (tagval, xobj->cache_, xobj->data_, + CDEV_BYTE); + xobj->cacheInited_ = 1; + } + + if (args.count == 1){ + struct dbr_time_char *retValue = 0; + retValue = (struct dbr_time_char *)args.dbr; + caRequestObject::updateResult (reqMask, reqType, + *retValue, xobj->data_, + reqObj->propCache() ); + + if (reqObj->longMask_ != 0) { + BYTE vtmp = *(BYTE *)(xobj->data_.value); + if (reqObj->bitValuesChanged ((int)vtmp, + reqObj->longMask_)) + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else { + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + case DBR_LONG: + if (!xobj->cacheInited_) { + // setup internal buffer pointer + caMonObj::setupMonitorBuffer (tagval, xobj->cache_, xobj->data_, + CDEV_INT32); + xobj->cacheInited_ = 1; + } + + if (args.count == 1) { + struct dbr_time_long *retValue = 0; + retValue = (struct dbr_time_long *)args.dbr; + caRequestObject::updateResult (reqMask, reqType, + *retValue, xobj->data_, + reqObj->propCache() ); + + if (reqObj->longMask_ != 0) { + if (reqObj->bitValuesChanged (*(int *)(xobj->data_.value), + reqObj->longMask_)) + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else { + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + case DBR_FLOAT: + if (!xobj->cacheInited_) { + // setup internal buffer pointer + caMonObj::setupMonitorBuffer (tagval, xobj->cache_, xobj->data_, + CDEV_FLOAT); + xobj->cacheInited_ = 1; + } + + if (args.count == 1) { + struct dbr_time_float *retValue = 0; + retValue = (struct dbr_time_float *)args.dbr; + caRequestObject::updateResult (reqMask, reqType, *retValue, + xobj->data_, + reqObj->propCache() ); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else { + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + case DBR_DOUBLE: + if (!xobj->cacheInited_) { + // setup internal buffer pointer + caMonObj::setupMonitorBuffer (tagval, xobj->cache_, xobj->data_, + CDEV_DOUBLE); + xobj->cacheInited_ = 1; + } + + if (args.count == 1) { + struct dbr_time_double *retValue = 0; + retValue = (struct dbr_time_double *)args.dbr; + caRequestObject::updateResult (reqMask, reqType, + *retValue, xobj->data_, + reqObj->propCache() ); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + else { + xobj->cache_.remove (); + caRequestObject::convertData ((int)reqObj->channel_->type_, + caService::CA_TAG_VALUE, + reqMask, caRequestObject::TIMESTMP, + args, xobj->cache_); + xobj->callCallbacks (cbkst, reqObj, xobj->cache_); + } + break; + default: + printf("Fatal Error: Unsupported data type\n"); + break; + } + } + else + xobj->callCallbacks (CDEV_IOFAILED, reqObj, xobj->cache_); +} + +int +caRequestObject::findSvcData (char *device, + char *msg, + cdevSystem& system, + char *svcData, + int dataLen) +{ + char message[256], fullname[128]; + + if (system.prefix()) + ::sprintf (fullname, "%s%s",system.prefix(),device); + else + ::strcpy (fullname, device); + + ::sprintf (message,"resolveServiceData %s %s", fullname, msg); + + cdevData result; + int status = (system.nameServer()).send (message, 0, result); + if (status == CDEV_SUCCESS){ + result.get (caService::CA_TAG_PV, svcData, dataLen); + int rd; + int dataStatus = result.get (caService::CA_TAG_RO, &rd); + if (dataStatus == CDEV_SUCCESS){ // channel is readonly + readonly_ = 1; + } +#ifdef _CDEV_DEBUG + printf("Service data is %s\n",svcData); +#endif + return status; + } + else + return CDEV_ERROR; +} + +int +caRequestObject::findAction (char *msg, int& action) +{ + char token0[64], token1[64], token2[64]; + int status; + +#ifdef __GNUC__ + // some version of gcc demand a memory location for msg + char buffer[256]; + strncpy (buffer, msg, sizeof (buffer)); + status = ::sscanf (buffer, "%s %s",token0, token1); +#else + status = ::sscanf (msg, "%s %s", token0, token1); +#endif + + if (::strcmp (token0, "get") == 0) + action = caRequestObject::GET; + else if (::strcmp (token0, "set") == 0) + action = caRequestObject::SET; + else if (::strcmp (token0, "monitorOn") == 0) + action = caRequestObject::MONITOR_ON; + else if (::strcmp (token0, "monitorOff") == 0) + action = caRequestObject::MONITOR_OFF; + else if (::strcmp (token0, "put") == 0) + action = caRequestObject::PUT; + else + action = caRequestObject::UNKNOWN; + + return CDEV_SUCCESS; +} + +int +caRequestObject::newTriggerSource (void) +{ + cdevData& cxt = getContext (); + int val = 0; + if (cxt.get (caService::CA_TAG_VALUE, &val) == CDEV_SUCCESS) { + if (val == 0) { + caPchannel* pch = channel_->pchannels_; + for (int i = 2; i < MAX_NUM_PCHANNELS; i++) { + if (cxt.get (pch[i].tag, &val) == CDEV_SUCCESS){ + // caller specify a trigger or I am going to setup channel + // for those properties which are not changed rapidly + if (val >= 2) + return 1; + } + } + } + } + return 0; +} + +void +caRequestObject::setPropCache (void) +{ + if (cache_ == 0) { + prop_ = new cdevData (); + cache_ = new caMonData (); + int status = caMonObj::setupMonitorBuffer (caService::CA_TAG_VALUE, + *prop_, *cache_, CDEV_FLOAT); + if (status != CDEV_SUCCESS) { + delete cache_; + delete prop_; + cache_ = 0; + prop_ = 0; + } + } +} + +caMonData* +caRequestObject::propCache (void) const +{ + return cache_; +} + +void +caRequestObject::updatePropCache (caRequestObject* obj, + int tag, + cdevData& data) +{ + caMonData* cache = obj->propCache (); + + if (cache != 0) { + if (tag == caService::CA_TAG_STATUS) + data.get (tag, cache->status); + else if (tag == caService::CA_TAG_SEVERITY) + data.get (tag, cache->severity); + else if (tag == caService::CA_TAG_PRECISION) + data.get (tag, cache->precision); + else if (tag == caService::CA_TAG_DISPHI) + data.get (tag, cache->disphi); + else if (tag == caService::CA_TAG_DISPLO) + data.get (tag, cache->displo); + else if (tag == caService::CA_TAG_ALRMHI) + data.get (tag, cache->alrmhi); + else if (tag == caService::CA_TAG_ALRMLO) + data.get (tag, cache->alrmlo); + else if (tag == caService::CA_TAG_WRNHI) + data.get (tag, cache->warnhi); + else if (tag == caService::CA_TAG_WRNLO) + data.get (tag, cache->warnlo); + else if (tag == caService::CA_TAG_CTRLHI) + data.get (tag, cache->ctrlhi); + else if (tag == caService::CA_TAG_CTRLLO) + data.get (tag, cache->ctrllo); + else + cdevSystem::defaultSystem().reportError + (CDEV_SEVERITY_ERROR, "caRequestObject", obj, + "Warning: property cache buffers does not have this tag %d\n", + tag); + } +} diff --git a/src/ca/caRequestObject.h b/src/ca/caRequestObject.h new file mode 100755 index 0000000..25f43e9 --- /dev/null +++ b/src/ca/caRequestObject.h @@ -0,0 +1,299 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Epics Channel Access request object class +// +// Author: Jie Chen +// +// Revision History: +// caRequestObject.h,v +// Revision 1.13 1998/04/10 13:55:41 chen +// add access information to caService +// +// Revision 1.12 1998/03/05 18:49:14 chen +// fix a bug on context == 2 on property channels +// +// Revision 1.11 1997/08/08 16:41:37 chen +// add char type and fix dbr== null +// +// Revision 1.10 1997/03/03 17:36:31 chen +// add buffering to channel access connection +// +// Revision 1.9 1996/09/18 14:46:52 chen +// Channel holds multiple monitor objects +// +// Revision 1.8 1996/09/10 19:21:05 chen +// change C++ include header +// +// Revision 1.7 1996/05/02 14:18:38 chen +// Fix monitorOn and unfinished transaction bug +// +// Revision 1.6 1995/10/17 20:20:42 chen +// redefine getState +// +// Revision 1.5 1995/10/06 19:03:38 chen +// add type name on enum +// +// Revision 1.4 1995/10/03 19:56:32 chen +// add monitoring properties +// +// Revision 1.3 1995/07/06 19:48:22 chen +// add default frequency to do connection +// +// Revision 1.2 1995/07/05 18:33:12 chen +// sync implemented by async + removal some codes +// +// Revision 1.1.1.1 1995/06/16 17:14:03 epics +// initial import of cdev +// +// +#ifndef _CA_REQUEST_OBJECT_H +#define _CA_REQUEST_OBJECT_H + +#include +#include + +// epics stuff +#if !defined (_EPICS_3_12) +#define __STDC__ +extern "C" { +#endif + +#include +#include + +#if !defined (_EPICS_3_12) +}; +#undef __STDC__ +#endif + +#include "caMonObj.h" + +typedef struct _ca_attr +{ + char *attrName; + int attrValue; +}caAttr; + +class caService; +class caChannel; +class caPchannel; +class cdevTranObj; +class caMonObj; + +class caRequestObject: public cdevRequestObject +{ +public: + // constructor and destructor + caRequestObject (char *device, + char *msg, + caService *svc, + cdevSystem& system = cdevSystem::defaultSystem() ); + ~caRequestObject (void); + + int setContext (cdevData &ctx); + // PURPOSE: set io context to this request object. + // Redefine setContext inherited from cdevIOcontext + // REQUIRE: nothing + // PROMISE: value tag will be always set, return CDEV_SUCCESS + + int send (cdevData& out, cdevData& result); + int send (cdevData *out, cdevData& result); + int send (cdevData& out, cdevData* result); + int send (cdevData *out, cdevData* result); + // PURPOSE: Synchronous IO operations "get", "set", "monitorOn/off" + // REQUIRE: When set, out must be supplied. When get result must be provided + // PROMISE: return CDEV_SUCCESS: success. + // There will be no synchronous monitorOn. + + int sendNoBlock (cdevData& out, cdevData& result); + int sendNoBlock (cdevData* out, cdevData& result); + int sendNoBlock (cdevData& out, cdevData* result); + int sendNoBlock (cdevData* out, cdevData* result); + // PURPOSE: Asynchronous IO operations used in conjunction with cdevGroup or system + // REQUIRE: When set, out must be supplied. When get result must be provied. + // Caller must call system.pend or group.pend to flush out network + // requests. + // PROMISE: return CDEV_SUCCESS: requests have been sent out. + + int sendCallback (cdevData& out, cdevCallback& callback); + int sendCallback (cdevData* out, cdevCallback& callback); + // PURPOSE: Asynchromous IO operations with a user supplied callback function + // REQUIRE: When set, out must be provided. + // PROMISE: User callback function will be called with status information + // status = CDEV_DISCONNECTED: channel discconected + // status = CDEV_SUCCESS : everything is OK + // status = CDEV_RECONNECTED : channel reconnected + // status = CDEV_ERROR : something fishy. + + int getState (void); + // PURPOSE: get connection state + // REQUIRE: none + // PROMISE: CDEV_CONNECTED or CDEV_NOTCONNECTED + + int getAccess (void); + // PURPOSE: get access state + // REQUIRE: none + // PROMISE: CDEV_ACCESS_NONE, CDEV_ACCESS_READONLY, CDEV_ACCESS_WRITE + + const char *className (void) const {return "caRequestObject";} + +protected: + // attach to a particular channel + void attachChannel (void); + + // real implementation of of execNoBlock & execCallback + int execNoBlock (cdevData* out, cdevData* result, void* arg); + int execCallback (cdevData* out, cdevCallback& callback, void* arg); + + // async get value callback function + int getValueCbk (caChannel* channel, cdevTranObj *obj); + + // insert result to user cdevData according to mask + static void fillResult (int mask, int type, + struct dbr_time_string& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_time_short& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_time_char& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_time_long& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_time_float& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_time_double& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_time_enum& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_ctrl_short& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_ctrl_char& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_ctrl_long& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_ctrl_float& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_ctrl_double& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_ctrl_enum& val, + cdevData& result); + + // update data value to fixed buffers of result and update property + // values if necessary pointed by cache + static void updateResult (int mask, int type, + struct dbr_time_short& val, + caMonData& result, + caMonData* cache); + static void updateResult (int mask, int type, + struct dbr_time_char& val, + caMonData& result, + caMonData* cache); + static void updateResult (int mask, int type, + struct dbr_time_long& val, + caMonData& result, + caMonData* cache); + static void updateResult (int mask, int type, + struct dbr_time_float& val, + caMonData& result, + caMonData* cache); + static void updateResult (int mask, int type, + struct dbr_time_double& val, + caMonData& result, + caMonData* cache); + + // return 1 if the context contains new trigger source (context + // value >= 2 + int newTriggerSource (void); + + // setup property monitoring buffer which holds latest values + // of properties + void setPropCache (void); + caMonData* propCache (void) const; + static void updatePropCache (caRequestObject* obj, + int tag, + cdevData& data); + + // convert data from channel access data type to cdevdata according to + // channel type and request mask/type + static void convertData (int chtype, + int tag, + int reqMask, + int reqType, + struct event_handler_args& args, + cdevData& data); + + // set value callback + int setValueCbk (caChannel* channel, cdevTranObj *obj); + + // monitor channel + int monitorValue (caChannel* channel, caMonObj *obj); + void initPropChannels (caPchannel* pchannel); + void initPropChannels (caChannel* channel); + void monitorProperties (caChannel* channel, caMonObj *obj); + int monitorPropValue (caChannel* channel, caMonObj *obj); + + // add callback to the property channel that has been created + void addCbksToPChannels (caChannel* channel, + cdevCallback& cbk, + cdevData* out); + + // data area + // enumerated value for ca request data type + typedef enum {VALUE = 1, STATUS = 4, TIMESTMP = 8, GRINFO = 16, + CTRLINFO = 0x00001000} CAENUMTAG; + // static channel acccess attribute + static caAttr caAttributes[]; + static int numAttributes; + // static requestObject action + typedef enum {GET = 0x1000, SET, MONITOR_ON, + MONITOR_OFF, PUT, UNKNOWN} CAENUMVERB; + +private: + // default get callback + static void defaultGetCallback (struct event_handler_args); + // default set callback + static void defaultSetCallback (struct event_handler_args); + // call user callback on monitor + static void callMonitorCallback (struct event_handler_args); + // call user callback on property monitoring callback + static void callPropMonitorCallback (struct event_handler_args); + // find out service data + int findSvcData (char *device, char *msg, cdevSystem& system, + char *svcData, int dataLen); + // find action data from message + static int findAction (char *msg, int& action); + + // properties cached values + caMonData* cache_; + cdevData* prop_; + + // action type + int action_; + // readonly flag + int readonly_; + // real channel access channel class object ptr + caChannel *channel_; + // request data type flag + int reqType_; + int reqMask_; +}; +#endif diff --git a/src/ca/caRequestObject.h.orig b/src/ca/caRequestObject.h.orig new file mode 100755 index 0000000..e4d6c4d --- /dev/null +++ b/src/ca/caRequestObject.h.orig @@ -0,0 +1,299 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Epics Channel Access request object class +// +// Author: Jie Chen +// +// Revision History: +// caRequestObject.h,v +// Revision 1.13 1998/04/10 13:55:41 chen +// add access information to caService +// +// Revision 1.12 1998/03/05 18:49:14 chen +// fix a bug on context == 2 on property channels +// +// Revision 1.11 1997/08/08 16:41:37 chen +// add char type and fix dbr== null +// +// Revision 1.10 1997/03/03 17:36:31 chen +// add buffering to channel access connection +// +// Revision 1.9 1996/09/18 14:46:52 chen +// Channel holds multiple monitor objects +// +// Revision 1.8 1996/09/10 19:21:05 chen +// change C++ include header +// +// Revision 1.7 1996/05/02 14:18:38 chen +// Fix monitorOn and unfinished transaction bug +// +// Revision 1.6 1995/10/17 20:20:42 chen +// redefine getState +// +// Revision 1.5 1995/10/06 19:03:38 chen +// add type name on enum +// +// Revision 1.4 1995/10/03 19:56:32 chen +// add monitoring properties +// +// Revision 1.3 1995/07/06 19:48:22 chen +// add default frequency to do connection +// +// Revision 1.2 1995/07/05 18:33:12 chen +// sync implemented by async + removal some codes +// +// Revision 1.1.1.1 1995/06/16 17:14:03 epics +// initial import of cdev +// +// +#ifndef _CA_REQUEST_OBJECT_H +#define _CA_REQUEST_OBJECT_H + +#include +#include + +// epics stuff +#if !defined (_EPICS_3_12) +#define __STDC__ +extern "C" { +#endif + +#include +#include + +#if !defined (_EPICS_3_12) +}; +#undef __STDC__ +#endif + +#include "caMonObj.h" + +typedef struct _ca_attr +{ + char *attrName; + int attrValue; +}caAttr; + +class caService; +class caChannel; +class caPchannel; +class cdevTranObj; +class caMonObj; + +class caRequestObject: public cdevRequestObject +{ +public: + // constructor and destructor + caRequestObject (char *device, + char *msg, + caService *svc, + cdevSystem& system = cdevSystem::defaultSystem() ); + ~caRequestObject (void); + + int setContext (cdevData &ctx); + // PURPOSE: set io context to this request object. + // Redefine setContext inherited from cdevIOcontext + // REQUIRE: nothing + // PROMISE: value tag will be always set, return CDEV_SUCCESS + + int send (cdevData& out, cdevData& result); + int send (cdevData *out, cdevData& result); + int send (cdevData& out, cdevData* result); + int send (cdevData *out, cdevData* result); + // PURPOSE: Synchronous IO operations "get", "set", "monitorOn/off" + // REQUIRE: When set, out must be supplied. When get result must be provided + // PROMISE: return CDEV_SUCCESS: success. + // There will be no synchronous monitorOn. + + int sendNoBlock (cdevData& out, cdevData& result); + int sendNoBlock (cdevData* out, cdevData& result); + int sendNoBlock (cdevData& out, cdevData* result); + int sendNoBlock (cdevData* out, cdevData* result); + // PURPOSE: Asynchronous IO operations used in conjunction with cdevGroup or system + // REQUIRE: When set, out must be supplied. When get result must be provied. + // Caller must call system.pend or group.pend to flush out network + // requests. + // PROMISE: return CDEV_SUCCESS: requests have been sent out. + + int sendCallback (cdevData& out, cdevCallback& callback); + int sendCallback (cdevData* out, cdevCallback& callback); + // PURPOSE: Asynchromous IO operations with a user supplied callback function + // REQUIRE: When set, out must be provided. + // PROMISE: User callback function will be called with status information + // status = CDEV_DISCONNECTED: channel discconected + // status = CDEV_SUCCESS : everything is OK + // status = CDEV_RECONNECTED : channel reconnected + // status = CDEV_ERROR : something fishy. + + int getState (void); + // PURPOSE: get connection state + // REQUIRE: none + // PROMISE: CDEV_CONNECTED or CDEV_NOTCONNECTED + + int getAccess (void); + // PURPOSE: get access state + // REQUIRE: none + // PROMISE: CDEV_ACCESS_NONE, CDEV_ACCESS_READONLY, CDEV_ACCESS_WRITE + + const char *className (void) const {return "caRequestObject";} + +protected: + // attach to a particular channel + void attachChannel (void); + + // real implementation of of execNoBlock & execCallback + int execNoBlock (cdevData* out, cdevData* result, void* arg); + int execCallback (cdevData* out, cdevCallback& callback, void* arg); + + // async get value callback function + int getValueCbk (caChannel* channel, cdevTranObj *obj); + + // insert result to user cdevData according to mask + static void fillResult (int mask, int type, + struct dbr_time_string& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_time_short& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_time_char& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_time_long& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_time_float& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_time_double& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_time_enum& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_ctrl_short& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_ctrl_char& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_ctrl_long& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_ctrl_float& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_ctrl_double& val, + cdevData& result); + static void fillResult (int mask, int type, + struct dbr_ctrl_enum& val, + cdevData& result); + + // update data value to fixed buffers of result and update property + // values if necessary pointed by cache + static void updateResult (int mask, int type, + struct dbr_time_short& val, + caMonData& result, + caMonData* cache); + static void updateResult (int mask, int type, + struct dbr_time_char& val, + caMonData& result, + caMonData* cache); + static void updateResult (int mask, int type, + struct dbr_time_long& val, + caMonData& result, + caMonData* cache); + static void updateResult (int mask, int type, + struct dbr_time_float& val, + caMonData& result, + caMonData* cache); + static void updateResult (int mask, int type, + struct dbr_time_double& val, + caMonData& result, + caMonData* cache); + + // return 1 if the context contains new trigger source (context + // value >= 2 + int newTriggerSource (void); + + // setup property monitoring buffer which holds latest values + // of properties + void setPropCache (void); + caMonData* propCache (void) const; + static void updatePropCache (caRequestObject* obj, + int tag, + cdevData& data); + + // convert data from channel access data type to cdevdata according to + // channel type and request mask/type + static void convertData (int chtype, + int tag, + int reqMask, + int reqType, + struct event_handler_args& args, + cdevData& data); + + // set value callback + int setValueCbk (caChannel* channel, cdevTranObj *obj); + + // monitor channel + int monitorValue (caChannel* channel, caMonObj *obj); + void initPropChannels (caPchannel* pchannel); + void initPropChannels (caChannel* channel); + void monitorProperties (caChannel* channel, caMonObj *obj); + int monitorPropValue (caChannel* channel, caMonObj *obj); + + // add callback to the property channel that has been created + void addCbksToPChannels (caChannel* channel, + cdevCallback& cbk, + cdevData* out); + + // data area + // enumerated value for ca request data type + typedef enum {VALUE = 1, STATUS = 4, TIMESTMP = 8, GRINFO = 16, + CTRLINFO = 0x00001000} CAENUMTAG; + // static channel acccess attribute + static caAttr caAttributes[]; + static int numAttributes; + // static requestObject action + typedef enum {GET = 0x1000, SET, MONITOR_ON, + MONITOR_OFF, UNKNOWN} CAENUMVERB; + +private: + // default get callback + static void defaultGetCallback (struct event_handler_args); + // default set callback + static void defaultSetCallback (struct event_handler_args); + // call user callback on monitor + static void callMonitorCallback (struct event_handler_args); + // call user callback on property monitoring callback + static void callPropMonitorCallback (struct event_handler_args); + // find out service data + int findSvcData (char *device, char *msg, cdevSystem& system, + char *svcData, int dataLen); + // find action data from message + static int findAction (char *msg, int& action); + + // properties cached values + caMonData* cache_; + cdevData* prop_; + + // action type + int action_; + // readonly flag + int readonly_; + // real channel access channel class object ptr + caChannel *channel_; + // request data type flag + int reqType_; + int reqMask_; +}; +#endif diff --git a/src/ca/caRequestObject.h.rej b/src/ca/caRequestObject.h.rej new file mode 100644 index 0000000..4af64d6 --- /dev/null +++ b/src/ca/caRequestObject.h.rej @@ -0,0 +1,22 @@ +*************** +*** 265,271 **** + static int numAttributes; + // static requestObject action + static enum {GET = 0x1000, SET, MONITOR_ON, +- MONITOR_OFF, UNKNOWN} caEnumVerb_; + + private: + // default get callback +--- 265,276 ---- + static int numAttributes; + // static requestObject action + static enum {GET = 0x1000, SET, MONITOR_ON, ++ MONITOR_OFF, PUT, UNKNOWN} caEnumVerb_; ++ // T. Straumann: added 'put' verb, which has the same functionality ++ // as 'set', but uses 'ca_array_put()' instead of ++ // 'ca_array_put_callback()', i.e. it is not waited ++ // for the end of record processing. (ca server doesn't ++ // handle more than one ca_array_put_callback() simultaneously). + + private: + // default get callback diff --git a/src/ca/caService.cc b/src/ca/caService.cc new file mode 100755 index 0000000..9077781 --- /dev/null +++ b/src/ca/caService.cc @@ -0,0 +1,405 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// CA service class +// +// Author: Jie Chen +// +// Revision History: +// caService.cc,v +// Revision 1.10 1998/09/02 19:08:49 chen +// change ca_flush_io to ca_pend_io (0.00000001) +// +// Revision 1.9 1998/03/05 18:49:14 chen +// fix a bug on context == 2 on property channels +// +// Revision 1.8 1998/02/18 19:48:26 chen +// fix ca set access error +// +// Revision 1.7 1997/03/03 17:36:32 chen +// add buffering to channel access connection +// +// Revision 1.6 1995/10/26 14:33:15 akers +// Removal of Warnings +// +// Revision 1.5 1995/10/03 19:57:12 chen +// Add lookup table for attributes from tags +// +// Revision 1.4 1995/08/28 18:07:09 chen +// Add some error check on removeReadFd +// +// Revision 1.3 1995/07/05 18:34:43 chen +// use default hash function +// +// Revision 1.2 1995/06/30 15:55:14 chen +// remove unnecessary files +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include +#include "caService.h" +#include "caRequestObject.h" +#include "caNameSvc.h" +#include "caChannel.h" + +// hash table size for channle ID pointers +const int CID_TABLE_SIZE = 997; + +int caService::CA_TAG_PV = 0x1001; +int caService::CA_TAG_DFV = 0x1002; +int caService::CA_TAG_RO = 0x1003; +int caService::CA_TAG_VALUE = 0; +int caService::CA_TAG_STATUS = 0; +int caService::CA_TAG_SEVERITY = 0; +int caService::CA_TAG_TIME = 0; +int caService::CA_TAG_UNITS = 0; +int caService::CA_TAG_DISPHI = 0; +int caService::CA_TAG_DISPLO = 0; +int caService::CA_TAG_ALRMHI = 0; +int caService::CA_TAG_ALRMLO = 0; +int caService::CA_TAG_WRNHI = 0; +int caService::CA_TAG_WRNLO = 0; +int caService::CA_TAG_CTRLHI = 0; +int caService::CA_TAG_CTRLLO = 0; +int caService::CA_TAG_RESULT_CODE = 0; +int caService::CA_TAG_PRECISION = 0; + +//=========================================================================== +// Implementation of class caService +//=========================================================================== +caService::caService(char *name, cdevSystem& system) +:cdevService(name, system), numFds_(0), fds_(0), + channelTable_ (CID_TABLE_SIZE, cdevStrHashFunc) +{ +#ifdef _TRACE_OBJECTS + printf(" Create caService class\n"); +#endif + // create new name service just for channel access use only + nameSvc_ = new caNameSvc (system); + // add new tag to cdevData + if (caService::CA_TAG_CTRLLO == 0){ + cdevData::insertTag (caService::CA_TAG_PV, "PV"); + cdevData::insertTag (caService::CA_TAG_DFV, "DEFAULT"); + cdevData::insertTag (caService::CA_TAG_RO, "readonly"); + caService::mapCtagToItag (); + } + // initialize tag to attribute table + initTagToAttrTable (); + // channel access initialize stuff + int status = ::ca_task_initialize(); + // here one could do ca_add_fd_registration + ::ca_add_fd_registration (&(caService::fdRegCallback), (void *)this); + ::ca_add_exception_event (&(caService::exceptionCallback), (void *)this); +} + +caService::~caService(void) +{ +#ifdef _TRACE_OBJECTS + printf(" Delete caService class\n"); +#endif + // system_.removeService (this); + ::ca_task_exit (); +} + +int +caService::getFd (int * &fd, int &numFds) +{ + if (numFds_ == 0){ + numFds = numFds_; + fd = 0; + } + else{ + fd = fds_; + numFds = numFds_; + } + return CDEV_SUCCESS; +} + +int +caService::handlePending (int /* fd */) +{ + if (::ca_pend_event (0.0001) == ECA_NORMAL) { + return CDEV_SUCCESS; + } + return CDEV_IOFAILED; +} + +int +caService::flush (void) +{ +#ifdef _CDEV_DEBUG + printf("Flush by caService\n"); +#endif + if (::ca_pend_event (0.00000001) == ECA_NORMAL) + return CDEV_SUCCESS; + else + return CDEV_IOFAILED; +} + +int +caService::poll (void) +{ +#ifdef _CDEV_DEBUG + printf("Poll by caService\n"); +#endif + if (::ca_pend_event (0.0001) == ECA_NORMAL) { + return CDEV_SUCCESS; + } + return CDEV_IOFAILED; +} + +int +caService::pend (int fd) +{ +#ifdef _CDEV_DEBUG + printf ("caService Pend\n"); +#endif + return handlePending (fd); +} + +int +caService::pend (double seconds, int) +{ + // for now I have to do this way since ca_array_get_callback has problem +#ifdef _CDEV_DEBUG + printf ("caService Pend %f\n",seconds); +#endif + if (::ca_pend_event (seconds) == ECA_NORMAL) { + return CDEV_SUCCESS; + } + return CDEV_IOFAILED; +} + +int +caService::getRequestObject (char* deviceName, char* msg, + cdevRequestObject * &req) +{ + req = new caRequestObject (deviceName, msg, this, system_); + if (req) + return CDEV_SUCCESS; + else + return CDEV_ERROR; +} + +int +caService::getNameServer (cdevDevice* &server) +{ + server = 0; + return CDEV_SUCCESS; +} + +void +caService::addReadFd (int fd) +{ + if (numFds_){ + int *newfds = new int[numFds_ + 1]; + for (int i =0; i < numFds_; i++) + newfds[i] = fds_[i]; + delete []fds_; + newfds[i] = fd; + fds_ = newfds; + numFds_ += 1; + } + else{ + fds_ = new int[1]; + fds_[0] = fd; + numFds_ = 1; + } +} + +void +caService::removeReadFd (int fd) +{ + // check whether this fd is inside the list + int found = 0; + for (int i = 0; i < numFds_; i++){ + if (fds_[i] == fd) { + found = 1; + break; + } + } + if (!found) + return; + if (numFds_ > 1){ + int *newfds = new int[numFds_ - 1]; + int j = 0; + for (i = 0; i < numFds_; i++){ + if (fds_[i] != fd) + newfds[j++] = fds_[i]; + } + delete []fds_; + fds_ = newfds; + numFds_ = numFds_ - 1; + } + else{ + delete []fds_; + numFds_ = 0; + } +} + +void +caService::fdRegCallback (void *arg, int fd, int opened) +{ + caService *obj = (caService *)arg; + if (opened){ + obj->addReadFd (fd); +#ifdef _CDEV_DEBUG + printf("fd %d opened\n",fd); +#endif + } + else{ + obj->removeReadFd (fd); +#ifdef _CDEV_DEBUG + printf("fd %d closed\n",fd); +#endif + } + + obj->registerFd (fd, opened); +} + +void +caService::exceptionCallback (struct exception_handler_args /* args */) +{ +#ifdef _CDEV_DEBUG + printf("CA: exception handler called\n"); +#endif +} + +int +caService::channelPtr (char *channelName, caChannel* &ch) +{ + cdevSlist& list = channelTable_.bucketRef (channelName); + cdevSlistIterator lit (list); + caChannel *cal; + + for (lit.init(); !lit; ++lit){ + cal = (caChannel *)lit (); + if (::strcmp (cal->channelName(), channelName) == 0){ + ch = (caChannel *)lit(); + return CDEV_SUCCESS; + } + } + ch = 0; + return CDEV_ERROR; +} + +int +caService::addChannel (char *channelName, caChannel* chPtr) +{ + channelTable_.add (channelName, (void *)chPtr); + return CDEV_SUCCESS; +} + +int +caService::removeChannel (char *channelName, caChannel* chPtr) +{ + channelTable_.remove (channelName, (void *)chPtr); + return CDEV_SUCCESS; +} + +void +caService::mapCtagToItag (void) +{ + cdevData::tagC2I ("value", &caService::CA_TAG_VALUE); + cdevData::tagC2I ("status", &caService::CA_TAG_STATUS); + cdevData::tagC2I ("severity", &caService::CA_TAG_SEVERITY); + cdevData::tagC2I ("time", &caService::CA_TAG_TIME); + cdevData::tagC2I ("units", &caService::CA_TAG_UNITS); + cdevData::tagC2I ("displayHigh", &caService::CA_TAG_DISPHI); + cdevData::tagC2I ("displayLow", &caService::CA_TAG_DISPLO); + cdevData::tagC2I ("alarmHigh", &caService::CA_TAG_ALRMHI); + cdevData::tagC2I ("alarmLow", &caService::CA_TAG_ALRMLO); + cdevData::tagC2I ("warningHigh", &caService::CA_TAG_WRNHI); + cdevData::tagC2I ("warningLow", &caService::CA_TAG_WRNLO); + cdevData::tagC2I ("controlHigh", &caService::CA_TAG_CTRLHI); + cdevData::tagC2I ("controlLow", &caService::CA_TAG_CTRLLO); + cdevData::tagC2I ("resultCode", &caService::CA_TAG_RESULT_CODE); + cdevData::tagC2I ("precision", &caService::CA_TAG_PRECISION); + // Initialize tag to attribute table +#ifdef _CDEV_DEBUG + printf("value tag value is %d\n", caService::CA_TAG_VALUE); + printf("status tag value is %d\n", caService::CA_TAG_STATUS); + printf("severity tag value is %d\n", caService::CA_TAG_SEVERITY); + printf("time tag value is %d\n", caService::CA_TAG_TIME); + printf("units tag value is %d\n", caService::CA_TAG_UNITS); + printf("displayHigh tag value is %d\n", caService::CA_TAG_DISPHI); + printf("displayLow tag value is %d\n", caService::CA_TAG_DISPLO); + printf("alarmHigh tag value is %d\n", caService::CA_TAG_ALRMHI); + printf("alarmLow tag value is %d\n", caService::CA_TAG_ALRMLO); + printf("warningHigh tag value is %d\n", caService::CA_TAG_WRNHI); + printf("warningLow tag value is %d\n", caService::CA_TAG_WRNLO); + printf("controlHigh tag value is %d\n", caService::CA_TAG_CTRLHI); + printf("controlLow tag value is %d\n", caService::CA_TAG_CTRLLO); + printf("result code tag value is %d\n", caService::CA_TAG_RESULT_CODE); + printf("precision tag value is %d\n", caService::CA_TAG_PRECISION); +#endif +} + +void +caService::initTagToAttrTable (void) +{ + int i = 0; + tagToAttrTb_[i].tag = caService::CA_TAG_VALUE; + tagToAttrTb_[i++].attr = "VAL"; + tagToAttrTb_[i].tag = caService::CA_TAG_STATUS; + tagToAttrTb_[i++].attr = "STAT"; + tagToAttrTb_[i].tag = caService::CA_TAG_SEVERITY; + tagToAttrTb_[i++].attr = "SEVR"; + tagToAttrTb_[i].tag = caService::CA_TAG_TIME; + tagToAttrTb_[i++].attr = "TIME"; + tagToAttrTb_[i].tag = caService::CA_TAG_UNITS; + tagToAttrTb_[i++].attr = "EGU"; + tagToAttrTb_[i].tag = caService::CA_TAG_PRECISION; + tagToAttrTb_[i++].attr = "PREC"; + tagToAttrTb_[i].tag = caService::CA_TAG_DISPHI; + tagToAttrTb_[i++].attr = "HOPR"; + tagToAttrTb_[i].tag = caService::CA_TAG_DISPLO; + tagToAttrTb_[i++].attr = "LOPR"; + tagToAttrTb_[i].tag = caService::CA_TAG_ALRMHI; + tagToAttrTb_[i++].attr = "HIHI"; + tagToAttrTb_[i].tag = caService::CA_TAG_ALRMLO; + tagToAttrTb_[i++].attr = "LOLO"; + tagToAttrTb_[i].tag = caService::CA_TAG_WRNHI; + tagToAttrTb_[i++].attr = "HIGH"; + tagToAttrTb_[i].tag = caService::CA_TAG_WRNLO; + tagToAttrTb_[i++].attr = "LOW"; + tagToAttrTb_[i].tag = caService::CA_TAG_CTRLHI; + tagToAttrTb_[i++].attr = "HOPR"; + tagToAttrTb_[i].tag = caService::CA_TAG_CTRLLO; + tagToAttrTb_[i++].attr = "LOPR"; +} + +const char* +caService::attr (int tag) const +{ + int found = 0; + for (int i = 0; i < 14; i++) { + if (tagToAttrTb_[i].tag == tag) + return tagToAttrTb_[i].attr; + } + return 0; +} + +// C interface routine to initialize an caService object +cdevService * +newCaService (char *name, cdevSystem *system) +{ + return new caService (name, *system); +} diff --git a/src/ca/caService.h b/src/ca/caService.h new file mode 100755 index 0000000..e56dc3f --- /dev/null +++ b/src/ca/caService.h @@ -0,0 +1,177 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// CA service class +// +// Author: Jie Chen +// +// Revision History: +// caService.h,v +// Revision 1.8 1998/03/05 18:49:14 chen +// fix a bug on context == 2 on property channels +// +// Revision 1.7 1998/02/18 19:48:27 chen +// fix ca set access error +// +// Revision 1.6 1997/03/03 17:36:33 chen +// add buffering to channel access connection +// +// Revision 1.5 1996/09/10 19:21:16 chen +// change C++ include header +// +// Revision 1.4 1995/10/03 19:57:21 chen +// Add lookup table for attributes from tags +// +// Revision 1.3 1995/07/05 18:34:34 chen +// use default hash function +// +// Revision 1.2 1995/06/30 15:55:17 chen +// remove unnecessary files +// +// Revision 1.1.1.1 1995/06/16 17:14:03 epics +// initial import of cdev +// +// +#ifndef _CA_SERVICE_H +#define _CA_SERVICE_H + +#include +#include +#include + +#include "caChannel.h" + +// epics stuff +#if !defined (_EPICS_3_12) +#define __STDC__ +extern "C"{ +#endif + +#include +#include + +#if !defined (_EPICS_3_12) +}; +#undef __STDC__ +#endif + +extern "C" CDEVSVCAPI cdevService *newCaService (char *name, cdevSystem* system); + +typedef struct _tag_to_attr +{ + int tag; + char* attr; +}caTagToAttr; + +class caService: public cdevService +{ + public: + // constructor + caService (char *name, cdevSystem &system = cdevSystem::defaultSystem ()); + + int getFd (int * &fd, int &numFd); + // PURPOSE: return channel access network file descriptors + // REQUIRE: callers provide pointer only and don't free memory + // PROMISE: numFd will be real number of file descriptors of the + // channel access client. return 0: always + + int flush (void); + // PURPOSE: flush network requests + // REQUIRE: nothing + // PROMISE: return 0: success, return 1: ca error + + int poll (void); + // PURPOSE: polling method + // REQUIRE: nothing + // PROMISE: return 0: success, return 1: ca error + + int pend (int fd = -1); + // PURPOSE: handle network pending + // REQUIRE: nothing + // PROMISE: return 0: success, return 1: ca error + int pend (double seconds, int fd = -1); + // PURPOSE: handle network pending for 'seconds' + // REQUIRE: nothing + // PROMISE: return 0: success. return 1: ca error + + int getRequestObject (char *deviceName, char *msg, + cdevRequestObject * &req); + // PURPOSE: return a caRequestObject (called from attachPtr function + // of cdevRequestObject class) + // REQUIRE: right pair of deviceName and msg. + // PROMISE: a caRequestObject + + int getNameServer (cdevDevice* &ns); + // PURPOSE: retrieve ca name server in case of missing DDL + // REQUIRE: nothing + // PROMISE: a cdevDevice based ca name service + + int channelPtr (char *channelName, caChannel* &ch); + // PURPOSE: check whether a channel has been created base on channel name + // REQUIRE: channelName != 0 + // PROMISE: return 0: found a channel. return -1: no + + int addChannel (char *channelName, caChannel* chPtr); + // PURPOSE: add a new channel to the table in caService + // REQUIRE: channelName != 0 and chPtr != 0 + // PROMISE: This channle will be inserted only once. return 0: always + + int removeChannel (char *channelName, caChannel* chPtr); + // PURPOSE: remove a channel from the table in caService + // REQUIRE: channelName != 0 and chPtr != 0 + // PROMISE: This channle will be removed. return 0: always + + const char* attr (int tag) const; + // PURPOSE: find a attribute of the ca record corresponding to a tag + // REQUIRE: tag must be ca default tag, and used by caRequestObject only + // PROMISE: return an attribute name + + // int tag for channel access + static int CA_TAG_VALUE, CA_TAG_STATUS, CA_TAG_SEVERITY; + static int CA_TAG_TIME, CA_TAG_UNITS, CA_TAG_DISPHI, CA_TAG_DISPLO; + static int CA_TAG_ALRMHI, CA_TAG_ALRMLO, CA_TAG_WRNHI, CA_TAG_WRNLO; + static int CA_TAG_CTRLHI, CA_TAG_CTRLLO, CA_TAG_RESULT_CODE; + static int CA_TAG_PRECISION; + // new tags + static int CA_TAG_PV, CA_TAG_DFV, CA_TAG_RO; + + const char *className (void) const {return "caService";} + +protected: + // deny direct access to destructor + ~caService (void); + // map char tags to int tags + static void mapCtagToItag (void); + + int handlePending (int fd); + // keep fd information + void addReadFd (int fd); + void removeReadFd (int fd); + + // initialize tag to attribute translation table + void initTagToAttrTable (void); + + // file descriptor callback routines for Channel access + // must be static function + static void fdRegCallback(void *args, int fd, int opend); + static void exceptionCallback (struct exception_handler_args args); + + private: + // file descriptors caService associated with + int *fds_; + int numFds_; + // integer tag to attribute translation table + caTagToAttr tagToAttrTb_[14]; + // default name service for channel access + cdevDevice *nameSvc_; + // hash table for channel access connection + cdevStrHash channelTable_; +}; +#endif diff --git a/src/ca/casvcwin32.mak b/src/ca/casvcwin32.mak new file mode 100755 index 0000000..b1c1f8f --- /dev/null +++ b/src/ca/casvcwin32.mak @@ -0,0 +1,29 @@ +# This is a Makefile for building channel access service for WIN32 +.SUFFIXES : .exe .cpp .cxx .h .hh .cc .rc .asm .res +CC = cl +CFLAGS = /nologo /ZI /W3 /GX /I "$(CDEV)\include" /I "$(EPICS)\base\include" /D "WIN32" /D "_CDEV_BUILD_SVC" /D "_WINDOWS" /D "_MBCS" /c /Tp +LINK = link +LINK_FLAGS = kernel32.lib user32.lib advapi32.lib wsock32.lib $(CDEV)\lib\cdev.lib $(EPICS)\base\lib\ca.lib $(EPICS)\base\lib\com.lib /nologo /dll /incremental:yes /machine:I386 /out:"caService.dll" + +WIN32_OBJS = caService.obj caRequestObject.obj caChannel.obj caNameSvc.obj caMonObj.obj caMisc.obj + +all: caService.dll copydll + +caService.dll: $(WIN32_OBJS) + $(LINK) $(LINK_FLAGS) $(WIN32_OBJS) + +copydll: caService.dll + @if not exist $(CDEVSHOBJ) mkdir $(CDEVSHOBJ) + @if exist $(CDEVSHOBJ) erase /Q $(CDEVSHOBJ)\caService.dll + copy caService.dll $(CDEVSHOBJ) + +clean: + -@erase /Q caService.dll + -@erase /Q caService.exp + -@erase /Q caService.lib + -@erase /Q *.obj + +.cc.obj: + -@erase /Q $@ + $(CC) $(CFLAGS)$< + diff --git a/src/callback/.shobj/Linux/cdevCallback.o b/src/callback/.shobj/Linux/cdevCallback.o new file mode 100644 index 0000000..f2010c3 Binary files /dev/null and b/src/callback/.shobj/Linux/cdevCallback.o differ diff --git a/src/callback/Makefile b/src/callback/Makefile new file mode 100755 index 0000000..1d1f3a2 --- /dev/null +++ b/src/callback/Makefile @@ -0,0 +1,51 @@ +# Makefile for callback directory +# +# cdev callback directory +# +# Makefile,v +# Revision 1.7 1998/08/17 14:04:48 akers +# Added 'Minor Version Number' to TARGETDIR in Makefiles +# +# Revision 1.6 1996/09/20 12:24:52 akers +# Changes added for Release 1.4 +# +# Revision 1.4 1996/06/26 15:54:09 akers +# Modifications to support multiple OS Versions +# +# Revision 1.3 1996/05/14 20:38:03 akers +# Makefile modifications +# +# Revision 1.2 1995/11/14 17:27:57 chen +# new makefile +# +# +include ../Makefile.config + +ifeq ($(SHOBJ),YES) + OBJTYPE=.shobj/$(TARGETDIR) +else + OBJTYPE=.obj/$(TARGETDIR) +endif + +ifeq ($(INCDIR), ) + INCDIR = ../.. +endif + +OBJS = $(OBJTYPE)/cdevCallback.o + +targets: $(OBJTYPE) $(OBJDIR)/$(OBJTYPE) copyobjs copyincs + +$(OBJTYPE) : + @mkdir -p $(OBJTYPE) + +$(OBJDIR)/$(OBJTYPE) : + @mkdir $(OBJDIR)/$(OBJTYPE) + +copyobjs: $(OBJS) + @cp -f $(OBJS) $(OBJDIR)/$(OBJTYPE) + +copyincs: + @cp -f *.h $(INCDIR) + +clean: clean_hail + @rm -rf *.o .obj .shobj core *~ diff --git a/src/callback/NMakefile.mak b/src/callback/NMakefile.mak new file mode 100644 index 0000000..e379b2a --- /dev/null +++ b/src/callback/NMakefile.mak @@ -0,0 +1,13 @@ +include ..\NMakefile.config + +OBJS = $(OBJDIR)\cdevCallback.obj + +targets : copyobjs copyincs + +copyobjs : $(OBJS) + -@if not exist ..\lib\$(OBJDIR) mkdir ..\lib\$(OBJDIR) + -@for %x in ($(OBJDIR)\*.obj) DO @copy %x ..\lib\$(OBJDIR) > nul + +copyincs : + -@for %x in (*.h *.i) DO @copy %x $(CDEV)\include > nul + diff --git a/src/callback/cdevCallback.cc b/src/callback/cdevCallback.cc new file mode 100755 index 0000000..bca78e2 --- /dev/null +++ b/src/callback/cdevCallback.cc @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// General cdev callback class +// +// Author: Jie Chen +// +// Revision History: +// cdevCallback.cc,v +// Revision 1.6 1997/03/03 17:35:33 chen +// add buffering to channel access connection +// +// Revision 1.5 1996/12/18 13:32:27 akers +// Added support for incomplete transactions and fireCallback method +// +// Revision 1.3 1995/10/16 17:43:19 chen +// fix a bug for SunOs gcc +// +// Revision 1.2 1995/09/05 17:18:32 chen +// add freelist and overload new/delete +// +// Revision 1.1.1.1 1995/06/16 17:14:09 epics +// initial import of cdev +// +// +#include +#include "cdevCallback.h" + +// The static incomplete_ integer +int cdevCallback::incomplete_ = 0; + +// the static free list header +cdevCallback *cdevCallback::newlist=0; + +cdevCallback::cdevCallback(void) + :function_(0), userarg_(0) +{ +#ifdef _TRACE_OBJECTS + printf("Create cdevCallback class object\n"); +#endif + // empty +} + +cdevCallback::cdevCallback(cdevCallbackFunction func, void *userarg) + :function_(func), userarg_(userarg) +{ +#ifdef _TRACE_OBJECTS + printf("Create cdevCallback class object\n"); +#endif + // empty +} + +cdevCallback::cdevCallback(const cdevCallback &callback) + :function_(callback.function_), userarg_(callback.userarg_) +{ +#ifdef _TRACE_OBJECTS + printf("Create cdevCallback class object\n"); +#endif + // empty +} + +cdevCallback &cdevCallback::operator=(const cdevCallback &callback) +{ + if(this != &callback) + { + function_=callback.function_; + userarg_=callback.userarg_; + } + return *this; +} + +cdevCallback::~cdevCallback(void) +{ +#ifdef _TRACE_OBJECTS + printf("Delete cdevCallback class object\n"); +#endif + function_=0; + // who release this memory + userarg_=0; +} + +cdevCallbackFunction +cdevCallback::callbackFunction(void) const +{ + return function_; +} + +void *cdevCallback::userarg(void) const +{ + return userarg_; +} + +int +cdevCallback::operator == (const cdevCallback &callback) +{ + if(function_ == callback.function_ && userarg_ == callback.userarg_) + return 1; + return 0; +} + +int +cdevCallback::operator != (const cdevCallback &callback) +{ + return !operator == (callback); +} + +void *cdevCallback::operator new(size_t size) +{ + if(size != sizeof(cdevCallback)) + { + // This check is crutial for cases when class + // derivation is used and the derived class + // has no operator new. + // Operator delete will field this over-sized block + // when it is reclaimed. + return malloc(size); + } + else if((cdevCallback::newlist) == 0) + { + // allocate and link +#ifdef _CDEV_DEBUG + printf("Allocate 100 cdevCallbacks \n"); +#endif + cdevCallback::newlist=(cdevCallback *) new char[100*sizeof(cdevCallback)]; + int i; + // some compiler do not like to put decleration inside + // for loop --jie chen Oct 16 1995 + for(i=0; i < 99; i++) + { + cdevCallback::newlist[i].freePtr= &(cdevCallback::newlist[i+1]); + } + cdevCallback::newlist[i].freePtr=0; + } +#ifdef _CDEV_DEBUG + printf("Get a new cdevCallback from the newList\n"); +#endif + cdevCallback *savenew=cdevCallback::newlist; + // move the pointer to the next available block + cdevCallback::newlist=cdevCallback::newlist->freePtr; + return savenew; +} + +void +cdevCallback::operator delete(void *p, size_t size) +{ + if(size != sizeof(cdevCallback)) + { + // See comments inside new operator + free(p); + } + else + { +#ifdef _CDEV_DEBUG + printf("Put a cdevCallback onto the FreeList\n"); +#endif + cdevCallback *s=(cdevCallback *) p; + // put this piece of memory back onto the head of the list + s->freePtr=cdevCallback::newlist; + cdevCallback::newlist=s; + } +} + + diff --git a/src/callback/cdevCallback.h b/src/callback/cdevCallback.h new file mode 100755 index 0000000..ac225ff --- /dev/null +++ b/src/callback/cdevCallback.h @@ -0,0 +1,154 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// general cdev callback class +// +// Author: Jie Chen and Walt Akers +// +// Revision History: +// cdevCallback.h,v +// Revision 1.10 1998/01/29 15:20:05 akers +// Ongoing development +// +// Revision 1.9 1997/07/16 18:38:41 akers +// Testing for function_ in fireCallback +// +// Revision 1.8 1997/03/03 17:35:35 chen +// add buffering to channel access connection +// +// Revision 1.7 1996/12/19 15:22:33 akers +// Ongoing development +// +// Revision 1.6 1996/12/18 13:32:28 akers +// Added support for incomplete transactions and fireCallback method +// +// Revision 1.4 1995/09/05 17:18:23 chen +// add freelist and overload new/delete +// +// Revision 1.3 1995/07/05 19:28:50 chen +// minor changes +// +// Revision 1.2 1995/07/05 18:36:39 chen +// Allow inheritance +// +// Revision 1.1.1.1 1995/06/16 17:14:10 epics +// initial import of cdev +// +// +#ifndef _CDEV_CALLBACK_H +#define _CDEV_CALLBACK_H + +#include +#include +#include + +class cdevRequestObject; +class cdevData; + +typedef void(*cdevCallbackFunction) (int status, +void *userarg, +cdevRequestObject &obj, +cdevData &result); + +class CDEV_CLASS_SPEC cdevCallback +{ +public: + // constructor and destructor + cdevCallback(void); + cdevCallback(cdevCallbackFunction, void *userarg); + cdevCallback(const cdevCallback &callback); + cdevCallback &operator=(const cdevCallback &callback); + virtual~cdevCallback(void); + + virtual cdevCallbackFunction callbackFunction(void) const; + // PURPOSE: return user callback function + // REQUIRE: nothing + // PROMISE: return 0 if there nothing + + virtual void *userarg(void) const; + // PURPUSE: return user arguments + // REQUIRE: nothing + // PROMISE: a user argument pointer + + int operator == (const cdevCallback &callback); + int operator != (const cdevCallback &callback); + // PURPOSE: if two cdevCallbacks have the same user function and user + // arguments, == return true + // REQUIRE: nothing + // PROMISE: + + void *operator new(size_t size); + void operator delete(void *p, size_t size); + // PURPOSE: overloaded new and delete operator. + // REQUIRE: none + // PROMISE: + + // ********************************************************************* + // * The fireCallback method is allows the developer to execute the + // * callback function that is specified in the cdevCallback object + // * and set the incomplete_ flag to the appropriate value prior to + // * execution, and then restore it to its default value before + // * returning. + // * + // * The value provided in the "partial" parameter will be used to set + // * the incomplete_ flag. + // ********************************************************************* + void fireCallback ( int status, + void * userarg, + cdevRequestObject & req, + cdevData & data, + int partial) + { + if(function_!=NULL) + { + incomplete_ = partial; + (*function_)(status, userarg, req, data); + incomplete_ = 0; + } + } + + // ********************************************************************* + // * The isTransactionDone method allows the caller to discover if the + // * transaction that executed the callback method is finished or + // * ongoing. + // ********************************************************************* + static int isTransactionDone ( void ) { return !incomplete_; } + +protected: + // data area + cdevCallbackFunction function_; + void *userarg_; + +private: + // Free List for all cdevCallback + // Reason: cdevCallback is a very small object (8 byte). Using free list + // can speed up a program by an order of magnitude over the + // default malloc-based memory allocation primitives. It can also + // be less wasteful of memory, eliminating malloc's overheade of + // four to eight bytes per allocation + static cdevCallback *newlist; + union + { + cdevCallback *freePtr; + char *rep; + }; + + // ********************************************************************* + // * The incomplete_ flag is used to indicate that the transaction that + // * has called this callback method is or is not finished. + // * + // * The incomplete_ flag may have the following values... + // * 0 - The transaction is finished + // * 1 - The transaction is ongoing and more callbacks may be + // * expected. + // ********************************************************************* + static int incomplete_; +}; +#endif diff --git a/src/cdevIO/.shobj/Linux/cdevData.o b/src/cdevIO/.shobj/Linux/cdevData.o new file mode 100644 index 0000000..8e6ab56 Binary files /dev/null and b/src/cdevIO/.shobj/Linux/cdevData.o differ diff --git a/src/cdevIO/.shobj/Linux/cdevDataEntry.o b/src/cdevIO/.shobj/Linux/cdevDataEntry.o new file mode 100644 index 0000000..a058817 Binary files /dev/null and b/src/cdevIO/.shobj/Linux/cdevDataEntry.o differ diff --git a/src/cdevIO/.shobj/Linux/cdevGlobalTagTable.o b/src/cdevIO/.shobj/Linux/cdevGlobalTagTable.o new file mode 100644 index 0000000..f9ccaea Binary files /dev/null and b/src/cdevIO/.shobj/Linux/cdevGlobalTagTable.o differ diff --git a/src/cdevIO/.shobj/Linux/cdevTagTable.o b/src/cdevIO/.shobj/Linux/cdevTagTable.o new file mode 100644 index 0000000..ae0a74e Binary files /dev/null and b/src/cdevIO/.shobj/Linux/cdevTagTable.o differ diff --git a/src/cdevIO/Makefile b/src/cdevIO/Makefile new file mode 100755 index 0000000..bcc8624 --- /dev/null +++ b/src/cdevIO/Makefile @@ -0,0 +1,54 @@ +# Makefile for cdevData etc +# +# cdev cdevIO directory +# +# Makefile,v +# Revision 1.9 1998/08/17 14:04:49 akers +# Added 'Minor Version Number' to TARGETDIR in Makefiles +# +# Revision 1.8 1996/07/10 21:03:31 chen +# add mkdir -p +# +# Revision 1.7 1996/06/26 15:54:10 akers +# Modifications to support multiple OS Versions +# +# Revision 1.6 1996/05/14 20:38:05 akers +# Makefile modifications +# +# Revision 1.5 1995/11/14 17:30:15 chen +# new makefile +# +# +include ../Makefile.config + +ifeq ($(SHOBJ),YES) + OBJTYPE=.shobj/$(TARGETDIR) +else + OBJTYPE=.obj/$(TARGETDIR) +endif + +ifeq ($(INCDIR), ) + INCDIR = ../.. +endif + +OBJS = $(OBJTYPE)/cdevData.o \ + $(OBJTYPE)/cdevDataEntry.o \ + $(OBJTYPE)/cdevTagTable.o \ + $(OBJTYPE)/cdevGlobalTagTable.o + +targets: $(OBJTYPE) $(OBJDIR)/$(OBJTYPE) copyobjs copyincs + +$(OBJTYPE) : + @mkdir -p $(OBJTYPE) + +$(OBJDIR)/$(OBJTYPE) : + @mkdir -p $(OBJDIR)/$(OBJTYPE) + +copyobjs: $(OBJS) + @cp $(OBJS) $(OBJDIR)/$(OBJTYPE) + +copyincs: + @cp *.h *.i $(INCDIR) + +clean: clean_hail + @rm -rf *.o .obj .shobj core *~ diff --git a/src/cdevIO/NMakefile.mak b/src/cdevIO/NMakefile.mak new file mode 100644 index 0000000..79a7845 --- /dev/null +++ b/src/cdevIO/NMakefile.mak @@ -0,0 +1,16 @@ +include ..\NMakefile.config + +OBJS = $(OBJDIR)\cdevData.obj \ + $(OBJDIR)\cdevDataEntry.obj \ + $(OBJDIR)\cdevTagTable.obj \ + $(OBJDIR)\cdevGlobalTagTable.obj + +targets : copyobjs copyincs + +copyobjs : $(OBJS) + -@if not exist ..\lib\$(OBJDIR) mkdir ..\lib\$(OBJDIR) + -@for %x in ($(OBJDIR)\*.obj) DO @copy %x ..\lib\$(OBJDIR) > nul + +copyincs : + -@for %x in (*.h *.i) DO @copy %x $(CDEV)\include > nul + diff --git a/src/cdevIO/cdevData.cc b/src/cdevIO/cdevData.cc new file mode 100755 index 0000000..4cc9587 --- /dev/null +++ b/src/cdevIO/cdevData.cc @@ -0,0 +1,3543 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: cdevData.h +// Generic tool designed to convert arrays of data types from one +// type to another +// +// Author: Walt Akers and Danjin Wu +// +// Revision History: +// cdevData.cc,v +// Revision 1.30 1998/04/09 16:06:58 akers +// Corrected problem with cdevDataIterator::operator++ +// +// Revision 1.29 1997/08/01 19:06:27 akers +// Added addTag and tagExists feature to the library +// +// Revision 1.28 1997/06/12 19:37:06 akers +// Rest incoming data +// +// Revision 1.27 1997/04/16 19:32:08 akers +// Ongoing development +// +// Revision 1.26 1997/01/14 19:39:30 chen +// add += operator +// +// Revision 1.25 1996/12/06 20:57:06 akers +// Patched minor error +// +// Revision 1.24 1996/11/21 17:02:54 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.23 1996/08/26 19:14:02 akers +// Adding cdevData.inserttag callback capabilities +// +// Revision 1.22 1996/08/23 15:34:04 akers +// Added comparison operator to cdevData +// +// Revision 1.21 1996/07/26 15:43:28 akers +// Minor change to copy operator +// +// Revision 1.20 1996/07/12 18:08:38 chen +// change copy and assignment to const cdevData& +// +// Revision 1.19 1995/12/01 21:14:49 danjin +// fix setBounds function +// +// Revision 1.18 1995/11/08 14:30:55 chen +// Fix for Irix5.3 +// +// Revision 1.17 1995/10/30 13:33:12 akers +// Added cdev specific version of strncpy +// +// Revision 1.16 1995/10/16 18:14:28 chen +// Fix a bug for SunOs and g++ +// +// Revision 1.15 1995/10/06 19:38:42 chen +// Seperate inline functions +// +// Revision 1.14 1995/10/03 19:36:25 chen +// Use new cdevGlobalTagTable Class +// +// Revision 1.13 1995/09/22 21:04:10 danjin +// added cdevDataIterator mechanism +// +// Revision 1.12 1995/09/13 15:27:50 danjin +// added changeTagName(oldtag, newtag) func +// +// Revision 1.11 1995/09/06 18:34:02 danjin +// added time stamp structure and related func +// +// Revision 1.10 1995/08/03 17:07:43 akers +// *** empty log message *** +// +// Revision 1.9 1995/08/03 15:24:23 akers +// Added overloaded double precision gcvt and inlined both gcvt functions +// +// Revision 1.8 1995/08/03 13:59:54 akers +// Added floating point version of gcvt to elliminate conversion errors +// +// Revision 1.7 1995/08/02 20:37:57 akers +// Forced char ** tagged data items to have a NULL value appended ath the end. +// +// Revision 1.6 1995/07/20 14:36:47 akers +// Mispelling in header +// +// Revision 1.5 1995/07/19 20:34:03 akers +// CVS +// +// Revision 1.4 1995/07/14 13:01:10 akers +// Updated version of cdevData source code +// +// +// +//-------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include + +#ifdef _CDEV_NO_INLINE +#include "cdevData.i" +#endif + +// ***************************************************************************** +// * gcvt: +// * This overloaded function is being used in conjunction with the +// * standard library gcvt to correct conversion errors when converting +// * float values. +// ***************************************************************************** +static char *gcvt(float value, size_t ndigit, char *buf) + { + char tbuf[32]; + sprintf(tbuf, "%.7g", value); + cdevStrncpy(buf, tbuf, ndigit); + return buf; + } + +static char *gcvt(double value, size_t ndigit, char * buf) + { + char tbuf[32]; + sprintf(tbuf, "%.14g", value); + cdevStrncpy(buf, tbuf, ndigit); + return buf; + } + + +// ***************************************************************************** +// * cdevConverter: +// * This is the type definition for all cdev conversion functions. These +// * functions are used to perform data conversion from one cdev datatype +// * to another. +// ***************************************************************************** +typedef void (*cdevConverter)(void * input, void * output, size_t nElems); + +// ***************************************************************************** +// * cdevConversionMatrix: +// * This matrix contains the cdev conversion functions necessary to convert +// * between all cdev data types. The user requests a conversion routime +// * by using the enumerated cdevDataType values that represent the from +// * type and the too type. +// * +// * For instance: +// * To convert from 16 bit integer to 32 bit integer, cdevData would +// * use the command... +// * cdevConversionMatrix[CDEV_INT16][CDEV_INT32](&in16, &out32, 1); +// * +// * To convert an array of 25 floats to an array of 25 doubles, +// * cdevData would use the command... +// * cdevConversionMatrix[CDEV_FLOAT][CDEV_DOUBLE](in, out, 25) +// ***************************************************************************** +extern const cdevConverter cdevConversionMatrix [CDEV_INVALID+1][CDEV_INVALID+1]; + +// ***************************************************************************** +// * copy: +// * This function copies the contents of the cdevData object specified by +// * data into this cdevData object. It is used by both the copy constructor +// * and by the assignment operator. +// ***************************************************************************** +cdevData & cdevData::copy (const cdevData & data) + { + if(this != (cdevData *)&data) + { + remove(); + for(cdevDataEntry *ptr = data.entries; ptr!=NULL; ptr = ptr->next_) + { + switch(ptr->dataType_) + { + case CDEV_BYTE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.cval); + else insert(ptr->tag_, ptr->data_.cptr, ptr->elems_, ptr->dim_); + break; + + case CDEV_INT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.sval); + else insert(ptr->tag_, ptr->data_.sptr, ptr->elems_, ptr->dim_); + break; + + case CDEV_UINT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.usval); + else insert(ptr->tag_, ptr->data_.usptr, ptr->elems_, ptr->dim_); + break; + + case CDEV_INT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.lval); + else insert(ptr->tag_, ptr->data_.lptr, ptr->elems_, ptr->dim_); + break; + + case CDEV_UINT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.ulval); + else insert(ptr->tag_, ptr->data_.ulptr, ptr->elems_, ptr->dim_); + break; + + case CDEV_FLOAT: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.fval); + else insert(ptr->tag_, ptr->data_.fptr, ptr->elems_, ptr->dim_); + break; + + case CDEV_DOUBLE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.dval); + else insert(ptr->tag_, ptr->data_.dptr, ptr->elems_, ptr->dim_); + break; + + case CDEV_STRING: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.str); + else insert(ptr->tag_, ptr->data_.strarr, ptr->elems_, ptr->dim_); + break; + + case CDEV_TIMESTAMP: + if (ptr->dim_==0) insert(ptr->tag_, ptr->data_.ts); + else insert(ptr->tag_, ptr->data_.tsptr, ptr->elems_, ptr->dim_); + break; + + default: + break; + } + if(ptr->tag_ && ptr->dim_ && ptr->dataType_tag_, ptr->bounds(), ptr->dim_); + } + } + return *this; + } + +// ***************************************************************************** +// * tagC2I: +// * This function converts a character string tag to its associated tag +// * number. This function serves only to call the functions and retrieve +// * the data that are within the cdevGlobalTagTable object. +// ***************************************************************************** +int cdevData::tagC2I(char *ctag, int *tag) + { + return cdevGlobalTagTable::tagTable()->tagC2I(ctag, tag); + } + +// ***************************************************************************** +// * tagI2C: +// * This function converts an integer tag to its associated character string +// * name. This function serves only to call the functions and retrieve the +// * data that are within the cdevGlobalTagTable object. +// ***************************************************************************** +int cdevData::tagI2C(int tag, char * &ctag) + { + return cdevGlobalTagTable::tagTable()->tagI2C(tag, ctag); + } + +// ***************************************************************************** +// * insertTag: +// * This function adds a new tag and its associated character string to the +// * global table of tags. This function serves only to call the functions +// * and retrieve the data that are within the cdevGlobalTagTable object. +// ***************************************************************************** +void cdevData::insertTag(int tag, char *ctag) + { + cdevGlobalTagTable::tagTable()->insertTag(tag, ctag); + } + +// ***************************************************************************** +// * cdevData::tagExists: +// * This function can be called to determine if a tag string has already +// * been added to the cdevTagTable. The value returned is a boolean +// * result that is TRUE (non-zero) if the tag exists or FALSE (0) if not. +// ***************************************************************************** +int cdevData::tagExists ( char * ctag ) + { + return cdevGlobalTagTable::tagTable()->tagExists(ctag); + } + + +// ***************************************************************************** +// * cdevData::tagExists: +// * This function can be called to determine if a tag integer has already +// * been added to the cdevTagTable. The value returned is a boolean +// * result that is TRUE (non-zero) if the tag exists or FALSE (0) if not. +// ***************************************************************************** +int cdevData::tagExists ( int tag ) + { + return cdevGlobalTagTable::tagTable()->tagExists(tag); + } + +// ***************************************************************************** +// * cdevData::addTag : +// * This method will add the tag string to the cdevTagTable if it +// * does not already exist. Tag Table will start searching for the +// * next available tag number above 1000. The value returned by the +// * function will be the integer that is assigned to the character string +// * tag. +// ***************************************************************************** +int cdevData::addTag ( char * ctag ) + { + return cdevGlobalTagTable::tagTable()->addTag(ctag); + } + +// *************************************************************************** +// * cdevData::addTagCallback : +// * This method will add a cdevTagTableCallback object to the list of +// * classes that should be notified each time a tag is added to the +// * cdevTagTable. +// *************************************************************************** +void cdevData::addTagCallback ( cdevTagTableCallback * cb ) + { + cdevGlobalTagTable::tagTable()->addTagCallback(cb); + } + +// *************************************************************************** +// * cdevData::delTagCallback : +// * This method will remote a cdevTagTableCallback object that was +// * previously added to the list of callback classes. +// * +// * Note: This method does not actually delete the cdevTagTableCallback +// * object, it merely removes it from the list. It is the +// * responsibility of the owner to delete the object when it is +// * no longer needed. +// *************************************************************************** +void cdevData::delTagCallback ( cdevTagTableCallback * cb ) + { + cdevGlobalTagTable::tagTable()->delTagCallback(cb); + } + +// ***************************************************************************** +// * cdevData::readTagTable : +// * This method allows the caller to obtain a list of tag names and +// * integers that are currently stored in this tag table. +// * +// * Note: This method will allocate an array of integers and an array of +// * character string pointers. The strings that are stored in the +// * string array will be the actual strings from within the +// * tag table and should not be deleted... +// * +// * The data allocated becomes the property of the caller and must +// * be deleted when it is no longer needed... the correct syntax to +// * delete these items is... +// * +// * delete tags; +// * delete ctags; +// * +// * This will delete the array, however, it will leave the +// * individual array elements intact. +// ***************************************************************************** +int cdevData::readTagTable ( int * &tags, char ** &ctags, int &ntags ) + { + return cdevGlobalTagTable::tagTable()->readTagTable(tags, ctags, ntags); + } + + +// ***************************************************************************** +// * lookupTag: +// * This function attempts to locate the specified tag within the cdevData +// * objects list of cdevDataEntry objects. If the tag is found, then +// * its associated cdevDataEntry object will be returned, otherwise, +// * if the caller has specified a non-zero value in the create flag, then +// * the new tag will be added to the list. +// ***************************************************************************** +cdevDataEntry * cdevData::lookupTag(int tag, int create) + { + cdevDataEntry *result = NULL, *prev = NULL; + + // ********************************************************************* + // * Walk through the list of cdevDataEntry objects until a matching + // * tag is found, or until no more items are available. + // ********************************************************************* + for(result=entries; + result!=NULL && result->tag_!=tag; + prev=result, result = result->next_); + + // ********************************************************************* + // * If result is NULL, then a matching entry was not found. If the + // * user has specified create, then create a new entry. + // ********************************************************************* + if ( result==NULL && create ) + { + // ************************************************************* + // * The prev flag is used to indicate the last known + // * cdevDataEntry object in the list. If prev contains NULL, + // * then the list was empty and must be allocated directly. + // ************************************************************* + if( prev == NULL ) + { + entries = new cdevDataEntry; + result = entries; + } + // ************************************************************* + // * Otherwise, the new cdevDataEntry object should be placed + // * at the bottom of the list. + // ************************************************************* + else + { + prev->next_ = new cdevDataEntry; + result = prev->next_; + } + } + + return result; + } + +// ***************************************************************************** +// * setupTag: +// * Convenience function to allow the cdevData object to more efficiently +// * prepare new cdevDataEntry objects for data insertion. +// * elemSize is the size of one element in bytes, numElems is the number of +// * elements to allocate, and numDims is the number of dimensions to create. +// ***************************************************************************** +cdevDataEntry * cdevData::setupTag (int tag, cdevDataTypes type, size_t elemSize, + size_t numElems, size_t numDims ) + { + cdevDataEntry * entry; + if((entry = lookupTag(tag, 1))!=NULL) + { + // ************************************************************* + // * If the entry is already populated and the new data is not + // * multidimensional, clear the old contents. + // ************************************************************* + if(entry->tag_ == tag && numDims<=0) entry->clear(); + + // ************************************************************* + // * If the entry is multidimensional, allocate a new data + // * block for storing the data. + // ************************************************************* + if(numDims > 0) + { + entry->allocate(numDims, numElems, elemSize); + if(numDims > 0) + { + cdevBounds * bounds = entry->bounds(); + // ***************************************************** + // * Set the first cdevBounds structure to indicate the + // * entire array. Subsequent structures (if any), + // * should indicate an offset of 0 and a length of 1. + // ***************************************************** + bounds[0].offset = 0; + bounds[0].length = numElems; + for(int i = 1; i < numDims; i++) + { + bounds[i].offset = 0; + bounds[i].length = 1; + } + } + } + + // ************************************************************* + // * Populate the entry with the new data. + // ************************************************************* + entry->tag_ = tag; + entry->dataType_ = type; + } + return entry; + } + + +// ***************************************************************************** +// * cdevData: +// * Default constructor for the cdevData object. Initializes local data. +// ***************************************************************************** +cdevData::cdevData ( void ) : entries(NULL) + { + } + +// ***************************************************************************** +// * cdevData: +// * Copy constructor. This constructor duplicates the cdevData object that +// * it has been passed as a parameter. +// ***************************************************************************** +cdevData::cdevData ( const cdevData & data ) : entries(NULL) + { + copy(data); + } + +// ***************************************************************************** +// * ~cdevData: +// * Default destructor for the cdevData object. Deallocates local data. +// ***************************************************************************** +cdevData::~cdevData( void ) + { + remove(); + } + +// ***************************************************************************** +// * xdrSize: +// * Calculates the size of the XDR Buffer necessary to store the cdevData +// * object. This function may be used to determine the size of a +// * preallocated buffer for storing the xdr representation of a cdevData +// * object. The bufLen parameter will receive the size of the buffer, and +// * the elementCount variable will receive the number of elements that will +// * be stored in the buffer. +// ***************************************************************************** +int cdevData::xdrSize (size_t * bufLen, size_t * elementCount) + { + cdevDataEntry * ptr = entries; + int xdrDataSize = 0; + int cdevElementCnt = 0; + int i; + + // ************************************# + // * CALCULATE THE SIZE OF THE BUFFER # + // ************************************# + // ************************************* + // * Add the size of the tag count int * + // ************************************* + xdrDataSize += XDR_Sizeof(cdevElementCnt); + + // ************************************* + // * Add the size of each valid item * + // ************************************* + for(ptr=entries; ptr!=NULL; ptr = ptr->next_) + { + // ***************************** + // * Do not process entries * + // * with CDEV_INVALID as the * + // * dataType or 0 as the tag. * + // ***************************** + if(ptr->dataType_==CDEV_INVALID || ptr->tag_==0) continue; + + // ***************************** + // * Calculate the number of * + // * elements in this tagged * + // * data item. * + // ***************************** + int numElements = ptr->dim_!=0?ptr->elems_:1; + + // ***************************** + // * Increment the counter * + // ***************************** + cdevElementCnt++; + + // ***************************** + // * Add the size of the * + // * cdevDataEntries tag_, * + // * dataType_, dim_, elems_. * + // ***************************** + xdrDataSize += 4 * XDR_Sizeof((int)1); + + // ***************************** + // * Add the size of the * + // * cdevBounds data. * + // ***************************** + xdrDataSize += ptr->dim_ * (XDR_Sizeof((int)1) * 2); + + // ***************************** + // * Add the size of the data * + // ***************************** + if (ptr->dataType_==CDEV_BYTE) xdrDataSize += numElements * XDR_Sizeof((unsigned char)'c'); + else if(ptr->dataType_==CDEV_INT16) xdrDataSize += numElements * XDR_Sizeof((short)1); + else if(ptr->dataType_==CDEV_UINT16) xdrDataSize += numElements * XDR_Sizeof((unsigned short)1); + else if(ptr->dataType_==CDEV_INT32) xdrDataSize += numElements * XDR_Sizeof((long)1); + else if(ptr->dataType_==CDEV_UINT32) xdrDataSize += numElements * XDR_Sizeof((unsigned long)1); + else if(ptr->dataType_==CDEV_FLOAT) xdrDataSize += numElements * XDR_Sizeof((float)1); + else if(ptr->dataType_==CDEV_DOUBLE) xdrDataSize += numElements * XDR_Sizeof((double)1); + else if(ptr->dataType_==CDEV_STRING) + { + if(numElements==1) xdrDataSize += XDR_Sizeof(ptr->data_.str); + else for(i=0; idata_.strarr[i]); + } + else if(ptr->dataType_==CDEV_TIMESTAMP) xdrDataSize += numElements * XDR_Sizeof(ptr->data_.ts); + } + + *elementCount = cdevElementCnt; + *bufLen = xdrDataSize; + + return *bufLen>0?CDEV_SUCCESS:CDEV_ERROR; + } + + +// ***************************************************************************** +// * xdrExport: +// * This function encapsulates the contents of the cdevData class into a +// * binary stream. This function allocates the buffer and returns the new +// * buffer and the buffer size. +// ***************************************************************************** +int cdevData::xdrExport ( char ** buf, size_t * bufLen ) + { + size_t count = 0; + + // ************************************# + // * Calculate the size of the buffer # + // ************************************# + xdrSize(bufLen, &count); + + // ************************************# + // * Allocate the buffer and call the # + // * export function. # + // ************************************# + if((*buf = new char[*bufLen])!=NULL) xdrExport(*buf, *bufLen, count); + + return buf==NULL?CDEV_ERROR:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * xdrExport: +// * This function encapsulates the contents of the cdevData class into a +// * preallocated binary stream. The buf parameter contains the address of +// * the caller allocated buffer, the bufLen parameter specifies the size +// * of the buffer, and the count parameter specifies the number of tagged +// * data items that will be copied from the cdevData object into the +// * binary stream. +// ***************************************************************************** +int cdevData::xdrExport ( char * buf, size_t bufLen, size_t count) + { + cdevDataEntry * ptr; + XDR_Writer writer; + int xdrDataSize = bufLen; + int cdevElementCnt = count; + int i; + + // ************************************# + // * Allocate the buffer # + // ************************************# + writer.attachData(buf, bufLen); + + // ************************************# + // * Transfer the data to the buffer # + // ************************************# + // ************************************* + // * Write the number of elements * + // ************************************* + writer.put(cdevElementCnt); + + // ************************************* + // * Write each valid item. * + // ************************************* + for(ptr = entries; ptr != NULL; ptr = ptr->next_) + { + // ***************************** + // * Do not process entries * + // * with CDEV_INVALID as the * + // * dataType or 0 as the tag. * + // ***************************** + if(ptr->dataType_==CDEV_INVALID || ptr->tag_==0) continue; + + // ***************************** + // * Calculate the number of * + // * elements in this tagged * + // * data item. * + // ***************************** + int numElements = ptr->dim_!=0?ptr->elems_:1; + + // ***************************** + // * Decrement the counter * + // ***************************** + cdevElementCnt--; + + // ***************************** + // * Write the tag_, dataType_ * + // * dim_, and elems_ of the * + // * cdevDataEntry object. * + // ***************************** + writer.put((int)ptr->tag_); + writer.put((int)ptr->dataType_); + writer.put((int)ptr->dim_); + writer.put((int)ptr->elems_); + + // ***************************** + // * Write the cdevBounds * + // * values asssociated with * + // * the cdevDataEntry (if any)* + // ***************************** + cdevBounds * bounds = ptr->bounds(); + for(i=0; idim_; i++) + { + writer.put((int)bounds[i].offset); + writer.put((int)bounds[i].length); + } + + // ***************************** + // * Write the data * + // ***************************** + if (ptr->dataType_==CDEV_BYTE) + { + if(numElements==1) writer.put(ptr->data_.cval); + else for(i=0; idata_.cptr[i]); + } + else if(ptr->dataType_==CDEV_INT16) + { + if(numElements==1) writer.put(ptr->data_.sval); + else for(i=0; idata_.sptr[i]); + } + else if(ptr->dataType_==CDEV_UINT16) + { + if(numElements==1) writer.put(ptr->data_.usval); + else for(i=0; idata_.usptr[i]); + } + else if(ptr->dataType_==CDEV_INT32) + { + if(numElements==1) writer.put(ptr->data_.lval); + else for(i=0; idata_.lptr[i]); + } + else if(ptr->dataType_==CDEV_UINT32) + { + if(numElements==1) writer.put(ptr->data_.ulval); + else for(i=0; idata_.ulptr[i]); + } + else if(ptr->dataType_==CDEV_FLOAT) + { + if(numElements==1) writer.put(ptr->data_.fval); + else for(i=0; idata_.fptr[i]); + } + else if(ptr->dataType_==CDEV_DOUBLE) + { + if(numElements==1) writer.put(ptr->data_.dval); + else for(i=0; idata_.dptr[i]); + } + else if(ptr->dataType_==CDEV_STRING) + { + if(numElements==1) writer.put(ptr->data_.str); + else for(i=0; idata_.strarr[i]); + } + else if(ptr->dataType_==CDEV_TIMESTAMP) + { + if(numElements==1) writer.put(ptr->data_.ts); + else for(i=0; idata_.tsptr[i]); + } + } + + // ************************************* + // * Detach the data from the writer * + // * object before the object is * + // * destroyed. * + // ************************************* + writer.detachData(); + + return CDEV_SUCCESS; + } + +// ***************************************************************************** +// * xdrImport: +// * This function populates the cdevData class using the contents of a +// * binary buffer that has bee created by the xdrExport function. +// ***************************************************************************** +int cdevData::xdrImport ( char * buf, size_t bufLen) + { + XDR_Reader reader; + int cdevElementCnt; + int i, j; + int xdrError = CDEV_SUCCESS; + + if(buf==NULL || bufLen==0) return CDEV_INVALIDARG; + + // ************************************* + // * Transfer the data buffers to the * + // * XDR_Reader class. * + // ************************************* + reader.attachData(buf, bufLen); + + // ************************************* + // * Deallocate any data previously * + // * assigned to the cdevData class. * + // ************************************* + remove(); + + // ************************************* + // * Read the element count from the * + // * buffer. * + // ************************************* + if(reader.get(cdevElementCnt)==0) xdrError = CDEV_ERROR; + + // ************************************* + // * Process each tagged element in * + // * the buffer. * + // ************************************* + for(i=0; idata_.cval)?CDEV_SUCCESS:CDEV_ERROR; + else for(j=0; jdata_.cptr[j])?CDEV_SUCCESS:CDEV_ERROR; + } + } + break; + + case CDEV_INT16: + if((entry = setupTag(tag_, dataType_, sizeof(short), numElements, dim_))!=NULL) + { + if(numElements==1) xdrError = reader.get(entry->data_.sval)?CDEV_SUCCESS:CDEV_ERROR; + else for(j=0; jdata_.sptr[j])?CDEV_SUCCESS:CDEV_ERROR; + } + } + break; + + case CDEV_UINT16: + if((entry = setupTag(tag_, dataType_, sizeof(unsigned short), numElements, dim_))!=NULL) + { + if(numElements==1) xdrError = reader.get(entry->data_.usval)?CDEV_SUCCESS:CDEV_ERROR; + else for(j=0; jdata_.usptr[j])?CDEV_SUCCESS:CDEV_ERROR; + } + } + break; + + case CDEV_INT32: + if((entry = setupTag(tag_, dataType_, sizeof(long), numElements, dim_))!=NULL) + { + if(numElements==1) xdrError = reader.get(entry->data_.lval)?CDEV_SUCCESS:CDEV_ERROR; + else for(j=0; jdata_.lptr[j])?CDEV_SUCCESS:CDEV_ERROR; + } + } + break; + + case CDEV_UINT32: + if((entry = setupTag(tag_, dataType_, sizeof(unsigned long), numElements, dim_))!=NULL) + { + if(numElements==1) xdrError = reader.get(entry->data_.ulval)?CDEV_SUCCESS:CDEV_ERROR; + else for(j=0; jdata_.ulptr[j])?CDEV_SUCCESS:CDEV_ERROR; + } + } + break; + + case CDEV_FLOAT: + if((entry = setupTag(tag_, dataType_, sizeof(float), numElements, dim_))!=NULL) + { + if(numElements==1) xdrError = reader.get(entry->data_.fval)?CDEV_SUCCESS:CDEV_ERROR; + else for(j=0; jdata_.fptr[j])?CDEV_SUCCESS:CDEV_ERROR; + } + } + break; + + case CDEV_DOUBLE: + if((entry = setupTag(tag_, dataType_, sizeof(double), numElements, dim_))!=NULL) + { + if(numElements==1) xdrError = reader.get(entry->data_.dval)?CDEV_SUCCESS:CDEV_ERROR; + else for(j=0; jdata_.dptr[j])?CDEV_SUCCESS:CDEV_ERROR; + } + } + break; + + case CDEV_STRING: + { + char ** ptr = new char *[numElements]; + memset(ptr, 0, sizeof(char *)*numElements); + + for(j=0; jdata_.ts)?CDEV_SUCCESS:CDEV_ERROR; + else for(j=0; jdata_.tsptr[j])?CDEV_SUCCESS:CDEV_ERROR; + } + } + break; + + case CDEV_INVALID: + break; + } + if(dim_!=0 && xdrError==CDEV_SUCCESS) setBounds(tag_, bounds, dim_); + } + + if(bounds!=NULL) delete bounds; + } + + // ************************************* + // * Divorce the data from the reader * + // * object before the object is * + // * destroyed. * + // ************************************* + reader.detachData(); + + return xdrError; + } + +// ***************************************************************************** +// * remove: +// * Removes the all cdevDataEntry objects from the cdevData object. +// ***************************************************************************** +void cdevData::remove( void ) + { + while(entries!=NULL) + { + cdevDataEntry * ptr = entries; + entries = ptr->next_; + delete ptr; + } + } + +// ***************************************************************************** +// * remove: +// * Removes a specified tagged data item from the cdevData object. +// ***************************************************************************** +void cdevData::remove(int tag) + { + cdevDataEntry *result = NULL, *prev = NULL; + + // ********************************************************************* + // * Walk through the list of cdevDataEntry objects until a matching + // * tag is found, or until no more items are available. + // ********************************************************************* + for(result=entries; + result!=NULL && result->tag_!=tag; + prev=result, result = result->next_); + + if(result!=NULL) + { + if(prev!=NULL) prev->next_ = result->next_; + else entries = result->next_; + delete result; + } + } + +// ********************************************************************* +// * changeTag: +// * Replace a new tag with the old one within the +// * cdevData object. If the old one can not be not found, +// * CDEV_NOTFOUND is returned. If the new tag has already +// * been found in that cdevData object, CDEV_ERROR is returned. +// ********************************************************************* +int cdevData::changeTag(int oldTag, int newTag) + { + int result; + cdevDataEntry *entry; + if((entry=lookupTag(oldTag)) == NULL) result = CDEV_NOTFOUND; + else + { + if( lookupTag(newTag) != NULL) result = CDEV_ERROR; + else + { + entry->tag_ = newTag; + result = CDEV_SUCCESS; + } + } + return result; + } + +int cdevData::changeTag(int oldTag, char *c_newTag) + { + int tag; + return tagC2I(c_newTag, &tag)?CDEV_NOTFOUND:changeTag(oldTag, tag); + } + +int cdevData::changeTag(char *c_oldTag, int newTag) + { + int tag; + return tagC2I(c_oldTag, &tag)?CDEV_NOTFOUND:changeTag(tag, newTag); + } + +int cdevData::changeTag(char *c_oldTag, char *c_newTag) + { + int tag1, tag2; + if ( (tagC2I(c_oldTag, &tag1)==0) && (tagC2I(c_newTag, &tag2)==0) ) + return ( changeTag(tag1, tag2) ); + else + return CDEV_NOTFOUND; + } + + +// ***************************************************************************** +// * getType: +// * Retrieves the cdevDataTypes of the referenced tagged data item. +// * If no item with that tag is within the cdevData object, then +// * CDEV_INVALID is returned. +// ***************************************************************************** +cdevDataTypes cdevData::getType(int tag) + { + cdevDataEntry * entry = lookupTag(tag); + return entry==NULL?CDEV_INVALID:entry->dataType_; + } + +// ***************************************************************************** +// * getDim: +// * Obtains the number of dimensions in the specified tagged data +// * item. Returns CDEV_SUCCESS if the tagged item exists, otherwise, +// * CDEV_NOTFOUND is returned. +// ***************************************************************************** +int cdevData::getDim(int tag, size_t *dim) + { + cdevDataEntry * entry = lookupTag(tag); + *dim = entry==NULL?0:entry->dim_; + return entry==NULL?CDEV_NOTFOUND:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * getElems: +// * Obtains the number of elements in the specified tagged data +// * item. Returns CDEV_SUCCESS if the tagged item exists, otherwise, +// * CDEV_NOTFOUND is returned. +// ***************************************************************************** +int cdevData::getElems(int tag, size_t *elems) + { + cdevDataEntry * entry = lookupTag(tag); + *elems = entry==NULL?0:(entry->dim_>0?entry->elems_:1); + return entry==NULL?CDEV_NOTFOUND:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * getBounds: +// * Obtains the bounding dimensions of a cdevDataEntry array. The +// * integer array passed as the bounds parameter must be allocated +// * by the caller. The number of integers required is 2 times the +// * number of dimensions. The len parameter specifies the actual +// * number of integers allocated. +// ***************************************************************************** +int cdevData::getBounds( int tag, size_t * bounds, size_t len ) + { + cdevDataEntry * entry = lookupTag(tag); + memset(bounds, 0, len*sizeof(size_t)); + if(entry!=NULL && entry->dim_>0) + { + int i; + cdevBounds * entryBounds = entry->bounds(); + len = (len/2 < entry->dim_) ? len/2 : entry->dim_; + for(i=0; idim_ > 0) + { + int i; + cdevBounds * entryBounds = entry->bounds(); + numBounds = (numBoundsdim_) ? numBounds : entry->dim_; + for(i=0; idim_>0) + { + int i; + int actualItems=1; + + cdevBounds * entryBounds = entry->bounds(); + len = (len/2 < entry->dim_) ? len/2 : entry->dim_; + + for(i=0; ielems_) + { + char * ctag; + cdevGlobalTagTable::tagTable()->tagI2C(tag, ctag); + result = CDEV_INVALIDARG; + } + else + { + int j = 0; + for(i=0; idim_ > 0) + { + int i; + int actualItems = 1; + + cdevBounds * entryBounds = entry->bounds(); + numBounds = (numBoundsdim_) ? numBounds : entry->dim_; + + for(i=0; ielems_) + { + char * ctag; + cdevGlobalTagTable::tagTable()->tagI2C(tag, ctag); + result = CDEV_INVALIDARG; + } + else + { + for(i=0; idata_.cval= data; + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar short int value into a cdevDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int cdevData::insert(int tag, short data) + { + cdevDataEntry * entry; + + if((entry = setupTag(tag, CDEV_INT16, sizeof(short), 1, 0))!=NULL) + { + entry->data_.sval= data; + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar unsigned short int value into a +// * cdevDataEntry object as a tagged data item. +// ***************************************************************************** +int cdevData::insert(int tag, unsigned short data) + { + cdevDataEntry * entry; + + if((entry = setupTag(tag, CDEV_UINT16, sizeof(unsigned short), 1, 0))!=NULL) + { + entry->data_.usval= data; + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar long int value into a cdevDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int cdevData::insert(int tag, long data) + { + cdevDataEntry * entry; + + if((entry = setupTag(tag, CDEV_INT32, sizeof(long), 1, 0))!=NULL) + { + entry->data_.lval= data; + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar unsigned long int value into a +// * cdevDataEntry object as a tagged data item. +// ***************************************************************************** +int cdevData::insert(int tag, unsigned long data) + { + cdevDataEntry * entry; + + if((entry = setupTag(tag, CDEV_UINT32, sizeof(long), 1, 0))!=NULL) + { + entry->data_.ulval= data; + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar float value into a cdevDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int cdevData::insert(int tag, float data) + { + cdevDataEntry * entry; + + if((entry = setupTag(tag, CDEV_FLOAT, sizeof(float), 1, 0))!=NULL) + { + entry->data_.fval= data; + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a scalar double value into a cdevDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int cdevData::insert(int tag, double data) + { + cdevDataEntry * entry; + + if((entry = setupTag(tag, CDEV_DOUBLE, sizeof(double), 1, 0))!=NULL) + { + entry->data_.dval= data; + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * insert: +// * Allows the caller to insert a time stamp value into a cdevDataEntry +// * object as a tagged data item. +// ***************************************************************************** +int cdevData::insert ( int tag, cdev_TS_STAMP data ) + { + cdevDataEntry * entry; + + if((entry = setupTag(tag, CDEV_TIMESTAMP, sizeof(cdev_TS_STAMP), 1, 0))!=NULL) + { + entry->data_.ts.secPastEpoch = data.secPastEpoch; + entry->data_.ts.nsec = data.nsec; + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of characters arrays of data +// * into a cdevData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int cdevData::insert (int tag, BYTE * data, size_t len, size_t ndim) + { + cdevDataEntry * entry; + + if(len==1 && data!=NULL) return insert(tag, *data); + else if(len<=0 || data==NULL) return CDEV_INVALIDARG; + else if((entry = setupTag(tag, CDEV_BYTE, sizeof(char), len, ndim))!=NULL) + { + memcpy(entry->data_.cptr, data, len*sizeof(char)); + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of short int arrays of data +// * into a cdevData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int cdevData::insert (int tag, short * data, size_t len, size_t ndim) + { + cdevDataEntry * entry; + + if(len==1 && data!=NULL) return insert(tag, *data); + else if(len<=0 || data==NULL) return CDEV_INVALIDARG; + else if((entry = setupTag(tag, CDEV_INT16, sizeof(short), len, ndim))!=NULL) + { + memcpy(entry->data_.sptr, data, len*sizeof(short)); + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of unsigned short int arrays +// * of data into a cdevData object. The len variable contains the total +// * number of elements to be inserted, the ndim variable indicates the +// * number of dimensions in the array. +// ***************************************************************************** +int cdevData::insert (int tag, unsigned short * data, size_t len, size_t ndim) + { + cdevDataEntry * entry; + + if(len==1 && data!=NULL) return insert(tag, *data); + else if(len<=0 || data==NULL) return CDEV_INVALIDARG; + else if((entry = setupTag(tag, CDEV_UINT16, sizeof(unsigned short), len, ndim))!=NULL) + { + memcpy(entry->data_.usptr, data, len*sizeof(unsigned short)); + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of long int arrays of data +// * into a cdevData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int cdevData::insert (int tag, long * data, size_t len, size_t ndim) + { + cdevDataEntry * entry; + + if(len==1 && data!=NULL) return insert(tag, *data); + else if(len<=0 || data==NULL) return CDEV_INVALIDARG; + else if((entry = setupTag(tag, CDEV_INT32, sizeof(long), len, ndim))!=NULL) + { + memcpy(entry->data_.lptr, data, len*sizeof(long)); + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of unsigned long int arrays +// * of data into a cdevData object. The len variable contains the total +// * number of elements to be inserted, the ndim variable indicates the +// * number of dimensions in the array. +// ***************************************************************************** +int cdevData::insert (int tag, unsigned long * data, size_t len, size_t ndim) + { + cdevDataEntry * entry; + + if(len==1 && data!=NULL) return insert(tag, *data); + else if(len<=0 || data==NULL) return CDEV_INVALIDARG; + else if((entry = setupTag(tag, CDEV_UINT32, sizeof(unsigned long), len, ndim))!=NULL) + { + memcpy(entry->data_.ulptr, data, len*sizeof(unsigned long)); + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of float arrays of data +// * into a cdevData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int cdevData::insert (int tag, float * data, size_t len, size_t ndim) + { + cdevDataEntry * entry; + + if(len==1 && data!=NULL) return insert(tag, *data); + else if(len<=0 || data==NULL) return CDEV_INVALIDARG; + else if((entry = setupTag(tag, CDEV_FLOAT, sizeof(float), len, ndim))!=NULL) + { + memcpy(entry->data_.fptr, data, len*sizeof(float)); + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of double arrays of data +// * into a cdevData object. The len variable contains the total number of +// * elements to be inserted, the ndim variable indicates the number of +// * dimensions in the array. +// ***************************************************************************** +int cdevData::insert (int tag, double * data, size_t len, size_t ndim) + { + cdevDataEntry * entry; + + if(len==1 && data!=NULL) return insert(tag, *data); + else if(len<=0 || data==NULL) return CDEV_INVALIDARG; + else if((entry = setupTag(tag, CDEV_DOUBLE, sizeof(double), len, ndim))!=NULL) + { + memcpy(entry->data_.dptr, data, len*sizeof(double)); + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of a character string into +// * a cdevData object. The length of the string is calculated using the +// * strlen function. It is important to note, that although this data item +// * uses the array_ block within the cdevDataEntry object, it has no +// * cdevBounds information associated with it. +// ***************************************************************************** +int cdevData::insert ( int tag, char * data ) + { + cdevDataEntry * entry; + int result = CDEV_ERROR; + int len = data!=NULL?strlen(data)+1:0; + + if(len>0 && (entry = lookupTag(tag, 1))!=NULL) + { + // ************************************************************* + // * Allocate a new data block for storing the character string. + // * Note that the number of dimensions will be zero, but the + // * array_ element within the cdevDataEntry object will still + // * be used. + // ************************************************************* + entry->allocate(0, len, sizeof(char)); + + // ************************************************************* + // * Populate the entry with the new data. + // ************************************************************* + entry->tag_ = tag; + entry->dataType_ = CDEV_STRING; + memcpy(entry->data_.str, data, len); + result = CDEV_SUCCESS; + } + return result; + } + +// ***************************************************************************** +// * insert: +// * The following function allows the insertion of an array of character +// * strings. Unlike the individual character string, this data may have +// * cdevBounds data associated within it. +// ***************************************************************************** +int cdevData::insert ( int tag, char ** data, size_t len, size_t ndim ) + { + int result = CDEV_SUCCESS; + cdevDataEntry * entry; + + // ********************************************************************* + // * If the user specified len is invalid (or 0 by default), walk + // * through the array of pointers until NULL is found. + // ********************************************************************* + if(len<=0) for(len=0; data && data[len]!=NULL; len++); + if(len==0) result = CDEV_INVALIDARG; + else if(len==1) result = insert(tag, *data); + else + { + int i; + size_t dataLen = 0; + + // ************************************************************* + // * To determine the data space needed to store an array of + // * character strings, the function must calculate the length + // * of each character string (plus one for the NULL terminator), + // * then add in the space necessary to store the pointers. + // ************************************************************* + for(i=0; ibounds()[0].length = len; + entry->elems_ = len; + entry->bytes_ = 4; + + // ***************************************************** + // * Set the pointer within the string array to point + // * to the extra memory allocated at the end of the + // * entry->data_.strarr block. Then copy the new data + // * into the string array. + // ***************************************************** + char ** ptr = entry->data_.strarr; + ptr[0] = (char *)(&entry->data_.strarr[len+1]); + strcpy(ptr[0], data[0]); + for(i=1; idata_.tsptr, data, len*sizeof(cdev_TS_STAMP)); + } + return (entry==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + + +// ***************************************************************************** +// * get: +// * This function retrieves a character value specified by tag from the +// * cdevData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int cdevData::get(int tag, BYTE * data) + { + int result, nelem=1; + cdevDataEntry * entry; + + if(data==NULL) result = CDEV_INVALIDARG; + else if((entry=lookupTag(tag, 0))==NULL) result = CDEV_NOTFOUND; + else + { + if(entry->dim_ > 0) + cdevConversionMatrix[entry->dataType_][CDEV_BYTE] + (entry->data_.vptr, data, entry->elems_); + else cdevConversionMatrix[entry->dataType_][CDEV_BYTE] + (&entry->data_, data, 1); + + result = CDEV_SUCCESS; + } + return result; + } + +// ***************************************************************************** +// * get: +// * This function retrieves an short integer value specified by tag from the +// * cdevData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int cdevData::get(int tag, short * data) + { + int result, nelem=1; + cdevDataEntry * entry; + + if(data==NULL) result = CDEV_INVALIDARG; + else if((entry=lookupTag(tag, 0))==NULL) result = CDEV_NOTFOUND; + else + { + if(entry->dim_ > 0) + cdevConversionMatrix[entry->dataType_][CDEV_INT16] + (entry->data_.vptr, data, entry->elems_); + else cdevConversionMatrix[entry->dataType_][CDEV_INT16] + (&entry->data_, data, 1); + + result = CDEV_SUCCESS; + } + return result; + } + +// ***************************************************************************** +// * get: +// * This function retrieves an unsigned short integer value specified by tag +// * from the cdevData object. This value may be either scalar or an array. +// * If the data is an array, the user must have preallocated sufficient +// * space to store the data. +// ***************************************************************************** +int cdevData::get(int tag, unsigned short * data) + { + int result, nelem=1; + cdevDataEntry * entry; + + if(data==NULL) result = CDEV_INVALIDARG; + else if((entry=lookupTag(tag, 0))==NULL) result = CDEV_NOTFOUND; + else + { + if(entry->dim_ > 0) + cdevConversionMatrix[entry->dataType_][CDEV_UINT16] + (entry->data_.vptr, data, entry->elems_); + else cdevConversionMatrix[entry->dataType_][CDEV_UINT16] + (&entry->data_, data, 1); + + result = CDEV_SUCCESS; + } + return result; + } + +// ***************************************************************************** +// * get: +// * This function retrieves an long integer value specified by tag from the +// * cdevData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int cdevData::get(int tag, long * data) + { + int result, nelem=1; + cdevDataEntry * entry; + + if(data==NULL) result = CDEV_INVALIDARG; + else if((entry=lookupTag(tag, 0))==NULL) result = CDEV_NOTFOUND; + else + { + if(entry->dim_ > 0) + cdevConversionMatrix[entry->dataType_][CDEV_INT32] + (entry->data_.vptr, data, entry->elems_); + else cdevConversionMatrix[entry->dataType_][CDEV_INT32] + (&entry->data_, data, 1); + + result = CDEV_SUCCESS; + } + return result; + } + +// ***************************************************************************** +// * get: +// * This function retrieves an unsigned long integer value specified by tag +// * from the cdevData object. This value may be either scalar or an array. +// * If the data is an array, the user must have preallocated sufficient +// * space to store the data. +// ***************************************************************************** +int cdevData::get(int tag, unsigned long * data) + { + int result, nelem=1; + cdevDataEntry * entry; + + if(data==NULL) result = CDEV_INVALIDARG; + else if((entry=lookupTag(tag, 0))==NULL) result = CDEV_NOTFOUND; + else + { + if(entry->dim_ > 0) + cdevConversionMatrix[entry->dataType_][CDEV_UINT32] + (entry->data_.vptr, data, entry->elems_); + else cdevConversionMatrix[entry->dataType_][CDEV_UINT32] + (&entry->data_, data, 1); + + result = CDEV_SUCCESS; + } + return result; + } + +// ***************************************************************************** +// * get: +// * This function retrieves a floating point value specified by tag from the +// * cdevData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int cdevData::get(int tag, float * data) + { + int result, nelem=1; + cdevDataEntry * entry; + + if(data==NULL) result = CDEV_INVALIDARG; + else if((entry=lookupTag(tag, 0))==NULL) result = CDEV_NOTFOUND; + else + { + if(entry->dim_ > 0) + cdevConversionMatrix[entry->dataType_][CDEV_FLOAT] + (entry->data_.vptr, data, entry->elems_); + else cdevConversionMatrix[entry->dataType_][CDEV_FLOAT] + (&entry->data_, data, 1); + + result = CDEV_SUCCESS; + } + return result; + } + + +// ***************************************************************************** +// * get: +// * This function retrieves a double float value specified by tag from the +// * cdevData object. This value may be either scalar or an array. If the +// * data is an array, the user must have preallocated sufficient space to +// * store the data. +// ***************************************************************************** +int cdevData::get(int tag, double * data) + { + int result, nelem=1; + cdevDataEntry * entry; + + if(data==NULL) result = CDEV_INVALIDARG; + else if((entry=lookupTag(tag, 0))==NULL) result = CDEV_NOTFOUND; + else + { + if(entry->dim_ > 0) + cdevConversionMatrix[entry->dataType_][CDEV_DOUBLE] + (entry->data_.vptr, data, entry->elems_); + else cdevConversionMatrix[entry->dataType_][CDEV_DOUBLE] + (&entry->data_, data, 1); + + result = CDEV_SUCCESS; + } + return result; + } + +// ***************************************************************************** +// * get: +// * This function retrieves a time stamp value specified by tag from the +// * cdevData object. +// ***************************************************************************** +int cdevData::get(int tag, cdev_TS_STAMP * data) + { + int result; + cdevDataEntry * entry; + + if(data==NULL) result = CDEV_INVALIDARG; + else if((entry=lookupTag(tag, 0))==NULL) result = CDEV_NOTFOUND; + else + { + if(entry->dim_ > 0) + cdevConversionMatrix[entry->dataType_][CDEV_TIMESTAMP] + (entry->data_.vptr, data, entry->elems_); + else + cdevConversionMatrix[entry->dataType_][CDEV_TIMESTAMP] + (&entry->data_, data, 1); + result = CDEV_SUCCESS; + } + return result; + } + + +// ***************************************************************************** +// * get: +// * This function retrieves a char string value specified by tag from the +// * cdevData object. For simplicity, this method operates differently +// * than the other get methods. +// ***************************************************************************** +int cdevData::get(int tag, char * data, size_t len) + { + int nelem = 1, result = CDEV_NOTFOUND, i; + cdevDataEntry * entry; + if(data!=NULL && (entry=lookupTag(tag, 0))!=NULL) + { + if(entry->dim_ > 0) + { + cdevBounds * bounds = entry->bounds(); + for(i=0; idim_; i++) nelem *= bounds[i].length; + } + + switch(entry->dataType_) + { + case CDEV_BYTE: + if(nelem==1) sprintf(data, "%.*s", len, ltoa(entry->data_.cval)); + else sprintf(data, "%.*s", len, ltoa(*entry->data_.str)); + break; + case CDEV_INT16: + if(nelem==1) sprintf(data, "%.*s", len, ltoa(entry->data_.sval)); + else sprintf(data, "%.*s", len, ltoa(*entry->data_.sptr)); + break; + case CDEV_UINT16: + if(nelem==1) sprintf(data, "%.*s", len, ultoa(entry->data_.usval)); + else sprintf(data, "%.*s", len, ultoa(*entry->data_.usptr)); + break; + case CDEV_INT32: + if(nelem==1) sprintf(data, "%.*s", len, ltoa(entry->data_.lval)); + else sprintf(data, "%.*s", len, ltoa(*entry->data_.lptr)); + break; + case CDEV_UINT32: + if(nelem==1) sprintf(data, "%.*s", len, ultoa(entry->data_.ulval)); + else sprintf(data, "%.*s", len, ultoa(*entry->data_.ulptr)); + break; + case CDEV_FLOAT: + if(nelem==1) gcvt(entry->data_.fval, len, data); + else gcvt(*entry->data_.fptr, len, data); + break; + case CDEV_DOUBLE: + if(nelem==1) gcvt(entry->data_.dval, len, data); + else gcvt(*entry->data_.dptr, len, data); + break; + case CDEV_STRING: + if(nelem==1) cdevStrncpy(data, entry->data_.str, len); + else cdevStrncpy(data, entry->data_.strarr[0], len); + data[len-1] = 0; + break; + case CDEV_TIMESTAMP: + if(nelem==1) + cdevStrncpy(data, ctime((time_t *)&(entry->data_.ts.secPastEpoch)), len); + data[len-1] = 0; + break; + + default: + break; + } + result = CDEV_SUCCESS; + } + return result; + } + +// ***************************************************************************** +// * get: +// * This function retrieves a char string array specified by tag from the +// * cdevData object. For simplicity, this method operates differently +// * than the other get methods. +// ***************************************************************************** +int cdevData::get(int tag, char ** data) + { + int result, nelem=1; + cdevDataEntry * entry; + + if(data==NULL) result = CDEV_INVALIDARG; + else if((entry=lookupTag(tag, 0))==NULL) result = CDEV_NOTFOUND; + else + { + if(entry->dim_ > 0) + cdevConversionMatrix[entry->dataType_][CDEV_STRING] + (entry->data_.vptr, data, entry->elems_); + else cdevConversionMatrix[entry->dataType_][CDEV_STRING] + (&entry->data_, data, 1); + + result = CDEV_SUCCESS; + } + return result; + } + +// ***************************************************************************** +// * find: +// * Allows the user to directly extract a pointer to the internal data +// * buffer that the cdevDataEntry object uses to store data. +// ***************************************************************************** +int cdevData::find(int tag, void* &data) + { + int result = CDEV_NOTFOUND; + cdevDataEntry * entry; + if((entry=lookupTag(tag, 0))!=NULL) + { + if(entry->dim_>0 || entry->dataType_==CDEV_STRING) data = entry->data_.vptr; + else data = &entry->data_; + result = CDEV_SUCCESS; + } + else data = NULL; + return result; + } + + +// ***************************************************************************** +// * operator == : +// * This method will allow the caller to rapidly determine if two cdevData +// * objects contain identical fields and values... +// * +// * In the first step, the method will count the total number of fields in +// * both objects... if they are not equal an error will be returned... +// * +// * Next the method will begin getting pointers to the cdevDataEntry objects +// * that are stored in each object and will use their embedded comparison +// * operators to compare the contents of each of them. +// ***************************************************************************** +int cdevData::operator == ( cdevData & data ) + { + int result = 1; + cdevDataEntry *entry1, *entry2; + int entry1Cnt=0, entry2Cnt=0; + + for(entry1=entries; entry1!=NULL; entry1=entry1->next_) entry1Cnt++; + for(entry2=data.entries; entry2!=NULL; entry2=entry2->next_) entry2Cnt++; + if(entry1Cnt==entry2Cnt) + { + result = 0; + for(entry1=entries; !result && entry1!=NULL; entry1=entry1->next_) + { + if((entry2 = data.lookupTag(entry1->tag_))!=NULL) + { + result = !(entry1->operator == (*entry2)); + } + else result = -1; + } + } + return !result; + } + +// ***************************************************************************** +// * Append operation: +// * This operation will append a cdevData onto an existing cdevData +// * and return this object. If there is confilicts among tags, the +// * appended one wins +// ***************************************************************************** +cdevData& +cdevData::operator += (const cdevData& data) + { + for(cdevDataEntry *ptr = data.entries; ptr!=NULL; ptr = ptr->next_) + { + switch(ptr->dataType_) + { + case CDEV_BYTE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.cval); + else insert(ptr->tag_, ptr->data_.cptr, ptr->elems_, ptr->dim_); + break; + + case CDEV_INT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.sval); + else insert(ptr->tag_, ptr->data_.sptr, ptr->elems_, ptr->dim_); + break; + + case CDEV_UINT16: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.usval); + else insert(ptr->tag_, ptr->data_.usptr, ptr->elems_, ptr->dim_); + break; + + case CDEV_INT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.lval); + else insert(ptr->tag_, ptr->data_.lptr, ptr->elems_, ptr->dim_); + break; + + case CDEV_UINT32: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.ulval); + else insert(ptr->tag_, ptr->data_.ulptr, ptr->elems_, ptr->dim_); + break; + + case CDEV_FLOAT: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.fval); + else insert(ptr->tag_, ptr->data_.fptr, ptr->elems_, ptr->dim_); + break; + + case CDEV_DOUBLE: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.dval); + else insert(ptr->tag_, ptr->data_.dptr, ptr->elems_, ptr->dim_); + break; + + case CDEV_STRING: + if(ptr->dim_==0) insert(ptr->tag_, ptr->data_.str); + else insert(ptr->tag_, ptr->data_.strarr, ptr->elems_, ptr->dim_); + break; + + case CDEV_TIMESTAMP: + if (ptr->dim_==0) insert(ptr->tag_, ptr->data_.ts); + else insert(ptr->tag_, ptr->data_.tsptr, ptr->elems_, ptr->dim_); + break; + + default: + break; + } + if(ptr->tag_ && ptr->dim_ && ptr->dataType_tag_, ptr->bounds(), ptr->dim_); + } + return *this; + } + + +// ***************************************************************************** +// * cdev Conversion Utilities +// * These functions are incorporated into the cdevConversionMatrix and are +// * used to convert between cdevDataTypes. Because these functions are +// * defined for use specifically within the cdevData object, they are not +// * declared in the header file and should not be used by external modules +// * or applications. +// * +// * All cdev function sthat use these utilities should access them through +// * the cdevConversionMatrix array as described at the beginning of this +// * file. +// ***************************************************************************** + +// ***************************************************************************** +// * cdevConvert: +// * 8 Bit Integer to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_BYTE_to_BYTE ( void * input, void * output, size_t nElems ) + { + memcpy(output, input, nElems*sizeof(char)); + } + +// ***************************************************************************** +// * cdevConvert: +// * 8 Bit Integer to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_BYTE_to_INT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((short *)output)[nElems] = (short)((BYTE *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 8 Bit Integer to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_BYTE_to_UINT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((BYTE *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 8 Bit Integer to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_BYTE_to_INT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((long *)output)[nElems] = (long)((BYTE *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 8 Bit Integer to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_BYTE_to_UINT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((BYTE *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 8 Bit Integer to Float Conversion Facilities +// ***************************************************************************** +void cdevConvert_BYTE_to_FLOAT ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((float *)output)[nElems] = (float)((BYTE *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 8 Bit Integer to Double Conversion Facilities +// ***************************************************************************** +void cdevConvert_BYTE_to_DOUBLE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((double *)output)[nElems] = (double)((BYTE *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 8 Bit Integer to String Array Conversion Facilities +// ***************************************************************************** +void cdevConvert_BYTE_to_STRING ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((char **)output)[nElems] = new char[strlen(ltoa(((BYTE *)input)[nElems]))+1]; + strcpy(((char **)output)[nElems], ltoa(((BYTE *)input)[nElems])); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 8 Bit Integer to Timestamp Conversion Facilities +// ***************************************************************************** +void cdevConvert_BYTE_to_TIMESTAMP ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((cdev_TS_STAMP *)output)[nElems].secPastEpoch = (unsigned long)((BYTE *)input)[nElems]; + ((cdev_TS_STAMP *)output)[nElems].nsec = 0; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 8 Bit Integer to Invalid Conversion Facilities... Does nothing +// ***************************************************************************** +void cdevConvert_BYTE_to_INVALID ( void *, void *, size_t ) + { + } + +// ***************************************************************************** +// * cdevConvert: +// * 16 Bit Integer to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT16_to_BYTE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((char *)output)[nElems] = (char)((short *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 16 Bit Integer to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT16_to_INT16 ( void * input, void * output, size_t nElems ) + { + memcpy(output, input, nElems*sizeof(short)); + } + +// ***************************************************************************** +// * cdevConvert: +// * 16 Bit Integer to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT16_to_UINT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((short *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 16 Bit Integer to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT16_to_INT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((long *)output)[nElems] = (long)((short *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 16 Bit Integer to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT16_to_UINT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((short *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 16 Bit Integer to Float Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT16_to_FLOAT ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((float *)output)[nElems] = (float)((short *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 16 Bit Integer to Double Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT16_to_DOUBLE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((double *)output)[nElems] = (double)((short *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 16 Bit Integer to String Array Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT16_to_STRING ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((char **)output)[nElems] = new char[strlen(ltoa(((short *)input)[nElems]))+1]; + strcpy(((char **)output)[nElems], ltoa(((short *)input)[nElems])); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 16 Bit Integer to Timestamp Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT16_to_TIMESTAMP ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((cdev_TS_STAMP *)output)[nElems].secPastEpoch = (unsigned long)((short *)input)[nElems]; + ((cdev_TS_STAMP *)output)[nElems].nsec = 0; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 16 Bit Integer to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void cdevConvert_INT16_to_INVALID ( void *, void *, size_t ) + { + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 16 Bit Integer to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT16_to_BYTE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((char *)output)[nElems] = (char)((unsigned short *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 16 Bit Integer to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT16_to_INT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((short *)output)[nElems] = (unsigned short)((unsigned short *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 16 Bit Integer to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT16_to_UINT16 ( void * input, void * output, size_t nElems ) + { + memcpy(output, input, nElems*sizeof(unsigned short)); + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 16 Bit Integer to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT16_to_INT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((long *)output)[nElems] = (long)((unsigned short *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 16 Bit Integer to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT16_to_UINT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((unsigned short *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 16 Bit Integer to Float Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT16_to_FLOAT ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((float *)output)[nElems] = (float)((unsigned short *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 16 Bit Integer to Double Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT16_to_DOUBLE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((double *)output)[nElems] = (double)((unsigned short *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 16 Bit Integer to String Array Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT16_to_STRING ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((char **)output)[nElems] = new char[strlen(ultoa(((unsigned short *)input)[nElems]))+1]; + strcpy(((char **)output)[nElems], ultoa(((unsigned short *)input)[nElems])); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 16 Bit Integer to Timestamp Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT16_to_TIMESTAMP ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((cdev_TS_STAMP *)output)[nElems].secPastEpoch=(unsigned long)((unsigned short *)input)[nElems]; + ((cdev_TS_STAMP *)output)[nElems].nsec = 0; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 16 Bit Integer to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void cdevConvert_UINT16_to_INVALID ( void *, void *, size_t ) + { + } + +// ***************************************************************************** +// * cdevConvert: +// * 32 Bit Integer to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT32_to_BYTE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((char *)output)[nElems] = (char)((long *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 32 Bit Integer to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT32_to_INT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((short *)output)[nElems] = (short)((long *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 32 Bit Integer to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT32_to_UINT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((long *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 32 Bit Integer to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT32_to_INT32 ( void * input, void * output, size_t nElems ) + { + memcpy(output, input, nElems*sizeof(long)); + } + +// ***************************************************************************** +// * cdevConvert: +// * 32 Bit Integer to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT32_to_UINT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((long *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 32 Bit Integer to Float Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT32_to_FLOAT ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((float *)output)[nElems] = (float)((long *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 32 Bit Integer to Double Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT32_to_DOUBLE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((double *)output)[nElems] = (double)((long *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 32 Bit Integer to String Array Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT32_to_STRING ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((char **)output)[nElems] = new char[strlen(ltoa(((long *)input)[nElems]))+1]; + strcpy(((char **)output)[nElems], ltoa(((long *)input)[nElems])); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 32 Bit Integer to Timestamp Conversion Facilities +// ***************************************************************************** +void cdevConvert_INT32_to_TIMESTAMP ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((cdev_TS_STAMP *)output)[nElems].secPastEpoch=(unsigned long)((long *)input)[nElems]; + ((cdev_TS_STAMP *)output)[nElems].nsec = 0; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * 32 Bit Integer to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void cdevConvert_INT32_to_INVALID ( void *, void *, size_t ) + { + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 32 Bit Integer to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT32_to_BYTE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((char *)output)[nElems] = (char)((unsigned long *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 32 Bit Integer to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT32_to_INT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((short *)output)[nElems] = (short)((unsigned long *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 32 Bit Integer to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT32_to_UINT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((unsigned long *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 32 Bit Integer to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT32_to_INT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((long *)output)[nElems] = (unsigned long)((unsigned long *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 32 Bit Integer to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT32_to_UINT32 ( void * input, void * output, size_t nElems ) + { + memcpy(output, input, nElems*sizeof(unsigned long)); + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 32 Bit Integer to Float Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT32_to_FLOAT ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((float *)output)[nElems] = (float)((unsigned long *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 32 Bit Integer to Double Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT32_to_DOUBLE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((double *)output)[nElems] = (double)((unsigned long *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 32 Bit Integer to String Array Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT32_to_STRING ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((char **)output)[nElems] = new char[strlen(ultoa(((unsigned long *)input)[nElems]))+1]; + strcpy(((char **)output)[nElems], ultoa(((unsigned long *)input)[nElems])); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 32 Bit Integer to Timestamp Conversion Facilities +// ***************************************************************************** +void cdevConvert_UINT32_to_TIMESTAMP ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((cdev_TS_STAMP *)output)[nElems].secPastEpoch=((unsigned long *)input)[nElems]; + ((cdev_TS_STAMP *)output)[nElems].nsec = 0; + } + } + + +// ***************************************************************************** +// * cdevConvert: +// * Unsigned 32 Bit Integer to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void cdevConvert_UINT32_to_INVALID ( void *, void *, size_t ) + { + } + +// ***************************************************************************** +// * cdevConvert: +// * Floating Point to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_FLOAT_to_BYTE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((char *)output)[nElems] = (char)((float *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Floating Point to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_FLOAT_to_INT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((short *)output)[nElems] = (short)((float *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Floating Point to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_FLOAT_to_UINT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((float *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Floating Point to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_FLOAT_to_INT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((long *)output)[nElems] = (long)((float *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Floating Point to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_FLOAT_to_UINT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((float *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Floating Point to Float Conversion Facilities +// ***************************************************************************** +void cdevConvert_FLOAT_to_FLOAT ( void * input, void * output, size_t nElems ) + { + memcpy(output, input, nElems*sizeof(float)); + } + +// ***************************************************************************** +// * cdevConvert: +// * Floating Point to Double Conversion Facilities +// ***************************************************************************** +void cdevConvert_FLOAT_to_DOUBLE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((double *)output)[nElems] = (double)((float *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Floating Point to String Array Conversion Facilities +// ***************************************************************************** +void cdevConvert_FLOAT_to_STRING ( void * input, void * output, size_t nElems ) + { + char buf[32]; + while(nElems>0) + { + nElems--; + gcvt(((float *)input)[nElems], (size_t)32, buf); + ((char **)output)[nElems] = new char[strlen(buf)+1]; + strcpy(((char **)output)[nElems], buf); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Floating Point to Timestamp Conversion Facilities +// ***************************************************************************** +void cdevConvert_FLOAT_to_TIMESTAMP ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((cdev_TS_STAMP *)output)[nElems].secPastEpoch=(unsigned long)((float *)input)[nElems]; + ((cdev_TS_STAMP *)output)[nElems].nsec = + (unsigned long)(((float)((float *)input)[nElems]-(unsigned long)((float *)input)[nElems])*1000000000); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Floating Point to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void cdevConvert_FLOAT_to_INVALID ( void *, void *, size_t ) + { + } + +// ***************************************************************************** +// * cdevConvert: +// * Double Floating Point to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_DOUBLE_to_BYTE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((char *)output)[nElems] = (char)((double *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Double Floating Point to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_DOUBLE_to_INT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((short *)output)[nElems] = (short)((double *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Double Floating Point to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_DOUBLE_to_UINT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)((double *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Double Floating Point to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_DOUBLE_to_INT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((long *)output)[nElems] = (long)((double *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Double Floating Point to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_DOUBLE_to_UINT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)((double *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Double Floating Point to Float Conversion Facilities +// ***************************************************************************** +void cdevConvert_DOUBLE_to_FLOAT ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((float *)output)[nElems] = (float)((double *)input)[nElems]; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Double Floating Point to Double Conversion Facilities +// ***************************************************************************** +void cdevConvert_DOUBLE_to_DOUBLE ( void * input, void * output, size_t nElems ) + { + memcpy(output, input, nElems*sizeof(double)); + } + +// ***************************************************************************** +// * cdevConvert: +// * Double Floating Point to String Array Conversion Facilities +// ***************************************************************************** +void cdevConvert_DOUBLE_to_STRING ( void * input, void * output, size_t nElems ) + { + char buf[32]; + while(nElems>0) + { + nElems--; + gcvt(((double *)input)[nElems], (size_t)32, buf); + ((char **)output)[nElems] = new char[strlen(buf)+1]; + strcpy(((char **)output)[nElems], buf); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Double Floating Point to Timestamp Conversion Facilities +// ***************************************************************************** +void cdevConvert_DOUBLE_to_TIMESTAMP ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((cdev_TS_STAMP *)output)[nElems].secPastEpoch= + (unsigned long)((double *)input)[nElems]; + ((cdev_TS_STAMP *)output)[nElems].nsec = + (unsigned long)(((double)((double *)input)[nElems]-(unsigned long)((double *)input)[nElems])*1000000000); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Double Floating Point to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void cdevConvert_DOUBLE_to_INVALID ( void *, void *, size_t ) + { + } + +// ***************************************************************************** +// * cdevConvert: +// * String Array to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_STRING_to_BYTE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((char *)output)[nElems] = (char)atof(((char **)input)[nElems]); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * String Array to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_STRING_to_INT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((short *)output)[nElems] = (short)atof(((char **)input)[nElems]); + } + + } + +// ***************************************************************************** +// * cdevConvert: +// * String Array to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_STRING_to_UINT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((unsigned short *)output)[nElems] = (unsigned short)atof(((char **)input)[nElems]); + } + + } + +// ***************************************************************************** +// * cdevConvert: +// * String Array to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_STRING_to_INT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((long *)output)[nElems] = (long)atof(((char **)input)[nElems]); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * String Array to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_STRING_to_UINT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((unsigned long *)output)[nElems] = (unsigned long)atof(((char **)input)[nElems]); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * String Array to Float Conversion Facilities +// ***************************************************************************** +void cdevConvert_STRING_to_FLOAT ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((float *)output)[nElems] = (float)atof(((char **)input)[nElems]); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * String Array to Double Conversion Facilities +// ***************************************************************************** +void cdevConvert_STRING_to_DOUBLE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; ((double *)output)[nElems] = (double)atof(((char **)input)[nElems]); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * String Array to String Array Conversion Facilities +// ***************************************************************************** +void cdevConvert_STRING_to_STRING ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((char **)output)[nElems] = new char[strlen(((char **)input)[nElems])+1]; + strcpy(((char **)output)[nElems], ((char **)input)[nElems]); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * String Array to Timestamp Conversion Facilities +// ***************************************************************************** +void cdevConvert_STRING_to_TIMESTAMP ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + double tmp = atof(((char **)input)[nElems]); + ((cdev_TS_STAMP *)output)[nElems].secPastEpoch=(unsigned long)tmp; + ((cdev_TS_STAMP *)output)[nElems].nsec =(unsigned long)((tmp-(unsigned long)tmp)*1000000000); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * String Array to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void cdevConvert_STRING_to_INVALID ( void *, void *, size_t ) + { + } + + +// ***************************************************************************** +// * cdevConvert: +// * Time Stamp to 8 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_TIMESTAMP_to_BYTE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((char *)output)[nElems] = (char)(((cdev_TS_STAMP *)input)[nElems].secPastEpoch); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Time Stamp to 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_TIMESTAMP_to_INT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((short *)output)[nElems] = (short)(((cdev_TS_STAMP *)input)[nElems].secPastEpoch); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Time Stamp to Unsigned 16 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_TIMESTAMP_to_UINT16 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((unsigned short *)output)[nElems]= + (unsigned short)(((cdev_TS_STAMP *)input)[nElems].secPastEpoch); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Time Stamp to 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_TIMESTAMP_to_INT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((long *)output)[nElems]= + (long)(((cdev_TS_STAMP *)input)[nElems].secPastEpoch); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Time Stamp to Unsigned 32 Bit Integer Conversion Facilities +// ***************************************************************************** +void cdevConvert_TIMESTAMP_to_UINT32 ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((unsigned long *)output)[nElems]= + ((cdev_TS_STAMP *)input)[nElems].secPastEpoch; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Time Stamp to Floating Point Conversion Facilities +// ***************************************************************************** +void cdevConvert_TIMESTAMP_to_FLOAT ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((float *)output)[nElems]= + (float)(((cdev_TS_STAMP *)input)[nElems].secPastEpoch+ + ((cdev_TS_STAMP *)input)[nElems].nsec/1000000000.); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Time Stamp to Doouble Floating Point Conversion Facilities +// ***************************************************************************** +void cdevConvert_TIMESTAMP_to_DOUBLE ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((double *)output)[nElems]= + (double)(((cdev_TS_STAMP *)input)[nElems].secPastEpoch+ + ((cdev_TS_STAMP *)input)[nElems].nsec/1000000000.); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Time Stamp to Char String Conversion Facilities +// ***************************************************************************** +void cdevConvert_TIMESTAMP_to_STRING ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((char **)output)[nElems] = new char[30]; + strcpy( ((char **)output)[nElems], + ctime((time_t *)(&(((cdev_TS_STAMP *)input)[nElems].secPastEpoch))) ); + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Time Stamp to Time Stamp Conversion Facilities +// ***************************************************************************** +void cdevConvert_TIMESTAMP_to_TIMESTAMP ( void * input, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((cdev_TS_STAMP *)output)[nElems].secPastEpoch = + ((cdev_TS_STAMP *)input)[nElems].secPastEpoch; + ((cdev_TS_STAMP *)output)[nElems].nsec = + ((cdev_TS_STAMP *)input)[nElems].nsec; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Time Stamp to Invalid Conversion Facilities...Dose Nothing +// ***************************************************************************** +void cdevConvert_TIMESTAMP_to_INVALID ( void *, void *, size_t ) + { + } + +// ***************************************************************************** +// * cdevConvert: +// * Invalid to 8 Bit Integer Conversion Facilities... Clears Output +// ***************************************************************************** +void cdevConvert_INVALID_to_BYTE ( void *, void * output, size_t nElems ) + { + memset((char *)output, 0, nElems*sizeof(char)); + } + +// ***************************************************************************** +// * cdevConvert: +// * Invalid to 16 Bit Integer Conversion Facilities... Clears Output +// ***************************************************************************** +void cdevConvert_INVALID_to_INT16 ( void *, void * output, size_t nElems ) + { + memset((short *)output, 0, nElems*sizeof(short)); + } + +// ***************************************************************************** +// * cdevConvert: +// * Invalid to Unsigned 16 Bit Integer Conversion Facilities... Clears Output +// ***************************************************************************** +void cdevConvert_INVALID_to_UINT16 ( void *, void * output, size_t nElems ) + { + memset((short *)output, 0, nElems*sizeof(unsigned short)); + } + +// ***************************************************************************** +// * cdevConvert: +// * Invalid to 32 Bit Integer Conversion Facilities... Clears Output +// ***************************************************************************** +void cdevConvert_INVALID_to_INT32 ( void *, void * output, size_t nElems ) + { + memset((long *)output, 0, nElems*sizeof(long)); + } + +// ***************************************************************************** +// * cdevConvert: +// * Invalid to Unsigned 32 Bit Integer Conversion Facilities... Clears Output +// ***************************************************************************** +void cdevConvert_INVALID_to_UINT32 ( void *, void * output, size_t nElems ) + { + memset((long *)output, 0, nElems*sizeof(unsigned long)); + } + +// ***************************************************************************** +// * cdevConvert: +// * Invalid to Float Conversion Facilities... Clears Output +// ***************************************************************************** +void cdevConvert_INVALID_to_FLOAT ( void *, void * output, size_t nElems ) + { + memset((float *)output, 0, nElems*sizeof(float)); + } + +// ***************************************************************************** +// * cdevConvert: +// * Invalid to Double Conversion Facilities... Clears Output +// ***************************************************************************** +void cdevConvert_INVALID_to_DOUBLE ( void *, void * output, size_t nElems ) + { + memset((double *)output, 0, nElems*sizeof(double)); + } + +// ***************************************************************************** +// * cdevConvert: +// * Invalid to String Array Conversion Facilities... Clears Output +// ***************************************************************************** +void cdevConvert_INVALID_to_STRING ( void *, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((char **)output)[nElems] = NULL; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Invalid to Timestamp Conversion Facilities... Clears Output +// ***************************************************************************** +void cdevConvert_INVALID_to_TIMESTAMP ( void *, void * output, size_t nElems ) + { + while(nElems>0) + { + nElems--; + ((cdev_TS_STAMP *)output)[nElems].secPastEpoch=0; + ((cdev_TS_STAMP *)output)[nElems].nsec =0; + } + } + +// ***************************************************************************** +// * cdevConvert: +// * Invalid to Invalid Conversion Facilities... Does Nothing +// ***************************************************************************** +void cdevConvert_INVALID_to_INVALID ( void *, void *, size_t ) + { + } + + +// ***************************************************************************** +// * cdevConversionMatrix: +// * Instanciation of the conversion matrix defined at the beginning of this +// * file. +// ***************************************************************************** +const cdevConverter cdevConversionMatrix [CDEV_INVALID+1][CDEV_INVALID+1] = + { + { + cdevConvert_BYTE_to_BYTE, + cdevConvert_BYTE_to_INT16, + cdevConvert_BYTE_to_UINT16, + cdevConvert_BYTE_to_INT32, + cdevConvert_BYTE_to_UINT32, + cdevConvert_BYTE_to_FLOAT, + cdevConvert_BYTE_to_DOUBLE, + cdevConvert_BYTE_to_STRING, + cdevConvert_BYTE_to_TIMESTAMP, + cdevConvert_BYTE_to_INVALID + }, + { + cdevConvert_INT16_to_BYTE, + cdevConvert_INT16_to_INT16, + cdevConvert_INT16_to_UINT16, + cdevConvert_INT16_to_INT32, + cdevConvert_INT16_to_UINT32, + cdevConvert_INT16_to_FLOAT, + cdevConvert_INT16_to_DOUBLE, + cdevConvert_INT16_to_STRING, + cdevConvert_INT16_to_TIMESTAMP, + cdevConvert_INT16_to_INVALID, + }, + { + cdevConvert_UINT16_to_BYTE, + cdevConvert_UINT16_to_INT16, + cdevConvert_UINT16_to_UINT16, + cdevConvert_UINT16_to_INT32, + cdevConvert_UINT16_to_UINT32, + cdevConvert_UINT16_to_FLOAT, + cdevConvert_UINT16_to_DOUBLE, + cdevConvert_UINT16_to_STRING, + cdevConvert_UINT16_to_TIMESTAMP, + cdevConvert_UINT16_to_INVALID, + }, + { + cdevConvert_INT32_to_BYTE, + cdevConvert_INT32_to_INT16, + cdevConvert_INT32_to_UINT16, + cdevConvert_INT32_to_INT32, + cdevConvert_INT32_to_UINT32, + cdevConvert_INT32_to_FLOAT, + cdevConvert_INT32_to_DOUBLE, + cdevConvert_INT32_to_STRING, + cdevConvert_INT32_to_TIMESTAMP, + cdevConvert_INT32_to_INVALID, + }, + { + cdevConvert_UINT32_to_BYTE, + cdevConvert_UINT32_to_INT16, + cdevConvert_UINT32_to_UINT16, + cdevConvert_UINT32_to_INT32, + cdevConvert_UINT32_to_UINT32, + cdevConvert_UINT32_to_FLOAT, + cdevConvert_UINT32_to_DOUBLE, + cdevConvert_UINT32_to_STRING, + cdevConvert_UINT32_to_TIMESTAMP, + cdevConvert_UINT32_to_INVALID, + }, + { + cdevConvert_FLOAT_to_BYTE, + cdevConvert_FLOAT_to_INT16, + cdevConvert_FLOAT_to_UINT16, + cdevConvert_FLOAT_to_INT32, + cdevConvert_FLOAT_to_UINT32, + cdevConvert_FLOAT_to_FLOAT, + cdevConvert_FLOAT_to_DOUBLE, + cdevConvert_FLOAT_to_STRING, + cdevConvert_FLOAT_to_TIMESTAMP, + cdevConvert_FLOAT_to_INVALID, + }, + { + cdevConvert_DOUBLE_to_BYTE, + cdevConvert_DOUBLE_to_INT16, + cdevConvert_DOUBLE_to_UINT16, + cdevConvert_DOUBLE_to_INT32, + cdevConvert_DOUBLE_to_UINT32, + cdevConvert_DOUBLE_to_FLOAT, + cdevConvert_DOUBLE_to_DOUBLE, + cdevConvert_DOUBLE_to_STRING, + cdevConvert_DOUBLE_to_TIMESTAMP, + cdevConvert_DOUBLE_to_INVALID, + }, + { + cdevConvert_STRING_to_BYTE, + cdevConvert_STRING_to_INT16, + cdevConvert_STRING_to_UINT16, + cdevConvert_STRING_to_INT32, + cdevConvert_STRING_to_UINT32, + cdevConvert_STRING_to_FLOAT, + cdevConvert_STRING_to_DOUBLE, + cdevConvert_STRING_to_STRING, + cdevConvert_STRING_to_TIMESTAMP, + cdevConvert_STRING_to_INVALID, + }, + { + cdevConvert_TIMESTAMP_to_BYTE, + cdevConvert_TIMESTAMP_to_INT16, + cdevConvert_TIMESTAMP_to_UINT16, + cdevConvert_TIMESTAMP_to_INT32, + cdevConvert_TIMESTAMP_to_UINT32, + cdevConvert_TIMESTAMP_to_FLOAT, + cdevConvert_TIMESTAMP_to_DOUBLE, + cdevConvert_TIMESTAMP_to_STRING, + cdevConvert_TIMESTAMP_to_TIMESTAMP, + cdevConvert_TIMESTAMP_to_INVALID, + }, + { + cdevConvert_INVALID_to_BYTE, + cdevConvert_INVALID_to_INT16, + cdevConvert_INVALID_to_UINT16, + cdevConvert_INVALID_to_INT32, + cdevConvert_INVALID_to_UINT32, + cdevConvert_INVALID_to_FLOAT, + cdevConvert_INVALID_to_DOUBLE, + cdevConvert_INVALID_to_STRING, + cdevConvert_INVALID_to_TIMESTAMP, + cdevConvert_INVALID_to_INVALID, + } + }; + + +// ***************************************************************************** +// *cdevDataIterator: +// * +// ***************************************************************************** +cdevDataIterator::cdevDataIterator(cdevData* data) + { + dataobj_ = data; + cur_ = 0; + } + +int cdevDataIterator::init() + { + if (dataobj_) + { + cur_ = dataobj_->entries; + return cur_ != 0; + } + else { return 0; } + } + +int cdevDataIterator::operator !() + { + return cur_ != 0; + } + +int cdevDataIterator::operator ++() + { + if(cur_) cur_ = cur_->next_; + return cur_ != 0; + } + +int cdevDataIterator::tag(void) + { + return (cur_!=0)?cur_->tag_:0; + } + +// ***************************************************************************** +// * ltoa and ultoa +// * Supporing routines for non hpux platform +// * the return values point to static data whose content is overwritten by +// * each call +// ***************************************************************************** +#ifndef __hpux +char *ltoa (long val) + { + static char ltoabuf[80]; + + sprintf (ltoabuf,"%ld", val); + + return ltoabuf; + } + +char *ultoa (unsigned long val) + { + static char ultoabuf[80]; + + sprintf (ultoabuf,"%lu", val); + + return ultoabuf; + } +#endif + +// ***************************************************************************** +// * asciiDump: +// * This function will dump the contents of the cdevData object to the +// * user specified file descriptor. +// ***************************************************************************** +#ifdef _WIN32 +void cdevData::asciiDump ( long osfHandle ) + { + int fd = _open_osfhandle(osfHandle, _O_WRONLY | _O_APPEND ); + FILE * fp = _fdopen ( fd, "a"); +#else +void cdevData::asciiDump ( FILE * fp ) + { +#endif + + cdevDataEntry * entry; + char tagText[CDEV_INVALID+1][20]; + + // ************************************* + // * Load the names of the dataTypes * + // ************************************* + sprintf(tagText[CDEV_BYTE], "8 Bit Integer"); + sprintf(tagText[CDEV_INT16], "16 Bit Integer"); + sprintf(tagText[CDEV_UINT16], "Unsigned 16 Bit Int"); + sprintf(tagText[CDEV_INT32], "32 Bit Integer"); + sprintf(tagText[CDEV_UINT32], "Unsigned 32 Bit Int"); + sprintf(tagText[CDEV_FLOAT], "Float"); + sprintf(tagText[CDEV_DOUBLE], "Double"); + sprintf(tagText[CDEV_STRING], "Char String"); + sprintf(tagText[CDEV_TIMESTAMP], "Time Stamp"); + sprintf(tagText[CDEV_INVALID], "Invalid Data"); + + for(entry=entries; entry!=NULL; entry=entry->next_) + { + char * tagName; + int i; + + cdevGlobalTagTable::tagTable()->tagI2C(entry->tag_, tagName); + + fprintf(fp, "Tag: %-5i\n", entry->tag_); + fprintf(fp, "Tag Name: %s\n", tagName); + fprintf(fp, "Data Type: %s", tagText[entry->dataType_]); + for(i=0; idim_; i++) + { + fprintf(fp, "[%i]", entry->bounds()[i].length); + } + fprintf(fp, "\nValues: "); + + switch(entry->dataType_) + { + case CDEV_BYTE: + if(entry->dim_==0) fprintf(fp, "% 4i", entry->data_.cval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 4i%s", entry->data_.cptr[i], + (i%13==12)?"\n ":" "); + break; + + case CDEV_INT16: + if(entry->dim_==0) fprintf(fp, "% 6hi", entry->data_.sval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 6hi%s", entry->data_.sptr[i], + (i%9==8)?"\n ":" "); + break; + + case CDEV_UINT16: + if(entry->dim_==0) fprintf(fp, "% 6hu", entry->data_.usval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 6hu%s", entry->data_.usptr[i], + (i%9==8)?"\n ":" "); + break; + + case CDEV_INT32: + if(entry->dim_==0) fprintf(fp, "% 8li", entry->data_.lval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 8li%s", entry->data_.lptr[i], + (i%7==6)?"\n ":" "); + break; + + case CDEV_UINT32: + if(entry->dim_==0) fprintf(fp, "% 8lu", entry->data_.ulval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 8lu%s", entry->data_.ulptr[i], + (i%7==6)?"\n ":" "); + break; + + case CDEV_FLOAT: + if(entry->dim_==0) fprintf(fp, "% 12.5f", entry->data_.fval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 12.5f%s", entry->data_.fptr[i], + (i%5==4)?"\n ":" "); + break; + + case CDEV_DOUBLE: + if(entry->dim_==0) fprintf(fp, "% 14.7f", entry->data_.dval); + else for(i=0; ielems_; i++) + fprintf(fp, "% 14.7f%s", entry->data_.dptr[i], + (i%4==3)?"\n ":" "); + break; + + case CDEV_STRING: + if(entry->dim_==0) fprintf(fp, "%s\n", entry->data_.str); + else for(i=0; ielems_; i++) + fprintf(fp, "%s\n ", entry->data_.strarr[i]); + break; + + case CDEV_TIMESTAMP: + if(entry->dim_==0) + fprintf(fp, "%u sec and %u nsec \n", + entry->data_.ts.secPastEpoch, entry->data_.ts.nsec); + else for(i=0; ielems_; i++) + fprintf(fp, "%u sec and %u nsec \n", + entry->data_.tsptr[i].secPastEpoch, entry->data_.tsptr[i].nsec); + break; + + case CDEV_INVALID: + break; + } + fprintf(fp, "\n\n"); + } + fflush(fp); +#ifdef _WIN32 + _commit(fd); +#endif + } diff --git a/src/cdevIO/cdevData.h b/src/cdevIO/cdevData.h new file mode 100755 index 0000000..498fe63 --- /dev/null +++ b/src/cdevIO/cdevData.h @@ -0,0 +1,578 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: cdevData.h +// Self descibing data structure to manage the storage and transport +// of data between local cdev functions, as well as remote client and +// server applications. +// +// Author: Walt Akers and Danjin Wu +// +// Revision History: +// cdevData.h,v +// Revision 1.24 1997/12/22 13:47:02 akers +// Made changeTag method virtual +// +// Revision 1.23 1997/08/01 19:06:29 akers +// Added addTag and tagExists feature to the library +// +// Revision 1.22 1997/01/14 19:39:39 chen +// add += operator +// +// Revision 1.21 1997/01/09 16:32:39 akers +// Corrected anachronism +// +// Revision 1.20 1996/11/21 17:02:57 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.19 1996/10/01 13:58:19 akers +// Changes to support AIX +// +// Revision 1.18 1996/09/20 19:33:11 akers +// Changed protection in cdevDataEntryStorage, cdevDataEntry and cdevData in order to support subclassing of the cdevData object +// +// Revision 1.17 1996/09/20 15:41:51 akers +// Made xdr methods virual +// +// Revision 1.16 1996/08/26 19:14:05 akers +// Adding cdevData.inserttag callback capabilities +// +// Revision 1.15 1996/08/23 15:34:07 akers +// Added comparison operator to cdevData +// +// Revision 1.14 1996/07/12 18:08:52 chen +// change copy and assignment to const cdevData& +// +// Revision 1.13 1996/04/12 13:40:04 akers +// Added char * cast operator +// +// Revision 1.12 1996/02/27 20:50:05 danjin +// add assignment operator from various typed data to cdevData object +// +// Revision 1.11 1995/11/01 15:43:42 akers +// Corrected INLINE definition +// +// Revision 1.10 1995/10/06 20:09:47 chen +// add stdio +// +// Revision 1.9 1995/10/06 19:38:34 chen +// Seperate inline functions +// +// Revision 1.8 1995/10/03 19:36:34 chen +// Use new cdevGlobalTagTable Class +// +// Revision 1.7 1995/09/22 21:04:24 danjin +// added cdevDataIterator mechanism +// +// Revision 1.6 1995/09/13 15:27:10 danjin +// added changeTagName func +// +// Revision 1.5 1995/09/06 18:34:16 danjin +// added time stamp structure and related func +// +// Revision 1.4 1995/07/20 14:36:52 akers +// Mispelling in header +// +// Revision 1.3 1995/07/19 20:34:06 akers +// CVS +// +// Revision 1.2 1995/07/14 13:20:09 akers +// Updated cdevData header file supporting changes specified at June 95 Review +// +// +// +//-------------------------------------------------------------------------- + +#ifndef _CDEV_DATA_H +#define _CDEV_DATA_H + +#include + +#ifdef _WIN32 +#include +#include +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __hpux +extern char* ltoa (long val); +extern char* ultoa (unsigned long val); +#endif + +#ifndef _WIN32 + extern "C" char *ctime (__const time_t *__timer) __THROW; +#endif + +class CDEV_CLASS_SPEC cdevData + { + friend class cdevDataIterator; + protected: + cdevDataEntry *entries; + + // ********************************************************************* + // * copy: + // * This function copies the contents of the cdevData object + // * specified by data into this cdevData object. It is used by + // * both the copy constructor and by the assignment operator. + // ********************************************************************* + cdevData & copy (const cdevData & data); + + // ********************************************************************* + // * lookupTag: + // * This function is for internal use and allows a cdevData object + // * to locate and optionally create a tagged data item. + // ********************************************************************* + cdevDataEntry * lookupTag(int tag, int create = 0); + cdevDataEntry * lookupTag(char * ctag, int create = 0); + + // ********************************************************************* + // * setupTag: + // * This function is for internal use and is used to prepare a new + // * cdevDataEntry object prior to inserting data into it. + // ********************************************************************* + cdevDataEntry * setupTag ( + int tag, cdevDataTypes type, size_t elemSize, + size_t numElems, size_t numDims ); + + public: + // ********************************************************************* + // * This group of static functions allows the user an interface to the + // * database of tagged data items that is stored in the + // * cdevGlobalTagTable object. + // ********************************************************************* + static int tagC2I (char *ctag, int *tag); + static int tagI2C (int tag, char * &ctag); + static void insertTag(int tag, char *ctag); + static int tagExists(char * ctag); + static int tagExists(int tag); + static int addTag (char * ctag); + + // *************************************************************************** + // * addTagCallback : + // * This method will add a cdevTagTableCallback object to the list of + // * classes that should be notified each time a tag is added to the + // * cdevTagTable. + // *************************************************************************** + static void addTagCallback ( cdevTagTableCallback * cb ); + + // *************************************************************************** + // * delTagCallback : + // * This method will remote a cdevTagTableCallback object that was + // * previously added to the list of callback classes. + // * + // * Note: This method does not actually delete the cdevTagTableCallback + // * object, it merely removes it from the list. It is the + // * responsibility of the owner to delete the object when it is + // * no longer needed. + // *************************************************************************** + static void delTagCallback ( cdevTagTableCallback * cb ); + + // ***************************************************************************** + // * readTagTable : + // * This method allows the caller to obtain a list of tag names and + // * integers that are currently stored in this tag table. + // * + // * Note: This method will allocate an array of integers and an array of + // * character string pointers. The strings that are stored in the + // * string array will be the actual strings from within the + // * tag table and should not be deleted... + // * + // * The data allocated becomes the property of the caller and must + // * be deleted when it is no longer needed... the correct syntax to + // * delete these items is... + // * + // * delete tags; + // * delete ctags; + // * + // * This will delete the array, however, it will leave the + // * individual array elements intact. + // ***************************************************************************** + static int readTagTable ( int * &tags, char ** &ctags, int &ntags ); + + // ********************************************************************* + // * cdevData: + // * This is the default constructor, it simply initializes + // * variables within the cdevData object. + // ********************************************************************* + cdevData ( void ); + + // ********************************************************************* + // * cdevData: + // * Copy constructor. This constructor duplicates the cdevData + // * object that it has been passed as a parameter. + // ********************************************************************* + cdevData ( const cdevData & data ); + + // ********************************************************************* + // * ~cdevData: + // * This is the default destructor for the cdevData object. It + // * frees any memory allocated for storage and deletes the object. + // ********************************************************************* + ~cdevData( void ); + + // ********************************************************************* + // * Assignment operator: + // * This function copies the contents of a cdevData object to this + // * object. + // ********************************************************************* + cdevData & operator = (const cdevData & data); + + // ********************************************************************* + // * Casting operators: + // * These operators provide convenience methods for the user to + // * obtain the value tagged data item from the cdevData object. + // ********************************************************************* + operator char ( void ); + operator short ( void ); + operator unsigned short ( void ); + operator int ( void ); + operator unsigned int ( void ); + operator long ( void ); + operator unsigned long ( void ); + operator float ( void ); + operator double ( void ); + operator char * ( void ); + + // ********************************************************************* + // * Assignment operators: + // * These operators provide convenience methods for the user to + // * obtain the value tagged cdevData object from various typed data. + // ********************************************************************* + cdevData& operator= (unsigned char x); + cdevData& operator= (short x); + cdevData& operator= (unsigned short x); + cdevData& operator= (int x); + cdevData& operator= (unsigned int x); + cdevData& operator= (long x); + cdevData& operator= (unsigned long x); + cdevData& operator= (float x); + cdevData& operator= (double x); + + // ********************************************************************* + // * Append operation: + // * This operation will append a cdevData onto an existing cdevData + // * and return this object. If there is confilicts among tags, the + // * appended one wins + // ********************************************************************* + cdevData& operator += (const cdevData& data); + + // ********************************************************************* + // * asciiDump: + // * Performs a diagnostic dump of the entire contents of the + // * cdevData object to the specified file pointer. + // ********************************************************************* +#ifdef _WIN32 + inline void asciiDump ( FILE * fp = stdout ) + { + int fd = _fileno(fp); + long osfHandle = _get_osfhandle(fd); + asciiDump(osfHandle); + _lseek(fd, 0L, SEEK_END); + } + void asciiDump ( long osfHandle ); +#else + void asciiDump ( FILE * fp = stdout ); +#endif + + // ********************************************************************* + // * XDR Utilities: + // * These functions provide the mechanisms for converting a cdevData + // * object into a network portable bninary stream, and then + // * reconstructing them after transport. + // ********************************************************************* + virtual int xdrSize (size_t * bufLen, size_t * elementCount); + virtual int xdrExport ( char ** buf, size_t * bufLen ); + virtual int xdrExport ( char * buf, size_t bufLen, size_t count); + virtual int xdrImport ( char * buf, size_t bufLen); + + // ********************************************************************* + // * remove: + // * Removes cdevDataEntry objects from the cdevData object by tag + // * integer or by tag string. If no tag is specified, then all + // * cdevDataEntry objects will be removed. + // ********************************************************************* + void remove( void ); + void remove( int tag ); + void remove( char * ctag ); + + // ********************************************************************* + // * changeTag: + // * Replace a new tag with the old one within the + // * cdevData object. If the old one can not be not found, + // * CDEV_NOTFOUND is returned. If the new tag has already + // * been found in that cdevData object, CDEV_ERROR is returned. + // ********************************************************************* + virtual int changeTag(int oldTag, int newTag); + int changeTag(int oldTag, char *c_newTag); + int changeTag(char *c_oldTag, int newTag); + int changeTag(char *c_oldTag, char *c_newTag); + + // ********************************************************************* + // * getType: + // * Retrieves the cdevDataTypes of the referenced tagged data item. + // * If no item with that tag is within the cdevData object, then + // * CDEV_INVALID is returned. + // ********************************************************************* + cdevDataTypes getType(int tag); + cdevDataTypes getType(char *ctag); + + + // ********************************************************************* + // * getDim: + // * Obtains the number of dimensions in the specified tagged data + // * item. Returns CDEV_SUCCESS if the tagged item exists, otherwise, + // * CDEV_NOTFOUND is returned. + // ********************************************************************** + int getDim(int tag, size_t *dim); + int getDim(char *ctag, size_t *dim); + + // ********************************************************************* + // * getElems: + // * Obtains the number of elements in the specified tagged data + // * item. Returns CDEV_SUCCESS if the tagged item exists, otherwise, + // * CDEV_NOTFOUND is returned. + // ********************************************************************** + int getElems(int tag, size_t *elems); + int getElems(char *ctag, size_t *elems); + + // ********************************************************************* + // * getBounds: + // * Obtains the bounding dimensions of a cdevDataEntry array. The + // * integer array passed as the bounds parameter must be allocated + // * by the caller. The number of integers required is 2 times the + // * number of dimensions, the first being the offset and the second + // * being the length of the dimension. The len parameter specifies + // * the actual number of integers allocated. + // ********************************************************************* + int getBounds(int tag, size_t * bounds, size_t len); + int getBounds(char * ctag, size_t * bounds, size_t len); + + // ********************************************************************* + // * getBounds: + // * Obtains the bounding dimensions of a cdevDataEntry array. The + // * cdevBounds structure passed as the bounds parameter must be + // * allocated by the caller. The numBounds variable indicates the + // * number of cdevBounds structures allocated by the caller. + // ********************************************************************* + int getBounds(int tag, cdevBounds * bounds, size_t numBounds); + int getBounds(char * ctag, cdevBounds * bounds, size_t numBounds); + + // ********************************************************************* + // * setBounds: + // * Allows the caller to set the dimensions of a multidimensional + // * tagged data item. The number of integers required is 2 times the + // * number of dimensions, the first being the offset and the second + // * being the length of the dimension. The len parameter specifies + // * the actual number of integers submitted. + // ********************************************************************* + int setBounds(int tag, size_t * bounds, size_t len); + int setBounds(char * ctag, size_t * bounds, size_t len); + + // ********************************************************************* + // * setBounds: + // * Allows the caller to set the dimensions of a multidimensional + // * tagged data item. The numBounds variable indicates the number + // * of cdevBounds structures submitted by the user. + // ********************************************************************* + int setBounds(int tag, cdevBounds * bounds, size_t numBounds); + int setBounds(char * ctag, cdevBounds * bounds, size_t numBounds); + + // ********************************************************************* + // * insert: + // * The following functions allow the insertion of scalar data into + // * a cdevData object. + // ********************************************************************* + int insert ( int tag, BYTE data ); + int insert ( int tag, short data ); + int insert ( int tag, unsigned short data ); + int insert ( int tag, long data ); + int insert ( int tag, unsigned long data ); + int insert ( int tag, float data ); + int insert ( int tag, double data ); + int insert ( int tag, cdev_TS_STAMP data ); + + // ********************************************************************* + // * Overloaded character tag based insertion mechanism + // ********************************************************************* + int insert ( char * ctag, BYTE data); + int insert ( char * ctag, short data); + int insert ( char * ctag, unsigned short data); + int insert ( char * ctag, long data); + int insert ( char * ctag, unsigned long data); + int insert ( char * ctag, float data); + int insert ( char * ctag, double data); + int insert ( char * ctag, cdev_TS_STAMP data); + + // ******************************************************************** + // * insert: + // * The following functions allow the insertion of arrays of data + // * into a cdevData object. The len variable contains the total + // * number of elements to be inserted, the ndim variable indicates + // * the number of dimensions in the array. + // ******************************************************************** + int insert (int tag, BYTE * data, size_t len, size_t ndim = 1); + int insert (int tag, short * data, size_t len, size_t ndim = 1); + int insert (int tag, unsigned short * data, size_t len, size_t ndim = 1); + int insert (int tag, long * data, size_t len, size_t ndim = 1); + int insert (int tag, unsigned long * data, size_t len, size_t ndim = 1); + int insert (int tag, float * data, size_t len, size_t ndim = 1); + int insert (int tag, double * data, size_t len, size_t ndim = 1); + int insert ( int tag, cdev_TS_STAMP *data, size_t len, size_t ndim = 1); + + // ********************************************************************* + // * Overloaded character tag based insertion mechanism + // ********************************************************************* + int insert (char * ctag, BYTE * data, size_t len, size_t ndim = 1); + int insert (char * ctag, short * data, size_t len, size_t ndim = 1); + int insert (char * ctag, unsigned short * data, size_t len, size_t ndim = 1); + int insert (char * ctag, long * data, size_t len, size_t ndim = 1); + int insert (char * ctag, unsigned long * data, size_t len, size_t ndim = 1); + int insert (char * ctag, float * data, size_t len, size_t ndim = 1); + int insert (char * ctag, double * data, size_t len, size_t ndim = 1); + int insert (char * ctag, cdev_TS_STAMP *data, size_t len, size_t ndim =1 ); + + // ********************************************************************* + // * insert: + // * The following functions explicitly call the long functions when + // * dealing with integer data. On a system with 16 bit integers, + // * the short functions should be called. + // ********************************************************************* +#ifdef DEFAULT_16_BIT_INTEGER + int insert ( int tag, int data ); + int insert ( int tag, unsigned int data ); + int insert ( char * ctag, int data); + int insert ( char * ctag, unsigned int data); + int insert (int tag, int * data, size_t len, size_t ndim = 1); + int insert (int tag, unsigned int * data, size_t len, size_t ndim = 1); + int insert (char * ctag, int * data, size_t len, size_t ndim = 1); + int insert (char * ctag, unsigned int * data, size_t len, size_t ndim = 1); +#else + int insert ( int tag, int data ); + int insert ( int tag, unsigned int data ) ; + int insert ( char * ctag, int data); + int insert ( char * ctag, unsigned int data); + int insert (int tag, int * data, size_t len, size_t ndim = 1); + int insert (int tag, unsigned int * data, size_t len, size_t ndim = 1); + int insert (char * ctag, int * data, size_t len, size_t ndim = 1); + int insert (char * ctag, unsigned int * data, size_t len, size_t ndim = 1); +#endif + + // ********************************************************************* + // * insert: + // * The following functions insert character strings and arrays of + // * character strings. Their treatment is different from the scalar + // * data types. + // ********************************************************************* + int insert ( int tag, char * data ); + int insert ( int tag, char ** data, size_t len = 0, size_t ndim = 1 ); + + // ********************************************************************* + // * Overloaded character tag based insertion mechanism + // ********************************************************************* + int insert ( char * ctag, char * data); + int insert ( char * ctag, char ** data, size_t len = 0, size_t ndim = 1); + + // ********************************************************************* + // * get: + // * This group of functions allows the user to extract scalar and + // * array data from the cdevData object. + // ********************************************************************* + int get(int tag, BYTE * data); + int get(int tag, short * data); + int get(int tag, unsigned short * data); + int get(int tag, long * data); + int get(int tag, unsigned long * data); + int get(int tag, float * data); + int get(int tag, double * data); + int get(int tag, char * data, size_t len); + int get(int tag, char ** data); + int get(int tag, cdev_TS_STAMP * data); + // ********************************************************************* + // * Overloaded character tag based extraction mechanism + // ********************************************************************* + int get(char * ctag, BYTE * data); + int get(char * ctag, short * data); + int get(char * ctag, unsigned short * data); + int get(char * ctag, long * data); + int get(char * ctag, unsigned long * data); + int get(char * ctag, float * data); + int get(char * ctag, double * data); + int get(char * ctag, char * data, size_t len); + int get(char * ctag, char ** data); + int get(char * ctag, cdev_TS_STAMP * data); + + // ********************************************************************* + // * get: + // * The following get functions explicitly call the long integer + // * functions unless the user is on a system with 16 bit integers. + // ********************************************************************* +#ifdef DEFAULT_16_BIT_INTEGER + int get(int tag, int * data); + int get(int tag, unsigned int * data); + int get(char *ctag, int * data); + int get(char *ctag, unsigned int * data); +#else + int get(int tag, int * data); + int get(int tag, unsigned int * data); + int get(char *ctag, int * data); + int get(char *ctag, unsigned int * data); +#endif + + // ********************************************************************* + // * find: + // * These functions allow the user to obtain a pointer to data + // * within the actual data variables within the cdevData object. + // ********************************************************************* + int find(int tag, void* &data); + int find(char * ctag, void* &data); + + // ********************************************************************* + // * operator ==, operator !=: + // * These methods provides a fast way for the caller to identify if two + // * cdevData objects contain the identical fields and values... + // ********************************************************************* + int operator == (cdevData & data); + int operator != (cdevData & data) { return !(operator == (data)); } + }; + + +class CDEV_CLASS_SPEC cdevDataIterator + { + public: + cdevDataIterator(cdevData* data); + ~cdevDataIterator() {}; + int init(); + int operator !(); + int operator ++(); + int tag(void); + + protected: + cdevData *dataobj_; + cdevDataEntry *cur_; + }; + +#undef INLINE +#ifndef _CDEV_NO_INLINE +#define INLINE inline +#include "cdevData.i" +#else +#define INLINE +#endif + +#endif diff --git a/src/cdevIO/cdevData.i b/src/cdevIO/cdevData.i new file mode 100755 index 0000000..af9206c --- /dev/null +++ b/src/cdevIO/cdevData.i @@ -0,0 +1,572 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: cdevData.h +// Self descibing data structure to manage the storage and transport +// of data between local cdev functions, as well as remote client and +// server applications. +// +// Author: Walt Akers and Danjin Wu +// +// Revision History: +// cdevData.i,v +// Revision 1.6 1996/11/21 17:02:59 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.5 1996/07/12 18:09:01 chen +// change copy and assignment to const cdevData& +// +// Revision 1.4 1996/04/12 13:40:07 akers +// Added char * cast operator +// +// Revision 1.3 1996/02/27 20:50:13 danjin +// add assignment operator from various typed data to cdevData object +// +// Revision 1.2 1995/10/16 18:14:20 chen +// Fix a bug for SunOs and g++ +// +// Revision 1.1 1995/10/06 19:39:03 chen +// all cdevData inline functions +// +// +INLINE +cdevDataEntry* cdevData::lookupTag(char * ctag, int create) +{ + int tag; + return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + (cdevDataEntry *)0:lookupTag(tag, create); +} + +INLINE +cdevData & +cdevData::operator = (const cdevData & data) +{ + return copy(data); +} + +INLINE +void cdevData::remove( char * ctag ) +{ + int tag; if(!cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)) remove(tag); +} + +INLINE +cdevDataTypes cdevData::getType(char *ctag) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + CDEV_INVALID:getType(tag); +} + +INLINE +int cdevData::getDim(char *ctag, size_t *dim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + CDEV_NOTFOUND:getDim(tag, dim); +} + +INLINE +int cdevData::getElems(char *ctag, size_t *elems) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + CDEV_NOTFOUND:getElems(tag, elems); +} + +INLINE +int cdevData::getBounds(char * ctag, size_t * bounds, size_t len) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + CDEV_NOTFOUND:getBounds(tag, bounds, len); +} + +INLINE +int cdevData::getBounds(char * ctag, cdevBounds * bounds, size_t numBounds) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + CDEV_NOTFOUND:getBounds(tag, bounds, numBounds); +} + +INLINE +int cdevData::setBounds(char * ctag, size_t * bounds, size_t len) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + CDEV_NOTFOUND:setBounds(tag, bounds, len); +} + +INLINE +int cdevData::setBounds(char * ctag, cdevBounds * bounds, size_t numBounds) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)? + CDEV_NOTFOUND:setBounds(tag, bounds, numBounds); +} + +INLINE +int cdevData::insert ( char * ctag, BYTE data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, short data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, unsigned short data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, long data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, unsigned long data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, float data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, double data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, cdev_TS_STAMP data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert (char * ctag, BYTE * data, size_t len, size_t ndim) +{ +int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, short * data, size_t len, size_t ndim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, unsigned short * data, size_t len, size_t ndim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, long * data, size_t len, size_t ndim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, unsigned long * data, size_t len, size_t ndim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, float * data, size_t len, size_t ndim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, double * data, size_t len, size_t ndim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert ( char * ctag, char * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data); +} + +INLINE +int cdevData::insert ( char * ctag, char ** data, size_t len, size_t ndim) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, cdev_TS_STAMP * data, size_t len, size_t ndim) +{ +int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:insert(tag, data, len, ndim); +} + +INLINE +int cdevData::get(char * ctag, BYTE * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, short * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, unsigned short * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, long * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, unsigned long * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, float * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, double * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, char * data, size_t len) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data, len); +} + +INLINE +int cdevData::get(char * ctag, char ** data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::get(char * ctag, cdev_TS_STAMP * data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:get(tag, data); +} + +INLINE +int cdevData::find(char * ctag, void* &data) +{ + int tag; return cdevGlobalTagTable::tagTable()->tagC2I(ctag, &tag)?CDEV_NOTFOUND:find(tag, data); +} + +#ifdef DEFAULT_16_BIT_INTEGER +INLINE +int cdevData::insert ( int tag, int data ) +{ + return insert(tag, (short)data); +} + +INLINE +int cdevData::insert ( int tag, unsigned int data ) +{ + return insert(tag, (unsigned short)data); +} + +INLINE +int cdevData::insert ( char * ctag, int data) +{ + return insert(ctag, (short)data); +} + +INLINE +int cdevData::insert ( char * ctag, unsigned int data) +{ + return insert(ctag, (unsigned short)data); +} + +INLINE +int cdevData::insert (int tag, int * data, size_t len, size_t ndim) +{ + return insert(tag, (short *)data, len, ndim); +} + +INLINE +int cdevData::insert (int tag, unsigned int * data, size_t len, size_t ndim) +{ + return insert(tag, (unsigned short *)data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, int * data, size_t len, size_t ndim) +{ + return insert(ctag, (short *)data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, unsigned int * data, size_t len, size_t ndim) +{ + return insert(ctag, (unsigned short *)data, len, ndim); +} +#else +INLINE +int cdevData::insert ( int tag, int data ) +{ + return insert(tag, (long)data); +} + +INLINE +int cdevData::insert ( int tag, unsigned int data ) +{ + return insert(tag, (unsigned long)data); +} + +INLINE +int cdevData::insert ( char * ctag, int data) +{ + return insert(ctag, (long)data); +} + +INLINE +int cdevData::insert ( char * ctag, unsigned int data) +{ + return insert(ctag, (unsigned long)data); +} + +INLINE +int cdevData::insert (int tag, int * data, size_t len, size_t ndim) +{ + return insert(tag, (long *)data, len, ndim); +} + +INLINE +int cdevData::insert (int tag, unsigned int * data, size_t len, size_t ndim) +{ + return insert(tag, (unsigned long *)data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, int * data, size_t len, size_t ndim) +{ + return insert(ctag, (long *)data, len, ndim); +} + +INLINE +int cdevData::insert (char * ctag, unsigned int * data, size_t len, size_t ndim) +{ + return insert(ctag, (unsigned long *)data, len, ndim); +} +#endif + +#ifdef DEFAULT_16_BIT_INTEGER +INLINE +int cdevData::get(int tag, int * data) +{ + return get(tag, (short *)data); +} + +INLINE +int cdevData::get(int tag, unsigned int * data) +{ + return get(tag, (unsigned short *) data); +} + +INLINE +int cdevData::get(char *ctag, int * data) +{ + return get(ctag, (short *)data); +} + +INLINE +int cdevData::get(char *ctag, unsigned int * data) +{ + return get(ctag, (unsigned short *) data); +} +#else +INLINE +int cdevData::get(int tag, int * data) +{ + return get(tag, (long *)data); +} + +INLINE +int cdevData::get(int tag, unsigned int * data) +{ + return get(tag, (unsigned long *) data); +} + +INLINE +int cdevData::get(char *ctag, int * data) +{ + return get(ctag, (long *)data); +} + +INLINE +int cdevData::get(char *ctag, unsigned int * data) +{ + return get(ctag, (unsigned long *) data); +} +#endif + +INLINE +cdevData::operator char( void ) +{ + BYTE x; get("value", &x); return x; +} + +INLINE +cdevData::operator short( void ) +{ + short x; get("value", &x); return x; +} + +INLINE +cdevData::operator unsigned short( void ) +{ + unsigned short x; get("value", &x); return x; +} + +INLINE +cdevData::operator int( void ) +{ + int x; get("value", &x); return x; +} + +INLINE +cdevData::operator unsigned int( void ) +{ + unsigned int x; get("value", &x); return x; +} + +INLINE +cdevData::operator long( void ) +{ + long x; get("value", &x); return x; +} + +INLINE +cdevData::operator unsigned long( void ) +{ + unsigned long x; get("value", &x); return x; +} + +INLINE +cdevData::operator float( void ) +{ + float x; get("value", &x); return x; +} + +INLINE +cdevData::operator double( void ) +{ + double x; get("value", &x); return x; +} + + +INLINE +cdevData::operator char * ( void ) +{ +char * result = NULL; +static char temp[64]; +size_t dim = 0; +int valueTag = 1; +cdevDataTypes dataType = CDEV_INVALID; + +tagC2I("value", &valueTag); +getDim(valueTag, &dim); +if(dim==0) dataType = getType(valueTag); + +switch(dataType) + { + case CDEV_INVALID: + result=NULL; + break; + + case CDEV_STRING: + find("value", (void * &)result); + break; + + default: + get("value", temp, 64); + result = temp; + break; + + } +return result; +} + + +INLINE +cdevData& cdevData::operator= (unsigned char x) +{ + insert("value", x); + return *this; +} + +INLINE cdevData& cdevData::operator= (short x) +{ + insert("value", x); + return *this; +} + +INLINE cdevData& cdevData::operator= (unsigned short x) +{ + insert("value", x); + return *this; +} + +INLINE cdevData& cdevData::operator= (int x) +{ + insert("value", x); + return *this; +} + +INLINE cdevData& cdevData::operator= (unsigned int x) +{ + insert("value", x); + return *this; +} +INLINE cdevData& cdevData::operator= (long x) +{ + insert("value", x); + return *this; +} + +INLINE cdevData& cdevData::operator= (unsigned long x) +{ + insert("value", x); + return *this; +} + +INLINE cdevData& cdevData::operator= (float x) +{ + insert("value", x); + return *this; +} + +INLINE cdevData& cdevData::operator= (double x) +{ + insert("value", x); + return *this; +} + + + diff --git a/src/cdevIO/cdevDataEntry.cc b/src/cdevIO/cdevDataEntry.cc new file mode 100755 index 0000000..d9e31ef --- /dev/null +++ b/src/cdevIO/cdevDataEntry.cc @@ -0,0 +1,132 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//------------------------------------------------------------------------------ +// +// description: cdevDataEntry.cc +// This file contains the non-inlined functions associated with the +// cdevDataEntry family of classes. +// +// Author: Walt Akers +// +// Revision History: +// cdevDataEntry.cc,v +// Revision 1.4 1996/11/21 17:03:01 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.3 1996/08/23 21:24:23 akers +// Corrected Problem with operator == +// +// Revision 1.2 1995/07/14 13:01:14 akers +// Updated version of cdevData source code +// +// +// +//------------------------------------------------------------------------------ +#include "cdevDataEntry.h" + + +// ***************************************************************************** +// * cdevDataEntryeStorage::operator ==: +// * This operator allows you to directly and rapidly compare two +// * cdevDataEntryStorage objects... +// ***************************************************************************** +int cdevDataEntryStorage::operator == (cdevDataEntryStorage & entry) + { + int result = 0; + int i = 0; + + // ********************************************************************* + // * First compare all of the pertinent scalar values... + // ********************************************************************* + if(tag_ == entry.tag_ && + dataType_ == entry.dataType_ && + dim_ == entry.dim_ && + elems_ == entry.elems_) + { + // ************************************************************* + // * Next compare the contents of the data items... + // ************************************************************* + if(dim_) + { + result = 0; + if(dataType_==CDEV_BYTE) + for(i=0; inext_; + } + + return result; + } diff --git a/src/cdevIO/cdevDataEntry.h b/src/cdevIO/cdevDataEntry.h new file mode 100755 index 0000000..cbccc55 --- /dev/null +++ b/src/cdevIO/cdevDataEntry.h @@ -0,0 +1,365 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//------------------------------------------------------------------------------ +// +// description: cdevDataEntry.h +// This file defines the classes necessary for storage of an individual +// tagged data item within a cdevData class object. +// +// Author: Walt Akers & Danjin Wu +// +// Revision History: +// cdevDataEntry.h,v +// Revision 1.9 1996/11/21 17:03:04 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.8 1996/09/20 19:33:12 akers +// Changed protection in cdevDataEntryStorage, cdevDataEntry and cdevData in order to support subclassing of the cdevData object +// +// Revision 1.7 1996/08/23 21:24:25 akers +// Corrected Problem with operator == +// +// Revision 1.6 1996/08/23 15:34:09 akers +// Added comparison operator to cdevData +// +// Revision 1.5 1995/10/16 18:13:59 chen +// Fix a bug fot sunOs and g++ +// +// Revision 1.4 1995/09/22 21:08:14 danjin +// cdevdataIterator is friend class +// +// Revision 1.3 1995/09/06 18:34:49 danjin +// added time stamp structure type +// +// Revision 1.2 1995/07/14 13:25:30 akers +// Header files added to support the changes specified at June 95 Review +// +// +// +//------------------------------------------------------------------------------ + +#ifndef __CDEV_DATA_ENTRY_H_ +#define __CDEV_DATA_ENTRY_H_ + +#include +#include + +// ############################################################################# +// # cdevDataEntryStorage: +// # This class contains the data elements and methods necessary to store data +// # associated with one tagged data item. +// # +// # Note: Because the cdevData object must actively manipulate the data in +// # this structure - it has been made public to increase access speed +// # and to allow the subclassing of the cdevData object. +// ############################################################################# +class cdevDataEntryStorage + { + public: + // ************************************************************* + // * tag_: + // * This is the integer value that is used to uniquely identify + // * a data element within a cdevData object. + // ************************************************************* + int tag_; + + // ************************************************************* + // * dataType_: + // * This is the data type of the tagged data item that is to be + // * stored in this cdevDataEntryStorage object. + // ************************************************************* + cdevDataTypes dataType_; + + // ************************************************************* + // * size_: + // * This variable is the allocated size of the buffer_ which is + // * used to store both the array data and its associated bounds + // * information. + // ************************************************************* + size_t size_; + + // ************************************************************* + // * dim_: + // * This variable indicates the user specified number of + // * dimensions that the array represents. + // ************************************************************* + size_t dim_; + + // ************************************************************* + // * elems_: + // * This variable contains the maximum number of elements that + // * the array may contain. + // ************************************************************* + size_t elems_; + + // ************************************************************* + // * bytes_: + // * This variable contains the number of bytes per element. + // ************************************************************* + size_t bytes_; + + // ************************************************************* + // * buffer_: + // * This is the buffer that is allocated to store data and + // * bounds information. + // ************************************************************* + unsigned char * buffer_; + + // ************************************************************* + // * data_: + // * This is a union that is used to store scalar data and a + // * pointer to the array data this is stored within this object + // ************************************************************* + union dataUnion { + BYTE cval; + short sval; + unsigned short usval; + long lval; + unsigned long ulval; + float fval; + double dval; + void * vptr; + BYTE * cptr; + short * sptr; + unsigned short * usptr; + long * lptr; + unsigned long * ulptr; + float * fptr; + double * dptr; + char * str; + char ** strarr; + cdev_TS_STAMP ts; + cdev_TS_STAMP * tsptr; + } data_; + + // ************************************************************* + // * cdevDataEntryStorage: + // * Default constructor for the cdevDataEntryStorage class. It sets + // * the buffer_ pointer to NULL to prevent deletion of non- + // * allocated memory, and then calls the clear method to + // * initialize all data variables. + // ************************************************************* + cdevDataEntryStorage ( void ) : buffer_(NULL) + { + clear(); + } + + // ************************************************************* + // * ~cdevDataEntryStorage: + // * Default destructor for the cdevDaaEntry class. It calls + // * the clear method to release and reinitialize all data + // * elements. + // ************************************************************* + ~cdevDataEntryStorage ( void ) + { + clear(); + } + + // ************************************************************* + // * clear: + // * Releases and reinitializes all data variables. + // ************************************************************* + void clear ( void ) + { + deallocate(); + tag_ = 0; + dataType_ = CDEV_INVALID; + } + + // ************************************************************* + // * allocate: + // * Allocates a block of memory sufficient to store a caller + // * specified number of cdevBounds structures and a caller + // * specified number of bytes. If sufficient space has already + // * been allocated, then it will be used, otherwise, a new + // * block will be created to service the request. + // ************************************************************* + void allocate ( size_t dimensions, size_t elems, size_t bytesPerElem ) + { + size_t newBlockSize = + (dimensions*sizeof(cdevBounds))+(elems * bytesPerElem); + + if(buffer_==NULL || newBlockSize>size_) + { + deallocate(); + buffer_ = ::new unsigned char[newBlockSize]; + size_ = newBlockSize; + } + dim_ = dimensions; + elems_ = elems; + bytes_ = bytesPerElem; + data_.vptr = &buffer_[dim_ * sizeof(cdevBounds)]; + memset (buffer_, 0, newBlockSize); + } + + // ************************************************************* + // * deallocate: + // * Deallocates any memory previously allocated to the buffer + // * and reinitializes the size_, dim_, bytes_ and buffer_ + // * variables. Any references to the previously allocated + // * block is cleared. + // ************************************************************* + void deallocate ( void ) + { + if(buffer_ != NULL) + { + ::delete buffer_; + buffer_ = NULL; + } + size_ = 0; + dim_ = 0; + elems_ = 0; + bytes_ = 0; + data_.dval = 0.00; + // memset(&data_, 0, sizeof(data_)); + } + + // ************************************************************* + // * bounds: + // * Returns a pointer to the cdevBounds object if the data + // * is multidimensional, otherwise, a NULL is returned. + // ************************************************************* + cdevBounds * bounds ( void ) + { + return (dim_>0)?(cdevBounds *)buffer_:(cdevBounds *)0; + } + + // ************************************************************* + // * operator ==: + // * This operator allows you to directly and rapidly + // * compare two cdevDataEntryStorage objects... + // ************************************************************* + int operator == (cdevDataEntryStorage & entry); + + // ************************************************************* + // * operator !=: + // * This operator allows the caller to directly and rapidly + // * comapre two cdevDataEntryStorage objects. + // ************************************************************* + int operator != (cdevDataEntryStorage & entry) + { + return !(operator == (entry)); + } + + }; + + +// ############################################################################# +// # cdevDataEntry: +// # This class is used to define the node attributes necessary to support +// # linked lists of cdevDataEntryStorage objects. It also provides an internal +// # freelist of cdevDataEntry objects. +// # +// # Note: Because the cdevData object must actively manipulate the data in +// # this structure - it has been made public to increase access speed +// # and to allow the subclassing of the cdevData object. +// ############################################################################# +class cdevDataEntry : public cdevDataEntryStorage + { + public: + // ************************************************************* + // * freeList_: + // * This is a pointer to a list of currently allocated + // * cdevDataEntrys that will be provided to the user + // * upon request. This technique should reduce the number of + // * mallocs called to allocated cdevDataEntrys. + // ************************************************************* + static cdevDataEntry * freeList_; + + // ************************************************************* + // * ALLOCATION_COUNT: + // * This is the minimum number of cdevDataEntrys that will + // * be allocated when the freeList_ becomes empty. + // ************************************************************* + enum { ALLOCATION_COUNT = 16 }; + + // ************************************************************* + // * next_ : + // * This is the pointer to the next element in the list of + // * cdevDataEntry objects. + // ************************************************************* + cdevDataEntry * next_; + + // ************************************************************* + // * cdevDataEntry: + // * Constructor for the class. It serves only to set the next_ + // * pointer to NULL. + // ************************************************************* + cdevDataEntry ( void ) : next_(NULL), cdevDataEntryStorage() + { + } + + // ************************************************************* + // * ~cdevDataEntry: + // * Destructor for the class. It is a placeholder that + // * does nothing when called. + // ************************************************************* + ~cdevDataEntry ( void ) + { + } + + // ************************************************************* + // * next: + // * Retrieves a pointer to the next_ cdevDataEntry object. + // * Incorporation of this function into a list object is the + // * responsibility of the caller. + // ************************************************************* + cdevDataEntry * &next ( void ) + { + return next_; + } + + // ************************************************************* + // * new: + // * Allocation function for the object. It will get the next + // * preallocated cdevDataEntry object from the freeList_, + // * or, if none are available, refill the freeList_ and then + // * return a new cdevDataEntry object. + // ************************************************************* + void * operator new ( size_t size ); + + // ************************************************************* + // * delete: + // * Rather than deallocating the cdevDataEntry object, this + // * function returns it to the freeList_ where it may be + // * retrieved by a later call of new. + // ************************************************************* + void operator delete ( void * ptr ) + { + cdevDataEntry * node = (cdevDataEntry *)ptr; + if(node != NULL) { + node->next_ = freeList_; + freeList_ = node; + } + } + + // ************************************************************* + // * operator ==: + // * This operator allows you to directly and rapidly + // * compare two cdevDataEntry objects... + // ************************************************************* + int operator == (cdevDataEntry & entry) + { + cdevDataEntryStorage *storage = &entry; + + return cdevDataEntryStorage::operator == (*storage); + } + + // ************************************************************* + // * operator !=: + // * This operator allows the caller to directly and rapidly + // * comapre two cdevDataEntry objects. + // ************************************************************* + int operator != (cdevDataEntry & entry) + { + cdevDataEntryStorage *storage = &entry; + return !(cdevDataEntryStorage::operator == (*storage)); + } + + }; + +#endif /* __CDEV_DATA_ENTRY_H_ */ diff --git a/src/cdevIO/cdevGlobalTagTable.cc b/src/cdevIO/cdevGlobalTagTable.cc new file mode 100755 index 0000000..16cc266 --- /dev/null +++ b/src/cdevIO/cdevGlobalTagTable.cc @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of cdevGlobalTagTable +// +// Author: Jie Chen +// +// Revision History: +// cdevGlobalTagTable.cc,v +// Revision 1.2 1996/05/07 16:32:31 chen +// Add stdio to the file +// +// Revision 1.1 1995/10/03 19:53:51 chen +// single instance of cdevTagTable +// +// +#include +#include +#include "cdevGlobalTagTable.h" + +cdevTagTable* cdevGlobalTagTable::instance_ = 0; + +cdevGlobalTagTable::cdevGlobalTagTable (void) +{ +#ifdef _CDEV_DEBUG + printf ("Create cdevGlobalTagTable Class Object\n"); +#endif + // empty +} + +cdevGlobalTagTable::~cdevGlobalTagTable (void) +{ +#ifdef _CDEV_DEBUG + printf ("delete cdevGlobalTagTable Class Object\n"); +#endif + // empty +} + +cdevTagTable* +cdevGlobalTagTable::tagTable (void) +{ + if (cdevGlobalTagTable::instance_ == 0) + cdevGlobalTagTable::instance_ = new cdevTagTable (); + return cdevGlobalTagTable::instance_; +} diff --git a/src/cdevIO/cdevGlobalTagTable.h b/src/cdevIO/cdevGlobalTagTable.h new file mode 100755 index 0000000..112daa2 --- /dev/null +++ b/src/cdevIO/cdevGlobalTagTable.h @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdev global tag table +// +// Author: Jie Chen +// +// Revision History: +// cdevGlobalTagTable.h,v +// Revision 1.1 1995/10/03 19:54:40 chen +// single instance of cdevTagTable +// +// +#ifndef _CDEV_GBL_TAG_TABLE_H +#define _CDEV_GBL_TAG_TABLE_H + +// Use singleton design pattern to ensure that there is only +// one tag table in the system without using global variable +// which is not desirable in C++ + +#include + +class CDEV_CLASS_SPEC cdevGlobalTagTable +{ +public: + static cdevTagTable* tagTable (void); + +protected: + // constructor + cdevGlobalTagTable (void); + virtual ~cdevGlobalTagTable (void); + +private: + static cdevTagTable* instance_; +}; +#endif diff --git a/src/cdevIO/cdevTagTable.cc b/src/cdevIO/cdevTagTable.cc new file mode 100755 index 0000000..2f4ff68 --- /dev/null +++ b/src/cdevIO/cdevTagTable.cc @@ -0,0 +1,424 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//------------------------------------------------------------------------------ +// +// description: +// cdevTagTable class manages tags within the cdev system. +// +// Author: Walt Akers +// +// +// +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include "cdevTagTable.h" + +char* cdevTagTable::defaultTags[] = +{ + "value", + "status", + "severity", + "time", + "units", + "displayHigh", + "displayLow", + "alarmHigh", + "alarmLow", + "warningHigh", + "warningLow", + "controlHigh", + "controlLow", + "bitMask", + "file", + "class", + "device", + "message", + "verb", + "attribute", + "collection", + "resultCode", // Used to return the completion status of a server operation + "clientID", // Used in context to identify a client by number + "precision", + NULL +}; +unsigned int cdevTagTable::numberDefTags = 24; +// Note: if you want to add new tags, make sure to change the above number to +// reflect the change of number of default tags + +// default tag table location and tag table environment variable +char* cdevTagTable::defaultTagTableLocation = "/usr/local/lib/cdevTagTable"; +char* cdevTagTable::tagTableEnv = "CDEVTAGTABLE"; + +const int INT_TAG_TABLE_SIZE = 997; +const int STR_TAG_TABLE_SIZE = 997; + +cdevTagTable::cdevTagTable (void) +:itagList_ (INT_TAG_TABLE_SIZE), + stagList_ (STR_TAG_TABLE_SIZE, cdevStrHashFunc), + callbacks_(NULL), + highestTag(1000) +{ +#ifdef _TRACE_OBJECT + printf ("Create cdevTagTable Class Object\n"); +#endif + initialize (); +} + +void cdevTagTable::initialize ( void ) +{ + // first check a tag table file pointed by an environment variable CDEVTAGTABLE + int tsuccess = 1, i = 0; + char** tags; + int* tagvalues; + unsigned int numTags = 0; + + char* tagtable = ::getenv (cdevTagTable::tagTableEnv); + if (tagtable) + tsuccess = cdevTagTable::parseTagTable (tagtable, tags, tagvalues, numTags); + else + tsuccess = cdevTagTable::parseTagTable (cdevTagTable::defaultTagTableLocation, + tags, tagvalues, numTags); + + if (tsuccess) { + for (i = 0; i < numTags; i++) + insertTag(tagvalues[i], tags [i]); + +#ifdef _CDEV_DEBUG + for(i = 0; i < numTags; i++){ + char * s; + tagI2C(tagvalues[i], s); + printf("Tag %i = %s\n", tagvalues[i], s); + } +#endif + + delete []tagvalues; + for (i = 0; i < numTags; i++) + delete []tags[i]; + delete []tags; + } + else { + for(i = 1; i <= cdevTagTable::numberDefTags; i++) + insertTag(i, cdevTagTable::defaultTags [i-1]); + +#ifdef _CDEV_DEBUG + for(i = 1; i <= cdevTagTable::numberDefTags; i++){ + char * s; + tagI2C(i, s); + printf("Tag %i = %s\n", i, s); + } +#endif + } + +} + +void +cdevTagTable::freeMemory (void) +{ + cdevStrHashIterator sit1(stagList_); + cdevTagEle *tmpele = 0; + for (sit1.init(); !sit1; ++sit1){ + if ( (tmpele = (cdevTagEle *)sit1 ()) != 0){ + delete []tmpele->tagName; + delete tmpele;} + } + // do not need to delete pointers inside itagList_ +} + +int +cdevTagTable::tagC2I(char *ctag, int *tag) +{ + cdevSlist& slist = stagList_.bucketRef (ctag); + cdevSlistIterator ssit (slist); + cdevTagEle *tmpele = 0; + for (ssit.init(); !ssit; ++ssit){ + tmpele = (cdevTagEle *)ssit (); + if ( ::strcmp (tmpele->tagName, ctag) == 0 ){ + *tag = tmpele->tagId; return CDEV_SUCCESS; + } + } + return CDEV_NOTFOUND; +} + +int +cdevTagTable::tagI2C(int tag, char * &ctag) +{ + cdevSlist& ilist = itagList_.bucketRef (tag); + cdevSlistIterator isit (ilist); + cdevTagEle *tmpele = 0; + for (isit.init(); !isit; ++isit){ + tmpele = (cdevTagEle *)isit (); + if ( tmpele->tagId == tag ){ + ctag = tmpele->tagName; return CDEV_SUCCESS; + } + } + return CDEV_NOTFOUND; +} + +void +cdevTagTable::insertTag(int tag, char *ctag) +{ + cdevSlist& slist = stagList_.bucketRef (ctag); + cdevSlist& ilist = itagList_.bucketRef (tag); + cdevSlistIterator ssit (slist); + cdevSlistIterator isit (ilist); + cdevTagEle *tmpele = 0; + int sfound = 0, ifound = 0; + + for (ssit.init(); !ssit; ++ssit){ + tmpele = (cdevTagEle *)ssit (); + if ( ::strcmp (tmpele->tagName, ctag) == 0 ){ + sfound = 1; break; + } + } + + for (isit.init(); !isit; ++isit){ + tmpele = (cdevTagEle *)isit (); + if ( tmpele->tagId == tag ){ + ifound = 1; break; } + } + + if ( (sfound == 0) && (ifound == 0) ) { + cdevTagEle *tag_elem = new cdevTagEle; + tag_elem->tagName = new char[::strlen(ctag) + 1]; + ::strcpy (tag_elem->tagName, ctag); + tag_elem->tagId = tag; + stagList_.add((char *)ctag, (void *)tag_elem); + itagList_.add(tag, (void *)tag_elem); + + // ************************************************************************* + // * Notify each of the callback objects that a new tag has been added. + // ************************************************************************* + if(callbacks_!=NULL) + { + cdevTagTableCallback * cb = callbacks_; + while(cb!=NULL) + { + cb->callback(tag, ctag); + cb = cb->next_; + } + } + } + else { +#ifdef _CDEV_DEBUG + printf ("the tag named %s is already in table: Error++++\n", ctag); +#endif + } +} + +// ***************************************************************************** +// * tagExists: +// * This function can be called to determine if a tag string has already +// * been added to the cdevTagTable. The value returned is a boolean +// * result that is TRUE (non-zero) if the tag exists or FALSE (0) if not. +// ***************************************************************************** +int cdevTagTable::tagExists ( char * ctag ) + { + int tag; + return !tagC2I(ctag, &tag); + } + + +// ***************************************************************************** +// * tagExists: +// * This function can be called to determine if a tag integer has already +// * been added to the cdevTagTable. The value returned is a boolean +// * result that is TRUE (non-zero) if the tag exists or FALSE (0) if not. +// ***************************************************************************** +int cdevTagTable::tagExists ( int tag ) + { + char * ctag; + return !tagI2C(tag, ctag); + } + +// ***************************************************************************** +// * addTag : +// * This method will add the tag string to the cdevTagTable if it +// * does not already exist. Tag Table will start searching for the +// * next available tag number above 1000. The value returned by the +// * function will be the integer that is assigned to the character string +// * tag. +// ***************************************************************************** +int cdevTagTable::addTag ( char * ctag ) + { + int tag; + char *ptr; + + if(tagC2I(ctag, &tag)!=CDEV_SUCCESS) + { + tag = highestTag; + while(tagI2C(tag, ptr)==CDEV_SUCCESS) tag++; + insertTag(tag, ctag); + highestTag = tag+1; + } + return tag; + } + + +// ***************************************************************************** +// * addTagCallback : +// * This method will add a cdevTagTableCallback object to the list of +// * classes that should be notified each time a tag is added to the +// * cdevTagTable. +// ***************************************************************************** +void cdevTagTable::addTagCallback ( cdevTagTableCallback * cb ) + { + if(cb!=NULL) + { + cb->next_ = callbacks_; + callbacks_ = cb; + } + } + +// ***************************************************************************** +// * delTagCallback : +// * This method will remote a cdevTagTableCallback object that was +// * previously added to the list of callback classes. +// * +// * Note: This method does not actually delete the cdevTagTableCallback +// * object, it merely removes it from the list. It is the +// * responsibility of the owner to delete the object when it is +// * no longer needed. +// ***************************************************************************** +void cdevTagTable::delTagCallback ( cdevTagTableCallback * cb ) + { + cdevTagTableCallback *prev = NULL, *ptr = callbacks_; + + while(ptr!=cb && ptr!=NULL) + { + prev = ptr; + ptr = ptr->next_; + } + + if(ptr!=NULL) + { + if(prev!=NULL) prev->next_ = ptr->next_; + else callbacks_ = ptr->next_; + } + } + +// ***************************************************************************** +// * readTagTable : +// * This method allows the caller to obtain a list of tag names and +// * integers that are currently stored in this tag table. +// * +// * Note: This method will allocate an array of integers and an array of +// * character string pointers. The strings that are stored in the +// * string array will be the actual strings from within the +// * tag table and should not be deleted... +// * +// * The data allocated becomes the property of the caller and must +// * be deleted when it is no longer needed... the correct syntax to +// * delete these items is... +// * +// * delete tags; +// * delete ctags; +// * +// * This will delete the array, however, it will leave the +// * individual array elements intact. +// ***************************************************************************** +int cdevTagTable::readTagTable ( int * &tags, char ** &ctags, int &ntags ) + { + cdevTagEle * element; + cdevIntHashIterator iter(itagList_); + int cnt = 0; + + ntags = 0; + tags = NULL; + ctags = NULL; + + iter.init(); + while(iter.getData()!=NULL) + { + ++cnt; + ++iter; + } + if(cnt) { + tags = new int [cnt]; + ctags = new char *[cnt]; + + iter.init(); + while((element=(cdevTagEle *)iter.getData())!=NULL && ntagstagId; + ctags[ntags] = element->tagName; + ++ntags; + ++iter; + } + } + return !ntags; + } + +void +cdevTagTable::asciiDump (FILE* fp) +{ + char** tagnames; + int* tagvalues; + int numtags = 0; + + readTagTable (tagvalues, tagnames, numtags); + + for (int i = 0; i < numtags; i++) + fprintf (fp, "%d %s\n", tagvalues[i], tagnames[i]); + + delete []tagvalues; + delete []tagnames; +} + +int +cdevTagTable::parseTagTable (char* file, + char** &tags, + int* &tagvalues, + unsigned int &numTags) +{ + FILE *fd = ::fopen (file, "r"); + + if (!fd) { + return 0; + } + + numTags = 0; + char buffer[128], tag[80]; + int tagval = 0; + + // first check how many tags: not efficient, but how many tags we are talking about + while (!feof (fd)) { + ::fgets (buffer, sizeof (buffer), fd); + if (::sscanf (buffer, "%d %s", &tagval, tag) == 2) + numTags ++; + } + ::fseek (fd, 0L, SEEK_SET); // reset to the begining of the file + + if (numTags == 0) { + ::fclose (fd); + return 0; + } + + // allocate space for tag/tagvalue array + tags = new char*[numTags]; + tagvalues = new int[numTags]; + + unsigned int i = 0; + while (!feof (fd)) { + ::fgets (buffer, sizeof (buffer), fd); + if (::sscanf (buffer, "%d %s", &tagval, tag) == 2) { + tags[i] = new char[::strlen (tag) + 1]; + ::strcpy (tags[i], tag); + tagvalues[i++] = tagval; + } + } + assert (i == numTags); + + ::fclose (fd); + return 1; +} diff --git a/src/cdevIO/cdevTagTable.h b/src/cdevIO/cdevTagTable.h new file mode 100755 index 0000000..c8c2de5 --- /dev/null +++ b/src/cdevIO/cdevTagTable.h @@ -0,0 +1,191 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//------------------------------------------------------------------------------ +// +// description: cdevTagTable.h +// cdevTagTable class manages tags within the cdev system. +// +// Author: Danjin Wu & Walt Akers +// +// Revision History: +// cdevTagTable.h,v +// Revision 1.12 1997/08/01 19:06:30 akers +// Added addTag and tagExists feature to the library +// +// Revision 1.11 1996/10/25 20:10:02 chen +// add asciiDump +// +// Revision 1.10 1996/08/26 19:14:07 akers +// Adding cdevData.inserttag callback capabilities +// +// Revision 1.9 1996/07/17 13:57:56 chen +// using CDEVTAGTABLE to find tags +// +// Revision 1.8 1995/10/03 19:37:11 chen +// Change back to object instead of pointers +// +// Revision 1.7 1995/09/29 15:25:55 danjin +// declare hash entry as pointer +// +// Revision 1.6 1995/09/28 19:01:48 danjin +// change: declare a ptr to list -> declare a list +// +// Revision 1.5 1995/08/21 18:02:48 danjin +// empty message +// +// Revision 1.3 1995/08/21 16:40:23 danjin +// modify comment +// +// Revision 1.2 1995/08/21 16:38:10 danjin +// modified big partion of this file +// +// Revision 1.1 1995/08/21 15:47:24 danjin +// merge Slist and hash into one for cdev +// +// +// +#ifndef _CDEV_TAG_TABLE_H +#define _CDEV_TAG_TABLE_H + +#include +#include +#include +#include + + +// ***************************************************************************** +// * class cdevTagTableCallback : +// * This class is used by the caller to post a callback to be notified +// * when changes are posted to a cdevTagTable. The class also has +// * a next pointer to allow it to be placed in a linked list within the +// * cdevTagTable... +// * +// * Note: Since this is a abstract base class, the caller must create a +// * class based on this class that has the callback method defined... +// * Also the destructor here is defined as virtual to force the delete +// * mechanism to work its way up the class hierarchy to the top level +// * before calling the destructor... +// ***************************************************************************** +class CDEV_CLASS_SPEC cdevTagTableCallback +{ +friend class cdevTagTable; +private: + cdevTagTableCallback *next_; +public: + cdevTagTableCallback ( void ) : next_(NULL) {} + virtual ~cdevTagTableCallback (void) {} + virtual void callback (int newTag, char *newName) = 0; +}; + + +struct cdevTagEle { + char *tagName; + int tagId; +}; +typedef struct cdevTagEle cdevTagEle; + +class CDEV_CLASS_SPEC cdevTagTable +{ +public: + cdevTagTable ( void ); + + ~cdevTagTable ( void ) + { + freeMemory (); +#ifdef _CDEV_DEBUG + printf("Destroying a cdevTagTable object\n"); +#endif + } + + int tagC2I (char* ctag, int* tag); + int tagI2C (int tag, char* &ctag); + void insertTag (int tag, char* ctag); + int tagExists (char *ctag); + int tagExists (int tag); + int addTag (char *ctag); + + // ************************************************* + // * addTagCallback : + // * This method will add a cdevTagTableCallback + // * object to the list of classes that should be + // * notified each time a tag is added to the + // * cdevTagTable. + // ************************************************* + void addTagCallback ( cdevTagTableCallback * cb ); + + // ************************************************* + // * delTagCallback : + // * This method will remote a cdevTagTableCallback + // * object that was previously added to the list + // * of callback classes. + // * + // * Note: This method does not actually delete + // * the cdevTagTableCallback object, it + // * merely removes it from the list. It + // * is the responsibility of the owner to + // * delete the object when it is no longer + // * needed. + // ************************************************* + void delTagCallback ( cdevTagTableCallback * cb ); + + // ************************************************* + // * readTagTable : + // * This method allows the caller to obtain a list + // * of tag names and integers that are currently + // * stored in this tag table. + // * + // * Note: This method will allocate an array of + // * integers and an array of character + // * string pointers. The strings that + // * are stored in the string array will be + // * the actual strings from within the + // * tag table and should not be deleted... + // * + // * The data allocated becomes the property + // * of the caller and must be deleted when + // * it is no longer needed... the correct + // * syntax to delete these items is... + // * + // * delete tags; + // * delete ctags; + // * + // * This will delete the array, however, + // * it will leave the individual array + // * elements intact. + // ************************************************* + int readTagTable ( int * &tags, char ** &ctags, int &ntags ); + + // ************************************************* + // * asciiDump (FILE* fp = stdout); + // * dump information of tag table to a file with two columns + // * left column is tag value, right column is tag string + // ************************************************* + void asciiDump (FILE* fp = stdout); + +protected: + void freeMemory (void); + void initialize ( void ); + // data area + cdevIntHash itagList_; + cdevStrHash stagList_; + cdevTagTableCallback * callbacks_; + int highestTag; + +private: + // default tag name if there is no tag file + static char* defaultTags[]; + static unsigned int numberDefTags; + static char* defaultTagTableLocation; + static char* tagTableEnv; + + // parse tag table file, return 0: failure, return 1: success + // caller free all memory upon success + static int parseTagTable (char* file, char** &tags, int* &tagvalues, + unsigned int &numTags); +}; +#endif /* _CDEV_TAG_TABLE_H */ + diff --git a/src/cdevIO/cdevTypes.h b/src/cdevIO/cdevTypes.h new file mode 100755 index 0000000..2a675cd --- /dev/null +++ b/src/cdevIO/cdevTypes.h @@ -0,0 +1,65 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 1991,1992 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + *---------------------------------------------------------------------------- + * + * description: cdevDataEntry.h + * Self describing data class. Designed to hold individual tagged data + * items within a cdevData class. + * + * Author: Walt Akers & Danjin Wu + * + * Revision History: + * cdevTypes.h,v + * Revision 1.5 1998/03/10 19:57:39 chen + * change to C style comment + * + * Revision 1.4 1998/03/10 18:54:27 chen + * cdevTypes.h + * + * Revision 1.3 1995/09/06 18:35:11 danjin + * added time stamp structure type + * + * Revision 1.2 1995/07/14 13:25:32 akers + * Header files added to support the changes specified at June 95 Review + * + * + * + */ +#ifndef _CDEV_TYPES_H +#define _CDEV_TYPES_H + +#include + +typedef unsigned char BYTE; + +enum cdevDataTypes + { + CDEV_BYTE, + CDEV_INT16, + CDEV_UINT16, + CDEV_INT32, + CDEV_UINT32, + CDEV_FLOAT, + CDEV_DOUBLE, + CDEV_STRING, + CDEV_TIMESTAMP, + CDEV_INVALID + }; + +typedef struct + { + size_t offset; + size_t length; + } cdevBounds; + +/* cdev time struct */ +typedef struct { + unsigned long secPastEpoch; /* seconds since Jan. 1, 1970 */ + unsigned long nsec; /* nanoseconds within second */ +} cdev_TS_STAMP; + +#endif diff --git a/src/cdevIO/xdrClass.h b/src/cdevIO/xdrClass.h new file mode 100755 index 0000000..d24d1ed --- /dev/null +++ b/src/cdevIO/xdrClass.h @@ -0,0 +1,450 @@ +#ifndef _XDR_CLASS_H_ +#define _XDR_CLASS_H_ + +#include +#include +#include +#if defined (ultrix) || defined (sgi) || defined (solaris) +#include +#endif + +// Under TGV Multinet and VMS, before you can #include rpc/xdr.h (below), +// rpc/types.h must be included, so that bool_t is defined and sys/types.h is +// #included. +// +// Under TGV Multinet and VMS, if you want sys/types.h, you need to have +// types.h already pulled in because sys/types.h makes it look like types.h +// is loaded. Then when types.h does get loaded, it is ignored because it +// looks like it is already loaded. +// +// rpc/types.h defines bool_t, required by rpc/xdr.h +// rpc/types.h #includes sys/types.h +// sys/types.h defines caddr_t, required by rpc/xdr.h and +// defines u_int,u_short required by netinet/in.h +// --Mr. Daniel Van Olst at SLAC vanolst@slc.slac.stanford.edu + +#ifdef __VMS +#ifdef _TGV_MULTINET +#include +#include +#include +#include +#endif +#include +#endif + +#ifdef _WIN32 +#include "xdr.h" +#else +#include +#include +#endif +#include + +static bool_t xdr_timestamp( XDR * xdrs, cdev_TS_STAMP * ts) { + if ( xdr_u_long (xdrs, &ts->secPastEpoch) == 0) return 0; + return (xdr_u_long (xdrs, &ts->nsec)); +} + +// ***************************************************************************** +// * XDR_Size_of : +// * Functions used to determine the size of a data element once translated +// * and placed into an XDR stream. +// ***************************************************************************** +#if !defined( NO_TEMPLATES ) + template inline unsigned XDR_Sizeof( T t ) { + return (RNDUP(sizeof(t))); } +#else + inline unsigned XDR_Sizeof(char x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(unsigned char x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(short x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(unsigned short x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(int x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(unsigned int x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(long x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(unsigned long x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(float x) { return (RNDUP(sizeof(x))); } + inline unsigned XDR_Sizeof(double x) { return (RNDUP(sizeof(x))); } + +#endif + +inline unsigned XDR_Sizeof( char * s ) { + return (RNDUP(strlen(s)) + BYTES_PER_XDR_UNIT); } + +inline unsigned XDR_Sizeof( char *, unsigned len ) { + return (RNDUP(len) + BYTES_PER_XDR_UNIT); } + +inline unsigned XDR_Sizeof( void *, unsigned len ) { + return (RNDUP(len) + BYTES_PER_XDR_UNIT); } + +inline unsigned XDR_Sizeof( cdev_TS_STAMP ts ) { + return (RNDUP(sizeof(ts))); } + +typedef struct + { + unsigned bufLen; + char * buf; + } XDR_DataBlock; + + +// ***************************************************************************** +// * This is the XDR_Data class. It allows the user to pass the data associated +// * with the XDR_Writer and XDR_Reader classes in a format that is not +// * restricted to XDR read or XDR write. +// ***************************************************************************** +class XDR_Data : public XDR_DataBlock + { + public: + XDR_Data ( void ) + { buf = NULL; bufLen = 0; } + + XDR_Data ( char * Buf, unsigned Len ) + { buf = NULL; bufLen = 0; assign(Buf, Len); } + + XDR_Data ( XDR_Data & x ) + { buf = NULL; bufLen = 0; assign(x.buf, x.bufLen); } + + ~XDR_Data ( void ) { deallocate(); } + unsigned & size ( void ) { return bufLen; } + char * & buffer ( void ) { return buf; } + int ready ( void ) { return (buf!=NULL && bufLen>0)?1:0; } + + void allocate ( unsigned Len ) + { + if(Len==0) XDR_Data::deallocate(); + else if(Len!=bufLen || buf==NULL) + { + XDR_Data::deallocate(); + bufLen = Len; + buf = new char[bufLen]; + XDR_Data::clear(); + } + else XDR_Data::clear(); + } + + void deallocate ( void ) + { + if(buf!=NULL) + { + delete buf; + buf = NULL; + } + bufLen = 0; + } + + void assign ( char * Buf, unsigned Len) + { + XDR_Data::allocate(Len); + memcpy(buf, Buf, bufLen); + } + + void clear ( void ) + { + memset(buf, 0, bufLen); + } + + void attachData ( XDR_Data & data ) + { + attachData(data.buf, data.bufLen); + } + + void attachData ( char * Buf, unsigned BufLen ) + { + XDR_Data::deallocate(); + buf = Buf; + bufLen = BufLen; + } + + void detachData ( void ) + { + buf = 0; + bufLen = 0; + } + }; + + +// ***************************************************************************** +// * This is the XDR_Base class. It provides the basic mechanism for generating +// * character streams that contain XDR data storage. +// ***************************************************************************** +class XDR_Base : public XDR_Data + { + protected: + XDR xdrs; + const enum xdr_op op; + + XDR_Base (enum xdr_op xop ) : XDR_Data(), op(xop) {} + XDR_Base (XDR_Data & xdrData, enum xdr_op xop) : op(xop) + { + allocate(xdrData.size()); + memcpy(buf, xdrData.buffer(), xdrData.size()); + xdr_setpos(xdr(), 0); + } + ~XDR_Base ( void ) { deallocate(); } + + public: + XDR * xdr ( void ) { return &xdrs; } + unsigned position ( void ) { return ready()?xdr_getpos(&xdrs):0L; } + + void allocate ( unsigned Len) + { + if(Len==0) XDR_Base::deallocate(); + else if(Len!=bufLen || buf==NULL) + { + XDR_Base::deallocate(); + XDR_Data::allocate(Len); + xdrmem_create(&xdrs, buf, bufLen, op); + } + else XDR_Data::clear(); + } + + void deallocate ( void ) + { + if(ready()) + { + xdr_destroy(&xdrs); + XDR_Data::deallocate(); + } + } + + void clear ( void ) + { + if(ready()) + { + XDR_Data::clear(); + xdr_setpos(&xdrs, 0); + } + } + + void attachData ( XDR_Data & data ) + { + XDR_Base::attachData(data.buf, data.bufLen); + } + + void attachData ( char * Buf, unsigned BufLen ) + { + XDR_Base::deallocate(); + XDR_Data::attachData(Buf, BufLen); + xdrmem_create(&xdrs, buf, bufLen, op); + } + + void detachData ( void ) + { + XDR_Data::detachData(); + XDR_Base::deallocate(); + } + }; + + + +// ***************************************************************************** +// * This is the XDR_Writer class. It provides the mechanisms for creating and +// * managing an outgoing stream of XDR data. +// ***************************************************************************** +class XDR_Writer : public XDR_Base + { + public: + XDR_Writer (unsigned len = 0) : XDR_Base(XDR_ENCODE) { XDR_Base::allocate(len); } + XDR_Writer (XDR_Data & xdrData ) : XDR_Base(xdrData, XDR_ENCODE) {} + + int put_char ( char x ) + { return ready()?xdr_char(&xdrs, &x):0; } + + int put_u_char ( unsigned char x ) +#ifndef sunos4 + { return ready()?xdr_u_char(&xdrs, &x):0; } +#else + { return ready()?xdr_u_char(&xdrs, (char *)&x):0; } +#endif + + int put_int ( int x ) + { return ready()?xdr_int(&xdrs, &x):0; } + + int put_u_int ( unsigned int x ) + { return ready()?xdr_u_int(&xdrs, &x):0; } + + int put_short ( short x ) + { return ready()?xdr_short(&xdrs, &x):0; } + + int put_u_short( unsigned short x ) + { return ready()?xdr_u_short(&xdrs, &x):0; } + + int put_long ( long x ) + { return ready()?xdr_long(&xdrs, &x):0; } + + int put_u_long ( unsigned long x ) + { return ready()?xdr_u_long(&xdrs, &x):0; } + + int put_float ( float x ) + { return ready()?xdr_float(&xdrs, &x):0; } + + int put_double ( double x ) + { return ready()?xdr_double(&xdrs, &x):0; } + + int put_bytes ( char ** bytes, unsigned int num ) + { return ready()? + xdr_bytes(&xdrs, bytes, &num, size()-position()): + 0; } + + int put_string ( char * str ) + { return ready()? + xdr_string(&xdrs, &str, size()-position()): + 0; } + + int put_opaque ( void * data, unsigned len ) + { int status = 0; + if(ready()) + { + status=xdr_u_int (&xdrs, &len); + if(status) status=xdr_opaque(&xdrs, (char *)data, len); + } + return status; + } + + int put_timestamp ( cdev_TS_STAMP ts ) + { return ready()?xdr_timestamp(&xdrs, &ts):0; } + + int put ( char x ) { return put_char(x); } + int put ( unsigned char x ) { return put_u_char(x); } + int put ( int x ) { return put_int(x); } + int put ( unsigned int x ) { return put_u_int(x); } + int put ( short x ) { return put_short(x); } + int put ( unsigned short x ) { return put_u_short(x); } + int put ( long x ) { return put_long(x); } + int put ( unsigned long x ) { return put_u_long(x); } + int put ( float x ) { return put_float(x); } + int put ( double x ) { return put_double(x); } + int put ( char * str ) { return put_string(str); } + int put ( void * x, unsigned len ) { return put_opaque(x, len); } + int put ( cdev_TS_STAMP ts ) { return put_timestamp(ts); } + }; + + +// ***************************************************************************** +// * This is the XDR_Reader class. It provides the mechanisms for creating and +// * managing an incoming stream of XDR data. +// ***************************************************************************** +class XDR_Reader : public XDR_Base + { + public: + XDR_Reader (unsigned len = 0) : XDR_Base(XDR_DECODE) { XDR_Base::allocate(len); } + XDR_Reader (XDR_Data & xdrData ) : XDR_Base(xdrData, XDR_DECODE) {} + + int get_char ( char & x ) + { return ready()?xdr_char(&xdrs, &x):0; } + + int get_u_char ( unsigned char & x ) +#ifndef sunos4 + { return ready()?xdr_u_char(&xdrs, &x):0; } +#else + { return ready()?xdr_u_char(&xdrs, (char *)&x):0; } +#endif + + int get_int ( int & x ) + { return ready()?xdr_int(&xdrs, &x):0; } + + int get_u_int ( unsigned int & x ) + { return ready()?xdr_u_int(&xdrs, &x):0; } + + int get_short ( short & x ) + { return ready()?xdr_short(&xdrs, &x):0; } + + int get_u_short ( unsigned short & x ) + { return ready()?xdr_u_short(&xdrs, &x):0; } + + int get_long ( long & x ) + { return ready()?xdr_long(&xdrs, &x):0; } + + int get_u_long ( unsigned long & x ) + { return ready()?xdr_u_long(&xdrs, &x):0; } + + int get_float ( float & x ) + { return ready()?xdr_float(&xdrs, &x):0; } + + int get_double ( double & x ) + { return ready()?xdr_double(&xdrs, &x):0; } + + int get_bytes ( char ** bytes, unsigned int & num, unsigned int max ) + { return ready()?xdr_bytes(&xdrs, bytes, &num, max):0; } + + int get_string_len ( void ) + { return ready()?ntohl(*(long *)((char *)buf+xdr_getpos(&xdrs))):0; } + + int get_string ( char ** str, unsigned int max = -1U ) + { + int result = 0; + int slen = get_string_len()+1; + char * s = new char[slen]; + if(ready()) + { + result = xdr_string(&xdrs, &s, slen); + if(str!=NULL) + { + if(max==-1U || *str==NULL) + { + *str = s; + s = NULL; + } + else + { + strncpy(*str, s, max); + str[max-1] = 0; + } + } + } + if(s!=NULL) delete s; + return result; + } + + int get_opaque ( void ** data, unsigned int * len, unsigned int max = -1U) + { + int result = 0; + + if(ready()) + { + unsigned int slen; + char * s; + + if((result=xdr_u_int(&xdrs, &slen))!=0) + { + s = new char[slen]; + result=xdr_opaque(&xdrs, s, slen); + } + if(result!=0) + { + if(*data==NULL || max==-1U) + { + *len = slen; + *data = s; + s = NULL; + } + else { + *len = (slen nul + +copyincs : + -@for %x in (*.h *.i) DO @copy %x $(CDEV)\include > nul + diff --git a/src/collection/cdevCollection.cc b/src/collection/cdevCollection.cc new file mode 100755 index 0000000..2f54b39 --- /dev/null +++ b/src/collection/cdevCollection.cc @@ -0,0 +1,365 @@ +/* + * ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * Description: + * cdevCollection class implementation + * + * Author: Walt Akers, Chip Watson & Jie Chen + * + * Revision History: + * cdevCollection.cc,v +// Revision 1.2 1996/11/21 16:54:57 akers +// Ongoing development +// + * Revision 1.1 1996/11/12 20:32:10 akers + * New collection device source code + * + * ----------------------------------------------------------------------------- + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "cdevCollection.h" + +// Construct a pre-existing or an empty collection +// Never called unless device known not to exist in this system +// AND known to not be a simple device (i.e. no name conflicts) +cdevCollection::cdevCollection(char *devName, cdevSystem &sys) +:cdevDevice(devName, sys), nameList_() + { + #ifdef _TRACE_OBJECTS + printf(" Create cdevCollection class object\n"); + #endif + cdevData data, result; + data.insert("device", devName); + int status=(sys.nameServer()).send("queryCollection", data, result); + if(status == CDEV_SUCCESS) + { + // must be pre-defined collection + size_t num=0; + if(result.getElems("value", &num) == CDEV_SUCCESS) + { + if(num > 0) + { + char * name[2]; + char **names; + if(num==1) + { + names = name; + names[1] = NULL; + result.find("value", (void * &)name[0]); + } + else result.find("value", (void* &)names); + status=add(num, names); + // add names + } + } + } + } + +cdevCollection::~cdevCollection(void) + { + #ifdef _TRACE_OBJECTS + printf(" Destroy cdevCollection class object\n"); + #endif + // remove names + cdevSlistIterator nlit(nameList_); + char *name; + for(nlit.init(); !nlit; ++nlit) + { + name=(char *) nlit(); + delete[]name; + } + } + +cdevCollection &cdevCollection::attachRef(char *name) + { + return cdevCollection::attachRef(name, cdevSystem::defaultSystem()); + } + +cdevCollection *cdevCollection::attachPtr(char *name) + { + return cdevCollection::attachPtr(name, cdevSystem::defaultSystem()); + } + +cdevCollection &cdevCollection::attachRef(char *name, cdevSystem &system) + { + cdevCollection *col=cdevCollection::attachPtr(name, system); + if(col == NULL) return *(new cdevErrorCollection(name)); + return *col; + } + +cdevCollection *cdevCollection::attachPtr(char *name, cdevSystem &system) + { + cdevDevice *dev=0; + cdevCollection *col=0; + cdevService *service=0; + + if(system.deviceCreated(name)) + { + // device exists in this system + dev=system.device(name); + if(::strcmp(dev->className(), "cdevCollection") != 0) + return NULL; + // if it is not a collection, error + col=(cdevCollection *) dev; + col->refCount_++; + } + else + { + cdevData data, result; + data.insert("device", name); + int status=(system.nameServer()).send("queryClass", data, result); + if(status == CDEV_SUCCESS) + { + // device is defined in directory + char *name; + result.find("value", (void* &) name); + if(::strcmp(name, "collection") != 0) + // if it is not a collection, error + return NULL; + } + col=new cdevCollection(name, system); + } + return col; + } + +void +cdevCollection::detach(cdevCollection &dev) + { + cdevCollection::detach(&dev); + } + +void +cdevCollection::detach(cdevCollection *dev) + { + if(--dev->refCount_ <= 0) + // no more reference attached + delete dev; + } + +cdevRequestObject *cdevCollection::getRequestObject(char *msg) + { + cdevRequestObject *obj=NULL; + getRequestObject(msg, obj); + return obj; + } + +int +cdevCollection::getRequestObject(char *msg, cdevRequestObject* &reqobj) + { + reqobj=findRequestObject(msg); + if(reqobj == NULL) + reqobj=cdevCollectionRequest::attachPtr(*this, msg, system_); + return (reqobj==NULL)?CDEV_ERROR:CDEV_SUCCESS; + } + +char **cdevCollection::getList() + { + int num=nameList_.count(); + char **list=new char*[num+1]; + char **listStart=list; + cdevSlistIterator nlit(nameList_); + + // *********************************************** + // * Note this method reverses the order of the + // * strings as it extracts them from the + // * list. + // *********************************************** + list[num]=NULL; + for(nlit.init(); !nlit && num > 0; ++nlit) + { + num--; + list[num]=(char *) nlit(); + } + return listStart; + } + +int +cdevCollection::add(char *name) + { + if(reqObjList_.isEmpty() == 0) return CDEV_INVALIDOP; + if(name == 0 || name[0] == '\0') return CDEV_INVALIDOP; + cdevSlistIterator nlit(nameList_); + char *test; + for(nlit.init(); !nlit; ++nlit) + { + test=(char *) nlit(); + if(::strcmp(test, name) == 0) + return CDEV_WARNING; + } + char *newname=strdup(name); + nameList_.add((void *) newname); + return CDEV_SUCCESS; + } + +int +cdevCollection::add(int num, char *firstname, ...) + { + if(reqObjList_.isEmpty() == 0) return CDEV_INVALIDOP; + char *device; + int status, tmpstatus; + va_list argp; + va_start(argp, firstname); + + status=CDEV_SUCCESS; + if(firstname) status=add(firstname); + while(--num > 0) + { + device=va_arg(argp, char *); + if(device) tmpstatus=add(device); + if(status == CDEV_SUCCESS) status=tmpstatus; + } + va_end(argp); + return status; + } + +int +cdevCollection::add(int num, char **names) + { + if(reqObjList_.isEmpty() == 0) return CDEV_INVALIDOP; + int status, tmpstatus; + status=CDEV_SUCCESS; + while(num-->0) + { + tmpstatus=add(*(names++)); + if(status == CDEV_SUCCESS) status=tmpstatus; + } + return status; + } + +int +cdevCollection::add(char **names) + { + if(reqObjList_.isEmpty() == 0) return CDEV_INVALIDOP; + if(names == 0) return CDEV_INVALIDOP; + int status, tmpstatus; + status=CDEV_SUCCESS; + while(*names) + { + tmpstatus=add(*(names++)); + if(status == CDEV_SUCCESS) status=tmpstatus; + } + return status; + } + +int +cdevCollection::addRegexp(char *regexp) + { + if(reqObjList_.isEmpty() == 0) return CDEV_INVALIDOP; + cdevData data, result; + data.insert("device", regexp); + int status=(system_.nameServer()).send("query", data, result); + if(status == CDEV_SUCCESS) + { + size_t num; + char **names; + result.getElems("value", &num); + result.find("value", (void* &) names); + status=add(num, names); + } + return status; + } + +int +cdevCollection::remove(char *name) + { + if(reqObjList_.isEmpty() == 0) return CDEV_INVALIDOP; + if(name == 0 || name[0] == '\0') return CDEV_WARNING; + cdevSlistIterator nlit(nameList_); + char *test; + for(nlit.init(); !nlit; ++nlit) + { + test=(char *) nlit(); + if(::strcmp(test, name) == 0) + { + nameList_.remove((void *) test); + return CDEV_SUCCESS; + } + } + return CDEV_WARNING; + } + +int +cdevCollection::remove(int num, char *name, ...) + { + if(reqObjList_.isEmpty() == 0) return CDEV_INVALIDOP; + char *device; + int status, tmpstatus; + va_list argp; + va_start(argp, name); + + status=CDEV_SUCCESS; + if(name) status=remove(name); + while(--num > 0) + { + device=va_arg(argp, char *); + if(device) tmpstatus=remove(device); + if(status == CDEV_SUCCESS) status=tmpstatus; + } + va_end(argp); + return status; + } + +int +cdevCollection::remove(int num, char **names) + { + int status, tmpstatus; + if(reqObjList_.isEmpty() == 0) return CDEV_INVALIDOP; + if(names == 0) return CDEV_INVALIDOP; + status=CDEV_SUCCESS; + while(num-->0) + { + tmpstatus=remove(*(names++)); + if(status == CDEV_SUCCESS) status=tmpstatus; + } + return status; + } + +int +cdevCollection::remove(char **names) + { + int status, tmpstatus; + if(reqObjList_.isEmpty() == 0) return CDEV_INVALIDOP; + if(names == 0) return CDEV_INVALIDOP; + status=CDEV_SUCCESS; + while(*names) + { + tmpstatus=remove(*(names++)); + if(status == CDEV_SUCCESS) status=tmpstatus; + } + return status; + } + +int +cdevCollection::removeRegexp(char *regexp) + { + if(reqObjList_.isEmpty() == 0) return CDEV_INVALIDOP; + cdevData data, result; + data.insert("device", regexp); + int status=(system_.nameServer()).send("query", data, result); + if(status == CDEV_SUCCESS) + { + size_t num; + result.getElems("value", &num); + char **names; + result.find("value", (void* &) names); + status=remove(num, names); + } + return status; + } diff --git a/src/collection/cdevCollection.h b/src/collection/cdevCollection.h new file mode 100755 index 0000000..79c4258 --- /dev/null +++ b/src/collection/cdevCollection.h @@ -0,0 +1,135 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * Description: + * cdevCollection class implementation + * + * Author: Walt Akers, Chip Watson & Jie Chen + * + * Revision History: + * cdevCollection.h,v + * Revision 1.3 1998/08/03 16:24:25 chen + * AIX porting + * + * Revision 1.2 1997/12/12 16:35:43 chen + * add VMS fix + * + * Revision 1.1 1996/11/12 20:32:11 akers + * New collection device source code + * + * ----------------------------------------------------------------------------- + */ + +#ifndef _CDEV_COLLECTION_H +#define _CDEV_COLLECTION_H + +#include +#include + +#if defined(__VMS) || defined (AIX) +typedef char* va_list; +#undef va_start +#define va_start(ap,v) ((void)((ap)=(char*)(&v + 1))) +#undef va_arg +#define va_arg(ap,type) (((type *)((ap)+=sizeof(type)))[-1]) +#undef va_end +#define va_end(ap) ((void)0) +#endif + +class cdevCollectionRequest; + +class CDEV_CLASS_SPEC cdevCollection: public cdevDevice +{ + friend class cdevDevice; + + public: + //=================================================================== + // Public Interface for Clients + //=================================================================== + static cdevCollection& attachRef (char *name); + static cdevCollection* attachPtr (char *name); + // PURPOSE: create a reference or pointer for device of a given name + // within the default system + // REQUIRE: name != 0 + // PROMISE: a cdevCollection + + static void detach (cdevCollection& dev); + static void detach (cdevCollection* dev); + // PURPOSE: destroy a cdevCollection + // REQUIRE: dev != 0 + // PROMISE: memory will be freed if no more attachment on this device + + //======================================================================== + // Public Interface for cdevRequestObject + //======================================================================== + virtual cdevRequestObject *getRequestObject (char * msg ); + virtual int getRequestObject (char *msg, cdevRequestObject* &reqobj); + // PURPOSE: get right requestObject based on its name + // REQUIRE: name != 0, callers provide pointer only. + // PROMISE: always return CDEV_SUCCESS. reqobj may be an errorRequestObject + + //======================================================================== + // Public Interface for RTTI + //======================================================================== + virtual const char *className (void) const {return "cdevCollection";} + + //======================================================================== + // Public Interface for list manipulation + //======================================================================== + char ** getList(); + // PURPOSE: obtain a null terminated array of device names + // REQUIRE: caller is responsible for freeing list + // PROMISE: if collection is empty, returns NULL + + int add(char* name); // add a single device + int add(int num, char* name, ...); // add multiple devices + int add(int num, char** names); // add array of names of length num + int add(char** names); // add a null terminated array of names + int addRegexp(char* regexp); // add by regular expression + int remove(char* name); + int remove(int num, char* name, ...); + int remove(int num, char** names); + int remove(char** names); // remove a null terminated array of names + int removeRegexp(char* regexp); + // PURPOSE: add(remove) a (list of/regexp of) names to the collection + // REQUIRE: nothing + // PROMISE: merged list will have no duplicates + // return CDEV_SUCCESS: no duplicates/missing found, CDEV_WARNING: + // at least one duplicate name was dropped during add or + // at least one name was not found during remove + + protected: + //constructors and destructor + cdevCollection (char *name, + cdevSystem& system = cdevSystem::defaultSystem() ); + virtual ~cdevCollection (void); + + // attach pointer or reference with system as second argument + static cdevCollection& attachRef (char *name, cdevSystem& system); + static cdevCollection* attachPtr (char *name, cdevSystem& system); + // PURPOSE: create a reference or pointer for device of a given name + // REQUIRE: name != 0 + // PROMISE: a cdevCollection + + private: + cdevSlist nameList_; + + // hide assignment and copy operator since the collection is + // a memory manager for collectionRequests and lists of devices + cdevCollection& operator = (const cdevCollection &); + cdevCollection (const cdevCollection &); + + // friend class declaration + friend class cdevCollectionRequest; +}; +#endif + + + + diff --git a/src/collection/cdevCollectionRequest.cc b/src/collection/cdevCollectionRequest.cc new file mode 100755 index 0000000..236e663 --- /dev/null +++ b/src/collection/cdevCollectionRequest.cc @@ -0,0 +1,200 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1995,1996 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * Description: + * Class implementing request objects for collections + * + * Author: Walt Akers + * + * Revision History: + * cdevCollectionRequest.cc,v +// Revision 1.2 1996/11/21 16:55:00 akers +// Ongoing development +// +// Revision 1.1 1996/11/12 20:32:14 akers +// New collection device source code +// + * ----------------------------------------------------------------------------- + */ + +#include +#include + +int cdevCollectionRequest::RESULT_CODE_TAG = 0; + +// ***************************************************************************** +// * cdevCollectionRequest::cdevCollectionRequest : +// * This is the constructor for this abstract base class. Because this +// * object has no internal data components the constructor is only required +// * to call the constructor for the underlying cdevRequestObject. +// * +// * It ensures that the resultCode tag has been added to the +// * cdevData GlobalTagTable. +// ***************************************************************************** +cdevCollectionRequest::cdevCollectionRequest + (char **, int, char *msg, cdevSystem &sys) + : cdevRequestObject("\0", msg, sys) + { + // ********************************************************************* + // * Install the RESULT_CODE_TAG at a location of 30 or higher if it + // * does not already exist. + // ********************************************************************* + if(cdevData::tagC2I("resultCode", &RESULT_CODE_TAG)!=CDEV_SUCCESS) + { + RESULT_CODE_TAG = 0; + for(int i=30; RESULT_CODE_TAG==0 && i<65534; i++) + { + cdevData::insertTag(i, "resultCode"); + cdevData::tagC2I("resultCode", &RESULT_CODE_TAG); + } + } + } + +// ***************************************************************************** +// * cdevCollectionRequest::~cdevCollectionRequest : +// * This is the virtual destructor for the class. It is a protected +// * placeholder that prevents the application from deleting a +// * cdevCollectionRequest directly. +// ***************************************************************************** +cdevCollectionRequest::~cdevCollectionRequest ( void ) + { + } + + +// ***************************************************************************** +// * cdevCollectionRequest::attachPtr : +// * This is the factory mechanism that is used by the cdevCollection +// * to generate a cdevCollectionRequest object. +// * +// * When called, it returns either a service-specific cdevCollectionRequest +// * object or a cdevGrpCollectionRequest object. +// ***************************************************************************** +cdevCollectionRequest * +cdevCollectionRequest::attachPtr(cdevCollection &dev, char *msg, cdevSystem & sys) + { + int serviceCount = 0; + char serviceName[255]; + cdevCollectionRequest * result = NULL; + + // ********************************************************************* + // * Get the list of device names that is associated with this + // * collection device. + // ********************************************************************* + int deviceNameCnt = 0; + char **deviceNames = dev.getList(); + char **deviceNamePtr = deviceNames; + + for(deviceNamePtr = deviceNames; *deviceNamePtr!=NULL; deviceNamePtr++) + { + deviceNameCnt++; + } + + // ********************************************************************* + // * Obtain a pointer to the cdevDirectory device. This will be used + // * to lookup the name of the service that is associated with each + // * device/message combination. + // ********************************************************************* + cdevDevice *dir = cdevDevice::attachPtr("cdevDirectory"); + + *serviceName = 0; + deviceNamePtr = deviceNames; + while(*deviceNamePtr!=NULL && serviceCount<2) + { + cdevData input, output; + + // ************************************************************ + // * Insert the name of the device and message to be resolved. + // ************************************************************ + input.insert("device", *deviceNamePtr); + input.insert("message", msg); + + // ************************************************************ + // Submit the request to the cdevDirectory object using the + // send command, and output the result if successful. + // ************************************************************ + if(dir->send("service", input, output)==CDEV_SUCCESS) + { + char * servicePtr; + output.find("value", (void * &)servicePtr); + if(servicePtr && *servicePtr) + { + if(*serviceName==0) + { + strcpy(serviceName, servicePtr); + serviceCount = 1; + } + else if(strcmp(serviceName, servicePtr)) + { + serviceCount++; + } + } + } + deviceNamePtr++; + } + // ********************************************************************* + // * If there is only one service involved in the cdevCollection, use + // * the service provided cdevCollectionRequest. + // ********************************************************************* + if(serviceCount==1) + { + cdevService * service = NULL; + if(!sys.serviceCreated(serviceName)) + { + sys.loadService(serviceName); + } + if((service = sys.service(serviceName))!=NULL) + { + // ***************************************************** + // * Get the cdevCollectionRequest directly from the + // * service... + // ***************************************************** + service->getCollectionRequest + (deviceNames, deviceNameCnt, msg, result); + + // ***************************************************** + // * Because this is a mono-service collection, the + // * service will be inserted into the request object. + // ***************************************************** + if(result) result->service(service); + } + } + // ********************************************************************* + // * If there is more than one service involved in the cdevCollection, + // * return a cdevGrpCollectionRequest object. + // ********************************************************************* + else if(serviceCount>1) + { + result = new cdevGrpCollectionRequest + (deviceNames, deviceNameCnt, msg, sys); + } + + // ********************************************************************* + // * If the result request object is not NULL, then register its name + // * with the cdevCollection that was used to create it. + // ********************************************************************* + if(result) + { + dev.registerReqObject(result); + result->device(&dev); + result->setContext(dev.getContext()); + } + else + { + sys.reportError(CDEV_SEVERITY_ERROR, + "cdevCollectionRequest", + NULL, + "Attempted operation on an empty collection" + ); + } + // ********************************************************************* + // * Delete the array of pointers, but not the pointers themselves. + // ********************************************************************* + delete deviceNames; + return result; + } diff --git a/src/collection/cdevCollectionRequest.h b/src/collection/cdevCollectionRequest.h new file mode 100755 index 0000000..737b144 --- /dev/null +++ b/src/collection/cdevCollectionRequest.h @@ -0,0 +1,69 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1995,1996 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * Description: + * Class implementing request objects for collections + * + * Author: Walt Akers + * + * Revision History: + * cdevCollectionRequest.h,v + * Revision 1.1 1996/11/12 20:32:18 akers + * New collection device source code + * + * ----------------------------------------------------------------------------- + */ +#ifndef _CDEV_COLLECTION_REQUEST_H +#define _CDEV_COLLECTION_REQUEST_H + +#include +#include +#include + +// ***************************************************************************** +// * cdevCollectionRequest: +// * This is the cdevCollectionRequest class. It is the master type for +// * all service derived cdevCollectionRequest objects. +// ***************************************************************************** +class CDEV_CLASS_SPEC cdevCollectionRequest: public cdevRequestObject +{ +friend class cdevCollection; +friend class cdevGrpCollectionRequest; + +public: + // ********************************************************************* + // * Returns the name of the class. + // ********************************************************************* + const char *className (void) const {return "cdevCollectionRequest";} + + // ********************************************************************* + // * Returns the RESULT_CODE_TAG identifier. + // ********************************************************************* + static int resultCodeTag(void) { return RESULT_CODE_TAG; } + +protected: + // ********************************************************************* + // * Constructor and destructor for the class. + // ********************************************************************* + cdevCollectionRequest (char **devices, int nDevices, char *msg, cdevSystem& sys); + virtual ~cdevCollectionRequest (void); + + // ********************************************************************* + // * Factory used to generate cdevCollectionRequest objects. + // ********************************************************************* + static cdevCollectionRequest * attachPtr(cdevCollection &device, char *msg, cdevSystem &system); + + // ********************************************************************* + // * This is the integer that wil be used to store the cdevData tag that + // * will contain the completion code. + // ********************************************************************* + static int RESULT_CODE_TAG; +}; + +#endif diff --git a/src/collection/cdevDefCollectionRequest.cc b/src/collection/cdevDefCollectionRequest.cc new file mode 100644 index 0000000..cf65260 --- /dev/null +++ b/src/collection/cdevDefCollectionRequest.cc @@ -0,0 +1,788 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * cdevDefCollectionRequest.h : This is the default class that will be used + * to support collection operations for services. + * + * Author: Walt Akers + * + * Revision History: + * cdevDefCollectionRequest.cc,v +// Revision 1.2 1998/10/22 17:57:33 chen +// fix a bug on setting collection values +// +// Revision 1.1 1996/11/12 20:32:23 akers +// New collection device source code +// + * ----------------------------------------------------------------------------- + */ + +#include +#include +#include + +int cdevDefCollectionRequest::sendCheckSum = 0; +cdevDefCollectionRequest::SendStatus cdevDefCollectionRequest::sendStatus; + +// ***************************************************************************** +// * cdevDefCollectionRequest::cdevDefCollectionRequest : +// * This is the constructor for the cdevDefCollectionRequest object. It +// * will initialize all of the internals for the class. +// ***************************************************************************** +cdevDefCollectionRequest::cdevDefCollectionRequest + (char **devices, int nDevices, char *msg, cdevSystem& sys) + : cdevCollectionRequest(devices, nDevices, msg, sys), + requests(NULL), + nRequests(nDevices), + format() + { + requests = new cdevRequestObject *[nDevices]; + for(int i=0; isetContext(ctx); + } + return cdevRequestObject::setContext(ctx); + } + +// ***************************************************************************** +// * getState: +// * This method allows the caller to obtain the combined state of the +// * collection of cdevRequestObjects that reside within this class. The +// * most restrictive state will be returned. +// * +// * Because the state definition variables proceeds from +// * CDEV_STATE_CONNECTED(0) to CDEV_STATE_INVALID(2), it can be assumed that +// * the higher a state result code is the more restrictive it is... +// * therefore, the highest state result code that is obtained from the +// * cdevRequestObjects will be returned to the caller. +// ***************************************************************************** +int cdevDefCollectionRequest::getState ( void ) + { + int state; + + if(nRequests==0) state = CDEV_STATE_INVALID; + else for(int i=0; igetState())>state) + { + state = tState; + } + } + return state; + } + +// ***************************************************************************** +// * getAccess: +// * This method allows the caller to obtain the combined access of the +// * collection of cdevRequestObjects that reside within this class. The +// * most restrictive access code will be returned. +// * +// * Because the access definition variables proceed from +// * CDEV_ACCESS_NONE(0) to CDEV_ACCESS_WRITE(2), it can be assumed that +// * the lower an access result code is the more restrictive it is... +// * therefore, the smallest access result code that is obtained from the +// * cdevRequestObjects will be returned to the caller. +// ***************************************************************************** +int cdevDefCollectionRequest::getAccess ( void ) + { + int accessCode; + + if(nRequests==0) accessCode = CDEV_ACCESS_NONE; + else for(int i=0; igetAccess())parent; + } + // ********************************************************************* + // * You'll note that this is a bone-jarring test to ensure that the + // * data that is provided is valid. + // ********************************************************************* + if(collector!=NULL && &collector->requests[request->index]==request) + { + collector->processRequest(request->index, status, &data); + + // ************************************************************* + // * Having processed this entry, I'll test to determine if all + // * of the members in this defCallbackCollector are finished - + // * if they are I'll dispatch the callback that was provided + // * earlier by the user and will delete the collector. + // ************************************************************* + if(collector->finished()) + { + (collector->xobj->userCallback_->callbackFunction()) + (CDEV_SUCCESS, + collector->xobj->userCallback_->userarg(), + *collector->xobj->reqObj_, + collector->result); + delete collector; + } + } + } + + +// ***************************************************************************** +// * send : +// * The send interface is used to provide synchronous I/O with the service. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int cdevDefCollectionRequest::send ( cdevData * in, cdevData * out ) + { + int status = CDEV_SUCCESS; + sendStatus.completionCode = 0; + sendStatus.finished = 0; + sendStatus.data = out; + + cdevCallback cb(syncCallback, (void *)sendCheckSum); + + if((status = sendCallback(in, cb))==CDEV_SUCCESS) + { + // ************************************************************* + // * I used to wait for a response here only if the outbound + // * cdevData object was non-null. However, that provided + // * unexpected behavior to the client. Now I wait whether + // * output data is expected or not. + // ************************************************************* + cdevTimeValue t(5.0); + cdevClock timer; + timer.schedule(NULL,t); + + do { + system_.poll(); + } while(!sendStatus.finished && !timer.expired()); + + if (!sendStatus.finished) + { + status = CDEV_ERROR; + system_.reportError( + CDEV_SEVERITY_ERROR, + "cdevCollectionRequest", + this, + "Services failed to respond after 5 seconds"); + } + else status = sendStatus.completionCode; + } + sendCheckSum++; + return status; + } + + +// ***************************************************************************** +// * cdevClientRequestObject::sendNoBlock : +// * This function allows the caller to submit an asynchronous message to the +// * server for processing. +// ***************************************************************************** +int cdevDefCollectionRequest::sendNoBlock (cdevData * in, cdevData * out) + { + cdevCallback cb(asyncNoBlockCallback, (void *)out); + return sendCallback(in, cb); + } + + +// ***************************************************************************** +// * sendCallback: +// * This method is used to submit a asynchronous call to the underlying +// * cdevRequestObjects. +// ***************************************************************************** +int cdevDefCollectionRequest::sendCallback (cdevData* in, cdevCallback& callback) + { + int failCount = 0; + int status = CDEV_SUCCESS; + cdevData* out = 0; + cdevTranObj *xobj = + new cdevTranObj(&system_, this, NULL, new cdevCallback(callback)); + defCallbackCollector *collector = + new defCallbackCollector(nRequests, format, *xobj); + + xobj->enableDeleteCbk(); + + // ******************************************************************** + // * first split incoming data to nRequest data + // * this may produce memory leaks: transaction object should has + // * an option to copy data pointer and delete it. -- Jie Chen 10/22/98 + // ******************************************************************** + if (in) + out = cdevDefCollectionRequest::splitData (*in, nRequests); + + + // ******************************************************************** + // * This loop will walk through each of the cdevRequestObjects that + // * are in the requests array and will call their sendCallback method. + // * + // * The callback that is passed to them will provide a pointer to the + // * specific entry in the requests array of the defCallbackCollector + // * object - this will be used to populate the proper entry in the + // * status attribute of the defCallbackCollector object. + // * + // * If the cdevRequestObject is NULL, or if the call fails - a + // * cdevError code will be placed in the statusCode tag of the status + // * data and failCount will be incremented. If all of the requests are + // * invalid or fail, then an error will be returned and the user + // * callback will not be executed. + // ********************************************************************* + for(int i=0; irequests[i])); + if(requests[i]!=NULL) { + if (!in) + status = requests[i]->sendCallback(in, cb); + else if (out) + status = requests[i]->sendCallback(&out[i], cb); + else + status = CDEV_CONVERT; + } + else status = CDEV_NOTFOUND; + if(status!=CDEV_SUCCESS) + { + collector->processRequest(i, status); + failCount++; + } + } + + // ********************************************************************* + // * Note: Due to memory leaks, we are going to delete the out array + // * of cdevData objects. In the event that the underlying cdevRequest + // * Object does not make a cpy of the cdevData object - then this will + // * most certainly cause a crash. Blame the service developer. + // ********************************************************************* + if (out) delete [] out; + + // ********************************************************************* + // * If all of the requests failed, then the collector object will be + // * deleted and an error will be returned... Note that when the + // * collector object is deleted, then the cdevTranObj that it contains + // * will also be deleted. + // ********************************************************************* + if (failCount>=nRequests) + { + status = CDEV_ERROR; + delete collector; + } + else status = CDEV_SUCCESS; + return status; + } + + +// ********************************************************************* +// * This is routine set scaler value to array of cdevData with a +// * specified tag +// ********************************************************************* +int +cdevDefCollectionRequest::setScalerDataValue (cdevData& data, int tag, + cdevData* res, int num) +{ + cdevDataTypes type; + int i, status; + + status = CDEV_SUCCESS; + + type = data.getType (tag); + switch (type) { + case CDEV_BYTE: + { + unsigned char val = 0; + if ((status = data.get (tag, &val)) == CDEV_SUCCESS) + for (i = 0; i < num; i++) + res[i].insert (tag, val); + } + break; + case CDEV_INT16: + { + short val = 0; + if ((status = data.get (tag, &val)) == CDEV_SUCCESS) + for (i = 0; i < num; i++) + res[i].insert (tag, val); + } + break; + case CDEV_UINT16: + { + unsigned short val = 0; + if ((status = data.get (tag, &val)) == CDEV_SUCCESS) + for (i = 0; i < num; i++) + res[i].insert (tag, val); + } + break; + case CDEV_INT32: + { + int val = 0; + if ((status = data.get (tag, &val)) == CDEV_SUCCESS) + for (i = 0; i < num; i++) + res[i].insert (tag, val); + } + break; + case CDEV_UINT32: + { + unsigned int val = 0; + if ((status = data.get (tag, &val)) == CDEV_SUCCESS) + for (i = 0; i < num; i++) + res[i].insert (tag, val); + } + break; + case CDEV_FLOAT: + { + float val = 0; + if ((status = data.get (tag, &val)) == CDEV_SUCCESS) + for (i = 0; i < num; i++) + res[i].insert (tag, val); + } + break; + case CDEV_DOUBLE: + { + double val = 0; + if ((status = data.get (tag, &val)) == CDEV_SUCCESS) + for (i = 0; i < num; i++) + res[i].insert (tag, val); + } + break; + case CDEV_STRING: + { + char val[1024]; + if ((status = data.get (tag, val, sizeof (val) - 1)) == CDEV_SUCCESS) + for (i = 0; i < num; i++) + res[i].insert (tag, val); + } + break; + case CDEV_TIMESTAMP: + { + cdev_TS_STAMP val; + if ((status = data.get (tag, &val)) == CDEV_SUCCESS) + for (i = 0; i < num; i++) + res[i].insert (tag, val); + } + break; + default: + status = CDEV_ERROR; + break; + } + return status; +} + +// ********************************************************************* +// * This is routine set vector value to array of cdevData with a +// * specified tag +// ********************************************************************* +int +cdevDefCollectionRequest::setVectorDataValue (cdevData& data, int tag, size_t dim, + cdevData* res, int num) +{ + int i = 0; + int j = 0; + int status = CDEV_SUCCESS; + cdevDataTypes type; + size_t elems, outelems; + cdevBounds* databounds; + cdevBounds* resbounds = 0; + + databounds = new cdevBounds[dim]; + + if (data.getElems (tag, &elems) != CDEV_SUCCESS) + return CDEV_ERROR; + + // Note: the last entry in the bounds information must be the same + // value as the num of data we want to generate + // We are only concerning about whole package of data. For incomplete + // data packet (i.e. offset != 0 length != whole length), we are not + // going to deal with it. + if (data.getBounds (tag, databounds, dim) == CDEV_SUCCESS && + databounds[0].length == num) { + + // do an extra check: not necessary + if (dim == 1 && num != elems) { + cdevSystem::defaultSystem().reportError + (CDEV_SEVERITY_ERROR, "cdevDefCollectionRequest", NULL, "One-dim array has wrong number of elements"); + return CDEV_ERROR; + } + + // calculate number of elements of output data + outelems = 1; + for (i = 1; i < dim; i++) + outelems *= databounds[i].length; + + if (outelems > 1) { + resbounds = new cdevBounds[dim - 1]; + for (i = 0; i < dim - 1; i++) { + resbounds[i].length = databounds[i + 1].length; + resbounds[i].offset = databounds[i + 1].offset; + } + } + + type = data.getType (tag); + switch (type) { + case CDEV_BYTE: + { + void* tmp = 0; + unsigned char* val = 0; + + if ((status = data.find (tag, tmp)) == CDEV_SUCCESS) { + val = (unsigned char *)tmp; + + if (outelems > 1) { + j = 0; + for (i = 0; i < num; i++) { + res[i].insert (tag, &(val[j]), outelems, dim - 1); + res[i].setBounds (tag, resbounds, dim - 1); + j += outelems; + } + } + else { + j = 0; + for (i = 0; i < num; i++) + res[i].insert (tag, val[j++]); + } + } + } + break; + case CDEV_INT16: + { + void* tmp = 0; + short* val = 0; + + if ((status = data.find (tag, tmp)) == CDEV_SUCCESS) { + val = (short *)tmp; + + if (outelems > 1) { + j = 0; + for (i = 0; i < num; i++) { + res[i].insert (tag, &(val[j]), outelems, dim - 1); + res[i].setBounds (tag, resbounds, dim - 1); + j += outelems; + } + } + else { + j = 0; + for (i = 0; i < num; i++) + res[i].insert (tag, val[j++]); + } + } + } + break; + case CDEV_UINT16: + { + void* tmp = 0; + unsigned short* val = 0; + + if ((status = data.find (tag, tmp)) == CDEV_SUCCESS) { + val = (unsigned short *)tmp; + + if (outelems > 1) { + j = 0; + for (i = 0; i < num; i++) { + res[i].insert (tag, &(val[j]), outelems, dim - 1); + res[i].setBounds (tag, resbounds, dim - 1); + j += outelems; + } + } + else { + j = 0; + for (i = 0; i < num; i++) + res[i].insert (tag, val[j++]); + } + } + } + break; + case CDEV_INT32: + { + void* tmp = 0; + int* val = 0; + + if ((status = data.find (tag, tmp)) == CDEV_SUCCESS) { + val = (int *)tmp; + + if (outelems > 1) { + j = 0; + for (i = 0; i < num; i++) { + res[i].insert (tag, &(val[j]), outelems, dim - 1); + res[i].setBounds (tag, resbounds, dim - 1); + j += outelems; + } + } + else { + j = 0; + for (i = 0; i < num; i++) + res[i].insert (tag, val[j++]); + } + } + } + break; + case CDEV_UINT32: + { + void* tmp = 0; + unsigned int* val = 0; + + if ((status = data.find (tag, tmp)) == CDEV_SUCCESS) { + val = (unsigned int *)tmp; + + if (outelems > 1) { + j = 0; + for (i = 0; i < num; i++) { + res[i].insert (tag, &(val[j]), outelems, dim - 1); + res[i].setBounds (tag, resbounds, dim - 1); + j += outelems; + } + } + else { + j = 0; + for (i = 0; i < num; i++) + res[i].insert (tag, val[j++]); + } + } + } + break; + case CDEV_FLOAT: + { + void* tmp = 0; + float* val = 0; + + if ((status = data.find (tag, tmp)) == CDEV_SUCCESS) { + val = (float *)tmp; + + if (outelems > 1) { + j = 0; + for (i = 0; i < num; i++) { + res[i].insert (tag, &(val[j]), outelems, dim - 1); + res[i].setBounds (tag, resbounds, dim - 1); + j += outelems; + } + } + else { + j = 0; + for (i = 0; i < num; i++) + res[i].insert (tag, val[j++]); + } + } + } + break; + case CDEV_DOUBLE: + { + void* tmp = 0; + double* val = 0; + + if ((status = data.find (tag, tmp)) == CDEV_SUCCESS) { + val = (double *)tmp; + + if (outelems > 1) { + j = 0; + for (i = 0; i < num; i++) { + res[i].insert (tag, &(val[j]), outelems, dim - 1); + res[i].setBounds (tag, resbounds, dim - 1); + j += outelems; + } + } + else { + j = 0; + for (i = 0; i < num; i++) + res[i].insert (tag, val[j++]); + } + } + } + break; + case CDEV_STRING: + { + if (dim == 1) { // Strings with dimention > 1 makes no sense + char** tmp = new char*[num]; + + if ((status = data.get (tag, tmp)) == CDEV_SUCCESS) { + for (i = 0; i < num; i++) + res[i].insert (tag, tmp[i]); + } + + for (i = 0; i < num; i++) + delete []tmp[i]; + delete []tmp; + } + else + status = CDEV_ERROR; + } + break; + case CDEV_TIMESTAMP: + { + void* tmp = 0; + cdev_TS_STAMP* val = 0; + + if ((status = data.find (tag, tmp)) == CDEV_SUCCESS) { + val = (cdev_TS_STAMP *)tmp; + + if (outelems > 1) { + j = 0; + for (i = 0; i < num; i++) { + res[i].insert (tag, &(val[j]), outelems, dim - 1); + res[i].setBounds (tag, resbounds, dim - 1); + j += outelems; + } + } + else { + j = 0; + for (i = 0; i < num; i++) + res[i].insert (tag, val[j++]); + } + } + } + break; + default: + status = CDEV_ERROR; + } + } + else + status = CDEV_ERROR; + + // free databounds + delete []databounds; + + if (resbounds) + delete []resbounds; + + return status; +} + + +// ********************************************************************* +// * This is routine split a input cdevData into an array of cdevData. +// * The input data is either a scaler value which will be duplicated +// * to all splited data values, or a array of data whose bound[0].length +// * must be the same as the 'num'. This works for a single tag +// ********************************************************************* +int +cdevDefCollectionRequest::splitDataItem (cdevData& data, int tag, + cdevData* res, int num) +{ + size_t dim; + int status; + + if (data.getDim (tag, &dim) != CDEV_SUCCESS) + return CDEV_ERROR; + + if (dim == 0) // scaler data, make every entry in the array the same + status = setScalerDataValue (data, tag, res, num); + else + status = setVectorDataValue (data, tag, dim, res, num); + + return status; +} + +// ********************************************************************* +// * This is routine split a input cdevData into an array of cdevData. +// * The input data is either a scaler value which will be duplicated +// * to all splited data values, or a array of data whose bound[0].length +// * must be the same as the 'num' +// * caller must free return cdevData array if it is not zero. +// ********************************************************************* +cdevData * +cdevDefCollectionRequest::splitData (cdevData& data, int num) +{ + int tag, status; + cdevData* res = 0; + cdevDataIterator ite (&data); + + // first allocate arrary of data + res = new cdevData[num]; + + status = CDEV_SUCCESS; + // walk through each tagged item to insert data into correct cdevData + // in the newly allocated array + for (ite.init (); !ite; ++ite) { + tag = ite.tag (); + if (splitDataItem (data, tag, res, num) != CDEV_SUCCESS) { + status = CDEV_CONVERT; + break; + } + } + if (status != CDEV_SUCCESS) { + delete []res; + res = 0; + } + return res; +} diff --git a/src/collection/cdevDefCollectionRequest.h b/src/collection/cdevDefCollectionRequest.h new file mode 100755 index 0000000..21d0c00 --- /dev/null +++ b/src/collection/cdevDefCollectionRequest.h @@ -0,0 +1,192 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * cdevDefCollectionRequest.h : This is the default class that will be used + * to support collection operations for services. + * + * Author: Walt Akers + * + * Revision History: + * cdevDefCollectionRequest.h,v + * Revision 1.2 1998/10/22 17:57:41 chen + * fix a bug on setting collection values + * + * Revision 1.1 1996/11/12 20:32:25 akers + * New collection device source code + * + * ----------------------------------------------------------------------------- + */ +#ifndef _CDEV_DEF_COLLECTION_REQUEST_H +#define _CDEV_DEF_COLLECTION_REQUEST_H + +#include + +class CDEV_CLASS_SPEC cdevDefCollectionRequest: public cdevCollectionRequest +{ +friend class cdevCollectionRequest; +friend class cdevService; + +public: + // ********************************************************************* + // * This structure is provided as the void * argument to the default + // * callback whenever the synchronous send is used. The checkSum is + // * used to detect if the result returned after the send method stopped + // * waiting for it. + // ********************************************************************* + typedef struct + { + int completionCode; + int finished; + cdevData *data; + } SendStatus; + + // ********************************************************************* + // * These methods get state and access information for the underlying + // * cdevRequestObjects. + // ********************************************************************* + virtual int getState (void); + virtual int getAccess (void); + + // ********************************************************************* + // * This method sets the context of each of the underlying + // * cdevRequestObjects. + // ********************************************************************* + virtual int setContext (cdevData &ctx); + + // ********************************************************************* + // * cdevClientRequestObject::send : + // * The send interface is used to provide synchronous I/O with the + // * service. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int send ( cdevData & in, cdevData & out ) + { return send(&in, &out); } + virtual int send ( cdevData * in, cdevData & out ) + { return send(in, &out); } + virtual int send ( cdevData & in, cdevData * out ) + { return send(&in, out); } + virtual int send ( cdevData * in, cdevData * out ); + + // ********************************************************************* + // * sendNoBlock : + // * The sendNoBlock interface is used in conjunction with cdevGroup + // * or cdevSystem to execute a series of operations. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int sendNoBlock (cdevData & in, cdevData & out) + { return sendNoBlock(&in, &out); } + virtual int sendNoBlock (cdevData * in, cdevData & out) + { return sendNoBlock(in, &out); } + virtual int sendNoBlock (cdevData & in, cdevData * out) + { return sendNoBlock(&in, out); } + virtual int sendNoBlock (cdevData * in, cdevData * out); + + // ********************************************************************* + // * sendCallback : + // * The sendCallback interface provides asynchronous communications + // * with the service. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int sendCallback (cdevData & in, cdevCallback & callback) + { return sendCallback(&in, callback); } + virtual int sendCallback (cdevData * in, cdevCallback & callback); + + // ********************************************************************* + // * This method returns the name of the class. + // ********************************************************************* + const char *className (void) const {return "cdevDefCollectionRequest";} + +protected: + // ********************************************************************* + // * These are the protected constructor and destructor for this object. + // ********************************************************************* + cdevDefCollectionRequest (char **devices, int nDevices, char *msg, cdevSystem& sys); + virtual ~cdevDefCollectionRequest (void); + + // ********************************************************************* + // * This is the syncCallback method. It will be used by the send + // * method in order to detect the completion of the operation. + // ********************************************************************* + static void syncCallback (int status, void * user, cdevRequestObject &, cdevData &data); + + // ********************************************************************* + // * This callback function is used to receive the individual callbacks + // * from the underlying cdevRequestObjects and is used by sendCallback. + // ********************************************************************* + static void asyncCallback (int, void *, cdevRequestObject &, cdevData &); + + // ********************************************************************* + // * This is the asyncNoBlockCallback method. It will be used by the + // * sendNoBlock method in order to detect the completion of the + // * operation. + // ********************************************************************* + static void asyncNoBlockCallback (int status, void * user, cdevRequestObject &, cdevData &data); + + + // ********************************************************************* + // * This is routine set scaler value to array of cdevData with a + // * specified tag + // ********************************************************************* + static int setScalerDataValue (cdevData& data, int tag, + cdevData* res, int num); + + // ********************************************************************* + // * This is routine set vector value to array of cdevData with a + // * specified tag + // ********************************************************************* + static int setVectorDataValue (cdevData& data, int tag, size_t dim, + cdevData* res, int num); + + // ********************************************************************* + // * This is routine split a input cdevData into an array of cdevData. + // * The input data is either a scaler value which will be duplicated + // * to all splited data values, or a array of data whose bound[0].length + // * must be the same as the 'num'. This works for a single tag + // ********************************************************************* + static int splitDataItem (cdevData& data, int tag, + cdevData* res, int num); + + + // ********************************************************************* + // * This is routine split a input cdevData into an array of cdevData. + // * The input data is either a scaler value which will be duplicated + // * to all splited data values, or a array of data whose bound[0].length + // * must be the same as the 'num' + // * caller must free return cdevData array if it is not zero. + // ********************************************************************* + static cdevData *splitData (cdevData& data, int splitnum); + +private: + static SendStatus sendStatus; + static int sendCheckSum; + + // ********************************************************************* + // * These are the cdevRequestObjects that are addressed by each call + // * to this cdevDefCollectionRequest. The nRequests variable contains + // * the number of cdevRequestObjects that are represented. + // ********************************************************************* + cdevRequestObject **requests; + int nRequests; + + // ********************************************************************* + // * This is the master data structure. It contains no actual data, + // * however, it identifies the data structure that should exist when + // * the request has been executed. + // * + // * This structure is inspected and updated at the completion of each + // * callback, and is used to initially create the cdevData objects that + // * are used for interim data storage. + // ********************************************************************* + cdevData format; +}; + +#endif diff --git a/src/collection/cdevErrorCollection.cc b/src/collection/cdevErrorCollection.cc new file mode 100755 index 0000000..3edb154 --- /dev/null +++ b/src/collection/cdevErrorCollection.cc @@ -0,0 +1,97 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * Description: + * cdevErrorCollection class implementation + * + * Author: Walt Akers, Chip Watson & Jie Chen + * + * Revision History: + * cdevErrorCollection.cc,v +// Revision 1.1 1996/11/12 20:32:27 akers +// New collection device source code +// + * ----------------------------------------------------------------------------- + */ + +#include +#include +#include + +#include +#include "cdevErrorCollection.h" + +cdevErrorCollection::cdevErrorCollection (char *devName) +:cdevCollection(devName) +{ +#ifdef _TRACE_OBJECTS + printf(" Create cdevErrorCollection class object\n"); +#endif + deviceName_ = new char[::strlen(devName) + 1]; + ::strcpy (deviceName_, devName); +} + +cdevErrorCollection::~cdevErrorCollection (void) +{ +#ifdef _TRACE_OBJECTS + printf(" Destroy cdevErrorCollection class object\n"); +#endif +} + +cdevRequestObject* +cdevErrorCollection::getRequestObject (char *msg) +{ + cdevRequestObject *obj = NULL; + getRequestObject (msg, obj); + return obj; +} + +int +cdevErrorCollection::getRequestObject (char *, cdevRequestObject* &reqobj) +{ + reqobj = NULL; + return CDEV_INVALIDOBJ; +} + +int +cdevErrorCollection::add(char *, ...) +{ + return CDEV_INVALIDOBJ; +} + +int +cdevErrorCollection::add(char **, int) +{ + return CDEV_INVALIDOBJ; +} + +int +cdevErrorCollection::addRegexp(char *) +{ + return CDEV_INVALIDOBJ; +} + +int +cdevErrorCollection::remove(char *, ...) +{ + return CDEV_INVALIDOBJ; +} + +int +cdevErrorCollection::remove(char **, int ) +{ + return CDEV_INVALIDOBJ; +} + +int +cdevErrorCollection::removeRegexp(char *) +{ + return CDEV_INVALIDOBJ; +} + diff --git a/src/collection/cdevErrorCollection.h b/src/collection/cdevErrorCollection.h new file mode 100755 index 0000000..0049107 --- /dev/null +++ b/src/collection/cdevErrorCollection.h @@ -0,0 +1,75 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * Description: + * cdevErrorCollection class implementation + * + * Author: Walt Akers, Chip Watson & Jie Chen + * + * Revision History: + * cdevErrorCollection.h,v + * Revision 1.1 1996/11/12 20:32:30 akers + * New collection device source code + * + * ----------------------------------------------------------------------------- + */ + +#ifndef _CDEV_ERRORCOLLECTION_H +#define _CDEV_ERRORCOLLECTION_H + +#include + +class cdevErrReqObject; + +class CDEV_CLASS_SPEC cdevErrorCollection: public cdevCollection +{ + public: + //======================================================================== + // Public Interface for cdevRequestObject + //======================================================================== + virtual cdevRequestObject *getRequestObject (char * msg ); + virtual int getRequestObject (char *msg, cdevRequestObject* &reqobj); + // PURPOSE: get a requestObject + // REQUIRE: name != 0, callers provide pointer only. + // PROMISE: always return CDEV_INVALIDOBJ + + //======================================================================== + // Public Interface for RTTI + //======================================================================== + virtual const char *className (void) const {return "cdevErrorCollection";} + + //======================================================================== + // Public Interface for list manipulation + //======================================================================== + int add(char* name, ...); + int add(char** list, int len); + int addRegexp(char* regexp); + int remove(char* name, ...); + int remove(char** list, int len); + int removeRegexp(char* regexp); + // PURPOSE: add(remove) a (list of/regexp of) names to the collection + // REQUIRE: nothing + // PROMISE: always return CDEV_INVALIDOBJ + + protected: + //constructors and destructor + //constructors will initialize list from directory service + cdevErrorCollection (char *name); + ~cdevErrorCollection (void); + + private: + // hide assignment and copy operator since the collection is + // a memory manager for collectionRequests and lists of devices + cdevErrorCollection& operator = (const cdevCollection &); + cdevErrorCollection (const cdevCollection &); + + // friend class declaration + friend class cdevCollection; +}; +#endif diff --git a/src/collection/cdevGrpCollectionRequest.cc b/src/collection/cdevGrpCollectionRequest.cc new file mode 100755 index 0000000..1c9b4c3 --- /dev/null +++ b/src/collection/cdevGrpCollectionRequest.cc @@ -0,0 +1,488 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * cdevGrpCollectionRequest.h : This class is used to collect the results that + * are generated by numerous service-specific + * cdevCollectionRequest objects. When all of the + * component collections have responded to this + * object, the data will be consolidated and + * returned to the caller. + * + * Author: Walt Akers + * + * Revision History: + * cdevGrpCollectionRequest.cc,v +// Revision 1.2 1997/04/02 17:54:03 akers +// Ongoing Development of CDEV 1.6 +// +// Revision 1.1 1996/11/12 20:32:32 akers +// New collection device source code +// + * ----------------------------------------------------------------------------- + */ +#include +#include +#include + +int cdevGrpCollectionRequest::sendCheckSum = 0; +cdevGrpCollectionRequest::SendStatus cdevGrpCollectionRequest::sendStatus; + +// ***************************************************************************** +// * cdevGrpCollectionRequest::cdevGrpCollectionRequest : +// * This is the constructor for the cdevGrpCollectionRequest object. It +// * will initialize all of the internals for the class. +// ***************************************************************************** +cdevGrpCollectionRequest::cdevGrpCollectionRequest + (char **devices, int nDevices, char *msg, cdevSystem& sys) + : cdevCollectionRequest(devices, nDevices, msg, sys), + collections(NULL), + nCollections(1), + requestOrder(NULL), + nRequests(0), + format() + { + // ********************************************************************* + // * This is a simple single linked-list that will be used to hold the + // * individual services as they are loaded. + // ********************************************************************* + class slist + { + public: + cdevService * service; + slist * next; + char * value; + int index; + int nItems; + + slist(char * Value="\0", int Index=0) + : service(NULL), next(NULL), value(strdup(Value)), + index(Index), nItems(0) {} + ~slist( void ) + { + if(next) delete next; + if(value) delete value; + } + } serviceList, *slistPtr; + + // ********************************************************************* + // * Obtain a pointer to the cdevDirectory device. This will be used + // * to lookup the name of the service that is associated with each + // * device/message combination. + // ********************************************************************* + cdevDevice *dir = cdevDevice::attachPtr("cdevDirectory"); + + // ********************************************************************* + // * Allocate the array of integers that will be used to store the + // * service number associated with each of the device/message + // * combinations. + // ********************************************************************* + requestOrder = new int[nDevices]; + + for(nRequests=0; nRequestssend("service", input, output)==CDEV_SUCCESS) + { + int found; + char * ptr; + output.find("value", (void * &)ptr); + if(ptr && *ptr) + { + slistPtr = &serviceList; + while(!(found=!strcmp(slistPtr->value, ptr)) && + slistPtr->next!=NULL) + { + slistPtr = slistPtr->next; + } + // ********************************************* + // * If the specified service was not found, + // * then create a new list entry for it. + // * Load the shared-library here if necessary. + // ********************************************* + if(!found) + { + slistPtr->next = new slist(ptr, slistPtr->index+1); + slistPtr = slistPtr->next; + if(!system_.serviceCreated(ptr)) + { + system_.loadService(ptr); + } + slistPtr->service = system_.service(ptr); + nCollections++; + } + requestOrder[nRequests] = slistPtr->index; + slistPtr->nItems++; + } + // ***************************************************** + // * If the required service is not specified, then + // * add the item to the "0" list. + // ***************************************************** + else { + requestOrder[nRequests] = 0; + serviceList.nItems++; + } + } + // ************************************************************* + // * If the service message could not be processed, then + // * add the item to the "0" list. + // ************************************************************* + else { + requestOrder[nRequests] = 0; + serviceList.nItems++; + } + } + + // ********************************************************************* + // * Allocate a block of cdevCollectionRequest pointers sufficient to + // * hold all of the cdevCollectionRequest objects from the different + // * servers. + // ********************************************************************* + collections = new cdevCollectionRequest *[nCollections]; + for(int k=0; knext) + { + if(slistPtr->service!=NULL) + { + int i, j; + // ***************************************************** + // * Allocate a block of character pointers to hold the + // * names associated with this service. + // ***************************************************** + char ** names = new char *[slistPtr->nItems]; + + // ***************************************************** + // * Copy the device name pointer for every device/msg + // * combination that is associated with this service to + // * the names array. + // ***************************************************** + for(i=0, j=0; iindex) + { + names[j++] = devices[i]; + } + } + + // ***************************************************** + // * Create/obtain a cdevCollectionRequest for the + // * group of device names that has been transfered to + // * the list. + // ***************************************************** + slistPtr->service->getCollectionRequest + (names, j, msg, collections[slistPtr->index]); + + // ***************************************************** + // * Delete the names array after it has been used. + // ***************************************************** + delete names; + } + } + } + + +// ***************************************************************************** +// * cdevGrpCollectionRequest::~cdevGrpCollectionRequest : +// * This is the destructor for the cdevGrpCollectionRequest object. +// ***************************************************************************** +cdevGrpCollectionRequest::~cdevGrpCollectionRequest ( void ) + { + for(int i=0; isetContext(ctx); + } + return cdevRequestObject::setContext(ctx); + } + +// ***************************************************************************** +// * getState: +// * This method allows the caller to obtain the combined state of the +// * collection of cdevRequestObjects that reside within this class. The +// * most restrictive state will be returned. +// * +// * Because the state definition variables proceeds from +// * CDEV_STATE_CONNECTED(0) to CDEV_STATE_INVALID(2), it can be assumed that +// * the higher a state result code is the more restrictive it is... +// * therefore, the highest state result code that is obtained from the +// * cdevRequestObjects will be returned to the caller. +// ***************************************************************************** +int cdevGrpCollectionRequest::getState ( void ) + { + int state; + + if(nCollections==0) state = CDEV_STATE_INVALID; + else for(int i=0; igetState())>state) + { + state = tState; + } + } + return state; + } + +// ***************************************************************************** +// * getAccess: +// * This method allows the caller to obtain the combined access of the +// * collection of cdevRequestObjects that reside within this class. The +// * most restrictive access code will be returned. +// * +// * Because the access definition variables proceed from +// * CDEV_ACCESS_NONE(0) to CDEV_ACCESS_WRITE(2), it can be assumed that +// * the lower an access result code is the more restrictive it is... +// * therefore, the smallest access result code that is obtained from the +// * cdevRequestObjects will be returned to the caller. +// ***************************************************************************** +int cdevGrpCollectionRequest::getAccess ( void ) + { + int accessCode; + + if(nCollections==0) accessCode = CDEV_ACCESS_NONE; + else for(int i=0; igetAccess())parent; + } + // ********************************************************************* + // * You'll note that this is a bone-jarring test to ensure that the + // * data that is provided is valid. + // ********************************************************************* + if(collector!=NULL && &collector->collections[request->index]==request) + { + collector->processCollection(request->index, status, &data); + + // ************************************************************* + // * Having processed this entry, I'll test to determine if all + // * of the members in this grpCallbackCollector are finished - + // * if they are I'll dispatch the callback that was provided + // * earlier by the user and will delete the collector. + // ************************************************************* + if(collector->finished()) + { + (collector->xobj->userCallback_->callbackFunction()) + (CDEV_SUCCESS, + collector->xobj->userCallback_->userarg(), + *collector->xobj->reqObj_, + collector->result); + delete collector; + } + } + } + + +// ***************************************************************************** +// * send : +// * The send interface is used to provide synchronous I/O with the service. +// * +// * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. +// ***************************************************************************** +int cdevGrpCollectionRequest::send ( cdevData * in, cdevData * out ) + { + int status = CDEV_SUCCESS; + sendStatus.completionCode = 0; + sendStatus.finished = 0; + sendStatus.data = out; + + cdevCallback cb(syncCallback, (void *)sendCheckSum); + + if((status = sendCallback(in, cb))==CDEV_SUCCESS) + { + // ************************************************************* + // * I used to wait for a response here only if the outbound + // * cdevData object was non-null. However, that provided + // * unexpected behavior to the client. Now I wait whether + // * output data is expected or not. + // ************************************************************* + cdevTimeValue t(5.0); + cdevClock timer; + timer.schedule(NULL,t); + + do { + system_.poll(); + } while(!sendStatus.finished && !timer.expired()); + + if (!sendStatus.finished) + { + status = CDEV_ERROR; + system_.reportError( + CDEV_SEVERITY_ERROR, + "cdevCollectionRequest", + this, + "Services failed to respond after 5 seconds"); + } + else status = sendStatus.completionCode; + } + sendCheckSum++; + return status; + } + + +// ***************************************************************************** +// * cdevClientRequestObject::sendNoBlock : +// * This function allows the caller to submit an asynchronous message to the +// * server for processing. +// ***************************************************************************** +int cdevGrpCollectionRequest::sendNoBlock (cdevData * in, cdevData * out) + { + cdevCallback cb(asyncNoBlockCallback, (void *)out); + return sendCallback(in, cb); + } + + +// ***************************************************************************** +// * sendCallback: +// * This method is used to submit a asynchronous call to the underlying +// * cdevRequestObjects. +// ***************************************************************************** +int cdevGrpCollectionRequest::sendCallback (cdevData* in, cdevCallback& callback) + { + int failCount = 0; + int status = CDEV_SUCCESS; + cdevTranObj *xobj = new cdevTranObj(&system_, this, NULL, new cdevCallback(callback)); + grpCallbackCollector *collector = new grpCallbackCollector + (nCollections, requestOrder, nRequests, format, *xobj); + + xobj->enableDeleteCbk(); + + // ******************************************************************** + // * This loop will walk through each of the cdevRequestObjects that + // * are in the requests array and will call their sendCallback method. + // * + // * The callback that is passed to them will provide a pointer to the + // * specific entry in the requests array of the grpCallbackCollector + // * object - this will be used to populate the proper entry in the + // * status attribute of the grpCallbackCollector object. + // * + // * If the cdevRequestObject is NULL, or if the call fails - a + // * cdevError code will be placed in the statusCode tag of the status + // * data and failCount will be incremented. If all of the requests are + // * invalid or fail, then an error will be returned and the user + // * callback will not be executed. + // ********************************************************************* + for(int i=0; icollections[i])); + if(collections[i]!=NULL) status = collections[i]->sendCallback(in, cb); + else status = CDEV_NOTFOUND; + if(status!=CDEV_SUCCESS) + { + collector->processCollection(i, status); + failCount++; + } + } + + // ********************************************************************* + // * If all of the requests failed, then the collector object will be + // * deleted and an error will be returned... Note that when the + // * collector object is deleted, then the cdevTranObj that it contains + // * will also be deleted. + // ********************************************************************* + if (failCount>=nCollections) + { + status = CDEV_ERROR; + delete collector; + } + else status = CDEV_SUCCESS; + return status; + } diff --git a/src/collection/cdevGrpCollectionRequest.h b/src/collection/cdevGrpCollectionRequest.h new file mode 100755 index 0000000..71c31c7 --- /dev/null +++ b/src/collection/cdevGrpCollectionRequest.h @@ -0,0 +1,167 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * cdevGrpCollectionRequest.h : This class is used to collect the results that + * are generated by numerous service-specific + * cdevCollectionRequest objects. When all of the + * component collections have responded to this + * object, the data will be consolidated and + * returned to the caller. + * + * Author: Walt Akers + * + * Revision History: + * cdevGrpCollectionRequest.h,v + * Revision 1.1 1996/11/12 20:32:34 akers + * New collection device source code + * + * ----------------------------------------------------------------------------- + */ +#ifndef _CDEV_GRP_COLLECTION_REQUEST_H +#define _CDEV_GRP_COLLECTION_REQUEST_H + +#include + +class CDEV_CLASS_SPEC cdevGrpCollectionRequest: public cdevCollectionRequest +{ +friend class cdevCollectionRequest; + +public: + // ********************************************************************* + // * This structure is provided as the void * argument to the default + // * callback whenever the synchronous send is used. The checkSum is + // * used to detect if the result returned after the send method stopped + // * waiting for it. + // ********************************************************************* + typedef struct + { + int completionCode; + int finished; + cdevData *data; + } SendStatus; + + // ********************************************************************* + // * These methods get state and access information for the underlying + // * cdevRequestObjects. + // ********************************************************************* + virtual int getState (void); + virtual int getAccess (void); + + // ********************************************************************* + // * This method sets the context of each of the underlying + // * cdevRequestObjects. + // ********************************************************************* + virtual int setContext (cdevData &ctx); + + // ********************************************************************* + // * send : + // * The send interface is used to provide synchronous I/O with the + // * service. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int send ( cdevData & in, cdevData & out ) + { return send(&in, &out); } + virtual int send ( cdevData * in, cdevData & out ) + { return send(in, &out); } + virtual int send ( cdevData & in, cdevData * out ) + { return send(&in, out); } + virtual int send ( cdevData * in, cdevData * out ); + + // ********************************************************************* + // * sendNoBlock : + // * The sendNoBlock interface is used in conjunction with cdevGroup + // * or cdevSystem to execute a series of operations. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int sendNoBlock (cdevData & in, cdevData & out) + { return sendNoBlock(&in, &out); } + virtual int sendNoBlock (cdevData * in, cdevData & out) + { return sendNoBlock(in, &out); } + virtual int sendNoBlock (cdevData & in, cdevData * out) + { return sendNoBlock(&in, out); } + virtual int sendNoBlock (cdevData * in, cdevData * out); + + // ********************************************************************* + // * sendCallback : + // * The sendCallback interface provides asynchronous communications + // * with the service. + // * + // * Returns CDEV_SUCCESS on success or CDEV_ERROR on error. + // ********************************************************************* + virtual int sendCallback (cdevData & in, cdevCallback & callback) + { return sendCallback(&in, callback); } + virtual int sendCallback (cdevData * in, cdevCallback & callback); + + // ********************************************************************* + // * This method returns the name of the class. + // ********************************************************************* + const char *className (void) const {return "cdevGrpCollectionRequest";} + +protected: + // ********************************************************************* + // * These are the protected constructor and destructor for this object. + // ********************************************************************* + cdevGrpCollectionRequest (char **devices, int nDevices, char *msg, cdevSystem& sys); + virtual ~cdevGrpCollectionRequest (void); + + // ********************************************************************* + // * This is the syncCallback method. It will be used by the send + // * method in order to detect the completion of the operation. + // ********************************************************************* + static void syncCallback (int status, void * user, cdevRequestObject &, cdevData &data); + + // ********************************************************************* + // * This callback function is used to receive the individual callbacks + // * from the underlying cdevRequestObjects and is used by sendCallback. + // ********************************************************************* + static void asyncCallback (int, void *, cdevRequestObject &, cdevData &); + + // ********************************************************************* + // * This is the asyncNoBlockCallback method. It will be used by the + // * sendNoBlock method in order to detect the completion of the + // * operation. + // ********************************************************************* + static void asyncNoBlockCallback (int status, void * user, cdevRequestObject &, cdevData &data); + +private: + static SendStatus sendStatus; + static int sendCheckSum; + + // ********************************************************************* + // * These are the cdevCollectionRequest objects that are addressed by + // * each call to this cdevGrpCollectionRequest. The nCollections + // * variable contains the number of cdevRequestObjects that are + // * represented. + // ********************************************************************* + cdevCollectionRequest **collections; + int nCollections; + + // ********************************************************************* + // * This is a table of integers that identifies the order in which + // * results from the incoming collections should be distributed to + // * the outbound data. + // ********************************************************************* + int * requestOrder; + int nRequests; + + // ********************************************************************* + // * This is the master data structure. It contains no actual data, + // * however, it identifies the data structure that should exist when + // * the request has been executed. + // * + // * This structure is inspected and updated at the completion of each + // * callback, and is used to initially create the cdevData objects that + // * are used for interim data storage. + // ********************************************************************* + cdevData format; +}; + +#endif diff --git a/src/collection/defCallbackCollector.cc b/src/collection/defCallbackCollector.cc new file mode 100755 index 0000000..d84e213 --- /dev/null +++ b/src/collection/defCallbackCollector.cc @@ -0,0 +1,445 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * defCallbackCollector : This class is used to collect the callbacks from a + * a single cdevDefCollectionRequest. This is an + * implementation class that is only associated with the + * default cdevCollectionObject if the developer's + * service does not provide specific support for + * collections. + * + * The cdevCollectionRequest object will obtain the + * cdevData object from this object and will return it + * to the caller or to an interim + * cdevGrpCollectionRequest object. + * + * Author: Walt Akers + * + * Revision History: + * defCallbackCollector.cc,v +// Revision 1.1 1996/11/12 20:32:35 akers +// New collection device source code +// + * ----------------------------------------------------------------------------- + */ + +#include "defCallbackCollector.h" + +// ***************************************************************************** +// * defCallbackCollector::defCallbackCollector : +// * This is the constructor for the defCallbackCollectior. It initializes +// * all internal data items. +// ***************************************************************************** +defCallbackCollector::defCallbackCollector(int NRequests, cdevData &Format, cdevTranObj &XObj ) + : counter(0), + requests (NULL), + nRequests(NRequests), + result (Format), + format (Format), + xobj (&XObj) + { + requests = new Request[nRequests]; + for(int i=0; i=nRequests); + } + +// ***************************************************************************** +// * defCallbackCollector::processRequest : +// * This method will copy the contents of the cdevData object associated +// * with a single request to the result cdevData object that will hold +// * the output for all of the requests.. +// * +// * This method increments the counter that is used to detect when all of +// * the collections have been processed. +// ***************************************************************************** +void defCallbackCollector::processRequest ( int idx, int status, cdevData *data ) + { + if(idx>=0 && idxinsert(cdevCollectionRequest::resultCodeTag(), status); + mergeData (result, *data, nRequests, idx); + } + else { + cdevData temp; + temp.insert(cdevCollectionRequest::resultCodeTag(), status); + mergeData(result, temp, nRequests, idx); + } + requests[idx].processed = 1; + counter++; + } + } + + +// ***************************************************************************** +// * defCallbackCollector::mergeData : +// * This method will copy the data items that are associated with +// * an inidividual request to the correct location in the arrays of the +// * result cdevData object that will hold the combined output from all of +// * the individual requests. +// ***************************************************************************** +void defCallbackCollector::mergeData (cdevData &to, cdevData &from, int arraySize, int idx) + { + cdevDataIterator iter(&from); + int tag; + iter.init(); + while((tag=iter.tag())!=0) + { + int done = 0; + size_t elems = 0; + cdevDataTypes fromType = from.getType(tag); + cdevDataTypes toType = to.getType(tag); + from.getElems(tag, &elems); + + if(elems>1) done = 1; + else to.getElems(tag, &elems); + + if(!done && (toType==CDEV_INVALID || elems!=arraySize)) + { + installEmptyArray(to, tag, fromType, arraySize); + } + if(!done) copyItemToArray(to, from, tag, idx); + + ++iter; + } + } + + +// ***************************************************************************** +// * defCallbackCollector::copyItemToArray : +// * This method will copy the element in a single tagged data item to its +// * correct index in the output array. +// ***************************************************************************** +void defCallbackCollector::copyItemToArray ( cdevData &to, cdevData &from, int tag, int idx) + { + size_t size; + cdevDataTypes fromType = from.getType(tag); + cdevDataTypes toType = to.getType(tag); + cdevDataTypes targetType; + + to.getElems(tag, &size); + + if(toType==CDEV_INVALID) + targetType = fromType; + else targetType = (fromType>toType)?fromType:toType; + + // ********************************************************************* + // * Even though the CDEV_TIME_STAMP is a senior type - it should not + // * overpower any other data type. + // ********************************************************************* + if(targetType==CDEV_TIMESTAMP) + { + if(fromType!=targetType && fromType!=CDEV_INVALID) targetType=fromType; + else if(toType!=targetType && toType!=CDEV_INVALID) targetType=toType; + } + + if(size>idx && idx>=0) switch(targetType) + { + case CDEV_BYTE: + { + unsigned char * ptr; + unsigned char item; + if(targetType!=toType) + { + ptr = new unsigned char[size]; + to.get(tag, ptr); + to.insert(tag, ptr, size); + delete ptr; + } + to.find(tag, (void *&)ptr); + from.get(tag, &item); + ptr[idx] = item; + break; + } + + case CDEV_INT16: + { + short * ptr; + short item; + if(targetType!=toType) + { + ptr = new short[size]; + to.get(tag, ptr); + to.insert(tag, ptr, size); + delete ptr; + } + to.find (tag, (void *&)ptr); + from.get(tag, &item); + ptr[idx] = item; + break; + } + + case CDEV_UINT16: + { + unsigned short * ptr; + unsigned short item; + if(targetType!=toType) + { + ptr = new unsigned short[size]; + to.get(tag, ptr); + to.insert(tag, ptr, size); + delete ptr; + } + to.find (tag, (void *&)ptr); + from.get(tag, &item); + ptr[idx] = item; + break; + } + + case CDEV_INT32: + { + long * ptr; + long item; + if(targetType!=toType) + { + ptr = new long[size]; + to.get(tag, ptr); + to.insert(tag, ptr, size); + delete ptr; + } + to.find (tag, (void *&)ptr); + from.get(tag, &item); + ptr[idx] = item; + break; + } + + case CDEV_UINT32: + { + unsigned long * ptr; + unsigned long item; + if(targetType!=toType) + { + ptr = new unsigned long[size]; + to.get(tag, ptr); + to.insert(tag, ptr, size); + delete ptr; + } + to.find (tag, (void *&)ptr); + from.get(tag, &item); + ptr[idx] = item; + break; + } + + case CDEV_FLOAT: + { + float * ptr; + float item; + if(targetType!=toType) + { + ptr = new float[size]; + to.get(tag, ptr); + to.insert(tag, ptr, size); + delete ptr; + } + to.find (tag, (void *&)ptr); + from.get(tag, &item); + ptr[idx] = item; + break; + } + + case CDEV_DOUBLE: + { + double * ptr; + double item; + if(targetType!=toType) + { + ptr = new double[size]; + to.get(tag, ptr); + to.insert(tag, ptr, size); + delete ptr; + } + to.find (tag, (void *&)ptr); + from.get(tag, &item); + ptr[idx] = item; + break; + } + + case CDEV_STRING: + { + int i; + char ** ptr = new char *[size]; + memset(ptr, 0, sizeof(char *)*size); + to.get(tag, ptr); + delete ptr[idx]; + from.get(tag, &ptr[idx]); + to.insert(tag, ptr, size); + for(i=0; i +#include +#include + +class defCallbackCollector +{ +public: + typedef struct + { + int index; + int processed; + defCallbackCollector * parent; + } Request; + + int counter; + cdevData result; + cdevData & format; + cdevTranObj * xobj; + Request * requests; + int nRequests; + + defCallbackCollector ( int NRequests, cdevData &Format, cdevTranObj &XObj ); + ~defCallbackCollector ( void ); + int finished ( void ); + void processRequest ( int idx, int status, cdevData *data = NULL ); + void mergeData ( cdevData &to, cdevData &from, int arraySize, int idx); + void copyItemToArray ( cdevData &to, cdevData &from, int tag, int idx); + void installEmptyArray ( cdevData &data, int tag, cdevDataTypes type, int size); +}; + +#endif /* _DEF_CALLBACK_COLLECTOR_H_ */ diff --git a/src/collection/grpCallbackCollector.cc b/src/collection/grpCallbackCollector.cc new file mode 100755 index 0000000..154b68a --- /dev/null +++ b/src/collection/grpCallbackCollector.cc @@ -0,0 +1,584 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + * ----------------------------------------------------------------------------- + * + * grpCallbackCollector : This class is used to collect the callbacks from a + * a group of collections and then compile the results + * into a single cdevData object. + * + * The cdevCollectionRequest object will obtain the + * cdevData object from this object and will return it + * to the caller. + * + * Author: Walt Akers + * + * Revision History: + * grpCallbackCollector.cc,v +// Revision 1.1 1996/11/12 20:32:39 akers +// New collection device source code +// + * ----------------------------------------------------------------------------- + */ + +#include "grpCallbackCollector.h" + +// ***************************************************************************** +// * grpCallbackCollector : +// * This is the constructor for the grpCallbackCollectior. It initializes +// * all internal data items. +// ***************************************************************************** +grpCallbackCollector::grpCallbackCollector(int NCollections, int * RequestOrder, int NRequests, cdevData &Format, cdevTranObj &XObj ) + : counter (0), + nCollections (NCollections), + requestOrder (RequestOrder), + nRequests (NRequests), + result (Format), + format (Format), + xobj (&XObj) + { + // ********************************************************************* + // * Allocate a block of Request structures that will be used to + // * maintain information about each of the individual collections. + // ********************************************************************* + collections = new Request[nCollections]; + + // ********************************************************************* + // * Initialize the Request structures with the index information and + // * count the number of requests that have the same index as this + // * collection. + // ********************************************************************* + for(int i=0; i=nCollections); + } + +// ***************************************************************************** +// * grpCallbackCollector::processCollection : +// * This method will copy the contents of the cdevData object associated +// * with a single collection to the result cdevData object that will hold +// * all of the results. +// * +// * This method increments the counter that is used to detect when all of +// * the collections have been processed. +// ***************************************************************************** +void grpCallbackCollector::processCollection ( int idx, int status, cdevData *data ) + + { + if(idx>=0 && idxtoType)?fromType:toType; + + // ********************************************************************* + // * Even though the CDEV_TIME_STAMP is a senior type - it should not + // * overpower any other data type. + // ********************************************************************* + if(targetType==CDEV_TIMESTAMP) + { + if(fromType!=targetType && fromType!=CDEV_INVALID) targetType=fromType; + else if(toType!=targetType && toType!=CDEV_INVALID) targetType=toType; + } + + if(toSize>idx && idx>=0) switch(targetType) + { + case CDEV_BYTE: + { + int i, j; + unsigned char * ptr; + unsigned char * items; + if(targetType!=toType) + { + ptr = new unsigned char[toSize]; + to.get(tag, ptr); + to.insert(tag, ptr, toSize); + delete ptr; + } + if(targetType!=fromType) + { + ptr = new unsigned char[fromSize]; + from.get(tag, ptr); + from.insert(tag, ptr, fromSize); + delete ptr; + } + to.find (tag, (void* &)ptr); + from.find(tag, (void* &)items); + for(j=0, i=0; i +#include +#include + +class grpCallbackCollector +{ +public: + typedef struct + { + int index; + int elements; + int processed; + grpCallbackCollector * parent; + } Request; + + int counter; + cdevData result; + cdevData & format; + cdevTranObj * xobj; + Request * collections; + int nCollections; + int * requestOrder; + int nRequests; + + grpCallbackCollector (int NCollections, int * RequestOrder, int NRequests, + cdevData &Format, cdevTranObj &XObj); + ~grpCallbackCollector ( void ); + int finished ( void ); + void processCollection ( int idx, int status, cdevData *data = NULL ); + void mergeData ( cdevData &to, cdevData &from, int idx ); + void copyItemsToArray ( cdevData &to, cdevData &from, int tag, int idx ); + void installEmptyArray ( cdevData &data, int tag, cdevDataTypes type, int size ); +}; + +#endif /* _GRP_CALLBACK_COLLECTOR_H_ */ diff --git a/src/common/.shobj/Linux/cdevClock.o b/src/common/.shobj/Linux/cdevClock.o new file mode 100644 index 0000000..3597c6a Binary files /dev/null and b/src/common/.shobj/Linux/cdevClock.o differ diff --git a/src/common/.shobj/Linux/cdevFdSet.o b/src/common/.shobj/Linux/cdevFdSet.o new file mode 100644 index 0000000..5129458 Binary files /dev/null and b/src/common/.shobj/Linux/cdevFdSet.o differ diff --git a/src/common/.shobj/Linux/cdevIntHash.o b/src/common/.shobj/Linux/cdevIntHash.o new file mode 100644 index 0000000..b1c589f Binary files /dev/null and b/src/common/.shobj/Linux/cdevIntHash.o differ diff --git a/src/common/.shobj/Linux/cdevSlist.o b/src/common/.shobj/Linux/cdevSlist.o new file mode 100644 index 0000000..1278be1 Binary files /dev/null and b/src/common/.shobj/Linux/cdevSlist.o differ diff --git a/src/common/.shobj/Linux/cdevStrHash.o b/src/common/.shobj/Linux/cdevStrHash.o new file mode 100644 index 0000000..4d03ae4 Binary files /dev/null and b/src/common/.shobj/Linux/cdevStrHash.o differ diff --git a/src/common/.shobj/Linux/cdevTimeValue.o b/src/common/.shobj/Linux/cdevTimeValue.o new file mode 100644 index 0000000..61f102d Binary files /dev/null and b/src/common/.shobj/Linux/cdevTimeValue.o differ diff --git a/src/common/.shobj/Linux/cdevTimerQueue.o b/src/common/.shobj/Linux/cdevTimerQueue.o new file mode 100644 index 0000000..0e5a1fa Binary files /dev/null and b/src/common/.shobj/Linux/cdevTimerQueue.o differ diff --git a/src/common/.shobj/Linux/shObjLoader.o b/src/common/.shobj/Linux/shObjLoader.o new file mode 100644 index 0000000..0246d3c Binary files /dev/null and b/src/common/.shobj/Linux/shObjLoader.o differ diff --git a/src/common/Makefile b/src/common/Makefile new file mode 100755 index 0000000..7a6d228 --- /dev/null +++ b/src/common/Makefile @@ -0,0 +1,64 @@ +# Makefile for Common Directory of CDEV +# +# cdev common directory +# +# Makefile,v +# Revision 1.9 1998/08/17 14:04:52 akers +# Added 'Minor Version Number' to TARGETDIR in Makefiles +# +# Revision 1.8 1998/02/10 18:04:55 chen +# add cdevSystem timer handler +# +# Revision 1.7 1996/07/10 21:03:43 chen +# add mkdir -p +# +# Revision 1.6 1996/06/26 15:54:12 akers +# Modifications to support multiple OS Versions +# +# Revision 1.5 1996/05/14 20:38:08 akers +# Makefile modifications +# +# Revision 1.4 1995/11/14 17:32:45 chen +# new makefile +# +# +include ../Makefile.config + +ifeq ($(SHOBJ),YES) + OBJTYPE=.shobj/$(TARGETDIR) +else + OBJTYPE=.obj/$(TARGETDIR) +endif + +ifeq ($(INCDIR), ) + INCDIR = ../.. +endif + +XTRACXXFLAGS = -I/usr/include/CC + +OBJS = $(OBJTYPE)/cdevFdSet.o \ + $(OBJTYPE)/shObjLoader.o \ + $(OBJTYPE)/cdevTimeValue.o \ + $(OBJTYPE)/cdevClock.o \ + $(OBJTYPE)/cdevSlist.o \ + $(OBJTYPE)/cdevStrHash.o \ + $(OBJTYPE)/cdevIntHash.o \ + $(OBJTYPE)/cdevTimerQueue.o + +targets: $(OBJTYPE) $(OBJDIR)/$(OBJTYPE) copyobjs copyincs + +$(OBJTYPE) : + @mkdir -p $(OBJTYPE) + +$(OBJDIR)/$(OBJTYPE) : + @mkdir -p $(OBJDIR)/$(OBJTYPE) + +copyobjs: $(OBJS) + @cp -f $(OBJS) $(OBJDIR)/$(OBJTYPE) + +copyincs: + @cp -f *.h $(INCDIR) + +clean: clean_hail + @rm -rf *.o .obj .shobj core *~ + diff --git a/src/common/NMakefile.mak b/src/common/NMakefile.mak new file mode 100755 index 0000000..1eeaadd --- /dev/null +++ b/src/common/NMakefile.mak @@ -0,0 +1,20 @@ +include ..\NMakefile.config + +OBJS = $(OBJDIR)\cdevFdSet.obj \ + $(OBJDIR)\shObjLoader.obj \ + $(OBJDIR)\cdevTimeValue.obj \ + $(OBJDIR)\cdevClock.obj \ + $(OBJDIR)\cdevSlist.obj \ + $(OBJDIR)\cdevStrHash.obj \ + $(OBJDIR)\cdevIntHash.obj \ + $(OBJDIR)\cdevTimerQueue.obj + +targets : copyobjs copyincs + +copyobjs : $(OBJS) + -@if not exist ..\lib\$(OBJDIR) mkdir ..\lib\$(OBJDIR) + -@for %x in ($(OBJDIR)\*.obj) DO @copy %x ..\lib\$(OBJDIR) > nul + +copyincs : + -@for %x in (*.h *.i) DO @copy %x $(CDEV)\include > nul + diff --git a/src/common/cdevClock.cc b/src/common/cdevClock.cc new file mode 100755 index 0000000..0717e75 --- /dev/null +++ b/src/common/cdevClock.cc @@ -0,0 +1,93 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevClock class implementation +// +// Author: Jie Chen +// +// Revision History: +// cdevClock.cc,v +// Revision 1.2 1998/02/10 18:04:56 chen +// add cdevSystem timer handler +// +// Revision 1.1.1.1 1995/06/16 17:14:01 epics +// initial import of cdev +// +// +#include "cdevClock.h" + +const cdevTimeValue cdevClock::zero; + +cdevClock::cdevClock (void): clock_value_ (), usr_arg_ (0) +{ +#ifdef _TRACE_OBJECTS + printf("Create cdevClock class\n"); +#endif +} + +cdevClock::~cdevClock (void) +{ +#ifdef _TRACE_OBJECTS + printf("Delete cdevClock class\n"); +#endif +} + +int +cdevClock::isEmpty (void) const +{ + return clock_value_ == cdevClock::zero; +} + +const cdevTimeValue & +cdevClock::scheduledTime (void) const +{ + return clock_value_; +} + +cdevTimeValue +cdevClock::currentTime (void) +{ + cdevTimeValue tv; + +#ifdef _WIN32 + _timeb cur_time; + _ftime (&cur_time); +#else + timeval cur_time; + ::gettimeofday (&cur_time, 0); +#endif + tv.set (cur_time); + return tv; +} + +int +cdevClock::schedule (const void *arg, + const cdevTimeValue &future_time) +{ + clock_value_ = future_time + cdevClock::currentTime(); + usr_arg_ = arg; + return 0; +} + +int +cdevClock::cancel (void) +{ + clock_value_ = cdevClock::zero; + return 0; +} + +int +cdevClock::expired (void) +{ + if (cdevClock::currentTime() >= clock_value_) + return 1; + else + return 0; +} diff --git a/src/common/cdevClock.h b/src/common/cdevClock.h new file mode 100755 index 0000000..90046ac --- /dev/null +++ b/src/common/cdevClock.h @@ -0,0 +1,81 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevClock Class Header File. +// +// Author: Jie Chen +// +// Revision History: +// cdevClock.h,v +// Revision 1.2 1998/02/10 18:04:56 chen +// add cdevSystem timer handler +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#ifndef _CDEV_CLOCK_H +#define _CDEV_CLOCK_H + +#include +#include +#include + +#include + +class CDEV_CLASS_SPEC cdevClock +{ + public: + // constructor and destructor + cdevClock (void); + virtual ~cdevClock(void); + + int isEmpty (void) const; + // PURPOSE: check whether this clock is set or not + // REQUIRE: nothing + // PROMISE: return 1: empty, return 0: not empty + + const cdevTimeValue &scheduledTime (void) const; + // PURPOSE: return scheduled timer value + // REQUIRE: nothing + // PROMISE: return time_value ZERO if empty + + static cdevTimeValue currentTime (void); + // PURPOSE: return current time + // REQUIRE: static function + // PROMISE: return current time (unix only) + + int schedule (const void *a, const cdevTimeValue &); + // PURPOSE: schedule a timer + // REQUIRE: nothing + // PROMISE: your timer will be remembered + + int cancel (void); + // PURPOSE: cancel a shceduled timer + // REQUIRE: nothing + // PROMISE: there will be no timer + + int expired (void); + // PURPOSE: check whether the timer is expired or not + // REQUIRE: nothing + // PROMISE: return 1: expired, return 0: not expired + + protected: + static const cdevTimeValue zero; + + private: + cdevTimeValue clock_value_; + const void *usr_arg_; + // deny access to copy and assignment operation + // no reason to create two clocks with same time value + cdevClock (const cdevClock&); + cdevClock& operator = (const cdevClock&); +}; +#endif diff --git a/src/common/cdevCommon.h b/src/common/cdevCommon.h new file mode 100755 index 0000000..b86f4a4 --- /dev/null +++ b/src/common/cdevCommon.h @@ -0,0 +1,44 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Utility prototypes and inline functions for cdev. +// +// Author: Walt Akers +// +// Revision History: +// cdevCommon.h,v +// Revision 1.2 1995/10/30 13:33:16 akers +// Added cdev specific version of strncpy +// +// +// +#ifndef _CDEV_COMMON_H +#define _CDEV_COMMON_H + +#include +#include + +// ***************************************************************************** +// * cdevStrncpy: +// * This is an alternative to the strncpy routine. This function will +// * always NULL terminate the resulting string, strncpy does not. +// ***************************************************************************** +inline char * cdevStrncpy(char *s1, const char *s2, size_t n) + { + char * result = s1; + if(s1!=NULL) + { + while(s2!=NULL && *s2 && (n--)>1) *(s1++) = *(s2++); + *s1=0; + } + return result; + } + +#endif /* _CDEV_COMMON_H */ diff --git a/src/common/cdevFdSet.cc b/src/common/cdevFdSet.cc new file mode 100755 index 0000000..d3cb3b0 --- /dev/null +++ b/src/common/cdevFdSet.cc @@ -0,0 +1,322 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// FD_Set Wrapper Based on ACE +// +// Author: Jie Chen +// +// Revision History: +// cdevFdSet.cc,v +// Revision 1.7 1997/12/12 16:40:18 chen +// add VMS fix +// +// Revision 1.6 1997/03/26 18:34:58 akers +// Ongoing development +// +// Revision 1.5 1997/02/18 15:46:49 chen +// port to linux 2.0.x +// +// Revision 1.4 1995/12/15 15:08:00 chen +// Add VMS Fix +// +// Revision 1.3 1995/10/16 18:20:12 chen +// change to fit under SunOs g++ +// +// Revision 1.2 1995/10/05 16:30:06 chen +// Fix for VMS +// +// Revision 1.1.1.1 1995/06/16 17:14:01 epics +// initial import of cdev +// +// +#include "cdevFdSet.h" + +#ifndef __VMS + +#ifndef __linux +extern "C" bzero (char *, int); +#endif + +#else +extern "C" bzero (char *, unsigned int); +#endif + +#ifdef CDEV_HAS_UNDERSCORE_FDBITS +#define fds_bits __fds_bits +#endif + +#if defined(__VMS) && defined(_TGV_MULTINET) +// Unfortunately when you use TGV Multinet, the bit offsets in the file* +// descriptor bitmasks used by select() cannot be found by simply using +// the value of the file descriptor. Fortunately, there is a simple rel* +// ship between the file descriptor value and the desired bit offset. +// (These macros are required because this file accesses the file +// descriptor bitmasks directly, without using the FD_SET(), FD_CLR(), * +// FD_ISSSET() macros). +#define FD_TO_BIT_OFFSET( fd ) ((fd)/CHANNELSIZE) +#define FD_FROM_BIT_OFFSET( ibit ) ((ibit)*CHANNELSIZE) +#else +// Under most operating systems the file descriptor value and the assoc* +// bit offset are one and the same. +#define FD_TO_BIT_OFFSET( fd ) (fd) +#define FD_FROM_BIT_OFFSET( ibit ) (ibit) +#endif // defined(__VMS) && defined(_TGV_MULTINET) + +inline int BIT_ENABLED (unsigned long word, int bit = 1) { return (word & bit) != 0; } +inline int BIT_DISABLED (unsigned long word, int bit = 1) { return (word & bit) == 0; } +inline void SET_BIT (unsigned long &word, int bit) { word |= bit; } +inline void CLR_BIT (unsigned long &word, int bit) { word &= ~bit; } + +const char cdevFdSet::nbits_[256] = +{ + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, +}; + +/* Counts the number of bits enabled in N. Uses a table lookup to + speed up the count. */ + +int +cdevFdSet::count_bits (unsigned long n) const +{ + return (cdevFdSet::nbits_[n & 0xff] + cdevFdSet::nbits_[(n >> 8) & 0xff] + + cdevFdSet::nbits_[(n >> 16) & 0xff] + cdevFdSet::nbits_[n >> 24]); +} + +void +cdevFdSet_Iterator::operator++ (void) +{ +#ifdef _WIN32 + this->index_++; +#else + this->val_ = (this->val_ >> 1) & cdevFdSet::MSB_MASK; + this->num_++; + + if (this->val_ == 0) { + for (this->index_++; + this->index_ < cdevFdSet::NUM_WORDS && fds_.mask_.fds_bits[this->index_] == 0; + this->index_++) + ; + + if (this->index_ == cdevFdSet::NUM_WORDS) { + this->num_ = fds_.max_handle_ + 1; + return; + } + else { + this->val_ = fds_.mask_.fds_bits[this->index_]; + this->num_ = this->index_ * cdevFdSet::WORD_SIZE; + } + } + + for (; BIT_DISABLED (this->val_); this->num_++) + this->val_ = (this->val_ >> 1) & cdevFdSet::MSB_MASK; +#endif +} + +cdevFdSet_Iterator::cdevFdSet_Iterator (cdevFdSet &f) +: fds_ (f), index_ (0), num_ (f.size_ == 0 ? f.max_handle_ + 1 : 0) +{ +#ifndef _WIN32 + for (; fds_.mask_.fds_bits[this->index_] == 0; this->index_++) + this->num_ += cdevFdSet::WORD_SIZE; + + for (this->val_ = this->fds_.mask_.fds_bits[this->index_]; + (BIT_DISABLED (this->val_)) && this->num_ < cdevFdSet::MAX_SIZE; + this->num_++) + this->val_ = (this->val_ >> 1) & cdevFdSet::MSB_MASK; +#endif +} + +/* Synchronize the underlying FD_SET with the MAX_FD and the SIZE. */ +void +cdevFdSet::sync (int max) +{ +#ifndef _WIN32 + this->size_ = 0; + + for (int i = max / cdevFdSet::WORD_SIZE; i >= 0; i--) + this->size_ += count_bits (this->mask_.fds_bits[i]); + + this->set_max (max); +#endif +} + +/* Resets the MAX_FD after a clear of the original MAX_FD. */ + +void +cdevFdSet::set_max (int current_max) +{ +#ifndef _WIN32 + int i = 0; + // SunOs g++ compiler does not like the i declared inside for loop + // --jie chen 10/16/95 + if (this->size_ == 0) + this->max_handle_ = -1; + else { + for (i = current_max / cdevFdSet::WORD_SIZE; + this->mask_.fds_bits[i] == 0; + i--) + ; + + this->max_handle_ = i * cdevFdSet::WORD_SIZE; + for (fd_mask val = this->mask_.fds_bits[i]; + (val & ~1) != 0; + val = (val >> 1) & cdevFdSet::MSB_MASK) + this->max_handle_++; + } +#endif +} + +/* Debugging method that prints out the underlying mask. */ + +int +cdevFdSet::pr_mask (FILE * fp) +{ + fprintf(fp, "[ "); + for (int i = 0; i < this->max_handle_ + 1; i++) + if (this->is_set (i)) + fprintf(fp," %d ", i); + + fprintf(fp, " ]"); + return this->size_; +} + +void +cdevFdSet::reset (void) +{ + this->max_handle_ = -1; + this->size_ = 0; + FD_ZERO (&this->mask_); +} + +/* Constructor, initializes the bitmask to all 0s. */ + +cdevFdSet::cdevFdSet (void) +{ + this->reset (); +} + +cdevFdSet::cdevFdSet (const fd_set &fd_mask): size_ (0) +{ + memcpy ((void *) &this->mask_, (void *) &fd_mask, sizeof this->mask_); + // sync is empty for WIN32 + this->sync (FD_SETSIZE); +} + +/* Returns the number of the large bit. */ + +int +cdevFdSet::max_set (void) const +{ + return this->max_handle_; +} + +/* Checks whether FD is enabled. */ + +int +cdevFdSet::is_set (int fd) const +{ +#ifdef _WIN32 + return FD_ISSET ((SOCKET)fd, &this->mask_); +#else + return FD_ISSET (fd, &this->mask_); +#endif +} + +/* Enables the FD. */ + +void +cdevFdSet::set_bit (int fd) +{ + if (!this->is_set (fd)) { +#ifdef _WIN32 + FD_SET ((SOCKET)fd, &this->mask_); +#else /* WIN32 */ + FD_SET (fd, &this->mask_); + this->size_++; +// again VMS system has different idea :----------- +#if defined(__VMS) && defined(_TGV_MULTINET) + if (FD_TO_BIT_OFFSET(fd) > this->max_handle_) + this->max_handle_ = FD_TO_BIT_OFFSET(fd); +#else + if (fd > this->max_handle_) + this->max_handle_ = fd; +#endif + +#endif + } +} + +/* Disables the FD. */ + +void +cdevFdSet::clr_bit (int fd) +{ + if (this->is_set (fd)) { +#ifdef _WIN32 + FD_CLR ((SOCKET)fd, &this->mask_); +#else + FD_CLR (fd, &this->mask_); + this->size_--; + +#if defined(__VMS) && defined(_TGV_MULTINET) + if (FD_TO_BIT_OFFSET(fd) == this->max_handle_) + this->set_max (this->max_handle_); +#else + if (fd == this->max_handle_) + this->set_max (this->max_handle_); +#endif + +#endif + } +} + +/* Returns a count of the number of enabled bits. */ +int +cdevFdSet::num_set (void) const +{ +#ifdef _WIN32 + return this->mask_.fd_count; +#else + return this->size_; +#endif +} + +int +cdevFdSet_Iterator::operator () (void) +{ +#ifdef _WIN32 + return this->index_ < this->fds_.mask_.fd_count + ? fds_.mask_.fd_array[this->index_] : -1; +#else + +#if defined(__VMS) && defined(_TGV_MULTINET) + return FD_FROM_BIT_OFFSET(this->num_ <= this->fds_.max_handle_ ? + this->num_ :-1); +#else + return this->num_ <= this->fds_.max_handle_ ? this->num_ : -1; +#endif + +#endif +} diff --git a/src/common/cdevFdSet.h b/src/common/cdevFdSet.h new file mode 100755 index 0000000..7713ff0 --- /dev/null +++ b/src/common/cdevFdSet.h @@ -0,0 +1,181 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// File Descriptor Mask Class (Based On ACE Handler_Set) +// +// Author: Jie Chen +// +// Revision History: +// cdevFdSet.h,v +// Revision 1.6 1997/03/26 18:34:58 akers +// Ongoing development +// +// Revision 1.5 1996/10/01 13:58:23 akers +// Changes to support AIX +// +// Revision 1.4 1996/09/19 18:50:06 akers +// Included time.h in order to match redefinition of fd_set to __fd_set. +// +// Revision 1.3 1995/12/15 15:08:06 chen +// Add VMS Fix +// +// Revision 1.2 1995/10/05 16:30:12 chen +// Fix for VMS +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#ifndef _CDEV_FDSET_H +#define _CDEV_FDSET_H + +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#else +#include + +#ifdef __VMS +#ifdef _TGV_MULTINET +// Under TGV multinet and VMS, if you want sys/types.h you need to have +// types.h already pulled in because sys/types.h makes it look like types.h +// is loaded. Then when types.h does get loaded, it is ignored because it +// looks like it is already loaded -- Mr. Danial Van Olst +#include +#endif +#endif + +#ifdef __VMS +#ifdef _TGV_MULTINET +// Under TGV Multinet and VMS, the file sys/param.h does not define +// NOFILE (max number of open files per process). +// FD_SETSIZE seems to be the correct value for NOFILE. +// See Multinet's sys/types.h file for more info on FD_SETSIZE. +// - Daniel Van Olst +#ifndef NOFILE +#define NOFILE FD_SETSIZE +#endif /* NOFILE not defined. */ + +#endif /* _TGV_MULTINET defined. */ +#endif /* __VMS defined. */ + +#include +#include + +/* The header sys/select.h must be included on AIX machines */ +/* in order to define the FD_ZERO macro. */ +#ifdef _AIX + #include +#endif + +/* This wrapper design is not very portable to DEC OSF/1 */ +/* I had to redefine NFDBITS to 32. On OSF/1 NFDBITS is a */ +/* macro that expands to (sizeof(fd_mask)*8) which is 4096 by */ +/* default. This was an inappropriate value for defining the */ +/* MSB_MASK default value. Any ideas? The workaround is a */ +/* pretty severe restriction for OSF/1. DJT */ +/*#if defined (__osf__) */ +/*#define NFDBITS 32 */ +/*#endif */ + +#endif + +class CDEV_CLASS_SPEC cdevFdSet +{ + // = TITLE + // C++ wrapper for the BSD fd_set abstraction. + // + // = DESCRIPTION + // + + friend class cdevFdSet_Iterator; + public: + // = Initialization and termination. + + cdevFdSet (void); + cdevFdSet (const fd_set &mask); + + // = Methods for manipulating bitsets. + void reset (void); + int is_set (int) const; + void set_bit (int); + void clr_bit (int); + int num_set (void) const; + int max_set (void) const; + int pr_mask ( FILE * fp = stdout ); + void sync (int max = FD_SETSIZE); + operator fd_set *( void ) { return &mask_; } + +private: + int size_; + int max_handle_; + fd_set mask_; + + enum + { +#ifdef _WIN32 + MAX_SIZE = FD_SETSIZE, +#else + MAX_SIZE = NOFILE, + WORD_SIZE = NFDBITS, + NUM_WORDS = howmany (NOFILE, NFDBITS), +#ifdef __DECCXX + // DECC warns about integer overflow if 1 used because 1 is signed + MSB_MASK = ~(1U << (NFDBITS - 1)) +#elif defined (CDEV_HAS_64BIT_LONGS) + MSB_MASK = ~(1UL << (NFDBITS - 1)) +#else + MSB_MASK = ~(1 << (NFDBITS - 1)) +#endif + +#endif + }; + + int count_bits (unsigned long n) const; + void set_max (int max); + + static const char nbits_[256]; +}; + +class cdevFdSet_Iterator + // = TITLE + // Iterator for the cdevFdSet abstraction. + // + // = DESCRIPTION + // +{ +public: + cdevFdSet_Iterator (cdevFdSet &); + int operator ()(void); + void operator++ (void); + +private: + cdevFdSet &fds_; +#ifdef _WIN32 + /* index into fd_array[FD_SETSIZE] */ + unsigned int index_; +#else + /* index into fd_mask array */ + int index_; +#endif + /* current FD value = bit number in the long mask */ + /* not used in the WIN32 platform */ + int num_; + +#ifndef _WIN32 + fd_mask val_; +#endif +}; + +#endif diff --git a/src/common/cdevIntHash.cc b/src/common/cdevIntHash.cc new file mode 100755 index 0000000..4b00869 --- /dev/null +++ b/src/common/cdevIntHash.cc @@ -0,0 +1,209 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//----------------------------------------------------------------------------- +// Description: +// cdevIntHash: cdev hash table keyed by an integer +// Open Hash with buckets implemented by single linked lists +// +// Note: void *s are stored inside the table. This class +// will not manage these pointers. Callers have to +// manage these pointers +// +// Author: Danjin Wu (Modified from cdevStrHash class) +// +// Revision History: +// cdevIntHash.cc,v +// Revision 1.4 1997/05/15 17:17:14 chen +// fix bugs for SunOS4 using CC +// +// Revision 1.3 1996/08/26 21:23:17 akers +// Corrected dereference of NULL in getData +// +// Revision 1.2 1996/08/26 21:12:33 akers +// Added getData method to iterator +// +// Revision 1.1 1995/08/21 15:45:45 danjin +// integer hash table +// +// +// +#include +#include +#include +#include "cdevIntHash.h" + + +//====================================================================== +// class cdevIntHash implementation +//====================================================================== +cdevIntHash::cdevIntHash (unsigned int max) +:tablesize(max) +{ +#ifdef _TRACE_OBJECTS + printf ("Create cdevIntHash Class Objects\n"); +#endif + // cdevSlist has a default constructor, so one can create an array of the list + buckets = new cdevSlist[tablesize]; + assert (buckets); +} + +cdevIntHash::~cdevIntHash (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete cdevIntHash Class Objects\n"); +#endif + delete []buckets; + buckets = 0; +} + +int +cdevIntHash::isEmpty() +{ + // if any table is non-empty, return 0 + for (int i = 0; i < tablesize; i++) + if (!buckets[i].isEmpty()) + return 0; + + // all empty + return 1; +} + +void +cdevIntHash::deleteAllValues() +{ + // delete all values from a hash table + // clear the elements from each of teh buckets + for (int i = 0; i < tablesize; i++) + buckets[i].deleteAllValues(); +} + +unsigned int +cdevIntHash::hash(const cdevIntKeyItem key) const +{ + // return hashed value of key + return (key % tablesize); +} + +void +cdevIntHash::add (cdevIntKeyItem key, cdevHashItem newele) +{ + buckets[hash (key)].add (newele); +} + +int +cdevIntHash::remove (cdevIntKeyItem key, cdevHashItem ele) +{ + return (buckets[hash (key)].remove (ele)); +} + +int +cdevIntHash::find (cdevIntKeyItem key, cdevHashItem ele) const +{ + return buckets[hash (key)].includes(ele); +} + +cdevSlist& +cdevIntHash::bucketRef (cdevIntKeyItem key) +{ + return (buckets[hash (key)]); +} + +//====================================================================== +// class cdevIntHashIterator implementation +//====================================================================== +cdevIntHashIterator::cdevIntHashIterator (cdevIntHash& v) +:base(v), currentIndex(0), itr(0) +{ +#ifdef _TRACE_OBJECTS + printf ("Create cdevIntHashIterator Class Object \n"); +#endif + // no further initialization +} + +cdevIntHashIterator::~cdevIntHashIterator (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete cdevIntHashIterator Class Object \n"); +#endif + currentIndex = 0; + if (itr) + delete itr; +} + +int +cdevIntHashIterator::init (void) +{ + // initialize iterator, + // start search with first bucket + currentIndex = 0; + itr = 0; + return getNextIterator(); +} + +cdevHashItem +cdevIntHashIterator::operator() (void) +{ + // return current element + return itr!=NULL?(*itr)():NULL; +} + +cdevHashItem cdevIntHashIterator::getData (void) +{ + // return current element + return itr!=NULL?(*itr)():NULL; +} + +int +cdevIntHashIterator::operator ! (void) +{ + // test if there is a current element + return itr != 0; +} + +int +cdevIntHashIterator::operator ++ (void) +{ + // see if current iterator can be advanced + if (itr && ++(*itr)) + return 1; + + // if not, get next iterator + currentIndex++; + return getNextIterator(); +} + +void +cdevIntHashIterator::operator = (cdevHashItem val) +{ + // change the current value + (*itr) = val; +} + +int +cdevIntHashIterator::getNextIterator (void) +{ + // if there is an old iterator, delete it + if (itr != 0) + delete itr; + + // now search for a new one + for (; currentIndex < base.tablesize; currentIndex++){ + // generate a new iterator at the current point + itr = new cdevSlistIterator (base.buckets[currentIndex]); + assert(itr != 0); + + // if it has at least one element, we're done + if (itr->init()) + return 1; + + // otherwise delete it, try again + delete itr; + } + // all out of iterators, can quit + itr = 0; + return 0; +} diff --git a/src/common/cdevIntHash.h b/src/common/cdevIntHash.h new file mode 100755 index 0000000..84f72f0 --- /dev/null +++ b/src/common/cdevIntHash.h @@ -0,0 +1,117 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevIntHash: cdev hash table keyed by an integer +// Open Hash with buckets implemented by single linked lists +// +// Note: void *s are stored inside the table. This class +// will not manage these pointers. Callers have to +// manage these pointers +// +// Author: Danjin Wu (Modified from cdevStrHash class) +// +// Revision History: +// cdevIntHash.h,v +// Revision 1.2 1996/08/26 21:12:35 akers +// Added getData method to iterator +// +// Revision 1.1 1995/08/21 15:45:36 danjin +// integer hash table +// +// +// +#ifndef _CDEV_INT_HASH_H +#define _CDEV_INT_HASH_H + +#include + +//====================================================================== +// One simple integer hash function +// This hash function is used in cdevData. +// It returns integer value between 0 to table size +//====================================================================== + +typedef int cdevIntKeyItem; +typedef void* cdevHashItem; +//====================================================================== +// class cdevIntHash +// collection of buckets indexed by hashed values +//====================================================================== +class cdevIntHashIterator; + +class CDEV_CLASS_SPEC cdevIntHash +{ +public: + // constructor, construct a table with entry max + cdevIntHash (unsigned int max); + // destructor + virtual ~cdevIntHash (void); + + // operations + + // is the table empty: return 1: yes. return 0: no + virtual int isEmpty(); + + // clear the elements of the set + virtual void deleteAllValues(); + + // add an element to the collection + virtual void add (cdevIntKeyItem key, cdevHashItem ele); + + // test to see whether this hash table includes one particular element + virtual int find (cdevIntKeyItem key, cdevHashItem ele) const; + + // remove an element. return 0: ele is not inside table. return 1: success + virtual int remove (cdevIntKeyItem key, cdevHashItem ele); + + // return a reference to a particular bucket according to the key + cdevSlist& bucketRef (cdevIntKeyItem key); + + protected: + friend class cdevIntHashIterator; + + // the actual table itself is a vector of buckets + const unsigned int tablesize; + cdevSlist* buckets; + + // convert key into unsigned integer value in range + unsigned int hash(const cdevIntKeyItem key) const; + +}; + +//====================================================================== +// class cdevIntHashIterator +// iterator protocol for hash tables +//====================================================================== +class CDEV_CLASS_SPEC cdevIntHashIterator +{ +public: + // constructor and destructor + cdevIntHashIterator (cdevIntHash& v); + ~cdevIntHashIterator (void); + + // iterator protocol + int init (void); + cdevHashItem operator ()(void); + cdevHashItem getData (void); + int operator ! (void); + int operator ++(void); + void operator = (cdevHashItem value); + +protected: + cdevIntHash& base; + unsigned int currentIndex; + // Single iterator within a bucket + cdevSlistIterator* itr; + // getNextIterator used to set internal iterator pointer + // return 1: got it. return 0: no more iterator + int getNextIterator (void); +}; +#endif diff --git a/src/common/cdevSlist.cc b/src/common/cdevSlist.cc new file mode 100755 index 0000000..f628c39 --- /dev/null +++ b/src/common/cdevSlist.cc @@ -0,0 +1,541 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Single Linked List for void * +// +// Note: remove and clean operations on the list +// will only remove link nodes without removal of +// the content inside the nodes. It is callers' +// responsiblity to clean up those contents +// +// This is unsafe C++ practice, use this list at you own risk +// +// Reason for this list: It is very difficult to instantiate +// a template class in a stand alone shared library +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// Revision History: +// cdevSlist.cc,v +// Revision 1.4 1995/10/17 15:26:45 chen +// fix to work under SunOs and gcc +// +// Revision 1.3 1995/10/05 16:30:31 chen +// Add stdio.h +// +// Revision 1.2 1995/08/17 20:33:05 chen +// fixing iterator bug +// +// Revision 1.1 1995/06/30 15:07:36 chen +// single linked list for void * +// +// +#include +#include "cdevSlist.h" + +//====================================================================== +// class cdevSlist implementation +//====================================================================== +cdevSlist::cdevSlist (void) +:ptrToFirstLink(0) +{ +#ifdef _TRACE_OBJECTS + printf ("Create cdevSlist Class Object\n"); +#endif + // no further initialization +} + +cdevSlist::cdevSlist (const cdevSlist & source) +{ +#ifdef _TRACE_OBJECTS + printf ("Create cdevSlist Class Object\n"); +#endif + // duplicate elements from source list + if (source.isEmpty()) + ptrToFirstLink = 0; + else{ + cdevSlistLink * firstLink = source.ptrToFirstLink; + ptrToFirstLink = firstLink->duplicate(); + } +} + +cdevSlist::~cdevSlist (void) +{ + // empty all elements from the list +#ifdef _TRACE_OBJECTS + printf ("Delete cdevSlist Class Object\n"); +#endif + deleteAllValues(); +} + +void cdevSlist::add (cdevSlistItem val) +{ + // add a new value to the front of a linked list + ptrToFirstLink = new cdevSlistLink(val, ptrToFirstLink); + assert(ptrToFirstLink != 0); +} + +int cdevSlist::remove (cdevSlistItem val) +{ + // remove an element from the list + // loop to test each element + cdevSlistLink *q = ptrToFirstLink; + for (cdevSlistLink * p = ptrToFirstLink; p; p = p->ptrToNextLink){ + if (val == p->value){ + if (q == p){ + // remove first element + ptrToFirstLink = p->ptrToNextLink; + delete p; + } + else{ + q->ptrToNextLink = p->ptrToNextLink; + delete p; + } + return 1; + } + q = p; + } + // not found + return 0; +} + +void cdevSlist::deleteAllValues (void) +{ + // clear all items from the list + cdevSlistLink * next; + + for (cdevSlistLink * p = ptrToFirstLink; p != 0; p = next){ + // delete the element pointed to by p + next = p->ptrToNextLink; + p->ptrToNextLink = 0; + delete p; + } + + // mark that the list contains no elements + ptrToFirstLink = 0; +} + +int cdevSlist::count (void) const +{ + // count how many items are there + cdevSlistLink * next; + int num = 0; + + for (cdevSlistLink *p = ptrToFirstLink; p != 0; p = next){ + next = p->ptrToNextLink; + num++; + } + return num; +} + +cdevSlist * cdevSlist::duplicate (void) const +{ + cdevSlist * newlist = new cdevSlist; + assert(newlist != 0); + + // copy list + if (ptrToFirstLink) + newlist->ptrToFirstLink = ptrToFirstLink->duplicate(); + + // return the new list + return newlist; +} + +cdevSlistItem +cdevSlist::firstElement (void) const +{ + // return first value in list + assert(ptrToFirstLink != 0); + return ptrToFirstLink->value; +} + +cdevSlistItem +cdevSlist::lastElement (void) const +{ + assert(ptrToFirstLink != 0); + // loop through until last element + cdevSlistLink *p = 0; + for (p = ptrToFirstLink; p->ptrToNextLink; p = p->ptrToNextLink) + ; + return p->value; +} + +int cdevSlist::includes(cdevSlistItem v) const +{ + // loop to test each element + for (cdevSlistLink * p = ptrToFirstLink; p; p = p->ptrToNextLink) + if (v == p->value) + return 1; + + // not found + return 0; +} + +int cdevSlist::isEmpty (void) const +{ + // test to see if the list is empty + // list is empty if the pointer to the first link is null + return ptrToFirstLink == 0; +} + +void cdevSlist::removeFirst (void) +{ + // make sure there is a first element + assert(ptrToFirstLink != 0); + + // save pointer to the removed node + cdevSlistLink * p = ptrToFirstLink; + + // reassign the ptrToFirstLink node + ptrToFirstLink = p->ptrToNextLink; + + // recover memory used by the first element + delete p; +} + +//====================================================================== +// class slink implementation +//====================================================================== +cdevSlistLink* +cdevSlistLink::insert(cdevSlistItem val) +{ + // insert a new link after current node + ptrToNextLink = new cdevSlistLink(val, ptrToNextLink); + + // check that allocation was successful + assert(ptrToNextLink != 0); + return ptrToNextLink; +} + +cdevSlistLink::cdevSlistLink (cdevSlistItem val, cdevSlistLink * nxt) +:value(val), ptrToNextLink(nxt) +{ + // create and initialize a new link field +} + +cdevSlistLink* +cdevSlistLink::duplicate (void) +{ + cdevSlistLink * newlink; + + // if there is a next field. copy remainder of list + if (ptrToNextLink != 0) + newlink = new cdevSlistLink(value, ptrToNextLink->duplicate()); + else + newlink = new cdevSlistLink (value, 0); + + // check that allocation was successful + assert(newlink != 0); + return newlink; +} + +//====================================================================== +// class listIterator implementation +//====================================================================== +cdevSlistIterator::cdevSlistIterator(cdevSlist & aList) +:theList(aList) +{ + // create and initialize a new list + init(); +} + +int cdevSlistIterator::init() +{ + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +cdevSlistItem +cdevSlistIterator::operator () (void) +{ + // return value of current element + // check to see if there is a current element + assert(currentLink != 0); + + // return value associated with current element + return currentLink->value; +} + +int cdevSlistIterator::operator ! (void) +{ + // test for termination of the iterator + // if current link references a removed value, + // update current to point to next position + if (currentLink == 0) + if (previousLink != 0) + currentLink = previousLink->ptrToNextLink; + + // now see if currentLink is valid + return currentLink != 0; +} + +int cdevSlistIterator::operator ++() +{ + // move current pointer to nect element + // special processing if current link is deleted + if (currentLink == 0){ + if (previousLink == 0) + currentLink = theList.ptrToFirstLink; + else + currentLink = previousLink->ptrToNextLink; + } + else{ + // advance pointer + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +void cdevSlistIterator::operator = (cdevSlistItem val) +{ + // modify value of current element + assert(currentLink != 0); + + // modify value of the current link + currentLink->value = val; +} + +void cdevSlistIterator::removeCurrent (void) +{ + // remove the current element from a list + // make sure there is a current element + assert(currentLink != 0); + + // case 1, removing first element + if (previousLink == 0) + theList.ptrToFirstLink = currentLink->ptrToNextLink; + + // case 2, not removing the first element + else + previousLink->ptrToNextLink = currentLink->ptrToNextLink; + + // delete current node + delete currentLink; + + // and set current pointer to null + currentLink = 0; +} + +void cdevSlistIterator::addBefore(cdevSlistItem val) +{ + // a a new element to list before current value + // case 1, not at start + if (previousLink) + previousLink = previousLink->insert(val); + + // case 2, at start of list + else{ + theList.cdevSlist::add(val); + previousLink = theList.ptrToFirstLink; + currentLink = previousLink->ptrToNextLink; + } +} + +void cdevSlistIterator::addAfter(cdevSlistItem val) +{ + // a a new element to list after current value + // case 1, not at start + if (currentLink != 0) + currentLink->insert(val); + + // case 2, at end of list + else if (previousLink != 0) + currentLink = previousLink->insert(val); + + // case 3, start of list + else + theList.cdevSlist::add(val); +} + +int cdevSlistIterator::searchSame(cdevSlistItem &val) +{ + // search the list to find out whether we have this element + // if we do, move cursor to this element return 1 + // if we don't return 0 + init(); + + if (currentLink == 0){ + // empty link + return 0; + } + while (currentLink != 0){ + // advance pointer + if (currentLink->value == val) + break; + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +//======================================================================== +// Implementation of cdevSlistCursor +// Implements of cursor without changing list +//======================================================================== +cdevSlistCursor::cdevSlistCursor(const cdevSlist & aList) +:theList(aList) +{ + // create and initialize a new list + init(); +} + +int +cdevSlistCursor::init() +{ + // set the iterator to the first element in the list + previousLink = 0; + currentLink = theList.ptrToFirstLink; + return currentLink != 0; +} + +cdevSlistItem +cdevSlistCursor::operator () (void) +{ + // return value of current element + // check to see if there is a current element + assert(currentLink != 0); + + // return value associated with current element + return currentLink->value; +} + +int cdevSlistCursor::operator ! (void) +{ + // test for termination of the iterator + // if current link references a removed value, + // update current to point to next position + if (currentLink == 0) + if (previousLink != 0) + currentLink = previousLink->ptrToNextLink; + + // now see if currentLink is valid + return currentLink != 0; +} + +int cdevSlistCursor::operator ++ (void) +{ + // move current pointer to nect element + // special processing if current link is deleted + if (currentLink == 0){ + if (previousLink == 0) + currentLink = theList.ptrToFirstLink; + else + currentLink = previousLink->ptrToNextLink; + } + else{ + // advance pointer + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +int cdevSlistCursor::searchSame (cdevSlistItem &val) +{ + // search the list to find out whether we have this element + // if we do, move cursor to this element return 1 + // if we don't return 0 + init(); + + if (currentLink == 0){ + // empty link + return 0; + } + while (currentLink != 0){ + // advance pointer + if (currentLink->value == val) + break; + previousLink = currentLink; + currentLink = currentLink->ptrToNextLink; + } + + // return true if we have a valid current element + return currentLink != 0; +} + +void cdevSlistCursor::operator = (cdevSlistItem ) +{ + // empty +} + + +//======================================================================== +// Implementation of doubleEndedList +//======================================================================== +cdevDoubleEndedSlist::cdevDoubleEndedSlist() +:cdevSlist() +{ + ptrToLastLink = 0; +} + +cdevDoubleEndedSlist::cdevDoubleEndedSlist(const cdevDoubleEndedSlist &v) +:cdevSlist(v) +{ + ptrToLastLink = v.ptrToLastLink; +} + +void cdevDoubleEndedSlist::add(cdevSlistItem val) +{ + // add method needs to check one special case when the first element + // is added to the list + if (isEmpty()) { + // call parent method + cdevSlist::add (val); + ptrToLastLink = ptrToFirstLink; + } + else{ + // always add to the head + cdevSlist::add(val); + } +} + +void +cdevDoubleEndedSlist::addToEnd(cdevSlistItem val) +{ + //add new value T to the end of the list + // if there is an end, add to it + if(ptrToLastLink != 0) + ptrToLastLink = ptrToLastLink->insert(val); + else{ + // otherwise just add to the front + add (val); + } +} + +void +cdevDoubleEndedSlist::deleteAllValues() +{ + //delete all values from the list + cdevSlist::deleteAllValues(); + ptrToLastLink = 0; +} + +void +cdevDoubleEndedSlist::removeFirst() +{ + //remove the first element from the list + // invoke the parent method + cdevSlist::removeFirst(); + + // only do something if we removed last element + if(isEmpty()) + ptrToLastLink = 0; +} + diff --git a/src/common/cdevSlist.h b/src/common/cdevSlist.h new file mode 100755 index 0000000..06750f0 --- /dev/null +++ b/src/common/cdevSlist.h @@ -0,0 +1,225 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Single Linked List for pointers void * +// +// Note: remove and clean operations on the list +// will only remove link nodes without removal of +// the content inside the nodes. It is callers' +// responsiblity to clean up those contents +// +// This is unsafe C++ practice, use this list at you own risk +// +// Reason for this list: It is very difficult to instantiate +// a template class in a stand alone shared library +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// Revision History: +// cdevSlist.h,v +// Revision 1.2 1996/11/21 17:03:09 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.1 1995/06/30 15:08:00 chen +// single linked list for void * +// +// +#ifndef _CDEV_SLIST_H +#define _CDEV_SLIST_H + +#include +#include + +typedef void* cdevSlistItem; + +//====================================================================== +// class cdevGenSlist +// Single Linked List for void* pointer +//====================================================================== +class cdevSlistLink; +class cdevSlistIterator; +class cdevSlistCursor; + +class CDEV_CLASS_SPEC cdevSlist +{ +public: + // constructors + cdevSlist (void); + cdevSlist (const cdevSlist & source); + virtual ~cdevSlist (void); + + // operations + + // add list item to the beginning of the list + virtual void add(cdevSlistItem value); + + // remove a list item from the list + // return 0: nothing to remove + // return 1: remove success + virtual int remove (cdevSlistItem value); + + // clean up the list. + virtual void deleteAllValues(); + + // return first element of the list + virtual cdevSlistItem firstElement() const; + + // return last element of the list + virtual cdevSlistItem lastElement() const; + + // duplicate ths whole list + virtual cdevSlist* duplicate() const; + + // check whether this list contains a particular item + // return 1: yes. return 0: no + virtual int includes(cdevSlistItem value) const; + + // Is list empty + // return 1: yes. return 0: no + virtual int isEmpty() const; + + // remove first element of the list + virtual void removeFirst(); + + // return number of elements inside the list + virtual int count() const; + + protected: + // data field + cdevSlistLink* ptrToFirstLink; + + // friends + friend class cdevSlistIterator; + // cannot modify list in anyways + friend class cdevSlistCursor; +}; + +//====================================================================== +// class cdevSlistLink +// Single linked list link node +//====================================================================== +class CDEV_CLASS_SPEC cdevSlistLink +{ + public: + // insert a new element following the current value + cdevSlistLink* insert (cdevSlistItem val); + + private: + // constructor + cdevSlistLink (cdevSlistItem linkValue, cdevSlistLink * nextPtr); + + // duplicate + cdevSlistLink* duplicate (void); + + // data areas + cdevSlistItem value; + cdevSlistLink* ptrToNextLink; + + // friends + friend class cdevSlist; + friend class cdevSlistIterator; + friend class cdevSlistCursor; +}; + +//=================================================================== +// class cdevSlistIterator +// implements iterator protocol for linked lists +// also permits removal and addition of elements +//=================================================================== +class CDEV_CLASS_SPEC cdevSlistIterator +{ +public: + // constructor + cdevSlistIterator (cdevSlist& aList); + + // iterator protocol + virtual int init (void); + virtual cdevSlistItem operator () (void); + virtual int operator ! (void); + virtual int operator ++ (void); + virtual void operator = (cdevSlistItem value); + + // new methods specific to list iterators + + // remove current item pointed by the iterator from the list + void removeCurrent(void); + + // add an item to the list before the position pointed by the iterator + void addBefore(cdevSlistItem newValue); + + // add an item to the list after the position pointed by the iterator + void addAfter(cdevSlistItem newValue); + + // search an item and move the iterator to that position + int searchSame(cdevSlistItem &value); + +protected: + // data areas + cdevSlistLink * currentLink; + cdevSlistLink * previousLink; + cdevSlist& theList; +}; + +//=================================================================== +// class cdevSlistCursor +// implements cursor protocol for linked lists +//=================================================================== +class CDEV_CLASS_SPEC cdevSlistCursor +{ +public: + // constructor + cdevSlistCursor (const cdevSlist& aList); + + // iterator protocol + virtual int init (void); + virtual cdevSlistItem operator () (void); + virtual int operator ! (void); + virtual int operator ++ (void); + virtual void operator = (cdevSlistItem value); + + int searchSame (cdevSlistItem &value); + + protected: + // data areas + cdevSlistLink * currentLink; + cdevSlistLink * previousLink; + const cdevSlist& theList; +}; + +//====================================================================== +// class doubleEndedList +// Not only keeps a pointer to first node +// but also keeps a pointer to last node +//====================================================================== +class CDEV_CLASS_SPEC cdevDoubleEndedSlist: public cdevSlist{ + public: + //constructor + cdevDoubleEndedSlist (void); + cdevDoubleEndedSlist (const cdevDoubleEndedSlist &v); + + // override the following methods from the cdevSlist + virtual void add (cdevSlistItem value); + virtual void deleteAllValues (void); + virtual void removeFirst (void); + + // add new element to the end of the list + virtual void addToEnd (cdevSlistItem value); + + protected: + cdevSlistLink *ptrToLastLink; +}; +#endif + + + + + + diff --git a/src/common/cdevSpec.h b/src/common/cdevSpec.h new file mode 100755 index 0000000..f5bd917 --- /dev/null +++ b/src/common/cdevSpec.h @@ -0,0 +1,73 @@ +/*----------------------------------------------------------------------------- + * Copyright (c) 1994,1995 Southeastern Universities Research Association, + * Continuous Electron Beam Accelerator Facility + * + * This software was developed under a United States Government license + * described in the NOTICE file included as part of this distribution. + * + *----------------------------------------------------------------------------- + * + * Description: + * Cdev and API Specification + * + * Every class header file and C interface header should include + * this header + * + * Authors: Jie Chen + * + * Revision History: + * $Log: cdevSpec.h,v $ + * Revision 1.1.1.1 2000/05/23 15:13:04 pal + * cdev_psi_1.7.2 + * + * Revision 1.2 1999/01/15 17:30:20 akers + * Adjustment + * + * Revision 1.1 1999/01/14 17:21:24 chen + * CDEV Class and API Spec Class for WIN32 + * + * + */ +#ifndef _CDEV_SPEC_H +#define _CDEV_SPEC_H + +#if defined (_WIN32) + +#if !defined (DLLIMPORT) +#define DLLIMPORT __declspec(dllimport) +#endif + +#if !defined (DLLEXPORT) +#define DLLEXPORT __declspec(dllexport) +#endif + +#if defined (_CDEV_CORE_EXPORTS_) +#define CDEVAPI DLLEXPORT +#define CDEV_CLASS_SPEC DLLEXPORT +#define CDEVSVC_CLASS_SPEC +#define CDEVSVCAPI +#elif defined (_CDEV_BUILD_SVC) +#define CDEVAPI DLLIMPORT +#define CDEV_CLASS_SPEC DLLIMPORT +#define CDEVSVC_CLASS_SPEC DLLEXPORT +#define CDEVSVCAPI DLLEXPORT +#else +#define CDEVAPI DLLIMPORT +#define CDEV_CLASS_SPEC DLLIMPORT +#define CDEVSVC_CLASS_SPEC +#define CDEVSVCAPI +#endif + +#else /* WIN32 */ + +#define CDEVAPI +#define DLLIMPORT +#define DLLEXPORT +#define CDEV_CLASS_SPEC +#define CDEVSVC_CLASS_SPEC +#define CDEVSVCAPI + +#endif + +#endif + diff --git a/src/common/cdevStrHash.cc b/src/common/cdevStrHash.cc new file mode 100755 index 0000000..ed8ce9a --- /dev/null +++ b/src/common/cdevStrHash.cc @@ -0,0 +1,241 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606 +// Email: coda@cebaf.gov Tel: (804) 249-7101 Fax: (804) 249-7363 +//----------------------------------------------------------------------------- +// +// Description: +// cdevStrHash: cdev hash table keyed by a variable length string +// Open Hash with buckets implemented by single linked lists +// +// Note: void *s are stored inside the table. This class +// will not manage these pointers. Callers have to +// manage these pointers +// +// Note: this is unsafe C++ practice. Use at your own risk +// +// Reason: It is so difficult to use a template class inside +// a shared library. (Cfront based C++ compiler cannot +// instantiate a template class during compilation time +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// Revision History: +// cdevStrHash.cc,v +// Revision 1.5 1997/05/15 17:17:15 chen +// fix bugs for SunOS4 using CC +// +// Revision 1.4 1996/08/26 21:23:18 akers +// Corrected dereference of NULL in getData +// +// Revision 1.3 1996/08/26 21:12:36 akers +// Added getData method to iterator +// +// Revision 1.2 1995/07/05 18:38:48 chen +// add simple str hash function +// +// Revision 1.1 1995/06/30 15:08:29 chen +// string hash table +// +// +#include +#include +#include +#include "cdevStrHash.h" + +//====================================================================== +// A simple string hash fucntion for cdevDevice and caChannel +// Its implementation will be changed for release 1.1 +//====================================================================== +unsigned int cdevStrHashFunc (char *src) +{ + unsigned int hash = 0, g; + + for (int i = 0; src[i] != '\0'; i++){ + hash = (hash << 4) + src[i]; + // assume 32 bit integer + if (g = hash & 0xf0000000){ + hash ^= g >> 24; + hash ^= g; + } + } + return hash; +} + + +//====================================================================== +// class cdevStrHash implementation +//====================================================================== +cdevStrHash::cdevStrHash (unsigned int max, unsigned int (*f)(cdevKeyItem)) +:tablesize(max), hashCode_ (f) +{ +#ifdef _TRACE_OBJECTS + printf ("Create cdevStrHash Class Objects\n"); +#endif + // cdevSlist has a default constructor, so one can create an array of the list + buckets = new cdevSlist[tablesize]; + assert (buckets); +} + +cdevStrHash::~cdevStrHash (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete cdevStrHash Class Objects\n"); +#endif + delete []buckets; + buckets = 0; +} + +int +cdevStrHash::isEmpty() +{ + // if any table is non-empty, return 0 + for (int i = 0; i < tablesize; i++) + if (!buckets[i].isEmpty()) + return 0; + + // all empty + return 1; +} + +void +cdevStrHash::deleteAllValues() +{ + // delete all values from a hash table + // clear the elements from each of teh buckets + for (int i = 0; i < tablesize; i++) + buckets[i].deleteAllValues(); +} + +unsigned int +cdevStrHash::hash(const cdevKeyItem& key) const +{ + // return hashed value of key + return ((*hashCode_)(key) % tablesize); +} + +void +cdevStrHash::add (cdevKeyItem key, cdevHashItem newele) +{ + buckets[hash (key)].add (newele); +} + +int +cdevStrHash::remove (cdevKeyItem key, cdevHashItem ele) +{ + return (buckets[hash (key)].remove (ele)); +} + +int +cdevStrHash::find (cdevKeyItem key, cdevHashItem ele) const +{ + return buckets[hash (key)].includes(ele); +} + +cdevSlist& +cdevStrHash::bucketRef (cdevKeyItem key) +{ + return (buckets[hash (key)]); +} + +//====================================================================== +// class cdevStrHashIterator implementation +//====================================================================== +cdevStrHashIterator::cdevStrHashIterator (cdevStrHash& v) +:base(v), currentIndex(0), itr(0) +{ +#ifdef _TRACE_OBJECTS + printf ("Create cdevStrHashIterator Class Object \n"); +#endif + // no further initialization +} + +cdevStrHashIterator::~cdevStrHashIterator (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete cdevStrHashIterator Class Object \n"); +#endif + currentIndex = 0; + if (itr) + delete itr; +} + +int +cdevStrHashIterator::init (void) +{ + // initialize iterator, + // start search with first bucket + currentIndex = 0; + itr = 0; + return getNextIterator(); +} + +cdevHashItem +cdevStrHashIterator::operator() (void) +{ + // return current element + return itr!=NULL?(*itr)():NULL; +} + +cdevHashItem cdevStrHashIterator::getData (void) +{ + // return current element + return itr!=NULL?(*itr)():NULL; +} + +int +cdevStrHashIterator::operator ! (void) +{ + // test if there is a current element + return itr != 0; +} + +int +cdevStrHashIterator::operator ++ (void) +{ + // see if current iterator can be advanced + if (itr && ++(*itr)) + return 1; + + // if not, get next iterator + currentIndex++; + return getNextIterator(); +} + +void +cdevStrHashIterator::operator = (cdevHashItem val) +{ + // change the current value + (*itr) = val; +} + +int +cdevStrHashIterator::getNextIterator (void) +{ + // if there is an old iterator, delete it + if (itr != 0) + delete itr; + + // now search for a new one + for (; currentIndex < base.tablesize; currentIndex++){ + // generate a new iterator at the current point + itr = new cdevSlistIterator (base.buckets[currentIndex]); + assert(itr != 0); + + // if it has at least one element, we're done + if (itr->init()) + return 1; + + // otherwise delete it, try again + delete itr; + } + // all out of iterators, can quit + itr = 0; + return 0; +} diff --git a/src/common/cdevStrHash.h b/src/common/cdevStrHash.h new file mode 100755 index 0000000..bde8d6f --- /dev/null +++ b/src/common/cdevStrHash.h @@ -0,0 +1,138 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +// CEBAF Data Acquisition Group, 12000 Jefferson Ave., Newport News, VA 23606 +// Email: coda@cebaf.gov Tel: (804) 249-7101 Fax: (804) 249-7363 +//----------------------------------------------------------------------------- +// +// Description: +// cdevStrHash: cdev hash table keyed by a variable length string +// Open Hash with buckets implemented by single linked lists +// +// Note: void *s are stored inside the table. This class +// will not manage these pointers. Callers have to +// manage these pointers +// +// Note: this is unsafe C++ practice. Use at your own risk +// +// Reason: It is so difficult to use a template class inside +// a shared library. (Cfront based C++ compiler cannot +// instantiate a template class during compilation time +// +// Author: Jie Chen +// CEBAF Data Acquisition Group +// +// Revision History: +// cdevStrHash.h,v +// Revision 1.3 1996/08/26 21:12:38 akers +// Added getData method to iterator +// +// Revision 1.2 1995/07/05 18:38:30 chen +// add simple str hash function +// +// Revision 1.1 1995/06/30 15:08:42 chen +// string hash table +// +// +#ifndef _CDEV_STR_HASH_H +#define _CDEV_STR_HASH_H + +#include + +//====================================================================== +// One simple string hash function +// This hash function is used in cdevDevice and caChannel. +// It returns integer value between 0 to MAX_INTEGER_VALUE +// and this value will be moded with the size of the hash +// table. +// It may be changed to a different hash function in +// release 1.1 +//====================================================================== +extern CDEVAPI unsigned int cdevStrHashFunc (char *str); + +typedef char* cdevKeyItem; +typedef void* cdevHashItem; + +//====================================================================== +// class cdevStrHash +// collection of buckets indexed by hashed values +//====================================================================== +class cdevStrHashIterator; + +class CDEV_CLASS_SPEC cdevStrHash +{ +public: + // constructor + // construct a table with entry max and hash function *f + // hash function return any integer from 0 to MAX_INT_VALUE + cdevStrHash (unsigned int max, unsigned int (*f)(cdevKeyItem)); + // destructor + virtual ~cdevStrHash (void); + + // operations + + // is the table empty: return 1: yes. return 0: no + virtual int isEmpty(); + + // clear the elements of the set + virtual void deleteAllValues(); + + // add an element to the collection + virtual void add (cdevKeyItem key, cdevHashItem ele); + + // test to see whether this hash table includes one particular element + virtual int find (cdevKeyItem key, cdevHashItem ele) const; + + // remove an element. return 0: ele is not inside table. return 1: success + virtual int remove (cdevKeyItem key, cdevHashItem ele); + + // return a reference to a particular bucket according to the key + cdevSlist& bucketRef (cdevKeyItem key); + + protected: + friend class cdevStrHashIterator; + + // the actual table itself is a vector of buckets + const unsigned int tablesize; + cdevSlist* buckets; + + // convert key into unsigned integer value in range + unsigned int hash(const cdevKeyItem& key) const; + + private: + unsigned int (*hashCode_)(cdevKeyItem); +}; + +//====================================================================== +// class cdevStrHashIterator +// iterator protocol for hash tables +//====================================================================== +class CDEV_CLASS_SPEC cdevStrHashIterator +{ +public: + // constructor and destructor + cdevStrHashIterator (cdevStrHash& v); + ~cdevStrHashIterator (void); + + // iterator protocol + int init (void); + cdevHashItem operator ()(void); + cdevHashItem getData (void); + int operator ! (void); + int operator ++(void); + void operator = (cdevHashItem value); + +protected: + cdevStrHash& base; + unsigned int currentIndex; + // Single iterator within a bucket + cdevSlistIterator* itr; + // getNextIterator used to set internal iterator pointer + // return 1: got it. return 0: no more iterator + int getNextIterator (void); +}; +#endif diff --git a/src/common/cdevTimeValue.cc b/src/common/cdevTimeValue.cc new file mode 100755 index 0000000..be0117a --- /dev/null +++ b/src/common/cdevTimeValue.cc @@ -0,0 +1,279 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// C++ Class for time value +// +// Author: Jie Chen +// +// Revision History: +// cdevTimeValue.cc,v +// Revision 1.2 1998/02/10 18:04:57 chen +// add cdevSystem timer handler +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#include "cdevTimeValue.h" + + +const long ONE_SECOND = 1000000L; + +const cdevTimeValue cdevTimeValue::zero; + +cdevTimeValue::cdevTimeValue (long sec, long usec) +:tv_sec_ (sec), tv_usec_ (usec) +{ + this->normalize (); +} + +#ifdef _WIN32 +void cdevTimeValue::set (const _timeb &tv) +{ + this->tv_sec_ = tv.time; + this->tv_usec_ = tv.millitm; + this->normalize (); +} +#endif + +void cdevTimeValue::set ( const timeval &tv ) +{ + this->tv_sec_ = tv.tv_sec; + this->tv_usec_ = tv.tv_usec; + this->normalize (); +} + +#ifdef _WIN32 +cdevTimeValue::cdevTimeValue ( const _timeb &tv ) +{ + this->set(tv); +} +#endif + +/* Initializes the cdevTimeValue object from a timeval */ +cdevTimeValue::cdevTimeValue (const timeval &tv) +{ + this->set (tv); +} + +/* Initializes the cdevTimeValue object from another cdevTimeValue */ + +cdevTimeValue::cdevTimeValue (const cdevTimeValue &tv) +: tv_sec_ (tv.tv_sec_), tv_usec_ (tv.tv_usec_) +{ + // empty +} + +// assignment operator +cdevTimeValue& +cdevTimeValue::operator = (const cdevTimeValue& tv) +{ + if (this != &tv){ + tv_sec_ = tv.tv_sec_; + tv_usec_ = tv.tv_usec_; + } + return *this; +} + +// Initialize the cdevTimeValue Object from a float value +cdevTimeValue::cdevTimeValue (double seconds) +{ + double sec = floor (seconds); + long usec = (long)((seconds - sec)*ONE_SECOND); + tv_sec_ = (long)sec; + tv_usec_ = usec; +} + +void +cdevTimeValue::normalize (void) +{ + while ((this->tv_usec_ >= ONE_SECOND) + || (this->tv_sec_ < 0 && this->tv_usec_ > 0 )){ + this->tv_usec_ -= ONE_SECOND; + this->tv_sec_++; + } + + while ((this->tv_usec_ <= -ONE_SECOND) + || (this->tv_sec_ > 0 && this->tv_usec_ < 0)){ + this->tv_usec_ += ONE_SECOND; + this->tv_sec_--; + } +} + +/* Returns number of seconds. */ +long +cdevTimeValue::sec (void) const +{ + return this->tv_sec_; +} + +/* Sets the number of seconds. */ + +void +cdevTimeValue::sec (long sec) +{ + this->tv_sec_ = sec; +} + +/* Returns number of micro-seconds. */ + +long +cdevTimeValue::usec (void) const +{ + return this->tv_usec_; +} + +/* Sets the number of micro-seconds. */ + +void +cdevTimeValue::usec (long usec) +{ + this->tv_usec_ = usec; +} + +/* Returns the value of the object as a timeval. */ + +#ifdef _WIN32 +cdevTimeValue::operator _timeb () const +{ + _timeb tv; + tv.time = this->tv_sec_; + tv.millitm = this->tv_usec_; + return tv; +} +#endif + +cdevTimeValue::operator timeval () const +{ + timeval tv; + tv.tv_sec = this->tv_sec_; + tv.tv_usec = this->tv_usec_; + return tv; +} + +/* return the value of the object a double */ +cdevTimeValue::operator double () const +{ + double tval = this->tv_sec_ + this->tv_usec_ / (double)(ONE_SECOND); + return tval; +} + +/* return a new value with increment */ +void +cdevTimeValue::operator += (const cdevTimeValue& val) +{ + tv_sec_ += val.tv_sec_; + tv_usec_ += val.tv_usec_; + normalize (); +} + +void +cdevTimeValue::operator -= (const cdevTimeValue& val) +{ + tv_sec_ -= val.tv_sec_; + tv_usec_ -= val.tv_usec_; + normalize (); +} + +/* Adds two cdevTimeValue objects together, returns the sum. */ + +cdevTimeValue +operator + (cdevTimeValue src1, cdevTimeValue src2) +{ + cdevTimeValue sum (src1.tv_sec_ + src2.tv_sec_, src1.tv_usec_ + src2.tv_usec_); + + sum.normalize (); + return sum; +} + +/* Subtracts two cdevTimeValue objects, returns the difference. */ + +cdevTimeValue +operator - (cdevTimeValue src1, cdevTimeValue src2) +{ + cdevTimeValue delta (src1.tv_sec_ - src2.tv_sec_, src1.tv_usec_ - src2.tv_usec_); + + delta.normalize (); + return delta; +} + +/* True if tv1 > tv2. */ + +int +operator > (cdevTimeValue src1, cdevTimeValue src2) +{ + if (src1.tv_sec_ > src2.tv_sec_) + return 1; + else if (src1.tv_sec_ == src2.tv_sec_ && src1.tv_usec_ > src2.tv_usec_) + return 1; + else + return 0; +} + +/* True if tv1 >= tv2. */ + +int +operator >= (cdevTimeValue src1, cdevTimeValue src2) +{ + if (src1.tv_sec_ > src2.tv_sec_) + return 1; + else if (src1.tv_sec_ == src2.tv_sec_ && src1.tv_usec_ >= src2.tv_usec_) + return 1; + else + return 0; +} + +/* True if tv1 < tv2. */ + +int +operator < (cdevTimeValue src1, cdevTimeValue src2) +{ + return src2 > src1; +} + +/* True if tv1 >= tv2. */ + +int +operator <= (cdevTimeValue src1, cdevTimeValue src2) +{ + return src2 >= src1; +} + +/* True if tv1 == tv2. */ + +int +operator == (cdevTimeValue src1, cdevTimeValue src2) +{ + return src1.tv_sec_ == src2.tv_sec_ && src1.tv_usec_ == src2.tv_usec_; +} + +/* True if tv1 != tv2. */ + +int +operator != (cdevTimeValue src1, cdevTimeValue src2) +{ + return !(src1 == src2); +} + +cdevTimeValue +cdevTimeValue::currentTime (void) +{ + cdevTimeValue tv; + +#ifdef _WIN32 + _timeb cur_time; + _ftime (&cur_time); +#else + timeval cur_time; + ::gettimeofday (&cur_time, 0); +#endif + tv.set (cur_time); + return tv; +} diff --git a/src/common/cdevTimeValue.h b/src/common/cdevTimeValue.h new file mode 100755 index 0000000..57cc03c --- /dev/null +++ b/src/common/cdevTimeValue.h @@ -0,0 +1,86 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// C++ Class for timeval structure +// +// Author: Jie Chen +// +// Revision History: +// cdevTimeValue.h,v +// Revision 1.2 1998/02/10 18:04:57 chen +// add cdevSystem timer handler +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#ifndef _CDEV_TIME_VALUE_H +#define _CDEV_TIME_VALUE_H + +#include +#include + +#ifdef _WIN32 + #include + #include + #include +#else + #include +#endif + +class CDEV_CLASS_SPEC cdevTimeValue +{ + public: + cdevTimeValue (long sec = 0, long usec = 0); + cdevTimeValue (double sec); +#ifdef _WIN32 + cdevTimeValue (const struct _timeb &t); +#endif + cdevTimeValue (const timeval &t); + cdevTimeValue (const cdevTimeValue &tv); + cdevTimeValue& operator = (const cdevTimeValue& tv); + +#ifdef _WIN32 + void set (const struct _timeb &t); +#endif + + void set (const timeval &t); + long sec (void) const; + void sec (long sec); + long usec (void) const; + void usec (long usec); + operator double () const; +#ifdef _WIN32 + operator struct _timeb () const; +#endif + operator timeval () const; + + void operator += (const cdevTimeValue& val); + void operator -= (const cdevTimeValue& val); + + friend cdevTimeValue operator + (cdevTimeValue tv1, cdevTimeValue tv2); + friend cdevTimeValue operator - (cdevTimeValue tv1, cdevTimeValue tv2); + friend int operator < (cdevTimeValue tv1, cdevTimeValue tv2); + friend int operator > (cdevTimeValue tv1, cdevTimeValue tv2); + friend int operator <= (cdevTimeValue tv1, cdevTimeValue tv2); + friend int operator >= (cdevTimeValue tv1, cdevTimeValue tv2); + friend int operator == (cdevTimeValue tv1, cdevTimeValue tv2); + friend int operator != (cdevTimeValue tv1, cdevTimeValue tv2); + + static const cdevTimeValue zero; + static cdevTimeValue currentTime (void); + + private: + void normalize (void); + + long tv_sec_; + long tv_usec_; +}; +#endif diff --git a/src/common/cdevTimerHandler.h b/src/common/cdevTimerHandler.h new file mode 100755 index 0000000..23a5fc0 --- /dev/null +++ b/src/common/cdevTimerHandler.h @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevTimerHandler Class +// +// This class is a base class for handling timer based event. +// Derived classes implement the real function. +// +// Author: Jie Chen +// +// Revision History: +// cdevTimerHandler.h,v +// Revision 1.1 1998/02/10 18:04:57 chen +// add cdevSystem timer handler +// +// +// +#ifndef _CDEV_TIMER_HANDLER_H +#define _CDEV_TIMER_HANDLER_H + +#include + +class cdevTimerHandler +{ +public: + // constructor + cdevTimerHandler (void) {} + // destructor + virtual ~cdevTimerHandler (void) {} + + virtual int timerCallback (double /* time */, + const void* /* arg */ = 0) {return 0;} + // PURPOSE: this function is called when timer is expired + // REQUIRE: none + // PROMISE: if return -1: all timers associated with this handler + // will be removed. return 0: everything is ok. + + virtual const char* className (void) const {return "cdevTimerHandler";} + +private: + // deny access to copy and assignment operator + cdevTimerHandler (const cdevTimerHandler& handler); + cdevTimerHandler& operator = (const cdevTimerHandler& handler); + +}; +#endif diff --git a/src/common/cdevTimerQueue.cc b/src/common/cdevTimerQueue.cc new file mode 100755 index 0000000..9caef9a --- /dev/null +++ b/src/common/cdevTimerQueue.cc @@ -0,0 +1,214 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of cdevTimerQueue Class +// +// Author: Jie Chen +// +// Revision History: +// cdevTimerQueue.cc,v +// Revision 1.1 1998/02/10 18:04:58 chen +// add cdevSystem timer handler +// +// +// +#include "cdevTimerQueue.h" + +//===================================================================== +// Implementation of cdevTimerQNode Class +//===================================================================== +cdevTimerQNode::cdevTimerQNode (cdevTimerHandler* h, + const void* arg, + const cdevTimeValue& t, + const cdevTimeValue& i, + int id) +:handler_ (h), arg_ (arg), timer_ (t), interval_ (i), tid_ (id) +{ +#ifdef _TRACE_OBJECTS + printf ("Create cdevTimerQNode Class Object\n"); +#endif + // empty +} + +//===================================================================== +// Implementation of cdevTimerQueue Class +//===================================================================== +cdevTimerQueue::cdevTimerQueue (void) +:queue_ (), timerId_ (0) +{ +#ifdef _TRACE_OBJECTS + printf ("Create cdevTimerQueue Class Object\n"); +#endif + // empty +} + +cdevTimerQueue::~cdevTimerQueue (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete cdevTimerQueue Class Object\n"); +#endif + cdevSlistIterator ite (queue_); + cdevTimerQNode* tnode = 0; + + for (ite.init(); !ite; ++ite) { + tnode = (cdevTimerQNode *) ite (); + delete tnode; + } + queue_.deleteAllValues (); +} + +int +cdevTimerQueue::isEmpty (void) const +{ + return queue_.isEmpty (); +} + +const cdevTimeValue& +cdevTimerQueue::earliestTime (void) const +{ + cdevTimerQNode* tnode = (cdevTimerQNode *)queue_.firstElement (); + return tnode->timer_; +} + +void +cdevTimerQueue::reschedule (cdevTimerQNode* node) +{ + cdevTimerQNode* tnode = 0; + if (queue_.isEmpty () || node->timer_ < earliestTime ()) { + // put in the beginning of queue + queue_.add (node); + } + else { + cdevSlistIterator ite (queue_); + int found = 0; + + for (ite.init (); !ite; ++ite) { + tnode = (cdevTimerQNode *) ite (); + if (node->timer_ > tnode->timer_) { + ite.addAfter (node); + found = 1; + break; + } + } + + // add to the end of the queue + if (!found) + ite.addAfter (node); + } +} + +int +cdevTimerQueue::scheduleTimer (cdevTimerHandler* h, + const void* arg, + const cdevTimeValue& future_time, + const cdevTimeValue& interval) +{ + timerId_ ++; + + cdevTimerQNode* tnode = 0; + cdevTimerQNode* qnode = new cdevTimerQNode (h, arg, + future_time, + interval, timerId_); + + if (queue_.isEmpty () || future_time < earliestTime ()) + queue_.add (qnode); + else { + // find right place to put this node + cdevSlistIterator ite (queue_); + int found = 0; + + for (ite.init (); !ite; ++ite) { + tnode = (cdevTimerQNode *) ite (); + if (future_time > tnode->timer_) { + ite.addAfter (qnode); + found = 1; + break; + } + } + + // add to the end of the queue + if (!found) + ite.addAfter (qnode); + } + return timerId_; +} + +int +cdevTimerQueue::cancel (int id) +{ + cdevSlistIterator ite (queue_); + cdevTimerQNode* tnode = 0; + + for (ite.init (); !ite; ++ite) { + tnode = (cdevTimerQNode *) ite (); + if (tnode->tid_ == id) { + delete tnode; + ite.removeCurrent (); + return 0; + } + } + return -1; +} + +int +cdevTimerQueue::cancel (cdevTimerHandler* handler) +{ + cdevSlistIterator ite (queue_); + cdevTimerQNode* tnode = 0; + + for (ite.init (); !ite; ++ite) { + tnode = (cdevTimerQNode *) ite (); + if (tnode->handler_ == handler) { + delete tnode; + ite.removeCurrent (); + return 0; + } + } + return -1; +} + +int +cdevTimerQueue::expire (const cdevTimeValue& curTime) +{ + while (1) { + // all timers have been called + if (queue_.isEmpty () || earliestTime () > curTime ) + break; + + cdevTimerQNode* fnode = (cdevTimerQNode *)queue_.firstElement (); + cdevTimerHandler* handler = fnode->handler_; + const void* arg = fnode->arg_; + int freemem = 1; + int res; + + // dequeue + queue_.removeFirst (); + + if (fnode->interval_ > cdevTimeValue::zero) { + do + fnode->timer_ += fnode->interval_; + while (fnode->timer_ <= curTime); + + reschedule (fnode); + freemem = 0; + } + + res = handler->timerCallback ((double)curTime, arg); + + if (res == -1) + cancel (handler); + + if (freemem) + delete fnode; + } + return 0; +} + + diff --git a/src/common/cdevTimerQueue.h b/src/common/cdevTimerQueue.h new file mode 100755 index 0000000..0718a3d --- /dev/null +++ b/src/common/cdevTimerQueue.h @@ -0,0 +1,128 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevTimerQueue Class +// +// Author: Jie Chen +// +// Revision History: +// cdevTimerQueue.h,v +// Revision 1.1 1998/02/10 18:04:58 chen +// add cdevSystem timer handler +// +// +// +#ifndef _CDEV_TIMER_QUEUE_H +#define _CDEV_TIMER_QUEUE_H + +#include +#include +#include + +class cdevTimerQueue; + +class cdevTimerQNode +{ +private: + + friend class cdevTimerQueue; + + cdevTimerQNode (cdevTimerHandler* h, + const void* arg, + const cdevTimeValue& t, + const cdevTimeValue& i, + int id); + + // data area + cdevTimerHandler* handler_; + + // user argument + const void* arg_; + + // first time interval to expire + cdevTimeValue timer_; + + // timer interval: if this is not zero this holds the time until the next + // timeout + cdevTimeValue interval_; + + // int timer id + int tid_; +}; + + +class CDEV_CLASS_SPEC cdevTimerQueue +{ +public: + // constructor + cdevTimerQueue (void); + // destructor + virtual ~cdevTimerQueue (void); + + int isEmpty (void) const; + // PURPOSE: check whether this queue is empty or not + // REQUIRE: nothing + // PROMISE: return 1, empty, 0, not empty + + const cdevTimeValue& earliestTime (void) const; + // PURPOSE: return earliestTime in the timer queue + // REQUIRE: nothing + // PROMISE: time value denoted the earliest time in the queue + + int scheduleTimer (cdevTimerHandler* handler, + const void* arg, + const cdevTimeValue& delay, + const cdevTimeValue& interval = cdevTimeValue::zero); + // PURPOSE: Schedule an that will expire after + // amount of time. If it expires then is passed in as the value to + // the 's callback method. If + // is != to then it is used to + // reschedule the automatically. This method + // returns a timer handle that uniquely identifies the + // in an internal list. This timer handle can be + // used to cancel an before it expires. The + // cancellation ensures that timer_ids are unique up to values of + // greater than 2 billion timers. As long as timers don't stay + // around longer than this there should be no problems with + // accidentally deleting the wrong timer. + + int cancel (cdevTimerHandler* handler); + // PURPOSE: cancel all timers associated with handler + // REQUIRE: handler != 0 + // PROMISE: all timer is canceled. return 0 + + int cancel (int id); + // PURPOSE: cancel a single timer with id + // REQUIRE: id must be valid + // PROMISE: if id is found, the timer is canceled. + + int expire (const cdevTimeValue& current_time); + // PURPOSE: run the method for all timers whose values are + // <= current_time + +private: + void reschedule (cdevTimerQNode* node); + // reschedule a "interval" timer + + cdevSlist queue_; + // real linked list as a queue + + int timerId_; + // run time timer id +}; +#endif + + + + + + + + diff --git a/src/common/shObjLoader.cc b/src/common/shObjLoader.cc new file mode 100755 index 0000000..5a2ec3d --- /dev/null +++ b/src/common/shObjLoader.cc @@ -0,0 +1,385 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// shObjLoader class (implementation) +// +// Author: Jie Chen +// +// Revision History: +// shObjLoader.cc,v +// Revision 1.7 1996/03/22 16:31:59 chen +// support solaris +// +// Revision 1.6 1995/11/14 17:33:46 chen +// fix to work under irix5.3 +// +// Revision 1.5 1995/10/26 14:33:18 akers +// Removal of Warnings +// +// Revision 1.4 1995/10/18 17:45:00 chen +// To work under SunOs +// +// Revision 1.3 1995/10/17 13:25:25 chen +// Change load (int flag) to load (void) +// +// Revision 1.2 1995/06/30 15:02:13 chen +// use cxx_shload +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#include +#include +#include +#include "shObjLoader.h" + +shObjLoader::shObjLoader (char *path) +{ +#ifdef _TRACE_OBJECTS + printf("Create shObjLoader class \n"); +#endif + libName_ = new char[::strlen (path) + 1]; + ::strcpy (libName_, path); +#ifdef __hpux + libHandler_ = 0; + desc_ = 0; +#endif + +#if defined (sunos4) || defined (sgi) || defined (solaris) || defined (aix) || defined (__linux) + libHandler_ = 0; +#endif + +#if defined (_WIN32) + libHandler_ = NULL; +#endif +} + +shObjLoader::~shObjLoader (void) +{ +#ifdef _TRACE_OBJECTS + printf("Delete shObjLoader class \n"); +#endif + this->close (); +} + +int +shObjLoader::open (char *name) +{ + if (libName_){ + delete []libName_; + libName_ = 0; + } + libName_ = new char[::strlen(name) + 1]; + ::strcpy (libName_, name); + return 0; +} + + +int +shObjLoader::load (void) +{ +#ifdef SHOBJ +#ifdef __hpux + + if ((libHandler_ = HP_SHOBJ_LOADER(libName_, BIND_IMMEDIATE | BIND_VERBOSE, 0)) == 0){ + perror ("shl_load: error loading library"); + return -1; + } +#endif // __hpux + +#ifdef sunos4 + libHandler_ = ::dlopen (libName_, RTLD_LAZY); +#endif + +#if defined (sgi) || defined (solaris) || defined (aix) || defined (__linux) + libHandler_ = ::dlopen (libName_, RTLD_NOW); +#endif + +#if defined (sunos4) || defined (sgi) || defined (solaris) || defined (aix) || defined (__linux) + if (libHandler_ == 0) { + #ifdef __linux + fprintf(stdout, "Attempt to load library %s failed\n%s\n", libName_, dlerror()); + #endif + perror ("dlopen: error loading library"); + return -1; + } +#endif // endif sun or sgi or linux + +#if defined (_WIN32) + libHandler_ = LoadLibrary (libName_); + if (libHandler_ == NULL) { + cdevSystem::defaultSystem().reportError( + CDEV_SEVERITY_ERROR, "shObjLoader", NULL, + "Cannot open dll library %s - ErrorCode %i\n", libName_, GetLastError()); + return -1; + } +#endif + + return 0; +#else + return 0; +#endif // end if SHOBJ +} + +int +shObjLoader::findProcedureSym +#ifdef SHOBJ + (const char * sym, void** value) +#else + (const char *, void **) +#endif +{ +#ifdef SHOBJ + +#ifdef __hpux + int status = ::shl_findsym (&libHandler_, sym, TYPE_PROCEDURE, + (void *)value); + return status; +#endif + +#if defined (sunos4) || defined (sgi) || defined (solaris) || defined (aix) || defined (__linux) + int status = 0; + void *val = 0; + val = ::dlsym (libHandler_, (char *)sym); + if (val == 0) { + status = -1; + *value = 0; + } + else + *value = val; + return status; +#endif // sun or sgi or linux + +#if defined (_WIN32) + int status = 0; + *value = (void *)GetProcAddress (libHandler_, sym); + if (*value == NULL) { + cdevSystem::defaultSystem().reportError( + CDEV_SEVERITY_ERROR, "shObjLoader", NULL, + "Cannot find function %s\n", sym); + FreeLibrary (libHandler_); + status = -1; + } + return status; +#endif + +#else + return 0; +#endif +} + +#ifdef __hpux +int +shObjLoader::findDataSym +#ifdef SHOBJ + (const char * sym, void* value) +#else + (const char *, void *) +#endif +{ +#ifdef SHOBJ + int status = :: shl_findsym (&libHandler_, sym, TYPE_DATA, value); + return status; +#else + return 0; +#endif +} + +int +shObjLoader::findSym +#ifdef SHOBJ + (const char * sym, void* value) +#else + (const char *, void *) +#endif +{ +#ifdef SHOBJ + int status = :: shl_findsym (&libHandler_, sym, TYPE_UNDEFINED, value); + return status; +#else + return 0; +#endif +} + +unsigned long +shObjLoader::textStartAddr (void) +{ +#ifdef SHOBJ + if (!libHandler_){ + cdevSystem::defaultSystem().reportError( + CDEV_SEVERITY_ERROR, "shObjLoader", NULL, + "No shared library handler yet."); + return 0; + } + if (!desc_){ + int status = shl_gethandle (libHandler_, &desc_); + if (status == -1){ + cdevSystem::defaultSystem().reportError( + CDEV_SEVERITY_ERROR, "shObjLoader", NULL, + "Invalid library handle."); + desc_ = 0; + return 0; + } + return desc_->tstart; + } +#endif + return 0; +} + +unsigned long +shObjLoader::textEndAddr (void) +{ +#ifdef SHOBJ + if (!libHandler_){ + cdevSystem::defaultSystem().reportError( + CDEV_SEVERITY_ERROR, "shObjLoader", NULL, + "No shared library handler yet."); + return 0; + } + if (!desc_){ + int status = shl_gethandle (libHandler_, &desc_); + if (status == -1){ + cdevSystem::defaultSystem().reportError( + CDEV_SEVERITY_ERROR, "shObjLoader", NULL, + "Invalid library handle."); + desc_ = 0; + return 0; + } + return desc_->tend; + } +#endif + return 0; +} + +unsigned long +shObjLoader::dataStartAddr (void) +{ +#ifdef SHOBJ + if (!libHandler_){ + cdevSystem::defaultSystem().reportError( + CDEV_SEVERITY_ERROR, "shObjLoader", NULL, + "No shared library handler yet."); + return 0; + } + if (!desc_){ + int status = shl_gethandle (libHandler_, &desc_); + if (status == -1){ + cdevSystem::defaultSystem().reportError( + CDEV_SEVERITY_ERROR, "shObjLoader", NULL, + "Invalid library handle."); + desc_ = 0; + return 0; + } + return desc_->dstart; + } +#endif + return 0; +} + +unsigned long +shObjLoader::dataEndAddr (void) +{ +#ifdef SHOBJ + if (!libHandler_){ + cdevSystem::defaultSystem().reportError( + CDEV_SEVERITY_ERROR, "shObjLoader", NULL, + "No shared library handler yet."); + return 0; + } + if (!desc_){ + int status = shl_gethandle (libHandler_, &desc_); + if (status == -1){ + cdevSystem::defaultSystem().reportError( + CDEV_SEVERITY_ERROR, "shObjLoader", NULL, + "Invalid library handle."); + desc_ = 0; + return 0; + } + return desc_->dend; + } +#endif + return 0; +} +#endif // __hpux + +const char * +shObjLoader::filename (void) +{ +#ifdef SHOBJ + if (libHandler_ == 0){ + cdevSystem::defaultSystem().reportError( + CDEV_SEVERITY_ERROR, "shObjLoader", NULL, + "No shared library handler yet."); + return 0; + } + return libName_; +#else + return 0; +#endif +} + +int +shObjLoader::close (void) +{ +#ifdef SHOBJ + if (libHandler_){ +#ifdef __hpux + int status = HP_SHOBJ_UNLOADER (libHandler_); + desc_ = 0; +#endif // __hpux + +#if defined (sunos4) || defined (sgi) || defined (solaris) || defined (aix) || defined (__linux) + int status = ::dlclose (libHandler_); +#endif // sun or sgi + +#if defined (_WIN32) + int status; + if (!FreeLibrary (libHandler_)) + status = -1; + else + status = 0; +#endif + + libHandler_ = 0; + + if (libName_) + delete []libName_; + libName_ = 0; + return status; + } + else + return 0; +#endif + return 0; +} + +#ifdef SHOBJ +#include +// trick dld to load all these math functions +void touch_math (void) +{ + double x = sin (1.0); + x = cos (1.0); + x = tan (1.0); + x = asin (1.0); + x = acos (1.0); + x = atan (1.0); + x = cosh (1.0); + x = sinh (1.0); + x = tanh (1.0); + x = log (1.0); + x = exp (1.0); + x = sqrt (1.0); + x = log10 (1.0); + x = ceil (1.0); + x = floor (1.0); +} +#endif diff --git a/src/common/shObjLoader.h b/src/common/shObjLoader.h new file mode 100755 index 0000000..3144695 --- /dev/null +++ b/src/common/shObjLoader.h @@ -0,0 +1,169 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// shObjLoader class (for hp ,sun (SunOs 4.x) , sgi (irix), +// solaris 2.x and linux only) +// +// Author: Jie Chen +// +// Revision History: +// shObjLoader.h,v +// Revision 1.6 1996/03/22 16:32:09 chen +// support solaris +// +// Revision 1.5 1995/11/14 17:35:17 chen +// better header +// +// Revision 1.4 1995/11/14 17:33:37 chen +// fix to work under irix5.3 +// +// Revision 1.3 1995/10/18 17:45:06 chen +// To work under SunOs +// +// Revision 1.2 1995/10/17 13:25:18 chen +// Change load (int flag) to load (void) +// +// Revision 1.1.1.1 1995/06/16 17:14:02 epics +// initial import of cdev +// +// +#ifndef _SH_OBJ_LOADER_H +#define _SH_OBJ_LOADER_H + +#include +#include + +#ifdef __hpux + #ifdef _CENTERLINE + #include + #define HP_SHOBJ_LOADER ::shl_load + #define HP_SHOBJ_UNLOADER ::shl_unload + #elif (_OS_MAJOR==9 || (_OS_MAJOR==10 && _OS_MINOR==10)) + #include + #define HP_SHOBJ_LOADER ::cxxshl_load + #define HP_SHOBJ_UNLOADER ::cxxshl_unload + #else + #include + #define HP_SHOBJ_LOADER ::shl_load + #define HP_SHOBJ_UNLOADER ::shl_unload + #endif +#endif + +#ifdef sunos4 +// sun header file dlfunc.h is not defined for cplusplus +extern "C" +{ +void *dlopen (char* path, int mode); +void *dlsym (void* handle, char* symbol); +char *dlerror (void); +int dlclose (void* handle); +}; +#define RTLD_LAZY 1 +#endif + +#if defined (sgi) || defined (solaris) || defined (aix) || defined (__linux) +#include +#endif + +#if defined (_WIN32) +#include + +#ifndef SHOBJ +#define SHOBJ 1 +#endif + +#endif + +#include + +class shObjLoader +{ +public: + //constructors and destructor + shObjLoader (char *path); + virtual ~shObjLoader (void); + + virtual int open (char *name); + // PURPOSE: open a shared library by a given name + // REQUIRE: name != 0 + // PROMISE: library path name will be stored + + virtual int load (void); + // PURPOSE: load a shared library in verbose mode if possible + // REQUIRE: call open first + // PROMISE: return 0: success loaded. return -1: load failed + + virtual int findProcedureSym (const char * sym, void** value); + // PURPOSE: find procedure address given by symbol + // REQUIRE: call load first + // PROMISE: value will be the address. return 0: success, -1: failure + +#ifdef __hpux + virtual int findDataSym (const char * sym, void * value); + // PURPOSE: find data address given by symbol + // REQUIRE: call load first + // PROMISE: value will be the address + + virtual int findSym (const char * sym, void * value); + // PURPOSE: find address given by symbol + // REQUIRE: call load first + // PROMISE: value will be the address. return 0: success, -1: failure + + unsigned long textStartAddr (void); + // PURPOSE: find text section start address + // REQUIRE: call load first + // PROMISE: return address, 0: failure + + unsigned long textEndAddr (void); + // PURPOSE: find text section end address + // REQUIRE: call load first + // PROMISE: return address, 0: failure + + unsigned long dataStartAddr (void); + // PURPOSE: find data section start address + // REQUIRE: call load first + // PROMISE: return address, 0: failure + + unsigned long dataEndAddr (void); + // PURPOSE: find data section end address + // REQUIRE: call load first + // PROMISE: return address, 0: failure +#endif // end __hpux + + const char *filename (void); + // PURPOSE: loaded shared library path name + // REQUIRE: nothing + // PROMISE: 0: means nothing loaded + + virtual int close (void); + // PURPOSE: remove shared library from memory + // REQUIRE: nothing + // PROMISE: Shared library will be removed from memory + // filename () return 0 + + virtual const char *className (void) const {return "shObjLoader";} + +private: +#ifdef __hpux + shl_t libHandler_; + struct shl_descriptor *desc_; +#endif // endif __hpux + +#if defined (sunos4) || defined (sgi) || defined (solaris) || defined (aix) || defined (__linux) + void* libHandler_; +#endif // endif sun or sgi + +#if defined (_WIN32) + HINSTANCE libHandler_; +#endif + + char *libName_; +}; +#endif diff --git a/src/configSvc b/src/configSvc new file mode 100755 index 0000000..c7fb205 --- /dev/null +++ b/src/configSvc @@ -0,0 +1,290 @@ +#!/bin/sh +# configSvc +# Usage: configSvc services=svcname0 svcname1 svcname3 ... +# headers=header0 header1 +# Purpose: construct a CDEV static service finder routine +# Author: Jie Chen +# CEBAF Data Acquisition Group +# configSvc,v +# Revision 1.16 1998/02/13 14:00:20 chen +# add cdevDirRequestObj +# +# Revision 1.15 1998/01/14 13:38:38 chen +# fix a small problem +# +# Revision 1.14 1997/12/22 18:23:04 akers +# Ongoing development of 1.6.2 +# +# Revision 1.13 1997/08/21 13:30:45 chen +# move -D_CDEV_ACCOUNTING_ to Makefile.config +# +# Revision 1.12 1997/08/15 18:10:54 akers +# Addition of CDEV Accounting +# +# Revision 1.11 1997/03/26 15:49:52 akers +# Ongoing development... +# +# Revision 1.10 1997/03/25 22:24:32 akers +# Development in support of a new cdevDirectory +# +# Revision 1.9 1996/10/15 12:54:04 akers +# Minor Change... +# +# Revision 1.8 1996/10/07 12:36:24 akers +# Minor Change +# +# Revision 1.7 1996/10/02 17:17:00 akers +# Inserted setup for Makefile.common +# +# Revision 1.6 1996/09/20 12:24:51 akers +# Changes added for Release 1.4 +# +# Revision 1.4 1996/06/26 15:54:04 akers +# Modifications to support multiple OS Versions +# +# Revision 1.3 1996/05/14 20:37:58 akers +# Makefile modifications +# +# Revision 1.2 1995/11/14 17:14:44 chen +# change to work under new makefiles +# +# + +configf=./directory/cdevSvcConfig.cc +makef=./directory/Makefile +os=`uname` + +case $os in +Linux) + ECHO='echo -e';; +linux) + ECHO='echo -e';; +*) + ECHO=echo;; +esac + +case $# in +0) $ECHO 'Usage: configSvc services=svcname ... headers=header0.. flags=flags0 ..\n. Generating Makefile and cdevSvcConfig.cc for dynamic loading only' 1>&2 +esac + +# remove old configuration file and makefile first +if test -f $configf +then + rm -f $configf +fi +if test -f $makef +then + rm -f $makef +fi + +# first get first service and first header +for arg +do +case $arg in +services=*) + firstsvc=`$ECHO $arg | sed 's/[a-z]*=//'`;; +headers=*) + firsthdr=`$ECHO $arg | sed 's/[a-z]*=//'`;; +flags=*) + firstflg=`$ECHO $arg | sed 's/[a-z]*=//'`;; +*) +esac +done + +hassvc=false + +#check empty service and header +case $firstsvc in +"") $ECHO "no service provided";; +*)hassvc=true;; +esac + +case $firsthdr in +"") $ECHO "no header directories provided" + case $hassvc in + true) $ECHO "Need header file location for services" + exit 2;; + esac;; +*) +esac + +case $firstflg in +"") $ECHO "no compiling flags provided";; +esac + +# copy common stuff to the top of the files +# c++ file +$ECHO // cdevSvcConfig.cc generated by configSvc, do not edit > $configf +$ECHO "#ifdef SHOBJ" >> $configf +$ECHO " // ******************************************" >> $configf +$ECHO " // * This section added to provide a credible" >> $configf +$ECHO " // * object file for the shared library..." >> $configf +$ECHO " // ******************************************" >> $configf +$ECHO " int CDEV_SVC_CONFIG_SHARED = 1;" >> $configf +$ECHO "#else" >> $configf + +# loop over first to include all headers and find out the last arguments +lastargument=nothing +svcs=true +hflag=false +fflag=false + +for arg +do + case $arg in + services=*) + $ECHO "#include <"$firstsvc"Service.h>" >> $configf + lastargument=$firstsvc;; + headers=*) + headers=-I$firsthdr + lastargument=$firsthdr + hflag=true + svcs=false;; + flags=*) + flags=-D$firstflg + lastargument=$firstflg + fflag=true + hflag=false + svcs=false;; + *) + lastargument=$arg + case $svcs in + false);; + true) + $ECHO "#include <"$arg"Service.h>" >> $configf + esac + case $hflag in + false);; + true) + headers="$headers -I$arg" + esac + case $fflag in + false);; + true) + flags="$flags -D$arg" + esac + esac +done +$ECHO "#include \"cdevSvcFinder.h\" " >> $configf +$ECHO "#include " >> $configf +$ECHO " " >> $configf +$ECHO " " >> $configf +$ECHO "cdevService* " >> $configf +$ECHO "cdevSvcFinder::findService (char* serviceName)" >> $configf +$ECHO "{" >> $configf +$ECHO " cdevService* svc = 0;" >> $configf + +# beginning of the loop indicator +svcs=true + +# now loop through all services +for arg +do + case $arg in + services=*) + $ECHO configuring service with name "$firstsvc"Service ...... + $ECHO " if (::strcmp (serviceName, \""$firstsvc"Service\") == 0) {" >> $configf + $ECHO " if (!system_.serviceCreated (serviceName))" >> $configf + $ECHO " svc = new "$firstsvc"Service (serviceName, system_);" >> $configf + $ECHO " else" >> $configf + $ECHO " svc = system_.service (serviceName);" >> $configf + $ECHO " }" >> $configf;; + headers=*) + svcs=false;; + flags=*) + svcs=false;; + *) + case $svcs in + true) + $ECHO configuring service with name "$arg"Service ...... + $ECHO " else if (::strcmp (serviceName, \""$arg"Service\") == 0) {" >> $configf; + $ECHO " if (!system_.serviceCreated (serviceName))" >> $configf + $ECHO " svc = new "$arg"Service (serviceName, system_);" >> $configf + $ECHO " else" >> $configf + $ECHO " svc = system_.service (serviceName);" >> $configf + $ECHO " }" >> $configf + esac + esac +done +$ECHO " return svc;" >> $configf +$ECHO "}" >> $configf +$ECHO "#endif" >> $configf + + +$ECHO "# Makefile generated by configSvc. Do not Edit" > $makef +$ECHO "include ../Makefile.config" >> $makef +$ECHO " " >> $makef +$ECHO "ifeq (\$(INCDIR), )" >> $makef +$ECHO " INCDIR = ../.." >> $makef +$ECHO "endif" >> $makef +$ECHO " " >> $makef +$ECHO "ifeq (\$(SHOBJ),YES)" >> $makef +$ECHO " OBJTYPE=.shobj/\$(TARGETDIR)" >> $makef +$ECHO "else" >> $makef +$ECHO " OBJTYPE=.obj/\$(TARGETDIR)" >> $makef +$ECHO "endif" >> $makef +$ECHO " " >> $makef +$ECHO "ifeq (\$(SHOBJ), YES)" >> $makef +$ECHO "XTRACXXFLAGS = -I/usr/include/CC $flags" >> $makef +$ECHO "else" >> $makef +$ECHO "XTRACXXFLAGS = -I/usr/include/CC $headers $flags" >> $makef +$ECHO "endif" >> $makef +$ECHO " " >> $makef +$ECHO "OBJS = \$(OBJTYPE)/cdevSvcFinder.o \$(OBJTYPE)/cdevDirectory.o \$(OBJTYPE)/cdevDirectoryTable.o \$(OBJTYPE)/cdevDirectoryTool.o \$(OBJTYPE)/cdevDirRequestObj.o \$(OBJTYPE)/cdevSvcConfig.o" >> $makef +$ECHO " " >> $makef +$ECHO "targets: \$(OBJTYPE) \$(OBJDIR)/\$(OBJTYPE) copyobjs copyincs" >> $makef +$ECHO " " >> $makef +$ECHO "\$(OBJTYPE) :" >> $makef +$ECHO " @mkdir -p \$(OBJTYPE)" >> $makef +$ECHO " " >> $makef +$ECHO "\$(OBJDIR)/\$(OBJTYPE) :" >> $makef +$ECHO " @mkdir \$(OBJDIR)/\$(OBJTYPE)" >> $makef +$ECHO " " >> $makef +$ECHO "copyobjs: \$(OBJS)" >> $makef +$ECHO " cp \$(OBJS) \$(OBJDIR)/\$(OBJTYPE)" >> $makef +$ECHO " " >> $makef +$ECHO "copyincs:" >> $makef +$ECHO " cp *.h \$(INCDIR)" >> $makef +$ECHO " " >> $makef +$ECHO " " >> $makef +$ECHO "clean: clean_hail" >> $makef +$ECHO " rm -rf *.o *.a *~ *.sl .obj .shobj core prtrpository" >> $makef + + +#create Makefile.archive +$ECHO "# ***********************************************************************" > ../include/makeinclude/Makefile.archive +$ECHO "# * Makefile.archive *" >> ../include/makeinclude/Makefile.archive +$ECHO "# * The ARCHIVELIBS variable should contain a complete list of *" >> ../include/makeinclude/Makefile.archive +$ECHO "# * all libraries that will be needed by an ARCHIVE cdev program. *" >> ../include/makeinclude/Makefile.archive +$ECHO "# * The variable should contain the path specification and the *" >> ../include/makeinclude/Makefile.archive +$ECHO "# * name of the library in the format that is required by your *" >> ../include/makeinclude/Makefile.archive +$ECHO "# * platform's linker. *" >> ../include/makeinclude/Makefile.archive +$ECHO "# ***********************************************************************" >> ../include/makeinclude/Makefile.archive +$ECHO "ARCHIVELIBS = -L\$(CDEVLIB) \c" >> ../include/makeinclude/Makefile.archive +# now loop through all services +for arg in $* +do + case $arg in + services=*) $ECHO "-l${firstsvc}Service \c" >> ../include/makeinclude/Makefile.archive;; + headers=*) break ;; + *) $ECHO "-l${arg}Service \c" >> ../include/makeinclude/Makefile.archive + esac +done +$ECHO " " >> ../include/makeinclude/Makefile.archive +$ECHO "*************************************************************************" +$ECHO "* Modifications Finished! *" +$ECHO "* *" +$ECHO "* You may need to add additional, platform-specific archive libraries *" +$ECHO "* to the definition in the file ../include/makeinclude/Makefile.archive *" +$ECHO "* *" +$ECHO "* For example: If you are using EPICS you will need to append the *" +$ECHO "* following string to the ARCHIVELIBS definition in Makefile.archive in *" +$ECHO "* order to include the necessary libraries... *" +$ECHO "* *" +$ECHO "* -L\$(EPICSLIB) -lca -lCom -lDb *" +$ECHO "* *" +$ECHO "* Other custom services may also require additional library *" +$ECHO "* definitions, consult the service's user documentation for information *" +$ECHO "*************************************************************************" +# finished and quit +exit 0 diff --git a/src/device/.shobj/Linux/cdevDevice.o b/src/device/.shobj/Linux/cdevDevice.o new file mode 100644 index 0000000..34ad9d4 Binary files /dev/null and b/src/device/.shobj/Linux/cdevDevice.o differ diff --git a/src/device/.shobj/Linux/cdevErrReqObject.o b/src/device/.shobj/Linux/cdevErrReqObject.o new file mode 100644 index 0000000..e407ae8 Binary files /dev/null and b/src/device/.shobj/Linux/cdevErrReqObject.o differ diff --git a/src/device/.shobj/Linux/cdevIOcontext.o b/src/device/.shobj/Linux/cdevIOcontext.o new file mode 100644 index 0000000..8bd187d Binary files /dev/null and b/src/device/.shobj/Linux/cdevIOcontext.o differ diff --git a/src/device/.shobj/Linux/cdevRequestObject.o b/src/device/.shobj/Linux/cdevRequestObject.o new file mode 100644 index 0000000..1fe5467 Binary files /dev/null and b/src/device/.shobj/Linux/cdevRequestObject.o differ diff --git a/src/device/Makefile b/src/device/Makefile new file mode 100755 index 0000000..1a1be51 --- /dev/null +++ b/src/device/Makefile @@ -0,0 +1,57 @@ +# Makefile for device directory of CDEV +# +# cdev device directory +# +# Makefile,v +# Revision 1.9 1998/08/17 14:04:57 akers +# Added 'Minor Version Number' to TARGETDIR in Makefiles +# +# Revision 1.8 1996/09/20 12:24:52 akers +# Changes added for Release 1.4 +# +# Revision 1.6 1996/06/26 15:54:14 akers +# Modifications to support multiple OS Versions +# +# Revision 1.5 1996/05/14 20:38:09 akers +# Makefile modifications +# +# Revision 1.4 1995/12/08 15:38:27 chen +# add inline files +# +# Revision 1.3 1995/11/14 17:37:02 chen +# new makefile +# +# +include ../Makefile.config + +ifeq ($(SHOBJ),YES) + OBJTYPE=.shobj/$(TARGETDIR) +else + OBJTYPE=.obj/$(TARGETDIR) +endif + +ifeq ($(INCDIR), ) + INCDIR = ../.. +endif + +OBJS = $(OBJTYPE)/cdevIOcontext.o \ + $(OBJTYPE)/cdevDevice.o \ + $(OBJTYPE)/cdevRequestObject.o \ + $(OBJTYPE)/cdevErrReqObject.o + +targets: $(OBJTYPE) $(OBJDIR)/$(OBJTYPE) copyobjs copyincs + +$(OBJTYPE) : + @mkdir -p $(OBJTYPE) + +$(OBJDIR)/$(OBJTYPE) : + @mkdir $(OBJDIR)/$(OBJTYPE) + +copyobjs: $(OBJS) + @cp $(OBJS) $(OBJDIR)/$(OBJTYPE) + +copyincs: + @cp *.h *.i $(INCDIR) + +clean: clean_hail + @rm -rf *.o .obj .shobj core *~ diff --git a/src/device/NMakefile.mak b/src/device/NMakefile.mak new file mode 100755 index 0000000..ee55361 --- /dev/null +++ b/src/device/NMakefile.mak @@ -0,0 +1,16 @@ +include ..\NMakefile.config + +OBJS = $(OBJDIR)\cdevIOcontext.obj \ + $(OBJDIR)\cdevDevice.obj \ + $(OBJDIR)\cdevRequestObject.obj \ + $(OBJDIR)\cdevErrReqObject.obj + +targets : copyobjs copyincs + +copyobjs : $(OBJS) + -@if not exist ..\lib\$(OBJDIR) mkdir ..\lib\$(OBJDIR) + -@for %x in ($(OBJDIR)\*.obj) DO @copy %x ..\lib\$(OBJDIR) > nul + +copyincs : + -@for %x in (*.h *.i) DO @copy %x $(CDEV)\include > nul + diff --git a/src/device/cdevDevice.cc b/src/device/cdevDevice.cc new file mode 100755 index 0000000..1b80d75 --- /dev/null +++ b/src/device/cdevDevice.cc @@ -0,0 +1,338 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevDevice class implementation +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevDevice.cc,v +// Revision 1.10 1997/10/07 15:22:03 chen +// fix reference counting problem for cdevRequestObject +// +// Revision 1.9 1997/08/27 18:20:11 chen +// indent a little +// +// Revision 1.8 1997/06/19 19:57:25 akers +// Ongoing development and updates +// +// Revision 1.6 1997/06/03 17:57:49 akers +// Bug Fix in attachPtr +// +// Revision 1.5 1996/11/21 17:03:12 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.4 1996/05/07 16:26:27 chen +// Add reference count to request object inside getRequestObject routine +// +// Revision 1.3 1995/07/05 18:39:48 chen +// change interface +// +// Revision 1.2 1995/06/30 15:59:26 chen +// remove all unnecessary files +// +// Revision 1.1.1.1 1995/06/16 17:14:06 epics +// initial import of cdev +// +// +#include +#include +#include + +#include +#include +#include +#include +#include "cdevDevice.h" + +cdevDevice::cdevDevice (char *devName, cdevSystem& sys) +:cdevIOcontext(), system_(sys), reqObjList_(), unregOn_ (1), + refCount_ (1) +{ +#ifdef _TRACE_OBJECTS + printf(" Create cdevDevice class object\n"); +#endif + deviceName_ = new char[::strlen(devName) + 1]; + ::strcpy (deviceName_, devName); + sys.registerDevice (this); +} + +cdevDevice::~cdevDevice (void) +{ +#ifdef _TRACE_OBJECTS + printf(" Destroy cdevDevice class object\n"); +#endif + // device will be removed from system side if unregOn_ unset + if (unregOn_) + system_.removeDevice (this); + // remove request object here + cdevSlistIterator sit (reqObjList_); + cdevRequestObject *tobj = 0; + + for (sit.init(); !sit; ++sit){ + tobj = (cdevRequestObject *)sit (); + tobj->unregOn_ = 0; + delete tobj; + } + delete []deviceName_; +} + +cdevDevice& +cdevDevice::attachRef (char *name) +{ + return cdevDevice::attachRef (name, cdevSystem::defaultSystem () ); +} + +cdevDevice * +cdevDevice::attachPtr (char *name) +{ + return cdevDevice::attachPtr (name, cdevSystem::defaultSystem () ); +} + +cdevDevice& +cdevDevice::attachRef (char *name, cdevSystem& system) +{ + return *cdevDevice::attachPtr (name, system); +} + +cdevDevice * +cdevDevice::attachPtr(char *name, cdevSystem &system) +{ + cdevDevice *dev =0; + cdevService *service=0; + + // ********************************************************************* + // * If the device has already been created, then increment the device's + // * reference count and return the existing pointer to the caller. + // ********************************************************************* + if(system.deviceCreated(name)) + { + dev=system.device(name); + dev->refCount_++; + } + // ********************************************************************* + // * If the device has not been created, then create it. + // ********************************************************************* + else + { + cdevData data, result; + data.insert("device", name); + // ************************************************************* + // * Use the queryClass method to determine the DDL class + // * associated with the device name. + // ************************************************************* + int status=(system.nameServer()).send("queryClass", data, result); + + // ************************************************************* + // * if the device name is defined in the cdevDirectory... + // ************************************************************* + if(status == CDEV_SUCCESS) + { + char *className; + result.find("value", (void* &) className); + + // ***************************************************** + // * If it is a collection, create a new cdevCollection + // ***************************************************** + if(::strcmp(className, "collection") == 0) + dev=new cdevCollection(name, system); + // ***************************************************** + // * Otherwise, create a simple cdevDevice. + // ***************************************************** + else dev=new cdevDevice(name, system); + } + // ************************************************************* + // * If the device name is not listed in the cdevDirectory, then + // * treat it as a simple device. + // ************************************************************* + else dev=new cdevDevice(name, system); + } + return dev; +} + +void +cdevDevice::detach (cdevDevice& dev) +{ + cdevDevice::detach (&dev); +} + +void +cdevDevice::detach (cdevDevice *dev) +{ + if (--dev->refCount_ <= 0) // no more reference attached + delete dev; +} + +const char * +cdevDevice::name (void) const +{ + return deviceName_; +} + +cdevSystem& +cdevDevice::system (void) const +{ + return system_; +} + +cdevRequestObject* +cdevDevice::getRequestObject (char *msg) +{ + cdevRequestObject *obj = 0; + int status = getRequestObject (msg, obj); + return obj; +} + +int +cdevDevice::getRequestObject (char *msg, cdevRequestObject* &reqobj) +{ + if (reqobj = findRequestObject (msg)) { + reqobj->refCount_ ++; + return CDEV_SUCCESS; + } + if (reqobj = cdevRequestObject::attachPtr (*this, msg, system_)) + return CDEV_SUCCESS; + reqobj = NULL; + return CDEV_ERROR; +} + +cdevRequestObject* +cdevDevice::findRequestObject (char *msg) +{ + cdevSlistIterator sit(reqObjList_); + int found = 0; + cdevRequestObject *obj = 0; + + for (sit.init(); !sit; ++sit) { + obj = (cdevRequestObject *)sit(); + if (::strcmp(obj->message(), msg) == 0) + return obj; + } + return (cdevRequestObject *)NULL; +} + +int +cdevDevice::setContext (cdevData &cxt) +{ + data_ = cxt; + cdevSlistIterator sit(reqObjList_); + cdevRequestObject *tobj = 0; + + for (sit.init(); !sit; ++sit) { + tobj = (cdevRequestObject *)sit (); + tobj->setContext (cxt); + } + return CDEV_SUCCESS; +} + +int +cdevDevice::registerReqObject (cdevRequestObject *obj) +{ + cdevSlistIterator sit(reqObjList_); + cdevRequestObject *tobj = 0; + int found = 0; + +#ifdef _CDEV_DEBUG + printf ("%s has %d number of requestObjects\n",name(), reqObjList_.count()); +#endif + for (sit.init(); !sit; ++sit){ + tobj = (cdevRequestObject *)sit (); + if (::strcmp(tobj->message(), obj->message() ) == 0) + return CDEV_ERROR; + } +#ifdef _CDEV_DEBUG + printf("add new reqObj with name %s message %s\n",name(), obj->message()); +#endif + reqObjList_.add ((void *)obj); + return CDEV_SUCCESS; +} + +int +cdevDevice::removeReqObject (cdevRequestObject *obj) +{ + reqObjList_.remove ((void *)obj); + return CDEV_SUCCESS; +} + +int +cdevDevice::send (char *msg, cdevData& out, cdevData& result) +{ + return send (msg, &out, &result); +} + +int +cdevDevice::send (char *msg, cdevData* out, cdevData& result) +{ + return send (msg, out, &result); +} + +int +cdevDevice::send (char *msg, cdevData& out, cdevData* result) +{ + return send (msg, &out, result); +} + +int +cdevDevice::send (char *msg, cdevData* out, cdevData* result) +{ + cdevRequestObject *reqobj; + + int status = getRequestObject (msg, reqobj); + if (status == CDEV_SUCCESS) + return reqobj->send (out, result); + else + return status; +} + +int +cdevDevice::sendNoBlock (char *msg, cdevData& out, cdevData& result) +{ + return sendNoBlock (msg, &out, &result); +} + +int +cdevDevice::sendNoBlock (char *msg, cdevData* out, cdevData& result) +{ + return sendNoBlock (msg, out, &result); +} + +int +cdevDevice::sendNoBlock (char *msg, cdevData& out, cdevData* result) +{ + return sendNoBlock (msg, &out, result); +} + +int +cdevDevice::sendNoBlock (char *msg, cdevData* out, cdevData* result) +{ + cdevRequestObject *reqobj; + int status = getRequestObject (msg, reqobj); + if (status == CDEV_SUCCESS) + return reqobj->sendNoBlock (out, result); + else + return status; +} + +int +cdevDevice::sendCallback (char *msg, cdevData& out, cdevCallback& callback) +{ + return sendCallback (msg, &out, callback); +} + +int +cdevDevice::sendCallback (char *msg, cdevData* out, cdevCallback& callback) +{ + cdevRequestObject *reqobj; + int status = getRequestObject (msg, reqobj); + if (status == CDEV_SUCCESS) + return reqobj->sendCallback (out, callback); + else + return status; +} diff --git a/src/device/cdevDevice.h b/src/device/cdevDevice.h new file mode 100755 index 0000000..0c687b9 --- /dev/null +++ b/src/device/cdevDevice.h @@ -0,0 +1,161 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevDevice: a virtual control device +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevDevice.h,v +// Revision 1.4 1996/11/21 17:03:13 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.3 1995/07/05 18:39:43 chen +// change interface +// +// Revision 1.2 1995/06/30 15:59:27 chen +// remove all unnecessary files +// +// Revision 1.1.1.1 1995/06/16 17:14:06 epics +// initial import of cdev +// +// +#ifndef _CDEV_DEVICE_H +#define _CDEV_DEVICE_H + +#include +#include +#include +#include +#include +#include + +class cdevRequestObject; + +class CDEV_CLASS_SPEC cdevDevice: public cdevIOcontext +{ + public: + //=================================================================== + // Public Interface for Clients + //=================================================================== + static cdevDevice& attachRef (char *name); + static cdevDevice* attachPtr (char *name); + // PURPOSE: create a reference or pointer for device of a given name + // within the default system + // REQUIRE: name != 0 + // PROMISE: a cdevDevice + + static void detach (cdevDevice& dev); + static void detach (cdevDevice* dev); + // PURPOSE: destroy a cdevDevice + // REQUIRE: dev != 0 + // PROMISE: memory will be freed if no more attachment on this device + + const char *name (void) const; + // PURPOSE: return device name + // REQUIRE: nothing + // PROMISE: a name + + cdevSystem& system (void) const; + // PURPOSE: return system associated with this device + // REQUIRE: nothing + // PROMISE: return reference of the system + + virtual int send (char *msg, cdevData &out, cdevData& result); + virtual int send (char *msg, cdevData *out, cdevData& result); + virtual int send (char *msg, cdevData &out, cdevData* result); + virtual int send (char *msg, cdevData *out, cdevData* result); + // PURPOSE: synchronous IO operations + // REQUIRE: when set, provide out, when get, provide result + // PROMISE: return CDEV_SUCCESS: success. Check cdevErrCode.h for error info + + virtual int sendNoBlock (char *msg, cdevData &out, cdevData &result); + virtual int sendNoBlock (char *msg, cdevData *out, cdevData &result); + virtual int sendNoBlock (char *msg, cdevData &out, cdevData *result); + virtual int sendNoBlock (char *msg, cdevData *out, cdevData *result); + // PURPOSE: asynchronous IO operations + // REQUIRE: same as the above and one may use cdevGroup to group these + // PROMISE: return CDEV_SUCCESS: success. Check cdevErrCode.h for error info + + virtual int sendCallback (char *msg, cdevData &out, cdevCallback &callback); + virtual int sendCallback (char *msg, cdevData *out, cdevCallback &callback); + // PURPOSE: asynchronous IO operations with user supplied callback function + // REQUIRE: out != 0 + // PROMISE: return CDEV_SUCCESS: request sendout success. + // check cdevErrCode.h for error info + + // setIOcontext function, pass cxt to requestObject int the list + virtual int setContext (cdevData& cxt); + // PURPOSE: set context to this device + // REQUIRE: nothing + // PROMISE: always return 0, set constext to all request objects + // in this device + + //======================================================================== + // Public Interface for cdevRequestObject + //======================================================================== + virtual cdevRequestObject* getRequestObject (char *msg); + // PURPOSE: get a requestObject based on message 'msg' + // REQUIRE: msg != 0 + // PROMISE: return a pointer to requestObject + + virtual int getRequestObject (char *msg, cdevRequestObject* &reqobj); + // PURPOSE: get right requestObject + // REQUIRE: msg != 0, callers provide pointer only. + // PROMISE: always return CDEV_SUCCESS. reqobj may be an errorRequestObject + + virtual int registerReqObject (cdevRequestObject *obj); + // PURPOSE: register a requestObject into this device + // REQUIRE: obj != 0 + // PROMISE: return CDEV_SUCCESS: success, CDEV_ERROR: already here + + virtual int removeReqObject (cdevRequestObject *obj); + // PURPOSE: remove a requestObject from the device + // REQUIRE: obj != 0 + // PROMISE: return CDEV_SUCCESS: success, CDEV_ERROR: not here + + virtual const char *className (void) const {return "cdevDevice";} + + protected: + //constructors and destructor + cdevDevice (char *name, cdevSystem& system = cdevSystem::defaultSystem() ); + virtual ~cdevDevice (void); + + // attach pointer or reference with system as second argument + // protected to prevent application from using multiple systems + static cdevDevice& attachRef (char *name, cdevSystem& system); + static cdevDevice* attachPtr (char *name, cdevSystem& system); + // PURPOSE: create a reference or pointer for device of a given name + // REQUIRE: name != 0 + // PROMISE: a cdevDevice + + cdevRequestObject* findRequestObject(char *msg); + // PURPOSE: find an existing requestObject + // REQUIRE: name != 0, callers provide pointer only. + // PROMISE: return valid request object or NULL if not found + + // Protected data items + char *deviceName_; + cdevSystem& system_; + cdevSlist reqObjList_; + int unregOn_; // unregister self from system on delete + int refCount_; + + private: + // hide assignment and copy operator since the device is + // a memory manager for requestObject + cdevDevice& operator = (const cdevDevice &); + cdevDevice (const cdevDevice &); + + // friend class declaration + friend class cdevSystem; + friend class cdevRequestObject; +}; +#endif diff --git a/src/device/cdevErrReqObject.cc b/src/device/cdevErrReqObject.cc new file mode 100755 index 0000000..02043da --- /dev/null +++ b/src/device/cdevErrReqObject.cc @@ -0,0 +1,134 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevErrReqObject class implementation. +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevErrReqObject.cc,v +// Revision 1.6 1998/03/09 18:51:36 chen +// redefine getState/getAccess for errReqObject +// +// Revision 1.5 1998/02/19 18:39:58 akers +// Bug Fixes +// +// Revision 1.4 1995/10/26 14:33:22 akers +// Removal of Warnings +// +// Revision 1.3 1995/10/17 20:21:23 chen +// change reportError status value +// +// Revision 1.2 1995/10/17 15:27:38 chen +// change reportError interface +// +// Revision 1.1.1.1 1995/06/16 17:14:06 epics +// initial import of cdev +// +// +#include +#include "cdevErrReqObject.h" + +cdevErrReqObject::cdevErrReqObject (cdevSystem& system) +:cdevRequestObject ("errHandleDevice","errHandle", system) +{ +#ifdef _TRACE_OBJECTS + printf(" Create cdevErrReqObject class\n"); +#endif + // empty +} + +cdevErrReqObject::~cdevErrReqObject (void) +{ +#ifdef _TRACE_OBJECTS + printf(" Delete cdevErrReqObject class\n"); +#endif + system_.errorRequestObject (0); +} + +int +cdevErrReqObject::send (cdevData& out, cdevData& result) +{ + return send (&out, &result); +} + +int +cdevErrReqObject::send (cdevData& out, cdevData* result) +{ + return send (&out, result); +} + +int +cdevErrReqObject::send (cdevData* out, cdevData& result) +{ + return send (out, &result); +} + +int +cdevErrReqObject::send (cdevData* , cdevData* ) +{ + system_.reportError (CDEV_SEVERITY_ERROR, system_.name(), + this, "Attempt to send with an invalid request object."); + return CDEV_INVALIDOBJ; +} + +int +cdevErrReqObject::sendNoBlock (cdevData& out, cdevData& result) +{ + return sendNoBlock (&out, &result); +} + +int +cdevErrReqObject::sendNoBlock (cdevData& out, cdevData* result) +{ + return sendNoBlock (&out, result); +} + +int +cdevErrReqObject::sendNoBlock (cdevData* out, cdevData& result) +{ + return sendNoBlock (out, &result); +} + +int +cdevErrReqObject::sendNoBlock (cdevData* , cdevData* ) +{ + system_.reportError (CDEV_SEVERITY_ERROR, system_.name(), + this, "Attempt to send with an invalid request object."); + return CDEV_INVALIDOBJ; +} + +int cdevErrReqObject::sendCallback (cdevData& out, cdevCallback &callback) +{ + return sendCallback (&out, callback); +} + +int +cdevErrReqObject::sendCallback (cdevData* /* out */, + cdevCallback & /* callback */) +{ + system_.reportError (CDEV_SEVERITY_ERROR, system_.name(), + this, "Attempt to send with an invalid request object."); + // send this request information to callback in the future + return CDEV_INVALIDOBJ; +} + +int +cdevErrReqObject::getState (void) +{ + return CDEV_STATE_INVALID; +} + +int +cdevErrReqObject::getAccess (void) +{ + return CDEV_ACCESS_NONE; +} + diff --git a/src/device/cdevErrReqObject.h b/src/device/cdevErrReqObject.h new file mode 100755 index 0000000..62f9fb2 --- /dev/null +++ b/src/device/cdevErrReqObject.h @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevRequestObject Error Handler Object (User Cannot Access this) +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevErrReqObject.h,v +// Revision 1.2 1998/03/09 18:51:37 chen +// redefine getState/getAccess for errReqObject +// +// Revision 1.1.1.1 1995/06/16 17:14:06 epics +// initial import of cdev +// +// +#ifndef _CDEV_ERR_REQOBJ_H +#define _CDEV_ERR_REQOBJ_H + +#include + +class cdevErrReqObject: public cdevRequestObject +{ + public: + // destructor + ~cdevErrReqObject (void); + + int send (cdevData& out, cdevData& result); + int send (cdevData* out, cdevData& result); + int send (cdevData& out, cdevData* result); + int send (cdevData* out, cdevData* result); + + int sendNoBlock (cdevData& out, cdevData& result); + int sendNoBlock (cdevData* out, cdevData& result); + int sendNoBlock (cdevData& out, cdevData* result); + int sendNoBlock (cdevData* out, cdevData* result); + + int sendCallback (cdevData& out, cdevCallback& callback); + int sendCallback (cdevData* out, cdevCallback& callback); + + int getState (void); + int getAccess (void); + + const char *className (void) const {return "cdevErrReqObject";} + + private: + // constructor + cdevErrReqObject (cdevSystem& system = cdevSystem::defaultSystem()); + friend class cdevSystem; +}; +#endif diff --git a/src/device/cdevIOcontext.cc b/src/device/cdevIOcontext.cc new file mode 100755 index 0000000..b2e8047 --- /dev/null +++ b/src/device/cdevIOcontext.cc @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevIOcontext class implementation +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevIOcontext.cc,v +// Revision 1.1.1.1 1995/06/16 17:14:06 epics +// initial import of cdev +// +// +#include +#include +#include"cdevIOcontext.h" + +cdevIOcontext::cdevIOcontext (void) +:data_(), userData_(0) +{ +#ifdef _TRACE_OBJECTS + printf("Create cdevIOcontext class\n"); +#endif + // empty +} + +cdevIOcontext::~cdevIOcontext (void) +{ +#ifdef _TRACE_OBJECTS + printf("Destroy cdevIOcontext class\n"); +#endif + // do not delete userData_, user has control over it +} + +cdevData& +cdevIOcontext::getContext (void) +{ + return data_; +} + +int +cdevIOcontext::setContext (cdevData& newData) +{ + data_ = newData; + return CDEV_SUCCESS; +} + +void +cdevIOcontext::setPrivate (void *newUserData) +{ + userData_ = newUserData; +} + +void * +cdevIOcontext::getPrivate (void) +{ + return (void *)userData_; +} diff --git a/src/device/cdevIOcontext.h b/src/device/cdevIOcontext.h new file mode 100755 index 0000000..7d34d25 --- /dev/null +++ b/src/device/cdevIOcontext.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevIOcontext header +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevIOcontext.h,v +// Revision 1.1.1.1 1995/06/16 17:14:06 epics +// initial import of cdev +// +// +#ifndef _CDEV_IO_CONTEXT_H +#define _CDEV_IO_CONTEXT_H + +#include +#include +#include +#include + +class CDEV_CLASS_SPEC cdevIOcontext +{ + public: + // constructors and destructor + virtual ~cdevIOcontext (void); + + cdevData& getContext (void); + // PURPOSE: get context represented by a cdevData + + virtual int setContext (cdevData& ctx); + // PURPOSE: set context from a cdevData + // derived class may provide different setContext function + // eg. channel access requestObject will use this function + // to provide right request data type + // REQUIRE: nothing + // PROMISE: return 0 + + void setPrivate (void *userdata); + // PURPOSE: set user provided data + // REQUIRE: nothing. user handle memory management of userdata + // PROMISE: user data will not be freeed when this is destroyed + + void * getPrivate (void); + // PURPOSE: get user provided data + // REQUIRE: nothing + // PROMISE: something + + virtual const char *className(void) const {return "cdevIOcontext";} + + protected: + // constructor, to prevent from direct instantiation + cdevIOcontext (void); + cdevData data_; + void *userData_; +}; +#endif + diff --git a/src/device/cdevRequestObject.cc b/src/device/cdevRequestObject.cc new file mode 100755 index 0000000..d11166f --- /dev/null +++ b/src/device/cdevRequestObject.cc @@ -0,0 +1,315 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevRequestObject implementation (abstract class) +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevRequestObject.cc,v +// Revision 1.16 1998/06/17 20:28:45 chen +// attachPtr can return null +// +// Revision 1.15 1998/02/19 18:39:59 akers +// Bug Fixes +// +// Revision 1.14 1998/01/30 13:50:02 akers +// Ongoing development +// +// Revision 1.13 1998/01/14 14:25:57 chen +// minor changes +// +// Revision 1.12 1997/03/25 13:51:40 akers +// *** empty log message *** +// +// +// Revision 1.10 1996/11/21 17:03:15 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.9 1996/05/07 16:27:00 chen +// Minor Changes +// +// Revision 1.8 1995/12/08 15:39:21 chen +// add inline functions + deferred execution mode +// +// Revision 1.7 1995/10/30 18:56:21 akers +// Minor corrections +// +// Revision 1.6 1995/10/30 13:33:18 akers +// Added cdev specific version of strncpy +// +// Revision 1.5 1995/10/17 15:28:24 chen +// change getState and getAccess to virtual +// +// Revision 1.4 1995/09/19 16:10:46 chen +// minor change on bit monitoring mechanism +// +// Revision 1.3 1995/09/18 18:22:07 chen +// add long/short monitoring method +// +// Revision 1.2 1995/07/05 18:40:52 chen +// remove system dependence on attachPtr etc +// +// Revision 1.1.1.1 1995/06/16 17:14:06 epics +// initial import of cdev +// +// +#include +#include +#include +#include "cdevRequestObject.h" + +#ifdef _CDEV_NO_INLINE +#include "cdevRequestObject.i" +#endif + +cdevRequestObject::cdevRequestObject (char *device, + char *msg, + cdevSystem& system) +:cdevIOcontext(), device_ (0), system_(system), unregOn_ (1), + longMask_ (0), refCount_ (1) +{ +#ifdef _TRACE_OBJECTS + printf(" Create cdevRequestObject class\n"); +#endif + deviceName_ = new char[::strlen(device) + 1]; + ::strcpy (deviceName_, device); + + message_ = new char[::strlen(msg) + 1]; + ::strcpy (message_, msg); +} + +cdevRequestObject::cdevRequestObject (cdevDevice &device, + char *msg, + cdevSystem& system) +:cdevIOcontext(), system_ (system), device_ (&device), unregOn_ (1), + refCount_ (1) +{ +#ifdef _TRACE_OBJECTS + printf(" Create cdevRequestObject class\n"); +#endif + deviceName_ = new char[::strlen(device.name() ) + 1]; + ::strcpy (deviceName_, device.name() ); + + message_ = new char[::strlen (msg) + 1]; + ::strcpy (message_, msg); +} + +cdevRequestObject::~cdevRequestObject (void) +{ +#ifdef _TRACE_OBJECTS + printf(" Delete cdevRequestObject class \n"); +#endif + if (unregOn_){ + if (device_) + device_->removeReqObject (this); + } + // service and device will be deleted from system side + delete []deviceName_; + delete []message_; +} + +cdevRequestObject& +cdevRequestObject::attachRef (char *deviceName, char *msg) +{ + return cdevRequestObject::attachRef(deviceName,msg, + cdevSystem::defaultSystem() ); +} + +cdevRequestObject* +cdevRequestObject::attachPtr (char *deviceName, char *msg) +{ + return cdevRequestObject::attachPtr (deviceName, msg, + cdevSystem::defaultSystem() ); +} + +cdevRequestObject& +cdevRequestObject::attachRef (char *deviceName, char *msg, cdevSystem& system) +{ + cdevDevice& dev = cdevDevice::attachRef (deviceName, system); + cdevRequestObject* reqobj; + if ((reqobj = dev.getRequestObject(msg))==0) { + reqobj = system.errorRequestObject (); + reqobj->device (&dev); + } + return *reqobj; +} + +cdevRequestObject* +cdevRequestObject::attachPtr (char *deviceName, char *msg, cdevSystem& system) +{ + cdevDevice& dev = cdevDevice::attachRef (deviceName, system); + cdevRequestObject* reqObj = dev.getRequestObject(msg); + /* reqobj could be null */ + return reqObj; +} + +// The following routine is the real factory -- called by cdevDevice only +cdevRequestObject * +cdevRequestObject::attachPtr (cdevDevice& dev, char *msg, cdevSystem& system) +{ + cdevRequestObject *req = 0; + cdevService *service = 0; + + // it may well be here, one has to do loading a shared library + // check system prefix here to get right name + char fullName[128], message[256]; + if (system.prefix () ){ + cdevStrncpy (fullName, system.prefix(), sizeof (fullName)); + int prefixlen = ::strlen(fullName); + cdevStrncpy (&(fullName[prefixlen]), (char *)dev.name(), + sizeof(fullName)-prefixlen); + } + else + cdevStrncpy (fullName, (char *)dev.name(), sizeof (fullName) ); + + sprintf (message,"resolveService %s %s",fullName, msg); + cdevData result; + char serviceName[128]; + int status = (system.nameServer()).send (message, 0, result); + if (status == CDEV_SUCCESS){ + if (result.get ("value", serviceName, sizeof (serviceName))==CDEV_SUCCESS){ +#ifdef _CDEV_DEBUG + printf("serviceName is %s\n",serviceName); +#endif + service = system.loadService (serviceName); + } + } + + if (service) { + int status = service->getRequestObject ((char *)dev.name(), msg, req); + if (status==0) { + dev.registerReqObject (req); + req->device (&dev); + req->service (service); + // set context same as device context + req->setContext (dev.getContext()); + return req; + } else { + cdevSystem::defaultSystem().reportError(CDEV_SEVERITY_SEVERE, "cdevService", NULL, "Service %s failed to provide object for %s %s", + serviceName, dev.name(), msg); + return 0; + } + } + else { + cdevSystem::defaultSystem().reportError(CDEV_SEVERITY_SEVERE, "cdevService", NULL, "Cannot find service for %s %s",dev.name(), msg); + return 0; + } +return 0; +} + +void +cdevRequestObject::detach (cdevRequestObject &objRef) +{ + cdevRequestObject::detach (&objRef); +} + +void +cdevRequestObject::detach (cdevRequestObject *objPtr) +{ + if (--objPtr->refCount_ <= 0) // no more reference attached + delete objPtr; +} + +char * +cdevRequestObject::message (void) const +{ + return message_; +} + +cdevDevice& +cdevRequestObject::device (void) const +{ + return *device_; +} + +void +cdevRequestObject::device (cdevDevice *device) +{ + device_ = device; +} + +cdevSystem& +cdevRequestObject::system (void) const +{ + return system_; +} + +void +cdevRequestObject::service (cdevService *service) +{ + service_ = service; +} + +cdevService& +cdevRequestObject::service (void) const +{ + return *service_; +} + +int +cdevRequestObject::getState (void) +{ + return CDEV_SUCCESS; +} + +int +cdevRequestObject::getAccess (void) +{ + return CDEV_SUCCESS; +} + +int +cdevRequestObject::setContext (cdevData& cxt) +{ + data_ = cxt; + + if (data_.get ("bitMask", &longMask_) != CDEV_SUCCESS) + longMask_ = 0; + return CDEV_SUCCESS; +} + +int +cdevRequestObject::bitValuesChanged (long value, long mask) +{ + static int firstTime = 1; + static long prevValue = 0; + int status = 0; + + if (firstTime) { // first time to call this routine + firstTime = 0; + status = 1; + } + else { + if ((value ^ prevValue) & mask) + status = 1; + } + prevValue = value; + return status; +} + +int +cdevRequestObject::executionMode (void) +{ + // top most active goupe mode will determine the mode of execution + // if there are more than one opened groups + cdevGroup *activeGrps[MAX_NUM_GROUPS]; + int numActiveGrps = 0; + system_.activeGroups (activeGrps, numActiveGrps); + int mode = CDEV_EXEC_IMMEDIATE; + if (numActiveGrps != 0) { + // note: groups are in the reverse order of start function + if (activeGrps[0]->executionMode () == CDEV_EXEC_DEFERRED && + !activeGrps[0]->readyToExec ()) { + mode = CDEV_EXEC_DEFERRED; + } + } + return mode; +} diff --git a/src/device/cdevRequestObject.h b/src/device/cdevRequestObject.h new file mode 100755 index 0000000..e6c230a --- /dev/null +++ b/src/device/cdevRequestObject.h @@ -0,0 +1,294 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevRequestObject class (abstract class) +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevRequestObject.h,v +// Revision 1.12 1998/02/13 14:00:44 chen +// add ref and deref +// +// Revision 1.11 1997/03/03 17:52:26 chen +// add buffering mechanism to caService +// +// Revision 1.9 1996/11/21 17:03:17 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.8 1996/03/22 16:33:26 chen +// fix inline decleration +// +// Revision 1.7 1995/12/08 15:39:06 chen +// add inline functions + deferred execution mode +// +// Revision 1.6 1995/10/17 15:28:00 chen +// change getState and getAccess to virtual +// +// Revision 1.5 1995/10/03 19:34:01 chen +// change public interface for system +// +// Revision 1.4 1995/09/19 16:10:35 chen +// minor change on bit monitoring mechanism +// +// Revision 1.3 1995/09/18 18:21:58 chen +// add long/short monitoring method +// +// Revision 1.2 1995/07/05 18:40:40 chen +// remove system dependence on attachPtr etc +// +// Revision 1.1.1.1 1995/06/16 17:14:06 epics +// initial import of cdev +// +// +#ifndef _CDEV_REQUESTOBJECT_H +#define _CDEV_REQUESTOBJECT_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +class cdevExecGroup; + +//======================================================================= +// some useful bit mask manipulation routines +//======================================================================= +#define NUMBITS_PER_BYTE 8 + +#ifdef _CDEV_NO_INLINE +//======================================================================= +// clear a long mask, set every bit to 0 +//======================================================================= +extern void cdevMaskZero (long& p); + +//======================================================================= +// turn on a bit at position n inside the mask p +//======================================================================= +extern void cdevMaskSet (long n, long& p); + +//======================================================================= +// turn off a bit at position n inside the mask p +//======================================================================= +extern void cdevMaskClr (long n, long& p); + +//======================================================================= +// check whether a bit n is set or not +//======================================================================= +extern int cdevMaskIsSet (long n, long p); +#endif + + +class CDEV_CLASS_SPEC cdevRequestObject: public cdevIOcontext +{ + public: + //====================================================================== + // Public Interface for Clients + //====================================================================== + static cdevRequestObject& attachRef (char *deviceName, char *msg); + static cdevRequestObject* attachPtr (char *deviceName, char *msg); + + // PURPOSE: Create or Attach Pointer or reference to a requestObject + // inside the default system + // REQUIRE: deviceName != 0, msg != 0. + // PROMISE: return a cdevRequestObject which may be an errorRequestObject + // depending on the device and message pair + + static void detach (cdevRequestObject& objRef); + static void detach (cdevRequestObject* objPtr); + // PURPOSE: Detach from a cdevRequestObject + // REQUIRE: objPtr != 0 + // PROMISE: If objPtr is the last one attached to a cdevRequestObject, + // the cdevRequestObject will be destroyed + + char *message (void) const; + // PURPOSE: return message of this requestObject + // REQUIRE: nothing + // PROMISE: a message + + cdevDevice& device (void) const; + // PURPOSE: return a refence a device holding this request object + // REQUIRE: nothing + // PROMISE: reference of a device + + cdevSystem& system (void) const; + // PURPOSE: return a reference of a system associated with this object + // REQUIRE: nothing + // PROMISE: reference of a system + + cdevService& service (void) const; + // PURPOSE: return a reference of a service associated with this object + // REQUIRE: nothing + // PROMISE: reference of a service + + virtual int getState (void); + // PURPOSE: return status information, derived classes implement this + // REQUIRE: nothing + // PROMISE: + + virtual int getAccess (void); + // PURPOSE: return access control information, derived classes implement this + // REQUIRE: nothing + // PROMISE: + + virtual int send (cdevData& out, cdevData& result) = 0; + virtual int send (cdevData *out, cdevData& result) = 0; + virtual int send (cdevData& out, cdevData* result) = 0; + virtual int send (cdevData *out, cdevData* result) = 0; + // PURPOSE: pure virtual functions for synchronous IO operations + // REQUIRE: derived classes implement those + // PROMISE: return CDEV_SUCCESS: success. See cdevErrCode.h for detail + + virtual int sendNoBlock (cdevData& out, cdevData& result) = 0; + virtual int sendNoBlock (cdevData *out, cdevData& result) = 0; + virtual int sendNoBlock (cdevData& out, cdevData* result) = 0; + virtual int sendNoBlock (cdevData* out, cdevData* result) = 0; + // PURPOSE: pure virtual functions for asynchronous IO operations + // REQUIRE: + // PROMISE: return CDEV_SUCCESS: success. See cdevErrCode.h for detail + + virtual int sendCallback (cdevData& out, cdevCallback& callback) = 0; + virtual int sendCallback (cdevData *out, cdevCallback& callback) = 0; + // PURPOSE: pure virtual functions for asynchronous IO operations with + // user provided callback functions + // REQUIRE: + // PROMISE: return CDEV_SUCCESS: success. See cdevErrCode.h for detail + + virtual int setContext (cdevData& cxt); + // PURPOSE: set context from a cdevData. Check longMask + // tag to set the bit monitoring mask + // derived class may provide different setContext function + // eg. channel access requestObject will use this function + // to provide right request data type. + // REQUIRE: nothing + // PROMISE: return 0 + + + // for subclasss of cdevDevice use only + void ref (void); + // PURPOSE: Increase reference count of this requestobject by one + // REQUIRE: none + // PROMISE: refcount will go up by 1 + + void deref (void); + // PURPOSE: decrease reference count of this requestobject by one + // REQUIRE: none + // PROMISE: refcount will go down by 1 + + + virtual const char *className (void) const {return "cdevRequestObject";} + +protected: + //constructors and destructors + cdevRequestObject (char *device, char *msg, + cdevSystem& system = cdevSystem::defaultSystem() ); + cdevRequestObject (cdevDevice &device, char *msg, + cdevSystem& system = cdevSystem::defaultSystem() ); + virtual ~cdevRequestObject (void); + + // protected version of send for service layer + virtual int execNoBlock (cdevData* out, cdevData* result, void* arg); + virtual int execCallback (cdevData* out, cdevCallback& callback, void* arg); + + // protected to prevent use of multiple systems for now + static cdevRequestObject& attachRef (char *deviceName, + char *msg, cdevSystem& system); + // PURPOSE: Create reference to a requestObject within a given system + // REQUIRE: deviceName != 0, msg != 0. + // PROMISE: return a cdevRequestObject which may be an errorRequestObject + // depending on the device and message pair + static cdevRequestObject* attachPtr (char *deviceName, + char *msg, cdevSystem& system); + // PURPOSE: Create pointer to a requestObject within a given system + // REQUIRE: deviceName != 0, msg != 0. + // PROMISE: return a cdevRequestObject or NULL if not a valid combination + + // following routine used only by cdevDevice, and is the real factory + static cdevRequestObject* attachPtr (cdevDevice& dev, + char *msg, cdevSystem& system); + // PURPOSE: Create pointer to a NEW requestObject within a given system + // REQUIRE: dev != 0, msg != 0. + // PROMISE: return a cdevRequestObject or NULL if not a valid combination + + virtual int bitValuesChanged (long value, long mask); + // PURPOSE: Check any bit values of 'value' changed or not according + // to the mask 'mask'. Any derived classes of cdevRequestObject + // may use this routine to monitor any set of bits in a long + // integer value. + // REQUIRE: none + // PROMISE: if any bit values changed, return 1, else return 0 + + // assign device to the object + void device (cdevDevice *dev); + // assign service to the object + void service (cdevService *service); + + // internal functions for service developer who wants to support + // deferred execution mode inside groups + + // callback will be duplicated if indeed one needs to do defferred ops + int deferExecution (cdevData* out, cdevData* result); + int deferExecution (cdevData* out, cdevCallback* callback); + int executionMode (void); + + // internal functions for service developer who wants to support + // buffering mechanism to improve performance + // note: buffer must be derived class of cdevGroup + + // callback will be duplicated + void bufferExecution (cdevData* out, cdevData* result, + cdevGroup* buffer, void* arg); + void bufferExecution (cdevData* out, cdevCallback* result, + cdevGroup* buffer, void* arg); + + // device pointer + cdevDevice *device_; + // system reference + cdevSystem& system_; + // device name + char *deviceName_; + // message name + char *message_; + // service pointer + cdevService *service_; + // flag to tell whether to unregister from a device on delete + int unregOn_; + // bit monitoring mask + long longMask_; + +private: + // copy and assignment + cdevRequestObject& operator = (const cdevRequestObject& object); + cdevRequestObject (const cdevRequestObject& object); + + // reference counting + int refCount_; + + // friend class declaration + friend class cdevDevice; + friend class cdevSystem; + friend class cdevExecGroup; +}; + +#undef INLINE +#ifndef _CDEV_NO_INLINE +#define INLINE inline +#include "cdevRequestObject.i" +#else +#define INLINE +#endif + +#endif diff --git a/src/device/cdevRequestObject.i b/src/device/cdevRequestObject.i new file mode 100755 index 0000000..ecfffde --- /dev/null +++ b/src/device/cdevRequestObject.i @@ -0,0 +1,154 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevRequestObject implementation (abstract class) +// inline functions +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevRequestObject.i,v +// Revision 1.3 1998/02/13 14:00:44 chen +// add ref and deref +// +// Revision 1.2 1997/03/03 17:52:28 chen +// add buffering mechanism to caService +// +// Revision 1.1 1995/12/08 15:39:43 chen +// inline functions +// +// + +// Note: How to determine to buffer an exeution object? +// If an execution object belongs to a group with +// an immediate execution mode, this object will not be +// buffered. If an execution object belongs to a group +// with a deferred execution mode, this execution object +// will be buffered + +INLINE +int +cdevRequestObject::deferExecution (cdevData* out, cdevData* result) +{ + if (executionMode () == CDEV_EXEC_DEFERRED) { + // create a transaction object + cdevExecObj* obj = new cdevExecObj (&system_, this, out, result, 0); + return 1; + } + else + return 0; +} + +INLINE +int +cdevRequestObject::deferExecution (cdevData* out, cdevCallback* callback) +{ + if (executionMode () == CDEV_EXEC_DEFERRED) { + // create a transaction object with new copy of callback + // must clone the data, as the caller did not + cdevCallback *ccbk = new cdevCallback (*callback); + cdevData *cloned = new cdevData(*out); + cdevExecObj* obj = new cdevExecObj (&system_, this, cloned, 0, ccbk); + return 1; + } + else + return 0; +} + +INLINE +void +cdevRequestObject::bufferExecution (cdevData* out, cdevData* result, + cdevGroup* group, void* arg) +{ + // create an execution object that is registered to the group + // caller has already cloned the data, so don't need to + cdevExecObj* obj = new cdevExecObj (&system_, this, out, result, 0, + group, arg); +} + +INLINE +void +cdevRequestObject::bufferExecution (cdevData* out, cdevCallback* callback, + cdevGroup* group, void* arg) +{ + // create an execution object that is registered to the group + // caller has already cloned the data, so don't need to + cdevExecObj* obj = new cdevExecObj (&system_, this, out, 0, callback, + group, arg); +} + +INLINE +int +cdevRequestObject::execNoBlock (cdevData*, cdevData*, void* ) +{ + // empty: derived class handles this + return CDEV_SUCCESS; +} + +INLINE +int +cdevRequestObject::execCallback (cdevData*, cdevCallback&, void* ) +{ + // empty: derived class handles this + return CDEV_SUCCESS; +} + +//======================================================================= +// clear a long mask, set every bit to 0 +//======================================================================= +INLINE +void cdevMaskZero (long& p) +{ + ::memset ((char *)&p, (char)0, sizeof (long)); +} + +//======================================================================= +// turn on a bit at position n inside the mask p +//======================================================================= +INLINE +void cdevMaskSet (long n, long& p) +{ + assert ((n >= 0) && (n < sizeof (long) * NUMBITS_PER_BYTE)); + p |= 1 << n; +} + +//======================================================================= +// turn off a bit at position n inside the mask p +//======================================================================= +INLINE +void cdevMaskClr (long n, long& p) +{ + assert ((n >= 0) && (n < sizeof (long) * NUMBITS_PER_BYTE)); + p &= ~(1 << n); +} + +//======================================================================= +// check whether a bit n is set or not +//======================================================================= +INLINE +int cdevMaskIsSet (long n, long p) +{ + assert ((n >= 0) && (n < sizeof (long) * NUMBITS_PER_BYTE)); + return (p & (1 << n)); +} + +INLINE +void cdevRequestObject::ref (void) +{ + refCount_ ++; +} + +INLINE +void cdevRequestObject::deref (void) +{ + refCount_ --; +} + + diff --git a/src/device/header.cc b/src/device/header.cc new file mode 100755 index 0000000..e28f28c --- /dev/null +++ b/src/device/header.cc @@ -0,0 +1,20 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// +// +// Author: Jie Chen +// +// Revision History: +// header.cc,v +// Revision 1.1.1.1 1995/06/16 17:14:06 epics +// initial import of cdev +// +// diff --git a/src/directory/.shobj/Linux/cdevDirRequestObj.o b/src/directory/.shobj/Linux/cdevDirRequestObj.o new file mode 100644 index 0000000..a79f587 Binary files /dev/null and b/src/directory/.shobj/Linux/cdevDirRequestObj.o differ diff --git a/src/directory/.shobj/Linux/cdevDirectory.o b/src/directory/.shobj/Linux/cdevDirectory.o new file mode 100644 index 0000000..84c1640 Binary files /dev/null and b/src/directory/.shobj/Linux/cdevDirectory.o differ diff --git a/src/directory/.shobj/Linux/cdevDirectoryTable.o b/src/directory/.shobj/Linux/cdevDirectoryTable.o new file mode 100644 index 0000000..12ec80f Binary files /dev/null and b/src/directory/.shobj/Linux/cdevDirectoryTable.o differ diff --git a/src/directory/.shobj/Linux/cdevDirectoryTool.o b/src/directory/.shobj/Linux/cdevDirectoryTool.o new file mode 100644 index 0000000..3fd5ec5 Binary files /dev/null and b/src/directory/.shobj/Linux/cdevDirectoryTool.o differ diff --git a/src/directory/.shobj/Linux/cdevSvcConfig.o b/src/directory/.shobj/Linux/cdevSvcConfig.o new file mode 100644 index 0000000..1933735 Binary files /dev/null and b/src/directory/.shobj/Linux/cdevSvcConfig.o differ diff --git a/src/directory/.shobj/Linux/cdevSvcFinder.o b/src/directory/.shobj/Linux/cdevSvcFinder.o new file mode 100644 index 0000000..a35f36c Binary files /dev/null and b/src/directory/.shobj/Linux/cdevSvcFinder.o differ diff --git a/src/directory/Makefile b/src/directory/Makefile new file mode 100644 index 0000000..fd57a20 --- /dev/null +++ b/src/directory/Makefile @@ -0,0 +1,38 @@ +# Makefile generated by configSvc. Do not Edit +include ../Makefile.config + +ifeq ($(INCDIR), ) + INCDIR = ../.. +endif + +ifeq ($(SHOBJ),YES) + OBJTYPE=.shobj/$(TARGETDIR) +else + OBJTYPE=.obj/$(TARGETDIR) +endif + +ifeq ($(SHOBJ), YES) +XTRACXXFLAGS = -I/usr/include/CC -D_HAS_CA +else +XTRACXXFLAGS = -I/usr/include/CC -I/devl/epics/base/include -I/home/pss060/sls/watson/work/cdev_1.7.2/src/ca -D_HAS_CA +endif + +OBJS = $(OBJTYPE)/cdevSvcFinder.o $(OBJTYPE)/cdevDirectory.o $(OBJTYPE)/cdevDirectoryTable.o $(OBJTYPE)/cdevDirectoryTool.o $(OBJTYPE)/cdevDirRequestObj.o $(OBJTYPE)/cdevSvcConfig.o + +targets: $(OBJTYPE) $(OBJDIR)/$(OBJTYPE) copyobjs copyincs + +$(OBJTYPE) : + @mkdir -p $(OBJTYPE) + +$(OBJDIR)/$(OBJTYPE) : + @mkdir $(OBJDIR)/$(OBJTYPE) + +copyobjs: $(OBJS) + cp $(OBJS) $(OBJDIR)/$(OBJTYPE) + +copyincs: + cp *.h $(INCDIR) + + +clean: clean_hail + rm -rf *.o *.a *~ *.sl .obj .shobj core prtrpository diff --git a/src/directory/NMakefile.mak b/src/directory/NMakefile.mak new file mode 100755 index 0000000..c1040f1 --- /dev/null +++ b/src/directory/NMakefile.mak @@ -0,0 +1,17 @@ +include ..\NMakefile.config + +OBJS = $(OBJDIR)\cdevDirectory.obj\ + $(OBJDIR)\cdevDirectoryTool.obj\ + $(OBJDIR)\cdevDirRequestObj.obj\ + $(OBJDIR)\cdevDirectoryTable.obj\ + $(OBJDIR)\cdevSvcFinder.obj + +targets : copyobjs copyincs + +copyobjs : $(OBJS) + -@if not exist ..\lib\$(OBJDIR) mkdir ..\lib\$(OBJDIR) + -@for %x in ($(OBJDIR)\*.obj) DO @copy %x ..\lib\$(OBJDIR) > nul + +copyincs : + -@for %x in (*.h *.i) DO @copy %x $(CDEV)\include > nul + diff --git a/src/directory/StringHash.h b/src/directory/StringHash.h new file mode 100755 index 0000000..afdfb40 --- /dev/null +++ b/src/directory/StringHash.h @@ -0,0 +1,235 @@ +#ifndef _VAR_STRING_HASH_H_ +#define _VAR_STRING_HASH_H_ 1 + +#include +#include +#include + +class StringHashNode +{ +friend class StringHash; +friend class StringHashIterator; + +private: + int copyKeyFlag; + char * hashString; + void * hashData; + StringHashNode * next; + + StringHashNode ( char * HashString, void * HashData, int copyKey=1); + ~StringHashNode ( void ); +}; + + +class StringHash +{ +friend class StringHashIterator; + +private: + int tableSize; + int copyKeyFlag; + StringHashNode ** nodes; + +public: + StringHash (int copyKey = 1, int TableSize = 255 ); + ~StringHash ( void ); + + inline unsigned int stringHash ( char * hashString ); + + inline void insert ( char * hashString, void * hashData ); + inline void remove ( char * hashString ); + inline void * find ( char * hashString ); +}; + + +class StringHashIterator +{ +private: + StringHash * hashTbl; + StringHashNode * node; + int idx; + +public: + StringHashIterator( StringHash * HashTbl ); + ~StringHashIterator( void ); + + inline void * first ( void ); + inline void * operator ++ ( void ); + inline void * operator ++ ( int x ); + inline char * key ( void ); + inline void * data ( void ); +}; + + +inline StringHashNode::StringHashNode ( char * HashString, void * HashData, int copyKey ) + : next(NULL), copyKeyFlag(copyKey) + { + if(copyKeyFlag) hashString = strdup(HashString); + else hashString = HashString; + hashData = HashData; + } + + +inline StringHashNode::~StringHashNode ( void ) + { + if(copyKeyFlag) delete hashString; + } + + +inline StringHash::StringHash ( int copyKey, int TableSize ) + : copyKeyFlag(copyKey), tableSize (TableSize) + { + nodes = new StringHashNode * [tableSize]; + memset(nodes, 0, sizeof(StringHashNode *) * tableSize ); + } + + +inline StringHash::~StringHash ( void ) + { + for(int i=0; inext; + delete node; + } + } + delete nodes; + } + +inline unsigned int StringHash::stringHash ( char * hashString ) + { + unsigned int hash = 0, g; + + for (int i = 0; hashString[i] != '\0'; i++) + { + hash = (hash << 4) + hashString[i]; + if (g = hash & 0xf0000000) + { + hash ^= g >> 24; + hash ^= g; + } + } + return (hash % tableSize); + } + +inline void StringHash::insert (char * hashString, void * hashData ) + { + unsigned int idx = stringHash(hashString); + StringHashNode * prev = NULL, * node = nodes[idx]; + StringHashNode * newNode = new StringHashNode(hashString, hashData, copyKeyFlag); + + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + newNode->next = node->next; + delete node; + } + if(prev!=NULL) prev->next = newNode; + else nodes[idx] = newNode; + } + +inline void StringHash::remove ( char * hashString ) + { + unsigned int idx = stringHash(hashString); + StringHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + if(node!=NULL) + { + if(prev!=NULL) prev->next = node->next; + else nodes[idx] = node->next; + delete node; + } + } + +inline void * StringHash::find ( char * hashString ) + { + unsigned int idx = stringHash(hashString); + StringHashNode * prev = NULL, * node = nodes[idx]; + while(node!=NULL && strcmp(node->hashString, hashString)) + { + prev = node; + node = prev->next; + } + return node!=NULL?node->hashData:NULL; + } + + +inline StringHashIterator::StringHashIterator(StringHash * HashTbl) + : hashTbl(HashTbl), idx(0), node(NULL) + { + } + +inline StringHashIterator::~StringHashIterator( void ) + { + } + +inline void * StringHashIterator::first ( void ) + { + if(hashTbl!=NULL) + { + for(idx = 0; idxtableSize && + (node = hashTbl->nodes[idx])==NULL; idx++); + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * StringHashIterator::operator ++ ( void ) + { + if(hashTbl!=NULL) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxtableSize && + (node = hashTbl->nodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline void * StringHashIterator::operator ++ ( int x ) + { + if(hashTbl!=NULL && x==0) + { + if(node==NULL) first(); + else if(node->next!=NULL) node = node->next; + else + { + node = NULL; + do { + idx++; + } while(idxtableSize && + (node = hashTbl->nodes[idx])==NULL); + } + } + else node = NULL; + return (node!=NULL)?node->hashData:NULL; + } + +inline char * StringHashIterator::key ( void ) + { + return (node!=NULL)?node->hashString:(char *)NULL; + } + +inline void * StringHashIterator::data ( void ) + { + return (node!=NULL)?node->hashData:NULL; + } + +#endif /* _VAR_STRING_HASH_H_ */ diff --git a/src/directory/cdevAccount.cc b/src/directory/cdevAccount.cc new file mode 100755 index 0000000..1d00af6 --- /dev/null +++ b/src/directory/cdevAccount.cc @@ -0,0 +1,843 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevAccount classes: These classes provide the basic functionality +// for CDEV accounting. +// +// Author: Walt Akers +//----------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ***************************************************************************** +// * Define _IGNORE_ARGV_ to prevent the application from learning the program +// * name using dubious measures. +// ***************************************************************************** +#define _IGNORE_ARGV_ 1 + +char cdevAccountRecord::tempBuf[cdevAccountRecord::MAX_TEMP_BUF]; + +cdevAccountEntry *cdevGlobalAccountEntry = NULL; + +// ***************************************************************************** +// * This is the method that will be register with at exit in order to remove +// * the cdevGlobalAccountEntry. +// ***************************************************************************** +void removeGlobalAccountRecord ( void ) + { + if(cdevGlobalAccountEntry!=NULL) + { + delete cdevGlobalAccountEntry; + cdevGlobalAccountEntry = NULL; + } + } + +// ***************************************************************************** +// * cdevAccountRecord::cdevAccountRecord : +// * This is the constructor for the cdevAccountRecord object. It initializes +// * all of the internal variables. +// ***************************************************************************** +cdevAccountRecord::cdevAccountRecord ( void ) : + serviceCnt(0), serviceList(0), serviceMax(0), argList(0), argCnt(0), next(NULL) + { + reset(); + } + +// ***************************************************************************** +// * cdevAccountRecord::~cdevAccountRecord : +// * This is the destructor for the cdevAccountRecord object. it deletes any +// * memory that may have been allocated by the class. +// ***************************************************************************** +cdevAccountRecord::~cdevAccountRecord ( void ) + { + reset(); + } + +// ***************************************************************************** +// * cdevAccountRecord::reset : +// * This method restores the data objects in the class to their initial +// * values. +// ***************************************************************************** +void cdevAccountRecord::reset ( void ) + { + int i; + + for(i=0; i0) + { + tempBuf[amntread] = 0; + for(sPtr=tempBuf; isspace(*sPtr) && *sPtr; sPtr++); + if((sPtr = strchr(sPtr, '\n'))!=NULL) + { + *sPtr = 0; + lseek(fd, startPos+strlen(tempBuf), SEEK_SET); + } + streamIn(tempBuf); + } + return (*hostName==0 || processID==0 || *cdevVersion==0)?-1:0; + } + +// ***************************************************************************** +// * cdevAccountRecord::streamIn : +// * This method allows the caller to read the next available accounting +// * record from a previously loaded data buffer. This function will return +// * a pointer to the next character following the record in the data buffer. +// ***************************************************************************** +char * cdevAccountRecord::streamIn ( char * buf ) + { + int i; + char * ptr = NULL; + char * ePtr = NULL; + char * retval = NULL; + + reset(); + + while(buf && isspace(*buf) && *buf) buf++; + if(buf && *buf && (ePtr = strchr(buf, '\n'))!=NULL) + { + *ePtr = 0; + retval = ePtr; + } + else if(buf && *buf) retval = buf+strlen(buf); + else retval = NULL; + + if(buf && *buf) strcpy(hostName, ((ptr=strtok(buf, ";"))==NULL)?"\0":ptr); + if(ptr) processID = ((ptr=strtok(NULL, ";"))==NULL)?0:atoi(ptr); + if(ptr) strcpy(startTime, ((ptr=strtok(NULL, ";"))==NULL)?"\0":ptr); + if(ptr) strcpy(appName, ((ptr=strtok(NULL, ";"))==NULL)?"\0":ptr); + if(ptr) strcpy(userName, ((ptr=strtok(NULL, ";"))==NULL)?"\0":ptr); + if(ptr) strcpy(osName, ((ptr=strtok(NULL, ";"))==NULL)?"\0":ptr); + if(ptr) strcpy(osRelease, ((ptr=strtok(NULL, ";"))==NULL)?"\0":ptr); + if(ptr) strcpy(cdevVersion, ((ptr=strtok(NULL, ";"))==NULL)?"\0":ptr); + if(ptr && (argCnt = ((ptr=strtok(NULL, ";"))==NULL)?0:atoi(ptr))>0) + { + argList = new char *[argCnt+1]; + for(i=0; i0) + { + serviceMax = serviceCnt+1; + serviceList = new char *[serviceMax+1]; + for(i=0; i0?serviceList[0]:"\0"); + for(i=1; i0) delete argList[--argCnt]; + if(argList!=NULL) + { + delete argList; + argList = NULL; + } + if(nArgs>0) + { + char * ptr; + argList = new char *[nArgs+1]; + for(argCnt=0; argCnt0) delete serviceList[--serviceCnt]; + if(serviceList!=NULL) + { + delete serviceList; + serviceList = NULL; + } + + if(nServices>0) + { + serviceMax = (nServices>32)?nServices:32; + serviceList = (char **)malloc((serviceMax+1)*sizeof(char *)); + for(serviceCnt=0; serviceCnt=serviceMax) + { + serviceMax = (serviceMax==0)?32:serviceMax*2; + if(serviceList) serviceList=(char **)realloc(serviceList, (serviceMax+1)*sizeof(char *)); + else serviceList = (char **)malloc((serviceMax+1)*sizeof(char *)); + } + serviceList[serviceCnt++] = strdup(ServiceName); + serviceList[serviceCnt] = NULL; + } + } + + +// **************************************************************************** +// * cdevAccountEntry::cdevAccountEntry : +// * This is the constructor for the class. Its only task is to determine +// * the name of the CDEV Accounting File and call initialize to populate +// * the class with the CDEV application data. +// **************************************************************************** +cdevAccountEntry::cdevAccountEntry ( char * OutputFile ) + : cdevAccountRecord() + { + if(OutputFile && *OutputFile) strcpy(outputFile, OutputFile); + else { + char * ptr = getenv("CDEV_ACCOUNT_FILE"); + if(ptr) strcpy(outputFile, ptr); + else { + ptr = getenv("CDEVDDL"); + if(ptr) + { + sprintf(outputFile, "%s", ptr); + if((ptr = strrchr(outputFile, '/'))!=NULL) ptr++; + else ptr = outputFile; + strcpy(ptr, "cdevAccount.txt"); + } + else sprintf(outputFile, "/usr/local/lib/cdevAccount.txt"); + } + } + initialize(); + } + +// **************************************************************************** +// * cdevAccountEntry::~cdevAccountEntry : +// * This is the destructor for the cdevAccountEntry class, it will remove +// * this record from the CDEV Accounting file. +// **************************************************************************** +cdevAccountEntry::~cdevAccountEntry ( void ) + { + removeRecord(); + } + +// ***************************************************************************** +// * cdevAccountEntry::initialize: +// * The initialize method will read all of the current information about the +// * application and write it to the outputFile. +// ***************************************************************************** +void cdevAccountEntry::initialize ( void ) + { + // ********************************************************************* + // * Call reset to clear any data that may be stored in the + // * cdevAccountRecord. + // ********************************************************************* + reset(); + + // ********************************************************************* + // * Obtain the process ID of the application. + // ********************************************************************* + setProcessID(getpid()); + + // ********************************************************************* + // * Set the current time. + // ********************************************************************* + time_t t1; + time(&t1); + setStartTime(t1); + + // ********************************************************************* + // * Get the name of the owner. + // ********************************************************************* + char *loginName = getlogin(); + if(loginName==NULL) loginName = (char *)getenv("USER"); + setUserName(loginName); + + // ********************************************************************* + // * Get the name of the local host. + // ********************************************************************* + gethostname(hostName, 128); + if(*hostName) + { + struct hostent * ePtr = gethostbyname(hostName); + if(ePtr!=NULL && ePtr->h_name!=NULL) strcpy(hostName, ePtr->h_name); + } + + // ********************************************************************* + // * Get the CDEV Version string. + // ********************************************************************* + sprintf(cdevVersion, + "%s.%s %s", + cdevSystem::CDEV_MAJOR_VERSION, + cdevSystem::CDEV_MINOR_VERSION, + #ifdef SHOBJ + "Shared" + #else + "Archive" + #endif + ); + + // ********************************************************************* + // * Get the operating system name and revision. + // ********************************************************************* + struct utsname u; + uname(&u); + setSystemName(u.sysname); + setSystemRelease(u.release); + + // ********************************************************************* + // * This approach is one that I would never recommend, however, + // * it seems to work consistently and it is expedient. + // ********************************************************************* + #ifndef _IGNORE_ARGV_ + char ** argv = environ-2; + int argc = 0; + + while(*argv && argv) + { + argv--; + argc++; + } + argv++; + argc--; + setAppName(*argv); + if(argc>0) setArguments(++argv, argc); + #endif + + // ********************************************************************* + // * Call the updateRecord method to write the new entry to disk. + // ********************************************************************* + updateRecord(); + } + + +// ***************************************************************************** +// * cdevAccountEntry::addService : +// * This method is called when a new service is loaded by cdev. The method +// * will call the addService method of the cdevAccountRecord to place the +// * entry in the database and will then call the updateRecord method to +// * write the updated entry to the outputFile. +// ***************************************************************************** +void cdevAccountEntry::addService ( char * serviceName ) + { + cdevAccountRecord::addService ( serviceName ); + updateRecord(); + } + +// ***************************************************************************** +// * cdevAccountEntry::updateRecord : +// * This method will write the data stored in the cdevAccountRecord to the +// * formatted ASCII output file specified by outputFile. +// ***************************************************************************** +int cdevAccountEntry::updateRecord ( void ) + { + int fd = -1; + + // ********************************************************************* + // * Call removeRecord to remove the current record if it exists. + // ********************************************************************* + removeRecord(); + + // ********************************************************************* + // * Create the file if it does not already exist. + // ********************************************************************* + if(access(outputFile, 00)) + { + fd = creat(outputFile, S_IRWXU|S_IRWXG|S_IRWXO); + fchmod(fd, S_IRWXU|S_IRWXG|S_IRWXO); + close(fd); + } + + // ********************************************************************* + // * Open the file and install a lock to ensure the data is + // * not modified during the update. Then write the record to + // * the end of the file. + // ********************************************************************* + if((fd = open(outputFile, O_RDWR))>0) + { + lockf(fd, F_LOCK, 0L); + lseek(fd, 0L, SEEK_END); + streamOut(fd); + close(fd); + } + return (fd>0)?0:-1; + } + + +// ***************************************************************************** +// * cdevAccountEntry::removeRecord : +// * This method will remove the current cdevAccountRecord entry from the +// * outputFile. +// ***************************************************************************** +int cdevAccountEntry::removeRecord ( void ) + { + FILE * fp = NULL; + + // ******************************************************************** + // * Open the file for read/write and then obtain a lock. + // ******************************************************************** + if((fp = fopen(outputFile, "r+"))!=NULL) + { + char key[128]; + int keyLen; + size_t amntread; + int found = 0; + long startPos; + long endPos; + + // ************************************************************ + // * Write the identification key into a string and use it to + // * search for the record before going to the trouble of + // * processing all of the data. + // ************************************************************ + sprintf(key, "%s;%i;", getHostName(), getProcessID()); + keyLen = strlen(key); + + // ************************************************************ + // * Lock the file and start processing entries. This function + // * relies on a special understanding of the format of the + // * data and performs a string comparison of the beginning of + // * the record with a special key string. + // * + // * This function will also use the tempBuf string that is + // * contained in the cdevAccountRecord super-class to read the + // * data. + // ************************************************************ + lockf(fileno(fp), F_LOCK, 0L); + + // ************************************************************ + // * Begin reading records from the data file. Record the + // * start position of the record. + // ************************************************************ + while(!found && + (startPos = ftell(fp))>=0 && + (fgets(tempBuf, MAX_TEMP_BUF, fp))!=NULL) + { + found = !strncmp(tempBuf, key, keyLen); + } + + // ************************************************************ + // * Once a matching record has been found, begin readig blocks + // * of data and writing them to the old records position. + // ************************************************************ + while(found && + (amntread = fread(tempBuf, 1, MAX_TEMP_BUF-1, fp))>0) + { + tempBuf[amntread] = 0; + endPos = ftell(fp); + fseek(fp, startPos, SEEK_SET); + fwrite(tempBuf, 1, amntread, fp); + startPos = ftell(fp); + fseek(fp, endPos, SEEK_SET); + } + + // ************************************************************* + // * Truncate the file to remove any old data that may follow + // * the last record. + // ************************************************************* + if(found) ftruncate(fileno(fp), startPos); + + // ************************************************************* + // * Close the file descriptor, this will automatically release + // * the lock. + // ************************************************************* + fclose(fp); + } + return (fp!=NULL)?0:-1; + } diff --git a/src/directory/cdevAccount.h b/src/directory/cdevAccount.h new file mode 100755 index 0000000..384d464 --- /dev/null +++ b/src/directory/cdevAccount.h @@ -0,0 +1,154 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevAccount classes: These classes provide the basic functionality +// for CDEV accounting. +// +// Author: Walt Akers +//----------------------------------------------------------------------------- + +#ifndef _CDEV_ACCOUNT_H_ +#define _CDEV_ACCOUNT_H_ 1 + +#include + +// ***************************************************************************** +// * class cdevAccountRecord : +// * The cdevAccountRecord class is used to store information about a single +// * CDEV application. This class contains the mechanisms necessary to write +// * this information to a disk file and then read entries back in sequentially +// ***************************************************************************** +class cdevAccountRecord +{ +public: + enum {MAX_TEMP_BUF=4096}; + + cdevAccountRecord ( void ); + ~cdevAccountRecord ( void ); + + void reset ( void ); + int streamIn ( FILE * fp ); + int streamIn ( int fd ); + char * streamIn ( char * ptr ); + int streamOut ( FILE * fp ); + int streamOut ( int fd ); + + void asciiDump ( FILE * fp = stdout ); + + cdevAccountRecord * getNext ( void ); + void setNext ( cdevAccountRecord * Next ); + + pid_t getProcessID ( void ); + void setProcessID ( pid_t ProcessID ); + char * getStartTime ( void ); + void setStartTime ( time_t StartTime ); + char * getAppName ( void ); + void setAppName ( char * AppName ); + char ** getArguments ( void ); + void setArguments ( char ** args, int nArgs); + char * getUserName ( void ); + void setUserName ( char * UserName ); + char * getHostName ( void ); + void setHostName ( char * HostName ); + char * getSystemName ( void ); + void setSystemName ( char * OSName ); + char * getSystemRelease ( void ); + void setSystemRelease ( char * OSRelease ); + char * getCDEVVersion ( void ); + void setCDEVVersion ( char * CDEVVersion ); + char ** getServiceList ( void ); + void setServiceList ( char ** ServiceList, int nServices ); + void addService ( char * ServiceName ); + +protected: + // ********************************************************************* + // * This is the pointer to the next cdevAccountRecord object that may + // * be stored in a cdevAccountTable + // ********************************************************************* + cdevAccountRecord * next; + + // ********************************************************************* + // * This is a static buffer that will be used to perform reads + // * whenever the size of the data to be read does not exceed the + // * basic size. + // ********************************************************************* + static char tempBuf[MAX_TEMP_BUF]; + + // ********************************************************************* + // * This is the process ID of the running CDEV application. + // ********************************************************************* + pid_t processID; + + // ********************************************************************* + // * This is the time that the application was started. + // ********************************************************************* + char startTime [20]; + + // ********************************************************************* + // * This is the name of the application and the arguments that were + // * provided when it was started. + // ********************************************************************* + char appName [256]; + int argCnt; + char ** argList; + + // ********************************************************************* + // * This is the name of the user that started the application. + // ********************************************************************* + char userName [128]; + + // ********************************************************************* + // * This is the name of the host where the application was started + // * and pertinent information about the operating system. + // ********************************************************************* + char hostName [128]; + char osName [32]; + char osRelease [32]; + + // ********************************************************************* + // * This is the version of CDEV that the application is using. + // * Includes the suffix (SHARED) or (ARCHIVE). + // ********************************************************************* + char cdevVersion[64]; + + // ********************************************************************* + // * These are the services that the application has loaded. + // ********************************************************************* + int serviceCnt; + int serviceMax; + char ** serviceList; +}; + + +// ***************************************************************************** +// * class cdevAccountEntry: +// * This class is used to create a single instance of a cdevAccountRecord +// * that will be associated with a CDEV application. This class instance +// * will be called to write accounting information to the CDEV Accounting +// * file whenever a significant event (start-up, service load, shutdown) +// * occurs. +// ***************************************************************************** +class cdevAccountEntry : public cdevAccountRecord +{ +public: + cdevAccountEntry ( char * OutputFile = NULL ); + ~cdevAccountEntry ( void ); + int updateRecord ( void ); + int removeRecord ( void ); + void initialize ( void ); + void addService ( char * service ); + +private: + char outputFile[256]; +}; + +extern cdevAccountEntry * cdevGlobalAccountEntry; + +#endif /* _CDEV_ACCOUNT_H_ */ diff --git a/src/directory/cdevAliasDefinition.h b/src/directory/cdevAliasDefinition.h new file mode 100755 index 0000000..e6fa268 --- /dev/null +++ b/src/directory/cdevAliasDefinition.h @@ -0,0 +1,117 @@ +#ifndef _CDEV_ALIAS_DEFINITION_H_ +#define _CDEV_ALIAS_DEFINITION_H_ + +#ifndef _CDEV_DIRECTORY_TABLE_H_ + #error "You must include cdevDirectoryTable.h to load cdevAliasDefinition.h" +#endif + +#include + +// ***************************************************************************** +// * class cdevAliasDefinition : +// * This class stores the name of an alias and a reference to the device +// * definition that it is associated with. +// * +// * This class maintains a variety of internal data items for the following +// * purposes... +// * +// * alias - This is the name of the alias. +// * device - This is the cdevDeviceDefinition for the device that it +// * references. +// * next - This is the next alias in the list. +// ***************************************************************************** +class cdevAliasDefinition +{ +private: + char * name; + cdevDeviceDefinition & device; + cdevAliasDefinition * next; + +public: + inline cdevAliasDefinition ( char * Name, cdevDeviceDefinition & Device ); + inline ~cdevAliasDefinition ( void ); + inline void asciiDump ( FILE * fp = stdout ); + + // ********************************************************************* + // * Member access methods. + // ********************************************************************* + inline char * getName ( void ); + inline cdevDeviceDefinition & getDevice ( void ); + inline cdevAliasDefinition * getNext ( void ); + inline void setNext ( cdevAliasDefinition * Next ); + +}; + + + +// ***************************************************************************** +// * cdevAliasDefinition::cdevAliasDefinition : +// * This is the constructor for the cdevAliasDefinition class. The Name +// * pointer becomes the property of the class and should not be accessed +// * by the caller after it has been provided to this constructor. +// ***************************************************************************** +inline cdevAliasDefinition::cdevAliasDefinition + ( char * Name, cdevDeviceDefinition & Device ) + : name(Name), device(Device), next(NULL) + { + } + + +// ***************************************************************************** +// * cdevAliasDefinition::~cdevAliasDefinition : +// * This is the destructor faor the cdevAliasDefinition class. +// ***************************************************************************** +inline cdevAliasDefinition::~cdevAliasDefinition ( void ) + { + delete name; + } + +// ***************************************************************************** +// * cdevAliasDefinition::~cdevAliasDefinition : +// * This is the destructor for the cdevAliasDefinition class. +// ***************************************************************************** +inline void cdevAliasDefinition::asciiDump ( FILE * fp ) + { + fprintf(fp, "alias %s %s\n", name, device.getName()); + } + + +// ***************************************************************************** +// * cdevAliasDefinition::getName : +// * This method allows the caller to obtain the name of the alias. +// ***************************************************************************** +inline char * cdevAliasDefinition::getName ( void ) + { + return name; + } + +// ***************************************************************************** +// * cdevAliasDefinition::getDevice : +// * This method allows the caller to retrieve the device definition +// * associated with the object. +// ***************************************************************************** +inline cdevDeviceDefinition & cdevAliasDefinition::getDevice ( void ) + { + return device; + } + +// ***************************************************************************** +// * cdevAliasDefinition::getNext : +// * This method allows the caller to get the next alias in the list. +// ***************************************************************************** +inline cdevAliasDefinition * cdevAliasDefinition::getNext ( void ) + { + return next; + } + +// ***************************************************************************** +// * cdevAliasDefinition::setNext : +// * This method allows the caller to set the next alias in the list. +// ***************************************************************************** +inline void cdevAliasDefinition::setNext ( cdevAliasDefinition * Next ) + { + next = Next; + } + + +#endif /* _CDEV_ALIAS_DEFINITION_H_ */ diff --git a/src/directory/cdevClassDefinition.h b/src/directory/cdevClassDefinition.h new file mode 100755 index 0000000..0fc6320 --- /dev/null +++ b/src/directory/cdevClassDefinition.h @@ -0,0 +1,697 @@ +#ifndef _CDEV_CLASS_DEFINITION_H_ +#define _CDEV_CLASS_DEFINITION_H_ + +#ifndef _CDEV_DIRECTORY_TABLE_H_ + #error "You must include cdevDirectoryTable.h to load cdevClassDefinition.h" +#endif + +// ***************************************************************************** +// * class cdevClassDefinition : +// * This class stores the definition of a single CDEV DDL class and all +// * of its associated verbs, attributes and messages. +// * +// * This class maintains a variety of internal data items for the following +// * purposes... +// * +// * directory - This is the cdevDirectoryTable that the class definition +// * is a member of... +// * +// * name - This is the name of the class as defined in the CDEV DDL +// * file. +// * +// * verbs - This is a list of cdevElementDefinitions that identify +// * each verb that was defined within the class definition. +// * +// * attributes - This is a list of cdevElementDefinitions that identify +// * each attribute that was defined within the class +// * definition. +// * +// * messages - This is a list of cdevElementDefinitions that identify +// * each messages that was defined within the class defintion. +// * +// * parent - This is the class definition for the class that this one +// * inherited from - if any. +// * +// * deviceHead - This is a list of device definitions for all devices that +// * deviceTail were created from this class. +// * +// * redirector - This is a table of all complete messages that this class +// * will support. This table is only generated if devices are +// * instanciated from the class - and it includes the message +// * contents from all parent classes. +// * +// * next - This is the next class definition that occurs... This list +// * is maintained in the cdevDirectoryTable object. +// ***************************************************************************** +class cdevClassDefinition +{ +private: + cdevDirectoryTable & directory; + cdevClassDefinition * next; + char * name; + cdevElementDefinition * verbs; + cdevElementDefinition * attributes; + cdevElementDefinition * messages; + cdevClassDefinition * parent; + cdevDeviceDefinition * deviceHead; + cdevDeviceDefinition * deviceTail; + StringHash redirector; + +public: + inline cdevClassDefinition(cdevDirectoryTable &Master, + char *Name = NULL, + cdevClassDefinition *Parent = NULL, + cdevElementDefinition *Verbs = NULL, + cdevElementDefinition *Attributes = NULL, + cdevElementDefinition *Messages = NULL); + inline ~cdevClassDefinition ( void ); + inline int addElement (cdevElementDefinition *&target, + cdevElementDefinition * element ); + inline int addElement (cdevElementDefinition *& target, + char * eleName, + cdevServiceDefinition * service, + char ** serviceData, + int nItems); + inline int addDevice (char * device, char * substName = NULL ); + inline int addVerb (char * eleName, cdevServiceDefinition *service, char ** serviceData, int nItems ); + inline int addVerb (cdevElementDefinition * element ); + inline int addAttribute (char * eleName, cdevServiceDefinition *service, char ** serviceData, int nItems ); + inline int addAttribute (cdevElementDefinition * element ); + inline int addMessage (char * eleName, cdevServiceDefinition *service, char ** serviceData, int nItems ); + inline int addMessage (cdevElementDefinition * element ); + inline int isA (char * className ); + inline void asciiDump (FILE * fp = stdout ); + inline void asciiDumpInstances ( FILE * fp = stdout ); + inline void asciiDumpRedirector ( FILE * fp = stdout ); + inline void createRedirectionTable ( void ); + + // ********************************************************************* + // * Member access functions: + // ********************************************************************* + inline char * getName ( void ); + inline cdevDirectoryTable & getDirectory ( void ); + inline cdevClassDefinition * getParent ( void ); + inline cdevElementDefinition * getVerbs ( void ); + inline cdevElementDefinition * getAttributes ( void ); + inline cdevElementDefinition * getMessages ( void ); + inline cdevDeviceDefinition * getDevices ( void ); + inline StringHash & getRedirector ( void ); + inline int getElements ( cdevDirectoryTable::ElementType type, + cdevElementDefinition ** &def, + int &nItems ); + inline cdevClassDefinition * getNext ( void ); + inline void setNext ( cdevClassDefinition * Next ); + +}; + + +// ***************************************************************************** +// * cdevClassDefinition::cdevClassDefinition : +// * This is the constructor for the class definition object. I +// ***************************************************************************** +inline cdevClassDefinition::cdevClassDefinition + ( cdevDirectoryTable &Master, + char *Name, + cdevClassDefinition *Parent, + cdevElementDefinition *Verbs, + cdevElementDefinition *Attributes, + cdevElementDefinition *Messages) + : directory (Master), + name (Name), + parent (Parent), + verbs (Verbs), + attributes (Attributes), + messages (Messages), + deviceHead (NULL), + deviceTail (NULL), + next (NULL) + { + } + +// ***************************************************************************** +// * cdevClassDefinition::~cdevClassDefinition : +// * This is the descructor for the cdevClassDefinition object. It will +// * delete the class name and each item from the elements list. +// ***************************************************************************** +inline cdevClassDefinition::~cdevClassDefinition ( void ) + { + cdevElementDefinition * ptr; + cdevDeviceDefinition * dPtr; + cdevRedirectorDefinition * rPtr; + StringHashIterator iter(&redirector); + + delete name; + + while(verbs!=NULL) + { + ptr = verbs; + verbs = verbs->getNext(); + delete ptr; + } + while(messages!=NULL) + { + ptr = messages; + messages = messages->getNext(); + delete ptr; + } + while(attributes!=NULL) + { + ptr = attributes; + attributes = attributes->getNext(); + delete ptr; + } + while(deviceHead!=NULL) + { + dPtr = deviceHead; + deviceHead = deviceHead->getNext(); + directory.getDeviceHash().remove(dPtr->getName()); + delete dPtr; + } + for(iter.first(); (rPtr = (cdevRedirectorDefinition *)iter.data())!=NULL; ) + { + iter++; + redirector.remove(rPtr->getName()); + delete rPtr; + } + } + +// ***************************************************************************** +// * cdevClassDefinition::addElement : +// * This method is used to add an element (verb, attribute, or message) to +// * the cdevClassDefinition. The target parameter is a reference to the +// * list that will receive the incoming element. +// ***************************************************************************** +inline int cdevClassDefinition::addElement + ( cdevElementDefinition *&target, + cdevElementDefinition * element ) + { + cdevElementDefinition *curr, *prev; + int result = CDEV_SUCCESS; + + for(curr=target, prev=NULL; + curr!=NULL && strcmp(curr->getName(), element->getName()); + curr=curr->getNext()) + { + prev = curr; + } + if(curr == NULL) + { + if(prev) prev->setNext(new cdevElementDefinition(element)); + else target = new cdevElementDefinition(element); + } + else result = CDEV_ERROR; + return result; + } + +// ***************************************************************************** +// * cdevClassDefinition::addElement : +// * This method will create a new element and add it to the list of elements +// * that is reference by the target paremeter. +// ***************************************************************************** +inline int cdevClassDefinition::addElement + (cdevElementDefinition *& target, + char * eleName, + cdevServiceDefinition * service, + char ** serviceData, + int nItems) + { + cdevElementDefinition *curr, *prev; + int result = CDEV_SUCCESS; + + for(curr=target, prev=NULL; + curr!=NULL && strcmp(curr->getName(), eleName); + curr=curr->getNext()) + { + prev = curr; + } + if(curr == NULL) + { + if(prev) prev->setNext(new cdevElementDefinition(eleName, service, serviceData, nItems)); + else target = new cdevElementDefinition(eleName, service, serviceData, nItems); + } + else result = CDEV_ERROR; + return result; + } + +// ***************************************************************************** +// * cdevClassDefinition::addDevice : +// * This method will add a new device to the device list. This device name +// * will also be placed in the hashTable in the cdevDirectoryTable object +// * specified by directory. +// * +// * Note the device name becomes the property of the cdevDeviceDefinition +// * class and should not be deleted. +// * +// * The redirection table for this device will also be created as the +// * first device is instanciated. +// ***************************************************************************** +inline int cdevClassDefinition::addDevice ( char * device, char * substName ) + { + int result = CDEV_SUCCESS; + + if(device!=NULL && directory.getDeviceHash().find(device)==NULL) + { + cdevDeviceDefinition * def = + new cdevDeviceDefinition(directory, device, substName, *this); + + if(deviceTail==NULL) + { + deviceHead = def; + deviceTail = def; + createRedirectionTable(); + directory.addClassInstance(this); + } + else { + deviceTail->setNext( def ); + deviceTail = def; + } + + directory.addDevice(def); + } + else result = CDEV_ERROR; + + return result; + } + +// ***************************************************************************** +// * cdevClassDefinition::addVerb : +// * This method will add a verb to the verbs element definition list. +// ***************************************************************************** +inline int cdevClassDefinition::addVerb + ( char * eleName, cdevServiceDefinition *service, char ** serviceData, int nItems ) + { + return addElement(verbs, eleName, service, serviceData, nItems); + } + +// ***************************************************************************** +// * cdevClassDefinition::addVerb : +// * This method will add a verb to the verbs element definition list. +// ***************************************************************************** +inline int cdevClassDefinition::addVerb ( cdevElementDefinition * element ) + { + return addElement(verbs, element); + } + +// ***************************************************************************** +// * cdevClassDefinition::addAttribute : +// * This method will add an attribute to the attributes element +// * definition list. +// ***************************************************************************** +inline int cdevClassDefinition::addAttribute + ( char * eleName, cdevServiceDefinition * service, char ** serviceData, int nItems ) + { + return addElement(attributes, eleName, service, serviceData, nItems); + } + +// ***************************************************************************** +// * cdevClassDefinition::addAttribute : +// * This method will add an attribute to the attributes element +// * definition list. +// ***************************************************************************** +inline int cdevClassDefinition::addAttribute ( cdevElementDefinition * element ) + { + return addElement(attributes, element); + } + +// ***************************************************************************** +// * cdevClassDefinition::addMessage : +// * This method will add a message to the messages element definition list. +// ***************************************************************************** +inline int cdevClassDefinition::addMessage + ( char * eleName, cdevServiceDefinition * service, char ** serviceData, int nItems ) + { + return addElement(messages, eleName, service, serviceData, nItems); + } + +// ***************************************************************************** +// * cdevClassDefinition::addMessage : +// * This method will add a message to the messages element definition list. +// ***************************************************************************** +inline int cdevClassDefinition::addMessage ( cdevElementDefinition * element ) + { + return addElement(messages, element); + } + +// ***************************************************************************** +// * cdevClassDefinition::isA : +// * This method will ascend the class hierarchy attempting to locate a +// * class with the name specified in className. It will return TRUE if this +// * class is or inherits from the specified className, or FALSE if not. +// ***************************************************************************** +inline int cdevClassDefinition::isA ( char * className ) + { + int result; + if(strcmp(name, className)==0) result = 1; + else if(parent!=NULL) result = parent->isA(className); + else result = 0; + return result; + } + +// ***************************************************************************** +// * cdevClassDefinition::asciiDump : +// * This method dumps the contents of the cdevClassDefinition to the user +// * specified file descriptor. +// ***************************************************************************** +inline void cdevClassDefinition::asciiDump ( FILE * fp ) + { + if(name) + { + fprintf(fp, "\nclass %s", name); + if(parent) fprintf(fp, " : %s", parent->name); + fprintf(fp, "\n\t{\n"); + + if(verbs!=NULL) verbs->asciiDumpList(fp, "verbs"); + if(attributes!=NULL) attributes->asciiDumpList(fp, "attributes"); + if(messages!=NULL) messages->asciiDumpList(fp, "messages"); + + fprintf(fp, "\t}\n"); + } + } + + +// ***************************************************************************** +// * cdevClassDefinition::asciiDumpInstances : +// * This method dumps the instance data of the class definition to the +// * caller specified file descriptor. +// ***************************************************************************** +inline void cdevClassDefinition::asciiDumpInstances ( FILE * fp ) + { + if(deviceHead!=NULL) + { + cdevDeviceDefinition * device = deviceHead; + + fprintf(fp, "\n%s : \n", name); + while(device!=NULL) + { + if(device->getName()!=device->getSubstituteName()) + { + fprintf(fp, "\t%s {%s}\n", device->getName(), device->getSubstituteName()); + } + else fprintf(fp, "\t%s\n", device->getName()); + device = device->getNext(); + } + fprintf(fp, "\t;\n"); + } + } + + +// ***************************************************************************** +// * cdevClassDefinition::asciiDumpRedirector : +// * This method dumps the contents of the redirection table that is used +// * to route messages to their intended service. +// ***************************************************************************** +inline void cdevClassDefinition::asciiDumpRedirector ( FILE * fp ) + { + StringHashIterator iter(&redirector); + cdevRedirectorDefinition * def; + + fprintf(fp, "\n/* Redirection table for class %s */\n", name); + fprintf(fp, "class %s\n\t{\n\tmessages\n\t\t{\n", name); + for(iter.first(); + (def = (cdevRedirectorDefinition *)iter.data())!=NULL; + iter++) + { + def->asciiDump(fp); + } + fprintf(fp, "\t\t}\n\t}\n"); + } + + +// ***************************************************************************** +// * cdevClassDefinition::createRedirectionTable : +// * This method will read the verbs, attributes and messages and will +// * generate a redirection table that will allow the cdevDirectoryTable +// * to route requests to the correct service using the proper serviceData. +// ***************************************************************************** +inline void cdevClassDefinition::createRedirectionTable ( void ) + { + cdevRedirectorDefinition * def; + cdevElementDefinition ** msgPtr, ** vrbPtr, **atrPtr; + int msgCnt, vrbCnt, atrCnt; + int msgIdx, vrbIdx, atrIdx; + + // ********************************************************************* + // * Get a pointer to all of the verbs that are in use by the class. + // ********************************************************************* + getElements(cdevDirectoryTable::MESSAGE, msgPtr, msgCnt); + getElements(cdevDirectoryTable::VERB, vrbPtr, vrbCnt); + getElements(cdevDirectoryTable::ATTRIBUTE, atrPtr, atrCnt); + + // ********************************************************************* + // * Process through all of the messages and add them to the + // * redirection list first. Display a warning if they are already + // * present. + // ********************************************************************* + for(msgIdx=0; msgIdxgetName() && msgPtr[msgIdx]->getService()) + { + if(redirector.find(msgPtr[msgIdx]->getName())!=NULL) + { + cdevReportError(CDEV_SEVERITY_INFO, "CDEV Directory", NULL, + "Message %s already defined for class %s", + msgPtr[msgIdx]->getName(), name); + } + else { + def = new cdevRedirectorDefinition(strdup(msgPtr[msgIdx]->getName()), *msgPtr[msgIdx]); + redirector.insert(def->getName(), def); + } + } + } + + // ********************************************************************* + // * Walk through the verb list and combine them with each attribute... + // * For each verb that has a service associated with it, use the verbs + // * element definition... If the verb does not have a service, then + // * use the attributes element definition. + // ********************************************************************* + for(vrbIdx=0; vrbIdxgetName()) + { + // ***************************************************** + // * Using the verbs service. + // ***************************************************** + if(vrbPtr[vrbIdx]->getService()) + { + for(atrIdx=0; atrIdxgetName()!=NULL) + { + char * temp = new char[strlen(vrbPtr[vrbIdx]->getName())+strlen(atrPtr[atrIdx]->getName())+2]; + sprintf(temp, "%s %s", vrbPtr[vrbIdx]->getName(), atrPtr[atrIdx]->getName()); + if(redirector.find(temp)!=NULL) + { + cdevReportError(CDEV_SEVERITY_INFO, "CDEV Directory", NULL, + "Message %s already defined for class %s", + temp, name); + delete temp; + } + else { + def = new cdevRedirectorDefinition(temp, *vrbPtr[vrbIdx]); + redirector.insert(def->getName(), def); + } + } + } + } + // ***************************************************** + // * Using the attributes service. + // ***************************************************** + else for(atrIdx=0; atrIdxgetName() && atrPtr[atrIdx]->getService()) + { + char * temp = new char[strlen(vrbPtr[vrbIdx]->getName())+strlen(atrPtr[atrIdx]->getName())+2]; + sprintf(temp, "%s %s", vrbPtr[vrbIdx]->getName(), atrPtr[atrIdx]->getName()); + if(redirector.find(temp)!=NULL) + { + cdevReportError(CDEV_SEVERITY_INFO, "CDEV Directory", NULL, + "Message %s already defined for class %s", + temp, name); + delete temp; + } + else { + def = new cdevRedirectorDefinition(temp, *atrPtr[atrIdx]); + redirector.insert(def->getName(), def); + } + } + else { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Neither the verb nor the message for \"%s %s\" has a service", + vrbPtr[vrbIdx]->getName(), atrPtr[atrIdx]->getName()); + } + } + } + } + + // ********************************************************************* + // * Release the memory used to store the pointers. + // ********************************************************************* + if(msgPtr) delete msgPtr; + if(vrbPtr) delete vrbPtr; + if(atrPtr) delete atrPtr; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getElements : +// * This method allows the caller to retrieve a list of all element +// * definitions of a particular type from all subclasses of the current +// * class. +// ***************************************************************************** +inline int cdevClassDefinition::getElements ( cdevDirectoryTable::ElementType type, + cdevElementDefinition ** &def, + int &nItems ) + { + StringHash tempHash; + cdevClassDefinition * classDef = this; + + def = NULL; + nItems = 0; + + do + { + cdevElementDefinition * el = + type==cdevDirectoryTable::VERB?classDef->verbs: + (type==cdevDirectoryTable::ATTRIBUTE?classDef->attributes: + classDef->messages); + + for(; el!=NULL; el = el->getNext()) + { + if(tempHash.find(el->getName())==NULL) + { + tempHash.insert(el->getName(), el); + nItems++; + } + } + classDef = classDef->parent; + } while(classDef!=NULL); + + if(nItems!=0) + { + StringHashIterator iter(&tempHash); + + def = new cdevElementDefinition * [nItems]; + nItems = 0; + + for(iter.first(); iter.key()!=NULL; iter++) + { + def[nItems++] = (cdevElementDefinition *)iter.data(); + } + } + + return nItems; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getName : +// * This method allows the caller to retrieve the name of the class. +// ***************************************************************************** +inline char * cdevClassDefinition::getName ( void ) + { + return name; + } + + +// ***************************************************************************** +// * cdevClassDefinition:: : +// * This method allows the caller to retrieve the directory table that +// * owns this device. +// ***************************************************************************** +inline cdevDirectoryTable & cdevClassDefinition::getDirectory ( void ) + { + return directory; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getParent : +// * This method allows the caller to retrieve the class definition that +// * this class inherits from. +// ***************************************************************************** +inline cdevClassDefinition * cdevClassDefinition::getParent ( void ) + { + return parent; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getVerbs : +// * This method allows the caller to retrieve the lement definition list +// * containing all of the classes verbs. +// ***************************************************************************** +inline cdevElementDefinition * cdevClassDefinition::getVerbs ( void ) + { + return verbs; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getAttributes : +// * This method allows the caller to retrieve the element definition list +// * containing all of the classes verbs. +// ***************************************************************************** +inline cdevElementDefinition * cdevClassDefinition::getAttributes ( void ) + { + return attributes; + } + + + +// ***************************************************************************** +// * cdevClassDefinition::getMessages : +// * This method allows the caller to retrieve the element definition list +// * containing all of the classes messages. +// ***************************************************************************** +inline cdevElementDefinition * cdevClassDefinition::getMessages ( void ) + { + return messages; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getDevices : +// * This method allows the caller to retrieve the device definition list +// * containing all of the instances of the class. +// ***************************************************************************** +inline cdevDeviceDefinition * cdevClassDefinition::getDevices ( void ) + { + return deviceHead; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getRedirector : +// * This method allows the caller to retrieve the redirection list for +// * the class. +// ***************************************************************************** +inline StringHash & cdevClassDefinition::getRedirector ( void ) + { + return redirector; + } + + +// ***************************************************************************** +// * cdevClassDefinition::getNext : +// * This method allows the caller to retrieve the next class definition in +// * the list. +// ***************************************************************************** +inline cdevClassDefinition * cdevClassDefinition::getNext ( void ) + { + return next; + } + + +// ***************************************************************************** +// * cdevClassDefinition::setNext : +// * This method allows the caller to set the next class definition in the +// * list. +// ***************************************************************************** +inline void cdevClassDefinition::setNext ( cdevClassDefinition * Next ) + { + next = Next; + } + + +#endif /* _CDEV_CLASS_DEFINITION_H_ */ diff --git a/src/directory/cdevCollectionDefinition.h b/src/directory/cdevCollectionDefinition.h new file mode 100755 index 0000000..0bae254 --- /dev/null +++ b/src/directory/cdevCollectionDefinition.h @@ -0,0 +1,144 @@ +#ifndef _CDEV_COLLECTION_DEFINITION_H_ +#define _CDEV_COLLECTION_DEFINITION_H_ + +#ifndef _CDEV_DIRECTORY_TABLE_H_ + #error "You must include cdevDirectoryTable.h to load cdevCollectionDefinition.h" +#endif + +// ***************************************************************************** +// * class cdevCollectionDefinition : +// * This class stores information that identifies a specific device name +// * and associates it with a collection of devices. +// * +// * This class maintains a variety of internal data items for the following +// * purposes... +// * +// * name - This is the name of the device as specified in the DDL file. +// * directory - This is the cdevDirectoryTable object where the device was +// * registered. +// * cdevClass - This is the definition object for the class that the device +// * belongs to (collection). +// * devices - This is the list of devices that make up the collection. +// * deviceCnt - This is the number of devices in the list. +// * next - This is the next device in the linked list of +// * cdevCollectionDefinition objects. This list is maintained +// * as part of the cdevClassDefinition object. +// ***************************************************************************** +class cdevCollectionDefinition +{ +private: + char * name; + char ** devices; + int deviceCnt; + cdevCollectionDefinition * next; + +public: + inline cdevCollectionDefinition ( char * Name, + char ** Devices = NULL, + int DeviceCnt = 0 ); + inline ~cdevCollectionDefinition ( void ); + + inline void asciiDump ( FILE * fp = stdout ); + + // ********************************************************************* + // * Member access methods. + // ********************************************************************* + inline char * getName ( void ); + inline char ** getDevices ( void ); + inline int getDeviceCnt ( void ); + inline cdevCollectionDefinition * getNext ( void ); + inline void setNext ( cdevCollectionDefinition * Next ); +}; + + +// ***************************************************************************** +// * cdevCollectionDefinition::cdevCollectionDefinition : +// * This is the constructor for the cdevCollectionDefinition class. +// ***************************************************************************** +inline cdevCollectionDefinition::cdevCollectionDefinition + ( char * Name, char ** Devices, int DeviceCnt ) + : next(NULL), name(Name), devices(Devices), deviceCnt(DeviceCnt) + { + } + +// ***************************************************************************** +// * cdevCollectionDefinition::~cdevCollectionDefinition : +// * This is the destructor for the cdevCollectionDefinition class. +// ***************************************************************************** +inline cdevCollectionDefinition::~cdevCollectionDefinition ( void ) + { + if(name) delete name; + if(devices && deviceCnt) + { + while((--deviceCnt)>=0) delete devices[deviceCnt]; + } + if(devices) delete devices; + } + +// ***************************************************************************** +// * cdevCollectionDefinition::asciiDump : +// * Write the formatted output of the collection to the specified file +// * pointer. +// ***************************************************************************** +inline void cdevCollectionDefinition::asciiDump ( FILE * fp ) + { + if(devices && deviceCnt) + { + fprintf(fp, "\ncollection %s :\n", name); + for(int i=0; isend (message_, out, result); +} + + +int +cdevDirRequestObj::sendNoBlock (cdevData& out, cdevData& result) +{ + return sendNoBlock (&out, &result); +} + +int +cdevDirRequestObj::sendNoBlock (cdevData& out, cdevData* result) +{ + return sendNoBlock (&out, result); +} + +int +cdevDirRequestObj::sendNoBlock (cdevData* out, cdevData& result) +{ + return sendNoBlock (out, &result); +} + +int +cdevDirRequestObj::sendNoBlock (cdevData* out, cdevData* result) +{ + return device_->sendNoBlock (message_, out, result); +} + +int +cdevDirRequestObj::sendCallback (cdevData& out, cdevCallback& cbk) +{ + return sendCallback (&out, cbk); +} + +int +cdevDirRequestObj::sendCallback (cdevData* out, cdevCallback& cbk) +{ + return device_->sendCallback(message_, out, cbk); +} + + diff --git a/src/directory/cdevDirRequestObj.h b/src/directory/cdevDirRequestObj.h new file mode 100755 index 0000000..653208b --- /dev/null +++ b/src/directory/cdevDirRequestObj.h @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevRequestObject for cdevDirectory Class +// +// Author: Jie Chen +// +// Revision History: +// cdevDirRequestObj.h,v +// Revision 1.1 1998/02/13 14:01:45 chen +// enable request object for cdevDirectory +// +// +#ifndef _CDEV_DIR_REQUEST_OBJ_H +#define _CDEV_DIR_REQUEST_OBJ_H + +#include +#include +#include + +class CDEV_CLASS_SPEC cdevDirRequestObj: public cdevRequestObject +{ +public: + // constructor and destructor + cdevDirRequestObj (cdevDevice& device, char* msg, + cdevSystem& system = cdevSystem::defaultSystem ()); + + ~cdevDirRequestObj (void); + + int send (cdevData& out, cdevData& result); + int send (cdevData *out, cdevData& result); + int send (cdevData& out, cdevData* result); + int send (cdevData *out, cdevData* result); + + + int sendNoBlock (cdevData& out, cdevData& result); + int sendNoBlock (cdevData* out, cdevData& result); + int sendNoBlock (cdevData& out, cdevData* result); + int sendNoBlock (cdevData* out, cdevData* result); + + int sendCallback (cdevData& out, cdevCallback& callback); + int sendCallback (cdevData* out, cdevCallback& callback); + + const char *className (void) const {return "cdevDirRequestObj";} +}; +#endif + + diff --git a/src/directory/cdevDirectory.cc b/src/directory/cdevDirectory.cc new file mode 100755 index 0000000..142154f --- /dev/null +++ b/src/directory/cdevDirectory.cc @@ -0,0 +1,826 @@ +#ifdef _WIN32 +#include +#define access _access +#else +#include +#endif +#include +#include + +#include +#include +#include +#include + +// ***************************************************************************** +// * compressMessage : +// * This function is designed to walk through a message string +// * and remove any extraneous spaces or tabs. +// ***************************************************************************** +static void compressMessage ( char * string ) + { + if(string!=NULL) + { + while(*string) + { + if(isspace(*string)) + { + for(char *ptr=string; isspace(*ptr); ptr++); + if(*ptr==0) *string=0; + else if(ptr>string+1) + { + *(string++)=' '; + strcpy(string, ptr); + } + else string++; + } + else string++; + } + } + } + + +// ***************************************************************************** +// * compressMessage : +// * This function is designed to walk through a message string specified +// * within a cdevData object and remove any extraneous spaces or tabs. +// ***************************************************************************** +static void compressMessage( cdevData * data ) + { + static int MESSAGE_TAG = 0; + + // ********************************************************************* + // * If the data points to an actual cdevData object and the message + // * tag has been defined, then extract the message from the cdevData + // * object and remove any spaces that it might contain. + // * + // * Note that I am using the integer cdevData tags in order to reduce + // * the time required to extract and manipulate the message. + // ********************************************************************* + if(data && (MESSAGE_TAG || !cdevData::tagC2I("message", &MESSAGE_TAG))) + { + char * ptr = NULL; + data->find(MESSAGE_TAG, (void *&)ptr); + if(ptr && *ptr) compressMessage(ptr); + } + } + + + +// ***************************************************************************** +// * cdevDirectory::cdevDirectory : +// * This is the constructor for a cdevDirectory object. +// ***************************************************************************** +cdevDirectory::cdevDirectory(cdevSystem &system) + : cdevDevice("cdevDirectory", system), + node (NULL), + table (new cdevDirectoryTable()), + commandHash(new StringHash) + { + char *filename=::getenv("CDEVDDL"); + char extFilename[512]; + + // ********************************************************************* + // * Populate the cdevDirectory using the CDEVDDL environment variable. + // ********************************************************************* + if(filename) + { + sprintf(extFilename, "%s-%s.%s", filename, + cdevSystem::CDEV_MAJOR_VERSION, + cdevSystem::CDEV_MINOR_VERSION); + + if(!access(extFilename, 00)) table->load(extFilename); + else if(!access(filename, 00)) table->load(filename); + } + + // ********************************************************************* + // * Create the hash table of commands. + // ********************************************************************* + commandHash->insert("query", + (void *)&(cdevDirectory::query)); + commandHash->insert("queryClass", + (void *)&(cdevDirectory::queryClass)); + commandHash->insert("queryClasses", + (void *)&(cdevDirectory::queryClasses)); + commandHash->insert("queryCollection", + (void *)&(cdevDirectory::queryCollection)); + commandHash->insert("queryVerbs", + (void *)&(cdevDirectory::queryVerbs)); + commandHash->insert("queryAttributes", + (void *)&(cdevDirectory::queryAttributes)); + commandHash->insert("queryMessages", + (void *)&(cdevDirectory::queryMessages)); + commandHash->insert("service", + (void *)&(cdevDirectory::service)); + commandHash->insert("resolveService", + (void *)&(cdevDirectory::resolveService)); + commandHash->insert("serviceData", + (void *)&(cdevDirectory::serviceData)); + commandHash->insert("resolveServiceData", + (void *)&(cdevDirectory::resolveServiceData)); + commandHash->insert("validate", + (void *)&(cdevDirectory::validate)); + commandHash->insert("update", + (void *)&(cdevDirectory::update)); + commandHash->insert("writeAscii", + (void *)&(cdevDirectory::writeAscii)); + commandHash->insert("writeBinary", + (void *)&(cdevDirectory::writeBinary)); + } + +// ***************************************************************************** +// * cdevDirectory:~cdevDirectory: +// * This is the destructor for a cdevDirectory object. +// ***************************************************************************** +cdevDirectory::~cdevDirectory(void) + { + while(node!=NULL) + { + cdevDirectoryNode *curr = node; + node = curr->next; + delete curr; + } + delete table; + delete commandHash; + } + +// ***************************************************************************** +// * cdevDirectory::addNameSvc : +// * This method allows the caller to add a new name service to the list +// * of name services that are managed by this class. If the name cannot +// * be resolved by the cdevDirectory, then each of the name services will +// * be called until the name has been resolved. +// ***************************************************************************** +int +cdevDirectory::addNameSvc(cdevDevice *svc) + { + int result = CDEV_SUCCESS; + + if(svc) + { + int found = 0; + cdevDirectoryNode *curr = node, * prev = NULL; + + while(curr!=NULL && !found) + { + if(curr->device==svc) found = 1; + prev = curr; + curr = prev->next; + } + if (!found) + { + if(prev) prev->next = new cdevDirectoryNode(svc); + else node = new cdevDirectoryNode(svc); + } + else result = CDEV_ERROR; + } + else result = CDEV_INVALIDARG; + + return result; + } + +// ***************************************************************************** +// * cdevDirectory::removeNameSvc : +// * This method removes a name service from the list that is maintained by +// * the cdevDirectory. +// ***************************************************************************** +int +cdevDirectory::removeNameSvc(cdevDevice *svc) + { + int result = CDEV_SUCCESS; + + if(svc) + { + int found = 0; + cdevDirectoryNode *curr = node, * prev = NULL; + + while(curr!=NULL && !found) + { + if(curr->device==svc) found = 1; + else { + prev = curr; + curr = prev->next; + } + } + if (found) + { + if(prev) prev->next = curr->next; + else node = curr->next; + delete curr; + } + else result = CDEV_NOTFOUND; + } + else result = CDEV_INVALIDARG; + + return result; + } + +// ***************************************************************************** +// * cdevDirectory::query : +// * This method calls the query method of the cdevDirectory tool in order +// * to resolve the request. If the request cannot be resolved, then each +// * of the underlying name servers objects will be contacted. +// ***************************************************************************** +int +cdevDirectory::query ( cdevDirectory &dir, char * msg, cdevData *in, cdevData *out ) + { + int result = CDEV_SUCCESS; + + if(out==NULL) result = CDEV_INVALIDARG; + else if((result = cdevDirectoryTool::query(*dir.table, in, out))!=CDEV_SUCCESS) + { + cdevDirectoryNode * curr = dir.node; + while(curr!=NULL && (result=curr->device->send(msg, in, out))!=CDEV_SUCCESS) + { + curr = curr->next; + } + } + return result; + } + +// ***************************************************************************** +// * cdevDirectory::queryClass : +// * This method calls the queryClass method of the cdevDirectory tool in +// * order to resolve the request. If the request cannot be resolved, then +// * each of the underlying name servers objects will be contacted. +// ***************************************************************************** +int +cdevDirectory::queryClass ( cdevDirectory &dir, char * msg, cdevData *in, cdevData *out ) + { + int result = CDEV_SUCCESS; + + if(out==NULL) result = CDEV_INVALIDARG; + else if((result = cdevDirectoryTool::queryClass(*dir.table, in, out))!=CDEV_SUCCESS) + { + cdevDirectoryNode * curr = dir.node; + while(curr!=NULL && (result=curr->device->send(msg, in, out))!=CDEV_SUCCESS) + { + curr = curr->next; + } + } + return result; + } + +// ***************************************************************************** +// * cdevDirectory::queryClasses : +// * This method calls the queryClasses method of the cdevDirectory tool in +// * order to resolve the request. If the request cannot be resolved, then +// * each of the underlying name servers objects will be contacted. +// ***************************************************************************** +int +cdevDirectory::queryClasses ( cdevDirectory &dir, char * msg, cdevData *in, cdevData *out ) + { + int result = CDEV_SUCCESS; + + if(out==NULL) result = CDEV_INVALIDARG; + else if((result = cdevDirectoryTool::queryClasses(*dir.table, in, out))!=CDEV_SUCCESS) + { + cdevDirectoryNode * curr = dir.node; + while(curr!=NULL && (result=curr->device->send(msg, in, out))!=CDEV_SUCCESS) + { + curr = curr->next; + } + } + return result; + } + +// ***************************************************************************** +// * cdevDirectory::queryCollection : +// * This method calls the queryCollection method of the cdevDirectoryTool in +// * order to obtain the list of devices that are part of a cdevCollection. If +// * the request cannot be resolved, then each of the underlying name servers +// * objects will be contacted. +// ***************************************************************************** +int +cdevDirectory::queryCollection ( cdevDirectory &dir, char * msg, cdevData *in, cdevData *out ) + { + int result = CDEV_SUCCESS; + + if(out==NULL) result = CDEV_INVALIDARG; + else if((result = cdevDirectoryTool::queryCollection(*dir.table, in, out))!=CDEV_SUCCESS) + { + cdevDirectoryNode * curr = dir.node; + while(curr!=NULL && (result=curr->device->send(msg, in, out))!=CDEV_SUCCESS) + { + curr = curr->next; + } + } + return result; + } + +// ***************************************************************************** +// * cdevDirectory::queryVerbs : +// * This method calls the queryVerbs method of the cdevDirectory tool in +// * order to resolve the request. If the request cannot be resolved, then +// * each of the underlying name servers objects will be contacted. +// ***************************************************************************** +int +cdevDirectory::queryVerbs ( cdevDirectory &dir, char * msg, cdevData *in, cdevData *out ) + { + int result = CDEV_SUCCESS; + + if(out==NULL) result = CDEV_INVALIDARG; + else if((result = cdevDirectoryTool::queryVerbs(*dir.table, in, out))!=CDEV_SUCCESS) + { + cdevDirectoryNode * curr = dir.node; + while(curr!=NULL && (result=curr->device->send(msg, in, out))!=CDEV_SUCCESS) + { + curr = curr->next; + } + } + return result; + } + +// ***************************************************************************** +// * cdevDirectory::queryAttributes : +// * This method calls the queryAttributes method of the cdevDirectory tool in +// * order to resolve the request. If the request cannot be resolved, then +// * each of the underlying name servers objects will be contacted. +// ***************************************************************************** +int +cdevDirectory::queryAttributes ( cdevDirectory &dir, char * msg, cdevData *in, cdevData *out ) + { + int result = CDEV_SUCCESS; + + if(out==NULL) result = CDEV_INVALIDARG; + else if((result = cdevDirectoryTool::queryAttributes(*dir.table, in, out))!=CDEV_SUCCESS) + { + cdevDirectoryNode * curr = dir.node; + while(curr!=NULL && (result=curr->device->send(msg, in, out))!=CDEV_SUCCESS) + { + curr = curr->next; + } + } + return result; + } + +// ***************************************************************************** +// * cdevDirectory::queryMessages : +// * This method calls the queryMessages method of the cdevDirectory tool in +// * order to resolve the request. If the request cannot be resolved, then +// * each of the underlying name servers objects will be contacted. +// ***************************************************************************** +int +cdevDirectory::queryMessages ( cdevDirectory &dir, char * msg, cdevData *in, cdevData *out ) + { + int result = CDEV_SUCCESS; + + if(out==NULL) result = CDEV_INVALIDARG; + else if((result = cdevDirectoryTool::queryMessages(*dir.table, in, out))!=CDEV_SUCCESS) + { + cdevDirectoryNode * curr = dir.node; + while(curr!=NULL && (result=curr->device->send(msg, in, out))!=CDEV_SUCCESS) + { + curr = curr->next; + } + } + return result; + } + +// ***************************************************************************** +// * cdevDirectory::service : +// * This method calls the service method of the cdevDirectory tool in +// * order to resolve the request. If the request cannot be resolved, then +// * each of the underlying name servers objects will be contacted. +// ***************************************************************************** +int +cdevDirectory::service ( cdevDirectory &dir, char * msg, cdevData *in, cdevData *out ) + { + int result = CDEV_SUCCESS; + + if(out==NULL) return CDEV_INVALIDARG; + + if((result = cdevDirectoryTool::service(*dir.table, in, out))!=CDEV_SUCCESS) + { + cdevDirectoryNode * curr = dir.node; + while(curr!=NULL && (result=curr->device->send(msg, in, out))!=CDEV_SUCCESS) + { + curr = curr->next; + } + } + // ********************************************************************* + // * If the system includes channel access, then fallthrough to channel + // * access as the default service. + // ********************************************************************* + #ifdef _HAS_CA + if(result!=CDEV_SUCCESS && dir.system_.defaultSvc ()) + { + char device[255]; + char message[255]; + + *device = 0; + *message = 0; + + if(in) { + in->get("device", device, 255); + in->get("message", message, 255); + } + + dir.system_.reportError + (CDEV_SEVERITY_WARN, "CDEV Directory", 0, + "No service matches \"%s\" - \"%s\", default to caService", + device, message); + + out->insert("value", "caService"); + result = CDEV_SUCCESS; + } + #endif + return result; + } + +// ***************************************************************************** +// * cdevDirectory::resolveService : +// * This method calls the resolveService method of the cdevDirectory tool in +// * order to resolve the request. If the request cannot be resolved, then +// * each of the underlying name servers objects will be contacted. +// ***************************************************************************** +int +cdevDirectory::resolveService ( cdevDirectory &dir, char * msg, cdevData *in, cdevData *out ) + { + int result = CDEV_SUCCESS; + cdevData In; + + if(out==NULL) return CDEV_INVALIDARG; + + // ********************************************************************* + // * Transfer the name of the device and message to the cdevData In + // * object for use in the "service" request. + // ********************************************************************* + if(in) In = *in; + char *ptr, *tPtr; + char device[255]; + + // ********************************************************************* + // * Jump over the resolveService command and read the device and + // * message. + // ********************************************************************* + ptr = msg+15; + while(*ptr && isspace(*ptr)) ptr++; + for(tPtr=device; *ptr && !isspace(*ptr); ) *(tPtr++) = *(ptr++); + *tPtr = 0; + while(*ptr && isspace(*ptr)) ptr++; + + // ********************************************************************* + // * Use the compressMessage method to remove any extraneous spaces from + // * the message string. + // ********************************************************************* + compressMessage(ptr); + + // ********************************************************************* + // * Place the device and message into the In cdevData object prior to + // * calling the service method. + // ********************************************************************* + if(*device) In.insert("device", device); + if(*ptr) In.insert("message", ptr); + + if((result = cdevDirectoryTool::service(*dir.table, &In, out))!=CDEV_SUCCESS) + { + cdevDirectoryNode * curr = dir.node; + while(curr!=NULL && (result=curr->device->send(msg, in, out))!=CDEV_SUCCESS) + { + curr = curr->next; + } + } + + // ********************************************************************* + // * If the system includes channel access, then fallthrough to channel + // * access as the default service. + // ********************************************************************* + #ifdef _HAS_CA + if(result!=CDEV_SUCCESS && dir.system_.defaultSvc ()) + { + dir.system_.reportError + (CDEV_SEVERITY_WARN, "CDEV Directory", 0, + "No service matches \"%s\" - \"%s\", default to caService", + device, ptr); + + out->insert("value", "caService"); + result = CDEV_SUCCESS; + } + #endif + + return result; + } + +// ***************************************************************************** +// * cdevDirectory::serviceData : +// * This method calls the serviceData method of the cdevDirectory tool in +// * order to resolve the request. If the request cannot be resolved, then +// * each of the underlying name servers objects will be contacted. +// ***************************************************************************** +int +cdevDirectory::serviceData ( cdevDirectory &dir, char * msg, cdevData *in, cdevData *out ) + { + int result = CDEV_SUCCESS; + + if(out==NULL) result = CDEV_INVALIDARG; + else if((result = cdevDirectoryTool::serviceData(*dir.table, in, out))!=CDEV_SUCCESS) + { + cdevDirectoryNode * curr = dir.node; + while(curr!=NULL && (result=curr->device->send(msg, in, out))!=CDEV_SUCCESS) + { + curr = curr->next; + } + } + return result; + } + +// ***************************************************************************** +// * cdevDirectory::resolveServiceData : +// * This method calls the resolveServiceData method of the cdevDirectory tool in +// * order to resolve the request. If the request cannot be resolved, then +// * each of the underlying name servers objects will be contacted. +// ***************************************************************************** +int +cdevDirectory::resolveServiceData ( cdevDirectory &dir, char * msg, cdevData *in, cdevData *out ) + { + int result = CDEV_SUCCESS; + cdevData In; + + if(out==NULL) return CDEV_INVALIDARG; + + // ********************************************************************* + // * Transfer the name of the device and message to the cdevData In + // * object for use in the "serviceData" request. + // ********************************************************************* + if(in) In = *in; + char *ptr, *tPtr; + char device[255]; + + // ********************************************************************* + // * Jump over the resolveServiceData command and read the device and + // * message. + // ********************************************************************* + ptr = msg+19; + while(*ptr && isspace(*ptr)) ptr++; + for(tPtr=device; *ptr && !isspace(*ptr); ) *(tPtr++) = *(ptr++); + *tPtr = 0; + while(*ptr && isspace(*ptr)) ptr++; + + // ********************************************************************* + // * Use the compressMessage method to remove any extraneous spaces from + // * the message string. + // ********************************************************************* + compressMessage(ptr); + + // ********************************************************************* + // * Place the device and message into the In cdevData object prior to + // * calling the serviceData method. + // ********************************************************************* + if(*device) In.insert("device", device); + if(*ptr) In.insert("message", ptr); + + if((result = cdevDirectoryTool::serviceData(*dir.table, &In, out))!=CDEV_SUCCESS) + { + cdevDirectoryNode * curr = dir.node; + while(curr!=NULL && (result=curr->device->send(msg, in, out))!=CDEV_SUCCESS) + { + curr = curr->next; + } + } + return result; + } + +// ***************************************************************************** +// * cdevDirectory::validate : +// * This method calls the validate method of the cdevDirectory tool in +// * order to resolve the request. If the request cannot be resolved, then +// * each of the underlying name servers objects will be contacted. +// ***************************************************************************** +int +cdevDirectory::validate ( cdevDirectory &dir, char * msg, cdevData *in, cdevData *out ) + { + int result = CDEV_SUCCESS; + if((result = cdevDirectoryTool::validate(*dir.table, in, out))!=CDEV_SUCCESS) + { + cdevDirectoryNode * curr = dir.node; + while(curr!=NULL && (result=curr->device->send(msg, in, out))!=CDEV_SUCCESS) + { + curr = curr->next; + } + } + return result; + } + +// ***************************************************************************** +// * cdevDirectory::update : +// * This method calls the update method of the cdevDirectory tool. +// ***************************************************************************** +int +cdevDirectory::update ( cdevDirectory &dir, char *, cdevData *in, cdevData *out ) + { + return cdevDirectoryTool::update(*dir.table, in, out); + } + +// ***************************************************************************** +// * cdevDirectory::writeAscii : +// * This method calls the writeAscii method of the cdevDirectory tool. +// ***************************************************************************** +int +cdevDirectory::writeAscii ( cdevDirectory &dir, char *, cdevData *in, cdevData *out ) + { + return cdevDirectoryTool::writeAscii(*dir.table, in, out); + } + +// ***************************************************************************** +// * cdevDirectory::writeBinary : +// * This method calls the writeBinary method of the cdevDirectory tool. +// ***************************************************************************** +int +cdevDirectory::writeBinary ( cdevDirectory &dir, char *, cdevData *in, cdevData *out ) + { + return cdevDirectoryTool::writeBinary(*dir.table, in, out); + } + +// ***************************************************************************** +// * cdevDirectory::send : +// * This method performs a synchronous send. +// ***************************************************************************** +int +cdevDirectory::send(char *msg, cdevData &in, cdevData &out) + { + return send(msg, &in, &out); + } + +// ***************************************************************************** +// * cdevDirectory::send : +// * This method performs a synchronous send. +// ***************************************************************************** +int +cdevDirectory::send(char *msg, cdevData &in, cdevData *out) + { + return send(msg, &in, out); + } + +// ***************************************************************************** +// * cdevDirectory::send : +// * This method performs a synchronous send. +// ***************************************************************************** +int +cdevDirectory::send(char *msg, cdevData *in, cdevData &out) + { + return send(msg, in, &out); + } + +// ***************************************************************************** +// * cdevDirectory::send : +// * This method performs a synchronous send. +// ***************************************************************************** +int +cdevDirectory::send(char *msg, cdevData *in, cdevData *out) + { + enum { MAX_VERB_LEN = 255 }; + static char verb[MAX_VERB_LEN]; + + int verbIdx = 0; + int result = CDEV_SUCCESS; + char *msgPtr = msg; + QueryFunction func = NULL; + + // ********************************************************************* + // * Extract the verb portion of the message. + // ********************************************************************* + while(*msgPtr && !isspace(*msgPtr) && verbIdxfind(verb); + + // ********************************************************************* + // * Use the compressMessage method to remove any extraneous spaces + // * from the message string (if it exists). + // ********************************************************************* + compressMessage(in); + + // ********************************************************************* + // * Execute the function if it is available, otherwise, descend through + // * the list of register name services and allow each of them to have + // * a crack at it. + // ********************************************************************* + if(func!=NULL) result = (*func)(*this, msg, in, out); + else { + cdevDirectoryNode * curr = node; + while(curr!=NULL && (result=curr->device->send(msg, in, out))!=CDEV_SUCCESS) + { + curr = curr->next; + } + } + return result; + } + +// ***************************************************************************** +// * cdevDirectory::sendNoBlock : +// * This method performs an asynchronous send. +// ***************************************************************************** +int +cdevDirectory::sendNoBlock(char *msg, cdevData &in, cdevData &out) + { + return send(msg, in, out); + } + +// ***************************************************************************** +// * cdevDirectory::sendNoBlock : +// * This method performs an asynchronous send. +// ***************************************************************************** +int +cdevDirectory::sendNoBlock(char *msg, cdevData *in, cdevData &out) + { + return send(msg, in, out); + } + +// ***************************************************************************** +// * cdevDirectory::sendNoBlock : +// * This method performs an asynchronous send. +// ***************************************************************************** +int +cdevDirectory::sendNoBlock(char *msg, cdevData &in, cdevData *out) + { + return send(msg, in, out); + } + + +// ***************************************************************************** +// * cdevDirectory::sendNoBlock : +// * This method performs an asynchronous send. +// ***************************************************************************** +int +cdevDirectory::sendNoBlock(char *msg, cdevData *in, cdevData *out) + { + return send(msg, in, out); + } + +// ***************************************************************************** +// * cdevDirectory::sendCallback : +// * This method performs an asynchronous send. +// ***************************************************************************** +int +cdevDirectory::sendCallback(char *msg, cdevData &in, cdevCallback &cb) + { + cdevData out; + int result; + cdevRequestObject & reqObj = *cdevSystem::defaultSystem().errorRequestObject(); + + result = send(msg, &in, &out); + cb.fireCallback(result, cb.userarg(), reqObj, out, 0); + return result; + } + +// ***************************************************************************** +// * cdevDirectory::sendCallback : +// * This method performs an asynchronous send. +// ***************************************************************************** +int +cdevDirectory::sendCallback(char *msg, cdevData *in, cdevCallback &cb) + { + cdevData out; + int result; + cdevRequestObject & reqObj = *cdevSystem::defaultSystem().errorRequestObject(); + + result = send(msg, in, &out); + if (result == CDEV_SUCCESS) + cb.fireCallback(result, cb.userarg(), reqObj, out, 0); + return result; + } + + +// ***************************************************************************** +// * cdevDirectory::getRequestObject : +// * Allows the caller to obtain a request object for the specified message. +// ***************************************************************************** +cdevRequestObject *cdevDirectory::getRequestObject(char *msg) + { + cdevRequestObject *obj=NULL; + getRequestObject(msg, obj); + return obj; + } + +// ***************************************************************************** +// * cdevDirectory::getRequestObject : +// * Allows the caller to obtain a request object for the specified message. +// ***************************************************************************** +int +cdevDirectory::getRequestObject(char* msg, cdevRequestObject* &reqobj) + { + if (reqobj = findRequestObject (msg)) { +#ifdef _CDEV_DEBUG + printf ("cdevDirectory: Find request object for %s\n", msg); +#endif + reqobj->ref (); + return CDEV_SUCCESS; + } +#ifdef _CDEV_DEBUG + printf ("cdevDirectory: create new request object for %s\n", msg); +#endif + reqobj = new cdevDirRequestObj (*this, msg, system_); + if (reqobj) { + registerReqObject (reqobj); + return CDEV_SUCCESS; + } + return CDEV_ERROR; + } + diff --git a/src/directory/cdevDirectory.h b/src/directory/cdevDirectory.h new file mode 100755 index 0000000..8601365 --- /dev/null +++ b/src/directory/cdevDirectory.h @@ -0,0 +1,88 @@ +#ifndef _CDEV_DIRECTORY_H +#define _CDEV_DIRECTORY_H + +#include +#include +#include +#include + +class cdevDirectoryTable; +class StringHash; + +class CDEV_CLASS_SPEC cdevDirectory : public cdevDevice +{ +public: + cdevDirectory(cdevSystem &system=cdevSystem::defaultSystem()); + ~cdevDirectory(void); + + int addNameSvc(cdevDevice *svc); + int removeNameSvc(cdevDevice *svc); + + int send(char *msg, cdevData &data, cdevData &result); + int send(char *msg, cdevData *data, cdevData &result); + int send(char *msg, cdevData &data, cdevData *result); + int send(char *msg, cdevData *data, cdevData *result); + + int sendNoBlock(char *msg, cdevData &out, cdevData &result); + int sendNoBlock(char *msg, cdevData *out, cdevData &result); + int sendNoBlock(char *msg, cdevData &out, cdevData *result); + int sendNoBlock(char *msg, cdevData *out, cdevData *result); + + int sendCallback(char *msg, cdevData &out, cdevCallback &callback); + int sendCallback(char *msg, cdevData *out, cdevCallback &callback); + + cdevRequestObject *getRequestObject (char *msg); + int getRequestObject (char *msg, cdevRequestObject* &reqobj); + + virtual const char *className(void) const { return "cdevDirectory"; } + +private: + typedef int (*QueryFunction) ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + + static int query ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int queryClass ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int queryClasses ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int queryCollection ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int queryVerbs ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int queryAttributes ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int queryMessages ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int service ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int resolveService ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int serviceData ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int resolveServiceData ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int validate ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int update ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int writeAscii ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + static int writeBinary ( cdevDirectory &dir, + char * msg, cdevData *in, cdevData *out ); + + class cdevDirectoryNode + { + public: + cdevDirectoryNode ( cdevDevice * svc = NULL ) : next(NULL), device(svc) {} + ~cdevDirectoryNode( void ) {} + cdevDirectoryNode * next; + cdevDevice * device; + }; + + cdevDirectoryNode * node; + class cdevDirectoryTable * table; + class StringHash * commandHash; +}; + +#endif diff --git a/src/directory/cdevDirectoryTable.cc b/src/directory/cdevDirectoryTable.cc new file mode 100755 index 0000000..e7b7a6a --- /dev/null +++ b/src/directory/cdevDirectoryTable.cc @@ -0,0 +1,1923 @@ +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#define open _open +#define O_RDONLY _O_RDONLY +#define read _read +#define close _close +#define creat _creat +#else +#include +#include +#endif + +#include + +#ifdef __VMS +#define DIRECTORY_CHAR ']' +#define DIRECTORY_SELF "[]" +#elif defined (_WIN32) +#define DIRECTORY_CHAR 0x5c +#define DIRECTORY_SELF ".\\" +#else +#define DIRECTORY_CHAR '/' +#define DIRECTORY_SELF "./" +#endif + +// ***************************************************************************** +// * cdevReportError : +// * This is the default error reporting mechanism... +// ***************************************************************************** +int cdevReportError(int severity, char *name, void *, char *formatString, ...) + { + va_list argp; + char msg[1024]; + char *p=msg; + int status=0; + + if(severity >= 2) + { + sprintf(msg, "%s %s: ", + name, + (severity == 0?"Information": + (severity == 1?"Warning": + (severity == 2?"Error": + (severity == 3?"Severe Error": + "Event"))))); + p+=::strlen(msg); + + va_start(argp, formatString); + status=vsprintf(p, formatString, argp); + va_end(argp); + + #ifndef _WIN32 + fprintf(stderr, "%s\n", msg); + fflush (stderr); + #else + HANDLE stderrHandle=GetStdHandle(STD_ERROR_HANDLE); + if(stderrHandle != INVALID_HANDLE_VALUE) + { + int nReady=strlen(msg); + unsigned long nWritten=0; + + WriteFile(stderrHandle, msg, nReady, &nWritten, NULL); + WriteFile(stderrHandle, "\n", 1, &nWritten, NULL); + } + #endif + } + return status; + } + +// ***************************************************************************** +// * These are the current and historical binary magic numbers for DDL files. +// ***************************************************************************** +long cdevDirectoryTable::BinaryMagic_1_4 = 0xcde5dd1f; +long cdevDirectoryTable::BinaryMagic_1_5 = 0xcde5dd20; +long cdevDirectoryTable::BinaryMagic = 0xcde5dd21; + +// ***************************************************************************** +// * getLongFromStream : +// * This is a convenience function to extract a non-aligned four-byte long +// * from a character string. +// ***************************************************************************** +inline long getLongFromStream ( char * ptr ) + { + long val; + memcpy(&val, ptr, 4); + return ntohl(val); + } + +// ***************************************************************************** +// * assimilateTags : +// * This is a convenience function that allows me to pull the service data +// * from the comma delimitted list into an array. +// ***************************************************************************** +inline int assimilateTags ( char *& ptr, char ** & tags, int & nTags ) + { + int result = 0; + char * tPtr; + + if(ptr && *ptr=='{') + { + for(ptr++; isspace(*ptr); ptr++); + + if(*ptr!='}') + { + tPtr = ptr; + do { + if(*tPtr==',' || *tPtr=='}') nTags++; + } while(*tPtr!='}' && *(tPtr++)); + + if(*tPtr!='}') result = -1; + else { + tags = new char *[nTags]; + memset(tags, 0, nTags*sizeof(char *)); + + for(int idx=0; *ptr && idxtags[idx]) + { + *tPtr = 0; + tPtr--; + } + idx++; + } + } + } + } + } + + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::load : +// * This method allows the caller to load a DDL file (binary or ASCII). +// ***************************************************************************** +int cdevDirectoryTable::load ( char * inputFile ) + { + int fd; + int result = CDEV_SUCCESS; + + if((fd = open(inputFile, O_RDONLY))==-1) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Could not open CDEV DDL file %s", inputFile); + result = CDEV_ERROR; + } + else { + long magicNum = 0; + + read(fd, &magicNum, sizeof(magicNum)); + magicNum = ntohl(magicNum); + close(fd); + + if(magicNum==BinaryMagic_1_4) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Cannot load a Binary DDL created by CDEV 1.4"); + result = CDEV_ERROR; + } + else if(magicNum==BinaryMagic_1_5) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Cannot load a Binary DDL created by CDEV 1.5"); + result = CDEV_ERROR; + } + else if(magicNum==BinaryMagic) result = binaryLoad(inputFile); + else result = asciiLoad(inputFile); + } + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::asciiLoad : +// * This method will load the contents of an ASCII Text DDL file into the +// * cdevDirectory object. +// ***************************************************************************** +int cdevDirectoryTable::asciiLoad ( char * inputFile ) + { + int result = CDEV_SUCCESS; + char ddlDir [1024]; + char ddlFile [255]; + char * buf = NULL; + int buflen = 0; + int cursor = 0; + + if(!inputFile || !*inputFile) + { + cdevReportError( + CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "CDEV DDL file has not been specified"); + result = CDEV_ERROR; + } + else { + strcpy(ddlDir, inputFile); + char * ptr = strrchr(ddlDir, DIRECTORY_CHAR); + if(ptr==NULL) + { + strcpy(ddlFile, inputFile); + strcpy(ddlDir, DIRECTORY_SELF); + } + else { + ptr++; + strcpy(ddlFile, ptr); + *ptr = 0; + } + result = loadText(ddlDir, ddlFile, buf, buflen, cursor); + } + + if(result==CDEV_SUCCESS) result = asciiBufferLoad(buf); + if(buf) free(buf); + + return result; + } + +// ***************************************************************************** +// * cdevDirectoryTable::asciiBufferLoad : +// * This method will load the contents of an ASCII Text DDL file into the +// * cdevDirectory object. +// ***************************************************************************** +int cdevDirectoryTable::asciiBufferLoad ( char * buf ) + { + int result = CDEV_SUCCESS; + + if(!buf || !*buf) + { + cdevReportError( + CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "NULL buffer provided to DDL loader"); + result = CDEV_ERROR; + } + else { + readServices (buf); + readClasses (buf); + readDevices (buf); + readAliases (buf); + readCollections (buf); + } + + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::binaryDump : +// * This method will write the binary contents of the cdevDirectoryTable to +// * an output file. +// ***************************************************************************** +void cdevDirectoryTable::binaryDump ( char * outputFile ) + { + cdevServiceDefinition *sPtr = NULL; + cdevClassDefinition *cPtr = NULL; + cdevElementDefinition *ePtr = NULL; + cdevDeviceDefinition *dPtr = NULL; + cdevAliasDefinition *aPtr = NULL; + + int fd = -1; + long i = 0; + + // ********************************************************************* + // * Open the output file. + // ********************************************************************* +#ifdef _WIN32 + if((fd = creat( outputFile, _S_IREAD | _S_IWRITE))==-1) +#else + if((fd = creat( outputFile, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH))==-1) +#endif + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Failed to open binary output file to write"); + return; + } + + // ********************************************************************* + // * Write the magic number to the output file. + // ********************************************************************* + i = htonl(BinaryMagic); + write(fd, &i, sizeof(i)); + + // ********************************************************************* + // * Write the service definitions to the output file. + // ********************************************************************* + + // Count the number of services. + for(i=0, sPtr=serviceHead; sPtr!=NULL; sPtr = sPtr->getNext(), i++); + + // Write the service count to the output file. + i = htonl(i); + write(fd, &i, sizeof(i)); + + // Write the individual services to the output file. + for(sPtr=serviceHead; sPtr!=NULL; sPtr = sPtr->getNext()) + { + // Write the service name. + write(fd, sPtr->getName(), strlen(sPtr->getName())+1); + + // Write the number of tags. + i = htonl(sPtr->getTagCnt()); + write(fd, &i, sizeof(i)); + + // Write each tag. + int tagCnt = sPtr->getTagCnt(); + char ** tags = sPtr->getTags(); + for(i=0; igetNext()) + { + if(cPtr!=collectionClass) i++; + } + + // Write the class count to the output file. + i = htonl(i); + write(fd, &i, sizeof(i)); + + // Write the individual classes to the output file. + for(cPtr=classHead; cPtr!=NULL; cPtr = cPtr->getNext()) + { + // Go to the next entry if the current entry is the + // collectionClass + if(cPtr == collectionClass) continue; + + // Write the class name. + write(fd, cPtr->getName(), strlen(cPtr->getName())+1); + + // Write the parent class name (if any) + if(cPtr->getParent()) write(fd, cPtr->getParent()->getName(), strlen(cPtr->getParent()->getName())+1); + else write(fd, "\0", 1); + + // Count the number of verbs + for(i=0, ePtr=cPtr->getVerbs(); ePtr!=NULL; ePtr=ePtr->getNext(), i++); + + // Write the verb count + i = htonl(i); + write(fd, &i, sizeof(i)); + + // Write each verb + for(ePtr = cPtr->getVerbs(); ePtr!=NULL; ePtr=ePtr->getNext()) + { + // Write the verb name + write(fd, ePtr->getName(), strlen(ePtr->getName())+1); + + // Write the service name + if(ePtr->getService()) write(fd, ePtr->getService()->getName(), strlen(ePtr->getService()->getName())+1); + else write(fd, "\0", 1); + + // Write the number of serviceData items + i = htonl(ePtr->getDataCnt()); + write(fd, &i, sizeof(i)); + + // Write each serviceData item + int nItems = ePtr->getDataCnt(); + char ** items = ePtr->getServiceData(); + for(i=0; igetAttributes(); ePtr!=NULL; ePtr=ePtr->getNext(), i++); + + // Write the attribute count + i = htonl(i); + write(fd, &i, sizeof(i)); + + // Write each attribute + for(ePtr = cPtr->getAttributes(); ePtr!=NULL; ePtr=ePtr->getNext()) + { + // Write the attribute name + write(fd, ePtr->getName(), strlen(ePtr->getName())+1); + + // Write the service name + if(ePtr->getService()) write(fd, ePtr->getService()->getName(), strlen(ePtr->getService()->getName())+1); + else write(fd, "\0", 1); + + // Write the number of serviceData items + i = htonl(ePtr->getDataCnt()); + write(fd, &i, sizeof(i)); + + // Write each serviceData item + int nItems = ePtr->getDataCnt(); + char ** items = ePtr->getServiceData(); + for(i=0; igetMessages(); ePtr!=NULL; ePtr=ePtr->getNext(), i++); + + // Write the message count + i = htonl(i); + write(fd, &i, sizeof(i)); + + // Write each message + for(ePtr = cPtr->getMessages(); ePtr!=NULL; ePtr=ePtr->getNext()) + { + // Write the message name + write(fd, ePtr->getName(), strlen(ePtr->getName())+1); + + // Write the service name + if(ePtr->getService()) write(fd, ePtr->getService()->getName(), strlen(ePtr->getService()->getName())+1); + else write(fd, "\0", 1); + + // Write the number of serviceData items + i = htonl(ePtr->getDataCnt()); + write(fd, &i, sizeof(i)); + + // Write each serviceData item + int nItems = ePtr->getDataCnt(); + char ** items = ePtr->getServiceData(); + for(i=0; igetDevices(); dPtr!=NULL; dPtr = dPtr->getNext(), i++); + + // Write the number of devices + i = htonl(i); + write(fd, &i, sizeof(i)); + + // Write each device + for(dPtr = cPtr->getDevices(); dPtr!=NULL; dPtr = dPtr->getNext()) + { + if(dPtr->getName() && *dPtr->getName()) + { + write(fd, dPtr->getName(), strlen(dPtr->getName())+1); + if(dPtr->getSubstituteName() && + *dPtr->getSubstituteName() && + dPtr->getSubstituteName()!=dPtr->getName()) + { + write(fd, dPtr->getSubstituteName(), strlen(dPtr->getSubstituteName())+1); + } + else write(fd, "\0", 1); + } + else write(fd, "\0", 1); + } + } + + // ********************************************************************* + // * Write the alias definitions to the output file + // ********************************************************************* + + // Count the number of aliases + for(i=0, aPtr = aliasHead; aPtr!=NULL; aPtr = aPtr->getNext(), i++); + + // Write the number of aliases. + i = htonl(i); + write(fd, &i, sizeof(i)); + + // Write each alias to the output file + for(aPtr = aliasHead; aPtr!=NULL; aPtr = aPtr->getNext()) + { + // Write the alias name. + write(fd, aPtr->getName(), strlen(aPtr->getName())+1); + + // Write the device name. + write(fd, aPtr->getDevice().getName(), strlen(aPtr->getDevice().getName())+1); + } + + // ********************************************************************* + // * Write the collection definitions to the output file. + // ********************************************************************* + + cdevCollectionDefinition * clPtr; + // Count the number of collections + for(i=0, clPtr = collectionHead; clPtr!=NULL; clPtr = clPtr->getNext(), i++); + + // Write the number of collections. + i = htonl(i); + write(fd, &i, sizeof(i)); + + for(clPtr = collectionHead; clPtr!=NULL; clPtr = clPtr->getNext()) + { + // Write the collection name + write(fd, clPtr->getName(), strlen(clPtr->getName())+1); + + // Write the number of devices in the collection + i = htonl(clPtr->getDeviceCnt()); + write(fd, &i, sizeof(i)); + + // Write the devices + char ** devices = clPtr->getDevices(); + int deviceCnt = clPtr->getDeviceCnt(); + for(i=0; i=0; svcCnt--) + { + char * svcName = NULL; + int nTags = 0; + char ** tags = 0; + + // ***************************************************** + // * Get the service name from the head of the stream + // ***************************************************** + svcName = strdup(ptr); + ptr += strlen(ptr)+1; + + // ***************************************************** + // * Read the number of tags from the head of the stream + // ***************************************************** + nTags = (int)getLongFromStream(ptr); + ptr += sizeof(long); + + // ***************************************************** + // * If the tag count is greater than 0, read the tags + // * into an array. + // ***************************************************** + if(nTags>0) + { + tags = new char *[nTags]; + for(i=0; i=0; nTags--) delete tags[nTags]; + } + if(tags) delete tags; + } + } + + // ************************************************************* + // * Read the class count from the data block. + // ************************************************************* + int classCnt = (int)getLongFromStream(ptr); + ptr+=sizeof(long); + + // ************************************************************* + // * Read the class definitions from the data block. + // ************************************************************* + for(; classCnt>0; classCnt--) + { + char * className = NULL; + cdevClassDefinition * parent = NULL; + cdevElementDefinition * verbs = NULL; + cdevElementDefinition * attributes = NULL; + cdevElementDefinition * messages = NULL; + cdevElementDefinition * tail = NULL; + + // ***************************************************** + // * Get the service name from the head of the stream + // ***************************************************** + className = strdup(ptr); + ptr += strlen(ptr)+1; + + // ***************************************************** + // * Read the parent class from the data block. + // ***************************************************** + parent = findClass(ptr); + ptr += strlen(ptr)+1; + + // ***************************************************** + // * Read the number of verbs from the data block. + // ***************************************************** + int verbCnt = (int)getLongFromStream(ptr); + ptr += sizeof(long); + tail = NULL; + + // ***************************************************** + // * If the verbCnt is greater than 0, then begin + // * reading verbs into the verbs list. + // ***************************************************** + for( ; verbCnt>0; verbCnt--) + { + // Get the verb name + char * verbName = strdup(ptr); + ptr += strlen(ptr)+1; + + // Get the service definition + cdevServiceDefinition * svcDef = findService(ptr); + ptr+=strlen(ptr)+1; + + // Get the number of tags + int nTags = (int)getLongFromStream(ptr); + ptr += sizeof(long); + + // Allocate the array of tags if necessary + char ** tags = nTags?new char *[nTags]:(char **)NULL; + + // Read each of the tags into the tags array + for(i=0; isetNext(new cdevElementDefinition(verbName, svcDef, tags, nTags)); + tail = tail->getNext(); + } + } + + // ***************************************************** + // * Read the number of attributes from the data block. + // ***************************************************** + int attributeCnt = (int)getLongFromStream(ptr); + ptr += sizeof(long); + tail = NULL; + + // ***************************************************** + // * If the attributeCnt is greater than 0, then begin + // * reading attributes into the attributes list. + // ***************************************************** + for( ; attributeCnt>0; attributeCnt--) + { + // Get the attribute name + char * attributeName = strdup(ptr); + ptr += strlen(ptr)+1; + + // Get the service definition + cdevServiceDefinition * svcDef = findService(ptr); + ptr+=strlen(ptr)+1; + + // Get the number of tags + int nTags = (int)getLongFromStream(ptr); + ptr += sizeof(long); + + // Allocate the array of tags if necessary + char ** tags = nTags?new char *[nTags]:(char **)NULL; + + // Read each of the tags into the tags array + for(i=0; isetNext(new cdevElementDefinition(attributeName, svcDef, tags, nTags)); + tail = tail->getNext(); + } + } + + // ***************************************************** + // * Read the number of messages from the data block. + // ***************************************************** + int messageCnt = (int)getLongFromStream(ptr); + ptr += sizeof(long); + tail = NULL; + + // ***************************************************** + // * If the messageCnt is greater than 0, then begin + // * reading messages into the messages list. + // ***************************************************** + for( ; messageCnt>0; messageCnt--) + { + // Get the message name + char * messageName = strdup(ptr); + ptr += strlen(ptr)+1; + + // Get the service definition + cdevServiceDefinition * svcDef = findService(ptr); + ptr+=strlen(ptr)+1; + + // Get the number of tags + int nTags = (int)getLongFromStream(ptr); + ptr += sizeof(long); + + // Allocate the array of tags if necessary + char ** tags = nTags?new char *[nTags]:(char **)NULL; + + // Read each of the tags into the tags array + for(i=0; isetNext(new cdevElementDefinition(messageName, svcDef, tags, nTags)); + tail = tail->getNext(); + } + } + + // ***************************************************** + // * Create the new cdevClassDefinition within the + // * cdevDirectoryTable. + // ***************************************************** + cdevClassDefinition * target; + cdevClassDefinition * actual; + + target = new cdevClassDefinition (*this, className, parent, verbs, attributes, messages); + if(addClass(target)!=CDEV_SUCCESS) + { + actual = findClass(className); + delete target; + } + else actual = target; + + // ***************************************************** + // * Read the table of devices that are associated with + // * the class. + // ***************************************************** + int nDevices = (int)getLongFromStream(ptr); + ptr += sizeof(long); + + for( ; nDevices>0; nDevices--) + { + if(*ptr) + { + char * d = strdup(ptr); + char * s = NULL; + + ptr+=strlen(ptr)+1; + if(*ptr) s = strdup(ptr); + + if(actual->addDevice(d, s)!=CDEV_SUCCESS) + { + delete d; + if(s) delete s; + } + } + ptr+=strlen(ptr)+1; + } + } + + // ************************************************************* + // * Read the table of aliases + // ************************************************************* + int aliasCnt = (int)getLongFromStream(ptr); + ptr += sizeof(long); + + for ( ; aliasCnt>0; aliasCnt--) + { + char * alias = strdup(ptr); + ptr += strlen(ptr)+1; + + cdevDeviceDefinition * device = (cdevDeviceDefinition *)deviceHash.find(ptr); + ptr += strlen(ptr)+1; + + if(*alias && device) addAlias(alias, *device); + else delete alias; + } + + // ********************************************************************* + // * Read the table of collections definitions + // ********************************************************************* + int collectionCnt = (int)getLongFromStream(ptr); + ptr += sizeof(long); + + for( ; collectionCnt>0; collectionCnt--) + { + int nDevices = 0; + char ** devices = NULL; + char * collection = strdup(ptr); + ptr += strlen(ptr)+1; + + nDevices = (int)getLongFromStream(ptr); + ptr += sizeof(long); + + if(nDevices) + { + devices = new char *[nDevices]; + for(int x=0; x0) + { + addCollection(collection, devices, nDevices); + } + else { + if(collection) delete collection; + if(nDevices>0 && devices) + { + while(--nDevices>=0) delete devices[nDevices]; + } + if(devices) delete devices; + } + } + } + + close (fd); + if(dataBlock) delete dataBlock; + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::loadText : +// * This method is used to read a DDL file into a single buffer. This +// * buffer may then be parsed into the cdevDirectoryTable structure. +// ***************************************************************************** +int cdevDirectoryTable::loadText ( char * includePath, char * filename, char * &buf, int &buflen, int &cursor) + { + static int depth = 0; + + FILE * fp = NULL; + char * ptr = NULL; + char fname[1024]; + + // ********************************************************************* + // * Increment the depth variable to indicate recursion into function. + // ********************************************************************* + depth++; + + // ********************************************************************* + // * Create the exact path from the includePath and filename. + // ********************************************************************* + sprintf(fname, "%s%s", includePath, filename); + + // ********************************************************************* + // * Create initial NULL terminated buffer if one does not exist. + // ********************************************************************* + if(buf==NULL || buflen==0) + { + buflen = 8192; + buf = (char *)malloc(buflen*sizeof(char)); + cursor = 1; + strcpy(buf, "\n\0"); + } + + if((fp = fopen(fname, "r"))!=NULL) + { + int fileSize; + int dataSize; + + fseek(fp, 0L, SEEK_END); + fileSize = (int)ftell(fp); + fseek(fp, 0L, SEEK_SET); + + dataSize = strlen(buf); + if(dataSize+fileSize > buflen) + { + buflen = (dataSize+fileSize)*2; + buf = (char *)realloc(buf, buflen*sizeof(char)); + } + + memmove(buf+cursor+fileSize, buf+cursor, (dataSize-cursor)+1); + fread (buf+cursor, fileSize, 1, fp); + fclose (fp); + + // ************************************************************* + // * Remove all of the comments from the input buffer. + // ************************************************************* + compressComments(filename, buf+cursor); + + // ************************************************************* + // * Start locating and processing includes. Note: because it + // * recursively calls this method to read in include files, the + // * ptr must be recalculated prior to each search. + // ************************************************************* + while ((ptr = strstr(buf+cursor, "#include"))!=NULL) + { + char *fnamePtr = ptr+8; + + // ***************************************************** + // * The cursor should point to the current position. + // ***************************************************** + cursor = ptr-buf; + + while(isspace(*fnamePtr)) fnamePtr++; + + if(*fnamePtr=='<') + { + fnamePtr++; + for(ptr=fnamePtr; *ptr && *ptr!='>' && *ptr!='\n'; ptr++); + if (*ptr=='>') + { + *ptr=0; + strcpy(fname, fnamePtr); + fnamePtr = fname; + *ptr='>'; + } + else { + cdevReportError( + CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Closing angle brace missing on #include in file %s", + filename); + fnamePtr = NULL; + } + } + else { + cdevReportError( + CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Opening angle brace missing on #include in file %s", + filename); + fnamePtr = NULL; + } + + // ***************************************************** + // * Remove the include directive from the data file. + // ***************************************************** + if(ptr = strchr(ptr, '\n')) + { + strcpy(buf+cursor, ptr+1); + } + else *(buf+cursor) = 0; + + // ***************************************************** + // * Load the include file to the current cursor + // * position. + // ***************************************************** + loadText(includePath, fnamePtr, buf, buflen, cursor); + } + } + else { + cdevReportError( + CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Could not find #include file %s", filename); + } + + // ********************************************************************* + // * Only compress the spaces after all of the data has been loaded. + // ********************************************************************* + if(--depth==0) compressSpaces (filename, buf); + return *buf?CDEV_SUCCESS:CDEV_ERROR; + } + +// ***************************************************************************** +// * cdevDirectoryTable::compressComments : +// * This method will remove all comments from the input buffer. +// ***************************************************************************** +void cdevDirectoryTable::compressComments ( char * filename, char * buf ) + { + // ************************************************************* + // * Remove all comment blocks. + // ************************************************************* + char *ptr = buf; + while((ptr = strstr(ptr, "/*"))!=NULL) + { + char *ePtr = strstr(ptr, "*/"); + if(ePtr==NULL) + { + cdevReportError( + CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Unterminated comment block in file %s", + filename); + *ptr = 0; + } + else strcpy(ptr, ePtr+2); + } + + // ************************************************************* + // * Remove all comment lines. + // ************************************************************* + ptr = buf; + while((ptr = strstr(ptr, "//"))!=NULL) + { + char *ePtr = strchr(ptr, '\n'); + if(ePtr!=NULL) strcpy(ptr, ePtr); + else *ptr ='\n'; + } + + } + +// ***************************************************************************** +// * cdevDirectoryTable::compressSpaces : +// * This method will remove any extraneous spaces from the input buffer. +// ***************************************************************************** +void cdevDirectoryTable::compressSpaces ( char *, char * buf ) + { + // ************************************************************* + // * Remove all extraneous white space... remember, if you take + // * it out here you won't have to parse it later... + // ************************************************************* + char *ptr = buf; + while(*(ptr = ptr+strcspn(ptr, " \t\n"))!=0) + { + if(*ptr=='\t') *ptr = ' '; + if(isspace(*(ptr+1))) + { + char * ePtr = ptr+1; + while(isspace(*ePtr)) + { + if(*ePtr=='\n') *ptr='\n'; + ePtr++; + } + strcpy(ptr+1, ePtr); + } + else ptr++; + } + } + + +// ***************************************************************************** +// * These are the definitive errors for the readServices method. +// ***************************************************************************** +static char * readServiceErrors [] = + { + "", + "Service name is missing from definition", + "Service definition is missing opening brace", + "Invalid service format", + "Tag definition is missing opening brace", + "Tag definition is missing closing brace", + "Service definition is missing closing brace" + }; + +// ***************************************************************************** +// * cdevDirectoryTable::readServices : +// * This method will read all of the services that are defined in the +// * specified input stream and will add them to the services entry of the +// * cdevDirectoryTable. +// ***************************************************************************** +void cdevDirectoryTable::readServices( char * buf ) + { + char * tPtr = buf; + char * ptr = buf; + + enum {SUCCESS=0, + SVC_NAME, + SVC_OPEN_BRACE, + SVC_FMT, + TAG_OPEN_BRACE, + TAG_CLOSE_BRACE, + SVC_CLOSE_BRACE} error; + + // ********************************************************************* + // * While locating the service keyword at the beginning of a line. + // ********************************************************************* + while((ptr=strstr(ptr, "\nservice "))!=NULL) + { + char * errorRestart = ptr+9; + char * name = NULL; + char ** tags = NULL; + int nTags = 0; + char * tPtr = ptr+=9; + + error = SUCCESS; + + while(*tPtr && !isspace(*tPtr)) tPtr++; + + // ************************************************************* + // * If the service name was located, copy it to the name + // * variable. Otherwise, set the error code. + // ************************************************************* + if(*tPtr) + { + *tPtr = 0; + name = strdup(ptr); + *tPtr = ' '; + } + else error = SVC_NAME; + + // ************************************************************* + // * If no errors have occurred locate the opening brace. + // ************************************************************* + if(!error && *(++tPtr)!='{') error = SVC_OPEN_BRACE; + else for(ptr=tPtr+1; isspace(*ptr); ptr++); + + // ************************************************************* + // * If no errors have occured, find the tags entry (if present) + // ************************************************************* + if(!error && *ptr=='}') error = SUCCESS; + else if(!error && !strncmp(ptr, "tags", 4)) + { + // ***************************************************** + // * Find the opening brace for the tag list. + // ***************************************************** + for(ptr+=4; isspace(*ptr); ptr++); + if(*ptr!='{') error = TAG_OPEN_BRACE; + else { + if(assimilateTags(ptr, tags, nTags)!=0) + { + error = TAG_CLOSE_BRACE; + } + } + // ***************************************************** + // * If no errors have occurred find the closing brace + // * for the service definition. + // ***************************************************** + if(!error) for(ptr++; isspace(*ptr); ptr++); + if(!error && *ptr!='}') error = SVC_CLOSE_BRACE; + } + else error = SVC_FMT; + + if(!error) + { + if(nTags==0 && tags!=NULL) + { + delete tags; + tags = NULL; + } + addService(name, tags, nTags); + } + else { + cdevReportError( + CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Service \"%s\" Error\n\t=> %s\n\t=> %s\n", name?name:"UNKNOWN", + readServiceErrors[error], + "Format is: service name { tags {tag1,tag2}}"); + + if(name) delete name; + if(tags && nTags) while(--nTags>=0) delete tags[nTags]; + if(tags) delete tags; + ptr = errorRestart; + } + } + + return; + } + + +// ***************************************************************************** +// * These are the definitive errors for the readClasses method. +// ***************************************************************************** +static char * readClassErrors [] = + { + "", + "Class name is missing from definition", + "Specified parent class is not defined", + "Parent class definition is formatted wrong", + "Class definition is missing opening brace", + "Class definition is missing closing brace", + "Class definition has no content" + }; + +// ***************************************************************************** +// * cdevDirectoryTable::readClasses : +// * This method will read all of the classes that are defined in the +// * specified input stream and will add them to the classes entry of the +// * cdevDirectoryTable. +// ***************************************************************************** +void cdevDirectoryTable::readClasses( char * buf ) + { + char parentName[255]; + char * ptr = buf; + char * tPtr; + + enum {SUCCESS=0, + CLASS_NAME, + CLASS_NO_PARENT, + CLASS_PARENT_FMT, + CLASS_OPEN_BRACE, + CLASS_CLOSE_BRACE, + CLASS_EMPTY} error; + + while((ptr = strstr(ptr, "\nclass "))!=NULL) + { + char * errorRestart = ptr+=7; + char * name = NULL; + cdevClassDefinition * newClass = NULL; + cdevClassDefinition * parent = NULL; + char * startClassCode = NULL; + char * endClassCode = NULL; + + error = SUCCESS; + *parentName = 0; + + // ************************************************************* + // * Reposition ptr to point at the first space after the class + // * name. If a space exists after the class name, then copy + // * the class name to the name variable, otherwise, report an + // * error. + // ************************************************************* + for(tPtr=ptr; *ptr && !isspace(*ptr); ptr++); + if(*ptr) + { + *ptr = 0; + name = strdup(tPtr); + *ptr = ' '; + } + else error = CLASS_NAME; + + if(!error) + { + // ***************************************************** + // * Reposition the ptr to the first occurence of a + // * colon or an opening brace after the class name. + // ***************************************************** + while(*ptr && *ptr!=':' && *ptr!='{') ptr++; + + // ***************************************************** + // * If a colon was found, then it indicates that the + // * class is a sub-class of another predefined class. + // * Read the name of the parent class into the + // * parentName variable. If the specified parent class + // * has not already been defined, then report an error. + // ***************************************************** + if(*ptr==':') + { + for(ptr++; isspace(*ptr); ptr++); + if(*ptr) + { + for(tPtr=ptr; *ptr && !isspace(*ptr); ptr++); + if(*ptr) + { + *ptr = 0; + strcpy(parentName, tPtr); + *ptr = ' '; + parent = findClass(parentName); + if(parent==NULL) error = CLASS_NO_PARENT; + } + while(*ptr && *ptr!='{') ptr++; + } + else error = CLASS_PARENT_FMT; + } + } + + // ************************************************************* + // * The opening brace indicates the beginning of the actual + // * class definition. From here the method will determine the + // * location of the class's closing brace and will begin + // * assimilating the definitions for verbs, attributes and + // * messages that are inside. + // ************************************************************* + if(!error && *ptr=='{') + { + int count = 1; + startClassCode = ++ptr; + endClassCode = startClassCode; + + while(count>0) + { + if(*endClassCode=='{') count++; + else if(*endClassCode=='}') count--; + else if(*endClassCode==0) count=0; + if(count) endClassCode++; + } + if(*endClassCode!='}') error = CLASS_CLOSE_BRACE; + } + else if(!error) error = CLASS_OPEN_BRACE; + + // ************************************************************* + // * At this point the class, parent class and extent of the + // * class definition is known and we can create the class + // * object and populate it with elements. + // ************************************************************* + if(!error) + { + newClass = new cdevClassDefinition(*this, name, parent); + + if(endClassCode!=startClassCode) + { + readElements(*newClass, VERB, startClassCode, endClassCode); + readElements(*newClass, ATTRIBUTE, startClassCode, endClassCode); + readElements(*newClass, MESSAGE, startClassCode, endClassCode); + } + + addClass(newClass); + } + else { + cdevReportError( + CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Class \"%s\" Error\n\t=> %s\n\t=> %s\n", name?name:"UNKNOWN", + readClassErrors[error], + "Format is: class name : parent { ... }"); + + if(name) delete name; + ptr = errorRestart; + } + } + + return; + } + + +// ***************************************************************************** +// * Type names that are associated with the various element types. +// ***************************************************************************** +static char * readElementTypeNames[] = + { + "verb", + "attribute", + "message" + }; + +// ***************************************************************************** +// * These are the definitive errors for the readElements method. +// ***************************************************************************** +static char * readElementErrors [] = + { + "", + "opening brace is missing", + "definition has no content", + "definition is missing service name", + "definition references an undefined service", + "requires a service definition", + "service data closing brace is missing", + "definition has invalid format" + }; + + +// ***************************************************************************** +// * cdevDirectoryTable::readElements : +// * This method is used to read a list of elements from the class definition +// * that is in the character string buffer specified by start and end. +// * If elements exist, then an cdevElementDefinition will be created and +// * they will be inserted into the list. +// ***************************************************************************** +void cdevDirectoryTable::readElements + (cdevClassDefinition &def, + ElementType type, + char *start, + char *end) + { + char oldEndChar; + char * ptr = start; + char targetString[32]; + int targetStringLen; + + enum { + SUCCESS = 0, + ELEMENT_OPEN_BRACE, + ELEMENT_EMPTY, + ELEMENT_NO_SERVICE, + ELEMENT_SERVICE_UNDEFINED, + MESSAGE_NEEDS_SERVICE, + SERVICE_DATA_CLOSE_BRACE, + ELEMENT_FMT + } error; + + // ********************************************************************* + // * Null terminate the end of the block in order to improve search. + // ********************************************************************* + if(end) { + if(*end!='}') end++; + oldEndChar = *end; + *end = 0; + } + + // ********************************************************************* + // * Create the string that represents the element definition and then + // * begin locating instances of the element within the data block. + // ********************************************************************* + sprintf(targetString, "%ss", readElementTypeNames[type]); + targetStringLen = strlen(targetString); + + while((ptr = strstr(ptr, targetString))!=NULL) + { + char * errorRestart = (ptr+=targetStringLen); + + error = SUCCESS; + + // ************************************************************* + // * The first character before and after the definition should + // * be some sort of white space... Otherwise, it has read an + // * invalid entry. + // ************************************************************* + if(isspace(*ptr) && isspace(*(ptr-targetStringLen-1))) + { + while(isspace(*ptr)) ptr++; + if(*ptr!='{') error = ELEMENT_OPEN_BRACE; + else for(ptr++; isspace(*ptr); ptr++); + while (!error && *ptr && *ptr!='}') + { + char oldChar; + char * tPtr = ptr; + char * name = NULL; + cdevServiceDefinition * service = NULL; + char ** tags = NULL; + int nTags = 0; + + // ********************************************* + // * Read the name of the element into the name + // * variable + // ********************************************* + while(*ptr && *ptr!=',' && *ptr!=';' && + *ptr!='}' && !isspace(*ptr)) ptr++; + oldChar = *ptr; + *ptr = 0; + if(strlen(tPtr)>0) name = strdup(tPtr); + else error = ELEMENT_EMPTY; + *ptr = oldChar; + + // ********************************************* + // * Position to the beginning of the + // * serviceName. + // ********************************************* + while(isspace(*ptr)) ptr++; + + // ********************************************* + // * If an opening brace is found at this point + // * it means that the developer entered the + // * service data without entering the service. + // ********************************************* + if(*ptr=='{') error = ELEMENT_NO_SERVICE; + + // ********************************************* + // * If a servicename has been provided. + // ********************************************* + if(!error && *ptr!=',' && *ptr!=';' && *ptr!='}') + { + tPtr = ptr; + while(*ptr && *ptr!=',' && *ptr!=';' && + *ptr!='}' && !isspace(*ptr)) ptr++; + + oldChar = *ptr; + *ptr = 0; + service = findService(tPtr); + *ptr = oldChar; + + if(service==NULL) error = ELEMENT_SERVICE_UNDEFINED; + else { + // ***************************** + // * Walk to the beginning of + // * the next entry. + // ***************************** + while(*ptr && isspace(*ptr)) ptr++; + + // ***************************** + // * If the next character is an + // * opening brace then the + // * service data can be read. + // ***************************** + if(!error && *ptr=='{') + { + if(assimilateTags(ptr, tags, nTags)!=0) + { + error = SERVICE_DATA_CLOSE_BRACE; + } + } + } + } + // ********************************************* + // * If no errors have occured walk to the end + // * of the definition. + // ********************************************* + if(!error) + { + while(*ptr && isspace(*ptr)) ptr++; + if(*ptr=='}') + { + // Do nothing + } + else if(*ptr==',' || *ptr==';') + { + for(ptr++; isspace(*ptr); ptr++); + } + else error = ELEMENT_FMT; + } + + // ********************************************* + // * If the entry is a message and the developer + // * has not specified a service, then it cannot + // * be added to the list. + // ********************************************* + if(!error && type==MESSAGE && service==NULL) + error=MESSAGE_NEEDS_SERVICE; + + // ********************************************* + // * If the data was read, add it to the + // * definition, otherwise, report an error. + // ********************************************* + if(!error) + { + if(nTags==0 && tags!=NULL) + { + delete tags; + tags = NULL; + } + + switch(type) + { + case VERB: + def.addVerb(name, service, tags, nTags); + break; + + case ATTRIBUTE: + def.addAttribute(name, service, tags, nTags); + break; + + case MESSAGE: + def.addMessage(name, service, tags, nTags); + break; + } + } + else { + cdevReportError( + CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Class \"%s\" - %s \"%s\" Error\n\t=> %s %s\n\t=> Format is: %ss {name service {serviceData};}\n", + def.getName(), readElementTypeNames[type], name?name:"UNKNOWN", + readElementTypeNames[type], readElementErrors[error], + readElementTypeNames[type]); + + if(name) delete name; + if(tags && nTags) while(--nTags>=0) delete tags[nTags]; + if(tags) delete tags; + ptr = errorRestart; + } + } + } + } + + *end = oldEndChar; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::readDevices : +// * This method is used to read all of the device instances that are defined +// * within the CDEV DDL data. +// ***************************************************************************** +void cdevDirectoryTable::readDevices ( char * buf ) + { + cdevClassDefinition * def; + + for(def = classHead; def!=NULL; def = def->getNext()) + { + char * ptr = buf; + char oldChar; + char * name; + char * substName; + char * tPtr; + char target[255]; + int targetLen; + sprintf(target, "\n%s :", def->getName()); + targetLen = strlen(target); + while((ptr = strstr(ptr, target))!=NULL) + { + ptr+=targetLen; + while(*ptr && *ptr!=';') + { + while(isspace(*ptr)) ptr++; + tPtr = ptr; + while(*ptr!=',' && *ptr!=';' && !isspace(*ptr)) ptr++; + + oldChar = *ptr; + *ptr = 0; + if(strlen(tPtr)>0) + { + name = strdup(tPtr); + substName = NULL; + *ptr = oldChar; + + // ************************************* + // * Start looking to see if a + // * substitution name is provided with + // * the device name. + // ************************************* + for(tPtr = ptr; isspace(*tPtr); tPtr++); + if(*tPtr=='{') + { + do { tPtr++; } while(isspace(*tPtr)); + for(ptr = tPtr; *ptr && !isspace(*ptr) && *ptr!='}'; ptr++); + oldChar = *ptr; + *ptr = 0; + if(strlen(tPtr)>0) + { + substName = strdup(tPtr); + } + *ptr = oldChar; + while(*ptr && *ptr!='}') ptr++; + } + + if(def->addDevice(name, substName)!=CDEV_SUCCESS) + { + cdevReportError( + CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Device %s has already been defined\n", name); + delete name; + delete substName; + } + } + else *ptr = oldChar; + + if(*ptr!=';') ptr++; + } + if(*ptr!=';') + { + cdevReportError( + CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Instance list for class %s unterminated\n\t=> Format is : class : instance1, instance2;", + def->getName()); + } + } + } + } + + +// ***************************************************************************** +// * These are the definitive errors for the readAliases method. +// ***************************************************************************** +static char * readAliasErrors [] = + { + "", + "Alias name has not been specified", + "Alias name has already been defined", + "Aliased device has not been specified", + "Aliased device has not been defined" + }; + +// ***************************************************************************** +// * cdevDirectoryTable::readAliases : +// * This method is used to read all of the alias definitions within the +// * CDEV DDL data. +// ***************************************************************************** +void cdevDirectoryTable::readAliases ( char * buf ) + { + char * ptr = buf; + + enum { + SUCCESS = 0, + ALIAS_NAME_NOT_SPECIFIED, + ALIAS_ALREADY_DEFINED, + ALIAS_DEVICE_NOT_SPECIFIED, + ALIAS_DEVICE_NOT_DEFINED + } error = SUCCESS; + + while((ptr = strstr(ptr, "\nalias "))!=NULL) + { + char oldChar; + char * name = NULL; + char deviceName[255]; + + error = SUCCESS; + ptr += 7; + *deviceName = 0; + + while(isspace(*ptr) && *ptr!='\n') ptr++; + if(*ptr=='\n' || *ptr=='\0') error = ALIAS_NAME_NOT_SPECIFIED; + else { + char *aPtr = ptr; + + while(*ptr && !isspace(*ptr)) ptr++; + oldChar = *ptr; + *ptr = 0; + name = strdup(aPtr); + *ptr = oldChar; + + while(isspace(*ptr) && *ptr!='\n') ptr++; + if(*ptr=='\n' || *ptr=='\0') error = ALIAS_DEVICE_NOT_SPECIFIED; + else { + char *dPtr = ptr; + cdevDeviceDefinition * def = NULL; + + while(*ptr && !isspace(*ptr)) ptr++; + oldChar = *ptr; + *ptr = 0; + strcpy(deviceName, dPtr); + *ptr = oldChar; + def = (cdevDeviceDefinition *)deviceHash.find(deviceName); + + if(def==NULL) error = ALIAS_DEVICE_NOT_DEFINED; + else if(deviceHash.find(name)!=NULL) error = ALIAS_ALREADY_DEFINED; + else addAlias (name, *def); + } + } + if (error) + { + cdevReportError( + CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Alias \"%s\" to device \"%s\" Error\n\t=> %s\n\t=> %s\n", + name?name:"UNKNOWN", *deviceName?deviceName:"UNKNOWN", + readAliasErrors[error], + "Format is: alias aliasname devicename"); + if(name) delete name; + } + } + } + +// ***************************************************************************** +// * These are the definitive errors for the readAliases method. +// ***************************************************************************** +static char * readCollectionErrors [] = + { + "", + "Collection name has not been specified", + "Collection definition is missing a colon", + "Collection definition is missing a semi-colon", + "Collection definition is empty" + }; + +// ***************************************************************************** +// * cdevDirectoryTable::readCollections : +// * This method is used to read all of the collection definitions from the +// * ASCII DDL file buffer. +// ***************************************************************************** +void cdevDirectoryTable::readCollections ( char * buf ) + { + char * ptr = buf; + char * tPtr; + + enum {SUCCESS=0, + COLLECTION_NAME, + COLLECTION_NO_COLON, + COLLECTION_NO_SEMICOLON, + COLLECTION_EMPTY} error; + + while((ptr = strstr(ptr, "\ncollection "))!=NULL) + { + char * errorRestart = ptr+=12; + char * name = NULL; + char ** devices = NULL; + int nDevices = 0; + + error = SUCCESS; + + // ************************************************************* + // * Reposition ptr to point at the first space after the class + // * name. If a space exists after the name, then copy + // * the name to the name variable, otherwise, report an error. + // ************************************************************* + for(tPtr=ptr; *ptr && !isspace(*ptr); ptr++); + if(*ptr) + { + *ptr = 0; + name = strdup(tPtr); + *ptr = ' '; + } + else error = COLLECTION_NAME; + + if(!error) + { + // ***************************************************** + // * Reposition the ptr to the first occurence of a + // * colon after the collection name. + // ***************************************************** + while(*ptr && isspace(*ptr)) ptr++; + + // ***************************************************** + // * If a colon was not found, then the definition is + // * formatted improperly and an error should be + // * reported. + // ***************************************************** + if(*ptr!=':') error = COLLECTION_NO_COLON; + else for(ptr++; isspace(*ptr); ptr++); + } + + // ************************************************************* + // * Count the number of device names in the definition. + // ************************************************************* + char * deviceStart = ptr; + while(!error && *ptr && *ptr!=';') + { + while(isspace(*ptr)) ptr++; + tPtr = ptr; + while(*ptr!=',' && *ptr!=';' && !isspace(*ptr)) ptr++; + + char oldChar = *ptr; + *ptr = 0; + if(strlen(tPtr)>0) nDevices++; + *ptr = oldChar; + if(*ptr!=';') ptr++; + } + + // ************************************************************* + // * If the closing semicolon is missing then set the error flag + // ************************************************************* + if(!error && *ptr!=';') error = COLLECTION_NO_SEMICOLON; + + // ************************************************************* + // * Otherwise, begin assimilating the device names into the + // * list. + // ************************************************************* + else if(!error && nDevices>0) + { + ptr = deviceStart; + devices = new char *[nDevices]; + nDevices = 0; + + while(*ptr && *ptr!=';') + { + while(isspace(*ptr)) ptr++; + tPtr = ptr; + while(*ptr!=',' && *ptr!=';' && !isspace(*ptr)) ptr++; + + char oldChar = *ptr; + *ptr = 0; + if(strlen(tPtr)>0) devices[nDevices++] = strdup(tPtr); + *ptr = oldChar; + if(*ptr!=';') ptr++; + } + } + + // ************************************************************* + // * If no errors have occured, add the new + // * cdevCollectionDefinition to the list. + // ************************************************************* + if(!error) + { + cdevCollectionDefinition * def = + new cdevCollectionDefinition(name, devices, nDevices); + + if(addCollection(def)!=CDEV_SUCCESS) delete def; + } + else { + cdevReportError( + CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Collection \"%s\" Error\n\t=> %s\n\t=> %s\n", + name?name:"UNKNOWN", readCollectionErrors[error], + "Format is: collection name : device1 device2;"); + + if(name) delete name; + if(devices) delete devices; + + ptr = errorRestart; + } + } + return; + } diff --git a/src/directory/cdevDirectoryTable.h b/src/directory/cdevDirectoryTable.h new file mode 100755 index 0000000..58e9372 --- /dev/null +++ b/src/directory/cdevDirectoryTable.h @@ -0,0 +1,722 @@ +#ifndef _CDEV_DIRECTORY_TABLE_H_ +#define _CDEV_DIRECTORY_TABLE_H_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __VMS +typedef unsigned long u_long; +typedef unsigned short u_short; +#endif + + +class cdevElementDefinition; +class cdevClassDefinition; +class cdevServiceDefinition; +class cdevAliasDefinition; +class cdevDeviceDefinition; +class cdevCollectionDefinition; + +int CDEV_CLASS_SPEC cdevReportError(int severity, char *name, void *, char *formatString, ...); + +// ***************************************************************************** +// * class cdevDirectoryTable : +// * This is the master class that is used to collect and maintain +// * information associated with the CDEV Device Definition Language file. +// * +// * This class maintains a number of tables and lists for the following +// * purposes... +// * +// * collectionClass - This is the single instance of the cdevClassDefinition +// * for the collection class. +// * +// * serviceHead - This is a list of all of the services that have been +// * serviceTail read from the DDL file in the order in which they +// * were loaded. +// * +// * classHead - This is a list of all of the classes that have been +// * classTail read from the DDL file in the order in which they +// * were loaded. +// * +// * aliasHead - This is a list of aliases that are defined within +// * aliasTail the DDL file. +// * +// * collectionHead - This is a list of collection devices that are +// * collectionTail defined within the DDL file. +// * +// * serviceHash - This is a hash table that allows for fast lookup of +// * each of the services that were loaded into the +// * service list. +// * +// * classHash - This is a hash table that allows fast lookup by name +// * of any of the classes that were loaded into the +// * class list. +// * +// * classInstanceHash - This is a hash table that contains only the names +// * and addresses of classes that have been used to +// * instanciate a device. +// * +// * deviceHash - This is a hash table that allows the caller to +// * quickly locate any device that has been defined in +// * the DDL file. +// * +// * collectionHash - This is a hash table that allows the caller to +// * quickly locate a collection device definition. +// ***************************************************************************** +class CDEV_CLASS_SPEC cdevDirectoryTable +{ +public: + static long BinaryMagic_1_4; + static long BinaryMagic_1_5; + static long BinaryMagic; + + typedef enum {VERB=0, ATTRIBUTE, MESSAGE} ElementType; + +private: + cdevClassDefinition * collectionClass; + + cdevServiceDefinition * serviceHead; + cdevServiceDefinition * serviceTail; + cdevClassDefinition * classHead; + cdevClassDefinition * classTail; + cdevAliasDefinition * aliasHead; + cdevAliasDefinition * aliasTail; + cdevCollectionDefinition * collectionHead; + cdevCollectionDefinition * collectionTail; + StringHash serviceHash; + StringHash classHash; + StringHash classInstanceHash; + StringHash deviceHash; + StringHash collectionHash; + +public: + inline cdevDirectoryTable ( void ); + inline ~cdevDirectoryTable ( void ); + + inline int addService ( cdevServiceDefinition *def ); + inline int addService ( char *name, + char **tags=NULL, + int nTags=0); + + inline int addClass ( cdevClassDefinition *def ); + inline int addClass ( char *name, + cdevClassDefinition *parent = NULL, + cdevElementDefinition *verbs = NULL, + cdevElementDefinition *attributes = NULL, + cdevElementDefinition *messages = NULL); + + inline int addClassInstance ( cdevClassDefinition * def ); + inline int addDevice ( cdevDeviceDefinition * def ); + inline int addAlias ( cdevAliasDefinition * def ); + inline int addAlias ( char * name, cdevDeviceDefinition & def ); + inline int addCollection ( cdevCollectionDefinition * def ); + inline int addCollection ( char * name, char ** devices, int nDevices ); + + inline void asciiDump ( FILE * fp = stdout ); + inline void asciiDumpRedirector ( FILE * fp = stdout ); + + inline cdevServiceDefinition * findService ( char * name ); + inline cdevClassDefinition * findClass ( char * name ); + + // ********************************************************************* + // * Member access methods. + // ********************************************************************* + inline cdevServiceDefinition * getServices ( void ); + inline cdevClassDefinition * getClasses ( void ); + inline cdevAliasDefinition * getAliases ( void ); + inline StringHash & getServiceHash ( void ); + inline StringHash & getClassHash ( void ); + inline StringHash & getInstanceHash ( void ); + inline StringHash & getDeviceHash ( void ); + inline StringHash & getCollectionHash (void ); + + // ********************************************************************* + // * External data load/dump methods. + // ********************************************************************* + int load ( char * inputFile ); + int asciiLoad ( char * inputFile ); + int asciiBufferLoad ( char * buffer ); + void binaryDump ( char * outputFile ); + int binaryLoad ( char * inputFile ); + int loadText ( char * includePath, char * filename, char * &buf, int &buflen, int &cursor); + void readServices ( char * buf ); + void readClasses ( char * buf ); + void readElements ( cdevClassDefinition &def, ElementType type, char *start, char *end ); + void readDevices ( char * buf ); + void readAliases ( char * buf ); + void readCollections ( char * buf ); + void compressComments ( char * filename, char * buf ); + void compressSpaces ( char * filename, char * buf ); +}; + +#include +#include +#include +#include +#include +#include +#include + +// ***************************************************************************** +// * cdevDirectoryTable::cdevDirectoryTable : +// * Constructor for the cdevDirectoryTable class. +// ***************************************************************************** +inline cdevDirectoryTable::cdevDirectoryTable ( void ) + : serviceHead(NULL), serviceTail(NULL), classHead(NULL), classTail(NULL), + aliasHead(NULL), aliasTail(NULL), collectionHead(NULL), + collectionTail(NULL), serviceHash(0), classHash(0), + deviceHash(0, 9973), classInstanceHash(0), collectionHash(0) + { + // ********************************************************************* + // * Note, by creating a collection class to hold all collection devices + // * I am preventing the developer from creating his own collection + // * class. + // ********************************************************************* + collectionClass = new cdevClassDefinition(*this, strdup("collection")); + addClass(collectionClass); + } + + +// ***************************************************************************** +// * cdevDirectoryTable::~cdevDirectoryTable : +// * This is the destructor for the cdevDirectoryTable class. +// ***************************************************************************** +inline cdevDirectoryTable::~cdevDirectoryTable ( void ) + { + while(serviceHead!=NULL) + { + cdevServiceDefinition *ptr = serviceHead; + serviceHead = ptr->getNext(); + serviceHash.remove(ptr->getName()); + delete ptr; + } + while(classHead!=NULL) + { + cdevClassDefinition *ptr = classHead; + classHead = ptr->getNext(); + classHash.remove(ptr->getName()); + classInstanceHash.remove(ptr->getName()); + delete ptr; + } + while(aliasHead!=NULL) + { + cdevAliasDefinition *ptr = aliasHead; + aliasHead = ptr->getNext(); + deviceHash.remove(ptr->getName()); + delete ptr; + } + while(collectionHead!=NULL) + { + cdevCollectionDefinition *ptr = collectionHead; + collectionHead = ptr->getNext(); + collectionHash.remove(ptr->getName()); + delete ptr; + } + } + + +// ***************************************************************************** +// * cdevDirectoryTable::addService : +// * Adds a new service to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addService ( cdevServiceDefinition * def ) + { + int result = CDEV_SUCCESS; + + if(def!=NULL && def->getName() && *def->getName()) + { + if(serviceHash.find(def->getName())!=NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Service \"%s\" is already defined", def->getName()); + result = CDEV_ERROR; + } + else + { + serviceHash.insert(def->getName(), def); + if(serviceTail==NULL) + { + serviceTail = def; + serviceHead = def; + } + else { + serviceTail->setNext(def); + serviceTail = def; + } + } + } + else result = CDEV_ERROR; + + return result; + } + + + +// ***************************************************************************** +// * cdevDirectoryTable::addService : +// * Adds a new service to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addService ( char * name, char ** tags, int nTags ) + { + int result = CDEV_SUCCESS; + + if(name!=NULL && *name) + { + if(serviceHash.find(name)!=NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Service \"%s\" is already defined", name); + result = CDEV_ERROR; + } + else + { + cdevServiceDefinition *def = new cdevServiceDefinition + (name, tags, nTags); + + serviceHash.insert(name, def); + if(serviceTail==NULL) + { + serviceTail = def; + serviceHead = def; + } + else { + serviceTail->setNext(def); + serviceTail = def; + } + } + } + else result = CDEV_ERROR; + + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::addClass : +// * Adds a new class to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addClass ( cdevClassDefinition * def ) + { + int result = CDEV_SUCCESS; + if(def!=NULL && def->getName() && *def->getName()) + { + if(classHash.find(def->getName())!=NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Class \"%s\" is already defined", def->getName()); + result = CDEV_ERROR; + } + else + { + classHash.insert(def->getName(), def); + if(classTail==NULL) + { + classTail = def; + classHead = def; + } + else { + classTail->setNext(def); + classTail = def; + } + } + } + else result = CDEV_ERROR; + + return result; + } + +// ***************************************************************************** +// * cdevDirectoryTable::addClass : +// * Adds a new class to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addClass + ( char *name, + cdevClassDefinition *parent, + cdevElementDefinition *verbs, + cdevElementDefinition *attributes, + cdevElementDefinition *messages) + { + int result = CDEV_SUCCESS; + + if(name!=NULL && *name) + { + if(classHash.find(name)!=NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Class \"%s\" is already defined", name); + result = CDEV_ERROR; + } + else + { + cdevClassDefinition *def = new cdevClassDefinition + (*this, name, parent, verbs, attributes, messages); + + classHash.insert(name, def); + if(classTail==NULL) + { + classTail = def; + classHead = def; + } + else { + classTail->setNext(def); + classTail = def; + } + } + } + else result = CDEV_ERROR; + + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::addClassInstance : +// * Adds a new class instance to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addClassInstance ( cdevClassDefinition * def ) + { + int result = CDEV_SUCCESS; + if(def!=NULL && def->getName() && *def->getName()) + { + if(classHash.find(def->getName())==NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Class \"%s\" has not been defined", def->getName()); + result = CDEV_ERROR; + } + else if(classInstanceHash.find(def->getName())==NULL) + { + classInstanceHash.insert(def->getName(), def); + } + } + else result = CDEV_ERROR; + + return result; + } + +// ***************************************************************************** +// * cdevDirectoryTable::addDevice : +// * Adds a new device to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addDevice ( cdevDeviceDefinition * def ) + { + int result = CDEV_SUCCESS; + if(def!=NULL && def->getName()!=NULL && *def->getName()) + { + if(deviceHash.find(def->getName())!=NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Device \"%s\" has already been defined", def->getName()); + result = CDEV_ERROR; + } + else deviceHash.insert(def->getName(), def); + } + else result = CDEV_ERROR; + + return result; + } + +// ***************************************************************************** +// * cdevDirectoryTable::addAlias : +// * Adds a new alias to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addAlias ( cdevAliasDefinition * def ) + { + int result = CDEV_SUCCESS; + if(def!=NULL && def->getName() && *def->getName()) + { + if(deviceHash.find(def->getName())!=NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Alias \"%s\" has already been defined", def->getName()); + result = CDEV_ERROR; + } + else { + if(aliasTail==NULL) + { + aliasHead = def; + aliasTail = def; + } + else { + aliasTail->setNext(def); + aliasTail = def; + } + deviceHash.insert(def->getName(), &def->getDevice()); + } + } + else result = CDEV_ERROR; + + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::addAlias : +// * Adds a new alias to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addAlias + ( char * name, cdevDeviceDefinition & device ) + { + cdevAliasDefinition *def = new cdevAliasDefinition(name, device); + int result = addAlias(def); + if(result!=CDEV_SUCCESS) delete def; + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::addCollection : +// * Adds a new collection to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addCollection ( cdevCollectionDefinition * def ) + { + int result = CDEV_SUCCESS; + if(def!=NULL && def->getName()!=NULL && *def->getName()) + { + if(deviceHash.find(def->getName())!=NULL || + collectionHash.find(def->getName())!=NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Collection device \"%s\" has already been defined", def->getName()); + result = CDEV_ERROR; + } + else { + if(collectionTail==NULL) + { + collectionTail = def; + collectionHead = def; + } + else { + collectionTail->setNext(def); + collectionTail = def; + } + collectionHash.insert(def->getName(), def); + collectionClass->addDevice (strdup(def->getName())); + } + } + else result = CDEV_ERROR; + + return result; + } + +// ***************************************************************************** +// * cdevDirectoryTable::addCollection : +// * Adds a new collection to the directory table. +// ***************************************************************************** +inline int cdevDirectoryTable::addCollection ( char * name, char ** devices, int nDevices ) + { + int result; + + cdevCollectionDefinition * def = + new cdevCollectionDefinition(name, devices, nDevices); + + if((result = addCollection(def))!=CDEV_SUCCESS) delete def; + + return result; + } +// ***************************************************************************** +// * cdevDirectoryTable::findService : +// * Allows the caller to locate a service by name. +// ***************************************************************************** +inline cdevServiceDefinition * cdevDirectoryTable::findService ( char * name ) + { + return (cdevServiceDefinition *)serviceHash.find(name); + } + + +// ***************************************************************************** +// * cdevDirectoryTable::findClass : +// * Allows the caller to locate a class by name. +// ***************************************************************************** +inline cdevClassDefinition * cdevDirectoryTable::findClass ( char * name ) + { + return (cdevClassDefinition *)classHash.find(name); + } + +// ***************************************************************************** +// * cdevDirectoryTable::asciiDump : +// * This method will write the contents of the cdevDirectory object to +// * the user provided file pointer. +// ***************************************************************************** +inline void cdevDirectoryTable::asciiDump ( FILE * fp ) + { + cdevServiceDefinition *sPtr = serviceHead; + if(sPtr) + { + fprintf(fp, "\n// ******************************************\n"); + fprintf(fp, "// * Table of service definitions... *\n"); + fprintf(fp, "// ******************************************\n"); + } + while(sPtr!=NULL) + { + sPtr->asciiDump(fp); + sPtr = sPtr->getNext(); + } + + cdevClassDefinition *cPtr = classHead; + if(cPtr) + { + fprintf(fp, "\n// ******************************************\n"); + fprintf(fp, "// * Table of class definitions... *\n"); + fprintf(fp, "// ******************************************\n"); + } + while(cPtr!=NULL) + { + if(cPtr!=collectionClass) cPtr->asciiDump(fp); + cPtr = cPtr->getNext(); + } + + cPtr = classHead; + if(cPtr) + { + fprintf(fp, "\n// ******************************************\n"); + fprintf(fp, "// * Table of class instance definitions... *\n"); + fprintf(fp, "// ******************************************\n"); + } + while(cPtr!=NULL) + { + if(cPtr!=collectionClass) cPtr->asciiDumpInstances(fp); + cPtr = cPtr->getNext(); + } + + cdevAliasDefinition *aPtr = aliasHead; + if(aPtr) + { + fprintf(fp, "\n\n// ******************************************\n"); + fprintf(fp, "// * Table of alias definitions... *\n"); + fprintf(fp, "// ******************************************\n"); + } + while(aPtr!=NULL) + { + aPtr->asciiDump(fp); + aPtr = aPtr->getNext(); + } + + cdevCollectionDefinition * clPtr = collectionHead; + if(clPtr) + { + fprintf(fp, "\n\n// ******************************************\n"); + fprintf(fp, "// * Table of collection definitions... *\n"); + fprintf(fp, "// ******************************************\n"); + } + while(clPtr!=NULL) + { + clPtr->asciiDump(fp); + clPtr = clPtr->getNext(); + } + } + +// ***************************************************************************** +// * cdevDirectoryTable::asciiDumpRedirector : +// * This is a diagnostic method that allows the caller to dump the contents +// * of the redirection table for each class that has been instanciated. +// ***************************************************************************** +inline void cdevDirectoryTable::asciiDumpRedirector ( FILE * fp ) + { + int cnt = 0; + + cdevClassDefinition *def; + for(def = classHead; def!=NULL; def = def->getNext()) + { + if(classInstanceHash.find(def->getName())!=NULL) + { + def->asciiDumpRedirector(fp); + cnt++; + } + } + if(!cnt) cdevReportError(CDEV_SEVERITY_WARN, "CDEV Directory", NULL, + "No devices have been instanciated"); + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getServices : +// * Returns the list of services that are defined within the directory. +// ***************************************************************************** +inline cdevServiceDefinition * cdevDirectoryTable::getServices ( void ) + { + return serviceHead; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getClasses : +// * Returns the list of classes that are defined within the directory. +// ***************************************************************************** +inline cdevClassDefinition * cdevDirectoryTable::getClasses ( void ) + { + return classHead; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getAliases : +// * Returns the list of aliases that are defined within the directory. +// ***************************************************************************** +inline cdevAliasDefinition * cdevDirectoryTable::getAliases ( void ) + { + return aliasHead; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getServiceHash : +// * Return a hash table of services that are defined within the directory. +// ***************************************************************************** +inline StringHash & cdevDirectoryTable::getServiceHash ( void ) + { + return serviceHash; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getClassHash : +// * Return a hash table of classes that are defined within the directory. +// ***************************************************************************** +inline StringHash & cdevDirectoryTable::getClassHash ( void ) + { + return classHash; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getInstanceHash : +// * Return a hash table of classes that have been instanciated within the +// * directory. +// ***************************************************************************** +inline StringHash & cdevDirectoryTable::getInstanceHash ( void ) + { + return classInstanceHash; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getDeviceHash : +// * Return a hash table of device names that have been instanciated in all +// * classes within the directory. This hash-table includes aliases that +// * have been instanciated. +// ***************************************************************************** +inline StringHash & cdevDirectoryTable::getDeviceHash ( void ) + { + return deviceHash; + } + + +// ***************************************************************************** +// * cdevDirectoryTable::getCollectionHash : +// * Return a hash table of collection names that have been instanciated in +// * the DDL file. Each collection definition contains the list of devices +// * that it contains. +// ***************************************************************************** +inline StringHash & cdevDirectoryTable::getCollectionHash ( void ) + { + return collectionHash; + } + + +#endif /* _CDEV_DIRECTORY_TABLE_H_ */ diff --git a/src/directory/cdevDirectoryTool.cc b/src/directory/cdevDirectoryTool.cc new file mode 100755 index 0000000..384e800 --- /dev/null +++ b/src/directory/cdevDirectoryTool.cc @@ -0,0 +1,1036 @@ +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#endif +#include +#include + + +// ***************************************************************************** +// * class QuickListNode : +// * This node class is used to temporarily store results that are retrieved +// * from the cdevDirectoryTable prior to placing them into an array. +// ***************************************************************************** +class QuickListNode +{ +friend class QuickList; + +private: + char * data; + QuickListNode * next; + static QuickListNode * freeList; + +public: + + QuickListNode( void ) + : data(NULL), next(NULL) + { + } + + QuickListNode( char *str ) + : data(NULL), next(NULL) + { + data = str; + } + + ~QuickListNode ( void ) + { + data = NULL; + next = NULL; + } + + void * operator new ( size_t ); + void operator delete ( void * item ); +}; + +QuickListNode * QuickListNode::freeList = NULL; + +void * QuickListNode::operator new ( size_t ) + { + QuickListNode * result = NULL; + + if(freeList==NULL) + { + QuickListNode * pile = ::new QuickListNode[64]; + for(int i=0; i<63; i++) pile[i].next = &pile[i+1]; + freeList = pile; + } + result = freeList; + freeList = freeList->next; + return result; + } + +void QuickListNode::operator delete ( void * item ) + { + QuickListNode * node = (QuickListNode *)item; + node->next = freeList; + freeList = node; + } + +// ***************************************************************************** +// * class QuickList : +// * This node class is used to temporarily store results that are retrieved +// * from the cdevDirectoryTable prior to placing them into an array. +// ***************************************************************************** +class QuickList +{ +private: + QuickListNode * cursor; + QuickListNode * head; + QuickListNode * tail; + int itemCnt; + +public: + QuickList ( void ) : cursor(NULL), head(NULL), tail(NULL), itemCnt(0) + { + } + + ~QuickList ( void ) + { + while(head!=NULL) + { + QuickListNode * x = head; + head = head->next; + delete x; + } + } + + char * first ( void ) + { + cursor = head; + return cursor?cursor->data:(char *)NULL; + } + + char * operator ++ ( void ) + { + if(cursor) cursor=cursor->next; + return cursor?cursor->data:(char *)NULL; + } + + char * operator ++ ( int ) + { + if(cursor) cursor=cursor->next; + return cursor?cursor->data:(char *)NULL; + } + + char * data ( void ) + { + return cursor?cursor->data:(char *)NULL; + } + + void add ( char * data ) + { + if(data) { + if(tail) + { + tail->next = new QuickListNode(data); + tail = tail->next; + itemCnt++; + } + else { + head = new QuickListNode(data); + tail = head; + itemCnt++; + } + } + } + + int count ( void ) + { + return itemCnt; + } + + char ** array ( void ) + { + char ** ptr = NULL; + if(itemCnt && head) { + ptr = new char * [itemCnt+1]; + QuickListNode * node; + int i = 0; + for(node = head; node!=NULL; node=node->next) + { + ptr[i++] = node->data; + } + ptr[i] = NULL; + } + return ptr; + } +}; + + + +// ***************************************************************************** +// * cdevDirectoryTool::cdevDirectoryTool : +// * This is the constructor for the cdevDirectoryTool object. It will +// * create a cdevDirectoryTable and use the file specified by CDEVDDL to +// * populate it with information. +// ***************************************************************************** +cdevDirectoryTool::cdevDirectoryTool ( void ) + : cdevDirectoryTable() + { + } + +// ***************************************************************************** +// * cdevDirectoryTool::~cdevDirectoryTool : +// * This is the destructor for the cdevDirectoryTool object. It will delete +// * the underlying cdevDirectoryTable. +// ***************************************************************************** +cdevDirectoryTool::~cdevDirectoryTool ( void ) + { + } + + +// ***************************************************************************** +// * cdevDirectoryTool::query : +// * This method allows the caller to query the cdevDirectoryTable for +// * all devices that are in a specified class. The returned list may +// * be narowed by providing a regular expression that will be used to +// * match the device. +// ***************************************************************************** +int cdevDirectoryTool::query (cdevDirectoryTable &table, cdevData *in, cdevData *out) + { + int result = CDEV_SUCCESS; + char device [255]; + char classname [255]; + + QuickList devices; + + char ** classes = NULL; + size_t nClasses = 0; + + if(!out) return CDEV_ERROR; + + // ********************************************************************* + // * Empty the outbound cdevData object prior to starting. + // ********************************************************************* + out->remove(); + + // ********************************************************************* + // * Prior to descending into the bowels of this code, determine if + // * the caller is asking for the contents of a collection device... + // ********************************************************************* + if(in) + { + *classname = 0; + *device = 0; + in->get("class", classname, 255); + in->get("device", device, 255); + + // ************************************************************* + // * If the class is not specified and the device is specified, + // * determine if the device is an instance of a collection. + // ************************************************************* + if(*classname==0 && *device!=0) + { + cdevCollectionDefinition * def = + (cdevCollectionDefinition *)table.getCollectionHash().find(device); + + // ***************************************************** + // * If the device is an instance of a collection, + // * extract the names of its component devices. + // ***************************************************** + if(def!=NULL) + { + out->insert("value", def->getDevices(), def->getDeviceCnt()); + return CDEV_SUCCESS; + } + } + } + + // ********************************************************************* + // * Call the queryClasses method to locate all of the class names + // * that are associated with this request. + // ********************************************************************* + if((result=queryClasses(table, in, out))!=CDEV_SUCCESS) return result; + + out->getElems("value", &nClasses); + classes = new char *[nClasses]; + out->get ("value", classes); + + // ********************************************************************* + // * Set the default values for the device. + // ********************************************************************* + sprintf(device, ".*"); + + // ********************************************************************* + // * Read the actual values of device and className from the + // * cdevData object if specified. + // ********************************************************************* + if(in) in->get("device", device, 255); + + // ********************************************************************* + // * Generate an operating system specific regexp structure. + // ********************************************************************* + #if defined(__hpux) || defined (solaris) || defined (__linux) || defined (AIX) + regex_t *regexp=0; + if((regexp=(regex_t *) malloc((size_t) sizeof(regex_t))) == 0) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "malloc() failed, memory error!"); + result = CDEV_ERROR; + } + else if(regcomp(regexp, device, REG_EXTENDED) != 0) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Bad regular expression: %s", device); + result = CDEV_ERROR; + } + #else + regexp *regexp=0; + if((regexp=regcomp(device))==0) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Bad regular expression: %s", device); + result = CDEV_ERROR; + } + #endif + + // ********************************************************************* + // * Walk through the list and locate all devices that match the + // * regular expression. + // ********************************************************************* + if(result==CDEV_SUCCESS) + { + for(int i = 0; igetDevices(); def!=NULL; def = def->getNext()) + { + #if defined (__hpux) || defined (solaris) || defined (__linux) || defined (AIX) + if(regexec(regexp, def->getName(), 0, 0, 0) == 0) + #else + if(regexec(regexp, def->getName()) != 0) + #endif + { + devices.add(def->getName()); + } + } + } + } + } + // ********************************************************************* + // * If device names were collected, then place them into the outbound + // * data object. Otherwise, set the result to CDEV_NOTFOUND. + // ********************************************************************* + if(result==CDEV_SUCCESS) + { + if(devices.count()>0) + { + char ** array = devices.array(); + out->insert("value", array); + delete array; + } + else { + out->remove(); + result = CDEV_NOTFOUND; + } + } + + // ********************************************************************* + // * Release the regular expression variable and return the result. + // ********************************************************************* + if(regexp) + { +#if !defined (__VMS) && !defined (_WIN32) + regfree(regexp); +#endif + free (regexp); + } + if(classes) + { + while(nClasses>0) delete classes[--nClasses]; + delete classes; + } + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTool::queryClass : +// * This method allows the caller to query the cdevDirectoryTable for +// * the name of the class that a specific device belongs to. +// ***************************************************************************** +int cdevDirectoryTool::queryClass (cdevDirectoryTable &table, cdevData *in, cdevData *out) + { + int result = CDEV_SUCCESS; + char device[255]; + + *device = 0; + + if(out==NULL) result = CDEV_INVALIDARG; + else { + out->remove(); + + if(!in || in->get("device", device, 255)!=CDEV_SUCCESS) + { + result = CDEV_INVALIDARG; + } + else { + cdevDeviceDefinition * def = + (cdevDeviceDefinition *) + table.getDeviceHash().find(device); + if(def==NULL) result = CDEV_NOTFOUND; + else { + out->insert("value", def->getClass().getName()); + result = CDEV_SUCCESS; + } + } + } + + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTool::queryClasses : +// * Finds all classes that match the specified regular expression. +// ***************************************************************************** +int cdevDirectoryTool::queryClasses (cdevDirectoryTable &table, cdevData *in, cdevData *out) + { + cdevClassDefinition * def; + int result = CDEV_SUCCESS; + QuickList classes; + char classname[255]; + + // ********************************************************************* + // * If the outbound cdevData object is not specified return CDEV_ERROR. + // ********************************************************************* + if(!out) return CDEV_ERROR; + + // ********************************************************************* + // * Obtain the class name using a default if necessary. + // ********************************************************************* + *classname = 0; + if(in) in->get("class", classname, 255); + + // ********************************************************************* + // * If the name represents a specific class name, then locate all + // * other classes that inherit from that class and add them to the + // * list. + // ********************************************************************* + if((def=(cdevClassDefinition *)table.getClassHash().find(classname))!=NULL) + { + cdevClassDefinition * cur; + for(cur=table.getClasses(); cur!=NULL; cur=cur->getNext()) + { + if(cur->isA(classname)) classes.add(cur->getName()); + } + } + // ********************************************************************* + // * Return the name of all implementation classes. That is all classes + // * that have device instances created from them. + // ********************************************************************* + else if(*classname==0) + { + cdevClassDefinition * cur; + for(cur=table.getClasses(); cur!=NULL; cur=cur->getNext()) + { + if(cur->getDevices()!=NULL) classes.add(cur->getName()); + } + } + // ********************************************************************* + // Otherwise, use regular expression comparison to locate all matches. + // ********************************************************************* + else { + // ************************************************************* + // * Generate an operating system specific regexp structure. + // ************************************************************* + #if defined(__hpux) || defined (solaris) || defined (__linux) || defined (AIX) + regex_t *regexp=0; + if((regexp=(regex_t *) malloc((size_t) sizeof(regex_t))) == 0) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "malloc() failed, memory error!"); + result = CDEV_ERROR; + } + else if(regcomp(regexp, classname, REG_EXTENDED) != 0) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Bad regular expression: %s", classname); + result = CDEV_ERROR; + } + #else + regexp *regexp=0; + if((regexp=regcomp(classname))==0) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Bad regular expression: %s", classname); + result = CDEV_ERROR; + } + #endif + + if(result==CDEV_SUCCESS) + { + StringHashIterator iter(&table.getClassHash()); + char * key; + + for(iter.first(); (key=iter.key())!=NULL; iter++) + { + #if defined (__hpux) || defined (solaris) || defined (__linux) || defined (AIX) + if(regexec(regexp, key, 0, 0, 0) == 0) + #else + if(regexec(regexp, key) != 0) + #endif + { + classes.add(key); + } + } + } + + // ************************************************************* + // * Release the regular expression variable. + // ************************************************************* + if(regexp) + { +#if !defined (__VMS) && !defined (_WIN32) + regfree(regexp); +#endif + free (regexp); + } + } + + // ********************************************************************* + // * If class names were collected, then place them into the outbound + // * data object. Otherwise, set the result to CDEV_NOTFOUND. + // ********************************************************************* + if(result==CDEV_SUCCESS) + { + if(classes.count()>0) + { + char ** array = classes.array(); + out->insert("value", array); + delete array; + } + else result = CDEV_NOTFOUND; + } + + return result; + } + +// ***************************************************************************** +// * cdevDirectoryTool::queryCollection : +// * Finds all devices that are part of a collection. +// ***************************************************************************** +int cdevDirectoryTool::queryCollection (cdevDirectoryTable &table, cdevData *in, cdevData *out) + { + int result = CDEV_SUCCESS; + char device [255]; + + if(!out) return CDEV_INVALIDARG; + + // ********************************************************************* + // * Empty the outbound cdevData object prior to starting. + // ********************************************************************* + out->remove(); + + if(in) + { + *device = 0; + in->get("device", device, 255); + + if(*device) + { + cdevCollectionDefinition * def = + (cdevCollectionDefinition *)table.getCollectionHash().find(device); + + // ***************************************************** + // * If the device is an instance of a collection, + // * extract the names of its component devices. + // ***************************************************** + if(def!=NULL) + { + if(def->getDeviceCnt()>0) + out->insert("value", def->getDevices(), def->getDeviceCnt()); + result = CDEV_SUCCESS; + } + else result = CDEV_NOTFOUND; + } + else result = CDEV_INVALIDARG; + } + else result = CDEV_INVALIDARG; + return result; + } + +// ***************************************************************************** +// * cdevDirectoryTool::queryElements : +// * This method allows the caller to query the cdevDirectoryTable for +// * the particular element type that is associated with a device or class. +// ***************************************************************************** +int cdevDirectoryTool::queryElements ( cdevDirectoryTable &table, + cdevDirectoryTable::ElementType type, + cdevData *in, cdevData *out) + { + int result = CDEV_SUCCESS; + cdevClassDefinition * classDef = NULL; + cdevElementDefinition ** elementDef = NULL; + int nElements = 0; + char device [255]; + char className[255]; + + *device = 0; + *className = 0; + + if(out==NULL) result = CDEV_INVALIDARG; + else { + out->remove(); + + if(!in || + (in->get("device", device, 255)!=CDEV_SUCCESS) && + in->get("class", className, 255)!=CDEV_SUCCESS) + { + result = CDEV_INVALIDARG; + } + else if(*device) + { + cdevDeviceDefinition * def = + (cdevDeviceDefinition *) + table.getDeviceHash().find(device); + + if(def==NULL) result = CDEV_NOTFOUND; + else classDef = &def->getClass(); + } + else { + classDef = (cdevClassDefinition *) + table.getClassHash().find(className); + if(classDef==NULL) result = CDEV_NOTFOUND; + } + } + + if(classDef!=NULL) + { + if(classDef->getElements(type, elementDef, nElements)>0) + { + int i = 0; + char ** ptr = new char *[nElements+1]; + + for(i=0; igetName(); + } + ptr[i] = NULL; + + out->insert("value", ptr); + delete ptr; + delete elementDef; + } + else { + result = CDEV_NOTFOUND; + if(elementDef) delete elementDef; + } + } + + return result; + } + +// ***************************************************************************** +// * cdevDirectoryTool::queryVerbs : +// * This method allows the caller to query the cdevDirectoryTable for +// * all verbs that are associated with a device or class. +// ***************************************************************************** +int cdevDirectoryTool::queryVerbs ( cdevDirectoryTable &table, + cdevData *in, cdevData *out) + { + return queryElements(table, cdevDirectoryTable::VERB, in, out); + } + +// ***************************************************************************** +// * cdevDirectoryTool::queryAttributes : +// * This method allows the caller to query the cdevDirectoryTable for +// * all verbs that are associated with a device or class. +// ***************************************************************************** +int cdevDirectoryTool::queryAttributes (cdevDirectoryTable &table, + cdevData *in, cdevData *out) + { + return queryElements(table, cdevDirectoryTable::ATTRIBUTE, in, out); + } + +// ***************************************************************************** +// * cdevDirectoryTool::queryMessages : +// * This method allows the caller to query the cdevDirectoryTable for +// * all verbs that are associated with a device or class. +// ***************************************************************************** +int cdevDirectoryTool::queryMessages ( cdevDirectoryTable &table, + cdevData *in, cdevData *out) + { + return queryElements(table, cdevDirectoryTable::MESSAGE, in, out); + } + + +// ***************************************************************************** +// * cdevDirectoryTool::service : +// * This method allows the caller to query the cdevDirectoryTable for +// * the service that will respond to a specified device and message. +// ***************************************************************************** +int cdevDirectoryTool::service ( cdevDirectoryTable &table, cdevData *in, cdevData *out) + { + cdevDeviceDefinition * def = NULL; + cdevRedirectorDefinition * redir = NULL; + cdevServiceDefinition * svc = NULL; + int result = CDEV_SUCCESS; + char device [255]; + char message[255]; + + if(out) out->remove(); + *device = 0; + *message = 0; + + if(in==NULL || out==NULL) + { + result = CDEV_INVALIDARG; + } + else if(in->get("device", device, 255)!=CDEV_SUCCESS || + in->get("message", message, 255)!=CDEV_SUCCESS || + *device == 0 || *message == 0) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Field device and message must be specified for service query"); + result = CDEV_INVALIDARG; + } + else if((def = (cdevDeviceDefinition *)table.getDeviceHash().find(device))==NULL) + { + cdevReportError(CDEV_SEVERITY_WARN, "CDEV Directory", NULL, + "Device %s is not listed in the CDEV Directory", + device); + result = CDEV_NOTFOUND; + } + else if((redir = (cdevRedirectorDefinition *)def->getClass().getRedirector().find(message))==NULL) + { + cdevReportError(CDEV_SEVERITY_WARN, "CDEV Directory", NULL, + "Message %s IS NOT supported by device %s", + message, device); + result = CDEV_NOTFOUND; + } + else if((svc = redir->getService()) == NULL) + { + cdevReportError(CDEV_SEVERITY_WARN, "CDEV Directory", NULL, + "No service associated with device \"%s\" message \"%s\"", + device, message); + result = CDEV_NOTFOUND; + } + else + { + char serviceName[255]; + sprintf(serviceName, "%sService", svc->getName()); + out->insert("value", serviceName); + result = CDEV_SUCCESS; + } + + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTool::serviceData : +// * This method allows the caller to query the cdevDirectoryTable for +// * the serviceData that is associated with a specific device/message +// * combination. +// ***************************************************************************** +int cdevDirectoryTool::serviceData ( cdevDirectoryTable &table, cdevData *in, cdevData *out) + { + cdevDeviceDefinition * def = NULL; + cdevRedirectorDefinition * redir = NULL; + int result = CDEV_SUCCESS; + char device [255]; + char message[255]; + + if(out) out->remove(); + *device = 0; + *message = 0; + + if(in==NULL || out==NULL) + { + result = CDEV_INVALIDARG; + } + else if(in->get("device", device, 255)!=CDEV_SUCCESS || + in->get("message", message, 255)!=CDEV_SUCCESS || + *device==0 || *message==0) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Field device and message must be specified for serviceData query"); + result = CDEV_INVALIDARG; + } + else if((def = (cdevDeviceDefinition *)table.getDeviceHash().find(device))==NULL) + { + cdevReportError(CDEV_SEVERITY_WARN, "CDEV Directory", NULL, + "Device %s is not listed in the CDEV Directory", + device); + result = CDEV_NOTFOUND; + } + else if((redir = (cdevRedirectorDefinition *)def->getClass().getRedirector().find(message))==NULL) + { + cdevReportError(CDEV_SEVERITY_WARN, "CDEV Directory", NULL, + "Message %s IS NOT supported by device %s", + message, device); + result = CDEV_NOTFOUND; + } + else { +#if defined (__VMS) && !defined (_WIN32) + const char ** serviceData = redir->getServiceData(); +#else + char ** serviceData = (char **)redir->getServiceData(); +#endif + int dataCount = redir->getDataCnt(); + + for(int i=0; i') + { + strcpy(&tagValue[j], def->getSubstituteName()); + j+=strlen(def->getSubstituteName()); + dTag++; + } + else tagValue[j++] = *dTag; + } + tagValue[j] = 0; + + if(*tagName && *tagValue) + { + if(cdevData::tagC2I(tagName, &tagNum)!=CDEV_SUCCESS) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Attempt to insert unknown cdevData tag\n\t=> Tag Name : %s\n\t=> Tag Value: %s\n", + tagName, tagValue); + } + else out->insert(tagName, tagValue); + } + } + result = CDEV_SUCCESS; + } + + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTool::validate : +// * This method allows the caller to confirm that the specified +// * device/class - mesage combination is valid. +// ***************************************************************************** +int cdevDirectoryTool::validate ( cdevDirectoryTable &table, cdevData *in, cdevData *out) + { + int result = CDEV_SUCCESS; + char className[255]; + char device [255]; + char message [255]; + char verb [255]; + char attribute[255]; + + if(out) out->remove(); + *device = 0; + *className = 0; + *message = 0; + *verb = 0; + *attribute = 0; + + if(in==NULL || out==NULL) + { + result = CDEV_INVALIDARG; + } + else if((in->get("device", device, 255)!=CDEV_SUCCESS && + in->get("class", className, 255)!=CDEV_SUCCESS) || + (*device==0 && *className==0)) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Field device or class must be specified for validate query"); + result = CDEV_INVALIDARG; + } + else if ((in->get("message", message, 255)!=CDEV_SUCCESS && + (in->get("verb", verb, 255)!=CDEV_SUCCESS || + in->get("attribute", attribute, 255)!=CDEV_SUCCESS)) || + (*message==0 && (*verb==0 || *attribute==0))) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "A valid message or verb/attribute must be specified for validate query"); + result = CDEV_INVALIDARG; + } + else { + cdevDeviceDefinition * deviceDef = NULL; + cdevClassDefinition * def = NULL; + + if(*className==0) + { + deviceDef = (cdevDeviceDefinition *)table.getDeviceHash().find(device); + if(deviceDef==NULL) out->insert("value", 0); + else def = &(deviceDef->getClass()); + } + else if((def = (cdevClassDefinition *)table.getClassHash().find(className))==NULL) + { + out->insert("value", 0); + } + + if(def!=NULL) + { + if(*message==0) sprintf(message, "%s %s", verb, attribute); + if(def->getRedirector().find(message)!=NULL) + { + out->insert("value", 1); + } + else out->insert("value", 0); + } + } + return result; + } + +// ***************************************************************************** +// * cdevDirectoryTool::update : +// * This method allows the caller to add new data to the cdevDirectoryTable. +// ***************************************************************************** +int cdevDirectoryTool::update ( cdevDirectoryTable &table, cdevData *in, cdevData *) + { + int result = CDEV_SUCCESS; + size_t nElems = 0; + + if(in==NULL || + in->getType("file")!=CDEV_STRING || + in->getElems("file", &nElems)!=CDEV_SUCCESS || + nElems!=1) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "A valid file or data block must be specified"); + result = CDEV_INVALIDARG; + } + else { + char *ptr; + in->find("file", (void *&)ptr); + + // ************************************************************* + // * If the specified data item is a file, read the file using + // * the load method. + // ************************************************************* +#ifdef _WIN32 + if(!_access(ptr, 00)) table.load(ptr); +#else + if(!access(ptr, 00)) table.load(ptr); +#endif + + // ************************************************************* + // * Otherwise, reformat the data stream to ensure that a + // * carriage return exists at the beginning of the block and + // * follows each open and close brace... Then use the + // * asciiBufferLoad method to read the data. + // ************************************************************* + else { + char * pPtr = ptr; + char * buf = NULL; + char * bPtr = NULL; + int cnt = 1; + + while(*pPtr!=0) + { + if(*pPtr=='}' || *pPtr=='{') cnt++; + pPtr++; + } + + buf = new char[strlen(ptr)+cnt+1]; + bPtr = buf; + pPtr = ptr; + *(bPtr++) = '\n'; + while(*pPtr!=0) + { + *(bPtr++) = *pPtr; + if(*pPtr=='{' || *pPtr=='}') *(bPtr++) = '\n'; + pPtr++; + } + *bPtr = 0; + + table.compressComments("<< User Input >>", buf); + table.compressSpaces ("<< User Input >>", buf); + result = table.asciiBufferLoad(buf); + + delete buf; + } + } + return result; + } + + +// ***************************************************************************** +// * cdevDirectoryTool::writeAscii : +// * Outputs the contents of the cdevDirectoryTable specified by table to +// * the ASCII file specified in the file tag. +// ***************************************************************************** +int cdevDirectoryTool::writeAscii ( cdevDirectoryTable &table, cdevData *in, cdevData * ) + { + int result = CDEV_SUCCESS; + char filename[255]; + FILE * fp; + + *filename = 0; + + if(in==NULL || + in->get("file", filename, 255)!=CDEV_SUCCESS || + *filename==0) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "A valid filename must be specified"); + result = CDEV_INVALIDARG; + } + else if ((fp = fopen(filename, "w"))==NULL) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "Could not open file %s to write", filename); + result = CDEV_INVALIDARG; + } + else { + table.asciiDump(fp); + fclose(fp); + } + + return result; + } + +// ***************************************************************************** +// * cdevDirectoryTool::writeBinary : +// * Outputs the contents of the cdevDirectoryTable specified by table to +// * the BINARY file specified in the file tag. +// ***************************************************************************** +int cdevDirectoryTool::writeBinary ( cdevDirectoryTable &table, cdevData *in, cdevData * ) + { + int result = CDEV_SUCCESS; + char filename[255]; + + *filename = 0; + + if(in==NULL || + in->get("file", filename, 255)!=CDEV_SUCCESS || + *filename==0) + { + cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL, + "A valid filename must be specified"); + result = CDEV_INVALIDARG; + } + else table.binaryDump(filename); + + return result; + } diff --git a/src/directory/cdevDirectoryTool.h b/src/directory/cdevDirectoryTool.h new file mode 100755 index 0000000..b51c78b --- /dev/null +++ b/src/directory/cdevDirectoryTool.h @@ -0,0 +1,28 @@ +#include +#include + +class CDEV_CLASS_SPEC cdevDirectoryTool : public cdevDirectoryTable +{ +public: + cdevDirectoryTool ( void ); + ~cdevDirectoryTool ( void ); + + static int query ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int queryClass ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int queryClasses ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int queryCollection ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int queryVerbs ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int queryAttributes ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int queryMessages ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int service ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int serviceData ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int validate ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int update ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int writeAscii ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + static int writeBinary ( cdevDirectoryTable &table, cdevData *in, cdevData *out ); + +protected: + static int queryElements ( cdevDirectoryTable &table, cdevDirectoryTable::ElementType type, + cdevData *in, cdevData *out); + +}; diff --git a/src/directory/cdevElementDefinition.h b/src/directory/cdevElementDefinition.h new file mode 100755 index 0000000..65d6560 --- /dev/null +++ b/src/directory/cdevElementDefinition.h @@ -0,0 +1,260 @@ +#ifndef _CDEV_ELEMENT_DEFINITION_H_ +#define _CDEV_ELEMENT_DEFINITION_H_ + +#ifndef _CDEV_DIRECTORY_TABLE_H_ + #error "You must include cdevDirectoryTable.h to load cdevElementDefinition.h" +#endif + +#include +#include + +// ***************************************************************************** +// * class cdevElementDefinition : +// * This class is used to store the information that describes the contents +// * of a single element of a CDEV DDL class definition (verb, attribute, +// * or message. +// * +// * This class maintains a variety of internal data items for the following +// * purposes... +// * +// * name - This is the name of the verb, attribute, or message that +// * is represented by this element definition. +// * service - This is the service that this element direct the request +// * to. +// * serviceData - These are the values that will be palcded in the tags +// * that were specified in the service definition. +// * nItems - This is the number of tagged data items that were +// * specified in the serviceData. +// * next - This is the next element item in the list. Lists of +// * elements are maintained in the cdevClassDefinition objects +// ***************************************************************************** +class cdevElementDefinition +{ +private: + cdevElementDefinition * next; + char * name; + cdevServiceDefinition * service; + char ** serviceData; + int nItems; + +public: + inline cdevElementDefinition ( cdevElementDefinition *def ); + inline cdevElementDefinition ( char * Name = NULL, + cdevServiceDefinition * Service = NULL, + char ** ServiceData = NULL, + int NItems = 0); + inline virtual ~cdevElementDefinition ( void ); + inline void asciiDump ( FILE * fp = stdout); + inline void asciiDumpList ( FILE * fp = stdout, char * keyword = "UNKNOWN"); + + // ********************************************************************* + // * Member access methods. + // ********************************************************************* + inline char * getName ( void ); + inline cdevServiceDefinition * getService ( void ); + inline char ** getServiceData ( void ); + inline int getDataCnt ( void ); + inline cdevElementDefinition * getNext ( void ); + inline void setNext ( cdevElementDefinition * Next ); +}; + + + +// ***************************************************************************** +// * cdevElementDefinition::cdevElementDefinition : +// * This is the constructor for the cdevElementDefintion class. This +// * constructor copies the contents from a pre-existing +// * cdevElementDefinition object, and assumes that the data should be +// * deleted by the originating class. +// ***************************************************************************** +inline cdevElementDefinition::cdevElementDefinition ( cdevElementDefinition *def ) + : next (NULL), + name (def->name), + service (def->service), + serviceData (def->serviceData), + nItems (def->nItems) + { + } + +// ***************************************************************************** +// * cdevElementDefinition::cdevElementDefinition : +// * This is the constructor for the cdevElementDefinition class and it +// * uses literal values that are provoded by the caller. It assumes that it +// * it responsible for deleteing these data items when the instance of the +// * class is deleted. +// ***************************************************************************** +inline cdevElementDefinition::cdevElementDefinition + ( char * Name, + cdevServiceDefinition * Service, + char ** ServiceData, + int NItems) + : next (NULL), + name (Name), + service (Service), + serviceData (ServiceData), + nItems (NItems) + { + } + +// ***************************************************************************** +// * cdevElementDefinition::~cdevElementDefinition : +// * This is the destructor for the cdevElementDefinition class. +// ***************************************************************************** +inline cdevElementDefinition::~cdevElementDefinition ( void ) + { + if(name) delete name; + while((--nItems)>=0) delete serviceData[nItems]; + if(serviceData) delete serviceData; + } + +// ***************************************************************************** +// * cdevElementDefinition::asciiDump : +// * This method will dump the contents of the cdevElementDefinition class +// * class to the user specified file pointer. +// ***************************************************************************** +inline void cdevElementDefinition::asciiDump ( FILE * fp ) + { + if(name) + { + fprintf(fp, "\t\t%s", name); + + if(service) + { + fprintf(fp, " %s", service->getName()); + + for(int i=0; inext) + { + int n = def->name==NULL?0:strlen(def->name); + int s = def->service==NULL?0:strlen(def->service->getName()); + if(n>nameLen) nameLen = n; + if(s>serviceLen) serviceLen = s; + } + if(serviceLen) + { + fprintf(fp, "\t%s\n\t\t{\n", keyword); + for(def = this; def!=NULL; def = def->next) + { + if(nameLen>0 && def->service) + fprintf(fp, "\t\t%-*s", nameLen, def->name); + else fprintf(fp, "\t\t%s", def->name); + + if(def->service) + { + if(serviceLen>0 && def->nItems) + fprintf(fp, " %-*s", serviceLen, def->service->getName()); + else fprintf(fp, " %s", def->service->getName()); + + for(int i=0; inItems; i++) + { + if(i==0) fprintf(fp, " {"); + fprintf(fp, "%s", def->serviceData[i]); + if(inItems-1) fprintf(fp, ", "); + else fprintf(fp, "}"); + } + } + fprintf(fp, ";\n"); + } + fprintf(fp, "\t\t}\n"); + } + else { + int cnt = 0; + char prefix[25]; + sprintf(prefix, "%s {", keyword); + fprintf(fp, "\t%s", prefix); + for(def = this; def!=NULL; def = def->next, cnt++) + { + if(def->next) + { + fprintf(fp, " %s,", def->name); + if(cnt==3) + { + fprintf(fp, "\n\t%*c", strlen("prefix")+1, 32); + cnt=-1; + } + } + else fprintf(fp, " %s ", def->name); + } + fprintf(fp, "}\n"); + } + } + + +// ***************************************************************************** +// * cdevElementDefinition::getName : +// * This method allows the caller to retrieve the name of the element. +// ***************************************************************************** +inline char * cdevElementDefinition::getName ( void ) + { + return name; + } + +// ***************************************************************************** +// * cdevElementDefinition::getService : +// * This method allows the caller to retrieve the service definition +// ***************************************************************************** +inline cdevServiceDefinition * cdevElementDefinition::getService ( void ) + { + return service; + } + +// ***************************************************************************** +// * cdevElementDefinition::getServiceData : +// * This method allows the caller to retrieve the service data. +// ***************************************************************************** +inline char ** cdevElementDefinition::getServiceData ( void ) + { + return serviceData; + } + +// ***************************************************************************** +// * cdevElementDefinition::getDataCnt : +// * This method allows the caller to retrieve the number of strings that +// * are stored in the serviceData. +// ***************************************************************************** +inline int cdevElementDefinition::getDataCnt ( void ) + { + return nItems; + } + +// ***************************************************************************** +// * cdevElementDefinition::getNext : +// * This method allows the caller to retrieve the next element in the list. +// ***************************************************************************** +inline cdevElementDefinition * cdevElementDefinition::getNext ( void ) + { + return next; + } + +// ***************************************************************************** +// * cdevElementDefinition::setNext : +// * This method allows the caller to set the next element in the list. +// ***************************************************************************** +inline void cdevElementDefinition::setNext ( cdevElementDefinition * Next ) + { + next = Next; + } + +#endif /* _CDEV_ELEMENT_DEFINITION_H_ */ diff --git a/src/directory/cdevRedirectorDefinition.h b/src/directory/cdevRedirectorDefinition.h new file mode 100755 index 0000000..15e103b --- /dev/null +++ b/src/directory/cdevRedirectorDefinition.h @@ -0,0 +1,127 @@ +#ifndef _CDEV_REDIRECTOR_DEFINITION_H_ +#define _CDEV_REDIRECTOR_DEFINITION_H_ + +#ifndef _CDEV_DIRECTORY_TABLE_H_ + #error "You must include cdevDirectoryTable.h to load cdevRedirectorDefinition.h" +#endif + +#include + +// ***************************************************************************** +// * class cdevRedirectorDefinition : +// * This class is used to store the information that identifies the +// * service and service data that is associated with a specific message. +// * This class is only instanciated in a cdevClassDefinition that has +// * been instanciated. +// * +// * To reduce the number of copies of extraneous data, this class will +// * use the service data that is stored in the cdevElementDefinition. +// ***************************************************************************** +class cdevRedirectorDefinition +{ +private: + char * name; + cdevServiceDefinition * service; + char ** serviceData; + int nItems; + +public: + inline cdevRedirectorDefinition ( char *Name, cdevElementDefinition &def); + inline ~cdevRedirectorDefinition ( void ); + inline void asciiDump ( FILE * fp = stdout ); + + // ********************************************************************* + // * Member access methods + // ********************************************************************* + inline char * getName ( void ); + inline cdevServiceDefinition * getService ( void ); + inline char ** getServiceData ( void ); + inline int getDataCnt ( void ); +}; + + +// ***************************************************************************** +// * cdevRedirectorDefinition::cdevRedirectorDefinition : +// * This is the constructor for the cdevRedirectorDefinition class... The +// * message parameter becomes the property of the class and should not +// * be accessed again by the caller... +// ***************************************************************************** +inline cdevRedirectorDefinition::cdevRedirectorDefinition + ( char *Name, cdevElementDefinition &def) + : name (Name), + service (def.getService()), + serviceData(def.getServiceData()), + nItems (def.getDataCnt()) + { + } + + +// ***************************************************************************** +// * cdevRedirectorDefinition::~cdevRedirectorDefinition : +// * This is the destructor for the cdevRedirectorDefinition object. +// ***************************************************************************** +inline cdevRedirectorDefinition::~cdevRedirectorDefinition ( void ) + { + delete name; + } + + +// ***************************************************************************** +// * cdevRedirectorDefinition::asciiDump : +// * This is a diagnostic method that allows the caller to dump the contents +// * of the class redirection table that identifies which service will +// * be used for each message. +// ***************************************************************************** +inline void cdevRedirectorDefinition::asciiDump ( FILE * fp ) + { + fprintf(fp, "\t\t\"%s\" %s", name, service->getName()); + if(serviceData!=NULL && nItems>0) + { + fprintf(fp, " {"); + for(int i=0; i + +// ***************************************************************************** +// * class cdevServiceDefinition : +// * This class stores a single CDEV service definition as defined in the +// * DDL file. This data is managed by the cdevServiceList. +// * +// * This class maintains a variety of internal data items for the following +// * purposes... +// * +// * name - This is the name of the service as specified in the +// * CDEV DDL file. +// * tags - These are the tags that will be used as service data when +// * loading elements that use this service. +// * nTags - This is the number of tags in the tags array. +// * next - This is the next service that was loaded from the CDEV DDL +// * file. This list is maintained in the cdevDirectoryTable +// * object. +// ***************************************************************************** +class cdevServiceDefinition +{ +private: + cdevServiceDefinition * next; + char * name; + char ** tags; + int nTags; +public: + inline cdevServiceDefinition ( char *Name=NULL, char ** Tags=NULL, int NTags=0); + inline ~cdevServiceDefinition ( void ); + inline void asciiDump ( FILE * fp = stdout ); + + // ********************************************************************* + // * Member access methods. + // ********************************************************************* + inline char * getName ( void ); + inline char ** getTags ( void ); + inline int getTagCnt ( void ); + inline cdevServiceDefinition * getNext ( void ); + inline void setNext ( cdevServiceDefinition * Next ); +}; + + +// ***************************************************************************** +// * cdevServiceDefinition::cdevServiceDefinition : +// * This is the constructor for the cdevService defintion. It uses the +// * following parameters: +// * +// * Name - the name of the service being added. +// * Tags - the service data tags that will be used by each device. +// * NTags - the number of tags in the list. +// ***************************************************************************** +inline cdevServiceDefinition::cdevServiceDefinition ( char *Name, char ** Tags, int NTags) + : next(NULL), name(Name), tags(Tags), nTags(NTags) + { + } + +// ***************************************************************************** +// * cdevServiceDefinition::cdevServiceDefinition : +// * This is the destructor for the cdevServiceDefinition class. It will +// * delete all data items that were provided to the constructor. +// ***************************************************************************** +inline cdevServiceDefinition::~cdevServiceDefinition ( void ) + { + if(name) delete name; + while(--nTags>=0) delete tags[nTags]; + if(tags) delete tags; + } + +// ***************************************************************************** +// * cdevServiceDefinition::asciiDump : +// * This method is used to write the contents of the service definition +// * object to an ouput file. +// ***************************************************************************** +inline void cdevServiceDefinition::asciiDump ( FILE * fp ) + { + fprintf(fp, "\nservice %s\n\t{\n\t", name); + if(tags && nTags) + { + int idx; + fprintf(fp, "tags {"); + for(idx=0; idx +#include "cdevSvcFinder.h" +#include + + +cdevService* +cdevSvcFinder::findService (char* serviceName) +{ + cdevService* svc = 0; + if (::strcmp (serviceName, "caService") == 0) { + if (!system_.serviceCreated (serviceName)) + svc = new caService (serviceName, system_); + else + svc = system_.service (serviceName); + } + return svc; +} +#endif diff --git a/src/directory/cdevSvcFinder.cc b/src/directory/cdevSvcFinder.cc new file mode 100755 index 0000000..5278322 --- /dev/null +++ b/src/directory/cdevSvcFinder.cc @@ -0,0 +1,246 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevSvcFind class Implementation +// +// Author: Jie Chen +// +// Revision History: +// cdevSvcFinder.cc,v +// Revision 1.14 1997/08/21 13:31:17 chen +// indent a little +// +// Revision 1.13 1997/08/18 14:16:30 akers +// Ongoing development of CDEV accounting +// +// Revision 1.12 1997/08/15 18:08:31 akers +// Addition of CDEV Accounting +// +// Revision 1.11 1997/08/07 13:36:32 akers +// Converted CDEV_MAJOR_VERSION and CDEV_MINOR_VERSION to strings to support adding minor revision numbers +// +// Revision 1.10 1997/02/18 15:48:04 chen +// port to linux 2.0.x +// +// Revision 1.9 1996/03/28 19:13:34 akers +// Minor changes in support of new version +// +// Revision 1.8 1996/03/28 18:31:25 akers +// Corrected error in cdevSvcFinder.cc +// +// Revision 1.7 1996/03/27 16:02:02 akers +// Modified service loader to search multiple directories +// +// Revision 1.6 1995/10/18 17:45:36 chen +// to reflect change in shObjLoader +// +// Revision 1.5 1995/10/17 13:26:07 chen +// change to handle shobj interface change +// +// Revision 1.4 1995/10/06 19:49:39 chen +// remove explict relation with caService +// +// Revision 1.3 1995/09/20 16:14:05 chen +// Fix a bug when there is no CDEVSHOBJ +// +// Revision 1.2 1995/06/30 16:01:34 chen +// use generic list +// +// Revision 1.1.1.1 1995/06/16 17:14:07 epics +// initial import of cdev +// +// +#include +#include +#include "cdevSvcFinder.h" +#include + +#ifdef _CDEV_ACCOUNTING_ +#include "cdevAccount.cc" +#endif + +cdevSvcFinder::cdevSvcFinder (cdevSystem& system) +:ldList_(), system_(system) + { +#ifdef _CDEV_ACCOUNTING_ + cdevGlobalAccountEntry = new cdevAccountEntry; + atexit(removeGlobalAccountRecord); +#endif + +#ifdef _TRACE_OBJECTS + printf("Create cdevSvcFinder class \n"); +#endif + } + +cdevSvcFinder::~cdevSvcFinder (void) + { +#ifdef _CDEV_ACCOUNTING_ + if(cdevGlobalAccountEntry!=NULL) + { + delete cdevGlobalAccountEntry; + cdevGlobalAccountEntry = NULL; + } +#endif + + cdevSlistIterator sit (ldList_); + shObjLoader *tloader = 0; + + for (sit.init(); !sit; ++sit) { + tloader = (shObjLoader *)sit (); + delete tloader; + } +#ifdef _TRACE_OBJECTS + printf("Delete cdevSvcFinder class \n"); +#endif + } + +int +cdevSvcFinder::getService (char *serviceName, + cdevService* &service) + { +#ifdef SHOBJ + service = loadService (serviceName); + if (service) + return 0; + else + return -1; +#else + service = findService (serviceName); + if (service) + return 0; + else + return -1; +#endif + } + +#ifdef SHOBJ +cdevService * +cdevSvcFinder::loadService (char *serviceName) + { + int status = -1; + cdevService* (*create)(char *, cdevSystem *); + cdevService *svc = NULL; + + // *************************************************************************** + // * This method detect if the specified service name is already loaded, if + // * not, it will search a list of three possible locations in an attempt to + // * load the service. + // *************************************************************************** + if (!system_.serviceCreated (serviceName)) + { + char location[3][256]; + char *envVar = ::getenv ("CDEVSHOBJ"); + + *location[0] = '\0'; + *location[1] = '\0'; + *location[2] = '\0'; + + if(envVar!=NULL && *envVar) + { +#ifdef _WIN32 + // ************************************************************* + // * The first search location is in the versioned directory + // * under the cdev shared object directory... this would look + // * like... "/usr/cdev/shobj/1.3/filename.so" + // ************************************************************* + sprintf(location[0], + "%s\\%s\\%s.dll", + envVar, + CDEV_VERSION_STRING, + serviceName); + // ************************************************************* + // * The second search location is within the cdev shared object + // * directory... this would look like... + // * "/usr/cdev/shobj/filename.so" + // ************************************************************* + sprintf(location[1], + "%s\\%s.dll", + envVar, + serviceName); + } + // ********************************************************************* + // * The third search location is within the /usr/local/lib directory... + // * This would look like... "/usr/local/lib/filename.so" + // ********************************************************************* + GetSystemDirectory(location[2], 256); + sprintf(location[2]+strlen(location[2]), "\\%s.dll", serviceName); +#else + // ************************************************************* + // * The first search location is in the versioned directory + // * under the cdev shared object directory... this would look + // * like... "/usr/cdev/shobj/1.3/filename.so" + // ************************************************************* + sprintf(location[0], + "%s/%s/%s.so", + envVar, + CDEV_VERSION_STRING, + serviceName); + // ************************************************************* + // * The second search location is within the cdev shared object + // * directory... this would look like... + // * "/usr/cdev/shobj/filename.so" + // ************************************************************* + sprintf(location[1], + "%s/%s.so", + envVar, + serviceName); + } + // ********************************************************************* + // * The third search location is within the /usr/local/lib directory... + // * This would look like... "/usr/local/lib/filename.so" + // ********************************************************************* + sprintf(location[2], "/usr/local/lib/%s.so", serviceName); +#endif + + // ********************************************************************* + // * Walk through the list of possible locations until the shared + // * library is successfully loaded, or until all options have been + // * exhausted. + // ********************************************************************* + status = -1; + for(int idx=0; idx<3 && status!=0; idx++) + { + if(*location[idx] != 0) + { + shObjLoader *loader = new shObjLoader (location[idx]); + if((status = loader->load ())==0) + { + char symbolName[64]; + sprintf (symbolName, "new%s", serviceName); + symbolName[3] = toupper (symbolName[3]); + status = loader->findProcedureSym (symbolName, (void **)&create); + } + + // ************************************************************* + // * If the service was successfully loaded, then add it to the + // * system. Otherwise, delete the loader object. + // ************************************************************* + if(status==0) + { + svc = (*create)(serviceName, &system_); + ldList_.add ((void *)loader); + + // *********************************************************** + // * If the service was successfully loaded, use the + // * cdevAccountEntry object to record the transaction. + // *********************************************************** +#ifdef _CDEV_ACCOUNTING_ + cdevGlobalAccountEntry->addService(location[idx]); +#endif + } + else delete loader; + } + } + } + else svc = system_.service (serviceName); + return svc; +} + +#endif diff --git a/src/directory/cdevSvcFinder.h b/src/directory/cdevSvcFinder.h new file mode 100755 index 0000000..871983e --- /dev/null +++ b/src/directory/cdevSvcFinder.h @@ -0,0 +1,67 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevSvcFinder class (Bind a service from a service name) +// +// Author: Jie Chen +// +// Revision History: +// cdevSvcFinder.h,v +// Revision 1.5 1997/08/18 14:16:31 akers +// Ongoing development of CDEV accounting +// +// Revision 1.4 1997/08/15 18:08:33 akers +// Addition of CDEV Accounting +// +// Revision 1.3 1995/09/20 16:22:21 chen +// Change findService to virtual +// +// Revision 1.2 1995/06/30 16:01:35 chen +// use generic list +// +// Revision 1.1.1.1 1995/06/16 17:14:07 epics +// initial import of cdev +// +// +#ifndef _CDEV_SVC_FINDER_H +#define _CDEV_SVC_FINDER_H + +#include +#include +#include + +class CDEV_CLASS_SPEC cdevSvcFinder +{ + public: + //constructor and destrcutor + cdevSvcFinder(cdevSystem & system = cdevSystem::defaultSystem()); + ~cdevSvcFinder (void); + + int getService(char *serviceName, cdevService* &service); + // PURPOSE: get or load a service into system + // REQUIRE: serviceName != 0 and callers provide pointer service + // PROMISE: return 0: service loaded. return -1: failure + + private: + // deny assignment and copy + cdevSvcFinder (const cdevSvcFinder& src); + cdevSvcFinder& operator = (const cdevSvcFinder& src); + // internal functions + +#ifdef SHOBJ + cdevService *loadService (char *serviceName); +#else + virtual cdevService *findService (char *serviceName); +#endif + // data area + cdevSlist ldList_; + cdevSystem& system_; +}; +#endif diff --git a/src/group/.shobj/Linux/cdevBlockList.o b/src/group/.shobj/Linux/cdevBlockList.o new file mode 100644 index 0000000..23350fc Binary files /dev/null and b/src/group/.shobj/Linux/cdevBlockList.o differ diff --git a/src/group/.shobj/Linux/cdevExecGroup.o b/src/group/.shobj/Linux/cdevExecGroup.o new file mode 100644 index 0000000..5e181cb Binary files /dev/null and b/src/group/.shobj/Linux/cdevExecGroup.o differ diff --git a/src/group/.shobj/Linux/cdevExecObj.o b/src/group/.shobj/Linux/cdevExecObj.o new file mode 100644 index 0000000..436898b Binary files /dev/null and b/src/group/.shobj/Linux/cdevExecObj.o differ diff --git a/src/group/.shobj/Linux/cdevGroup.o b/src/group/.shobj/Linux/cdevGroup.o new file mode 100644 index 0000000..2f4ae0d Binary files /dev/null and b/src/group/.shobj/Linux/cdevGroup.o differ diff --git a/src/group/.shobj/Linux/cdevTranObj.o b/src/group/.shobj/Linux/cdevTranObj.o new file mode 100644 index 0000000..f94bc0a Binary files /dev/null and b/src/group/.shobj/Linux/cdevTranObj.o differ diff --git a/src/group/Makefile b/src/group/Makefile new file mode 100755 index 0000000..19ddca4 --- /dev/null +++ b/src/group/Makefile @@ -0,0 +1,69 @@ +# Makefile for group directory of CDEV +# +# cdev group directory +# +# Makefile,v +# Revision 1.12 1998/08/17 14:04:59 akers +# Added 'Minor Version Number' to TARGETDIR in Makefiles +# +# Revision 1.11 1998/01/30 13:49:17 akers +# Ongoing development +# +# Revision 1.10 1998/01/14 14:26:38 chen +# add cdevMonitorObj +# +# Revision 1.9 1997/03/03 17:35:58 chen +# add buffering to channel access connection +# +# Revision 1.8 1996/09/20 12:24:53 akers +# Changes added for Release 1.4 +# +# Revision 1.6 1996/06/26 15:54:15 akers +# Modifications to support multiple OS Versions +# +# Revision 1.5 1996/05/14 20:38:12 akers +# Makefile modifications +# +# Revision 1.4 1995/12/08 15:32:45 chen +# change filenames +# +# Revision 1.3 1995/11/14 17:40:49 chen +# new makefile +# +# +include ../Makefile.config + + +ifeq ($(INCDIR), ) + INCDIR = ../.. +endif + +ifeq ($(SHOBJ),YES) + OBJTYPE=.shobj/$(TARGETDIR) +else + OBJTYPE=.obj/$(TARGETDIR) +endif + +OBJS = $(OBJTYPE)/cdevBlockList.o \ + $(OBJTYPE)/cdevGroup.o \ + $(OBJTYPE)/cdevExecGroup.o \ + $(OBJTYPE)/cdevTranObj.o \ + $(OBJTYPE)/cdevExecObj.o + +targets: $(OBJTYPE) $(OBJDIR)/$(OBJTYPE) copyobjs copyincs + +$(OBJTYPE) : + @mkdir -p $(OBJTYPE) + +$(OBJDIR)/$(OBJTYPE) : + @mkdir $(OBJDIR)/$(OBJTYPE) + +copyobjs: $(OBJS) + @cp -f $(OBJS) $(OBJDIR)/$(OBJTYPE) + +copyincs: + @cp -f *.h $(INCDIR) + +clean: clean_hail + @rm -rf *.o .obj .shobj core *~ + diff --git a/src/group/NMakefile.mak b/src/group/NMakefile.mak new file mode 100755 index 0000000..e32e35a --- /dev/null +++ b/src/group/NMakefile.mak @@ -0,0 +1,17 @@ +include ..\NMakefile.config + +OBJS = $(OBJDIR)\cdevBlockList.obj \ + $(OBJDIR)\cdevGroup.obj \ + $(OBJDIR)\cdevExecGroup.obj \ + $(OBJDIR)\cdevTranObj.obj \ + $(OBJDIR)\cdevExecObj.obj + +targets : copyobjs copyincs + +copyobjs : $(OBJS) + -@if not exist ..\lib\$(OBJDIR) mkdir ..\lib\$(OBJDIR) + -@for %x in ($(OBJDIR)\*.obj) DO @copy %x ..\lib\$(OBJDIR) > nul + +copyincs : + -@for %x in (*.h *.i) DO @copy %x $(CDEV)\include > nul + diff --git a/src/group/cdevBlockList.cc b/src/group/cdevBlockList.cc new file mode 100755 index 0000000..10da353 --- /dev/null +++ b/src/group/cdevBlockList.cc @@ -0,0 +1,551 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Implementation of block list which holds pointer of transaction object +// +// Author: Jie Chen +// +// Revision History: +// cdevBlockList.cc,v +// Revision 1.1 1995/12/08 15:33:15 chen +// linked block list +// +// Revision 1.2 1995/10/16 18:38:21 chen +// Change to work under SunOs and g++ +// +// Revision 1.1.1.1 1995/06/16 17:14:07 epics +// initial import of cdev +// +// +#include "cdevBlockList.h" + +//============================================================================ +// class cdevBlockList implementation +//============================================================================ +cdevBlockList::cdevBlockList (unsigned int blockSize) +:firstBlock_(0, 0, blockSize),blockSize_(blockSize), size_ (blockSize), + defValue_ (0) +{ + // empty +} + +cdevBlockList::cdevBlockList (const blockListItem& defVal, + unsigned int blockSize) +:firstBlock_(0, 0, defVal, blockSize), blockSize_(blockSize), size_ (blockSize) +{ + defValue_ = new blockListItem; + *defValue_ = defVal; +} + +cdevBlockList::cdevBlockList (const cdevBlockList &rsc) +:firstBlock_ (rsc.firstBlock_), blockSize_ (rsc.blockSize_), + size_ (rsc.size_) +{ + if (rsc.defValue_){ + defValue_ = new blockListItem; + *defValue_ = *rsc.defValue_; + } + else + defValue_ = 0; +} + +cdevBlockList& +cdevBlockList::operator = (const cdevBlockList &rsc) +{ + if (this != &rsc){ + deleteAll(); + firstBlock_ = rsc.firstBlock_; + blockSize_ = rsc.blockSize_; + size_ = rsc.size_; + if (rsc.defValue_){ + defValue_ = new blockListItem; + *defValue_ = *rsc.defValue_; + } + else + defValue_ = 0; + } + return *this; +} + +cdevBlockList::~cdevBlockList (void) +{ + deleteAll (); +} + +cdevBlockList* +cdevBlockList::duplicate (void) const +{ + cdevBlockList *newList = new cdevBlockList (*this); + return newList; +} + +blockListItem & +cdevBlockList::operator [] (unsigned int index) const +{ + // get value indexed by number 'index' + assert (index < length()); + int steps = index/blockSize_; + int i = 0; + const cdevBlockLink *p = &firstBlock_; + + while (i < steps){ + p = p->ptrToNextLink_; + i++; + } + + int slots = index - steps*blockSize_; + return p->value_[slots]; +} + + +int +cdevBlockList::includes (blockListItem value) const +{ + for (const cdevBlockLink *p = &firstBlock_; p != 0; p = p->ptrToNextLink_){ + for (int i = 0; i < blockSize_; i++){ + if (p->value_[i] == value){ + return 1; + } + } + } + return 0; +} + +int +cdevBlockList::length (void) const +{ + return size_; +} + +unsigned int +cdevBlockList::entryNumber (blockListItem *ptr) +{ + unsigned int num = 0; + + for (const cdevBlockLink *q = &firstBlock_; q != 0; q = q->ptrToNextLink_){ + for (int i = 0; i < blockSize_; i++){ + if (ptr == &(q->value_[i])) + return num; + num++; + } + } + return 0; +} + +blockListItem * +cdevBlockList::entryPointer (unsigned int steps) +{ + unsigned int numBlocks = steps/blockSize_; + unsigned int slotNum = steps - blockSize_*numBlocks; + cdevBlockLink *p = &firstBlock_; + + int i = 0; + while(i < numBlocks+1){ + p = p->ptrToNextLink_; + i++; + } + return &(p->value_[slotNum]); +} + +cdevBlockLink * +cdevBlockList::blockPointer (blockListItem *ptr) +{ + blockListItem *p; + + for (cdevBlockLink *q = &firstBlock_; q != 0; q = q->ptrToNextLink_){ + p = q->value_; + for (int i = 0; i < blockSize_; i++){ + if (p == ptr) + return q; + p++; + } + } + return 0; +} + +void +cdevBlockList::deleteAll (void) +{ + // clear all out from the list except the first link + if (firstBlock_.ptrToNextLink_){ + cdevBlockLink *next; + for (cdevBlockLink * p = firstBlock_.ptrToNextLink_; p != 0; p = next){ + // delete the element pointed by p + next = p->ptrToNextLink_; + p->ptrToNextLink_ = 0; + p->ptrToPrevLink_ = 0; + delete p; + } + } + blockListItem junk = NULL; + for (int i = 0; i < blockSize_; i++) + firstBlock_.value_[i] = junk; + if (defValue_){ + delete defValue_; + defValue_ = 0; + } + size_ = blockSize_; +} + +void +cdevBlockList::clearAll (void) +{ + blockListItem junk = NULL; + for (cdevBlockLink * p = &firstBlock_; p != 0; p = p->ptrToNextLink_){ + for (int i = 0; i < blockSize_; i++) + p->value_[i] = junk; + } + if (defValue_){ + delete defValue_; + defValue_ = 0; + } +} + +//============================================================================ +// class blockLink implementation +//============================================================================ +cdevBlockLink::cdevBlockLink (cdevBlockLink *nxt, + cdevBlockLink *pre, + unsigned int blkSize) +:blockSize_ (blkSize), ptrToNextLink_ (nxt), ptrToPrevLink_ (pre) +{ + value_ = new blockListItem[blkSize]; + assert (value_); + if (nxt) + nxt->ptrToPrevLink_ = this; + if (pre) + pre->ptrToNextLink_ = this; +} + +cdevBlockLink::cdevBlockLink (cdevBlockLink *nxt, + cdevBlockLink *pre, + const blockListItem& defVal, + unsigned int blkSize) +:blockSize_ (blkSize), ptrToNextLink_ (nxt), ptrToPrevLink_ (pre) +{ + value_ = new blockListItem[blkSize]; + assert (value_); + for (int i = 0; i < blkSize; i++) + value_[i] = defVal; + if (nxt) + nxt->ptrToPrevLink_ = this; + if (pre) + pre->ptrToNextLink_ = this; +} + +cdevBlockLink::cdevBlockLink (cdevBlockLink *nxt, + cdevBlockLink *pre, + blockListItem *data, unsigned int blkSize) +:blockSize_ (blkSize), ptrToNextLink_ (nxt), ptrToPrevLink_ (pre) +{ + value_ = new blockListItem[blkSize]; + assert (value_); + for (int i = 0; i < blkSize; i++) + value_[i] = data[i]; + if (nxt) + nxt->ptrToPrevLink_ = this; + if (pre) + pre->ptrToNextLink_ = this; +} + +cdevBlockLink::cdevBlockLink (const cdevBlockLink &link) +:blockSize_ (link.blockSize_) +{ + ptrToNextLink_ = ptrToPrevLink_ = 0; + value_ = new blockListItem[link.blockSize_]; + for (int i = 0; i < blockSize_; i++) + value_[i] = link.value_[i]; + if (link.ptrToNextLink_){ + ptrToNextLink_ = (link.ptrToNextLink_)->duplicate(0); + ptrToNextLink_->ptrToPrevLink_ = this; + } + if (link.ptrToPrevLink_){ + ptrToPrevLink_ = (link.ptrToPrevLink_)->duplicate (1); + ptrToPrevLink_->ptrToNextLink_ = this; + } +} + +cdevBlockLink& +cdevBlockLink::operator = (const cdevBlockLink &link) +{ + if (this != &link){ + ptrToNextLink_ = ptrToPrevLink_ = 0; + freeAllMemory (); + value_ = new blockListItem[link.blockSize_]; + blockSize_ = link.blockSize_; + for (int i = 0; i < link.blockSize_; i++) + value_[i] = link.value_[i]; + if (link.ptrToNextLink_){ + ptrToNextLink_ = (link.ptrToNextLink_)->duplicate(0); + ptrToNextLink_->ptrToPrevLink_ = this; + } + if (link.ptrToPrevLink_){ + ptrToPrevLink_ = (link.ptrToPrevLink_)->duplicate (1); + ptrToPrevLink_->ptrToNextLink_ = this; + } + } + return *this; +} + +void +cdevBlockLink::freeAllMemory (void) +{ + cdevBlockLink *next, *prev; + + if (ptrToNextLink_){ + for (cdevBlockLink * p = ptrToNextLink_; p != 0; p = next){ + next = p->ptrToNextLink_; + p->ptrToNextLink_ = 0; + p->ptrToPrevLink_ = 0; + delete p; + } + } + if (ptrToPrevLink_){ + for (cdevBlockLink *p = ptrToPrevLink_; p != 0; p = prev){ + prev = p->ptrToPrevLink_; + p->ptrToPrevLink_ = 0; + p->ptrToNextLink_ = 0; + delete p; + } + } + ptrToNextLink_ = 0; + ptrToPrevLink_ = 0; + delete []value_; + blockSize_ = 0; +} + +cdevBlockLink * +cdevBlockLink::duplicate (void) +{ + cdevBlockLink *newLink, *prev, *p, *q, *next; + + newLink = new cdevBlockLink (0, 0, value_, blockSize_); + prev = newLink; + // if there is a next field, copy remainder of the list + if (ptrToNextLink_ != 0){ + for (p = ptrToNextLink_; p != 0; p = p->ptrToNextLink_){ + q = new cdevBlockLink (0, prev, p->value_, blockSize_); + prev = q; + } + } + + // if there is previous filed + next = newLink; + if (ptrToPrevLink_ != 0){ + for (p = ptrToPrevLink_; p != 0; p = p->ptrToPrevLink_){ + q = new cdevBlockLink (next, 0, p->value_, blockSize_); + next = q; + } + } + assert (newLink != 0); + return newLink; +} + +cdevBlockLink * +cdevBlockLink::duplicate (int type) +{ + cdevBlockLink *newLink, *prev, *p, *q, *next; + + newLink = new cdevBlockLink (0, 0, value_, blockSize_); + if (type == 0){ // copy from here to right + prev = newLink; + // if there is a next field, copy remainder of the list + if (ptrToNextLink_ != 0){ + for (p = ptrToNextLink_; p != 0; p = p->ptrToNextLink_){ + q = new cdevBlockLink (0, prev, p->value_, blockSize_); + prev = q; + } + } + } + else{ // copy from here to left + // if there is previous filed + next = newLink; + if (ptrToPrevLink_ != 0){ + for (p = ptrToPrevLink_; p != 0; p = p->ptrToPrevLink_){ + q = new cdevBlockLink (next, 0, p->value_, blockSize_); + next = q; + } + } + } + assert (newLink != 0); + return newLink; +} + +cdevBlockLink::~cdevBlockLink (void) +{ + delete []value_; + blockSize_ = 0; + ptrToNextLink_ = 0; + ptrToPrevLink_ = 0; +} + +cdevBlockLink * +cdevBlockLink::addNewBlock (const blockListItem &defValue) +{ + // insert a new block after current block + ptrToNextLink_ = new cdevBlockLink (ptrToNextLink_, this, + defValue, blockSize_); + assert (ptrToNextLink_ != 0); + return ptrToNextLink_; +} + +cdevBlockLink * +cdevBlockLink::addNewBlock (void) +{ + // insert a new block after current block + ptrToNextLink_ = new cdevBlockLink (ptrToNextLink_, this, blockSize_); + assert (ptrToNextLink_ != 0); + return ptrToNextLink_; +} + +//============================================================================ +// class cdevBlockListIterator implementation +//============================================================================ +cdevBlockListIterator::cdevBlockListIterator (cdevBlockList & l) +:data (l), curPos_ (0) +{ + currEntry_ = &(data.firstBlock_.value_[0]); + blockStart_ = currEntry_; + blockEnd_ = &(data.firstBlock_.value_[data.blockSize_ - 1]); + cdevBlockLink *p = 0; + for (p = &(data.firstBlock_); p->ptrToNextLink_ != 0; + p = p->ptrToNextLink_) + ; + listEnd_ = &(p->value_[data.blockSize_ - 1]); +} + +int +cdevBlockListIterator::init (void) +{ + curPos_ = 0; + currEntry_ = &(data.firstBlock_.value_[0]); + blockStart_ = currEntry_; + blockEnd_ = &(data.firstBlock_.value_[data.blockSize_ - 1]); + cdevBlockLink *p = 0; + for (p = &data.firstBlock_; p->ptrToNextLink_ != 0; + p = p->ptrToNextLink_) + ; + listEnd_ = &(p->value_[data.blockSize_ - 1]); + return 1; +} + +int +cdevBlockListIterator::end (void) +{ + cdevBlockLink *p = 0; + for (p = &data.firstBlock_; p->ptrToNextLink_ != 0; + p = p->ptrToNextLink_) + ; + curPos_ = data.length() - 1; + blockStart_ = &(p->value_[0]); + blockEnd_ = &(p->value_[data.blockSize_ -1]); + currEntry_ = blockEnd_; + listEnd_ = blockEnd_; + return 1; +} + +blockListItem +cdevBlockListIterator::operator () (void) +{ + return *currEntry_; +} + +int +cdevBlockListIterator::operator ! (void) +{ + return curPos_ < data.length() && curPos_ >= 0; +} + +int +cdevBlockListIterator::operator ++ (void) +{ + if (currEntry_ != blockEnd_){ // still inside one block + currEntry_++; + curPos_++; + return 1; + } + else if (currEntry_ != listEnd_){ // reach one end of block + cdevBlockLink *currBlock = data.blockPointer (currEntry_); + cdevBlockLink *p = currBlock->ptrToNextLink_; + currEntry_ = &(p->value_[0]); + blockStart_ = currEntry_; + blockEnd_ = &(p->value_[data.blockSize_ - 1]); + curPos_++; + return 1; + } + else{ + curPos_++; + return 0; + } +} + +int +cdevBlockListIterator::operator -- (void) +{ + if (currEntry_ != blockStart_){ // still inside one block + currEntry_--; + curPos_--; + return 1; + } + else if (currEntry_ != &(data.firstBlock_.value_[0])){ // reach beginning + cdevBlockLink *currBlock = data.blockPointer (currEntry_); + cdevBlockLink *p = currBlock->ptrToPrevLink_; + blockStart_ = &(p->value_[0]); + blockEnd_ = &(p->value_[data.blockSize_ - 1]); + currEntry_ = blockEnd_; + curPos_--; + return 1; + } + else { // begnning of the list + curPos_--; + return 0; + } +} + +void +cdevBlockListIterator::operator = (blockListItem newVal) +{ + *currEntry_ = newVal; +} + +blockListItem * +cdevBlockListIterator::currentPosition (void) +{ + return currEntry_; +} + +int +cdevBlockListIterator::forcePut (blockListItem newVal) +{ + if (curPos_ < data.length()){ + *currEntry_ = newVal; + } + else{ + cdevBlockLink *p = 0; + for (p = &data.firstBlock_; p->ptrToNextLink_ != 0; + p = p->ptrToNextLink_) + ; + if (data.defValue_){ + p->addNewBlock(*(data.defValue_)); + data.size_ += data.blockSize_; + } + else{ + p->addNewBlock(); + data.size_ += data.blockSize_; + } + cdevBlockLink *curr = p->ptrToNextLink_; + currEntry_ = &(curr->value_[0]); + blockStart_ = currEntry_; + blockEnd_ = &(curr->value_[data.blockSize_ - 1]); + listEnd_ = blockEnd_; + *currEntry_ = newVal; + } + return 1; +} diff --git a/src/group/cdevBlockList.h b/src/group/cdevBlockList.h new file mode 100755 index 0000000..d2fc6aa --- /dev/null +++ b/src/group/cdevBlockList.h @@ -0,0 +1,169 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Linked list of blocks of void pointer +// +// Not safe C++ practice because of void*. +// Reason: It is very difficult to do instantiation inside +// a shared library. +// +// Author: Jie Chen +// +// Revision History: +// cdevBlockList.h,v +// Revision 1.1 1995/12/08 15:33:31 chen +// linked block list +// +// Revision 1.1.1.1 1995/06/16 17:14:07 epics +// initial import of cdev +// +// +#ifndef _CDEV_XOBJ_LIST_H +#define _CDEV_XOBJ_LIST_H + +#include +#include +#include + +typedef void* blockListItem; + +//=========================================================================== +// class tranObjBlockList +// List of blocks each with size +//=========================================================================== +const int DEFAULT_BLOCK_SIZE = 64; + +class cdevBlockListIterator; + +//=========================================================================== +// class cdevBlockLink +// Node for the cdevBlockList class (private) +//============================================================================= +class CDEV_CLASS_SPEC cdevBlockLink +{ + private: + //constructors + // create a single block with all unset value in it + cdevBlockLink (cdevBlockLink * nextPtr, cdevBlockLink *prevPtr, + unsigned int size = DEFAULT_BLOCK_SIZE); + // create a single block with default value in it + cdevBlockLink (cdevBlockLink * nextPtr, cdevBlockLink *prevPtr, + const blockListItem& defVal, + unsigned int size = DEFAULT_BLOCK_SIZE); + // create a single block with some value in it + cdevBlockLink (cdevBlockLink * nextPtr, cdevBlockLink *prevPtr, + blockListItem *date, + unsigned int size = DEFAULT_BLOCK_SIZE); + // copy constructor, copy all lists + cdevBlockLink (const cdevBlockLink& link); + // assignment operator + cdevBlockLink& operator = (const cdevBlockLink &link); + // destructor + virtual ~cdevBlockLink (void); + + // operations + // duplicate whole list + cdevBlockLink* duplicate (void); + // duplicate list starting here to the right + cdevBlockLink* duplicate (int type); // type 0. goes to right, 1 left + // insert a new block after + cdevBlockLink* addNewBlock (void); + cdevBlockLink* addNewBlock (const blockListItem & defValue); + // free all memory associated with the list + void freeAllMemory (void); + + // data area + blockListItem *value_; + unsigned int blockSize_; + // default value stored in the block + // keep track how many slots are occupied + cdevBlockLink *ptrToNextLink_; + cdevBlockLink *ptrToPrevLink_; + + // friends + friend class cdevBlockList; + friend class cdevBlockListIterator; +}; + +class CDEV_CLASS_SPEC cdevBlockList +{ + public: + // constructors and destructor + cdevBlockList (unsigned int blockSize = DEFAULT_BLOCK_SIZE); + cdevBlockList (const blockListItem& defVal, + unsigned int blockSize = DEFAULT_BLOCK_SIZE); + cdevBlockList (const cdevBlockList &rsc); + cdevBlockList& operator = (const cdevBlockList &rsc); + virtual ~cdevBlockList (void); + + // operations + // access elements via subscript + virtual blockListItem & operator [] (unsigned int ) const; + // free all memory + virtual void deleteAll (void); + // just clean out value + virtual void clearAll (void); + virtual cdevBlockList * duplicate (void) const; + virtual int includes (blockListItem value) const; + virtual int length (void) const; + + protected: + // data filed + cdevBlockLink firstBlock_; + unsigned int blockSize_; + unsigned int size_; + blockListItem* defValue_; + + private: + // return how many steps a particular pointer away from + // the beginning of the first block + unsigned int entryNumber (blockListItem *ptr); + cdevBlockLink* blockPointer (blockListItem *ptr); + blockListItem* entryPointer (unsigned int steps); + friend class cdevBlockListIterator; +}; + +//========================================================================= +// class cdevBlockListIterator +// Iterator class used to loop over all list elements +//========================================================================= +class CDEV_CLASS_SPEC cdevBlockListIterator +{ + public: + // constructor + cdevBlockListIterator (cdevBlockList &l); + + // iterator protocol + virtual int init (void); + virtual blockListItem operator () (); + virtual int operator !(); + // prefix + virtual int operator ++(); + virtual void operator = (blockListItem newValue); + + // new method for blockList + int forcePut (blockListItem value); + blockListItem * currentPosition(); + // prefix + int operator --(); + // move cursor to the end of the list + virtual int end (void); + + protected: + // data fields + cdevBlockList &data; + blockListItem* currEntry_; + blockListItem* blockEnd_; + blockListItem* blockStart_; + blockListItem* listEnd_; + unsigned int curPos_; +}; +#endif + diff --git a/src/group/cdevExecGroup.cc b/src/group/cdevExecGroup.cc new file mode 100755 index 0000000..56ec1c0 --- /dev/null +++ b/src/group/cdevExecGroup.cc @@ -0,0 +1,209 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevExecGroup class implementation +// +// Author: Jie Chen +// +// Revision History: +// cdevExecGroup.cc,v +// Revision 1.2 1997/04/02 17:54:05 akers +// Ongoing Development of CDEV 1.6 +// +// Revision 1.1 1997/03/03 17:35:59 chen +// add buffering to channel access connection +// +// +// +#include +#include +#include +#include "cdevExecGroup.h" + +cdevExecGroup::cdevExecGroup (cdevService* service, + unsigned int blockSize, cdevSystem &system) +:cdevGroup (blockSize, system) +{ +#ifdef _TRACE_OBJECTS + printf(" Create cdevExecGroup class\n"); +#endif + // remove this group from the system + // this group will no visible from system + unregOn_ = 0; + if (!errBit_) + system.removeGroup (this); + errBit_ = 0; + + // mode is always in the deferred mode + mode_ = CDEV_EXEC_DEFERRED; + + // add this service to the list + serviceList_.add (service); +} + +cdevExecGroup::~cdevExecGroup (void) +{ +#ifdef _TRACE_OBJECTS + printf(" Destroy cdevExecGroup class\n"); +#endif + // empty +} + +int +cdevExecGroup::start (void) +{ + return CDEV_SUCCESS; +} + +int +cdevExecGroup::end (void) +{ + return CDEV_SUCCESS; +} + +int +cdevExecGroup::flush (void) +{ + // must send out commands before closing the group + if (mode_ == CDEV_EXEC_DEFERRED) { + ite_.init (); + execAllCommands (); + } + + if (hwMark_) { + getServices (); + cdevSlistIterator sit(serviceList_); + cdevService *tsvc = 0; + for (sit.init(); !sit; ++sit){ + tsvc = (cdevService *)sit (); + tsvc->flush(); + } + } + return CDEV_SUCCESS; +} + +int +cdevExecGroup::poll (void) +{ + return CDEV_SUCCESS; +} + +int +cdevExecGroup::pend (int /* fd */) +{ + return CDEV_SUCCESS; +} + +int +cdevExecGroup::pend (double /* seconds */, int /* fd */) +{ + return CDEV_SUCCESS; +} + +int +cdevExecGroup::handleEvents (cdevTimeValue * /* tv */) +{ + return CDEV_SUCCESS; +} + +void +cdevExecGroup::notifyService (int /* handle */) +{ + // empty +} + +cdevService * +cdevExecGroup::pendingService (int /* handle */) +{ + return 0; +} + +int +cdevExecGroup::allFinished (void) +{ + return 1; +} + +int +cdevExecGroup::status (int /* status */[], int & /* numTransactions */) +{ + return CDEV_SUCCESS; +} + +void +cdevExecGroup::getServices (void) +{ + // empty +} + + +void +cdevExecGroup::execDeferred (void) +{ + mode_ = CDEV_EXEC_DEFERRED; +} + +void +cdevExecGroup::execImmediate (void) +{ + mode_ = CDEV_EXEC_IMMEDIATE; +} + +int +cdevExecGroup::executionMode (void) const +{ + return mode_; +} + +int +cdevExecGroup::execAllCommands (void) +{ + int status= CDEV_SUCCESS; + int ist; + + // change execution stage to execution + execStage_ = 1; + // lock the list + remEobj_ = 0; + + cdevExecObj *obj = 0; + int i = 0; + for (eite_.init (); i < numEobjs_ && !eite_; ++eite_) { + obj = (cdevExecObj *) eite_ (); + cdevRequestObject *reqobj = obj->reqObj_; + if (obj->userCallback_ != 0) { + if ((ist = reqobj->execCallback (obj->outData_, *(obj->userCallback_), + obj->arg_)) != CDEV_SUCCESS) + status = ist; + } + else { + if ((ist= reqobj->execNoBlock (obj->outData_, obj->resultData_, + obj->arg_)) != CDEV_SUCCESS) + status = ist; + } + // delete execution obejct + delete obj; + i++; + } + + remEobj_ = 1; + numEobjs_ = 0; + + // turn the execution stage to buffering stage again + execStage_ = 0; + + return status; +} + +int +cdevExecGroup::readyToExec (void) const +{ + return execStage_; +} diff --git a/src/group/cdevExecGroup.h b/src/group/cdevExecGroup.h new file mode 100755 index 0000000..8f748e4 --- /dev/null +++ b/src/group/cdevExecGroup.h @@ -0,0 +1,138 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevExecGroup: handle buffering mechanism for multiple +// executions +// +// For service layer only +// +// Author: Jie Chen +// +// Revision History: +// cdevExecGroup.h,v +// Revision 1.1 1997/03/03 17:36:00 chen +// add buffering to channel access connection +// +// +// +#ifndef _CDEV_EXEC_GROUP_H +#define _CDEV_EXEC_GROUP_H + +#include + +class cdevExecObj; + +class CDEV_CLASS_SPEC cdevExecGroup: public cdevGroup +{ +public: + // constructors and destructor + cdevExecGroup (cdevService* service, + unsigned int blockSize = DEFAULT_BLOCK_SIZE, + cdevSystem& system = cdevSystem::defaultSystem()); + ~cdevExecGroup (void); + + int flush (void); + // PURPOSE: flush all network requests inside this group + // REQUIRE: nothing + // PROMISE: all network requests of this group will be sent out + // return CDEV_SUCCESS + + virtual const char *className (void) const {return "cdevExecGroup";} + +protected: + + int start (void); + // PURPOSE: start this group. (see next) + // REQUIRE: nothing + // PROMISE: group stared, return CDEV_SUCCESS + + int end (void); + // PURPOSE: end this group, all async IO between + // start and end will be in the group + // REQUIRE: nothing + // PROMISE: group ended, return CDEV_SUCCESS + + int poll (void); + // PURPOSE: polling all outstanding IO events of this group + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS + + int pend (int fd = -1); + // PURPOSE: do network pending for IO events forever until all + // network requests of this group have come back + // REQUIRE: nothing + // PROMISE: all come back or block forever (return CDEV_SUCCESS) + + int pend (double seconds, int fd = -1); + // PURPOSE: do network pending for IO events for upto 'seconds' long or + // all network requests of this group have come back + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS: finished, return CDEV_TIMEOUT: timeout + + int allFinished (void); + // PURPOSE: check all transaction finished of this group + // REQUIRE: after pend call + // PROMISE: return 1: all finished, 0: not yet + + int status (int status[], int &numTransactions); + // PURPOSE: check status of all transactions + // REQURIE: transaction status will be in the integer array returned + // by this call. Element of the array = 0 finished. + // Callers provide integer array buffer with buffer size + // PROMISE: return CDEV_SUCCESS on success and numTransaction will be + // real number of trasanctions. return CDEV_INVALIDARG + // when the integer buffer is not big enough. + + void execDeferred (void); + void execImmediate (void); + // PURPOSE: change behaviour of execution of command inside the group + // execDeferred will buffer all commands until pend or poll or + // flush is called + // execImmediate will flush commands to underlying services + // immediately + // REQUIRE: none + // PROMISE: execution mode changed + + int executionMode (void) const; + // PURPOSE: return execution mode + // REQUIRE: none + // PROMISE: CDEV_EXEC_DEFERRED or CDEV_EXEC_IMMEDIATE + + int readyToExec (void) const; + // PURPOSE: for deferred mode group only. Return execution stage. + // REQUIRE: none + // PROMISE: 0: the deferred group is still in the buffered stage + // 1: the deferred group is ready to flush all buffered + // commands + + // get underlying service + void getServices (void); + + // send out all buffered commands + int execAllCommands (void); + + // find out which service is ready + cdevService *pendingService (int handle); + // handle events inherited from cdevSync + int handleEvents (cdevTimeValue *tv); + // notify one partucular service + void notifyService (int fd); + +private: + // data member + // deny access of copy and assignment since the group is a manager + cdevExecGroup (const cdevExecGroup& ); + cdevExecGroup& operator = (const cdevExecGroup&); + + // friend class + friend class cdevExecObj; +}; +#endif + diff --git a/src/group/cdevExecObj.cc b/src/group/cdevExecObj.cc new file mode 100755 index 0000000..f5eaeff --- /dev/null +++ b/src/group/cdevExecObj.cc @@ -0,0 +1,104 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdev Transaction Object class (for service developer only) +// +// Author: Jie Chen +// +// Revision History: +// cdevExecObj.cc,v +// Revision 1.2 1997/03/03 17:36:02 chen +// add buffering to channel access connection +// +// Revision 1.1 1995/12/08 15:34:37 chen +// execution object +// +// +#include +#include "cdevExecObj.h" + +// Note: How to determine to buffer an exeution object? +// If an execution object belongs to a group with +// an immediate execution mode, this object will not be +// buffered. If an execution object belongs to a group +// with a deferred execution mode, this execution object +// will be buffered + + +cdevExecObj::cdevExecObj (void) +:system_ (0), reqObj_ (0), outData_ (0), resultData_ (0), + userCallback_ (0), status_ (-1) +{ +#ifdef _TRACE_OBJECTS + printf ("Create cdevExecObj Class Object\n"); +#endif + deferredGroup_ = 0; + entryPtr_ = 0; +} + +cdevExecObj::cdevExecObj (cdevSystem* system, + cdevRequestObject* obj, + cdevData* out, + cdevData* result, + cdevCallback* callback, + cdevGroup* execg, + void* arg) +:system_ (system), reqObj_ (obj), outData_ (out), + resultData_ (result), userCallback_ (callback), status_ (1), arg_ (arg) +{ +#ifdef _TRACE_OBJECTS + printf ("Create cdevExecObj Class Object\n"); +#endif + if (execg == 0) { + int i = 0; + cdevGroup* activeGroups [MAX_NUM_GROUPS]; + int numActiveGrps = 0; + for (i = 0; i < MAX_NUM_GROUPS; i++) { + activeGroups [i] = 0; + } + // system could return empty groups + system_->activeGroups (activeGroups, numActiveGrps); + // only store execution object in the inner most group + // Whether to buffer this execution object has been determined + // by request object + if (numActiveGrps != 0) { + entryPtr_ = (activeGroups[0])->addExecObj (this); + deferredGroup_ = activeGroups[0]; + } + } + else { + deferredGroup_ = execg; + entryPtr_ = execg->addExecObj (this); + } + +} + +cdevExecObj::~cdevExecObj (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete cdevExecObj class object\n"); +#endif + // remove this execution object from the deferred group + if (deferredGroup_) { + if (deferredGroup_->remEobj_) + *entryPtr_ = 0; + } + status_ = -1; + deferredGroup_ = 0; + if (outData_) delete outData_; + // don't worry about callback which cannot be detructed by any means since + // everything is inside a group +} + +int +cdevExecObj::status (void) const +{ + return status_; +} diff --git a/src/group/cdevExecObj.h b/src/group/cdevExecObj.h new file mode 100755 index 0000000..c158979 --- /dev/null +++ b/src/group/cdevExecObj.h @@ -0,0 +1,100 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdev deferred execution object (for service developer only) +// +// deferred execution object is registered into one and only one +// opened group which is the outmost deferred one +// +// Author: Jie Chen +// +// Revision History: +// cdevExecObj.h,v +// Revision 1.2 1997/03/03 17:36:03 chen +// add buffering to channel access connection +// +// Revision 1.1 1995/12/08 15:34:50 chen +// execution object +// +// +#ifndef _CDEV_EXEC_OBJ_H +#define _CDEV_EXEC_OBJ_H + +#include +#include +#include +#include +#include + +class cdevGroup; +class cdevRequestObject; + +class CDEV_CLASS_SPEC cdevExecObj +{ +public: + // constructor and destructor + cdevExecObj (void); + cdevExecObj (cdevSystem* sys, + cdevRequestObject* reqobj, + cdevData* out, + cdevData* result, + cdevCallback* callback, + cdevGroup* execg = 0, + void* arg = 0); + // Important note: + // No objects pointed by the pointers will be deleted from this object + ~cdevExecObj (void); + + int status (void) const; + // PURPOSE: return status of transaction object + // REQUIRE: nothing + // PROMISE: -1: not registered into any group, 1: registered into groups + + int removeFromGrps (void); + // PURPOSE: remove this transaction object from all groups + // REQUIRE: nothing + // PROMISE: status = -1 + + // data area for requestObject to access + cdevSystem *system_; + cdevRequestObject *reqObj_; + cdevData *outData_; + cdevData *resultData_; + cdevCallback *userCallback_; + int status_; + cdevGroup *deferredGroup_; + // pointer entries to the entry inside deferred group + cdevExecObj **entryPtr_; + // any user provided argument + void *arg_; + + virtual const char *className (void) const {return "cdevExecObj";} + +private: + // deny copy and assignment operation + // It makes no sense for two identical transaction objects + cdevExecObj (const cdevExecObj& rsc); + cdevExecObj& operator = (const cdevExecObj& rsc); + + // friend class + friend class cdevGroup; +}; +#endif + + + + + + + + + + + diff --git a/src/group/cdevGroup.cc b/src/group/cdevGroup.cc new file mode 100755 index 0000000..dbf8975 --- /dev/null +++ b/src/group/cdevGroup.cc @@ -0,0 +1,565 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevGroup class implementation +// +// Author: Jie Chen +// +// Revision History: +// cdevGroup.cc,v +// Revision 1.11 1997/07/28 12:58:24 chen +// fix a bug that causes missing fds +// +// Revision 1.10 1997/04/02 17:54:05 akers +// Ongoing Development of CDEV 1.6 +// +// Revision 1.9 1997/03/03 17:36:04 chen +// add buffering to channel access connection +// +// Revision 1.8 1997/01/29 19:37:06 akers +// Removed assertion +// +// Revision 1.7 1996/05/02 14:17:27 chen +// handle unfinished transaction +// +// Revision 1.6 1996/01/17 17:50:48 chen +// change status implementation +// +// Revision 1.5 1995/12/14 19:11:45 chen +// fix a bug on a default group +// +// Revision 1.4 1995/12/08 15:35:30 chen +// handle deferred mode +// +// Revision 1.3 1995/07/05 18:42:50 chen +// change status interface +// +// Revision 1.2 1995/06/30 16:03:35 chen +// use generic list +// +// Revision 1.1.1.1 1995/06/16 17:14:07 epics +// initial import of cdev +// +// +#include +#include +#include +#include "cdevGroup.h" + +cdevGroup::cdevGroup (unsigned int blockSize, cdevSystem &system) +:cdevSync(), objList_ ((cdevTranObj *)0, blockSize), ite_ (objList_), + eobjList_ ((cdevExecObj *)0, blockSize), eite_ (eobjList_), + serviceList_(), system_ (system), + remXobj_ (1), hwMark_(0), active_ (0), + mode_ (CDEV_EXEC_IMMEDIATE), numEobjs_ (0), execStage_ (0) +{ +#ifdef _TRACE_OBJECTS + printf(" Create cdevGroup class\n"); +#endif + unregOn_ = 1; + errBit_ = system.registerGroup (this); +} + +cdevGroup::~cdevGroup (void) +{ +#ifdef _TRACE_OBJECTS + printf(" Destroy cdevGroup class\n"); +#endif + cleanAll (); + cleanAllEobjs (); + active_ = 0; + // system will clean this up depending on unregOn_ flag + if (unregOn_) + system_.removeGroup (this); +} + +void +cdevGroup::cleanAll (void) +{ + // first to clean out all transaction objects + // we may change this implementation. + // eg. we put all unfinished transaction objects to some + // free list in the system + + // lock the list with remXobj_ set off + remXobj_ = 0; + int i = 0; + cdevTranObj* obj = 0; + for (ite_.init(); i < hwMark_ && !ite_; ++ite_){ + obj = (cdevTranObj *)ite_ (); + if (obj != 0 && obj->status_ == 1){ + obj->trash (this); + ite_ = 0; + } + i++; + } + remXobj_ = 1; + + // clear all service pointer from the service list + serviceList_.deleteAllValues (); + // clear out high water mark + hwMark_ = 0; +} + +int +cdevGroup::start (void) +{ + if (!active_){ + cleanAll (); + cleanAllEobjs (); + execStage_ = 0; + ite_.init (); + eite_.init (); + if (errBit_){ + system_.reportError( + CDEV_SEVERITY_SEVERE, "cdevGroup", NULL, + "Exceeds maximum number of groups\n"); + return CDEV_ERROR; + } + active_ = 1; + return system_.registerActiveGroup (this); + } + else + return CDEV_SUCCESS; +} + +int +cdevGroup::end (void) +{ + if (active_){ + active_ = 0; + return system_.removeActiveGroup (this); + } + else + return CDEV_SUCCESS; +} + +cdevTranObj ** +cdevGroup::addTranObj (cdevTranObj *obj) +{ + ite_.forcePut ((void *)obj); + cdevTranObj **tmp = (cdevTranObj **)ite_.currentPosition(); + ++ite_; + hwMark_ ++; + return tmp; +} + + +void +cdevGroup::setupFdMask (void) +{ + cdevSlistIterator sit(serviceList_); + cdevService *tsvc = 0; + + rdMask_.reset(); + wrMask_.reset(); + exMask_.reset(); + for (sit.init(); !sit; ++sit){ + tsvc = (cdevService *)sit (); + int *fd = 0; + int numFds = 0; + tsvc->getFd (fd, numFds); + if (numFds != 0){ + for (int j = 0; j < numFds; j++) + attachReadFd (fd[j]); + numFds = 0; + } + } +} + +void +cdevGroup::qpoll (void) +{ + // service list is constructed already + cdevSlistIterator sit(serviceList_); + cdevService *tsvc = 0; + for (sit.init(); !sit; ++sit){ + tsvc = (cdevService *)sit (); + tsvc->poll(); + } +} + +int +cdevGroup::flush (void) +{ + // must send out commands before closing the group + if (mode_ == CDEV_EXEC_DEFERRED) { + if (allFinished ()) { + cleanAll (); + ite_.init (); + execAllCommands (); + } + else + return CDEV_ERROR; + } + if (hwMark_) { + getServices (); + cdevSlistIterator sit(serviceList_); + cdevService *tsvc = 0; + for (sit.init(); !sit; ++sit){ + tsvc = (cdevService *)sit (); + tsvc->flush(); + } + } + return CDEV_SUCCESS; +} + +int +cdevGroup::poll (void) +{ + if (active_) // implicitly end this group + end (); + if (hwMark_) { + getServices (); + cdevSlistIterator sit(serviceList_); + cdevService *tsvc = 0; + for (sit.init(); !sit; ++sit){ + tsvc = (cdevService *)sit (); + tsvc->poll(); + } + } + return CDEV_SUCCESS; +} + +int +cdevGroup::pend (int /* fd */) +{ + if (active_) // implicitly end this group + end (); + if (hwMark_) { + getServices (); + cdevSlistIterator sit(serviceList_); + cdevService *tsvc = 0; + // first flush out all requests + for (sit.init(); !sit; ++sit) { + tsvc = (cdevService *)sit (); + tsvc->flush (); + } + + rdMask_.reset(); + wrMask_.reset(); + exMask_.reset(); + for (sit.init(); !sit; ++sit){ + tsvc = (cdevService *)sit (); + int *fd = 0; + int numFds = 0; + tsvc->getFd (fd, numFds); + if (numFds != 0){ + for (int j = 0; j < numFds; j++) + attachReadFd (fd[j]); + numFds = 0; + } + } + // check IO ready or not + return handleEvents ((cdevTimeValue *)0); + } + else + return CDEV_SUCCESS; +} + +int +cdevGroup::pend (double seconds, int /* fd */) +{ + if (active_) // implicitly end this group + end (); + if (hwMark_) { + if (seconds > 0.0){ + getServices (); + cdevSlistIterator sit(serviceList_); + cdevService *tsvc = 0; + for (sit.init(); !sit; ++sit) { + tsvc = (cdevService *)sit (); + tsvc->flush(); + } + rdMask_.reset (); + wrMask_.reset (); + exMask_.reset (); + + for (sit.init(); !sit; ++sit){ + tsvc = (cdevService *)sit (); + int *fd = 0; + int numFds = 0; + tsvc->getFd (fd, numFds); + for (int j = 0; j < numFds; j++) { + attachReadFd (fd[j]); + } + numFds = 0; + } + //check IO ready + cdevTimeValue how_long (seconds); + return handleEvents (&how_long); + } + else + return poll (); + } + else + return CDEV_SUCCESS; +} + +int +cdevGroup::handleEvents (cdevTimeValue *tv) +{ + cdevFdSet rmaskret; + cdevFdSet wmaskret; + cdevFdSet emaskret; + int nfound = 0; + cdevClock timer; + + // some times this group is already finished by some other group's + // pend activities + if (allFinished ()) + return CDEV_SUCCESS; + + if (tv){ // finite time out value + // poke low level service first + qpoll (); + + // check latest fd's + setupFdMask (); + + // split time out value into smaller chunks + cdevTimeValue ttv (0.1); + int numloops = 0; + int i = 0; + + if (*tv > ttv) { + numloops = (int)(tv->sec ()/0.1 + tv->usec ()/100000.0); + + while (i < numloops && !allFinished ()) { + i++; + nfound = waitFor (rmaskret, wmaskret, emaskret, &ttv); + if (nfound <= 0) + qpoll (); + else + dispatch (nfound, rmaskret, wmaskret, emaskret); + + + // check fd mask to make sure new fds are added + if( !allFinished() ) + setupFdMask (); + } + if (i < numloops) // success + return CDEV_SUCCESS; + } + else { + nfound = waitFor (rmaskret, wmaskret, emaskret, tv); + if (nfound <= 0) + qpoll (); + else + dispatch (nfound, rmaskret, wmaskret, emaskret); + } + if (allFinished()) + return CDEV_SUCCESS; + // timed out + return CDEV_TIMEOUT; + } + else { // infinite long time out + while (!allFinished ()){ + // poke low level service first + qpoll (); + + // check latest fd's + setupFdMask (); + + // make sure there is no block + cdevTimeValue ttv (0.1); + + nfound = waitFor (rmaskret, wmaskret, emaskret, &ttv); + + if (nfound <= 0) { + // just poke at the low level service + qpoll (); + } + else { + // really handle lower level IO here + dispatch (nfound, rmaskret, wmaskret, emaskret); + } + } + } + return CDEV_SUCCESS; +} + +void +cdevGroup::notifyService (int handle) +{ + cdevService *service = pendingService (handle); + + if (service && service->pend (handle) < 0) + { + // remove this file descriptor + detachReadFd (handle); + } +} + +cdevService * +cdevGroup::pendingService (int handle) +{ + cdevSlistIterator sit (serviceList_); + cdevService *tsvc = 0; + + for (sit.init(); !sit; ++sit){ + tsvc = (cdevService *)sit (); + int *fd = 0; + int numFds = 0; + tsvc->getFd (fd, numFds); + if (numFds != 0){ + for (int j = 0; j < numFds; j++) + if (handle == fd[j]) + return tsvc; + numFds = 0; + } + } + return (cdevService *)0; +} + +int +cdevGroup::allFinished (void) +{ + int i = 0; + cdevTranObj* obj = 0; + for (ite_.init(); i < hwMark_ && !ite_; ++ite_){ + obj = (cdevTranObj *)ite_(); + if (obj != 0 && obj->status_ == 1) + return 0; + i++; + } + return 1; +} + +int +cdevGroup::status (int status[], int & numTransactions) +{ + int num = numTransactions; + numTransactions = (hwMark_ < num) ? hwMark_ : num; + cdevTranObj* obj = 0; + ite_.init(); + for (int i = 0; i < numTransactions; i++){ + obj = (cdevTranObj *)ite_ (); + if (obj != 0) + status[i] = obj->status_; + else + status[i] = 0; + ++ite_; + } + return CDEV_SUCCESS; +} + +void +cdevGroup::getServices (void) +{ + serviceList_.deleteAllValues(); + int i = 0; + cdevTranObj* obj = 0; + for (ite_.init(); i < hwMark_ && !ite_; ++ite_){ + obj = (cdevTranObj *) ite_ (); + if (obj != 0 && obj->status_ == 1) + if (!serviceList_.includes((void *)&(obj->reqObj_->service()))) { + serviceList_.add ((void *)&(obj->reqObj_->service() )); + } + i++; + } +} + + +cdevExecObj ** +cdevGroup::addExecObj (cdevExecObj *eobj) +{ + eite_.forcePut ((void *)eobj); + cdevExecObj **tmp = (cdevExecObj **)eite_.currentPosition(); + ++eite_; + numEobjs_ ++; + return tmp; +} + +void +cdevGroup::cleanAllEobjs (void) +{ + // first to clean out all execution objects + + // lock the list with remEobj_ set off + remEobj_ = 0; + cdevExecObj* obj = 0; + int i = 0; + + for (eite_.init(); i < numEobjs_ && !eite_; ++eite_){ + obj = (cdevExecObj *) eite_ (); + if (obj != 0 && obj->status_ == 1){ + delete obj; + eite_ = 0; + } + i++; + } + remEobj_ = 1; + numEobjs_ = 0; +} + +void +cdevGroup::execDeferred (void) +{ + mode_ = CDEV_EXEC_DEFERRED; +} + +void +cdevGroup::execImmediate (void) +{ + mode_ = CDEV_EXEC_IMMEDIATE; +} + +int +cdevGroup::executionMode (void) const +{ + return mode_; +} + +int +cdevGroup::execAllCommands (void) +{ + int status= CDEV_SUCCESS; + int ist; + + // change execution stage to execution + execStage_ = 1; + + // reopen this group for handling synchronization of all operations + if (!active_) { + active_ = 1; + system_.registerActiveGroup (this); + } + + cdevExecObj *obj = 0; + int i = 0; + for (eite_.init (); i < numEobjs_ && !eite_; ++eite_) { + obj = (cdevExecObj *) eite_ (); + cdevRequestObject *reqobj = obj->reqObj_; + if (obj->userCallback_ != 0) { + if ((ist = reqobj->sendCallback (obj->outData_, *(obj->userCallback_))) + != CDEV_SUCCESS) + status = ist; + } + else { + if ((ist= reqobj->sendNoBlock (obj->outData_, obj->resultData_)) + != CDEV_SUCCESS) + status = ist; + } + // do not delete transaction objects until restart this group + // user can use flush to resend all commands + i++; + } + // turn the execution stage to buffering stage again + execStage_ = 0; + + return status; +} + +int +cdevGroup::readyToExec (void) const +{ + return execStage_; +} diff --git a/src/group/cdevGroup.h b/src/group/cdevGroup.h new file mode 100755 index 0000000..c562ad8 --- /dev/null +++ b/src/group/cdevGroup.h @@ -0,0 +1,201 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevGroup: handle multiple asynchronous operations +// +// Author: Jie Chen +// +// Revision History: +// cdevGroup.h,v +// Revision 1.5 1997/03/03 17:36:05 chen +// add buffering to channel access connection +// +// Revision 1.4 1995/12/08 15:35:37 chen +// handle deferred mode +// +// Revision 1.3 1995/07/05 18:42:44 chen +// change status interface +// +// Revision 1.2 1995/06/30 16:03:36 chen +// use generic list +// +// Revision 1.1.1.1 1995/06/16 17:14:07 epics +// initial import of cdev +// +// +#ifndef _CDEV_GROUP_H +#define _CDEV_GROUP_H + +#include +#include +#include +#include +#include +#include +#include + +#include "cdevBlockList.h" + +#define CDEV_EXEC_IMMEDIATE 0 +#define CDEV_EXEC_DEFERRED 1 + + +class CDEV_CLASS_SPEC cdevGroup: public cdevSync +{ +public: + // constructors and destructor + cdevGroup (unsigned int blockSize = DEFAULT_BLOCK_SIZE, + cdevSystem& system = cdevSystem::defaultSystem()); + virtual ~cdevGroup (void); + + virtual int start (void); + // PURPOSE: start this group. (see next) + // REQUIRE: nothing + // PROMISE: group stared, return CDEV_SUCCESS + + virtual int end (void); + // PURPOSE: end this group, all async IO between + // start and end will be in the group + // REQUIRE: nothing + // PROMISE: group ended, return CDEV_SUCCESS + + virtual int flush (void); + // PURPOSE: flush all network requests inside this group + // REQUIRE: nothing + // PROMISE: all network requests of this group will be sent out + // return CDEV_SUCCESS + + virtual int poll (void); + // PURPOSE: polling all outstanding IO events of this group + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS + + virtual int pend (int fd = -1); + // PURPOSE: do network pending for IO events forever until all + // network requests of this group have come back + // REQUIRE: nothing + // PROMISE: all come back or block forever (return CDEV_SUCCESS) + + virtual int pend (double seconds, int fd = -1); + // PURPOSE: do network pending for IO events for upto 'seconds' long or + // all network requests of this group have come back + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS: finished, return CDEV_TIMEOUT: timeout + + int allFinished (void); + // PURPOSE: check all transaction finished of this group + // REQUIRE: after pend call + // PROMISE: return 1: all finished, 0: not yet + + int status (int status[], int &numTransactions); + // PURPOSE: check status of all transactions + // REQURIE: transaction status will be in the integer array returned + // by this call. Element of the array = 0 finished. + // Callers provide integer array buffer with buffer size + // PROMISE: return CDEV_SUCCESS on success and numTransaction will be + // real number of trasanctions. return CDEV_INVALIDARG + // when the integer buffer is not big enough. + + void execDeferred (void); + void execImmediate (void); + // PURPOSE: change behaviour of execution of command inside the group + // execDeferred will buffer all commands until pend or poll or + // flush is called + // execImmediate will flush commands to underlying services + // immediately + // REQUIRE: none + // PROMISE: execution mode changed + + int executionMode (void) const; + // PURPOSE: return execution mode + // REQUIRE: none + // PROMISE: CDEV_EXEC_DEFERRED or CDEV_EXEC_IMMEDIATE + + int readyToExec (void) const; + // PURPOSE: for deferred mode group only. Return execution stage. + // REQUIRE: none + // PROMISE: 0: the deferred group is still in the buffered stage + // 1: the deferred group is ready to flush all buffered + // commands + + virtual const char *className (void) const {return "cdevGroup";} + +protected: + // all add and remove operation on the transaction object + cdevTranObj **addTranObj (cdevTranObj* obj); + // clean out all transaction objects + void cleanAll (void); + // get all services associaed with transaction objects + // only used when one about to call IO operations + void getServices (void); + // find out which service is ready + cdevService *pendingService (int handle); + // handle events inherited from cdevSync + virtual int handleEvents (cdevTimeValue *tv); + // notify one partucular service + virtual void notifyService (int fd); + // quick polling underlying services + virtual void qpoll (void); + + // setup file read mask + void setupFdMask (void); + + // add execution object to the list + cdevExecObj **addExecObj (cdevExecObj* eobj); + // cleanout all execution objects + void cleanAllEobjs (void); + // send out all buffered commands + int execAllCommands (void); + +protected: + // data member + // transaction object list + cdevBlockList objList_; + // order dependent, careful!!! + cdevBlockListIterator ite_; + // execution object list + cdevBlockList eobjList_; + // order dependent, careful!!! + cdevBlockListIterator eite_; + // service list associcated with this group + cdevSlist serviceList_; + cdevSystem &system_; + // flag to tell whether one unregister itself from the system + int unregOn_; + // flag to see whether this group is created successfully + int errBit_; + // flag to see whether transaction object should remove itself + // from the object list + int remXobj_; + // flag to lock the execution object list + int remEobj_; + // how many transaction objects are in this group + int hwMark_; + // group active flag + int active_; + // operation mode of group + int mode_; + // number of execution objects + int numEobjs_; + // stage of deferred execution: buffer mode or execution mode + // 0: buffer stage, 1: execution stage + int execStage_; + + // deny access of copy and assignment since the group is a manager + cdevGroup (const cdevGroup& ); + cdevGroup& operator = (const cdevGroup&); + + // friend class + friend class cdevSystem; + friend class cdevTranObj; + friend class cdevExecObj; +}; +#endif + diff --git a/src/group/cdevMonitorObj.h b/src/group/cdevMonitorObj.h new file mode 100755 index 0000000..23c5130 --- /dev/null +++ b/src/group/cdevMonitorObj.h @@ -0,0 +1,92 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdev Monitoring Object class (for service developer only) +// +// This class is for services that support monitoring capabilities. +// It is very much like transanaction object but without being registered +// in the groups. The transaction objects will be deleted after the first +// callbacks. The monitor objects will stay around as long as the monitors +// are on. +// +// Service developers may have to derive from this class to handle +// service specific monitoring +// +// Author: Jie Chen +// +// Revision History: +// cdevMonitorObj.h,v +// Revision 1.4 1998/02/06 15:29:08 chen +// cosmatic change +// +// Revision 1.3 1998/01/30 14:25:18 akers +// Ongoing development +// +// Revision 1.2 1998/01/30 13:49:19 akers +// Ongoing development +// +// Revision 1.1 1998/01/14 14:26:39 chen +// add cdevMonitorObj +// +// +// +#ifndef _CDEV_MONITOR_OBJ_H +#define _CDEV_MONITOR_OBJ_H + +#include + +class cdevMonitorObj +{ +public: + // constructor and destructor + cdevMonitorObj(cdevTranObj &tranObj):system_(tranObj.system_), + reqObj_(tranObj.reqObj_), resultData_(tranObj.resultData_), + userCallback_(tranObj.userCallback_), tobj_(&tranObj) + { +#ifdef _TRACE_OBJECTS + printf("Create cdevMonitorObj Class Object\n"); +#endif + // disable transaction from deleting the callback + tobj_->disableDeleteCbk(); + } + + virtual ~cdevMonitorObj(void) + { +#ifdef _TRACE_OBJECTS + printf("Delete cdevMonitorObj Class Object\n"); +#endif + if(userCallback_ != 0) + { +#ifdef _CMLOG_DEBUG + printf("Delete userCallback inside cdevMonitorObj\n"); +#endif + delete userCallback_; + } + userCallback_=0; + } + + virtual const char *className(void) const {return"cdevMonitorObj";} + + // data area for requestObject to access + cdevSystem *system_; + cdevRequestObject *reqObj_; + cdevData *resultData_; + cdevCallback *userCallback_; + + // pointer to transaction object + cdevTranObj *tobj_; + +private: + // deny access to copy and assignment + cdevMonitorObj(const cdevMonitorObj &); + cdevMonitorObj &operator=(const cdevMonitorObj &); +}; + +#endif diff --git a/src/group/cdevTranObj.cc b/src/group/cdevTranObj.cc new file mode 100755 index 0000000..d1d4976 --- /dev/null +++ b/src/group/cdevTranObj.cc @@ -0,0 +1,217 @@ +// +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdev Transaction Object Class (Implementation) +// +// Author: Jie Chen +// +// Revision History: +// cdevTranObj.cc,v +// Revision 1.9 1996/12/18 13:35:12 akers +// Minor change +// +// Revision 1.6 1996/05/02 14:17:37 chen +// handle unfinished transaction +// +// Revision 1.5 1995/12/08 15:35:48 chen +// handle deferred mode +// +// Revision 1.4 1995/10/16 18:38:13 chen +// Change to work under SunOs and g++ +// +// Revision 1.3 1995/10/03 19:34:45 chen +// disable/enable deleting callback +// +// Revision 1.2 1995/09/05 17:19:10 chen +// remove callback object inside the destructor +// +// Revision 1.1.1.1 1995/06/16 17:14:07 epics +// initial import of cdev +// +// +#include +#include "cdevGroup.h" +#include +#include "cdevTranObj.h" + +cdevTranObj::cdevTranObj (void) +:system_ (0), reqObj_ (0), resultData_ (0), userCallback_ (0), + status_ (-1), numGroups_ (0), deleteCallback_ (1), trash_ (0) +{ +#ifdef _TRACE_OBJECTS + printf("Create cdevTranObj class object\n"); +#endif + for (int i = 0; i < MAX_NUM_GROUPS; i++){ + activeGroups_[i] = 0; + entryPtr_[i] = 0; + } +} + +cdevTranObj::cdevTranObj (cdevSystem *sys, + cdevRequestObject *obj, + cdevData *data, + cdevCallback *callback) +:system_(sys), reqObj_ (obj), resultData_ (data), + userCallback_ (callback), status_ (1), deleteCallback_ (1), trash_ (0) +{ +#ifdef _TRACE_OBJECTS + printf("Create cdevTranObj class object\n"); +#endif + int i; + for (i = 0; i < MAX_NUM_GROUPS; i++){ + activeGroups_[i] = 0; + entryPtr_[i] = 0; + } + // system could return empty groups + system_->activeGroups (activeGroups_, numGroups_); + for (i = 0; i < numGroups_; i++) { + if (activeGroups_[i]->executionMode () == CDEV_EXEC_IMMEDIATE) + entryPtr_[i] = (activeGroups_[i])->addTranObj (this); + else if (activeGroups_[i]->executionMode () == CDEV_EXEC_DEFERRED && + activeGroups_[i]->readyToExec ()) + entryPtr_[i] = (activeGroups_[i])->addTranObj (this); + } +} + +cdevTranObj::~cdevTranObj (void) +{ +#ifdef _TRACE_OBJECTS + printf("Destroy cdevTranObj class object\n"); +#endif + // remove this transaction objects from all the list + for (int i = 0; i < numGroups_; i++){ + if (activeGroups_[i]->remXobj_){ + if (entryPtr_[i] != 0) + *entryPtr_[i] = 0; + } + } + status_ = -1; + numGroups_ = 0; + // delete the cdevCallback object since it was created by copying user + // callback object in cdevDevice or cdevRequestObject + if (userCallback_ != 0){ + if (deleteCallback_) { +#ifdef _CDEV_DEBUG + printf ("Delete callback inside transaction object\n"); +#endif + delete userCallback_; + } + else { +#ifdef _CDEV_DEBUG + printf ("Cannot delete callbacks inside tran obj\n"); +#endif + } + } + userCallback_ = 0; +} + +int +cdevTranObj::operator == (const cdevTranObj& rsc) +{ + int i = 0; + if (system_ == rsc.system_ && reqObj_ == rsc.reqObj_ && + resultData_ == rsc.resultData_ && userCallback_ == rsc.userCallback_ && + status_ == rsc.status_ && numGroups_ == rsc.numGroups_){ + for (i = 0; i < numGroups_; i++){ + if (activeGroups_[i] != rsc.activeGroups_[i]) + return 0; + } + for (i = 0; i < numGroups_; i++){ + if (entryPtr_[i] != rsc.entryPtr_[i]) + return 0; + } + return 1; + } + else + return 0; +} + +int +cdevTranObj::operator != (const cdevTranObj& rsc) +{ + return !operator == (rsc); +} + +int +cdevTranObj::status (void) const +{ + return status_; +} + +int +cdevTranObj::removeFromGrps (void) +{ +#ifdef _CDEV_DEBUG + printf ("cdevTranObj::removeFromGrps\n"); +#endif + // remove this transaction objects from all the list + for (int i = 0; i < numGroups_; i++){ + if (activeGroups_[i]->remXobj_){ + if (entryPtr_[i] != 0) + *entryPtr_[i] = 0; + } + } + status_ = -1; + numGroups_ = 0; + return 0; +} + +void +cdevTranObj::disableDeleteCbk (void) +{ + deleteCallback_ = 0; +} + +void +cdevTranObj::enableDeleteCbk (void) +{ + deleteCallback_ = 1; +} + +void +cdevTranObj::trash (cdevGroup* grp) +{ + int i, j; + + if (numGroups_ > 1) { // readjust the active groups +#ifdef _CDEV_DEBUG + printf ("0x%x has number groups %d\n", this, numGroups_); +#endif + for (i = 0; i < numGroups_; i++) { + if (activeGroups_[i] == grp) { + j = i; + break; + } + } +#ifdef _CDEV_DEBUG + printf ("remove this transaction object 0x%x from group %d\n", this, j); +#endif + for (i = j; i < numGroups_ - 1; i++) { + activeGroups_[i] = activeGroups_[i + 1]; + *entryPtr_[i] = *entryPtr_[i + 1]; + } + numGroups_ --; + } + if (numGroups_ == 1) { +#ifdef _CDEV_DEBUG + printf ("Turn this transaction object 0x%x into junk\n", this); +#endif + trash_ = 1; + numGroups_ = 0; + } +} + +int +cdevTranObj::isTrash (void) const +{ + return trash_; +} + diff --git a/src/group/cdevTranObj.h b/src/group/cdevTranObj.h new file mode 100755 index 0000000..6feb196 --- /dev/null +++ b/src/group/cdevTranObj.h @@ -0,0 +1,112 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdev Transaction Object class (for service developer only) +// +// Author: Jie Chen +// +// Revision History: +// cdevTranObj.h,v +// Revision 1.4 1996/05/02 14:17:44 chen +// handle unfinished transaction +// +// Revision 1.3 1995/12/08 15:35:57 chen +// handle deferred mode +// +// Revision 1.2 1995/10/03 19:34:52 chen +// disable/enable deleting callback +// +// Revision 1.1.1.1 1995/06/16 17:14:07 epics +// initial import of cdev +// +// +#ifndef _CDEV_TRANOBJ_H +#define _CDEV_TRANOBJ_H + +#include +#include +#include +#include +#include +#include + +class cdevGroup; +class cdevRequestObject; + +class CDEV_CLASS_SPEC cdevTranObj +{ +public: + // constructors and destructor + cdevTranObj (void); + cdevTranObj (cdevSystem *sys, + cdevRequestObject *reqObj, + cdevData *data, + cdevCallback *callback); + ~cdevTranObj (void); + + int status (void) const; + // PURPOSE: return status of transaction object + // REQUIRE: nothing + // PROMISE: -1: not registered into any group, 1: registered into groups + + int operator == (const cdevTranObj& rsc); + int operator != (const cdevTranObj& rsc); + // PURPOSE: equality operator + // REQUIRE: nothing + // PROMISE: obvious + + int removeFromGrps (void); + // PURPOSE: remove this transaction object from all groups + // REQUIRE: nothing + // PROMISE: status = -1 + + void disableDeleteCbk (void); + void enableDeleteCbk (void); + // PURPOSE: enable/disable delete callback flag + // REQUIRE: nothing + // PROMISE: you know + + void trash (cdevGroup* grp); + int isTrash (void) const; + // PURPOSE: throw this transaction object into a trash dump + // REQUIRE: nothing; + // PROMISE: this transaction object will not attempt to call any callback + // function + + // data area for requestObject to access + cdevSystem *system_; + cdevRequestObject *reqObj_; + cdevData *resultData_; + cdevCallback *userCallback_; + int status_; + cdevGroup *activeGroups_[MAX_NUM_GROUPS]; + int numGroups_; + // pointer entries to all active groups + cdevTranObj **entryPtr_[MAX_NUM_GROUPS]; + + const char *className (void) const {return "cdevTranObj";} + +private: + // deny copy and assignment operation + // It makes no sense for two identical transaction objects + cdevTranObj (const cdevTranObj& rsc); + cdevTranObj& operator = (const cdevTranObj& rsc); + + // flag of deleting callback or not. + // Reason: callback may need stay after the transaction object goes away + int deleteCallback_; + + // flag of garbage transaction object (do not care any callbacks) + int trash_; + + // friend class + friend class cdevGroup; +}; +#endif diff --git a/src/lib/.shobj/Linux/cdev.o b/src/lib/.shobj/Linux/cdev.o new file mode 100644 index 0000000..b5a1ab4 Binary files /dev/null and b/src/lib/.shobj/Linux/cdev.o differ diff --git a/src/lib/.shobj/Linux/cdevBlockList.o b/src/lib/.shobj/Linux/cdevBlockList.o new file mode 100644 index 0000000..23350fc Binary files /dev/null and b/src/lib/.shobj/Linux/cdevBlockList.o differ diff --git a/src/lib/.shobj/Linux/cdevCallback.o b/src/lib/.shobj/Linux/cdevCallback.o new file mode 100644 index 0000000..f2010c3 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevCallback.o differ diff --git a/src/lib/.shobj/Linux/cdevClock.o b/src/lib/.shobj/Linux/cdevClock.o new file mode 100644 index 0000000..3597c6a Binary files /dev/null and b/src/lib/.shobj/Linux/cdevClock.o differ diff --git a/src/lib/.shobj/Linux/cdevCollection.o b/src/lib/.shobj/Linux/cdevCollection.o new file mode 100644 index 0000000..dcfe6fc Binary files /dev/null and b/src/lib/.shobj/Linux/cdevCollection.o differ diff --git a/src/lib/.shobj/Linux/cdevCollectionRequest.o b/src/lib/.shobj/Linux/cdevCollectionRequest.o new file mode 100644 index 0000000..826974a Binary files /dev/null and b/src/lib/.shobj/Linux/cdevCollectionRequest.o differ diff --git a/src/lib/.shobj/Linux/cdevConfigFinder.o b/src/lib/.shobj/Linux/cdevConfigFinder.o new file mode 100644 index 0000000..60b338f Binary files /dev/null and b/src/lib/.shobj/Linux/cdevConfigFinder.o differ diff --git a/src/lib/.shobj/Linux/cdevData.o b/src/lib/.shobj/Linux/cdevData.o new file mode 100644 index 0000000..8e6ab56 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevData.o differ diff --git a/src/lib/.shobj/Linux/cdevDataEntry.o b/src/lib/.shobj/Linux/cdevDataEntry.o new file mode 100644 index 0000000..a058817 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevDataEntry.o differ diff --git a/src/lib/.shobj/Linux/cdevDefCollectionRequest.o b/src/lib/.shobj/Linux/cdevDefCollectionRequest.o new file mode 100644 index 0000000..ac08945 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevDefCollectionRequest.o differ diff --git a/src/lib/.shobj/Linux/cdevDevice.o b/src/lib/.shobj/Linux/cdevDevice.o new file mode 100644 index 0000000..34ad9d4 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevDevice.o differ diff --git a/src/lib/.shobj/Linux/cdevDirRequestObj.o b/src/lib/.shobj/Linux/cdevDirRequestObj.o new file mode 100644 index 0000000..a79f587 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevDirRequestObj.o differ diff --git a/src/lib/.shobj/Linux/cdevDirectory.o b/src/lib/.shobj/Linux/cdevDirectory.o new file mode 100644 index 0000000..84c1640 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevDirectory.o differ diff --git a/src/lib/.shobj/Linux/cdevDirectoryTable.o b/src/lib/.shobj/Linux/cdevDirectoryTable.o new file mode 100644 index 0000000..12ec80f Binary files /dev/null and b/src/lib/.shobj/Linux/cdevDirectoryTable.o differ diff --git a/src/lib/.shobj/Linux/cdevDirectoryTool.o b/src/lib/.shobj/Linux/cdevDirectoryTool.o new file mode 100644 index 0000000..3fd5ec5 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevDirectoryTool.o differ diff --git a/src/lib/.shobj/Linux/cdevErrReqObject.o b/src/lib/.shobj/Linux/cdevErrReqObject.o new file mode 100644 index 0000000..e407ae8 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevErrReqObject.o differ diff --git a/src/lib/.shobj/Linux/cdevErrSvc.o b/src/lib/.shobj/Linux/cdevErrSvc.o new file mode 100644 index 0000000..af16259 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevErrSvc.o differ diff --git a/src/lib/.shobj/Linux/cdevError.o b/src/lib/.shobj/Linux/cdevError.o new file mode 100644 index 0000000..e6e821b Binary files /dev/null and b/src/lib/.shobj/Linux/cdevError.o differ diff --git a/src/lib/.shobj/Linux/cdevErrorCollection.o b/src/lib/.shobj/Linux/cdevErrorCollection.o new file mode 100644 index 0000000..a7b43c1 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevErrorCollection.o differ diff --git a/src/lib/.shobj/Linux/cdevExecGroup.o b/src/lib/.shobj/Linux/cdevExecGroup.o new file mode 100644 index 0000000..5e181cb Binary files /dev/null and b/src/lib/.shobj/Linux/cdevExecGroup.o differ diff --git a/src/lib/.shobj/Linux/cdevExecObj.o b/src/lib/.shobj/Linux/cdevExecObj.o new file mode 100644 index 0000000..436898b Binary files /dev/null and b/src/lib/.shobj/Linux/cdevExecObj.o differ diff --git a/src/lib/.shobj/Linux/cdevFdSet.o b/src/lib/.shobj/Linux/cdevFdSet.o new file mode 100644 index 0000000..5129458 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevFdSet.o differ diff --git a/src/lib/.shobj/Linux/cdevGlobalTagTable.o b/src/lib/.shobj/Linux/cdevGlobalTagTable.o new file mode 100644 index 0000000..f9ccaea Binary files /dev/null and b/src/lib/.shobj/Linux/cdevGlobalTagTable.o differ diff --git a/src/lib/.shobj/Linux/cdevGroup.o b/src/lib/.shobj/Linux/cdevGroup.o new file mode 100644 index 0000000..2f4ae0d Binary files /dev/null and b/src/lib/.shobj/Linux/cdevGroup.o differ diff --git a/src/lib/.shobj/Linux/cdevGrpCollectionRequest.o b/src/lib/.shobj/Linux/cdevGrpCollectionRequest.o new file mode 100644 index 0000000..da50cda Binary files /dev/null and b/src/lib/.shobj/Linux/cdevGrpCollectionRequest.o differ diff --git a/src/lib/.shobj/Linux/cdevIOcontext.o b/src/lib/.shobj/Linux/cdevIOcontext.o new file mode 100644 index 0000000..8bd187d Binary files /dev/null and b/src/lib/.shobj/Linux/cdevIOcontext.o differ diff --git a/src/lib/.shobj/Linux/cdevIntHash.o b/src/lib/.shobj/Linux/cdevIntHash.o new file mode 100644 index 0000000..b1c589f Binary files /dev/null and b/src/lib/.shobj/Linux/cdevIntHash.o differ diff --git a/src/lib/.shobj/Linux/cdevRequestObject.o b/src/lib/.shobj/Linux/cdevRequestObject.o new file mode 100644 index 0000000..1fe5467 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevRequestObject.o differ diff --git a/src/lib/.shobj/Linux/cdevService.o b/src/lib/.shobj/Linux/cdevService.o new file mode 100644 index 0000000..c46a5c8 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevService.o differ diff --git a/src/lib/.shobj/Linux/cdevSlist.o b/src/lib/.shobj/Linux/cdevSlist.o new file mode 100644 index 0000000..1278be1 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevSlist.o differ diff --git a/src/lib/.shobj/Linux/cdevStrHash.o b/src/lib/.shobj/Linux/cdevStrHash.o new file mode 100644 index 0000000..4d03ae4 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevStrHash.o differ diff --git a/src/lib/.shobj/Linux/cdevSvcConfig.o b/src/lib/.shobj/Linux/cdevSvcConfig.o new file mode 100644 index 0000000..1933735 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevSvcConfig.o differ diff --git a/src/lib/.shobj/Linux/cdevSvcFinder.o b/src/lib/.shobj/Linux/cdevSvcFinder.o new file mode 100644 index 0000000..a35f36c Binary files /dev/null and b/src/lib/.shobj/Linux/cdevSvcFinder.o differ diff --git a/src/lib/.shobj/Linux/cdevSync.o b/src/lib/.shobj/Linux/cdevSync.o new file mode 100644 index 0000000..7d70dd0 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevSync.o differ diff --git a/src/lib/.shobj/Linux/cdevSystem.o b/src/lib/.shobj/Linux/cdevSystem.o new file mode 100644 index 0000000..e095ae5 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevSystem.o differ diff --git a/src/lib/.shobj/Linux/cdevSystemBase.o b/src/lib/.shobj/Linux/cdevSystemBase.o new file mode 100644 index 0000000..eb39e79 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevSystemBase.o differ diff --git a/src/lib/.shobj/Linux/cdevTagTable.o b/src/lib/.shobj/Linux/cdevTagTable.o new file mode 100644 index 0000000..ae0a74e Binary files /dev/null and b/src/lib/.shobj/Linux/cdevTagTable.o differ diff --git a/src/lib/.shobj/Linux/cdevTimeValue.o b/src/lib/.shobj/Linux/cdevTimeValue.o new file mode 100644 index 0000000..61f102d Binary files /dev/null and b/src/lib/.shobj/Linux/cdevTimeValue.o differ diff --git a/src/lib/.shobj/Linux/cdevTimerQueue.o b/src/lib/.shobj/Linux/cdevTimerQueue.o new file mode 100644 index 0000000..0e5a1fa Binary files /dev/null and b/src/lib/.shobj/Linux/cdevTimerQueue.o differ diff --git a/src/lib/.shobj/Linux/cdevTranObj.o b/src/lib/.shobj/Linux/cdevTranObj.o new file mode 100644 index 0000000..f94bc0a Binary files /dev/null and b/src/lib/.shobj/Linux/cdevTranObj.o differ diff --git a/src/lib/.shobj/Linux/cdevUserFdService.o b/src/lib/.shobj/Linux/cdevUserFdService.o new file mode 100644 index 0000000..971c039 Binary files /dev/null and b/src/lib/.shobj/Linux/cdevUserFdService.o differ diff --git a/src/lib/.shobj/Linux/defCallbackCollector.o b/src/lib/.shobj/Linux/defCallbackCollector.o new file mode 100644 index 0000000..8fe9ef9 Binary files /dev/null and b/src/lib/.shobj/Linux/defCallbackCollector.o differ diff --git a/src/lib/.shobj/Linux/grpCallbackCollector.o b/src/lib/.shobj/Linux/grpCallbackCollector.o new file mode 100644 index 0000000..3c4e9ac Binary files /dev/null and b/src/lib/.shobj/Linux/grpCallbackCollector.o differ diff --git a/src/lib/.shobj/Linux/shObjLoader.o b/src/lib/.shobj/Linux/shObjLoader.o new file mode 100644 index 0000000..0246d3c Binary files /dev/null and b/src/lib/.shobj/Linux/shObjLoader.o differ diff --git a/src/lib/Makefile b/src/lib/Makefile new file mode 100755 index 0000000..d862cea --- /dev/null +++ b/src/lib/Makefile @@ -0,0 +1,135 @@ +# Makefile +# +# cdev library directory Makefile +# cdev version 1.1.0 +# +# Makefile,v +# Revision 1.29 1998/02/13 14:03:56 chen +# add cdevDirRequestObj +# +# Revision 1.28 1998/02/10 18:06:04 chen +# add system timer handler +# +# Revision 1.27 1998/01/30 13:50:04 akers +# Ongoing development +# +# Revision 1.26 1998/01/14 14:27:35 chen +# add cdevMonitorObj +# +# Revision 1.25 1997/12/17 15:08:31 akers +# Added mkdir for CDEVLIB +# +# Revision 1.24 1997/08/27 18:24:52 chen +# add cdevConfigFinder +# +# Revision 1.23 1997/04/02 17:54:08 akers +# Ongoing Development of CDEV 1.6 +# +# Revision 1.22 1997/03/25 22:24:42 akers +# Development in support of a new cdevDirectory +# +# Revision 1.21 1997/03/03 17:36:13 chen +# add buffering to channel access connection +# +# Revision 1.19 1996/11/21 17:03:25 akers +# Ongoing Developement of CDEV 1.5 +# +# Revision 1.18 1996/09/20 12:24:54 akers +# Changes added for Release 1.4 +# +# Revision 1.16 1996/06/26 15:54:17 akers +# Modifications to support multiple OS Versions +# +# Revision 1.15 1996/05/14 20:38:13 akers +# Makefile modifications +# +# Revision 1.14 1996/03/22 16:34:04 chen +# support solaris +# +# Revision 1.13 1996/02/23 16:55:34 danjin +# add cls.o +# +# Revision 1.12 1995/12/14 19:10:51 chen +# add support for C interface +# +# Revision 1.11 1995/12/08 15:27:55 chen +# change to add more files +# +# Revision 1.10 1995/11/14 17:42:37 chen +# new makefile +# +# +include ../Makefile.config + +ifeq ($(INCDIR), ) + INCDIR = ../.. +endif + +ifeq ($(SHOBJ),YES) + OBJTYPE=.shobj/$(TARGETDIR) +else + OBJTYPE=.obj/$(TARGETDIR) +endif + +OBJS = $(OBJTYPE)/cdevFdSet.o \ + $(OBJTYPE)/cdevTimeValue.o \ + $(OBJTYPE)/cdevCallback.o \ + $(OBJTYPE)/cdevClock.o \ + $(OBJTYPE)/cdevTimerQueue.o \ + $(OBJTYPE)/cdevSlist.o \ + $(OBJTYPE)/cdevStrHash.o \ + $(OBJTYPE)/cdevIntHash.o \ + $(OBJTYPE)/cdevData.o \ + $(OBJTYPE)/cdevDataEntry.o \ + $(OBJTYPE)/cdevTagTable.o \ + $(OBJTYPE)/cdevGlobalTagTable.o \ + $(OBJTYPE)/cdevDevice.o \ + $(OBJTYPE)/cdevDirectory.o \ + $(OBJTYPE)/cdevDirRequestObj.o \ + $(OBJTYPE)/cdevDirectoryTable.o \ + $(OBJTYPE)/cdevDirectoryTool.o \ + $(OBJTYPE)/cdevErrReqObject.o \ + $(OBJTYPE)/cdevErrSvc.o \ + $(OBJTYPE)/cdevError.o \ + $(OBJTYPE)/cdevGroup.o \ + $(OBJTYPE)/cdevExecGroup.o \ + $(OBJTYPE)/cdevIOcontext.o \ + $(OBJTYPE)/cdevRequestObject.o \ + $(OBJTYPE)/cdevCollection.o \ + $(OBJTYPE)/cdevGrpCollectionRequest.o \ + $(OBJTYPE)/cdevCollectionRequest.o \ + $(OBJTYPE)/defCallbackCollector.o \ + $(OBJTYPE)/cdevDefCollectionRequest.o \ + $(OBJTYPE)/grpCallbackCollector.o \ + $(OBJTYPE)/cdevErrorCollection.o \ + $(OBJTYPE)/cdevService.o \ + $(OBJTYPE)/cdevSvcFinder.o \ + $(OBJTYPE)/cdevSvcConfig.o \ + $(OBJTYPE)/cdevSync.o \ + $(OBJTYPE)/cdevSystem.o \ + $(OBJTYPE)/cdevSystemBase.o \ + $(OBJTYPE)/cdevUserFdService.o \ + $(OBJTYPE)/cdevConfigFinder.o \ + $(OBJTYPE)/cdevTranObj.o \ + $(OBJTYPE)/cdevExecObj.o \ + $(OBJTYPE)/shObjLoader.o \ + $(OBJTYPE)/cdevBlockList.o \ + $(OBJTYPE)/cdev.o + +ifeq ($(OS_TYPE), BSD) +OBJS := $(OBJS) $(OBJTYPE)/regexp.o $(OBJTYPE)/regsub.o $(OBJTYPE)/regerror.o +endif + +targets: $(OBJTYPE) $(LIBDIR)/$(CDEV_LIB) + +$(OBJTYPE) : + @mkdir -p $(OBJTYPE) + +$(LIBDIR)/$(CDEV_LIB): $(OBJS) + @rm -f $@ + @mkdir -p $(LIBDIR) + $(MAKELIB) $@ $(OBJS) + $(RANLIB) $@ + +clean: clean_hail + rm -rf *.o .obj .shobj diff --git a/src/lib/NMakefile.mak b/src/lib/NMakefile.mak new file mode 100755 index 0000000..9356ce1 --- /dev/null +++ b/src/lib/NMakefile.mak @@ -0,0 +1,84 @@ +include ..\NMakefile.config + +LIBDIR = ..\..\lib\$(TARGETDIR) + +OBJS = $(OBJDIR)\cdev.obj\ + $(OBJDIR)\cdevBlockList.obj\ + $(OBJDIR)\cdevCallback.obj\ + $(OBJDIR)\cdevClock.obj\ + $(OBJDIR)\cdevCollection.obj\ + $(OBJDIR)\cdevCollectionRequest.obj\ + $(OBJDIR)\cdevConfigFinder.obj\ + $(OBJDIR)\cdevData.obj\ + $(OBJDIR)\cdevDataEntry.obj\ + $(OBJDIR)\cdevDefCollectionRequest.obj\ + $(OBJDIR)\cdevDevice.obj\ + $(OBJDIR)\cdevDirRequestObj.obj\ + $(OBJDIR)\cdevDirectory.obj\ + $(OBJDIR)\cdevDirectoryTable.obj\ + $(OBJDIR)\cdevDirectoryTool.obj\ + $(OBJDIR)\cdevErrReqObject.obj\ + $(OBJDIR)\cdevErrSvc.obj\ + $(OBJDIR)\cdevError.obj\ + $(OBJDIR)\cdevErrorCollection.obj\ + $(OBJDIR)\cdevExecGroup.obj\ + $(OBJDIR)\cdevExecObj.obj\ + $(OBJDIR)\cdevFdSet.obj\ + $(OBJDIR)\cdevGlobalTagTable.obj\ + $(OBJDIR)\cdevGroup.obj\ + $(OBJDIR)\cdevGrpCollectionRequest.obj\ + $(OBJDIR)\cdevIOcontext.obj\ + $(OBJDIR)\cdevIntHash.obj\ + $(OBJDIR)\cdevRequestObject.obj\ + $(OBJDIR)\cdevService.obj\ + $(OBJDIR)\cdevSlist.obj\ + $(OBJDIR)\cdevStrHash.obj\ + $(OBJDIR)\cdevSvcFinder.obj\ + $(OBJDIR)\cdevSync.obj\ + $(OBJDIR)\cdevSystem.obj\ + $(OBJDIR)\cdevSystemBase.obj\ + $(OBJDIR)\cdevTagTable.obj\ + $(OBJDIR)\cdevTimeValue.obj\ + $(OBJDIR)\cdevTimerQueue.obj\ + $(OBJDIR)\cdevTranObj.obj\ + $(OBJDIR)\cdevUserFdService.obj\ + $(OBJDIR)\defCallbackCollector.obj\ + $(OBJDIR)\grpCallbackCollector.obj\ + $(OBJDIR)\regerror.obj\ + $(OBJDIR)\regexp.obj\ + $(OBJDIR)\regsub.obj\ + $(OBJDIR)\shObjLoader.obj\ + $(OBJDIR)\xdr.obj\ + $(OBJDIR)\xdr_array.obj\ + $(OBJDIR)\xdr_float.obj\ + $(OBJDIR)\xdr_mem.obj\ + $(OBJDIR)\xdr_rec.obj\ + $(OBJDIR)\xdr_reference.obj\ + $(OBJDIR)\xdr_stdio.obj + +!IF "$(SHOBJ)" == "NO" +TARGETS = $(LIBDIR)\cdev.lib +!ELSE +TARGETS = $(LIBDIR)\cdev.dll +!ENDIF + +targets : $(TARGETS) + +$(LIBDIR)\cdev.lib : $(OBJS) + @echo =^> Building $(@F) + @echo =^> Objects: $(?F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(LINK_LIB_FLAGS) /out:$@ $(OBJS) + @echo ^<= Done... + +$(LIBDIR)\cdev.dll : $(OBJS) + @echo =^> Building $(@F) + @echo =^> Objects: $(?F) + -@if exist $@ erase $@ + -@if not exist $(@D) mkdir $(@D) + @$(LIB32) $(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $(OBJS) + @echo ^<= Done... + @echo cdev.dll has been installed in the $(LIBDIR). + @echo Please add $(LIBDIR) to your path. + diff --git a/src/make.sh b/src/make.sh new file mode 100755 index 0000000..f7b1eb1 --- /dev/null +++ b/src/make.sh @@ -0,0 +1,6 @@ +#!/bin/sh +CDEV=/usr/local/i386-glibc22-linux/cdev-1.7.2n +CDEVINCLUDE=/usr/local/i386-glibc22-linux/cdev-1.7.2n/include +CDEVLIB=/usr/local/i386-glibc22-linux/cdev-1.7.2n/lib +CDEVSHOBJ=/usr/local/i386-glibc22-linux/cdev-1.7.2n/lib +exec make "$@" diff --git a/src/premake b/src/premake new file mode 100755 index 0000000..c3c51f9 --- /dev/null +++ b/src/premake @@ -0,0 +1,2 @@ +setenv EPICS /usr/csite4/epics/Beta8.2 +alias make `which gmake` diff --git a/src/regexp/Makefile b/src/regexp/Makefile new file mode 100755 index 0000000..63a6330 --- /dev/null +++ b/src/regexp/Makefile @@ -0,0 +1,63 @@ +# Makefile for regular expresion +# +# cdev regexp directory (not for hp) +# +# Makefile,v +# Revision 1.8 1996/09/20 12:24:58 akers +# Changes added for Release 1.4 +# +# Revision 1.5 1996/06/26 15:54:20 akers +# Modifications to support multiple OS Versions +# +# Revision 1.4 1996/05/14 20:38:22 akers +# Makefile modifications +# +# Revision 1.3 1996/03/22 16:37:42 chen +# support solaris +# +# Revision 1.2 1995/11/14 17:45:56 chen +# new makefile +# +# +include ../Makefile.config + +ifeq ($(SHOBJ),YES) + OBJTYPE=.shobj/$(TARGETDIR) +else + OBJTYPE=.obj/$(TARGETDIR) +endif + +SRC = regexp.c regsub.c regerror.c +OBJS = $(OBJTYPE)/regexp.o \ + $(OBJTYPE)/regsub.o \ + $(OBJTYPE)/regerror.o + +ifeq ($(INCDIR), ) + INCDIR = ../.. +endif + +ifeq ($(OS_TYPE), BSD) +targets: $(OBJTYPE) $(OBJDIR)/$(OBJTYPE) copyobjs copyincs +else +targets: +endif + +$(OBJTYPE) : + @mkdir -p $(OBJTYPE) + + +$(OBJDIR)/$(OBJTYPE) : + @mkdir $(OBJDIR)/$(OBJTYPE) + +regexpTest: $(OBJS) regexpTest.o + rm -f $@ + $(CC) -o $@ regexpTest.o $(OBJS) + +copyobjs: $(OBJS) + @cp -f $(OBJS) $(OBJDIR)/$(OBJTYPE) + +copyincs: + @cp -f *.h $(INCDIR) + +clean: clean_hail + @rm -rf *.o .obj .shobj core *~ regexpTest diff --git a/src/regexp/NMakefile.mak b/src/regexp/NMakefile.mak new file mode 100755 index 0000000..8c76680 --- /dev/null +++ b/src/regexp/NMakefile.mak @@ -0,0 +1,16 @@ +include ..\NMakefile.config + +OBJS = $(OBJDIR)\regexp.obj \ + $(OBJDIR)\regsub.obj \ + $(OBJDIR)\regerror.obj + +targets : copyobjs copyincs + +copyobjs : $(OBJS) + -@if not exist ..\lib\$(OBJDIR) mkdir ..\lib\$(OBJDIR) + -@for %x in ($(OBJDIR)\*.obj) DO @copy %x ..\lib\$(OBJDIR) > nul + +copyincs : + -@for %x in (*.h *.i) DO @copy %x $(CDEV)\include > nul + + diff --git a/src/regexp/README b/src/regexp/README new file mode 100755 index 0000000..7153688 --- /dev/null +++ b/src/regexp/README @@ -0,0 +1,92 @@ +This directory contains Henry Spencer's regexp library, slightly modified by +Juan D. Martin (juando@cnm.us.es) for use with xfm. The contents of this +directory are _not_ covered by the GPL, but are copyright the University of +Toronto. The original README file with the exact licensing conditions is +included below. + +---------------------------------------------------------------------------- + +This is a nearly-public-domain reimplementation of the V8 regexp(3) package. +It gives C programs the ability to use egrep-style regular expressions, and +does it in a much cleaner fashion than the analogous routines in SysV. + + Copyright (c) 1986 by University of Toronto. + Written by Henry Spencer. Not derived from licensed software. + + Permission is granted to anyone to use this software for any + purpose on any computer system, and to redistribute it freely, + subject to the following restrictions: + + 1. The author is not responsible for the consequences of use of + this software, no matter how awful, even if they arise + from defects in it. + + 2. The origin of this software must not be misrepresented, either + by explicit claim or by omission. + + 3. Altered versions must be plainly marked as such, and must not + be misrepresented as being the original software. + +Barring a couple of small items in the BUGS list, this implementation is +believed 100% compatible with V8. It should even be binary-compatible, +sort of, since the only fields in a "struct regexp" that other people have +any business touching are declared in exactly the same way at the same +location in the struct (the beginning). + +This implementation is *NOT* AT&T/Bell code, and is not derived from licensed +software. Even though U of T is a V8 licensee. This software is based on +a V8 manual page sent to me by Dennis Ritchie (the manual page enclosed +here is a complete rewrite and hence is not covered by AT&T copyright). +The software was nearly complete at the time of arrival of our V8 tape. +I haven't even looked at V8 yet, although a friend elsewhere at U of T has +been kind enough to run a few test programs using the V8 regexp(3) to resolve +a few fine points. I admit to some familiarity with regular-expression +implementations of the past, but the only one that this code traces any +ancestry to is the one published in Kernighan & Plauger (from which this +one draws ideas but not code). + +Simplistically: put this stuff into a source directory, copy regexp.h into +/usr/include, inspect Makefile for compilation options that need changing +to suit your local environment, and then do "make r". This compiles the +regexp(3) functions, compiles a test program, and runs a large set of +regression tests. If there are no complaints, then put regexp.o, regsub.o, +and regerror.o into your C library, and regexp.3 into your manual-pages +directory. + +Note that if you don't put regexp.h into /usr/include *before* compiling, +you'll have to add "-I." to CFLAGS before compiling. + +The files are: + +Makefile instructions to make everything +regexp.3 manual page +regexp.h header file, for /usr/include +regexp.c source for regcomp() and regexec() +regsub.c source for regsub() +regerror.c source for default regerror() +regmagic.h internal header file +try.c source for test program +timer.c source for timing program +tests test list for try and timer + +This implementation uses nondeterministic automata rather than the +deterministic ones found in some other implementations, which makes it +simpler, smaller, and faster at compiling regular expressions, but slower +at executing them. In theory, anyway. This implementation does employ +some special-case optimizations to make the simpler cases (which do make +up the bulk of regular expressions actually used) run quickly. In general, +if you want blazing speed you're in the wrong place. Replacing the insides +of egrep with this stuff is probably a mistake; if you want your own egrep +you're going to have to do a lot more work. But if you want to use regular +expressions a little bit in something else, you're in luck. Note that many +existing text editors use nondeterministic regular-expression implementations, +so you're in good company. + +This stuff should be pretty portable, given appropriate option settings. +If your chars have less than 8 bits, you're going to have to change the +internal representation of the automaton, although knowledge of the details +of this is fairly localized. There are no "reserved" char values except for +NUL, and no special significance is attached to the top bit of chars. +The string(3) functions are used a fair bit, on the grounds that they are +probably faster than coding the operations in line. Some attempts at code +tuning have been made, but this is invariably a bit machine-specific. diff --git a/src/regexp/regerror.c b/src/regexp/regerror.c new file mode 100755 index 0000000..f392e80 --- /dev/null +++ b/src/regexp/regerror.c @@ -0,0 +1,12 @@ +#include + +void +#if defined (__STDC__) || defined (__cplusplus) +regerror(char* s) +#else +regerror(s) +char *s; +#endif +{ + fprintf(stderr, "regexp(3): %s", s); +} diff --git a/src/regexp/regexp.3 b/src/regexp/regexp.3 new file mode 100755 index 0000000..b25fb4b --- /dev/null +++ b/src/regexp/regexp.3 @@ -0,0 +1,315 @@ +.\" Copyright 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)regexp.3 5.2 (Berkeley) 4/20/91 +.\" +.Dd April 20, 1991 +.Dt REGEXP 3 +.Os +.Sh NAME +.Nm regcomp , +.Nm regexec , +.Nm regsub , +.Nm regerror +.Nd regular expression handlers +.Sh SYNOPSIS +.Fd #include +.Ft regexp * +.Fn regcomp "const char *exp" +.Ft int +.Fn regexec "const regexp *prog" "const char *string" +.Ft void +.Fn regsub "const regexp *prog" "const char *source" "char *dest" +.Sh DESCRIPTION +The +.Fn regcomp , +.Fn regexec , +.Fn regsub , +and +.Fn regerror +functions +implement +.Xr egrep 1 Ns -style +regular expressions and supporting facilities. +.Pp +The +.Fn regcomp +function +compiles a regular expression into a structure of type +.Xr regexp , +and returns a pointer to it. +The space has been allocated using +.Xr malloc 3 +and may be released by +.Xr free . +.Pp +The +.Fn regexec +function +matches a +.Dv NUL Ns -terminated +.Fa string +against the compiled regular expression +in +.Fa prog . +It returns 1 for success and 0 for failure, and adjusts the contents of +.Fa prog Ns 's +.Em startp +and +.Em endp +(see below) accordingly. +.Pp +The members of a +.Xr regexp +structure include at least the following (not necessarily in order): +.Bd -literal -offset indent +char *startp[NSUBEXP]; +char *endp[NSUBEXP]; +.Ed +.Pp +where +.Dv NSUBEXP +is defined (as 10) in the header file. +Once a successful +.Fn regexec +has been done using the +.Fn regexp , +each +.Em startp Ns - Em endp +pair describes one substring +within the +.Fa string , +with the +.Em startp +pointing to the first character of the substring and +the +.Em endp +pointing to the first character following the substring. +The 0th substring is the substring of +.Fa string +that matched the whole +regular expression. +The others are those substrings that matched parenthesized expressions +within the regular expression, with parenthesized expressions numbered +in left-to-right order of their opening parentheses. +.Pp +The +.Fn regsub +function +copies +.Fa source +to +.Fa dest , +making substitutions according to the +most recent +.Fn regexec +performed using +.Fa prog . +Each instance of `&' in +.Fa source +is replaced by the substring +indicated by +.Em startp Ns Bq +and +.Em endp Ns Bq . +Each instance of +.Sq \e Ns Em n , +where +.Em n +is a digit, is replaced by +the substring indicated by +.Em startp Ns Bq Em n +and +.Em endp Ns Bq Em n . +To get a literal `&' or +.Sq \e Ns Em n +into +.Fa dest , +prefix it with `\e'; +to get a literal `\e' preceding `&' or +.Sq \e Ns Em n , +prefix it with +another `\e'. +.Pp +The +.Fn regerror +function +is called whenever an error is detected in +.Fn regcomp , +.Fn regexec , +or +.Fn regsub . +The default +.Fn regerror +writes the string +.Fa msg , +with a suitable indicator of origin, +on the standard +error output +and invokes +.Xr exit 2 . +The +.Fn regerror +function +can be replaced by the user if other actions are desirable. +.Sh REGULAR EXPRESSION SYNTAX +A regular expression is zero or more +.Em branches , +separated by `|'. +It matches anything that matches one of the branches. +.Pp +A branch is zero or more +.Em pieces , +concatenated. +It matches a match for the first, followed by a match for the second, etc. +.Pp +A piece is an +.Em atom +possibly followed by `*', `+', or `?'. +An atom followed by `*' matches a sequence of 0 or more matches of the atom. +An atom followed by `+' matches a sequence of 1 or more matches of the atom. +An atom followed by `?' matches a match of the atom, or the null string. +.Pp +An atom is a regular expression in parentheses (matching a match for the +regular expression), a +.Em range +(see below), `.' +(matching any single character), `^' (matching the null string at the +beginning of the input string), `$' (matching the null string at the +end of the input string), a `\e' followed by a single character (matching +that character), or a single character with no other significance +(matching that character). +.Pp +A +.Em range +is a sequence of characters enclosed in `[]'. +It normally matches any single character from the sequence. +If the sequence begins with `^', +it matches any single character +.Em not +from the rest of the sequence. +If two characters in the sequence are separated by `\-', this is shorthand +for the full list of +.Tn ASCII +characters between them +(e.g. `[0-9]' matches any decimal digit). +To include a literal `]' in the sequence, make it the first character +(following a possible `^'). +To include a literal `\-', make it the first or last character. +.Sh AMBIGUITY +If a regular expression could match two different parts of the input string, +it will match the one which begins earliest. +If both begin in the same place but match different lengths, or match +the same length in different ways, life gets messier, as follows. +.Pp +In general, the possibilities in a list of branches are considered in +left-to-right order, the possibilities for `*', `+', and `?' are +considered longest-first, nested constructs are considered from the +outermost in, and concatenated constructs are considered leftmost-first. +The match that will be chosen is the one that uses the earliest +possibility in the first choice that has to be made. +If there is more than one choice, the next will be made in the same manner +(earliest possibility) subject to the decision on the first choice. +And so forth. +.Pp +For example, +.Sq Li (ab|a)b*c +could match +`abc' in one of two ways. +The first choice is between `ab' and `a'; since `ab' is earlier, and does +lead to a successful overall match, it is chosen. +Since the `b' is already spoken for, +the `b*' must match its last possibility\(emthe empty string\(emsince +it must respect the earlier choice. +.Pp +In the particular case where no `|'s are present and there is only one +`*', `+', or `?', the net effect is that the longest possible +match will be chosen. +So +.Sq Li ab* , +presented with `xabbbby', will match `abbbb'. +Note that if +.Sq Li ab* , +is tried against `xabyabbbz', it +will match `ab' just after `x', due to the begins-earliest rule. +(In effect, the decision on where to start the match is the first choice +to be made, hence subsequent choices must respect it even if this leads them +to less-preferred alternatives.) +.Sh RETURN VALUES +The +.Fn regcomp +function +returns +.Dv NULL +for a failure +.Pf ( Fn regerror +permitting), +where failures are syntax errors, exceeding implementation limits, +or applying `+' or `*' to a possibly-null operand. +.Sh SEE ALSO +.Xr ed 1 , +.Xr ex 1 , +.Xr expr 1 , +.Xr egrep 1 , +.Xr fgrep 1 , +.Xr grep 1 , +.Xr regex 3 +.Sh HISTORY +Both code and manual page for +.Fn regcomp , +.Fn regexec , +.Fn regsub , +and +.Fn regerror +were written at the University of Toronto +and appeared in +.Bx 4.3 tahoe . +They are intended to be compatible with the Bell V8 +.Xr regexp 3 , +but are not derived from Bell code. +.Sh BUGS +Empty branches and empty regular expressions are not portable to V8. +.Pp +The restriction against +applying `*' or `+' to a possibly-null operand is an artifact of the +simplistic implementation. +.Pp +Does not support +.Xr egrep Ns 's +newline-separated branches; +neither does the V8 +.Xr regexp 3 , +though. +.Pp +Due to emphasis on +compactness and simplicity, +it's not strikingly fast. +It does give special attention to handling simple cases quickly. diff --git a/src/regexp/regexp.c b/src/regexp/regexp.c new file mode 100755 index 0000000..777157f --- /dev/null +++ b/src/regexp/regexp.c @@ -0,0 +1,1318 @@ +/* + * regcomp and regexec -- regsub and regerror are elsewhere + * + * Copyright (c) 1986 by University of Toronto. + * Written by Henry Spencer. Not derived from licensed software. + * + * Permission is granted to anyone to use this software for any + * purpose on any computer system, and to redistribute it freely, + * subject to the following restrictions: + * + * 1. The author is not responsible for the consequences of use of + * this software, no matter how awful, even if they arise + * from defects in it. + * + * 2. The origin of this software must not be misrepresented, either + * by explicit claim or by omission. + * + * 3. Altered versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * + * Beware that some of this code is subtly aware of the way operator + * precedence is structured in regular expressions. Serious changes in + * regular-expression syntax might require a total rethink. + */ +#include +#include +#include "regexp.h" +#include "regmagic.h" + +/* + * The "internal use only" fields in regexp.h are present to pass info from + * compile to execute that permits the execute phase to run lots faster on + * simple cases. They are: + * + * regstart char that must begin a match; '\0' if none obvious + * reganch is the match anchored (at beginning-of-line only)? + * regmust string (pointer into program) that match must include, or NULL + * regmlen length of regmust string + * + * Regstart and reganch permit very fast decisions on suitable starting points + * for a match, cutting down the work a lot. Regmust permits fast rejection + * of lines that cannot possibly match. The regmust tests are costly enough + * that regcomp() supplies a regmust only if the r.e. contains something + * potentially expensive (at present, the only such thing detected is * or + + * at the start of the r.e., which can involve a lot of backup). Regmlen is + * supplied because the test in regexec() needs it and regcomp() is computing + * it anyway. + */ + +/* + * Structure for regexp "program". This is essentially a linear encoding + * of a nondeterministic finite-state machine (aka syntax charts or + * "railroad normal form" in parsing technology). Each node is an opcode + * plus a "next" pointer, possibly plus an operand. "Next" pointers of + * all nodes except BRANCH implement concatenation; a "next" pointer with + * a BRANCH on both ends of it is connecting two alternatives. (Here we + * have one of the subtle syntax dependencies: an individual BRANCH (as + * opposed to a collection of them) is never concatenated with anything + * because of operator precedence.) The operand of some types of node is + * a literal string; for others, it is a node leading into a sub-FSM. In + * particular, the operand of a BRANCH node is the first node of the branch. + * (NB this is *not* a tree structure: the tail of the branch connects + * to the thing following the set of BRANCHes.) The opcodes are: + */ + +/* definition number opnd? meaning */ +#define END 0 /* no End of program. */ +#define BOL 1 /* no Match "" at beginning of line. */ +#define EOL 2 /* no Match "" at end of line. */ +#define ANY 3 /* no Match any one character. */ +#define ANYOF 4 /* str Match any character in this string. */ +#define ANYBUT 5 /* str Match any character not in this string. */ +#define BRANCH 6 /* node Match this alternative, or the next... */ +#define BACK 7 /* no Match "", "next" ptr points backward. */ +#define EXACTLY 8 /* str Match this string. */ +#define NOTHING 9 /* no Match empty string. */ +#define STAR 10 /* node Match this (simple) thing 0 or more times. */ +#define PLUS 11 /* node Match this (simple) thing 1 or more times. */ +#define OPEN 20 /* no Mark this point in input as start of #n. */ + /* OPEN+1 is number 1, etc. */ +#define CLOSE 30 /* no Analogous to OPEN. */ + +/* + * Opcode notes: + * + * BRANCH The set of branches constituting a single choice are hooked + * together with their "next" pointers, since precedence prevents + * anything being concatenated to any individual branch. The + * "next" pointer of the last BRANCH in a choice points to the + * thing following the whole choice. This is also where the + * final "next" pointer of each individual branch points; each + * branch starts with the operand node of a BRANCH node. + * + * BACK Normal "next" pointers all implicitly point forward; BACK + * exists to make loop structures possible. + * + * STAR,PLUS '?', and complex '*' and '+', are implemented as circular + * BRANCH structures using BACK. Simple cases (one character + * per match) are implemented with STAR and PLUS for speed + * and to minimize recursive plunges. + * + * OPEN,CLOSE ...are numbered at compile time. + */ + +/* + * A node is one char of opcode followed by two chars of "next" pointer. + * "Next" pointers are stored as two 8-bit pieces, high order first. The + * value is a positive offset from the opcode of the node containing it. + * An operand, if any, simply follows the node. (Note that much of the + * code generation knows about this implicit relationship.) + * + * Using two bytes for the "next" pointer is vast overkill for most things, + * but allows patterns to get big without disasters. + */ +#define OP(p) (*(p)) +#define NEXT(p) (((*((p)+1)&0377)<<8) + *((p)+2)&0377) +#define OPERAND(p) ((p) + 3) + +/* + * See regmagic.h for one further detail of program structure. + */ + + +/* + * Utility definitions. + */ +#ifndef CHARBITS +#define UCHARAT(p) ((int)*(unsigned char *)(p)) +#else +#define UCHARAT(p) ((int)*(p)&CHARBITS) +#endif + +#define FAIL(m) { regerror(m); return(NULL); } +#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') +#define META "^$.[()|?+*\\" + +/* + * Flags to be passed up and down. + */ +#define HASWIDTH 01 /* Known never to match null string. */ +#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ +#define SPSTART 04 /* Starts with * or +. */ +#define WORST 0 /* Worst case. */ + +/* + * Global work variables for regcomp(). + */ +static char *regparse; /* Input-scan pointer. */ +static int regnpar; /* () count. */ +static char regdummy; +static char *regcode; /* Code-emit pointer; ®dummy = don't. */ +static long regsize; /* Code size. */ + +/* + * Forward declarations for regcomp()'s friends. + */ +#ifndef STATIC +#define STATIC static +#endif + +#if defined (__STDC__) || defined (__cplusplus) +STATIC char *reg(int paren, int* flagp); +STATIC char *regbranch(int* flagp); +STATIC char *regpiece(int* flagp); +STATIC char *regatom(int* flagp); +STATIC char *regnode(char op); +STATIC char *regnext(register char* p); +STATIC void regc(char b); +STATIC void reginsert(char op, char* oprnd); +STATIC void regtail(char* p, char *val); +STATIC void regoptail(char* p, char *val); +#ifdef STRCSPN +STATIC int strcspn(char* s1, char* s2); +#endif +#else +STATIC char *reg(); +STATIC char *regbranch(); +STATIC char *regpiece(); +STATIC char *regatom(); +STATIC char *regnode(); +STATIC char *regnext(); +STATIC void regc(); +STATIC void reginsert(); +STATIC void regtail(); +STATIC void regoptail(); +#ifdef STRCSPN +STATIC int strcspn(); +#endif + +#endif + + +/* + - regcomp - compile a regular expression into internal code + * + * We can't allocate space until we know how big the compiled form will be, + * but we can't compile it (and thus know how big it is) until we've got a + * place to put the code. So we cheat: we compile it twice, once with code + * generation turned off and size counting turned on, and once "for real". + * This also means that we don't allocate space until we are sure that the + * thing really will compile successfully, and we never have to move the + * code and thus invalidate pointers into it. (Note that it has to be in + * one piece because free() must be able to free it all.) + * + * Beware that the optimization-preparation code in here knows about some + * of the structure of the compiled regexp. + */ +regexp * +#if defined (__STDC__) || defined (__cplusplus) +regcomp(char *exp) +#else +regcomp(exp) +char *exp; +#endif +{ + register regexp *r; + register char *scan; + register char *longest; + register int len; + int flags; + + if (exp == NULL) + FAIL("NULL argument"); + + /* First pass: determine size, legality. */ + regparse = exp; + regnpar = 1; + regsize = 0L; + regcode = ®dummy; + regc(MAGIC); + if (reg(0, &flags) == NULL) + return(NULL); + + /* Small enough for pointer-storage convention? */ + if (regsize >= 32767L) /* Probably could be 65535L. */ + FAIL("regexp too big"); + + /* Allocate space. */ + r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize); + if (r == NULL) + FAIL("out of space"); + + /* Second pass: emit code. */ + regparse = exp; + regnpar = 1; + regcode = r->program; + regc(MAGIC); + if (reg(0, &flags) == NULL) + return(NULL); + + /* Dig out information for optimizations. */ + r->regstart = '\0'; /* Worst-case defaults. */ + r->reganch = 0; + r->regmust = NULL; + r->regmlen = 0; + scan = r->program+1; /* First BRANCH. */ + if (OP(regnext(scan)) == END) { /* Only one top-level choice. */ + scan = OPERAND(scan); + + /* Starting-point info. */ + if (OP(scan) == EXACTLY) + r->regstart = *OPERAND(scan); + else if (OP(scan) == BOL) + r->reganch++; + + /* + * If there's something expensive in the r.e., find the + * longest literal string that must appear and make it the + * regmust. Resolve ties in favor of later strings, since + * the regstart check works with the beginning of the r.e. + * and avoiding duplication strengthens checking. Not a + * strong reason, but sufficient in the absence of others. + */ + if (flags&SPSTART) { + longest = NULL; + len = 0; + for (; scan != NULL; scan = regnext(scan)) + if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) { + longest = OPERAND(scan); + len = strlen(OPERAND(scan)); + } + r->regmust = longest; + r->regmlen = len; + } + } + + return(r); +} + +/* + - reg - regular expression, i.e. main body or parenthesized thing + * + * Caller must absorb opening parenthesis. + * + * Combining parenthesis handling with the base level of regular expression + * is a trifle forced, but the need to tie the tails of the branches to what + * follows makes it hard to avoid. + */ +static char * +#if defined (__STDC__) || defined (__cplusplus) +reg(int paren, int* flagp) +#else +reg(paren, flagp) +int paren; /* Parenthesized? */ +int *flagp; +#endif +{ + register char *ret; + register char *br; + register char *ender; + register int parno; + int flags; + + *flagp = HASWIDTH; /* Tentatively. */ + + /* Make an OPEN node, if parenthesized. */ + if (paren) { + if (regnpar >= NSUBEXP) + FAIL("too many ()"); + parno = regnpar; + regnpar++; + ret = regnode(OPEN+parno); + } else + ret = NULL; + + /* Pick up the branches, linking them together. */ + br = regbranch(&flags); + if (br == NULL) + return(NULL); + if (ret != NULL) + regtail(ret, br); /* OPEN -> first. */ + else + ret = br; + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + while (*regparse == '|') { + regparse++; + br = regbranch(&flags); + if (br == NULL) + return(NULL); + regtail(ret, br); /* BRANCH -> BRANCH. */ + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + } + + /* Make a closing node, and hook it on the end. */ + ender = regnode((paren) ? CLOSE+parno : END); + regtail(ret, ender); + + /* Hook the tails of the branches to the closing node. */ + for (br = ret; br != NULL; br = regnext(br)) + regoptail(br, ender); + + /* Check for proper termination. */ + if (paren && *regparse++ != ')') { + FAIL("unmatched ()"); + } else if (!paren && *regparse != '\0') { + if (*regparse == ')') { + FAIL("unmatched ()"); + } else + FAIL("junk on end"); /* "Can't happen". */ + /* NOTREACHED */ + } + + return(ret); +} + +/* + - regbranch - one alternative of an | operator + * + * Implements the concatenation operator. + */ +static char * +#if defined (__STDC__) || (__cplusplus) +regbranch(int* flagp) +#else +regbranch(flagp) +int *flagp; +#endif +{ + register char *ret; + register char *chain; + register char *latest; + int flags; + + *flagp = WORST; /* Tentatively. */ + + ret = regnode(BRANCH); + chain = NULL; + while (*regparse != '\0' && *regparse != '|' && *regparse != ')') { + latest = regpiece(&flags); + if (latest == NULL) + return(NULL); + *flagp |= flags&HASWIDTH; + if (chain == NULL) /* First piece. */ + *flagp |= flags&SPSTART; + else + regtail(chain, latest); + chain = latest; + } + if (chain == NULL) /* Loop ran zero times. */ + (void) regnode(NOTHING); + + return(ret); +} + +/* + - regpiece - something followed by possible [*+?] + * + * Note that the branching code sequences used for ? and the general cases + * of * and + are somewhat optimized: they use the same NOTHING node as + * both the endmarker for their branch list and the body of the last branch. + * It might seem that this node could be dispensed with entirely, but the + * endmarker role is not redundant. + */ +static char * +#if defined (__STDC__) || defined (__cplusplus) +regpiece(int* flagp) +#else +regpiece(flagp) +int *flagp; +#endif +{ + register char *ret; + register char op; + register char *next; + int flags; + + ret = regatom(&flags); + if (ret == NULL) + return(NULL); + + op = *regparse; + if (!ISMULT(op)) { + *flagp = flags; + return(ret); + } + + if (!(flags&HASWIDTH) && op != '?') + FAIL("*+ operand could be empty"); + *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); + + if (op == '*' && (flags&SIMPLE)) + reginsert(STAR, ret); + else if (op == '*') { + /* Emit x* as (x&|), where & means "self". */ + reginsert(BRANCH, ret); /* Either x */ + regoptail(ret, regnode(BACK)); /* and loop */ + regoptail(ret, ret); /* back */ + regtail(ret, regnode(BRANCH)); /* or */ + regtail(ret, regnode(NOTHING)); /* null. */ + } else if (op == '+' && (flags&SIMPLE)) + reginsert(PLUS, ret); + else if (op == '+') { + /* Emit x+ as x(&|), where & means "self". */ + next = regnode(BRANCH); /* Either */ + regtail(ret, next); + regtail(regnode(BACK), ret); /* loop back */ + regtail(next, regnode(BRANCH)); /* or */ + regtail(ret, regnode(NOTHING)); /* null. */ + } else if (op == '?') { + /* Emit x? as (x|) */ + reginsert(BRANCH, ret); /* Either x */ + regtail(ret, regnode(BRANCH)); /* or */ + next = regnode(NOTHING); /* null. */ + regtail(ret, next); + regoptail(ret, next); + } + regparse++; + if (ISMULT(*regparse)) + FAIL("nested *?+"); + + return(ret); +} + +/* + - regatom - the lowest level + * + * Optimization: gobbles an entire sequence of ordinary characters so that + * it can turn them into a single node, which is smaller to store and + * faster to run. Backslashed characters are exceptions, each becoming a + * separate node; the code is simpler that way and it's not worth fixing. + */ +static char * +#if defined (__STDC__) || (__cplusplus) +regatom(int* flagp) +#else +regatom(flagp) +int *flagp; +#endif +{ + register char *ret; + int flags; + + *flagp = WORST; /* Tentatively. */ + + switch (*regparse++) { + case '^': + ret = regnode(BOL); + break; + case '$': + ret = regnode(EOL); + break; + case '.': + ret = regnode(ANY); + *flagp |= HASWIDTH|SIMPLE; + break; + case '[': { + register int _class_; + register int classend; + + if (*regparse == '^') { /* Complement of range. */ + ret = regnode(ANYBUT); + regparse++; + } else + ret = regnode(ANYOF); + if (*regparse == ']' || *regparse == '-') + regc(*regparse++); + while (*regparse != '\0' && *regparse != ']') { + if (*regparse == '-') { + regparse++; + if (*regparse == ']' || *regparse == '\0') + regc('-'); + else { + _class_ = UCHARAT(regparse-2)+1; + classend = UCHARAT(regparse); + if (_class_ > classend+1) + FAIL("invalid [] range"); + for (; _class_ <= classend; _class_++) + regc(_class_); + regparse++; + } + } else + regc(*regparse++); + } + regc('\0'); + if (*regparse != ']') + FAIL("unmatched []"); + regparse++; + *flagp |= HASWIDTH|SIMPLE; + } + break; + case '(': + ret = reg(1, &flags); + if (ret == NULL) + return(NULL); + *flagp |= flags&(HASWIDTH|SPSTART); + break; + case '\0': + case '|': + case ')': + FAIL("internal urp"); /* Supposed to be caught earlier. */ + break; + case '?': + case '+': + case '*': + FAIL("?+* follows nothing"); + break; + case '\\': + if (*regparse == '\0') + FAIL("trailing \\"); + ret = regnode(EXACTLY); + regc(*regparse++); + regc('\0'); + *flagp |= HASWIDTH|SIMPLE; + break; + default: { + register int len; + register char ender; + + regparse--; + len = strcspn(regparse, META); + if (len <= 0) + FAIL("internal disaster"); + ender = *(regparse+len); + if (len > 1 && ISMULT(ender)) + len--; /* Back off clear of ?+* operand. */ + *flagp |= HASWIDTH; + if (len == 1) + *flagp |= SIMPLE; + ret = regnode(EXACTLY); + while (len > 0) { + regc(*regparse++); + len--; + } + regc('\0'); + } + break; + } + + return(ret); +} + +/* + - regnode - emit a node + */ +static char * /* Location. */ +#if defined (__STDC__) || defined (__cplusplus) +regnode(char op) +#else +regnode(op) +char op; +#endif +{ + register char *ret; + register char *ptr; + + ret = regcode; + if (ret == ®dummy) { + regsize += 3; + return(ret); + } + + ptr = ret; + *ptr++ = op; + *ptr++ = '\0'; /* Null "next" pointer. */ + *ptr++ = '\0'; + regcode = ptr; + + return(ret); +} + +/* + - regc - emit (if appropriate) a byte of code + */ +static void +#if defined (__STDC__) || defined (__cplusplus) +regc(char b) +#else +regc(b) +char b; +#endif +{ + if (regcode != ®dummy) + *regcode++ = b; + else + regsize++; +} + +/* + - reginsert - insert an operator in front of already-emitted operand + * + * Means relocating the operand. + */ +static void +#if defined (__STDC__) || defined (__cplusplus) +reginsert(char op, char* opnd) +#else +reginsert(op, opnd) +char op; +char *opnd; +#endif +{ + register char *src; + register char *dst; + register char *place; + + if (regcode == ®dummy) { + regsize += 3; + return; + } + + src = regcode; + regcode += 3; + dst = regcode; + while (src > opnd) + *--dst = *--src; + + place = opnd; /* Op node, where operand used to be. */ + *place++ = op; + *place++ = '\0'; + *place++ = '\0'; +} + +/* + - regtail - set the next-pointer at the end of a node chain + */ +static void +#if defined (__STDC__) || defined (__cplusplus) +regtail(char* p, char* val) +#else +regtail(p, val) +char *p; +char *val; +#endif +{ + register char *scan; + register char *temp; + register int offset; + + if (p == ®dummy) + return; + + /* Find last node. */ + scan = p; + for (;;) { + temp = regnext(scan); + if (temp == NULL) + break; + scan = temp; + } + + if (OP(scan) == BACK) + offset = scan - val; + else + offset = val - scan; + *(scan+1) = (offset>>8)&0377; + *(scan+2) = offset&0377; +} + +/* + - regoptail - regtail on operand of first argument; nop if operandless + */ +static void +#if defined (__STDC__) || defined (__cplusplus) +regoptail(char* p, char* val) +#else +regoptail(p, val) +char *p; +char *val; +#endif +{ + /* "Operandless" and "op != BRANCH" are synonymous in practice. */ + if (p == NULL || p == ®dummy || OP(p) != BRANCH) + return; + regtail(OPERAND(p), val); +} + +/* + * regexec and friends + */ + +/* + * Global work variables for regexec(). + */ +static char *reginput; /* String-input pointer. */ +static char *regbol; /* Beginning of input, for ^ check. */ +static char **regstartp; /* Pointer to startp array. */ +static char **regendp; /* Ditto for endp. */ + +/* + * Forwards. + */ +#if defined (__STDC__) || defined (__cplusplus) +STATIC int regtry(regexp* prog, char* string); +STATIC int regmatch(char* prog); +STATIC int regrepeat(char* p); +#else +STATIC int regtry(); +STATIC int regmatch(); +STATIC int regrepeat(); +#endif + +#ifdef DEBUG +int regnarrate = 0; +#if defined (__STDC__) || defined (__cplusplus) +void regdump(regexp* r); +STATIC char *regprop(char *op); +#else +void regdump(); +STATIC char *regprop(); +#endif + +#endif + +/* + - regexec - match a regexp against a string + */ +int +#if defined (__STDC__) || defined (__cplusplus) +regexec(register regexp* prog, register char* string) +#else +regexec(prog, string) +register regexp *prog; +register char *string; +#endif +{ + register char *s; + + /* Be paranoid... */ + if (prog == NULL || string == NULL) { + regerror("NULL parameter"); + return(0); + } + + /* Check validity of program. */ + if (UCHARAT(prog->program) != MAGIC) { + regerror("corrupted program"); + return(0); + } + + /* If there is a "must appear" string, look for it. */ + if (prog->regmust != NULL) { + s = string; + while ((s = strchr(s, prog->regmust[0])) != NULL) { + if (strncmp(s, prog->regmust, prog->regmlen) == 0) + break; /* Found it. */ + s++; + } + if (s == NULL) /* Not present. */ + return(0); + } + + /* Mark beginning of line for ^ . */ + regbol = string; + + /* Simplest case: anchored match need be tried only once. */ + if (prog->reganch) + return(regtry(prog, string)); + + /* Messy cases: unanchored match. */ + s = string; + if (prog->regstart != '\0') + /* We know what char it must start with. */ + while ((s = strchr(s, prog->regstart)) != NULL) { + if (regtry(prog, s)) + return(1); + s++; + } + else + /* We don't -- general case. */ + do { + if (regtry(prog, s)) + return(1); + } while (*s++ != '\0'); + + /* Failure. */ + return(0); +} + +/* + - regtry - try match at specific point + */ +static int /* 0 failure, 1 success */ +#if defined (__STDC__) || defined (__cplusplus) +regtry(regexp* prog, char* string) +#else +regtry(prog, string) +regexp *prog; +char *string; +#endif +{ + register int i; + register char **sp; + register char **ep; + + reginput = string; + regstartp = prog->startp; + regendp = prog->endp; + + sp = prog->startp; + ep = prog->endp; + for (i = NSUBEXP; i > 0; i--) { + *sp++ = NULL; + *ep++ = NULL; + } + if (regmatch(prog->program + 1)) { + prog->startp[0] = string; + prog->endp[0] = reginput; + return(1); + } else + return(0); +} + +/* + - regmatch - main matching routine + * + * Conceptually the strategy is simple: check to see whether the current + * node matches, call self recursively to see whether the rest matches, + * and then act accordingly. In practice we make some effort to avoid + * recursion, in particular by going through "ordinary" nodes (that don't + * need to know whether the rest of the match failed) by a loop instead of + * by recursion. + */ +static int /* 0 failure, 1 success */ +#if defined (__STDC__) || defined (__cplusplus) +regmatch(char* prog) +#else +regmatch(prog) +char *prog; +#endif +{ + register char *scan; /* Current node. */ + char *next; /* Next node. */ + + scan = prog; +#ifdef DEBUG + if (scan != NULL && regnarrate) + fprintf(stderr, "%s(\n", regprop(scan)); +#endif + while (scan != NULL) { +#ifdef DEBUG + if (regnarrate) + fprintf(stderr, "%s...\n", regprop(scan)); +#endif + next = regnext(scan); + + switch (OP(scan)) { + case BOL: + if (reginput != regbol) + return(0); + break; + case EOL: + if (*reginput != '\0') + return(0); + break; + case ANY: + if (*reginput == '\0') + return(0); + reginput++; + break; + case EXACTLY: { + register int len; + register char *opnd; + + opnd = OPERAND(scan); + /* Inline the first character, for speed. */ + if (*opnd != *reginput) + return(0); + len = strlen(opnd); + if (len > 1 && strncmp(opnd, reginput, len) != 0) + return(0); + reginput += len; + } + break; + case ANYOF: + if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL) + return(0); + reginput++; + break; + case ANYBUT: + if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL) + return(0); + reginput++; + break; + case NOTHING: + break; + case BACK: + break; + case OPEN+1: + case OPEN+2: + case OPEN+3: + case OPEN+4: + case OPEN+5: + case OPEN+6: + case OPEN+7: + case OPEN+8: + case OPEN+9: { + register int no; + register char *save; + + no = OP(scan) - OPEN; + save = reginput; + + if (regmatch(next)) { + /* + * Don't set startp if some later + * invocation of the same parentheses + * already has. + */ + if (regstartp[no] == NULL) + regstartp[no] = save; + return(1); + } else + return(0); + } + break; + case CLOSE+1: + case CLOSE+2: + case CLOSE+3: + case CLOSE+4: + case CLOSE+5: + case CLOSE+6: + case CLOSE+7: + case CLOSE+8: + case CLOSE+9: { + register int no; + register char *save; + + no = OP(scan) - CLOSE; + save = reginput; + + if (regmatch(next)) { + /* + * Don't set endp if some later + * invocation of the same parentheses + * already has. + */ + if (regendp[no] == NULL) + regendp[no] = save; + return(1); + } else + return(0); + } + break; + case BRANCH: { + register char *save; + + if (OP(next) != BRANCH) /* No choice. */ + next = OPERAND(scan); /* Avoid recursion. */ + else { + do { + save = reginput; + if (regmatch(OPERAND(scan))) + return(1); + reginput = save; + scan = regnext(scan); + } while (scan != NULL && OP(scan) == BRANCH); + return(0); + /* NOTREACHED */ + } + } + break; + case STAR: + case PLUS: { + register char nextch; + register int no; + register char *save; + register int min; + + /* + * Lookahead to avoid useless match attempts + * when we know what character comes next. + */ + nextch = '\0'; + if (OP(next) == EXACTLY) + nextch = *OPERAND(next); + min = (OP(scan) == STAR) ? 0 : 1; + save = reginput; + no = regrepeat(OPERAND(scan)); + while (no >= min) { + /* If it could work, try it. */ + if (nextch == '\0' || *reginput == nextch) + if (regmatch(next)) + return(1); + /* Couldn't or didn't -- back up. */ + no--; + reginput = save + no; + } + return(0); + } + break; + case END: + return(1); /* Success! */ + break; + default: + regerror("memory corruption"); + return(0); + break; + } + + scan = next; + } + + /* + * We get here only if there's trouble -- normally "case END" is + * the terminating point. + */ + regerror("corrupted pointers"); + return(0); +} + +/* + - regrepeat - repeatedly match something simple, report how many + */ +static int +#if defined (__STDC__) || defined (__cplusplus) +regrepeat(char* p) +#else +regrepeat(p) +char *p; +#endif +{ + register int count = 0; + register char *scan; + register char *opnd; + + scan = reginput; + opnd = OPERAND(p); + switch (OP(p)) { + case ANY: + count = strlen(scan); + scan += count; + break; + case EXACTLY: + while (*opnd == *scan) { + count++; + scan++; + } + break; + case ANYOF: + while (*scan != '\0' && strchr(opnd, *scan) != NULL) { + count++; + scan++; + } + break; + case ANYBUT: + while (*scan != '\0' && strchr(opnd, *scan) == NULL) { + count++; + scan++; + } + break; + default: /* Oh dear. Called inappropriately. */ + regerror("internal foulup"); + count = 0; /* Best compromise. */ + break; + } + reginput = scan; + + return(count); +} + +/* + - regnext - dig the "next" pointer out of a node + */ +static char * +#if defined (__STDC__) || defined (__cplusplus) +regnext(register char* p) +#else +regnext(p) +register char *p; +#endif +{ + register int offset; + + if (p == ®dummy) + return(NULL); + + offset = NEXT(p); + if (offset == 0) + return(NULL); + + if (OP(p) == BACK) + return(p-offset); + else + return(p+offset); +} + +#ifdef DEBUG + +#if defined (__STDC__) || defined (__cplusplus) +STATIC char *regprop(char* op); +#else +STATIC char *regprop(); +#endif + +/* + - regdump - dump a regexp onto stdout in vaguely comprehensible form + */ +void +#if defined (__STDC__) || defined (__cplusplus) +regdump(regexp* r) +#else +regdump(r) +regexp *r; +#endif +{ + register char *s; + register char op = EXACTLY; /* Arbitrary non-END op. */ + register char *next; + extern char *strchr(); + + + s = r->program + 1; + while (op != END) { /* While that wasn't END last time... */ + op = OP(s); + printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */ + next = regnext(s); + if (next == NULL) /* Next ptr. */ + printf("(0)"); + else + printf("(%d)", (s-r->program)+(next-s)); + s += 3; + if (op == ANYOF || op == ANYBUT || op == EXACTLY) { + /* Literal string, where present. */ + while (*s != '\0') { + putchar(*s); + s++; + } + s++; + } + putchar('\n'); + } + + /* Header fields of interest. */ + if (r->regstart != '\0') + printf("start `%c' ", r->regstart); + if (r->reganch) + printf("anchored "); + if (r->regmust != NULL) + printf("must have \"%s\"", r->regmust); + printf("\n"); +} + +/* + - regprop - printable representation of opcode + */ +static char * +#if defined (__STDC__) || defined (__cplusplus) +regprop(char *op) +#else +regprop(op) +char *op; +#endif +{ + register char *p; + static char buf[50]; + + (void) strcpy(buf, ":"); + + switch (OP(op)) { + case BOL: + p = "BOL"; + break; + case EOL: + p = "EOL"; + break; + case ANY: + p = "ANY"; + break; + case ANYOF: + p = "ANYOF"; + break; + case ANYBUT: + p = "ANYBUT"; + break; + case BRANCH: + p = "BRANCH"; + break; + case EXACTLY: + p = "EXACTLY"; + break; + case NOTHING: + p = "NOTHING"; + break; + case BACK: + p = "BACK"; + break; + case END: + p = "END"; + break; + case OPEN+1: + case OPEN+2: + case OPEN+3: + case OPEN+4: + case OPEN+5: + case OPEN+6: + case OPEN+7: + case OPEN+8: + case OPEN+9: + sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); + p = NULL; + break; + case CLOSE+1: + case CLOSE+2: + case CLOSE+3: + case CLOSE+4: + case CLOSE+5: + case CLOSE+6: + case CLOSE+7: + case CLOSE+8: + case CLOSE+9: + sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); + p = NULL; + break; + case STAR: + p = "STAR"; + break; + case PLUS: + p = "PLUS"; + break; + default: + regerror("corrupted opcode"); + break; + } + if (p != NULL) + (void) strcat(buf, p); + return(buf); +} +#endif + +/* + * The following is provided for those people who do not have strcspn() in + * their C libraries. They should get off their butts and do something + * about it; at least one public-domain implementation of those (highly + * useful) string routines has been published on Usenet. + */ +#ifdef STRCSPN +/* + * strcspn - find length of initial segment of s1 consisting entirely + * of characters not from s2 + */ + +static int +#if defined (__STDC__) || defined (__cplusplus) +strcspn(char* s1, char* s2) +#else +strcspn(s1, s2) +char *s1; +char *s2; +#endif +{ + register char *scan1; + register char *scan2; + register int count; + + count = 0; + for (scan1 = s1; *scan1 != '\0'; scan1++) { + for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */ + if (*scan1 == *scan2++) + return(count); + count++; + } + return(count); +} +#endif diff --git a/src/regexp/regexp.h b/src/regexp/regexp.h new file mode 100755 index 0000000..4dbda87 --- /dev/null +++ b/src/regexp/regexp.h @@ -0,0 +1,66 @@ +/* + * Definitions etc. for regexp(3) routines. + * + * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof], + * not the System V one. + */ + +#ifndef _CDEV_REGEXP_H +#define _CDEV_REGEXP_H +/* The following is copied directly from */ + +#ifndef X_NOT_STDC_ENV +#include +#ifndef index +#define index strchr +#endif +#ifndef rindex +#define rindex strrchr +#endif + +#else + +#ifdef SYSV +#include +#define index strchr +#define rindex strrchr +#else +#include +#define strchr index +#define strrchr rindex +#endif + +#endif /* X_NOT_STDC_ENV */ + +#define NSUBEXP 10 +typedef struct regexp { + char *startp[NSUBEXP]; + char *endp[NSUBEXP]; + char regstart; /* Internal use only. */ + char reganch; /* Internal use only. */ + char *regmust; /* Internal use only. */ + int regmlen; /* Internal use only. */ + char program[1]; /* Unwarranted chumminess with compiler. */ +} regexp; + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (__STDC__) || defined (__cplusplus) +extern regexp *regcomp(char* exp); +extern int regexec(register regexp* prog, register char* string); +extern void regsub(regexp* prog, char* source, char* dest); +extern void regerror(char* s); +#else +extern regexp *regcomp(); +extern int regexec(); +extern void regsub(); +extern void regerror(); +#endif + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/src/regexp/regexpTest.c b/src/regexp/regexpTest.c new file mode 100755 index 0000000..90b3a35 --- /dev/null +++ b/src/regexp/regexpTest.c @@ -0,0 +1,30 @@ +/* regular expression test program */ +#include +#include "regexp.h" +char *table[]= +{ + "dave","dave1","dave2","chen","chen1","beaf","meimei" +}; +#define tableSize 7 + +main (int argc, char **argv) +{ + int i = 0; + char exp[80]; + regexp *rexp = 0; + + while (1) { + printf ("Enter a regular expression\n"); + scanf ("%s",exp); + rexp = regcomp (exp); + if (rexp == 0) { + fprintf (stderr, "regular expression generated failed\n"); + exit (1); + } + for (i = 0; i < tableSize; i++) { + if (regexec (rexp, table[i]) != 0) + printf ("Matche: %s\n",table[i]); + } + free (rexp); + } +} diff --git a/src/regexp/regmagic.h b/src/regexp/regmagic.h new file mode 100755 index 0000000..5acf447 --- /dev/null +++ b/src/regexp/regmagic.h @@ -0,0 +1,5 @@ +/* + * The first byte of the regexp internal "program" is actually this magic + * number; the start node begins in the second byte. + */ +#define MAGIC 0234 diff --git a/src/regexp/regsub.c b/src/regexp/regsub.c new file mode 100755 index 0000000..4677190 --- /dev/null +++ b/src/regexp/regsub.c @@ -0,0 +1,82 @@ +/* + * regsub + * + * Copyright (c) 1986 by University of Toronto. + * Written by Henry Spencer. Not derived from licensed software. + * + * Permission is granted to anyone to use this software for any + * purpose on any computer system, and to redistribute it freely, + * subject to the following restrictions: + * + * 1. The author is not responsible for the consequences of use of + * this software, no matter how awful, even if they arise + * from defects in it. + * + * 2. The origin of this software must not be misrepresented, either + * by explicit claim or by omission. + * + * 3. Altered versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + */ +#include +#include "regexp.h" +#include "regmagic.h" + +#ifndef CHARBITS +#define UCHARAT(p) ((int)*(unsigned char *)(p)) +#else +#define UCHARAT(p) ((int)*(p)&CHARBITS) +#endif + +/* + - regsub - perform substitutions after a regexp match + */ +void +#if defined (__STDC__) || defined (__cplusplus) +regsub(regexp* prog, char* source, char* dest) +#else +regsub(prog, source, dest) +regexp *prog; +char *source; +char *dest; +#endif +{ + register char *src; + register char *dst; + register char c; + register int no; + register int len; + + if (prog == NULL || source == NULL || dest == NULL) { + regerror("NULL parm to regsub"); + return; + } + if (UCHARAT(prog->program) != MAGIC) { + regerror("damaged regexp fed to regsub"); + return; + } + + src = source; + dst = dest; + while ((c = *src++) != '\0') { + if (c == '&') + no = 0; + else if (c == '\\' && '0' <= *src && *src <= '9') + no = *src++ - '0'; + else + no = -1; + + if (no < 0) /* Ordinary character. */ + *dst++ = c; + else if (prog->startp[no] != NULL && prog->endp[no] != NULL) { + len = prog->endp[no] - prog->startp[no]; + (void) strncpy(dst, prog->startp[no], len); + dst += len; + if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */ + regerror("damaged match string"); + return; + } + } + } + *dst++ = '\0'; +} diff --git a/src/siteconfig/Makefile b/src/siteconfig/Makefile new file mode 100755 index 0000000..736c616 --- /dev/null +++ b/src/siteconfig/Makefile @@ -0,0 +1,36 @@ +# Makefile for site configuration (sample) +# +# Makefile,v +# Revision 1.1 1997/08/27 18:21:51 chen +# cebaf site cdev system configuration +# +# +# +include ../Makefile.config + +ifeq ($(SHOBJ),YES) + OBJTYPE=.shobj/$(TARGETDIR) +else + OBJTYPE=.obj/$(TARGETDIR) +endif + +OBJS = $(OBJTYPE)/cebafConfig.o + +ifeq ($(SHOBJ),YES) + TARGETLIB=$(CDEVSHOBJ)/$(CDEVVERSION)/cdevSiteConfig.so +else + TARGETLIB= +endif + +targets: $(OBJTYPE) $(TARGETLIB) + +$(OBJTYPE) : + @mkdir -p $(OBJTYPE) + +$(CDEVSHOBJ)/$(CDEVVERSION)/cdevSiteConfig.so: $(OBJS) + @mkdir -p $(CDEVSHOBJ)/$(CDEVVERSION) + $(MAKELIB) $@ $(OBJS) + +clean: clean_hail + rm -rf *.o *.a *~ .obj .shobj core ptrepository + diff --git a/src/siteconfig/cebafConfig.cc b/src/siteconfig/cebafConfig.cc new file mode 100755 index 0000000..7047ee8 --- /dev/null +++ b/src/siteconfig/cebafConfig.cc @@ -0,0 +1,40 @@ +// Simple test program to config cebaf error reporting system +// of cdev system +#include +#include +#include +#include + +extern "C" int _cdev_site_config (cdevSystem* sys); + +static cdevRequestObject* cmlogobj = 0; + +static void +cebafErrorReport (int severity, + char* text, + cdevRequestObject* obj) +{ + cdevData data; + + data.insert ("facility", "cdevSystem"); + data.insert ("severity", severity); + data.insert ("text", text); + + cmlogobj->send (data, 0); +} + +int +_cdev_site_config (cdevSystem* sys) +{ + cmlogobj = cdevRequestObject::attachPtr ("cmlog", "set msg"); + + if (!cmlogobj) + return -1; + + sys->attachErrorHandler (cebafErrorReport); + + sys->reportError (CDEV_SEVERITY_INFO, + "CEBAF local cmlog error handler is installed", + 0); + return 0; +} diff --git a/src/skeleton/Makefile b/src/skeleton/Makefile new file mode 100755 index 0000000..82fb7c4 --- /dev/null +++ b/src/skeleton/Makefile @@ -0,0 +1,50 @@ +# Makefile for skeleton service +# +# cdev skeleton service directory (example service) +# +# Makefile,v +# Revision 1.6 1996/06/26 15:54:22 akers +# Modifications to support multiple OS Versions +# +# Revision 1.5 1995/11/20 15:20:18 chen +# add target +# +# Revision 1.4 1995/11/14 17:47:43 chen +# new makefile +# +# +include ../Makefile.config + +XTRACXXFLAGS = -D_CDEV_DEBUG + + +ifeq ($(SHOBJ),YES) + OBJTYPE=.shobj/$(TARGETDIR) +else + OBJTYPE=.obj/$(TARGETDIR) +endif + +OBJS = $(OBJTYPE)/skService.o $(OBJTYPE)/skRequestObject.o + +ifeq ($(SHOBJ), YES) +targets: $(OBJTYPE) $(LIBDIR)/skService.so + +$(LIBDIR)/skService.so: $(OBJS) + @if test ! -d $(LIBDIR); then mkdir -p $(LIBDIR); else echo; fi + rm -f $@ + $(MAKELIB) $@ $(OBJS) +else +targets: $(OBJTYPE) $(LIBDIR)/libsk.a + +$(LIBDIR)/libsk.a: $(OBJS) + @if test ! -d $(LIBDIR); then mkdir -p $(LIBDIR); else echo; fi + rm -f $@ + $(MAKELIB) $@ $(OBJS) + $(RANLIB) $@ +endif + +$(OBJTYPE) : + @mkdir -p $(OBJTYPE) + +clean: clean_hail + rm -rf *.so *.o *.a *~ core ptrepository diff --git a/src/skeleton/README b/src/skeleton/README new file mode 100755 index 0000000..05af60e --- /dev/null +++ b/src/skeleton/README @@ -0,0 +1,36 @@ + + Skeleton Service README file + +The files in this directory implement a skeleton service which may be a +useful starting point for developing your own service. To turn this into +a real service supporting synchronous read/write, take the following steps: + +src/Makefile: + + add skeleton to the list of supported directories (DIRS = ) + (put \ on previous line) + + $(CDEVSRC)/skeleton + +skService class: + + constructor: add calls to initialize your I/O system. The + skeleton service maintains 2 addressable numbers. + +skRequestObject: + + constructor: add calls to parse the message, and to attach the + relevant parameter in your I/O system + (replace dummy code) + + send: add call to perform the appropriate I/O + (dummy code reads / writes the 2 variables) + + +In the skeleton request object, all asychronous calls are mapped onto +synchronous calls, and only the verbs "get" and "set" are supported. +The name server is used to map the message onto the service's address +space (choice of variable). + +Once you get this much working, look at the channel access service to +see how to support asynchronous calls. diff --git a/src/skeleton/skRequestObject.cc b/src/skeleton/skRequestObject.cc new file mode 100755 index 0000000..dfea8f2 --- /dev/null +++ b/src/skeleton/skRequestObject.cc @@ -0,0 +1,202 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// CDEV Skeleton request object +// +// Author: Jie Chen +// +// Revision History: +// skRequestObject.cc,v +// Revision 1.3 1996/01/05 18:41:28 chen +// Fix a potential bug for GCC +// +// Revision 1.2 1995/07/22 22:58:59 watson +// var1,var2 version +// +// Revision 1.1 1995/07/22 20:20:08 watson +// add skeleton service +// +// +#include +#include +#include +#include "skService.h" +#include "skRequestObject.h" + +skRequestObject::skRequestObject (char *device, char *msg, cdevSystem& system) +:cdevRequestObject (device, msg, system) +{ +#ifdef _TRACE_OBJECTS + printf (" Create skRequestObject class\n"); +#endif + int status = findSvcData(device, msg, system, index_); + status = skRequestObject::findAction (msg, action_); +} + +skRequestObject::~skRequestObject (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Destroy skRequestObject class\n"); +#endif +} + +int +skRequestObject::findSvcData (char *device, + char *msg, + cdevSystem& system, + int& index) +{ + char message[256], fullname[128]; + + if (system.prefix()) + ::sprintf (fullname, "%s%s",system.prefix(),device); + else + ::strcpy (fullname, device); + + ::sprintf (message,"resolveServiceData %s %s", fullname, msg); + + cdevData result; + int status = (system.nameServer()).send (message, 0, result); + if (status == CDEV_SUCCESS){ + status = result.get (skService::SK_TAG_XYZ, &index); +#ifdef _CDEV_DEBUG + printf("Service data is %i\n",index); +#endif + return status; + } + else + return CDEV_ERROR; +} + + +int +skRequestObject::findAction (char *msg, int& action) +{ + char token0[32]; + +#ifdef __GNUC__ + // some version of gcc demand memory location for char string + char buffer[256]; + ::strncpy (buffer, msg, sizeof (buffer)); + int status = ::sscanf (buffer, "%s", token0); +#else + int status = ::sscanf (msg, "%s", token0); +#endif + if (status == 1){ + if (::strcmp (token0, "get") == 0) + action = skRequestObject::GET; + else if (::strcmp (token0, "set") == 0) + action = skRequestObject::SET; + else + action = skRequestObject::UNKNOWN; + } + else + action = skRequestObject::UNKNOWN; + return 0; +} + +int +skRequestObject::send (cdevData& out, cdevData& result) +{ + return send (&out, &result); +} + +int +skRequestObject::send (cdevData& out, cdevData* result) +{ + return send (&out, result); +} + +int +skRequestObject::send (cdevData* out, cdevData& result) +{ + return send (out, &result); +} + +int +skRequestObject::send (cdevData* out, cdevData* result) +{ + switch (action_){ + case GET: + if (!result) + return CDEV_ERROR; + if (index_ == 1) + result->insert (skService::SK_TAG_VALUE, + ((skService *)service_)->var1); + else if (index_ == 2) + result->insert (skService::SK_TAG_VALUE, + ((skService *)service_)->var2); + else + result->insert (skService::SK_TAG_VALUE, + 0 ); + break; + case SET: + if (!out) + return CDEV_ERROR; + { + int tmp; + if (out->get (skService::SK_TAG_VALUE, &tmp) != CDEV_SUCCESS) + return CDEV_ERROR; + if (index_ == 1) + ((skService *)service_)->var1 = tmp; + else if (index_ == 2) + ((skService *)service_)->var2 = tmp; + } + break; + default: + return CDEV_ERROR; + } + return CDEV_SUCCESS; +} + +int +skRequestObject::sendNoBlock (cdevData& data, cdevData& result) +{ + return sendNoBlock (&data, &result); +} + +int +skRequestObject::sendNoBlock (cdevData& data, cdevData* result) +{ + return sendNoBlock (&data, result); +} + +int +skRequestObject::sendNoBlock (cdevData* data, cdevData& result) +{ + return sendNoBlock (data, &result); +} + +int +skRequestObject::sendNoBlock (cdevData* data, cdevData* result) +{ + int status = send (data, result); + return status; +} + +int +skRequestObject::sendCallback (cdevData& data, cdevCallback& callback) +{ + return sendCallback (&data, callback); +} + +int +skRequestObject::sendCallback (cdevData* data, cdevCallback& callback) +{ + cdevData result; + int status = send (data, result); + (*callback.callbackFunction ())(status, callback.userarg (), + *this, result); + return status; +} + + + + diff --git a/src/skeleton/skRequestObject.h b/src/skeleton/skRequestObject.h new file mode 100755 index 0000000..d942cb8 --- /dev/null +++ b/src/skeleton/skRequestObject.h @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// CDEV Skeleton request object +// +// Author: Jie Chen +// +// Revision History: +// skRequestObject.h,v +// Revision 1.2 1995/07/22 22:59:00 watson +// var1,var2 version +// +// Revision 1.1 1995/07/22 20:20:09 watson +// add skeleton service +// +// +#ifndef _CDEV_SK_REQUESTOBJ_H +#define _CDEV_SK_REQUESTOBJ_H + +#include +#include +#include + +class CDEVSVC_CLASS_SPEC skRequestObject: public cdevRequestObject +{ + public: + // constructor and destructor + skRequestObject (char* device, char* msg, cdevSystem& system); + ~skRequestObject (void); + + // IO operations + int send (cdevData& out, cdevData& result); + int send (cdevData* out, cdevData& result); + int send (cdevData& out, cdevData* result); + int send (cdevData* out, cdevData* result); + + int sendNoBlock (cdevData& out, cdevData& result); + int sendNoBlock (cdevData* out, cdevData& result); + int sendNoBlock (cdevData& out, cdevData* result); + int sendNoBlock (cdevData* out, cdevData* result); + + int sendCallback (cdevData& out, cdevCallback& callback); + int sendCallback (cdevData* out, cdevCallback& callback); + + enum {GET = 0x3000, SET, UNKNOWN}; + + const char *className (void) const {return "skRequestObject";}; + + protected: + // convert char string action msg into integer + static int findAction (char *msg, int& action); + static int findSvcData (char *device, char *msg, + cdevSystem& system, int& ind); + // callback functions + static void getCallback (int status, void *arg, int result); + static void setCallback (int status, void *arg, int result); + + private: + int action_; + int index_; +}; + +#endif diff --git a/src/skeleton/skService.cc b/src/skeleton/skService.cc new file mode 100755 index 0000000..8ee5710 --- /dev/null +++ b/src/skeleton/skService.cc @@ -0,0 +1,122 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdev skeleton service +// +// Author: Jie Chen, Chip Watson +// +// Revision History: +// skService.cc,v +// Revision 1.2 1995/07/22 22:59:00 watson +// var1,var2 version +// +// Revision 1.1 1995/07/22 20:20:09 watson +// add skeleton service +// +// +#include +#include +#include "skService.h" +#include "skRequestObject.h" + +int skService::SK_TAG_XYZ = 0; // tag for service data +int skService::SK_TAG_VALUE = 0; // tag for "value" data + +skService::skService (char *name, cdevSystem& system) +:cdevService (name, system), var1 (100), var2 (1000) +{ +#ifdef _TRACE_OBJECTS + printf (" Create skService Class Object\n"); +#endif + // add tags to this service + if (skService::SK_TAG_VALUE == 0) { + cdevData::addTag ("XYZ"); + skService::mapCtagToItag (); + } +} + +skService::~skService (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete skService Class Object\n"); +#endif +} + +int +skService::getFd (int* &fd, int& numfd) +{ + fd = 0; + numfd = 0; + return CDEV_SUCCESS; +} + +int +skService::flush (void) +{ + printf ("skService flush\n"); + return CDEV_SUCCESS; +} + +int +skService::poll (void) +{ + // no outstanding work, so return + return CDEV_SUCCESS; +} + +int +skService::pend (int) +{ + // no outstanding work, so return + return CDEV_SUCCESS; +} + +int +skService::pend (double, int) +{ + // no outstanding work, so return + return CDEV_SUCCESS; +} + +int +skService::getRequestObject (char* device, + char* msg, + cdevRequestObject* &reqobj) +{ + reqobj = new skRequestObject (device, msg, system_); + if (reqobj) + return CDEV_SUCCESS; + else + return CDEV_ERROR; +} + +int +skService::getNameServer (cdevDevice* &ns) +{ + // this service does not implement a name server device + ns = 0; + return CDEV_SUCCESS; +} + + +void +skService::mapCtagToItag (void) +{ + // cache the integer equivalent of "value" tag + cdevData::tagC2I ("value", &skService::SK_TAG_VALUE); + cdevData::tagC2I ("XYZ", &skService::SK_TAG_XYZ); +} + + +cdevService * +newSkService (char *name, cdevSystem* sys) +{ + return new skService (name, *sys); +} diff --git a/src/skeleton/skService.h b/src/skeleton/skService.h new file mode 100755 index 0000000..c8eb80c --- /dev/null +++ b/src/skeleton/skService.h @@ -0,0 +1,78 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// Skeleton Service +// +// Author: Jie Chen +// +// Revision History: +// skService.h,v +// Revision 1.2 1995/07/22 22:59:01 watson +// var1,var2 version +// +// Revision 1.1 1995/07/22 20:20:10 watson +// add skeleton service +// +// +#ifndef _CDEV_SK_SERVICE_H +#define _CDEV_SK_SERVICE_H + +#include +#include + +extern "C" CDEVSVCAPI cdevService *newSkService (char *name, cdevSystem* system); + +class CDEVSVC_CLASS_SPEC skService: public cdevService +{ +public: + // constructor + skService (char* name, cdevSystem& system = cdevSystem::defaultSystem ()); + + // get fd + int getFd (int* &fd, int& numFd); + + // network operations + int flush (void); + int poll (void); + int pend (int fd = -1); + int pend (double seconds, int fd = -1); + + // return right request object + int getRequestObject (char *device, char *msg, + cdevRequestObject* &reqobj); + + // get name server, no use now + int getNameServer (cdevDevice* &ns); + + // tag values + static int SK_TAG_VALUE; + static int SK_TAG_XYZ; + + // class name + const char *className (void) const {return "skService";} + +protected: + // deny access to destructor + ~skService (void); + // map char tags to int tags + static void mapCtagToItag (void); + +private: + // friend class + friend class skRequestObject; + int var1; + int var2; +}; + +#endif + + + + diff --git a/src/system/.shobj/Linux/cdevConfigFinder.o b/src/system/.shobj/Linux/cdevConfigFinder.o new file mode 100644 index 0000000..60b338f Binary files /dev/null and b/src/system/.shobj/Linux/cdevConfigFinder.o differ diff --git a/src/system/.shobj/Linux/cdevErrSvc.o b/src/system/.shobj/Linux/cdevErrSvc.o new file mode 100644 index 0000000..af16259 Binary files /dev/null and b/src/system/.shobj/Linux/cdevErrSvc.o differ diff --git a/src/system/.shobj/Linux/cdevError.o b/src/system/.shobj/Linux/cdevError.o new file mode 100644 index 0000000..e6e821b Binary files /dev/null and b/src/system/.shobj/Linux/cdevError.o differ diff --git a/src/system/.shobj/Linux/cdevService.o b/src/system/.shobj/Linux/cdevService.o new file mode 100644 index 0000000..c46a5c8 Binary files /dev/null and b/src/system/.shobj/Linux/cdevService.o differ diff --git a/src/system/.shobj/Linux/cdevSync.o b/src/system/.shobj/Linux/cdevSync.o new file mode 100644 index 0000000..7d70dd0 Binary files /dev/null and b/src/system/.shobj/Linux/cdevSync.o differ diff --git a/src/system/.shobj/Linux/cdevSystem.o b/src/system/.shobj/Linux/cdevSystem.o new file mode 100644 index 0000000..e095ae5 Binary files /dev/null and b/src/system/.shobj/Linux/cdevSystem.o differ diff --git a/src/system/.shobj/Linux/cdevSystemBase.o b/src/system/.shobj/Linux/cdevSystemBase.o new file mode 100644 index 0000000..eb39e79 Binary files /dev/null and b/src/system/.shobj/Linux/cdevSystemBase.o differ diff --git a/src/system/.shobj/Linux/cdevUserFdService.o b/src/system/.shobj/Linux/cdevUserFdService.o new file mode 100644 index 0000000..971c039 Binary files /dev/null and b/src/system/.shobj/Linux/cdevUserFdService.o differ diff --git a/src/system/Makefile b/src/system/Makefile new file mode 100755 index 0000000..0d9e360 --- /dev/null +++ b/src/system/Makefile @@ -0,0 +1,66 @@ +# Makefile for system directory of CDEV +# +# cdev system directory +# +# Makefile,v +# Revision 1.10 1998/08/17 14:05:03 akers +# Added 'Minor Version Number' to TARGETDIR in Makefiles +# +# Revision 1.9 1997/08/27 18:23:30 chen +# Change error reporting to site specific scheme +# +# Revision 1.8 1997/02/18 15:45:41 chen +# port to linux 2.0.x + addUserFdCallback +# +# Revision 1.7 1996/09/20 12:24:58 akers +# Changes added for Release 1.4 +# +# Revision 1.5 1996/06/26 15:54:23 akers +# Modifications to support multiple OS Versions +# +# Revision 1.4 1996/05/14 20:38:24 akers +# Makefile modifications +# +# Revision 1.3 1995/11/14 17:49:27 chen +# new makefile +# +# +include ../Makefile.config + +ifeq ($(SHOBJ),YES) + OBJTYPE=.shobj/$(TARGETDIR) +else + OBJTYPE=.obj/$(TARGETDIR) +endif + +ifeq ($(INCDIR), ) + INCDIR = ../.. +endif + +XTRACXXFLAGS = -I/usr/include/CC + +OBJS = $(OBJTYPE)/cdevError.o \ + $(OBJTYPE)/cdevSync.o \ + $(OBJTYPE)/cdevSystemBase.o \ + $(OBJTYPE)/cdevService.o \ + $(OBJTYPE)/cdevSystem.o \ + $(OBJTYPE)/cdevErrSvc.o \ + $(OBJTYPE)/cdevUserFdService.o \ + $(OBJTYPE)/cdevConfigFinder.o + +targets: $(OBJTYPE) $(OBJDIR)/$(OBJTYPE) copyobjs copyincs + +$(OBJTYPE) : + @mkdir -p $(OBJTYPE) + +$(OBJDIR)/$(OBJTYPE) : + @mkdir $(OBJDIR)/$(OBJTYPE) + +copyobjs: $(OBJS) + @cp -f $(OBJS) $(OBJDIR)/$(OBJTYPE) + +copyincs: + @cp -f *.h $(INCDIR) + +clean: clean_hail + @rm -rf *.o .obj .shobj core *~ diff --git a/src/system/NMakefile.mak b/src/system/NMakefile.mak new file mode 100755 index 0000000..79b35f3 --- /dev/null +++ b/src/system/NMakefile.mak @@ -0,0 +1,20 @@ +include ..\NMakefile.config + +OBJS = $(OBJDIR)\cdevError.obj \ + $(OBJDIR)\cdevSync.obj \ + $(OBJDIR)\cdevSystemBase.obj \ + $(OBJDIR)\cdevService.obj \ + $(OBJDIR)\cdevSystem.obj \ + $(OBJDIR)\cdevErrSvc.obj \ + $(OBJDIR)\cdevUserFdService.obj \ + $(OBJDIR)\cdevConfigFinder.obj + +targets : copyincs copyobjs + +copyobjs : $(OBJS) + -@if not exist ..\lib\$(OBJDIR) mkdir ..\lib\$(OBJDIR) + -@for %x in ($(OBJDIR)\*.obj) DO @copy %x ..\lib\$(OBJDIR) > nul + +copyincs : + -@for %x in (*.h *.i) DO @copy %x $(CDEV)\include > nul + diff --git a/src/system/cdevConfigFinder.cc b/src/system/cdevConfigFinder.cc new file mode 100755 index 0000000..dde5c00 --- /dev/null +++ b/src/system/cdevConfigFinder.cc @@ -0,0 +1,149 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// CDEV Configuration Loader for different site +// +// Author: Jie Chen +// +// Revision History: +// cdevConfigFinder.cc,v +// Revision 1.2 1997/09/18 18:12:50 chen +// check site configuration file before loading +// +// Revision 1.1 1997/08/27 18:23:30 chen +// Change error reporting to site specific scheme +// +// +// +#include "cdevConfigFinder.h" + +#ifdef SHOBJ +#include +#include + +#ifndef _WIN32 +#include +#endif + +int cdevConfigFinder::tloadconfig_ = 0; + +cdevConfigFinder::cdevConfigFinder (cdevSystem& system) +:loader_ (0), system_ (system) +{ +#ifdef _TRACE_OBJECTS + printf ("Create cdevConfigFinder Class Object\n"); +#endif +} + +cdevConfigFinder::~cdevConfigFinder (void) +{ +#ifdef _TRACE_OBJECTS + printf ("Delete cdevConfigFinder Class Object\n"); +#endif + if (loader_) + delete loader_; +} + +int +cdevConfigFinder::loadConfig (void) +{ + if (!cdevConfigFinder::tloadconfig_) { + int status = -1; + int (*create)(cdevSystem *); + + char location[3][256]; + char *envVar = ::getenv ("CDEVSHOBJ"); + + *location[0] = '\0'; + *location[1] = '\0'; + *location[2] = '\0'; + + // assign flag + cdevConfigFinder::tloadconfig_ = 1; + + if(envVar!= NULL && *envVar) { + // ************************************************************* + // * The first search location is in the versioned directory + // * under the cdev shared object directory... this would look + // * like... "/usr/cdev/shobj/1.3/filename.so" + // ************************************************************* + sprintf(location[0], + "%s/%s.%s/%s", + envVar, + cdevSystem::CDEV_MAJOR_VERSION, + cdevSystem::CDEV_MINOR_VERSION, + _CDEV_CONFIG_FILENAME); + // ************************************************************* + // * The second search location is within the cdev shared object + // * directory... this would look like... + // * "/usr/cdev/shobj/filename.so" + // ************************************************************* + sprintf(location[1], + "%s/%s", + envVar, + _CDEV_CONFIG_FILENAME); + } + // ********************************************************************* + // * The third search location is within the /usr/local/lib directory... + // * This would look like... "/usr/local/lib/filename.so" + // ********************************************************************* + sprintf(location[2], "/usr/local/lib/%s", _CDEV_CONFIG_FILENAME); + + // ********************************************************************* + // * Walk through the list of possible locations until the shared + // * library is successfully loaded, or until all options have been + // * exhausted. + // ********************************************************************* + struct stat sbuf; + for(int i = 0; i < 3; i++) { + if (*location[i] != '\0') { + + // find out whether this file is there + if (stat (location[i], &sbuf) != 0) + continue; + + + loader_ = new shObjLoader (location[i]); + if( loader_->load () == 0) { + if (loader_->findProcedureSym (_CDEV_CONFIG_ROUTINE, + (void **)&create) == 0) { + status = (*create)(&system_); + break; + } + else { + delete loader_; + loader_ = 0; + } + } + else { + delete loader_; + loader_ = 0; + } + } + } + return status; + } + else + return 0; +} + +#else +#include "cdevConfigFinder.h" + +cdevConfigFinder::cdevConfigFinder (cdevSystem &) +{ + // empty +} + +#endif + + + + diff --git a/src/system/cdevConfigFinder.h b/src/system/cdevConfigFinder.h new file mode 100755 index 0000000..6f2bbfc --- /dev/null +++ b/src/system/cdevConfigFinder.h @@ -0,0 +1,95 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// CDEV Configuration Loader for different site +// +// Author: Jie Chen +// +// Revision History: +// cdevConfigFinder.h,v +// Revision 1.1 1997/08/27 18:23:30 chen +// Change error reporting to site specific scheme +// +// +// +#ifndef _CDEV_CONFIG_FINDER_H +#define _CDEV_CONFIG_FINDER_H + +#if defined (_WIN32) + +#ifndef SHOBJ +#define SHOBJ 1 +#endif + +#endif /* WIN 32 */ + +#ifdef SHOBJ + +#include +#include +#include + +#define _CDEV_CONFIG_FILENAME "cdevSiteConfig.so" +#define _CDEV_CONFIG_ROUTINE "_cdev_site_config" + +class shObjLoader; + +class cdevConfigFinder +{ +public: + // constructor and destructor + cdevConfigFinder (cdevSystem& system = cdevSystem::defaultSystem ()); + ~cdevConfigFinder (void); + + + int loadConfig (void); + // PURPOSE: load a site defined configuration file with routine name + // _cdev_site_config (cdevSystem& system) + // REQUIRE: none + // PROMISE: return 0: configuration loaded. return -1: failed + +protected: + + // flag that denotes whether the system has tried load config or not + static int tloadconfig_; + +private: + // deny assignment and copy operations + cdevConfigFinder (const cdevConfigFinder& finder); + cdevConfigFinder& operator = (const cdevConfigFinder& finder); + + // data area + shObjLoader* loader_; + cdevSystem& system_; +}; + +#else + +#include +#include +#include + +class cdevConfigFinder +{ +public: + // constructor + cdevConfigFinder (cdevSystem& system = cdevSystem::defaultSystem ()); + + int loadConfig (void) {return 0;} +private: + // deny assignment and copy operations + cdevConfigFinder (const cdevConfigFinder& finder); + cdevConfigFinder& operator = (const cdevConfigFinder& finder); +}; +#endif + +#endif + + diff --git a/src/system/cdevErrCode.h b/src/system/cdevErrCode.h new file mode 100755 index 0000000..cd617ce --- /dev/null +++ b/src/system/cdevErrCode.h @@ -0,0 +1,99 @@ +/* +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// CDEV error codes +// +// Author: Jie Chen +// +// Revision History: +// cdevErrCode.h,v +// Revision 1.8 1998/01/14 17:49:48 chen +// add msg error +// +// Revision 1.7 1998/01/14 13:47:10 chen +// add more status code +// +// Revision 1.6 1996/12/16 20:48:51 akers +// Support for additional cdevCallback features +// +// Revision 1.5 1996/11/21 17:03:29 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.4 1995/10/17 17:33:57 akers +// Updated error, status, access and severity codes +// +// Revision 1.3 1995/10/03 20:07:13 chen +// add connection event type +// +// Revision 1.2 1995/07/05 18:44:05 chen +// change to C code callable style +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +*/ +#ifndef _CDEV_ERROR_CODE_H +#define _CDEV_ERROR_CODE_H + +/* Error and status values */ +#define CDEV_WARNING -2 /* Failure of function is non-consequential */ +#define CDEV_ERROR -1 /* Errors that are not in any categories */ +#define CDEV_SUCCESS 0 /* cdev success */ +#define CDEV_INVALIDOBJ 1 /* invalid cdev objects */ +#define CDEV_INVALIDARG 2 /* invalid argument passed to cdev calls */ +#define CDEV_INVALIDSVC 3 /* wrong service during dynamic loading */ +#define CDEV_INVALIDOP 4 /* operation is unsupported (collection) */ + +#define CDEV_NOTCONNECTED 5 /* not connected to low network service */ +#define CDEV_IOFAILED 6 /* low level network service IO failed */ +#define CDEV_CONFLICT 7 /* conflicts of data types or tags */ +#define CDEV_NOTFOUND 8 /* cdev cannot find user request (cdevData) */ + +#define CDEV_TIMEOUT 9 /* time out */ +#define CDEV_CONVERT 10 /* cdevData conversion error */ +#define CDEV_OUTOFRANGE 11 /* value out of range for device attribute */ +#define CDEV_NOACCESS 12 /* insufficient access to perform request */ +#define CDEV_ACCESSCHANGED 13 /* change in access permission of device */ + +#define CDEV_DISCONNECTED 60 /* channel has been disconnected */ +#define CDEV_RECONNECTED 61 /* channel has been reconnected */ + +#define CDEV_DELETE_CALLBACK 70 /* the callback object will be deleted */ + +/* status related to callback status and more */ +#define CDEV_NOTCONSERVER 80 /* can not connect to server/ not connected */ +#define CDEV_NOTFOUNDSERVER 81 /* can not find server */ +#define CDEV_CONN_TIMEOUT 82 /* connection timeout */ +#define CDEV_BADIO 86 /* TCP io is bad file descriptor */ +#define CDEV_OVERFLOW 87 /* overflow buffer */ +#define CDEV_INCOMPLETE 88 /* data flow will coming (unfinished) */ +#define CDEV_CBK_FINISHED 89 /* callback finished (monitor off) */ +#define CDEV_PAUSED 90 /* callback is paused */ +#define CDEV_MSG_ERR 91 /* query message syntax error */ + +/* Request object state values */ +#define CDEV_STATE_CONNECTED 0 /* request object is connected to device */ +#define CDEV_STATE_NOTCONNECTED 1 /* request object is not connected */ +#define CDEV_STATE_INVALID 2 /* request object is invalid */ + +/* Request object access values */ +#define CDEV_ACCESS_NONE 0 /* no access to specified attribute */ +#define CDEV_ACCESS_READONLY 1 /* read-only access to attribute */ +#define CDEV_ACCESS_WRITE 2 /* read-write access to attribute */ + +/* cdevError class severity codes */ +#define CDEV_SEVERITY_INFO 0 /* informative message */ +#define CDEV_SEVERITY_WARN 1 /* warning message */ +#define CDEV_SEVERITY_ERROR 2 /* error message */ +#define CDEV_SEVERITY_SEVERE 3 /* severe or fatal error message */ + +#endif diff --git a/src/system/cdevErrSvc.cc b/src/system/cdevErrSvc.cc new file mode 100755 index 0000000..4c18b46 --- /dev/null +++ b/src/system/cdevErrSvc.cc @@ -0,0 +1,90 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevService Error Handler Class +// +// Author: Jie Chen +// +// Revision History: +// cdevErrSvc.cc,v +// Revision 1.1.1.1 1995/06/16 17:14:07 epics +// initial import of cdev +// +// +#include +#include +#include +#include +#include "cdevErrSvc.h" + +cdevErrSvc::cdevErrSvc (cdevSystem& system) +:cdevService ("cdev_Error_Service", system) +{ +#ifdef _TRACE_OBJECTS + printf(" Create cdevErrSvc class\n"); +#endif + // don't register this service to service list + // User should not access this service + // Parent class already register itselef + system.removeService (this); +} + +cdevErrSvc::~cdevErrSvc (void) +{ +#ifdef _TRACE_OBJECTS + printf(" Delete cdevErrSvc class\n"); +#endif +} + +int +cdevErrSvc::getFd (int* &fd, int& numFd) +{ + numFd = 0; + fd = 0; + return CDEV_INVALIDSVC; +} + +int +cdevErrSvc::flush (void) +{ + return CDEV_INVALIDSVC; +} + +int +cdevErrSvc::poll (void) +{ + return CDEV_INVALIDSVC; +} + +int +cdevErrSvc::pend (int ) +{ + return CDEV_INVALIDSVC; +} + +int +cdevErrSvc::pend (double, int) +{ + return CDEV_INVALIDSVC; +} + +int +cdevErrSvc::getRequestObject (char *, char *, cdevRequestObject* &reqObj) +{ + reqObj = 0; + return CDEV_INVALIDSVC; +} + +int +cdevErrSvc::getNameServer (cdevDevice* &ns) +{ + ns = 0; + return CDEV_INVALIDSVC; +} diff --git a/src/system/cdevErrSvc.h b/src/system/cdevErrSvc.h new file mode 100755 index 0000000..828d272 --- /dev/null +++ b/src/system/cdevErrSvc.h @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevService Error Handler Class +// +// Author: Jie Chen +// +// Revision History: +// cdevErrSvc.h,v +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#ifndef _CDEV_ERR_SVC_H +#define _CDEV_ERR_SVC_H + +#include "cdevService.h" + +class cdevErrSvc: public cdevService +{ + public: + cdevErrSvc (cdevSystem& system = cdevSystem::defaultSystem()); + // PURPOSE: constructor + // REQUIRE: nothing + // PROMISE: a cdevErrSvc + + ~cdevErrSvc (void); + // PURPOSE: Destructor + // REQUIRE: nothing + // PROMISE: free all memory + + int getFd (int * &fd, int &numFd); + // PURPOSE: get service file descriptors + // REQUIRE: callers provide no memory, caller don't free memory + // PROMISE: numFd gives number of file descriptors, numFd >= 0 + + int flush (void); + // PURPOSE: flush network request + // REQUIRE: nothing + // PROMISE: return 0 + + int poll (void); + // PURPOSE: Service Polling Method + // REQURIE: nothing + // PROMISE: return 0 + + int pend (int fd = -1); + // PURPOSE: Service Pending Method + // REQUIRE: nothing + // PROMISE: return 0 + + int pend (double seconds, int fd = -1); + // PURPOSE: Service Pending Method For Upto 'seconds' + // REQUIRE: nothing + // PROMISE: return 0 + + int getRequestObject (char *deviceName, char *msg, + cdevRequestObject * &reqObj); + // PURPOSE: get requestobject + // REQUIRE: nothing + // PROMISE: return 0, reqobj = 0; + + int getNameServer (cdevDevice * &ns); + // PURPOSE: get name server + // REQUIRE: nothing + // PROMISE: return 0, ns = 0 + + const char *className (void) const {return "cdevErrSvc";} +}; +#endif diff --git a/src/system/cdevError.cc b/src/system/cdevError.cc new file mode 100755 index 0000000..91d5032 --- /dev/null +++ b/src/system/cdevError.cc @@ -0,0 +1,261 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevError class (abstract base class) +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevError.cc,v +// Revision 1.10 1997/08/27 18:23:31 chen +// Change error reporting to site specific scheme +// +// Revision 1.9 1997/03/25 22:24:42 akers +// Development in support of a new cdevDirectory +// +// Revision 1.8 1996/02/26 16:28:04 akers +// Change report error formatting +// +// Revision 1.7 1995/12/14 19:11:19 chen +// add support to C interface +// +// Revision 1.6 1995/10/26 19:26:17 akers +// Final Revisions for Version 1.1 +// +// Revision 1.5 1995/10/26 14:45:21 akers +// Added carriage return to error handler +// +// Revision 1.4 1995/10/26 14:33:30 akers +// Removal of Warnings +// +// Revision 1.3 1995/10/17 17:44:12 akers +// Added setThreshold functionality and made data items protected +// +// Revision 1.2 1995/10/17 15:29:54 chen +// change reportError interface +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#include +#include +#include +#include +#include "cdevError.h" +#include "cdevErrCode.h" +#include "cdevRequestObject.h" + +void defaultErrorHandler(int severity, char *text, + cdevRequestObject* /* obj */) + { + if(severity != CDEV_SEVERITY_VOID_DATA && text && *text) + { + #ifndef _WIN32 + fprintf(stderr, "%s\n", text); + #else + HANDLE stderrHandle=GetStdHandle(STD_ERROR_HANDLE); + if(stderrHandle != INVALID_HANDLE_VALUE) + { + int nReady=strlen(text); + unsigned long nWritten=0; + + WriteFile(stderrHandle, text, nReady, &nWritten, NULL); + WriteFile(stderrHandle, "\n", 1, &nWritten, NULL); + } + #endif + } + } + +cdevErrorHandler cdevError::defaultErrorHandler_=defaultErrorHandler; + +//============================================================================ +// Implementation of cdevError class +//============================================================================ +cdevError::cdevError(void) + : autoErrorOn_(1), + threshold_(CDEV_SEVERITY_WARN), + errorHandler_(defaultErrorHandler), + numhandlers_(0) + { + #ifdef _TRACE_OBJECTS + printf("Create abstract class cdevError\n"); + #endif + for(int i=0; i < _CDEV_MAX_ERR_HANDLERS; i++) + handlers_[i]=0; + } + +cdevError::cdevError(cdevErrorHandler handler) + : autoErrorOn_(1), + threshold_(CDEV_SEVERITY_WARN), + errorHandler_(handler) + { + #ifdef _TRACE_OBJECTS + printf("Create abstract class cdevError\n"); + #endif + } + +cdevError::~cdevError(void) + { + #ifdef _TRACE_OBJECTS + printf("Delete abstract class cdevError\n"); + #endif + } + +void +cdevError::setErrorHandler(cdevErrorHandler handler) + { + errorHandler_=handler; + } + +void +cdevError::setThreshold(int errorThreshold) + { + threshold_=errorThreshold; + } + +int +cdevError::autoErrorOn(void) + { + autoErrorOn_=1; + return CDEV_SUCCESS; + } + +int +cdevError::autoErrorOff(void) + { + autoErrorOn_=0; + return CDEV_SUCCESS; + } + +int +cdevError::attachErrorHandler(cdevErrorHandler handler) + { + // check to see whether this handler is already here + for(int i=0; i < numhandlers_; i++) + { + if(handler == handlers_[i]) + return CDEV_ERROR; + } + + // make sure the buffer is not overflowed + if(numhandlers_ >= _CDEV_MAX_ERR_HANDLERS) + return CDEV_ERROR; + + handlers_[numhandlers_++]=handler; + return CDEV_SUCCESS; + } + +int +cdevError::detachErrorHandler(cdevErrorHandler handler) + { + int index =- 1; + int i=0; + for(i=0; i < numhandlers_; i++) + { + if(handler == handlers_[i]) + index=i; + } + + // cannot find this handler + if(index ==- 1) + return CDEV_ERROR; + + // move elements one position up + for(i=index+1; i < numhandlers_; i++) + handlers_[i-1]=handlers_[i]; + + numhandlers_--; + + return CDEV_SUCCESS; + } + + +int cdevError::vreportError(int severity, char *name, + cdevRequestObject *obj, char *formatString, + va_list argp) + { + int status=0; + + if(severity >= threshold_) + { + char msg[1024]; + char *p=msg; + int i=0; + + sprintf(msg, "%s %s: ", + name, + (severity == 0?"Information": + (severity == 1?"Warning": + (severity == 2?"Error": + (severity == 3?"Severe Error": + "Event"))))); + + p+=::strlen(msg); + status=vsprintf(p, formatString, argp); + + if(!autoErrorOn_) (*errorHandler_) (severity, msg, obj); + else (*defaultErrorHandler_) (severity, msg, obj); + + // report the error message to all attached message reporter + for(i=0; i < numhandlers_; i++) + { + (*handlers_[i]) (severity, msg, obj); + } + } + return status; + } + +int cdevError::reportError(int severity, char *name, + cdevRequestObject *obj, + char *formatString, ...) + { + va_list argp; + int status=0; + + va_start(argp, formatString); + status=vreportError(severity, name, obj, formatString, argp); + va_end(argp); + + return status; + } + +void +cdevError::reportError(int severity, char *msg, cdevRequestObject *obj) + { + if(severity >= threshold_) + { + if(!autoErrorOn_) (*errorHandler_) (severity, msg, obj); + else (*defaultErrorHandler_) (severity, msg, obj); + + // report the error message to all attached message reporter + for(int i=0; i < numhandlers_; i++) + { + (*handlers_[i]) (severity, msg, obj); + } + } + } + +void +cdevError::reportError(void *data, cdevRequestObject *obj) + { + int severity=CDEV_SEVERITY_VOID_DATA; + + if(!autoErrorOn_) + (*errorHandler_) (severity, (char *) data, obj); + + // report the error message to all attached message reporter + for(int i=0; i < numhandlers_; i++) + { + (*handlers_[i]) (severity, (char *) data, obj); + } + } + + diff --git a/src/system/cdevError.h b/src/system/cdevError.h new file mode 100755 index 0000000..b22ecd3 --- /dev/null +++ b/src/system/cdevError.h @@ -0,0 +1,135 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevError class (abstract base class) +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevError.h,v +// Revision 1.5 1997/08/27 18:23:31 chen +// Change error reporting to site specific scheme +// +// Revision 1.4 1995/12/14 19:11:14 chen +// add support to C interface +// +// Revision 1.3 1995/10/17 17:44:13 akers +// Added setThreshold functionality and made data items protected +// +// Revision 1.2 1995/10/17 15:29:45 chen +// change reportError interface +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#ifndef _CDEV_ERROR_H +#define _CDEV_ERROR_H + +#include +#include + +#define _CDEV_MAX_ERR_HANDLERS 5 +#define CDEV_SEVERITY_VOID_DATA 0xcde5da2a + +class cdevRequestObject; + +typedef void (*cdevErrorHandler)(int severity, + char *text, + cdevRequestObject* obj); + +class CDEV_CLASS_SPEC cdevError +{ + public: + // destructor + virtual ~cdevError (void); + + virtual int autoErrorOn (void); + // PURPOSE: turn on flag which enables auto error on + // REQUIRE: derived class can implement diffrently + // PROMISE: return 0 + + virtual int autoErrorOff (void); + // PURPOSE: turn on flag which disables auto error on + // REQUIRE: derived class can implement diffrently + // PROMISE: return 0 + + virtual int vreportError (int severity, + char * name, + cdevRequestObject * obj, + char * formatString, + va_list argp); + + // PURPOSE: report error to somewhere + // REQUIRE: formatString can have anything that works in printf + // PROMISE: same as printf + + virtual int reportError (int severity, + char *name, + cdevRequestObject* obj, + char *formatString,...); + // PURPOSE: report error to somewhere + // REQUIRE: formatString can have anything that works in printf + // PROMISE: same as printf + + virtual void reportError (int severity, + char *message, + cdevRequestObject* obj); + // PURPOSE: report error to somewhere with a whole string + // REQUIRE: user whole string + // PROMISE: + + + virtual void setErrorHandler (cdevErrorHandler handler = 0); + // PURPOSE: allow caller to set up his/her own error Handler + // REQUIRE: handle > 0 stands for a real function pointer + // PROMISE: next time error will be handled by new error handler + + virtual void setThreshold ( int errorThreshold ); + // PURPOSE: allow the caller to specify the minimum severity to report + // REQUIRE: errorThreshold >=0 + // PROMISE: errors with severity < errorThreshold wil not be reported + + virtual int attachErrorHandler (cdevErrorHandler handler); + // PURPOSE: allow caller to attach error handler to trap error messages + // REQUIRE: handler > 0 + // PROMISE: return CDEV_SUCCESS if this handler is attached to trap messgaes + + virtual int detachErrorHandler (cdevErrorHandler handler); + // PURPOSE: allow caller to dettach error handler + // REQUIRE: handler > 0 + // PROMISE: return CDEV_SUCCESS if this handler is removed. + + virtual void reportError (void *data, + cdevRequestObject* obj); + // PURPOSE: report error to somewhere with user defined data object. + // This routine is intended for site developer use only to + // support site wide error logging system. + // REQUIRE: user whole string + // PROMISE: + + virtual const char *className(void) const {return "cdevError";} + + protected: + // constructers, avoiding direct instantation + cdevError (void); + cdevError (cdevErrorHandler handler); + + // data areas + cdevErrorHandler errorHandler_; + static cdevErrorHandler defaultErrorHandler_; + int autoErrorOn_; + int threshold_; + + // list of error handlers + int numhandlers_; + cdevErrorHandler handlers_[_CDEV_MAX_ERR_HANDLERS]; +}; +#endif diff --git a/src/system/cdevSelector.h b/src/system/cdevSelector.h new file mode 100755 index 0000000..5ca2140 --- /dev/null +++ b/src/system/cdevSelector.h @@ -0,0 +1,253 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: cdevSelector.h +// The cdevSelector class provides a mechanism for cdevServices to provide +// a locally changable file descriptor to the cdevSystem for select +// operations. +// +// If the service does not support or require file descriptors to operate, +// it may make one of these objects in its constructor and then provide +// the 'readfd' to the cdevSystem when it calls the services getFD method. +// The service may then 'insertEvents' into the object, which will in-turn +// cause the cdevSystems select mechanism to call the service. Once the +// service has responded to the events it should call 'removeEvents' to +// prevent the select mechanism from being triggered again. +// +// Author: Walt Akers +// +// Revision History: +// cdevSelector.h,v +// Revision 1.3 1996/12/05 21:10:49 akers +// Changes to support multiple CDEV DDL versions +// +// Revision 1.2 1995/10/19 20:16:55 akers +// Added capability to test the read file descriptor for data before reading +// +// Revision 1.1 1995/08/18 16:23:41 akers +// Mechanism for providing file descriptor selection for services. +// +// + +#ifndef _CDEV_SELECTOR_H_ +#define _CDEV_SELECTOR_H_ + +#include +#include +#include +#include +#include + +#if defined(solaris) || defined(SunOS) + #include +#endif + +class cdevSelector +{ +private: + typedef struct + { + int readfd; + int writefd; + } SocketPair; + SocketPair sp; + char cbuf[21]; + +public: + cdevSelector ( void ); + ~cdevSelector ( void ); + int insertEvent ( int numEvents = 1 ); + int removeEvent ( int numEvents = 1 ); + void purge ( void ); + int writefd ( void ); + int readfd ( void ); +}; + + + +// ***************************************************************************** +// * cdevSelector::cdevSelector : +// * Constructor for the cdevSelector class. +// ***************************************************************************** +inline cdevSelector::cdevSelector ( void ) + { + if(pipe((int *)&sp)!=0) + { + sp.readfd = -1; + sp.writefd = -1; + } + else + { + int val; + + val = ::fcntl(sp.readfd, F_GETFL, 0); + if(val>0) ::fcntl(sp.readfd, F_SETFL, val|O_NONBLOCK); + + val = ::fcntl(sp.writefd, F_GETFL, 0); + if(val>0) ::fcntl(sp.writefd, F_SETFL, val|O_NONBLOCK); + } + } + + + +// ***************************************************************************** +// * cdevSelector::~cdevSelector : +// * Destructor for the cdevSelector class. +// ***************************************************************************** +inline cdevSelector::~cdevSelector ( void ) + { + if(sp.readfd != -1) close(sp.readfd); + if(sp.writefd != -1) close(sp.writefd); + } + + + +// ***************************************************************************** +// * cdevSelector::insertEvent : +// * Adds one or more bytes (indicating events) to the pipe +// ***************************************************************************** +inline int cdevSelector::insertEvent ( int numEvents ) + { + int result = 0; + char *cptr = cbuf; + + // ********************************************************************* + // * If the write file descriptor is valid + // ********************************************************************* + if(sp.writefd>0) + { + // ************************************************************* + // * If the user wants to add more bytes than the buffer can + // * handle, allocated a sufficient buffer to hold the data. + // ************************************************************* + if(numEvents>20) cptr = new char[numEvents]; + + // ************************************************************* + // * Write the specified number of bytes to the buffer. + // ************************************************************* + write(sp.writefd, cptr, numEvents); + + // ************************************************************* + // * Delete the buffer if it was allocated locally. + // ************************************************************* + if(cptr!=cbuf) delete cptr; + } + else result = -1; + return result; + } + + + +// ***************************************************************************** +// * cdevSelector::removeEvent : +// * Removes one or more bytes (indicating events) from the pipe. +// ***************************************************************************** +inline int cdevSelector::removeEvent ( int numEvents ) + { + int result = 0; + char *cptr = cbuf; + + // ********************************************************************* + // * If the read file descriptor is valid. + // ********************************************************************* + if(sp.readfd>0) + { + int count; + // ************************************************************* + // * Find out how many bytes are ready to read. + // ************************************************************* + ioctl(sp.readfd, FIONREAD, &count); + if(numEvents>count) numEvents = count; + + if(numEvents>0) + { + // ***************************************************** + // * If the user wants to remove more bytes than the + // * buffer can handle, allocated a sufficient buffer to + // * hold the data. + // ***************************************************** + if(numEvents>20) cptr = new char[numEvents]; + + // ***************************************************** + // * Read the specified number of bytes from the pipe. + // ***************************************************** + read(sp.readfd, cptr, numEvents); + + // ***************************************************** + // * Delete the buffer if it was allocated locally. + // ***************************************************** + if(cptr!=cbuf) delete cptr; + } + } + else result = -1; + return result; + } + + + +// ***************************************************************************** +// * cdevSelector::purge : +// * This function removes all bytes from the pipe. +// ***************************************************************************** +inline void cdevSelector::purge ( void ) + { + int count; + char * cptr = cbuf; + + if(sp.readfd>0) + { + // ************************************************************* + // * Find out how many bytes are ready to read. + // ************************************************************* + ioctl(sp.readfd, FIONREAD, &count); + + if(count>0) + { + // ***************************************************** + // * If the user wants to remove more bytes than the + // * buffer can handle, allocated a sufficient buffer to + // * hold the data. + // ***************************************************** + if(count>20) cptr = new char[count]; + + // ***************************************************** + // * Read the specified number of bytes from the pipe. + // ***************************************************** + read(sp.readfd, cptr, count); + + // ***************************************************** + // * Delete the buffer if it was allocated locally. + // ***************************************************** + if(cptr!=cbuf) delete cptr; + } + } + } + + + +// ***************************************************************************** +// * cdevSelector::writefd +// * Returns the write file descriptor associated with the pipe. +// ***************************************************************************** +inline int cdevSelector::writefd ( void ) + { + return sp.writefd; + } + + + +// ***************************************************************************** +// * cdevSelector::readfd +// * Returns the read file descriptor associated with the pipe. +// ***************************************************************************** +inline int cdevSelector::readfd ( void ) + { + return sp.readfd; + } + +#endif /* _CDEV_SELECTOR_H_ */ diff --git a/src/system/cdevService.cc b/src/system/cdevService.cc new file mode 100755 index 0000000..6ed599d --- /dev/null +++ b/src/system/cdevService.cc @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevSerice class (Abstract class ) +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevService.cc,v +// Revision 1.3 1997/08/27 18:23:31 chen +// Change error reporting to site specific scheme +// +// Revision 1.2 1996/11/21 17:03:30 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#include +#include +#include +#include "cdevService.h" +#include "cdevDefCollectionRequest.h" + +cdevService::cdevService (char *name, cdevSystem & system) +:cdevSystemBase(),system_(system) +{ +#ifdef _TRACE_OBJECTS + printf(" Create cdevService class object\n"); +#endif + serviceName_ = new char[::strlen(name) + 1]; + ::strcpy (serviceName_, name); + unregOn_ = 1; + system.registerService (this); +} + +cdevService::~cdevService (void) +{ +#ifdef _TRACE_OBJECTS + printf(" Delete cdevService class object\n"); +#endif + delete []serviceName_; + // system will clean this, depending on unregOn_ flag + if (unregOn_) + system_.removeService (this); +} + +int +cdevService::getCollectionRequest (char ** devices, int nDevices, + char * msg, cdevCollectionRequest * &req) +{ + req = new cdevDefCollectionRequest(devices, nDevices, msg, system_); + return (req==NULL)?CDEV_ERROR:CDEV_SUCCESS; +} + +char * +cdevService::name (void) const +{ + return serviceName_; +} + +int +cdevService::registerFd (int fd, int opened) +{ + if (opened){ // add to existing file mask + system_.attachReadFd (fd); + } + else { // remove from the file mask + system_.detachReadFd (fd); + } + return CDEV_SUCCESS; +} + +const int +cdevService::version (void) const +{ + return CDEV_VERSION; +} + diff --git a/src/system/cdevService.h b/src/system/cdevService.h new file mode 100755 index 0000000..d7cac28 --- /dev/null +++ b/src/system/cdevService.h @@ -0,0 +1,92 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevSerice class (Abstract class ) +// +// Author: Jie Chen, Chip Watson & Walt Akers +// +// Revision History: +// cdevService.h,v +// Revision 1.3 1997/08/27 18:23:32 chen +// Change error reporting to site specific scheme +// +// Revision 1.2 1996/11/21 17:03:32 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#ifndef _CDEV_SERVICE_H +#define _CDEV_SERVICE_H + +#include "cdevSystemBase.h" +#include "cdevSystem.h" + +class cdevCollectionRequest; + +class cdevDevice; + +class CDEV_CLASS_SPEC cdevService: public cdevSystemBase +{ +public: + virtual int getFd (int* &fd, int &numFd) = 0; + // PURPOSE: get service's IO file descriptors + // REQUIRE: callers provide pointer (eg. int *fd = 0;) no memory. callers + // should never free memory pointed by fd. fd should be cached + // inside derived class for easy/quick access + // PROMISE: numFd >= 0 + + virtual int getNameServer (cdevDevice* &server) = 0; + // PURPOSE: get right name server associated with this service + // REQUIRE: caller provide pointer only, derived class provides + // an empty function for now + // PROMISE: not implemented yet + + virtual int registerFd (int fd, int opened = 1); + // PURPOSE: updating file descriptor mask + // REQUIRE: opend = 1 for adding, else removing + // PROMISE: return 0 + + virtual char *name (void) const; + // PURPOSE: return name of this service + // REQUIRE: name must be unique in one system + // PROMISE: name + + virtual int getCollectionRequest (char ** devices, int nDevices, + char * msg, cdevCollectionRequest * &req); + // PURPOSE: return collection requestobject + // REQUIRE: devices != NULL, ndevices > 0 + // PROMISE: CDEV_SUCCESS on success, CDEV_ERROR no request object + + const int version (void) const; + // PURPOSE: return version of service + // REQUIRE: none + // PROMISE: version number of this service + + virtual const char *className (void) const {return "cdevService";} + +protected: + // constructor: deny access for direct instantiation + cdevService (char *name, cdevSystem &system = cdevSystem::defaultSystem ()); + // destructor, all services must be created and destroyed by system + virtual ~cdevService (void); + + // data area + cdevSystem &system_; + char *serviceName_; + // flag to tell whether one unregister itself from system + int unregOn_; + // friend class decleration + friend class cdevSystem; +}; +#endif + + diff --git a/src/system/cdevSync.cc b/src/system/cdevSync.cc new file mode 100755 index 0000000..e42d603 --- /dev/null +++ b/src/system/cdevSync.cc @@ -0,0 +1,272 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevSync class (abstract base class) +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevSync.cc,v +// Revision 1.9 1997/02/18 15:45:42 chen +// port to linux 2.0.x + addUserFdCallback +// +// Revision 1.8 1997/01/09 16:32:04 akers +// Altered attachReadFd and detachReadFd to return CDEV_WARNING if they are already attached or detached prior to the call +// +// Revision 1.7 1996/06/26 15:54:25 akers +// Modifications to support multiple OS Versions +// +// Revision 1.6 1995/11/08 14:44:42 chen +// fix for irix5.3 +// +// Revision 1.5 1995/11/07 19:52:24 chen +// change HP_UX flag to hpux +// +// Revision 1.4 1995/10/26 14:33:31 akers +// Removal of Warnings +// +// Revision 1.3 1995/10/05 18:40:16 chen +// VMS fixes +// +// Revision 1.2 1995/08/22 15:32:15 akers +// Removed assertion from the cdevSync::dispatch function +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#include +#include +#include +#include "cdevSync.h" + +#ifdef __VMS +#ifdef _TGV_MULTINET +#include // for sys/socket.h +#include // for select() proto() +#endif // _TGV_MULTINET +#endif // __VMS defined. + +#ifdef sgi +#include +#endif + +cdevSync::cdevSync (void) +{ +#ifdef _TRACE_OBJECTS + printf("Create abstract class cdevSync\n"); +#endif +} + +cdevSync::~cdevSync (void) +{ +#ifdef _TRACE_OBJECTS + printf("Destroy abstract class cdevSync\n"); +#endif +} + +int +cdevSync::attachReadFd (int fd) +{ + if(!rdMask_.is_set(fd)) + { + rdMask_.set_bit (fd); + return CDEV_SUCCESS; + } + return CDEV_WARNING; +} + +int +cdevSync::detachReadFd (int fd) +{ + if(rdMask_.is_set(fd)) + { + rdMask_.clr_bit (fd); + return CDEV_SUCCESS; + } + return CDEV_WARNING; +} + +int +cdevSync::handleEvents (void) +{ + return handleEvents (0); +} + +int +cdevSync::handleEvents (cdevTimeValue *tv) +{ + cdevFdSet rmaskret; + cdevFdSet wmaskret; + cdevFdSet emaskret; + int nfound = 0, status = 1; + cdevClock timer; + + if (tv) + timer.schedule (0, *tv); + + nfound = waitFor (rmaskret, wmaskret, emaskret, tv); + // really handle lower level pend here + dispatch (nfound, rmaskret, wmaskret, emaskret); + + if (tv) { // finite time value + while (!timer.expired()){ + cdevTimeValue newTv = timer.scheduledTime() - cdevClock::currentTime(); + nfound = waitFor (rmaskret, wmaskret, emaskret, &newTv); + if (nfound > 0) + status = 0; + // really handle lower level pend here + dispatch (nfound, rmaskret, wmaskret, emaskret); + } + } + // status == 0 stands for there is at least one IO event + if (status == 0) + return CDEV_SUCCESS; + else + return CDEV_TIMEOUT; +} + +int +cdevSync::waitFor (cdevFdSet &rmaskret, + cdevFdSet &wmaskret, + cdevFdSet &emaskret, + cdevTimeValue *how_long) +{ + int nfound = 0; + + // *************************************************************************** + // * This code added to protect against NULL cdevTimeValue being submitted + // * to the function. + // *************************************************************************** + timeval tv = (how_long?*how_long:cdevTimeValue(60,0)); + + do { + int maxfd = maxHandle (rdMask_.max_set(), + wrMask_.max_set(), + exMask_.max_set() ) + 1; + + // every time one calls select rmaskret or similiar will change. + // all the masks are cleared when the timer expires + rmaskret = rdMask_; + wmaskret = wrMask_; + emaskret = exMask_; + +#if !defined(__hpux) || (defined(__hpux) && _OS_MAJOR_>9) + nfound = ::select (maxfd, (fd_set *)rmaskret, + (fd_set *)wmaskret, (fd_set *)emaskret, + &tv); +#else + nfound = ::select (maxfd, (int *)(fd_set *)rmaskret, + (int *)(fd_set *)wmaskret, + (int *)(fd_set *)emaskret, + &tv); +#endif + } // select system may well be interrupted by signals, check!!! + while (nfound == -1 && handleError () > 0 ); + return nfound; +} + +void +cdevSync::dispatch (int nfound, + cdevFdSet &rmaskret, + cdevFdSet & /* wmaskret */, + cdevFdSet & /* emaskret */) +{ + int i; + + if (nfound > 0) + for (cdevFdSet_Iterator fdir (rmaskret); + (i = fdir ()) != -1 && --nfound >= 0; + ++fdir){ + notifyService (i); + } +} + +int +cdevSync::handleError (void) +{ +#ifdef _WIN32 + // check interrupt + int wsaerr = WSAGetLastError (); + if (wsaerr == WSAEINTR) + return 1; + // check bad file descriptors + if (wsaerr == WSAEBADF) + return checkFds (); + return -1; +#else + // check interrupt + if (errno == EINTR) + return 1; + // check bad file descriptors + if (errno == EBADF) + return checkFds (); + return -1; +#endif +} + +int +cdevSync::checkFds (void) +{ + cdevFdSet rmask; + cdevTimeValue time_poll; + timeval tv = time_poll; + cdevFdSet_Iterator ite (rdMask_); + int i; + + for (; (i = ite()) != -1; ++ite){ + rmask.set_bit (i); +#if !defined(__hpux) || (defined(__hpux) && _OS_MAJOR_>9) + if(::select (i+1, (fd_set *)rmask, 0, 0, &tv) < 0) +#else + if(::select (i+1, (int *)(fd_set *)rmask, + 0, 0, &tv) < 0) +#endif + detachReadFd (i); + rmask.clr_bit (i); + } + return 1; +} + +int +cdevSync::checkFd (int fd) +{ + cdevFdSet rmask; + cdevTimeValue time_poll; + timeval tv = time_poll; + + rmask.set_bit (fd); +#if !defined(__hpux) || (defined(__hpux) && _OS_MAJOR_>9) + if(::select (fd + 1, (fd_set *)rmask, 0, 0, &tv) < 0) + return -1; +#else + if(::select (fd + 1, (int *)(fd_set *)rmask, + 0, 0, &tv) < 0) + return -1; +#endif + + return 0; +} + + +void +cdevSync::notifyService (int /* fd */) +{ + // empty, derived class give real implementation + return; +} + +int +cdevSync::maxHandle (int i, int j, int k) +{ + int t = i < j ? j : i; + + return k < t ? t : k; +} diff --git a/src/system/cdevSync.h b/src/system/cdevSync.h new file mode 100755 index 0000000..7751454 --- /dev/null +++ b/src/system/cdevSync.h @@ -0,0 +1,139 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevSync class (abstract base class) +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevSync.h,v +// Revision 1.3 1997/02/18 15:45:43 chen +// port to linux 2.0.x + addUserFdCallback +// +// Revision 1.2 1996/03/22 17:57:45 chen +// change attach/detach ReadFd to virtual +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#ifndef _CDEV_SYNC_H +#define _CDEV_SYNC_H + +#include +#include +#include +#include +#include + +class CDEV_CLASS_SPEC cdevSync{ + public: + // destructors + virtual ~cdevSync (void); + + virtual int flush (void) = 0; + // PURPOSE: pure virtual function to define intreface for net flush + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS + + virtual int poll (void) = 0; + // PURPOSE: pure virtual function to define intreface for polling method + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS: OK. return -1: network error + + virtual int pend (int fd = -1) = 0; + // PURPOSR: pure virtual function to define interface for pending method + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS, OK, return -1: network error + + virtual int pend (double seconds, int fd = -1) = 0; + // PURPOSR: pure virtual function to define interface for pending method + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS, OK, return CDEV_TIMEOUT: timeout. + // -1: network error + + virtual const char *className (void) const {return "cdevSync";} + + protected: + // constructor + cdevSync (void); + + virtual int attachReadFd (int fd); + // PURPOSE: add a new file descriptor to mask + // REQURIE: fd > 3. You know what I mean + // PROMISE: return 0 success + + virtual int detachReadFd (int fd); + // PURPOSE: remove a file descriptor from the mask + // REQUIRE: fd > 3 + // PROMISE: return 0 success + + int handleEvents (void); + // PURPOSE: wait until IO events arrive and dispatch IO events + // REQUIRE: nothing + // PROMISE: return 0: success, -1: error + + virtual int handleEvents (cdevTimeValue *tv); + // PURPOSE: handle IO events for upto 'tv' long + // REQUIRE: nothing + // PROMISE: return 0: success at least one IO event occured, 1: timeout + + int waitFor (cdevFdSet &rmaskret, + cdevFdSet &wmaskret, + cdevFdSet &emaskret, + cdevTimeValue *how_long); + // PURPOSE: Wait for IO events to occur upto time 'how_long' + // REQUIRE: nothing + // PROMISE: >0 IO event ready. 0 nothing, timeout + + void dispatch (int nfound, + cdevFdSet &rmaskret, + cdevFdSet &wmaskret, + cdevFdSet &emaskret); + // PURPOSE: dispath IO events to the appropriate service + // REQUIRE: nothing + // PROMISE: dispatched + + virtual void notifyService (int handle); + // PURPOSE: notify low level service there are IO events + // REQUIRE: derived class does real implementation + // PROMISE: nothing + + int handleError (void); + // PURPOSE: handle interrupt error while waiting for IO events + // REQUIRE: nothing + // PROMISE: return 1: interrupt or bad file descriptor, return -1: error + + int checkFds (void); + // PURPOSE: check whether file descriptors are valid + // REQUIRE: nothing + // PROMISE: return 1 always + + int checkFd (int fd); + // PURPOSE: check whether file descriptor fd is valid + // REQUIRE: nothing + // PROMISE: return 0 success, -1, failure + + int maxHandle (int i, int j, int k); + // PURPOSE: utility to calculate maximum of there integers + // REQUIRE: nothing + // PROMISE: maximum of there integers + + // File Descriptor Mask for IO Multiplexing + cdevFdSet rdMask_; + cdevFdSet wrMask_; + cdevFdSet exMask_; +}; +#endif + + + + + diff --git a/src/system/cdevSystem.cc b/src/system/cdevSystem.cc new file mode 100755 index 0000000..f3f21c8 --- /dev/null +++ b/src/system/cdevSystem.cc @@ -0,0 +1,1535 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevSystem class (implementation) +// +// Author: Jie Chen, Chip Watson & Walt Akers +// +// Revision History: +// cdevSystem.cc,v +// Revision 1.20 1998/02/13 14:23:06 chen +// add fall through service behaviour +// +// Revision 1.19 1998/02/13 14:03:40 chen +// check timer queue in poll +// +// Revision 1.18 1998/02/10 18:05:47 chen +// add add/removeTimer to the system +// +// Revision 1.17 1997/12/22 18:23:06 akers +// Ongoing development of 1.6.2 +// +// Revision 1.16 1997/12/12 16:39:42 chen +// add fix for VMS +// +// Revision 1.15 1997/08/27 18:23:32 chen +// Change error reporting to site specific scheme +// +// Revision 1.14 1997/08/07 13:36:33 akers +// Converted CDEV_MAJOR_VERSION and CDEV_MINOR_VERSION to strings to support adding minor revision numbers +// +// Revision 1.13 1997/03/03 17:35:45 chen +// add buffering to channel access connection +// +// Revision 1.11 1997/01/29 17:58:42 akers +// Patch for notifyService +// +// Revision 1.10 1997/01/29 17:39:35 akers +// Removed assertion from cdevSystem +// +// Revision 1.9 1996/03/22 17:57:06 chen +// add cdevFdChangedCallback +// +// Revision 1.8 1995/10/26 14:33:32 akers +// Removal of Warnings +// +// Revision 1.7 1995/10/03 20:07:33 chen +// use cdevGlobalTagTable class +// +// Revision 1.6 1995/08/17 19:41:05 danjin +// added missing %s in printf command +// +// Revision 1.5 1995/07/19 20:32:43 akers +// Added command cdevGlobalTagTable.initialize() to the constructor +// +// Revision 1.4 1995/07/14 11:51:39 akers +// Modifications to support changes in cdevData class. +// +// Revision 1.3 1995/07/05 18:45:32 chen +// allow access to devices etc... +// +// Revision 1.2 1995/06/30 16:06:25 chen +// remove all unnecessary files and use a genric list and hash +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +//----------------------------------------------------------------------------- + +#include +#include +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cdevService.h" +#include "cdevSystem.h" + +const char * cdevSystem::CDEV_MAJOR_VERSION ="1"; +const char * cdevSystem::CDEV_MINOR_VERSION ="7.2"; + +// ***************************************************************************** +// * These inline functions are defined here for use in this module. +// * max and min are also defined in WINDEF.H in WIN Platform +// ***************************************************************************** +#ifndef max +inline int max (int a, int b) { return a>b?a:b; } +#endif + +#ifndef min +inline int min (int a, int b) { return aloadConfig (); +} + + +// ***************************************************************************** +// * cdevSystem::~cdevSystem : +// * This is the destructor for the cdevSystem object. It will delete any +// * data that was allocated to the class. +// ***************************************************************************** +cdevSystem::~cdevSystem(void) +{ +#ifdef _TRACE_OBJECTS + printf(" Delete cdevSystem Class\n"); +#endif + + if (systemName_ == 0) + return; + + // ********************************************************************* + // * Remove this system from the list + // ********************************************************************* + cdevSystem::remove(this); + + // ********************************************************************* + // * Free all memory associated with this syetem + // ********************************************************************* +#if !defined (_WIN32) + // On Win32, a dynamic loaded dll (services and requestobjects) will be + // detached before code reach here when programs quit. + freeMemory(); +#endif + + delete[]systemName_; + if(prefix_) + delete[]prefix_; + + activeGrps_=0; + + // ********************************************************************* + // * ns_ will be removed from device list + // * errObj_ will be deleted through device list + // * but I have to remove service finder + // ********************************************************************* + delete svcFinder_; + + // ********************************************************************* + // * remove errSvc Object. + // * Lock removal since errSvcObj_ is not registered + // ********************************************************************* + errSvcObj_->unregOn_=0; + delete errSvcObj_; + + // ********************************************************************* + // * remove transaction object and more + // ********************************************************************* + delete defXobj_; + delete defCallbackObj_; + + // ********************************************************************* + // * remove configuration finder + // ********************************************************************* + delete configFinder_; +} + + +// ***************************************************************************** +// * cdevSystem::attachRef : +// * This method allows the caller to obtain a reference to a specific +// * cdevSystem object. +// ***************************************************************************** +cdevSystem & +cdevSystem::attachRef(char *name, char *prefix) +{ + return *cdevSystem::attachPtr(name, prefix); +} + + +// ***************************************************************************** +// * cdevSystem::attachPtr : +// * This method allows the caller to obtain a pointer to a specific +// * cdevSystem object. +// ***************************************************************************** +cdevSystem * +cdevSystem::attachPtr(char *name, char *prefix) +{ + cdevSystem *newSystem=0; + + cdevSlistIterator sit(cdevSystem::systemList_()); + int found=0; + + for(sit.init(); !sit; ++sit) + { + newSystem=(cdevSystem *) sit(); + if(::strcmp(name, newSystem->name()) == 0) + { + if(prefix && newSystem->prefix() && ::strcmp(prefix, newSystem->prefix()) == 0) + found=1; + else if(!prefix && !newSystem->prefix()) + found=1; + else + found=0; + } + if(found) + break; + } + if(found) + { + newSystem->refCount_++; + return newSystem; + } + else + return(new cdevSystem(name, prefix)); +} + + +// ***************************************************************************** +// * cdevSystem::getDevice : +// * This method allows the caller to obtain a pointer to a specified +// * cdevDevice object. +// ***************************************************************************** +cdevDevice * +cdevSystem::getDevice(char *name) +{ + cdevDevice *dev=0; + dev=cdevDevice::attachPtr(name, *this); + return dev; +} + + +// ***************************************************************************** +// * cdevSystem::prefix : +// * This method returns the prefix string which has been associated with +// * this cdevSystem object. +// ***************************************************************************** +char * +cdevSystem::prefix(void) const +{ + return prefix_; +} + + +// ***************************************************************************** +// * cdevSystem::prefix : +// * This method allows the caller to specify the prefix string which will +// * be associated with this cdevSystem object. +// ***************************************************************************** +void +cdevSystem::prefix(char *pre) +{ + if(prefix_) + { + delete[]prefix_; + prefix_=0; + } + prefix_=new char[::strlen(pre)+1]; + ::strcpy(prefix_, pre); +} + + +// ***************************************************************************** +// * cdevSystem::freeMemory : +// * This method will delete all devices and services that are associated +// * with this cdevSystem object. +// ***************************************************************************** +void +cdevSystem::freeMemory(void) +{ + // ********************************************************************* + // * Delete all devices + // ********************************************************************* + cdevStrHashIterator sit1(deviceList_); + cdevDevice *tdev=0; + for(sit1.init(); !sit1; ++sit1) + { + // ************************************************************* + // * Turn off unregister flags off so device destructor will not + // * remove itself again + // ************************************************************* + tdev=(cdevDevice *) sit1(); + tdev->unregOn_=0; +#ifdef _CDEV_DEBUG + printf("Free device %s\n", tdev->name()); +#endif + delete tdev; + } + + // ********************************************************************* + // * Delete all services + // ********************************************************************* + cdevSlistIterator sit(serviceList_); + cdevService *tsvc=0; + for(sit.init(); !sit; ++sit) + { + // ************************************************************* + // * Turn off unregister flags off so service destructor will + // * not remove itself again + // ************************************************************* + tsvc=(cdevService *) sit(); + tsvc->unregOn_=0; +#ifdef _CDEV_DEBUG + printf("Free service %s\n", tsvc->name()); +#endif + delete tsvc; + } + // ********************************************************************* + // * Don't delete groups, groups are dynamic variables + // * Don't worry about active group + // ********************************************************************* +} + + +// ***************************************************************************** +// * cdevSystem::defaultSystem : +// * This method returns a static cdevSystem object that is used as the +// * default cdevSystem object. +// ***************************************************************************** +cdevSystem & cdevSystem::defaultSystem(void) +{ + // ********************************************************************* + // * Make sure default system constructed before being used + // ********************************************************************* + static cdevSystem sys("cdevDefaultSystem"); + return sys; +} + +// ***************************************************************************** +// * cdevSystem::finalize +// * This method clean up system memory and everything +// * Any calls after this will have unexpected behaviour +// ***************************************************************************** +void +cdevSystem::finalize (void) +{ + // ********************************************************************* + // * Remove this system from the list + // ********************************************************************* + cdevSystem::remove(this); + + // ********************************************************************* + // * Free all memory associated with this syetem + // ********************************************************************* + freeMemory(); + + delete[]systemName_; + systemName_ = 0; + + if(prefix_) + delete[]prefix_; + + activeGrps_=0; + + // ********************************************************************* + // * ns_ will be removed from device list + // * errObj_ will be deleted through device list + // * but I have to remove service finder + // ********************************************************************* + delete svcFinder_; + + // ********************************************************************* + // * remove errSvc Object. + // * Lock removal since errSvcObj_ is not registered + // ********************************************************************* + errSvcObj_->unregOn_=0; + delete errSvcObj_; + + // ********************************************************************* + // * remove transaction object and more + // ********************************************************************* + delete defXobj_; + delete defCallbackObj_; + + // ********************************************************************* + // * remove configuration finder + // ********************************************************************* + delete configFinder_; +} + +// ***************************************************************************** +// * cdevSystem::nameServer : +// * This method returns a pointer to a cdevDirectory object that is used +// * by the cdevSystem to perform directory operations. +// ***************************************************************************** +cdevDirectory & +cdevSystem::nameServer(void) +{ + return *ns_; +} + + +// ***************************************************************************** +// * cdevSystem::errorRequestObject : +// * This method returns an error request object that will be used whenever +// * a caller creates a cdevRequestObject using an invalid device/message +// * combination. +// ***************************************************************************** +cdevRequestObject * +cdevSystem::errorRequestObject(void) +{ + if(errObj_) + return errObj_; + else + return new cdevErrReqObject(*this); +} + + +// ***************************************************************************** +// * cdevSystem::errorRequestObject : +// * This method allows the caller to specify the error request object that +// * will be used to process invalid device/message combinations. +// ***************************************************************************** +void +cdevSystem::errorRequestObject(cdevRequestObject *obj) +{ + // obj = 0; + errObj_=obj; +} + + +// ***************************************************************************** +// * cdevSystem::systemList_ : +// * This method allows the caller to retrieve a list of cdevSystem objects +// * that have been instanciated. +// ***************************************************************************** +cdevSlist & +cdevSystem::systemList_(void) +{ + // ********************************************************************* + // * Make sure static list constructed before being used + // ********************************************************************* + static cdevSlist list; + return list; +} + + +// ***************************************************************************** +// * cdevSystem::name : +// * This method allows the caller to obtain the name of this cdevSystem +// * object. +// ***************************************************************************** +char * +cdevSystem::name(void) const +{ + return systemName_; +} + + +// ***************************************************************************** +// * cdevSystem::remove : +// * This method allows the caller to remove a specific cdevSystem object +// * from the internal system list. +// ***************************************************************************** +int +cdevSystem::remove(cdevSystem *system) +{ +#ifdef _CDEV_DEBUG + printf("remove system %s from the list\n", system->name()); +#endif + cdevSystem::systemList_().remove((void *) system); + return CDEV_SUCCESS; +} + + +// ***************************************************************************** +// * cdevSystem::registerService : +// * This method is used to register a service with the cdevSystem object. +// ***************************************************************************** +int +cdevSystem::registerService(cdevService *service) +{ + if(!serviceList_.includes((void *) service)) + { +#ifdef _CDEV_DEBUG + printf("register new service %s\n", service->name()); +#endif + serviceList_.add((void *) service); + return CDEV_SUCCESS; + } + else + { +#ifdef _CDEV_DBUG + printf("this service %s is already here\n", service->name()); +#endif + return CDEV_ERROR; + } +} + + +// ***************************************************************************** +// * cdevSystem::removeService : +// * This method is used to remove a service that has been registered with +// * with this cdevSystem object. +// ***************************************************************************** +int +cdevSystem::removeService(cdevService *service) +{ +#ifdef _CDEV_DEBUG + printf("remove service %s from the list\n", service->name()); +#endif + serviceList_.remove((void *) service); + return CDEV_SUCCESS; +} + + +// ***************************************************************************** +// * cdevSystem::serviceCreated : +// * This method allows the caller to determine if a service has been +// * created and installed in the service list for this cdevSystem object. +// ***************************************************************************** +int +cdevSystem::serviceCreated(char *serviceName) +{ + cdevSlistIterator sit(serviceList_); + int found=0; + cdevService *tsvc=0; + + for(sit.init(); !sit; ++sit) + { + tsvc=(cdevService *) sit(); + if(::strcmp(tsvc->name(), serviceName) == 0) + { +#ifdef _CDEV_DEBUG + printf("This service %s has been created\n", tsvc->name()); +#endif + found=1; + break; + } + } + return found; +} + + +// ***************************************************************************** +// * cdevSystem::service : +// * This method allows the caller to get a pointer to a cdevService object +// * by providing the name of the service. +// ***************************************************************************** +cdevService * +cdevSystem::service(char *serviceName) +{ + cdevSlistIterator sit(serviceList_); + int found=0; + cdevService *obj=0; + + for(sit.init(); !sit; ++sit) + { + obj=(cdevService *) sit(); + if(::strcmp(obj->name(), serviceName) == 0) + { + found=1; + break; + } + } + if(found) + return obj; + else + return 0; +} + + +// ***************************************************************************** +// * cdevSystem::loadService : +// * This method causes the cdevSystem object to load the specified service. +// ***************************************************************************** +cdevService * +cdevSystem::loadService(char *serviceName) +{ + cdevService *svc=0; + int status=svcFinder_->getService(serviceName, svc); + if(status == 0) + return svc; + else + return 0; +} + + +// ***************************************************************************** +// * cdevSystem::suspendService : +// * This method causes the cdevSystem object to suspend processing of the +// * specified service's file descriptors. +// ***************************************************************************** +int +cdevSystem::suspendService(cdevService * /* service */) +{ + return CDEV_SUCCESS; +} + + +// ***************************************************************************** +// * cdevSystem::resumeService : +// * This method causes the cdevSystem object to resume processing +// * events on the specified service's file descriptors. +// ***************************************************************************** +int +cdevSystem::resumeService(cdevService * /* service */) +{ + return CDEV_SUCCESS; +} + + +// ***************************************************************************** +// * cdevSystem::registerDevice : +// * This method is used to register the specified cdevDevice with the +// * the cdevSystem object ( if the device is not already registered). +// ***************************************************************************** +int +cdevSystem::registerDevice(cdevDevice *dev) +{ + if(!deviceList_.find((char *) dev->name(), (void *) dev)) + { +#ifdef _CDEV_DEBUG + printf("add new device %s\n", dev->name()); +#endif + deviceList_.add((char *) dev->name(), (void *) dev); + return CDEV_SUCCESS; + } + else + { +#ifdef _CDEV_DEBUG + printf("this device %s is already here: Error++++\n", dev->name()); +#endif + return CDEV_ERROR; + } +} + + +// ***************************************************************************** +// * cdevSystem::removeDevice : +// * This method will remove the named device from the device list that is +// * maintained by the cdevSystem object. +// ***************************************************************************** +int +cdevSystem::removeDevice(cdevDevice *dev) +{ +#ifdef _CDEV_DEBUG + printf("remove device %s\n", dev->name()); +#endif + deviceList_.remove((char *) dev->name(), (void *) dev); + return CDEV_SUCCESS; +} + + +// ***************************************************************************** +// * cdevSystem::deviceCreated : +// * This method returns a boolean value that indicates if the cdevDevice +// * specified by device name has been created already. +// ***************************************************************************** +int +cdevSystem::deviceCreated(char *deviceName) +{ + cdevSlist &list=deviceList_.bucketRef(deviceName); + cdevSlistIterator sit(list); + cdevDevice *tdev=0; + int found=0; + + for(sit.init(); !sit; ++sit) + { + tdev=(cdevDevice *) sit(); + if(::strcmp(tdev->name(), deviceName) == 0) + { +#ifdef _CDEV_DEBUG + printf("this device %s is already created\n", tdev->name()); +#endif + found=1; + break; + } + } + return found; +} + + +// ***************************************************************************** +// * cdevSystem::device : +// * This method allows the caller to obtain a cdevDevice object using the +// * name of the device. +// ***************************************************************************** +cdevDevice * +cdevSystem::device(char *deviceName) +{ + cdevSlist &list=deviceList_.bucketRef(deviceName); + cdevSlistIterator sit(list); + int found=0; + cdevDevice *obj=0; + + for(sit.init(); !sit; ++sit) + { + obj=(cdevDevice *) sit(); + if(::strcmp(obj->name(), deviceName) == 0) + { + found=1; + break; + } + } + if(found) + return obj; + else + return 0; +} + + +// ***************************************************************************** +// * cdevSystem::registerGroup : +// * This method allows the caller to register a new group with the +// * cdevSystem object. +// ***************************************************************************** +int +cdevSystem::registerGroup(cdevGroup *grp) +{ + if(groupList_.count() < MAX_NUM_GROUPS && !groupList_.includes((void *) grp)) + { +#ifdef _CDEV_DEBUG + printf("Add new group\n"); +#endif + groupList_.add((void *) grp); + return CDEV_SUCCESS; + } + else + { +#ifdef _CDEV_DEBUG + printf("Exceeds max num of group limit: Error++++++\n"); +#endif + return CDEV_ERROR; + } +} + + +// ***************************************************************************** +// * cdevSystem::removeGroup : +// * This method allows the caller to remove a cdevgroup object from the +// * list that is maintained within the cdevSystem object. +// ***************************************************************************** +int +cdevSystem::removeGroup(cdevGroup *grp) +{ +#ifdef _CDEV_DEBUG + printf("Remove a group\n"); +#endif + groupList_.remove((void *) grp); + activeGroupList_.remove((void *) grp); + return CDEV_SUCCESS; +} + + +// ***************************************************************************** +// * cdevSystem::registerActiveGroup : +// ***************************************************************************** +int +cdevSystem::registerActiveGroup(cdevGroup *grp) +{ + if(groupList_.count() < MAX_NUM_GROUPS && !groupList_.includes((void *) grp)) + { + groupList_.add((void *) grp); + } + if(!activeGroupList_.includes((void *) grp)) + { +#ifdef _CDEV_DEBUG + printf("Add an active group\n"); +#endif + activeGroupList_.add((void *) grp); + activeGrps_=1; + return CDEV_SUCCESS; + } + return CDEV_ERROR; +} + + +// ***************************************************************************** +// * cdevSystem::removeActiveGroup +// ***************************************************************************** +int +cdevSystem::removeActiveGroup(cdevGroup *grp) +{ +#ifdef _CDEV_DEBUG + printf("remove an active group\n"); +#endif + int status=activeGroupList_.remove((void *) grp); + if(activeGroupList_.count() == 0) + activeGrps_=0; + return CDEV_SUCCESS; +} + + +// ***************************************************************************** +// * cdevSystem::activeGroups : +// ***************************************************************************** +int +cdevSystem::activeGroups(cdevGroup **groups, int &numGroups) +{ + numGroups=activeGroupList_.count(); + if(numGroups > 0) + { + cdevSlistIterator sit(activeGroupList_); + int i=0; + for(sit.init(); !sit; ++sit) + { + groups[i++]=(cdevGroup *) sit(); + } + } + return CDEV_SUCCESS; +} + + +// ***************************************************************************** +// * cdevSystem::activeGroups +// ***************************************************************************** +int +cdevSystem::activeGroups(void) const +{ + return activeGrps_; +} + + +// ***************************************************************************** +// * cdevSystem::attachReadFd : +// * This method is called to add a newly opened file descriptor to the +// * cdevFdSet that is used to maintain the list of file descriptors. If +// * the file descriptor has been newly opened, a used specified callback +// * will be executed to notify the user of the new file descriptor. +// ***************************************************************************** +int +cdevSystem::attachReadFd(int fd) +{ + int status=cdevSync::attachReadFd(fd); + + if(status == CDEV_SUCCESS) + { + cdevSlistIterator ite(fdCbkList_); + cdevSlistIterator itearg(fdCbkArgList_); + cdevFdChangedCallback cbkfunc=0; + void *userarg=0; + + // ************************************************************* + // * processing two lists at the same pace + // ************************************************************* + itearg.init(); + while(!itearg) + { + for(ite.init(); !ite; ++ite) + { + cbkfunc=(cdevFdChangedCallback) ite(); + userarg=itearg(); + // ********************************************* + // * call registered callback + // ********************************************* + + (*cbkfunc) (fd, 1, userarg); + ++itearg; + } + } + } + return status; +} + + + +// ***************************************************************************** +// * cdevSystem::detachReadFd : +// * This method is called to remove a file descriptor from the list of +// * file descriptors that the cdevSystem object will pend for events. If +// * the fd was previously registered with the cdevSystem object, then a +// * user specified callback will be executed to notify the user that +// * the file descriptor is no longer in use. +// ***************************************************************************** +int +cdevSystem::detachReadFd(int fd) +{ + int status=cdevSync::detachReadFd(fd); + + if(status == CDEV_SUCCESS) + { + cdevSlistIterator ite(fdCbkList_); + cdevSlistIterator itearg(fdCbkArgList_); + cdevFdChangedCallback cbkfunc=0; + void *userarg=0; + + // ************************************************************* + // * Processing two lists at the same pace + // ************************************************************* + itearg.init(); + while(!itearg) + { + for(ite.init(); !ite; ++ite) + { + cbkfunc=(cdevFdChangedCallback) ite(); + userarg=itearg(); + // ********************************************* + // * Call registered callback + // ********************************************* + (*cbkfunc) (fd, 0, userarg); + ++itearg; + } + } + } + return status; +} + +// ***************************************************************************** +// * cdevSystem::addFdChangedCallback : +// * This method allows the caller to specify a callback function that +// * will be executed each time a file descriptor is added or removed from +// * the list of file descriptors that the cdevSystem object will poll for +// * events. +// ***************************************************************************** +int +cdevSystem::addFdChangedCallback(cdevFdChangedCallback cbk, void *arg) +{ + fdCbkList_.add((void *) cbk); + fdCbkArgList_.add(arg); + return CDEV_SUCCESS; +} + +// ***************************************************************************** +// * cdevSystem::addUserFdCallback : +// * This method allows the caller to specify a callback function that +// * will be executed each time there are something to be read at this +// * file descriptor. The callback function should return 0 on success +// * read, and -1 on an IO faliure +// ***************************************************************************** +int +cdevSystem::addUserFdCallback (int fd, cdevUserFdCallback cbk, void* arg, + cdevUserFdCbkId& id) +{ + // first check whether this fd is already in the monitored list + int efd[256]; + int ec = 256; + int es = CDEV_SUCCESS; + + if ((es = getFd (efd, ec)) != CDEV_SUCCESS) + return es; + + for (int i = 0; i < ec; i++) { + if (efd[i] == fd) + return CDEV_INVALIDARG; + } + + // check whether this fd is a bad fd + if (checkFd (fd) < 0) + return CDEV_IOFAILED; + + // now create a unique userFdService + char tempsvcn[32]; + strcpy (tempsvcn, cdevUserFdService::prefixName ()); +#ifdef _WIN32 + _mktemp (tempsvcn); +#else + // get a unique name + mkstemp (tempsvcn); +#endif +#ifdef _CDEV_DEBUG + printf ("Create a cdevUserFdService: %s \n", tempsvcn); +#endif + + cdevUserFdService* fdsvc = new cdevUserFdService (fd, cbk, arg, tempsvcn, + *this); + id = (cdevUserFdCbkId)fdsvc; + return CDEV_SUCCESS; +} + +int +cdevSystem::removeUserFdCallback (cdevUserFdCbkId id) +{ + cdevUserFdService* fdsvc = (cdevUserFdService *)id; + + if (serviceCreated (fdsvc->name ()) ) { + removeService (fdsvc); + delete fdsvc; + return CDEV_SUCCESS; + } + return CDEV_ERROR; +} + + +// ***************************************************************************** +// * cdevSystem::flush : +// * This method calls the flush method of each of the services that are +// * maintained in the internal service list. The service's flush mechanism +// * should force all of their buffers to be written to the respective +// * underlying control systems. +// ***************************************************************************** +int +cdevSystem::flush(void) +{ + cdevSlistIterator sit(serviceList_); + cdevService *tsvc=0; + + for(sit.init(); !sit; ++sit) + { + tsvc=(cdevService *) sit(); + tsvc->flush(); + } + return CDEV_SUCCESS; +} + + +// ***************************************************************************** +// * cdevSystem::setupMask : +// * This method will setup the file descriptor mask for the service +// * provided file descriptors. +// ***************************************************************************** +void +cdevSystem::setupMask ( void ) +{ + static cdevFdSet newSet; + fd_set * newSetData = (fd_set *)newSet; + fd_set * oldSetData = (fd_set *)rdMask_; + int * fd; + int numFds; + + cdevSlistIterator sit(serviceList_); + cdevService *tsvc=0; + + // ********************************************************************* + // * Clean all fd masks, except the read mask... it will be explictly + // * updated. + // ********************************************************************* + wrMask_.reset(); + exMask_.reset(); + + // ********************************************************************* + // * Reset the newSet data. + // ********************************************************************* + newSet.reset(); + + // ********************************************************************* + // * Load all of the service file descriptors into the newSet. + // ********************************************************************* + for(sit.init(); !sit; ++sit) + { + fd = NULL; + numFds = 0; + tsvc = (cdevService *) sit(); + + tsvc->getFd(fd, numFds); + while(numFds>0) + { + numFds--; + newSet.set_bit(fd[numFds]); + } + } + + // ********************************************************************* + // * If the two groups of fd_set objects are different, figure out how + // * many bits have to be compared to find all changes, then walk + // * through the list and set the appropriate flags in the rdMask_ + // * object. + // ********************************************************************* + int max_set = max(newSet.max_set(), rdMask_.max_set()); + if(max_set > 0 && memcmp(newSetData, oldSetData, sizeof(fd_set))!=0) + { + long set_flag = 0; + while(max_set > 0) + { + set_flag = FD_ISSET(max_set, newSetData); + if(set_flag != FD_ISSET(max_set, oldSetData)) + { + if(set_flag) attachReadFd(max_set); + else detachReadFd(max_set); + } + max_set--; + } + } +} + + +// ***************************************************************************** +// * cdevSystem::poll : +// * This method will poll each of the underlying services, giving the +// * opportunity to process any read or write events that they may have. +// ***************************************************************************** +int +cdevSystem::poll(void) +{ + cdevSlistIterator sit(serviceList_); + cdevService *tsvc=0; + + for(sit.init(); !sit; ++sit) + { + tsvc=(cdevService *) sit(); + tsvc->poll(); + } + + // check timer queue here + cdevTimeValue timerSkew (0, 1000*10); // solaris timer skew + if (!timerQueue_.isEmpty ()) + timerQueue_.expire (cdevTimeValue::currentTime () + timerSkew); + + return CDEV_SUCCESS; +} + + +// ***************************************************************************** +// * cdevSystem::pend : +// * This method causes the cdevSystem object to wait for an event to occur +// * on one of the underlying file descriptors. +// ***************************************************************************** +int +cdevSystem::pend(int) +{ + // ********************************************************************* + // * Flush all I/O out + // ********************************************************************* + flush(); + + // ********************************************************************* + // * Setup the file descriptor mask. + // ********************************************************************* + setupMask (); + + // ********************************************************************* + // * Check IO ready + // ********************************************************************* + return handleEvents((cdevTimeValue *)0); +} + + +// ***************************************************************************** +// * cdevSystem::pend : +// * This method causes the cdevSystem object to wait a specified number +// * of seconds for an event to occur on one of the underlying file +// * descriptors. +// ***************************************************************************** +int +cdevSystem::pend(double seconds, int) +{ + if(seconds > 0.0) + { + // ************************************************************* + // * Flush all io out + // ************************************************************* + flush(); + + // ********************************************************************* + // * Setup the file descriptor mask. + // ********************************************************************* + setupMask (); + + // ************************************************************* + // * Check IO ready + // ************************************************************* + cdevTimeValue how_long(seconds); + return handleEvents(&how_long); + } + else return poll(); +} + + +// ***************************************************************************** +// * cdevSystem::getRequestObject : +// * This method will obtain the request object associated with the +// * specified device/message combination. +// ***************************************************************************** +int +cdevSystem::getRequestObject(char *deviceName, char *msg, cdevRequestObject* &req) +{ + req=cdevRequestObject::attachPtr(deviceName, msg, *this); + if(req) + return CDEV_SUCCESS; + else + return CDEV_ERROR; +} + + +// ***************************************************************************** +// * cdevSystem::addTimer +// ***************************************************************************** +int +cdevSystem::addTimer (cdevTimerHandler* handler, + const void* arg, + double delay, double interval) +{ + cdevTimeValue t0 (delay); + cdevTimeValue td = t0 + cdevTimeValue::currentTime (); + + if (interval > 0.000001) { + cdevTimeValue ti (interval); + return timerQueue_.scheduleTimer (handler, arg, td, ti); + } + else + return timerQueue_.scheduleTimer (handler, arg, td); +} + + +// ***************************************************************************** +// * cdevSystem::removeTimer +// ***************************************************************************** +int +cdevSystem::removeTimer (cdevTimerHandler* handler) +{ + if (timerQueue_.cancel (handler) != 0) + return CDEV_ERROR; + return CDEV_SUCCESS; +} + +// ***************************************************************************** +// * cdevSystem::removeTimer +// ***************************************************************************** +int +cdevSystem::removeTimer (int id) +{ + if (timerQueue_.cancel (id) != 0) + return CDEV_ERROR; + return CDEV_SUCCESS; +} + +// ***************************************************************************** +// * cdevSystem::enableDefaultSvc +// ***************************************************************************** +void +cdevSystem::enableDefaultSvc (void) +{ + defaultSvc_ = 1; +} + +void +cdevSystem::disableDefaultSvc (void) +{ + defaultSvc_ = 0; +} + +int +cdevSystem::defaultSvc (void) const +{ + return defaultSvc_; +} + +// ***************************************************************************** +// * cdevSystem::notifyService : +// ***************************************************************************** +void +cdevSystem::notifyService(int handle) +{ + cdevService *service=getService(handle); + + if(service && service->pend(handle) < 0) + { + // ************************************************************* + // * Remove this file descriptor + // ************************************************************* + detachReadFd(handle); + } +} + + +// ***************************************************************************** +// * cdevSystem::getService : +// * This method allows the caller to obtain a pointer to the cdevService +// * that is associated with the specified file handle. +// ***************************************************************************** +cdevService * +cdevSystem::getService(int handle) +{ + cdevSlistIterator sit(serviceList_); + cdevService *tsvc=0; + + for(sit.init(); !sit; ++sit) + { + tsvc=(cdevService *) sit(); + int *fd=0; + int numFds=0; + tsvc->getFd(fd, numFds); + if(numFds != 0) + { + for(int j=0; j < numFds; j++) + if(handle == fd[j]) + { + return tsvc; + } + numFds=0; + } + } + return(cdevService *) 0; +} + + +// ***************************************************************************** +// * cdevSystem::getFd : +// * This method will return the list of file handles that are currently +// * being managed by this cdevSystem object. If the buffer provided is +// * too small (as specified in numFD), CDEV_ERROR will be returned. +// * Otherwise, the fd array will be populated with the list of file +// * descriptors, the number of items will be placed in the numFd parameter, +// * and CDEV_SUCCESS will be returned. +// ***************************************************************************** +int +cdevSystem::getFd(int fd[], int &numFD) +{ + cdevSlistIterator sit(serviceList_); + cdevService *tsvc=0; + + int k=0; + int oldNumFD=numFD; + for(sit.init(); !sit; ++sit) + { + tsvc=(cdevService *) sit(); + int *ifd=0; + int inumFds=0; + tsvc->getFd(ifd, inumFds); + if(inumFds != 0) + { + for(int j=0; j < inumFds; j++) + { + if(k >= oldNumFD) + return CDEV_INVALIDARG; + fd[k++]=ifd[j]; + } + inumFds=0; + } + } + numFD=k; + return CDEV_SUCCESS; +} + +// ***************************************************************************** +// * cdevSystem::handleEvents +// ***************************************************************************** +int +cdevSystem::handleEvents (cdevTimeValue *tv) +{ + cdevFdSet rmaskret; + cdevFdSet wmaskret; + cdevFdSet emaskret; + int nfound = 0, status = 1; + cdevClock timer; + cdevTimeValue timerSkew (0, 1000*10); // solaris timer skew + + if (!tv) { + cdevTimeValue* timeout = calculateTimeOut (tv); + + nfound = waitFor (rmaskret, wmaskret, emaskret, timeout); + // really handle lower level pend here + dispatch (nfound, rmaskret, wmaskret, emaskret); + + if (nfound > 0) + status = 0; + + if (!timerQueue_.isEmpty ()) + timerQueue_.expire (cdevTimeValue::currentTime () + timerSkew); + } + else { + timer.schedule (0, *tv); + while (!timer.expired()){ + // maximum time out value + cdevTimeValue newTv = timer.scheduledTime() - cdevTimeValue::currentTime(); + // caculate timeout value from timer queue + cdevTimeValue* timeout = calculateTimeOut (&newTv); + + nfound = waitFor (rmaskret, wmaskret, emaskret, timeout); + // really handle lower level pend here + dispatch (nfound, rmaskret, wmaskret, emaskret); + + if (nfound > 0) + status = 0; + + // handle timer callbacks + if (!timerQueue_.isEmpty ()) + timerQueue_.expire (cdevTimeValue::currentTime () + timerSkew); + } + } + // status == 0 stands for there is at least one IO event + if (status == 0) + return CDEV_SUCCESS; + return CDEV_TIMEOUT; +} + +// ***************************************************************************** +// * cdevSystem::calculate timeout +// ***************************************************************************** +cdevTimeValue * +cdevSystem::calculateTimeOut (cdevTimeValue* maxTimeOut) +{ + static cdevTimeValue timeout; + + if (timerQueue_.isEmpty ()) { + if (maxTimeOut) { + timeout = *maxTimeOut; + return &timeout; + } + return 0; + } + else { + cdevTimeValue currTime = cdevTimeValue::currentTime (); + + if (timerQueue_.earliestTime () > currTime) { + // The earliest time on the timer queue is still in the future. + // Therefore use smaller of (1) caller's wait timer or (2) the delta time + // between now and earliest time on the timer queue + timeout = timerQueue_.earliestTime () - currTime; + if (maxTimeOut == 0 || *maxTimeOut > timeout) + return &timeout; + else + return maxTimeOut; + } + else { + // The earliest time is now in the past. We have to call all + // timers + timeout = cdevTimeValue::zero; + return &timeout; + } + } +} + + diff --git a/src/system/cdevSystem.h b/src/system/cdevSystem.h new file mode 100755 index 0000000..e894d6b --- /dev/null +++ b/src/system/cdevSystem.h @@ -0,0 +1,466 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevSystem class +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevSystem.h,v +// Revision 1.18 1998/02/13 14:23:06 chen +// add fall through service behaviour +// +// Revision 1.17 1998/02/10 18:05:47 chen +// add add/removeTimer to the system +// +// Revision 1.16 1997/12/12 16:39:42 chen +// add fix for VMS +// +// Revision 1.15 1997/08/27 18:23:33 chen +// Change error reporting to site specific scheme +// +// Revision 1.14 1997/08/07 13:36:33 akers +// Converted CDEV_MAJOR_VERSION and CDEV_MINOR_VERSION to strings to support adding minor revision numbers +// +// Revision 1.13 1997/03/25 22:24:43 akers +// Development in support of a new cdevDirectory +// +// Revision 1.12 1997/03/03 17:35:47 chen +// add buffering to channel access connection +// +// Revision 1.10 1997/01/29 17:39:38 akers +// Removed assertion from cdevSystem +// +// Revision 1.9 1996/11/21 17:03:34 akers +// Ongoing Developement of CDEV 1.5 +// +// Revision 1.8 1996/09/20 12:24:58 akers +// Changes added for Release 1.4 +// +// Revision 1.7 1996/04/05 22:02:24 chen +// fix static enum problem with gcc +// +// Revision 1.6 1996/03/27 16:03:10 akers +// Added CDEV_MAJOR_VERSION and CDEV_MINOR_VERSION to the cdevSystem object +// +// Revision 1.5 1996/03/22 17:57:00 chen +// add cdevFdChangedCallback +// +// Revision 1.4 1995/10/05 18:40:45 chen +// Move destructor to public, static needs it +// +// Revision 1.3 1995/07/05 18:45:41 chen +// allow access to devices etc... +// +// Revision 1.2 1995/06/30 16:06:26 chen +// remove all unnecessary files and use a genric list and hash +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#ifndef _CDEV_SYSTEM_H +#define _CDEV_SYSTEM_H + +#include +#include +#include +#include +#include +#include + +#ifdef __VMS +extern "C" { +char* strdup (char *s); +char* mkstemp (char *s); +int htonl (int a); +int ntohl (int a); +}; +#endif + +class cdevService; +class cdevDevice; +class cdevRequestObject; +class cdevErrReqObject; +class cdevDirectory; +class cdevGroup; +class cdevExecGroup; +class cdevSvcFinder; +class cdevTranObj; +class cdevCallback; +class cdevErrSvc; +class cdevConfigFinder; + +// maximum number of groups inside a system +const int MAX_NUM_GROUPS = 5; + +// file descriptor changed callback +// opened = 1, newly opend fd, opened = 0, closed fd +typedef void (*cdevFdChangedCallback) (int fd, int opened, + void *arg); + +// arbitrary user fd callback (user let cdev to minitor his/her's fd) +// opened = 1, ok, opened = 0, fd is bad fd +// user should return 0: for success reading, -1: for failure +typedef int (*cdevUserFdCallback) (int opened, int fd, void *arg); + +// define user fd callback handler id +typedef long cdevUserFdCbkId; + + +class CDEV_CLASS_SPEC cdevSystem: public cdevSystemBase +{ +public: + // *************************************************************************** + // * The CDEV_MAJOR_VERSION and CDEV_MINOR_VERSION variables are used to + // * identify the version of CDEV shared objects that should be used. + // *************************************************************************** + + // WARNING: these two strings are deprecated in 1.7.x, and will be + // removed in 1.8, and replace with a single version string. + + static const char *CDEV_MAJOR_VERSION; + static const char *CDEV_MINOR_VERSION; + + //============================================================== + // Public interface for clients + //============================================================== + static cdevSystem& attachRef (char *name, char *prefix = 0); + static cdevSystem* attachPtr (char *name, char *prefix = 0); + // PURPOSE: cdevSystem creation factory + // REQUIRE: nothing + // PROMISE: return system reference or pointer + + cdevDevice* getDevice (char *device); + // PURPOSE: create a cdevDevice + // REQUIRE: device != 0 + // PROMISE: return a pointer to a cdevDevice + + char *name (void) const; + // PURPOSE: return name of this system + // REQUIRE: callers don't free memory + // PROMISE: name of this system + + char *prefix (void) const; + // PURPOSE: return prefix of this system + // REQUIRE: callers don't free memory + // PROMISE: prefix of this syste, + + void prefix (char *pre); + // PURPOSE: set prefix to this system + // REQUIRE: pre != 0 + // PROMISE: old prefix will be overwritten by new one + + virtual int flush (void); + // PURPOSE: flush all network request to all services + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS + + virtual int poll (void); + // PURPOSE: poll all network services + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS + + virtual int pend (int fd = -1); + // PURPOSE: pend all network services and dispatch IO event to right services + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS + + virtual int pend (double seconds, int fd = -1); + // PURPOSE: pend all network services for 'seconds' time long. + // Dispatch IO event to right services + // REQUIRE: nothing + // PROMISE: return CDEV_SUCCESS or CDEV_TIMEOUT + + static cdevSystem &defaultSystem (void); + // PURPOSE: Caller access to default system which is created automatically + // REQUIRE: nothing + // PROMISE: return the same system everytime one calls this + + void finalize (void); + // PURPOSE: clean up all system resources + // REQUIRE: last routine to call before quitting + // PROMISE: nothing + + int getFd (int fd[], int &numFD); + // PURPOSE: provide file descriptors to other system such as X window + // REQUIRE: user provide big enough integer buffer and buffer size + // PROMISE: numFD is real number of fds of success return CDEV_SUCCESS. + // return CDEV_INVALIDARG: not big enoght buffer + + int addFdChangedCallback (cdevFdChangedCallback cbk, void* arg); + // PURPOSE: provide file descriptor callback mechanism + // REQUIRE: none + // PROMISE: if lower cdevServices provide system any notification of + // fd changes, the system will call all registered callbacks + + int addUserFdCallback (int fd, cdevUserFdCallback cbk, void* arg, + cdevUserFdCbkId& id); + // PURPOSE: add user fd to system fd list, when there is something + // to be read at this fd, the user callback will be executed + // REQUIRE: none + // PROMISE: if fd is already inside the managed fd list, returns + // CDEV_INVALIDARG. if fd is a bad fd, returns CDEV_IOFAILED. + // CDEV_SUCCESS and valid id will denote a success + + int removeUserFdCallback (cdevUserFdCbkId id); + // PURPOSE: remove a user register fd callback with callback id + // REQUIRE: none + // PROMISE: return CDEV_NOTFOUND, if id is not found. return CDEV_SUCCESS + // if id has been removed (system will close associated fd if it + // is a not bad fd) + + int addTimer (cdevTimerHandler* handler, + const void* arg, + double delay, double interval = 0.0); + // PURPOSE: register a 'handler' that will expire + // after delay amount of seconds. If it expires then is + // passed in the function of handler. If + // interval != 0.0, then this timer becomes a repetitive timer + // with timer interval 'interval'. + // REQUIRE: handler must have a real timerCallback function + // PROMISE: A unique id will be returned. Callers can use this id + // to cancel timer before it expires. + + int removeTimer (cdevTimerHandler* handler); + // PURPOSE: remove timers associated with a 'handler' + // REQUIRE: none + // PROMISE: return CDEV_SUCCESS if all timers are removed. return CDEV_ERROR + // if there is no timer associated with this handler + + int removeTimer (int timerid); + // PURPOSE: remove a timer with timer id 'timerid' + // REQUIRE: none + // PROMISE: return CDEV_SUCCESS if the timer is removed. return CDEV_ERROR + // if this timer is not registered. + + void enableDefaultSvc (void); + void disableDefaultSvc (void); + // PURPOSE: enable/disable using default service if a device msg pair cannot + // match to any services + // REQUIRE: none + // PROMISE: + + int defaultSvc (void) const; + // PURPOSE: check whether a default service in used if a device msg pair + // cannot match any services + // REQUIRE: none + // PROMISE: return 1 true. return 0 false + + //=================================================================== + // Public interface for internal implementation use + //=================================================================== + virtual int registerService (cdevService *service); + // PURPOSE: register a service to the system + // REQUIRE: service != 0 + // PROMISE: service only be registered once + + virtual int removeService (cdevService *service); + // PURPOSE: remove this service from the system + // REQUIRE: service != 0 + // PROMISE: service will be removed, but service is sitll valid + + virtual int serviceCreated (char *serviceName); + // PURPOSE: check a service inside the system by name + // REQUIRE: serviceName != 0 + // PROMISE: return 1: found, 0: not found + + cdevService *service (char *serviceName); + // PURPOSE: return a service pointer inside system by name + // REQUIRE: serviceName != 0 + // PROMISE: return cdevService* != 0 on success, return 0: failure + + cdevService *loadService (char *serviceName); + // PURPOSE: load a new service by service name (shared library) + // REQUIRE: serviceName != 0 + // PROMISE: return cdevService* != 0 on success, return 0: failure + + virtual int suspendService (cdevService *service); + // PURPOSE: temprarily suspend service + // REQUIRE: nothing + // PROMISE: not implemented yet + + virtual int resumeService (cdevService *service); + // PURPOSE: resume a suspended service + // REQUIRE: nothing + // PROMISE: not implemented yet + + int registerDevice (cdevDevice *device); + // PURPOSE: register a cdevDevice to the system + // REQUIRE: device != 0 + // PROMISE: device will be registered once, CDEV_SUCCESS: success. + // CDEV_ERROR: already here + + int removeDevice (cdevDevice *); + // PURPOSE: remove a device from the system + // REQUIRE: device != 0 + // PROMISE: return CDEV_SUCCESS: rmoval success. + // return CDEV_ERROR: not here + + int deviceCreated (char *deviceName); + // PURPOSE: check a device created in the system by name + // REQUIRE: deviceName != 0 + // PROMISE: return 1: device is here, return 0: not here + + cdevDevice *device (char *deviceName); + // PURPOSE: return a device in the system by name + // REQUIRE: deviceName != 0 + // PROMISE: return device !=0 on success, return 0: failure + + virtual int getRequestObject (char *deviceName, + char *msg, + cdevRequestObject * &req); + // PURPOSE: get a cdevRequestObject from system by devicename and message + // REQUIRE: deviceName != 0 and msg != 0 + // PROMISE: return CDEV_SUCCESS: success. + // return CDEV_ERROR: failure + + int registerGroup (cdevGroup *grp); + // PURPOSE: register a group into the system + // REQUIRE: grp != 0 + // PROMISE: return CDEV_SUCCESS: success, CDEV_ERROR: already here + + int removeGroup (cdevGroup *grp); + // PURPOSE: remove a group from the system + // REQUIRE: grp != 0 + // PROMISE: return CDEV_SUCCESS: removal success. + // return CDEV_ERROR: not here. grp is still valid. + + int registerActiveGroup (cdevGroup *grp); + // PURPOSE: register an active group (group stared) + // REQUIRE: grp != 0 + // PROMISE: return CDEV_SUCCESS: success, + // CDEV_ERROR: already here + + int removeActiveGroup (cdevGroup *grp); + // PURPOSE: remove an active group + // REQUIRE: grp != 0 + // PROMISE: return CDEV_SUCCESS: success. + // return CDEV_ERROR: not here. grp is still valid + + int activeGroups (cdevGroup **grps, int& numGroups); + // PURPOSE: return active groups inside the system + // REQUIRE: callers provide memory for grps (eg. grps = new cdevGroup*[5]) + // or cdevGroup grps[5]. numGroups is the buffer size of grps. + // callers don't free grps[i] which is a pointer to internal rep. + // PROMISE: numGrps is the real number of active groups + + int activeGroups (void) const; + // PURPOSE: check whether there are any active groups + // REQUIRE: nothing + // PROMISE: 1: yes, 0: no + + cdevDirectory& nameServer (void); + // PURPOSE: default name server + // REQUIRE: nothing + // PROMISE: always here + + cdevRequestObject *errorRequestObject (void); + // PURPOSE: return default error request object in case of error + // REQUIRE: nothing + // PROMISE: return error request object + + void errorRequestObject (cdevRequestObject *obj); + // PURPOSE: set default error request object in case of error + // REQUIRE: nothing + // PROMISE: default error request object will be set + + virtual ~cdevSystem (void); + +protected: + // constructor and destructor + cdevSystem (char *systemName, char *prefix = 0); + + // redefine attach/detach file descriptor to notify callback if there + // any of them + virtual int attachReadFd (int fd); + virtual int detachReadFd (int fd); + + // setup the read mask in preparation for pend operation. + void setupMask ( void ); + + // free all memory + void freeMemory (void); + // interface to system collection + static int remove (cdevSystem *); + + // handle network I/O events + virtual int handleEvents (cdevTimeValue* tv); + + // calculate time out according to user request maximum timeout + // and timer queue earliest timeout + // returned pointer is a pointer to a static value + cdevTimeValue* calculateTimeOut (cdevTimeValue* maxtimeout); + + // notify lower level service object + virtual void notifyService (int handle); + // get individul service from file descriptor + cdevService *getService (int handle); + +private: + // data area + cdevSlist serviceList_; + // hash table keep track all devices which are keyed by device name + cdevStrHash deviceList_; + // group list inside the system + cdevSlist groupList_; + // active group list inside the system + cdevSlist activeGroupList_; + // system list + static cdevSlist& systemList_ (void); + // flag to denote there are some active groups + int activeGrps_; + // this system name + char *systemName_; + // prefix name for this system + char *prefix_; + // default name server, cdevDirectory for now + cdevDirectory *ns_; + // cdevService name binding mechanism + cdevSvcFinder *svcFinder_; + // cdev site configuraton loader + cdevConfigFinder *configFinder_; + // Reference counting + int refCount_; + // callback list for fdChangedCallback + cdevSlist fdCbkList_; + cdevSlist fdCbkArgList_; + // timer queue + cdevTimerQueue timerQueue_; + // fall through to a default service or not if no service is found + int defaultSvc_; + + //==================================================== + // The followings are for linked editor. + // Try to trick the link editor to load those symbols + // which otherwise will not be exported to library + //==================================================== + // default cdevServiceError handler object + cdevService *errSvcObj_; + // touch cdevTranObj class and alot of more + cdevTranObj *defXobj_; + // touch cdevCallback class + cdevCallback *defCallbackObj_; + // default requestobject error handle object + cdevRequestObject *errObj_; + // an empty cdevExecGroup object + cdevExecGroup* egroup_; + //=================================================== + // Deny access since memeber-wise copy will not work + // since this system is actually a memory manager + //=================================================== + cdevSystem (const cdevSystem &); + cdevSystem& operator = (const cdevSystem &); + // friend class declaration + friend class cdevService; + friend class cdevErrReqObject; +}; + +#endif diff --git a/src/system/cdevSystemBase.cc b/src/system/cdevSystemBase.cc new file mode 100755 index 0000000..8038ab7 --- /dev/null +++ b/src/system/cdevSystemBase.cc @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevSystemBase class (abstract class) +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevSystemBase.cc,v +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#include +#include "cdevSystemBase.h" + +cdevSystemBase::cdevSystemBase (void) +:cdevSync (), cdevError () +{ +#ifdef _TRACE_OBJECTS + printf (" Create cdevSystemBase class \n"); +#endif +} + +cdevSystemBase::~cdevSystemBase (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Destroy cdevSystemBase class \n"); +#endif +} diff --git a/src/system/cdevSystemBase.h b/src/system/cdevSystemBase.h new file mode 100755 index 0000000..786efa3 --- /dev/null +++ b/src/system/cdevSystemBase.h @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevSystemBase class (abstract class) +// +// Author: Jie Chen & Chip Watson +// +// Revision History: +// cdevSystemBase.h,v +// Revision 1.2 1996/05/28 13:00:12 chen +// minor changes +// +// Revision 1.1.1.1 1995/06/16 17:14:08 epics +// initial import of cdev +// +// +#ifndef _CDEV_SYSTEM_BASE +#define _CDEV_SYSTEM_BASE + +#include "cdevError.h" +#include "cdevSync.h" + +class CDEV_CLASS_SPEC cdevSystemBase: public cdevSync, public cdevError +{ + public: + virtual ~cdevSystemBase (void); + // PURPOSE: destructor for cdevSystemBase + // REQUIRE: nothing + // PROMISE: it will be gone + + virtual char *name (void) const = 0; + // PURPOSE: pure virtual function + // REQUIRE: derived class provides real implementation + // PROMISE: nothing + + virtual int getRequestObject (char *deviceName, + char *msg, + cdevRequestObject* &req) = 0; + // PURPOSE: pure virtual function + // REQUIRE: callers provide pointer to cdevRequestObject only, no memory + // PROMISE: nothing + virtual const char *className (void) const {return "cdevSystemBase";} + + protected: + //constructor, deny direct instantiation + cdevSystemBase (void); +}; +#endif + diff --git a/src/system/cdevUserFdService.cc b/src/system/cdevUserFdService.cc new file mode 100755 index 0000000..d5701bc --- /dev/null +++ b/src/system/cdevUserFdService.cc @@ -0,0 +1,104 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevUserFdService Class +// +// Author: Jie Chen +// +// Revision History: +// cdevUserFdService.cc,v +// Revision 1.2 1997/04/02 17:54:09 akers +// Ongoing Development of CDEV 1.6 +// +// Revision 1.1 1997/02/18 15:45:47 chen +// port to linux 2.0.x + addUserFdCallback +// +// +// +#include +#include "cdevUserFdService.h" + +char* cdevUserFdService::fdsvcname_ = "fdsvcXXXXXX"; + +cdevUserFdService::cdevUserFdService (int fd, cdevUserFdCallback cbk, + void* arg, + char* name, + cdevSystem& system) +:cdevService (name, system), cbk_ (cbk), arg_ (arg) +{ +#ifdef _TRACE_OBJECTS + printf (" Create cdevUserFdService Class Object: %s\n", name); +#endif + fd_ = new int; + *fd_ = fd; +} + +cdevUserFdService::~cdevUserFdService (void) +{ +#ifdef _TRACE_OBJECTS + printf (" Delete cdevUserFdService Class Object: %s\n", serviceName_); +#endif + // delete fd memory + delete fd_; +} + +int +cdevUserFdService::getFd (int* &fd, int &numFd) +{ + numFd = 1; + fd = fd_; + + return CDEV_SUCCESS; +} + +int +cdevUserFdService::getNameServer (cdevDevice* &server) +{ + server = 0; + return CDEV_SUCCESS; +} + +int +cdevUserFdService::flush (void) +{ + return CDEV_SUCCESS; +} + +int +cdevUserFdService::poll (void) +{ + return (*cbk_)(1, *fd_, arg_); +} + +int +cdevUserFdService::pend (int /* fd */ ) +{ + return poll (); +} + +int +cdevUserFdService::pend (double /* timeout */, int /* fd */) +{ + return poll (); +} + +int +cdevUserFdService::getRequestObject (char* /* deviceName */, char* /* msg */, + cdevRequestObject * &req) +{ + req = 0; + return CDEV_ERROR; +} + +char* +cdevUserFdService::prefixName (void) +{ + return cdevUserFdService::fdsvcname_; +} diff --git a/src/system/cdevUserFdService.h b/src/system/cdevUserFdService.h new file mode 100755 index 0000000..0af4c40 --- /dev/null +++ b/src/system/cdevUserFdService.h @@ -0,0 +1,105 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// cdevFdServive (Arbitrary user file descriptor service) +// +// Author: Jie Chen +// +// Revision History: +// cdevUserFdService.h,v +// Revision 1.1 1997/02/18 15:45:48 chen +// port to linux 2.0.x + addUserFdCallback +// +// +// +#ifndef _CDEV_USER_FD_SERVICE_H +#define _CDEV_USER_FD_SERVICE_H + +#include + +class cdevUserFdService: public cdevService +{ +public: + cdevUserFdService (int fd, cdevUserFdCallback cbk, void* arg, + char* name, + cdevSystem& system = cdevSystem::defaultSystem () + ); + // PURPOSE: construction of fdService + // REQUIRE: none + // PROMISE: A fd servive with a unique name + + ~cdevUserFdService (void); + // PURPOSE: destruction of fdService + // REQUIRE: none + // PROMISE: this object is gone forever + + int getFd (int* &fd, int &numFd); + // PURPOSE: get service's IO file descriptors + // REQUIRE: callers provide pointer (eg. int *fd = 0;) no memory. callers + // should never free memory pointed by fd. fd should be cached + // inside derived class for easy/quick access + // PROMISE: numFd >= 0 + + int getNameServer (cdevDevice* &server); + // PURPOSE: get right name server associated with this service + // REQUIRE: caller provide pointer only, derived class provides + // an empty function for now + // PROMISE: not implemented yet + + int flush (void); + // PURPOSE: pure virtual function to define intreface for net flush + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS + + int poll (void); + // PURPOSE: pure virtual function to define intreface for polling method + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS: OK. return -1: network error + + int pend (int fd = -1); + // PURPOSR: pure virtual function to define interface for pending method + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS, OK, return -1: network error + + int pend (double seconds, int fd = -1); + // PURPOSR: pure virtual function to define interface for pending method + // REQUIRE: derived class provide implementation + // PROMISE: return CDEV_SUCCESS, OK, return CDEV_TIMEOUT: timeout. + // -1: network error + + static char* prefixName (void); + // PURPOSE: return common prefix name for all services + // REQUIRE: none + // PROMISE: return common prefix name + + const char *className (void) const {return "cdevUserFdService";} + +protected: + // hide request object creation method + int getRequestObject (char *deviceName, + char *msg, + cdevRequestObject* &req); + // PURPOSE: get request object: this service return 0 + // REQUIRE: callers provide pointer to cdevRequestObject only, no memory + // PROMISE: nothing + +private: + // associated fd + int* fd_; + // user function and usr argument + cdevUserFdCallback cbk_; + void* arg_; + + // unique name for fd services + static char* fdsvcname_; +}; +#endif + + diff --git a/src/system/cdevVersion.h b/src/system/cdevVersion.h new file mode 100755 index 0000000..0d619f2 --- /dev/null +++ b/src/system/cdevVersion.h @@ -0,0 +1,42 @@ +/* +//----------------------------------------------------------------------------- +// Copyright (c) 1994,1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +// +//----------------------------------------------------------------------------- +// +// Description: +// CDEV VERSION Information +// +// Author: Jie Chen +// +// Revision History: +// cdevVersion.h,v +// Revision 1.3 1997/12/22 18:23:06 akers +// Ongoing development of 1.6.2 +// +// Revision 1.2 1997/10/17 17:27:18 chen +// set right version number +// +// Revision 1.1 1997/08/27 18:23:33 chen +// Change error reporting to site specific scheme +// +// +// +*/ +#ifndef _CDEV_VERSION_H +#define _CDEV_VERSION_H + +#define CDEV_MAJOR_VERS 1 +#define CDEV_MINOR_VERS 7 +#define CDEV_REVISION 2 + +#define CDEV_VERSION (CDEV_MAJOR_VERS*10000 + CDEV_MINOR_VERS*100 + CDEV_REVISION) + +#define CDEV_VERSION_STRING "1.7.2" + +#endif + diff --git a/src/utility/.shobj/Linux/cddl.o b/src/utility/.shobj/Linux/cddl.o new file mode 100644 index 0000000..a00cd03 Binary files /dev/null and b/src/utility/.shobj/Linux/cddl.o differ diff --git a/src/utility/.shobj/Linux/cdevUtil.o b/src/utility/.shobj/Linux/cdevUtil.o new file mode 100644 index 0000000..aefd26b Binary files /dev/null and b/src/utility/.shobj/Linux/cdevUtil.o differ diff --git a/src/utility/.shobj/Linux/uncompile.o b/src/utility/.shobj/Linux/uncompile.o new file mode 100644 index 0000000..516307b Binary files /dev/null and b/src/utility/.shobj/Linux/uncompile.o differ diff --git a/src/utility/Makefile b/src/utility/Makefile new file mode 100755 index 0000000..565fce9 --- /dev/null +++ b/src/utility/Makefile @@ -0,0 +1,39 @@ +ARCH = OS +APPNAME = CDEV Utility Applications + +include ../../include/makeinclude/Makefile.$(ARCH) + +TARGETS = $(CDEV)/bin/$(TARGETDIR)/cdevUtil \ + $(CDEV)/bin/$(TARGETDIR)/cddl \ + $(CDEV)/bin/$(TARGETDIR)/uncompile +BINARIES = $(TARGETS) +CXXEXTRA = $(CLASS_INCLUDES) -I. -I../directory + +hpux hpux-sl hpux-cl hpux-cl-sl irix5 irix5-sl sunos4-gcc sunos4-gcc-sl solaris solaris-sl solaris-gcc solaris-gcc-sl ultrix-gcc aix linux linux-sl: + @$(MAKE) -s ARCH=$@ + +targets: CBINDIR $(TARGETS) + +CBINDIR: + @mkdir -p $(CDEVBIN) + +cdevUtil: $(CDEV)/bin/$(TARGETDIR)/cdevUtil + @echo "\c" + +cddl: $(CDEV)/bin/$(TARGETDIR)/cddl + @echo "\c" + +uncompile: $(CDEV)/bin/$(TARGETDIR)/uncompile + @echo "\c" + +$(CDEV)/bin/$(TARGETDIR)/cdevUtil: $(OBJDIR)/cdevUtil.o + @mkdir -p $(CDEV)/bin/$(TARGETDIR) + @$(LINK.cc) + +$(CDEV)/bin/$(TARGETDIR)/cddl: $(OBJDIR)/cddl.o + @mkdir -p $(CDEV)/bin/$(TARGETDIR) + @$(LINK.cc) + +$(CDEV)/bin/$(TARGETDIR)/uncompile: $(OBJDIR)/uncompile.o + @mkdir -p $(CDEV)/bin/$(TARGETDIR) + @$(LINK.cc) diff --git a/src/utility/NMakefile.mak b/src/utility/NMakefile.mak new file mode 100644 index 0000000..bcddbfe --- /dev/null +++ b/src/utility/NMakefile.mak @@ -0,0 +1,36 @@ +.SUFFIXES: .cc .objbj + +ARCH = WINNT-4.0 +SHOBJ = YES +APPNAME = CDEV Utility Applications + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +TARGETS = $(CDEV)\bin\$(TARGETDIR)\cdevUtil.exe \ + $(CDEV)\bin\$(TARGETDIR)\cddl.exe \ + $(CDEV)\bin\$(TARGETDIR)\uncompile.exe +BINARIES = $(TARGETS) +CXXEXTRA = -I. -I..\directory + +targets: $(CDEVBIN) $(TARGETS) + +$(CDEVBIN): + @mkdir -p $@ + +$(CDEV)\bin\$(TARGETDIR)\cdevUtil.exe: .exec\$(TARGETDIR)\cdevUtil.obj + @if not exist $(CDEV)\bin\$(TARGETDIR) mkdir -p $(CDEV)\bin\$(TARGETDIR) + @$(LINK) \ + $(CDEVLIB)\cdev.lib $(LINK_EXE_FLAGS) /out:$@ \ + .exec\$(TARGETDIR)\cdevUtil.obj + +$(CDEV)\bin\$(TARGETDIR)\cddl.exe: .exec\$(TARGETDIR)\cddl.obj + @if not exist $(CDEV)\bin\$(TARGETDIR) mkdir -p $(CDEV)\bin\$(TARGETDIR) + @$(LINK) \ + $(CDEVLIB)\cdev.lib $(LINK_EXE_FLAGS) /out:$@ \ + .exec\$(TARGETDIR)\cddl.obj + +$(CDEV)\bin\$(TARGETDIR)\uncompile.exe: .exec\$(TARGETDIR)\uncompile.obj + @if not exist $(CDEV)\bin\$(TARGETDIR) mkdir -p $(CDEV)\bin\$(TARGETDIR) + @$(LINK) \ + $(CDEVLIB)\cdev.lib $(LINK_EXE_FLAGS) /out:$@ \ + .exec\$(TARGETDIR)\uncompile.obj diff --git a/src/utility/cddl.cc b/src/utility/cddl.cc new file mode 100755 index 0000000..33adfea --- /dev/null +++ b/src/utility/cddl.cc @@ -0,0 +1,32 @@ +#include + +int main ( int argc, char ** argv ) + { + int result = 0; + char * inputFile = NULL; + char * outputFile = NULL; + + for(int i=1; i Bad or missing arguments\n => Format is: cddl inputFile -o outputFile"); + result = -1; + } + else { + cdevDirectoryTable table; + + fprintf(stdout, "cddl: Compiling %s to %s\n", inputFile, outputFile); + fflush (stdout); + + if(table.load (inputFile)==CDEV_SUCCESS) table.binaryDump(outputFile); + } + + return result; + } diff --git a/src/utility/cdevUtil.cc b/src/utility/cdevUtil.cc new file mode 100755 index 0000000..5d358a1 --- /dev/null +++ b/src/utility/cdevUtil.cc @@ -0,0 +1,592 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: cdevUtil.cc +// A simple command line utility designed to provide a direct user +// interface to cdevServices. +// +// Author: Walt Akers +// +// Revision History: +// cdevUtil.cc,v +// Revision 1.1 1998/02/13 17:11:59 akers +// Ongoing development +// +// Revision 1.1 1998/02/13 14:42:04 akers +// Ongoing development +// +// Revision 1.13 1997/07/16 21:25:17 akers +// Corrected patch that was installed in hpux-10.xx +// +// Revision 1.12 1997/03/25 22:24:44 akers +// Development in support of a new cdevDirectory +// +// Revision 1.11 1997/01/30 20:36:08 akers +// Ongoing development and improvement +// +// Revision 1.10 1996/06/26 15:54:27 akers +// Modifications to support multiple OS Versions +// +// Revision 1.9 1996/03/28 19:13:48 akers +// Minor changes in support of new version +// +// Revision 1.8 1995/11/27 14:23:11 akers +// Made cdevUtil VMS compliant +// +// Revision 1.7 1995/10/31 14:53:23 akers +// Minor Update +// +// Revision 1.6 1995/10/30 13:33:24 akers +// Added cdev specific version of strncpy +// +// Revision 1.5 1995/10/26 19:23:57 akers +// Added SIGSEGV Handler to cdevUtil +// +// Revision 1.4 1995/08/23 18:49:15 akers +// Added batch interface and multiple dimensional value display. +// +// Revision 1.3 1995/08/23 13:11:51 akers +// New source code release of cdevUtil +// +//-------------------------------------------------------------------------- +#ifdef _WIN32 + #include + #include + #include + #include + #include +#else + #include + #include + #include + #include + #include +#endif + +#include +#include +#include +#include +#include +#include + +#ifndef WIN32 + #define min(a, b) ((a)<(b)?(a):(b)) + #define max(a, b) ((a)>(b)?(a):(b)) +#endif + +char * CDEV_PROMPT = "> "; +int debugging_mode = 0; +cdevSystem & defSystem = cdevSystem::defaultSystem(); + +char globalLastDevice[255] = "\0"; +char globalLastAttrib[255] = "VAL"; +char globalParms [4][255]; +struct { + char tag[128]; + char value[255]; + } globalTaggedData[100]; + +#ifndef __VMS + // Under VMS this signal occurs in situations that are not abnormal, + // and thus cannot be used as simply as this. + // See the "DEC C Run Time Library Reference Manual" for details. + void SIGSEGV_Handler(int) { exit(1); } +#endif /* __VMS not defined */ + +// ***************************************************************************** +// * defCallback: +// * This is the default callback function used by the system. +// ***************************************************************************** +void defCallback ( int status, void * userarg, cdevRequestObject & reqObj, cdevData & data ) +{ +cdevCallbackArg * arg = (cdevCallbackArg *)userarg; +char temp[255]; +char ** value = NULL; +size_t count = 0; + +sprintf(temp, "None"); +if(data.getElems("value", &count)==CDEV_SUCCESS) + { + if(count>1) + { + value = new char *[count+1]; + value[0] = NULL; + data.get("value", value); + } + else data.get("value", temp, 255); + } + +fprintf(stdout, "%s %d: Device: %s - Message: %s", + status==CDEV_SUCCESS?"SUCCESS":"FAILURE",status, + reqObj.device().name(), + reqObj.message()); + +if(count>1) + { + fprintf(stdout, "\n%s", CDEV_PROMPT); + for(int i=0; ipermanent()==0) delete arg; +} + + +// ***************************************************************************** +// * monitorCallback : +// * This is the monitoring callback. When the user issues a monitorOn +// * command, this is the callback function that will be used to process +// * the results. +// ***************************************************************************** +void monitorCallback ( int status, void * , cdevRequestObject & reqObj, cdevData & data ) +{ +char * attrib = strstr(reqObj.message(), "monitorOn"); +char value[255]; +*value = 0; + +if(attrib) attrib+=10; +data.get("value", value, 255); + +if(status==CDEV_SUCCESS) + { + fprintf(stdout, + "MonitorOn Device: %s - Attrib: %s ... value changed to %s\n%s", + reqObj.device().name(), attrib, value, CDEV_PROMPT); + fflush (stdout); + } +} + + +// ***************************************************************************** +// * decomposeMessage : +// * This function breaks a cdev message string down into its components +// * to allow it to be transmitted through the system. +// ***************************************************************************** +void decomposeMessage ( char * message ) +{ +int idx = 0; +int tagIdx = 0; +memset(&globalParms, 0, sizeof(globalParms)); +memset(&globalTaggedData, 0, sizeof(globalTaggedData)); + +char * tagPtr; +if((tagPtr = strchr(message, '='))!=NULL && tagPtr>message) + { + tagPtr--; + while(tagPtr>message && isspace(*tagPtr)) tagPtr--; + while(tagPtr>message && !isspace(*tagPtr)) tagPtr--; + if(tagPtr > message) + { + *tagPtr = 0; + tagPtr++; + } + else tagPtr = NULL; + } +else tagPtr = NULL; + +char * ptr = message; +while (ptr!=NULL && *ptr && idx<4) + { + while(*ptr && isspace(*ptr)) ptr++; + char * eptr = ptr; + + if(idx<3) while(*eptr && !isspace(*eptr)) eptr++; + else while(*eptr && isprint(*eptr)) eptr++; + + cdevStrncpy(globalParms[idx], ptr, min(255, (eptr-ptr)+1)); + ptr = eptr; + idx++; + } + +// ***************************************************************************** +// * Always place an entry for the value tag in the first element of the +// * globalTaggedData structure. This will give you room to later advance +// * parameters into the tagged data list without having to search to the +// * end. +// ***************************************************************************** +if(*globalParms[3]!='\0') + { + strcpy(globalTaggedData[0].tag, "value"); + cdevStrncpy(globalTaggedData[0].value, globalParms[3], 255); + } +else strcpy(globalTaggedData[0].tag, "value"); +tagIdx++; + +while(tagPtr && *tagPtr && tagIdx<99) + { + char * tagName = NULL; + char * endTagName = NULL; + char * tagValue = NULL; + char * endTagValue = NULL; + char * nextTag = NULL; + + tagName = tagPtr; + while(*tagName && isspace(*tagName)) tagName++; + endTagName = strchr(tagName, '='); + if(endTagName && *endTagName) + { + tagValue = endTagName+1; + while(isspace(*(endTagName-1))) endTagName--; + } + while(tagValue && *tagValue && isspace(*tagValue)) tagValue++; + if((nextTag = strchr(tagValue, '='))!=NULL) + { + nextTag--; + while(isspace(*nextTag) && nextTag>tagValue) nextTag--; + while(!isspace(*nextTag) && nextTag>tagValue) nextTag--; + if(isspace(*nextTag)) + { + endTagValue = nextTag; + nextTag++; + while(isspace(*(endTagValue-1))) endTagValue--; + } + else + { + nextTag = NULL; + endTagValue = tagValue; + } + } + else + { + endTagValue = tagValue; + while(endTagValue && *endTagValue) endTagValue++; + } + if(tagName && tagNamedata().insert(globalTaggedData[i].tag, dValue); + else arg->data().insert(globalTaggedData[i].tag, globalTaggedData[i].value); + } + + cdevDevice * dev = defSystem.getDevice(device); + cdevRequestObject * reqObj = dev->getRequestObject(messageOut); + + if(debugging_mode) + { + fprintf(stdout, "Attempting to transmit using the following parameters\n"); + fprintf(stdout, "Device: %s %d\n", globalParms[0],strlen(globalParms[0])); + fprintf(stdout, "Verb: %s %d\n", globalParms[1],strlen(globalParms[1])); + fprintf(stdout, "Attrib: %s %d\n", globalParms[2],strlen(globalParms[2])); + + for(i=0; globalTaggedData[i].tag[0]!=0; i++) + { + if(globalTaggedData[i].value[0]!=0) + { + fprintf(stdout, "Tag: %s = %s %d\n", + globalTaggedData[i].tag, + globalTaggedData[i].value, strlen(globalTaggedData[i].value)); + } + } + fprintf(stdout, "\n"); + } + + if(reqObj && + reqObj != defSystem.errorRequestObject()) + { + if (debugging_mode) { + printf("data to send:\n"); + arg->data().asciiDump(); + } + + result = reqObj->sendCallback(arg->data(), arg->callback()); + if (debugging_mode) printf("result %d\n",result); + } + else result = -1; + + if(result!=0) + { + delete arg; + done = useLastDevice(); + } + else + { + strcpy(globalLastDevice, globalParms[0]); + strcpy(globalLastAttrib, globalParms[2]); + if(debugging_mode) fprintf(stdout, "Transmission was successful.\n"); + } + } + +if(result != CDEV_SUCCESS) fprintf(stdout, "Could not transmit message as specified. %d\n",result); + +if(debugging_mode) + fprintf(stdout, "------------------ END DEBUG OUTPUT -----------------\n"); + +return result; +} + +// ***************************************************************************** +// * printHelp: +// * Displays a help message to the user. +// ***************************************************************************** +void printHelp ( void ) +{ +fprintf(stdout, "\n"); +fprintf(stdout, "------------------------------------------------------------------------------\n"); +fprintf(stdout, "cdevUtil: A command line interface to cdev...\n"); +fprintf(stdout, "\n"); +fprintf(stdout, "INTERNAL COMMANDS:\n"); +fprintf(stdout, " debug on - turns on debugging mode\n"); +fprintf(stdout, " debug off - turns off debugging mode\n"); +fprintf(stdout, " help - prints this message\n"); +fprintf(stdout, " quit - exit the cdev utility\n"); +fprintf(stdout, "\n"); +fprintf(stdout, "CDEV COMMANDS:\n"); +fprintf(stdout, " cdev Commands have the following syntax...\n"); +fprintf(stdout, "\n"); +fprintf(stdout, " device verb attr tag1=value1 tag2=value2\n"); +fprintf(stdout, "\n"); +fprintf(stdout, " where device = the name of the cdev device\n"); +fprintf(stdout, " verb = the operation to perform\n"); +fprintf(stdout, " attr = the attribute of the cdev device to operate on\n"); +fprintf(stdout, " tags = tags may be either general cdev tags or tags that\n"); +fprintf(stdout, " are specified by the service.\n"); +fprintf(stdout, "\n"); +fprintf(stdout, " The following command sets the VAL attribute of device TEST1 to 100.\n"); +fprintf(stdout, "\n"); +fprintf(stdout, " TEST1 set VAL value=100\n"); +fprintf(stdout, "------------------------------------------------------------------------------\n"); +} + + +void waitForStdin ( cdevSystem & system ) + { + int fd[32]; + int numFD = 31, nfds; + int stdinReady = 0; + fd_set rfds; // Ready file descriptors + fd_set afds; // Active file descriptors + + do { + // ************************************************************* + // * Copy the file descriptor for stdin to the list of + // * descriptors + // ************************************************************* + fd[0] = fileno(stdin); + + // ************************************************************* + // * Get the file descriptors in use by the cdevSystem object + // ************************************************************* + system.getFd(&fd[1], numFD); + + // ************************************************************* + // * Add in the previously defined file descriptors + // ************************************************************* + numFD += 1; + + // ************************************************************* + // * Zero the active file descriptors + // ************************************************************* + FD_ZERO(&afds); + + // ************************************************************* + // * Setup the active file descriptors + // ************************************************************* + for(int i=0; i9) + if(select(nfds, &rfds, 0, 0, 0)<0) +#else + if(select(nfds, (int *)&rfds, 0, 0, 0)<0) +#endif + + { + system.reportError( + CDEV_SEVERITY_WARN, + "select", NULL, + "select function returned -1"); + } + // ************************************************************* + // * Iterate through the list of file descriptors + // ************************************************************* + else + { + // ***************************************************** + // * If the stdin descriptor is ready, set the flag + // ***************************************************** + if(FD_ISSET(fd[0], &rfds)) stdinReady = 1; + + // ***************************************************** + // * Always poll the cdev system object + // ***************************************************** + system.poll(); + } + } while(!stdinReady); + } + + +int main(int argc, char ** argv) +{ +int done = 0; +char command[2048]; + +#if (!defined(__VMS) && !defined(_WIN32)) + // Under VMS this signal occurs in situations that are not abnormal, + // and thus cannot be used as simply as this. + // See the "DEC C Run Time Library Reference Manual" for details. + signal(SIGSEGV, SIGSEGV_Handler); +#endif /* __VMS not defined */ + +cdevSystem::defaultSystem().setThreshold(CDEV_SEVERITY_ERROR); + +if(argc>1) + { + int i; + char * oldCdevPrompt = CDEV_PROMPT; + CDEV_PROMPT = "\0"; + fprintf(stdout, "Submitting batch cdev commands...\n"); + for(i=1; i1) submitMessage(argv[i]); + cdevSystem::defaultSystem().poll(); + } + cdevSystem::defaultSystem().poll(); + CDEV_PROMPT = oldCdevPrompt; + } + +if(!done) + { + fprintf(stdout, CDEV_PROMPT); + fflush (stdout); + } + +while( !done ) + { + waitForStdin(cdevSystem::defaultSystem()); + + fgets(command, 2048, stdin); + if(*command == 'q' && !strcmp(command, "quit\n")) done = 1; + else if(*command=='d' && !strcmp(command, "debug on\n")) debugging_mode = 1; + else if(*command=='d' && !strcmp(command, "debug off\n")) debugging_mode = 0; + else if(*command=='h' && !strcmp(command, "help\n")) printHelp(); + else if(strlen(command)>1) submitMessage(command); + if(!done) fprintf(stdout, CDEV_PROMPT); + fflush (stdout); + + cdevSystem::defaultSystem().poll(); + } +return 0; +} + + diff --git a/src/utility/cdevUtil.h b/src/utility/cdevUtil.h new file mode 100755 index 0000000..fdf0280 --- /dev/null +++ b/src/utility/cdevUtil.h @@ -0,0 +1,47 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1991,1992 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: cdevUtil.cc +// A simple command line utility designed to provide a direct user +// interface to cdevServices. +// +// Author: Walt Akers +// +// +//-------------------------------------------------------------------------- + +#ifndef _CDEV_UTIL_H_ +#define _CDEV_UTIL_H_ 1 + +// ***************************************************************************** +// * class cdevCallbackArg: +// * This class is used to control deletion of the cdevData object passed as +// * an argument to the sendCallback function. This class is passed as the +// * userarg element of the callback structure, and if the permanent flag is +// * false(0) when the callback is executed, the class and its contents will +// * be deleted. +// ***************************************************************************** +class cdevCallbackArg +{ +private: + int Permanent; + cdevCallback Callback; + cdevData Data; + +public: + cdevCallbackArg ( cdevCallbackFunction func, int permanent = 0) + : Permanent(permanent), Callback(func, this) {} + ~cdevCallbackArg( void ) {} + + int & permanent ( void ) { return Permanent; } + cdevCallback & callback ( void ) { return Callback; } + cdevData & data ( void ) { return Data; } +}; + +#endif /* _CDEV_UTIL_H_ */ + diff --git a/src/utility/uncompile.cc b/src/utility/uncompile.cc new file mode 100755 index 0000000..a03600b --- /dev/null +++ b/src/utility/uncompile.cc @@ -0,0 +1,40 @@ +#include + +int main ( int argc, char ** argv ) + { + int result = 0; + char * inputFile = NULL; + char * outputFile = NULL; + FILE * fp = NULL; + + for(int i=1; i Bad or missing arguments\n => Format is: uncompile inputFile -o outputFile"); + result = -1; + } + else if((fp = fopen(outputFile, "w"))==NULL) + { + cdevSystem::defaultSystem().reportError + (CDEV_SEVERITY_ERROR, "CDEV DDL Un-Compiler", NULL, + "Could not open output file %s", outputFile); + result = -1; + } + else { + cdevDirectoryTable table; + + fprintf(stdout, "uncompile: Converting %s to %s\n", inputFile, outputFile); + fflush (stdout); + if(table.load (inputFile)==CDEV_SUCCESS) table.asciiDump(fp); + fclose(fp); + } + + return result; + } diff --git a/src/xdr/NMakefile.mak b/src/xdr/NMakefile.mak new file mode 100755 index 0000000..b92e096 --- /dev/null +++ b/src/xdr/NMakefile.mak @@ -0,0 +1,20 @@ +include ..\NMakefile.config + +OBJS = $(OBJDIR)\xdr.obj\ + $(OBJDIR)\xdr_array.obj\ + $(OBJDIR)\xdr_float.obj\ + $(OBJDIR)\xdr_mem.obj\ + $(OBJDIR)\xdr_rec.obj\ + $(OBJDIR)\xdr_reference.obj\ + $(OBJDIR)\xdr_stdio.obj + +targets : copyobjs copyincs + +copyobjs : $(OBJS) + -@if not exist ..\lib\$(OBJDIR) mkdir ..\lib\$(OBJDIR) + -@for %x in ($(OBJDIR)\*.obj) DO @copy %x ..\lib\$(OBJDIR) > nul + +copyincs : + -@for %x in (*.h *.i) DO @copy %x $(CDEV)\include > nul + + diff --git a/src/xdr/xdr.c b/src/xdr/xdr.c new file mode 100755 index 0000000..1ce9793 --- /dev/null +++ b/src/xdr/xdr.c @@ -0,0 +1,584 @@ +/* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)xdr.c 1.35 87/08/12"; +#endif + +/* + * xdr.c, Generic XDR routines implementation. + * + * Copyright (C) 1986, Sun Microsystems, Inc. + * + * These are the "generic" xdr routines used to serialize and de-serialize + * most common data items. See xdr.h for more info on the interface to + * xdr. + */ + +#include + +#ifdef _WIN32 +#include +#include +#include "xdr.h" +#else +char *malloc(); + +#include +#include +#endif + +/* + * constants specific to the xdr "protocol" + */ +#define XDR_FALSE ((long) 0) +#define XDR_TRUE ((long) 1) +#define LASTUNSIGNED ((u_int) 0-1) + +/* + * for unit alignment + */ +static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 }; + +/* + * Free a data structure using XDR + * Not a filter, but a convenient utility nonetheless + */ +void +xdr_free(proc, objp) + xdrproc_t proc; + char *objp; +{ + XDR x; + + x.x_op = XDR_FREE; + (*proc)(&x, objp); +} + +/* + * XDR nothing + */ +bool_t +xdr_void(/* xdrs, addr */) + /* XDR *xdrs; */ + /* caddr_t addr; */ +{ + + return (TRUE); +} + +/* + * XDR integers + */ +bool_t +xdr_int(xdrs, ip) + XDR *xdrs; + int *ip; +{ + +#ifdef lint + (void) (xdr_short(xdrs, (short *)ip)); + return (xdr_long(xdrs, (long *)ip)); +#else + if (sizeof (int) == sizeof (long)) { + return (xdr_long(xdrs, (long *)ip)); + } else { + return (xdr_short(xdrs, (short *)ip)); + } +#endif +} + +/* + * XDR unsigned integers + */ +bool_t +xdr_u_int(xdrs, up) + XDR *xdrs; + u_int *up; +{ + +#ifdef lint + (void) (xdr_short(xdrs, (short *)up)); + return (xdr_u_long(xdrs, (u_long *)up)); +#else + if (sizeof (u_int) == sizeof (u_long)) { + return (xdr_u_long(xdrs, (u_long *)up)); + } else { + return (xdr_short(xdrs, (short *)up)); + } +#endif +} + +/* + * XDR long integers + * same as xdr_u_long - open coded to save a proc call! + */ +bool_t +xdr_long(xdrs, lp) + register XDR *xdrs; + long *lp; +{ + + if (xdrs->x_op == XDR_ENCODE) + return (XDR_PUTLONG(xdrs, lp)); + + if (xdrs->x_op == XDR_DECODE) + return (XDR_GETLONG(xdrs, lp)); + + if (xdrs->x_op == XDR_FREE) + return (TRUE); + + return (FALSE); +} + +/* + * XDR unsigned long integers + * same as xdr_long - open coded to save a proc call! + */ +bool_t +xdr_u_long(xdrs, ulp) + register XDR *xdrs; + u_long *ulp; +{ + + if (xdrs->x_op == XDR_DECODE) + return (XDR_GETLONG(xdrs, (long *)ulp)); + if (xdrs->x_op == XDR_ENCODE) + return (XDR_PUTLONG(xdrs, (long *)ulp)); + if (xdrs->x_op == XDR_FREE) + return (TRUE); + return (FALSE); +} + +/* + * XDR short integers + */ +bool_t +xdr_short(xdrs, sp) + register XDR *xdrs; + short *sp; +{ + long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (long) *sp; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *sp = (short) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * XDR unsigned short integers + */ +bool_t +xdr_u_short(xdrs, usp) + register XDR *xdrs; + u_short *usp; +{ + u_long l; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + l = (u_long) *usp; + return (XDR_PUTLONG(xdrs, &l)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &l)) { + return (FALSE); + } + *usp = (u_short) l; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + + +/* + * XDR a char + */ +bool_t +xdr_char(xdrs, cp) + XDR *xdrs; + char *cp; +{ + int i; + + i = (*cp); + if (!xdr_int(xdrs, &i)) { + return (FALSE); + } + *cp = i; + return (TRUE); +} + +/* + * XDR an unsigned char + */ +bool_t +xdr_u_char(xdrs, cp) + XDR *xdrs; + char *cp; +{ + u_int u; + + u = (*cp); + if (!xdr_u_int(xdrs, &u)) { + return (FALSE); + } + *cp = u; + return (TRUE); +} + +/* + * XDR booleans + */ +bool_t +xdr_bool(xdrs, bp) + register XDR *xdrs; + bool_t *bp; +{ + long lb; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + lb = *bp ? XDR_TRUE : XDR_FALSE; + return (XDR_PUTLONG(xdrs, &lb)); + + case XDR_DECODE: + if (!XDR_GETLONG(xdrs, &lb)) { + return (FALSE); + } + *bp = (lb == XDR_FALSE) ? FALSE : TRUE; + return (TRUE); + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * XDR enumerations + */ +bool_t +xdr_enum(xdrs, ep) + XDR *xdrs; + enum_t *ep; +{ +#ifndef lint + enum sizecheck { SIZEVAL }; /* used to find the size of an enum */ + + /* + * enums are treated as ints + */ + if (sizeof (enum sizecheck) == sizeof (long)) { + return (xdr_long(xdrs, (long *)ep)); + } else if (sizeof (enum sizecheck) == sizeof (short)) { + return (xdr_short(xdrs, (short *)ep)); + } else { + return (FALSE); + } +#else + (void) (xdr_short(xdrs, (short *)ep)); + return (xdr_long(xdrs, (long *)ep)); +#endif +} + +/* + * XDR opaque data + * Allows the specification of a fixed size sequence of opaque bytes. + * cp points to the opaque object and cnt gives the byte length. + */ +bool_t +xdr_opaque(xdrs, cp, cnt) + register XDR *xdrs; + caddr_t cp; + register u_int cnt; +{ + register u_int rndup; + static crud[BYTES_PER_XDR_UNIT]; + + /* + * if no data we are done + */ + if (cnt == 0) + return (TRUE); + + /* + * round byte count to full xdr units + */ + rndup = cnt % BYTES_PER_XDR_UNIT; + if (rndup > 0) + rndup = BYTES_PER_XDR_UNIT - rndup; + + if (xdrs->x_op == XDR_DECODE) { + if (!XDR_GETBYTES(xdrs, cp, cnt)) { + return (FALSE); + } + if (rndup == 0) + return (TRUE); + return (XDR_GETBYTES(xdrs, crud, rndup)); + } + + if (xdrs->x_op == XDR_ENCODE) { + if (!XDR_PUTBYTES(xdrs, cp, cnt)) { + return (FALSE); + } + if (rndup == 0) + return (TRUE); + return (XDR_PUTBYTES(xdrs, xdr_zero, rndup)); + } + + if (xdrs->x_op == XDR_FREE) { + return (TRUE); + } + + return (FALSE); +} + +/* + * XDR counted bytes + * *cpp is a pointer to the bytes, *sizep is the count. + * If *cpp is NULL maxsize bytes are allocated + */ +bool_t +xdr_bytes(xdrs, cpp, sizep, maxsize) + register XDR *xdrs; + char **cpp; + register u_int *sizep; + u_int maxsize; +{ + register char *sp = *cpp; /* sp is the actual string pointer */ + register u_int nodesize; + + /* + * first deal with the length since xdr bytes are counted + */ + if (! xdr_u_int(xdrs, sizep)) { + return (FALSE); + } + nodesize = *sizep; + if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) { + return (FALSE); + } + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) { + + case XDR_DECODE: + if (nodesize == 0) { + return (TRUE); + } + if (sp == NULL) { + *cpp = sp = (char *)mem_alloc(nodesize); + } + if (sp == NULL) { + (void) fprintf(stderr, "xdr_bytes: out of memory\n"); + return (FALSE); + } + /* fall into ... */ + + case XDR_ENCODE: + return (xdr_opaque(xdrs, sp, nodesize)); + + case XDR_FREE: + if (sp != NULL) { + mem_free(sp, nodesize); + *cpp = NULL; + } + return (TRUE); + } + return (FALSE); +} + +/* + * Implemented here due to commonality of the object. + */ +bool_t +xdr_netobj(xdrs, np) + XDR *xdrs; + struct netobj *np; +{ + + return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ)); +} + +/* + * XDR a descriminated union + * Support routine for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * an entry with a null procedure pointer. The routine gets + * the discriminant value and then searches the array of xdrdiscrims + * looking for that value. It calls the procedure given in the xdrdiscrim + * to handle the discriminant. If there is no specific routine a default + * routine may be called. + * If there is no specific or default routine an error is returned. + */ +bool_t +xdr_union(xdrs, dscmp, unp, choices, dfault) + register XDR *xdrs; + enum_t *dscmp; /* enum to decide which arm to work on */ + char *unp; /* the union itself */ + struct xdr_discrim *choices; /* [value, xdr proc] for each arm */ + xdrproc_t dfault; /* default xdr routine */ +{ + register enum_t dscm; + + /* + * we deal with the discriminator; it's an enum + */ + if (! xdr_enum(xdrs, dscmp)) { + return (FALSE); + } + dscm = *dscmp; + + /* + * search choices for a value that matches the discriminator. + * if we find one, execute the xdr routine for that value. + */ + for (; choices->proc != NULL_xdrproc_t; choices++) { + if (choices->value == dscm) + return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED)); + } + + /* + * no match - execute the default xdr routine if there is one + */ + return ((dfault == NULL_xdrproc_t) ? FALSE : + (*dfault)(xdrs, unp, LASTUNSIGNED)); +} + + +/* + * Non-portable xdr primitives. + * Care should be taken when moving these routines to new architectures. + */ + + +/* + * XDR null terminated ASCII strings + * xdr_string deals with "C strings" - arrays of bytes that are + * terminated by a NULL character. The parameter cpp references a + * pointer to storage; If the pointer is null, then the necessary + * storage is allocated. The last parameter is the max allowed length + * of the string as specified by a protocol. + */ +bool_t +xdr_string(xdrs, cpp, maxsize) + register XDR *xdrs; + char **cpp; + u_int maxsize; +{ + register char *sp = *cpp; /* sp is the actual string pointer */ + u_int size; + u_int nodesize; + + /* + * first deal with the length since xdr strings are counted-strings + */ + switch (xdrs->x_op) { + case XDR_FREE: + if (sp == NULL) { + return(TRUE); /* already free */ + } + /* fall through... */ + case XDR_ENCODE: + size = strlen(sp); + break; + } + if (! xdr_u_int(xdrs, &size)) { + return (FALSE); + } + if (size > maxsize) { + return (FALSE); + } + nodesize = size + 1; + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) { + + case XDR_DECODE: + if (nodesize == 0) { + return (TRUE); + } + if (sp == NULL) + *cpp = sp = (char *)mem_alloc(nodesize); + if (sp == NULL) { + (void) fprintf(stderr, "xdr_string: out of memory\n"); + return (FALSE); + } + sp[size] = 0; + /* fall into ... */ + + case XDR_ENCODE: + return (xdr_opaque(xdrs, sp, size)); + + case XDR_FREE: + mem_free(sp, nodesize); + *cpp = NULL; + return (TRUE); + } + return (FALSE); +} + +/* + * Wrapper for xdr_string that can be called directly from + * routines like clnt_call + */ +bool_t +xdr_wrapstring(xdrs, cpp) + XDR *xdrs; + char **cpp; +{ + if (xdr_string(xdrs, cpp, LASTUNSIGNED)) { + return (TRUE); + } + return (FALSE); +} diff --git a/src/xdr/xdr.h b/src/xdr/xdr.h new file mode 100755 index 0000000..b1f4530 --- /dev/null +++ b/src/xdr/xdr.h @@ -0,0 +1,388 @@ +/* @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)xdr.h 1.19 87/04/22 SMI */ + +/* + * xdr.h, External Data Representation Serialization Routines. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +/* + * xdr.h porting XDR to Windows NT platform + * + * Jie Chen at Jefferson Lab, chen@jlab.org + */ + +#ifndef __XDR_HEADER__ +#define __XDR_HEADER__ + +/* + * XDR provides a conventional way for converting between C data + * types and an external bit-string representation. Library supplied + * routines provide for the conversion on built-in C data types. These + * routines and utility routines defined here are used to help implement + * a type encode/decode routine for each user-defined type. + * + * Each data type provides a single procedure which takes two arguments: + * + * bool_t + * xdrproc(xdrs, argresp) + * XDR *xdrs; + * *argresp; + * + * xdrs is an instance of a XDR handle, to which or from which the data + * type is to be converted. argresp is a pointer to the structure to be + * converted. The XDR handle contains an operation field which indicates + * which of the operations (ENCODE, DECODE * or FREE) is to be performed. + * + * XDR_DECODE may allocate space if the pointer argresp is null. This + * data can be freed with the XDR_FREE operation. + * + * We write only one procedure per data type to make it easy + * to keep the encode and decode procedures for a data type consistent. + * In many cases the same code performs all operations on a user defined type, + * because all the hard work is done in the component type routines. + * decode as a series of calls on the nested data types. + */ + +/* RPC Types: + * + * These types actually are defined in the rpc/types.h in the regular + * Unix boxes. Copying them here makes life easier + * + * Jie Chen: 12/17/98 + */ +typedef char * caddr_t; +typedef unsigned int u_int; +typedef unsigned long u_long; +typedef unsigned short u_short; +typedef unsigned char u_char; +typedef int bool_t; +typedef int enum_t; + +#define __dontcare__ -1 + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#define mem_alloc(bsize) malloc(bsize) +#define mem_free(ptr,bsize) free(ptr) + +#if defined (__STDC__) || defined (__cplusplus) +#define P_(s) s +#else +#define P_(s) () +#endif + +/* + * Windows NT specific things are declared here + */ +#if defined (_WIN32) + +#if !defined (DLLIMPORT) +#define DLLIMPORT __declspec(dllimport) +#endif + +#if !defined (DLL_EXPORT) +#define DLLEXPORT __declspec(dllexport) +#endif + +#if defined (_CDEV_CORE_EXPORTS_) +#define XDRAPI DLLEXPORT +#else +#define XDRAPI DLLIMPORT +#endif + +#if(_WIN32_WINNT >= 0x0400) +#include +#include +#else +#include +#endif /* _WIN32_WINNT >= 0x0400 */ + +#else + +#define XDRAPI +#define DLLIMPORT +#define DLLEXPORT + +#endif + +/* + * Xdr operations. XDR_ENCODE causes the type to be encoded into the + * stream. XDR_DECODE causes the type to be extracted from the stream. + * XDR_FREE can be used to release the space allocated by an XDR_DECODE + * request. + */ +enum xdr_op { + XDR_ENCODE=0, + XDR_DECODE=1, + XDR_FREE=2 +}; + +/* + * This is the number of bytes per unit of external data. + */ +#define BYTES_PER_XDR_UNIT (4) +#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ + * BYTES_PER_XDR_UNIT) + +/* + * The XDR handle. + * Contains operation which is being applied to the stream, + * an operations vector for the paticular implementation (e.g. see xdr_mem.c), + * and two private fields for the use of the particular impelementation. + */ +typedef struct { + enum xdr_op x_op; /* operation; fast additional param */ + struct xdr_ops *x_ops; + caddr_t x_public; /* users' data */ + caddr_t x_private; /* pointer to private data */ + caddr_t x_base; /* private used for position info */ + int x_handy; /* extra private word */ +} XDR; + +struct xdr_ops { + bool_t (*x_getlong)P_((XDR *, long *)); + /* get a long from underlying stream */ + bool_t (*x_putlong)P_((XDR *, long *)); + /* put a long to " */ + bool_t (*x_getbytes)P_((XDR *, caddr_t, int)); + /* get some bytes from " */ + bool_t (*x_putbytes)P_((XDR *, caddr_t, int)); + /* put some bytes to " */ + u_int (*x_getpostn)P_((XDR *)); + /* returns bytes off from beginning */ + bool_t (*x_setpostn)P_((XDR *, u_int)); + /* lets you reposition the stream */ + long * (*x_inline)P_((XDR *, int)); + /* buf quick ptr to buffered data */ + void (*x_destroy)P_((XDR *)); + /* free privates of this xdr_stream */ +}; + + +/* + * A xdrproc_t exists for each data type which is to be encoded or decoded. + * + * The second argument to the xdrproc_t is a pointer to an opaque pointer. + * The opaque pointer generally points to a structure of the data type + * to be decoded. If this pointer is 0, then the type routines should + * allocate dynamic storage of the appropriate size and return it. + * bool_t (*xdrproc_t)(XDR *, caddr_t *); + */ +#ifdef __cplusplus +typedef bool_t (*xdrproc_t)(XDR *, void *); +#else +#ifdef __STDC__ +typedef bool_t (*xdrproc_t)(); /* for backword compatablity */ +#else +typedef bool_t (*xdrproc_t)(); +#endif +#endif + + +/* + * Operations defined on a XDR handle + * + * XDR *xdrs; + * long *longp; + * caddr_t addr; + * u_int len; + * u_int pos; + */ +#define XDR_GETLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) +#define xdr_getlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) + +#define XDR_PUTLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) +#define xdr_putlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) + +#define XDR_GETBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) +#define xdr_getbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) + +#define XDR_PUTBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) +#define xdr_putbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) + +#define XDR_GETPOS(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) +#define xdr_getpos(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) + +#define XDR_SETPOS(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) +#define xdr_setpos(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) + +#define XDR_INLINE(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) +#define xdr_inline(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) + +#define XDR_DESTROY(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) +#define xdr_destroy(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) + +/* + * Support struct for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * a entry with a null procedure pointer. The xdr_union routine gets + * the discriminant value and then searches the array of structures + * for a matching value. If a match is found the associated xdr routine + * is called to handle that part of the union. If there is + * no match, then a default routine may be called. + * If there is no match and no default routine it is an error. + */ +#define NULL_xdrproc_t ((xdrproc_t)0) +struct xdr_discrim { + int value; + xdrproc_t proc; +}; + +/* + * In-line routines for fast encode/decode of primitve data types. + * Caveat emptor: these use single memory cycles to get the + * data from the underlying buffer, and will fail to operate + * properly if the data is not aligned. The standard way to use these + * is to say: + * if ((buf = XDR_INLINE(xdrs, count)) == NULL) + * return (FALSE); + * <<< macro calls >>> + * where ``count'' is the number of bytes of data occupied + * by the primitive data types. + * + * N.B. and frozen for all time: each data type here uses 4 bytes + * of external representation. + */ +#define IXDR_GET_LONG(buf) ((long)ntohl((u_long)*(buf)++)) +#define IXDR_PUT_LONG(buf, v) (*(buf)++ = (long)htonl((u_long)v)) + +#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) +#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf)) +#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf)) + +#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) +#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v))) + +/* + * These are the "generic" xdr routines. + */ +#if defined (__cplusplus) +extern "C" { +#endif + +extern XDRAPI bool_t xdr_void P_((void)); +extern XDRAPI bool_t xdr_int P_((XDR *, int *)); +extern XDRAPI bool_t xdr_u_int P_((XDR *, u_int *)); +extern XDRAPI bool_t xdr_long P_((XDR *, long *)); +extern XDRAPI bool_t xdr_u_long P_((XDR *, u_long *)); +extern XDRAPI bool_t xdr_short P_((XDR *, short *)); +extern XDRAPI bool_t xdr_u_short P_((XDR *, u_short *)); +extern XDRAPI bool_t xdr_bool P_((XDR *, bool_t *)); +extern XDRAPI bool_t xdr_enum P_((XDR *, enum_t *)); +extern XDRAPI bool_t xdr_array P_((XDR *, caddr_t *, u_int *, const u_int, const u_int, const xdrproc_t)); +extern XDRAPI bool_t xdr_bytes P_((XDR *, char **, u_int *, const u_int)); +extern XDRAPI bool_t xdr_opaque P_((XDR *, caddr_t, const u_int)); +extern XDRAPI bool_t xdr_string P_((XDR *, char **, const u_int)); +extern XDRAPI bool_t xdr_union P_((XDR *, enum_t *, char *, const struct xdr_discrim *, const xdrproc_t)); +extern XDRAPI bool_t xdr_char P_((XDR *, char *)); +extern XDRAPI bool_t xdr_u_char P_((XDR *, u_char *)); +extern XDRAPI bool_t xdr_vector P_((XDR *, char *, const u_int, const u_int, const xdrproc_t)); +extern XDRAPI bool_t xdr_float P_((XDR *, float *)); +extern XDRAPI bool_t xdr_double P_((XDR *, double *)); +extern XDRAPI bool_t xdr_reference P_((XDR *, caddr_t *, u_int, const xdrproc_t)); +extern XDRAPI bool_t xdr_pointer P_((XDR *, char **, u_int, const xdrproc_t)); +extern XDRAPI bool_t xdr_wrapstring P_((XDR *, char **)); +extern XDRAPI void xdr_free P_((xdrproc_t, char *)); +#if defined (__cplusplus) +}; +#endif + +/* + * Common opaque bytes objects used by many rpc protocols; + * declared here due to commonality. + */ +#define MAX_NETOBJ_SZ 1024 +struct netobj { + u_int n_len; + char *n_bytes; +}; +typedef struct netobj netobj; +extern bool_t xdr_netobj(); + +/* + * These are the public routines for the various implementations of + * xdr streams. + */ +#ifdef __cplusplus +extern "C" { +#endif +extern XDRAPI void xdrmem_create P_((XDR *, const caddr_t, const u_int, const enum xdr_op)); + /* XDR using memory buffers */ +extern XDRAPI void xdrstdio_create P_((XDR *, FILE *, const enum xdr_op)); + /* XDR using stdio library */ +extern XDRAPI void xdrrec_create P_((XDR *, const u_int, const u_int, const caddr_t, int (*) (void *, caddr_t, int), int (*) (void *, caddr_t, int))); + /* XDR pseudo records for tcp */ +extern XDRAPI bool_t xdrrec_endofrecord P_((XDR *, bool_t)); + /* make end of xdr record */ +extern XDRAPI bool_t xdrrec_skiprecord P_((XDR *)); + /* move to beginning of next record */ +extern XDRAPI bool_t xdrrec_eof P_((XDR *)); + /* true if no more input */ +#ifdef __cplusplus +}; +#endif + +#endif !__XDR_HEADER__ diff --git a/src/xdr/xdr_array.c b/src/xdr/xdr_array.c new file mode 100755 index 0000000..52ad911 --- /dev/null +++ b/src/xdr/xdr_array.c @@ -0,0 +1,160 @@ +/* @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * xdr_array.c, Generic XDR routines impelmentation. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These are the "non-trivial" xdr primitives used to serialize and de-serialize + * arrays. See xdr.h for more info on the interface to xdr. + */ + +#include + +#ifdef _WIN32 +#include +#include +#include "xdr.h" +#define bzero(s, n) (memset(s, 0, n)) +#else +#include +#include +#endif + +#define LASTUNSIGNED ((u_int)0-1) + + +/* + * XDR an array of arbitrary elements + * *addrp is a pointer to the array, *sizep is the number of elements. + * If addrp is NULL (*sizep * elsize) bytes are allocated. + * elsize is the size (in bytes) of each element, and elproc is the + * xdr procedure to call to handle each element of the array. + */ +bool_t +xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc) + register XDR *xdrs; + caddr_t *addrp; /* array pointer */ + u_int *sizep; /* number of elements */ + u_int maxsize; /* max numberof elements */ + u_int elsize; /* size in bytes of each element */ + xdrproc_t elproc; /* xdr routine to handle each element */ +{ + register u_int i; + register caddr_t target = *addrp; + register u_int c; /* the actual element count */ + register bool_t stat = TRUE; + register u_int nodesize; + + /* like strings, arrays are really counted arrays */ + if (! xdr_u_int(xdrs, sizep)) { + return (FALSE); + } + c = *sizep; + if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) { + return (FALSE); + } + nodesize = c * elsize; + + /* + * if we are deserializing, we may need to allocate an array. + * We also save time by checking for a null array if we are freeing. + */ + if (target == NULL) + switch (xdrs->x_op) { + case XDR_DECODE: + if (c == 0) + return (TRUE); + *addrp = target = mem_alloc(nodesize); + if (target == NULL) { + (void) fprintf(stderr, + "xdr_array: out of memory\n"); + return (FALSE); + } + bzero(target, nodesize); + break; + + case XDR_FREE: + return (TRUE); + } + + /* + * now we xdr each element of array + */ + for (i = 0; (i < c) && stat; i++) { + stat = (*elproc)(xdrs, target, LASTUNSIGNED); + target += elsize; + } + + /* + * the array may need freeing + */ + if (xdrs->x_op == XDR_FREE) { + mem_free(*addrp, nodesize); + *addrp = NULL; + } + return (stat); +} + +/* + * xdr_vector(): + * + * XDR a fixed length array. Unlike variable-length arrays, + * the storage of fixed length arrays is static and unfreeable. + * > basep: base of the array + * > size: size of the array + * > elemsize: size of each element + * > xdr_elem: routine to XDR each element + */ +bool_t +xdr_vector(xdrs, basep, nelem, elemsize, xdr_elem) + register XDR *xdrs; + register char *basep; + register u_int nelem; + register u_int elemsize; + register xdrproc_t xdr_elem; +{ + register u_int i; + register char *elptr; + + elptr = basep; + for (i = 0; i < nelem; i++) { + if (! (*xdr_elem)(xdrs, elptr, LASTUNSIGNED)) { + return(FALSE); + } + elptr += elemsize; + } + return(TRUE); +} + diff --git a/src/xdr/xdr_float.c b/src/xdr/xdr_float.c new file mode 100755 index 0000000..3e91cc4 --- /dev/null +++ b/src/xdr/xdr_float.c @@ -0,0 +1,273 @@ +/* @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * xdr_float.c, Generic XDR routines impelmentation. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These are the "floating point" xdr routines used to (de)serialize + * most common data items. See xdr.h for more info on the interface to + * xdr. + */ + +#include + +#ifdef _WIN32 +#include +#include +#include "xdr.h" +#else +#include +#include +#endif + +/* + * NB: Not portable. + * This routine works on Suns (Sky / 68000's) and Vaxen. + */ + +#ifdef vax + +/* What IEEE single precision floating point looks like on a Vax */ +struct ieee_single { + unsigned int mantissa: 23; + unsigned int exp : 8; + unsigned int sign : 1; +}; + +/* Vax single precision floating point */ +struct vax_single { + unsigned int mantissa1 : 7; + unsigned int exp : 8; + unsigned int sign : 1; + unsigned int mantissa2 : 16; +}; + +#define VAX_SNG_BIAS 0x81 +#define IEEE_SNG_BIAS 0x7f + +static struct sgl_limits { + struct vax_single s; + struct ieee_single ieee; +} sgl_limits[2] = { + {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ + { 0x0, 0xff, 0x0 }}, /* Max IEEE */ + {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ + { 0x0, 0x0, 0x0 }} /* Min IEEE */ +}; +#endif /* vax */ + +bool_t +xdr_float(xdrs, fp) + register XDR *xdrs; + register float *fp; +{ +#if defined (vax) + struct ieee_single is; + struct vax_single vs, *vsp; + struct sgl_limits *lim; + int i; +#endif + switch (xdrs->x_op) { + + case XDR_ENCODE: +#if !defined (vax) + return (XDR_PUTLONG(xdrs, (long *)fp)); +#else + vs = *((struct vax_single *)fp); + for (i = 0, lim = sgl_limits; + i < sizeof(sgl_limits)/sizeof(struct sgl_limits); + i++, lim++) { + if ((vs.mantissa2 == lim->s.mantissa2) && + (vs.exp == lim->s.exp) && + (vs.mantissa1 == lim->s.mantissa1)) { + is = lim->ieee; + goto shipit; + } + } + is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; + is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; + shipit: + is.sign = vs.sign; + return (XDR_PUTLONG(xdrs, (long *)&is)); +#endif + + case XDR_DECODE: +#if !defined (vax) + return (XDR_GETLONG(xdrs, (long *)fp)); +#else + vsp = (struct vax_single *)fp; + if (!XDR_GETLONG(xdrs, (long *)&is)) + return (FALSE); + for (i = 0, lim = sgl_limits; + i < sizeof(sgl_limits)/sizeof(struct sgl_limits); + i++, lim++) { + if ((is.exp == lim->ieee.exp) && + (is.mantissa == lim->ieee.mantissa)) { + *vsp = lim->s; + goto doneit; + } + } + vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; + vsp->mantissa2 = is.mantissa; + vsp->mantissa1 = (is.mantissa >> 16); + doneit: + vsp->sign = is.sign; + return (TRUE); +#endif + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * This routine works on Suns (Sky / 68000's) and Vaxen. + */ + +#ifdef vax +/* What IEEE double precision floating point looks like on a Vax */ +struct ieee_double { + unsigned int mantissa1 : 20; + unsigned int exp : 11; + unsigned int sign : 1; + unsigned int mantissa2 : 32; +}; + +/* Vax double precision floating point */ +struct vax_double { + unsigned int mantissa1 : 7; + unsigned int exp : 8; + unsigned int sign : 1; + unsigned int mantissa2 : 16; + unsigned int mantissa3 : 16; + unsigned int mantissa4 : 16; +}; + +#define VAX_DBL_BIAS 0x81 +#define IEEE_DBL_BIAS 0x3ff +#define MASK(nbits) ((1 << nbits) - 1) + +static struct dbl_limits { + struct vax_double d; + struct ieee_double ieee; +} dbl_limits[2] = { + {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ + { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ + {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ + { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ +}; + +#endif /* vax */ + + +bool_t +xdr_double(xdrs, dp) + register XDR *xdrs; + double *dp; +{ + register long *lp; +#if defined (vax) + struct ieee_double id; + struct vax_double vd; + register struct dbl_limits *lim; + int i; +#endif + + switch (xdrs->x_op) { + + case XDR_ENCODE: +#if !defined (vax) + lp = (long *)dp; +#else + vd = *((struct vax_double *)dp); + for (i = 0, lim = dbl_limits; + i < sizeof(dbl_limits)/sizeof(struct dbl_limits); + i++, lim++) { + if ((vd.mantissa4 == lim->d.mantissa4) && + (vd.mantissa3 == lim->d.mantissa3) && + (vd.mantissa2 == lim->d.mantissa2) && + (vd.mantissa1 == lim->d.mantissa1) && + (vd.exp == lim->d.exp)) { + id = lim->ieee; + goto shipit; + } + } + id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; + id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3); + id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | + (vd.mantissa3 << 13) | + ((vd.mantissa4 >> 3) & MASK(13)); + shipit: + id.sign = vd.sign; + lp = (long *)&id; +#endif + return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp)); + + case XDR_DECODE: +#if !defined (vax) + lp = (long *)dp; + return (XDR_GETLONG(xdrs, lp++) && XDR_GETLONG(xdrs, lp)); +#else + lp = (long *)&id; + if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp)) + return (FALSE); + for (i = 0, lim = dbl_limits; + i < sizeof(dbl_limits)/sizeof(struct dbl_limits); + i++, lim++) { + if ((id.mantissa2 == lim->ieee.mantissa2) && + (id.mantissa1 == lim->ieee.mantissa1) && + (id.exp == lim->ieee.exp)) { + vd = lim->d; + goto doneit; + } + } + vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; + vd.mantissa1 = (id.mantissa1 >> 13); + vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | + (id.mantissa2 >> 29); + vd.mantissa3 = (id.mantissa2 >> 13); + vd.mantissa4 = (id.mantissa2 << 3); + doneit: + vd.sign = id.sign; + *dp = *((double *)&vd); + return (TRUE); +#endif + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} diff --git a/src/xdr/xdr_mem.c b/src/xdr/xdr_mem.c new file mode 100755 index 0000000..2b0325c --- /dev/null +++ b/src/xdr/xdr_mem.c @@ -0,0 +1,198 @@ +/* @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * xdr_mem.h, XDR implementation using memory buffers. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * If you have some data to be interpreted as external data representation + * or to be converted to external data representation in a memory buffer, + * then this is the package for you. + * + */ + +#ifdef _WIN32 +#include +#include + +#if(_WIN32_WINNT >= 0x0400) +#include +#include +#else +#include +#endif /* _WIN32_WINNT >= 0x0400 */ + +#define bcopy(s1, s2, n) (memcpy (s2, s1, n)) +#include "xdr.h" +#else +#include +#include +#include +#endif + +static bool_t xdrmem_getlong(); +static bool_t xdrmem_putlong(); +static bool_t xdrmem_getbytes(); +static bool_t xdrmem_putbytes(); +static u_int xdrmem_getpos(); +static bool_t xdrmem_setpos(); +static long * xdrmem_inline(); +static void xdrmem_destroy(); + +static struct xdr_ops xdrmem_ops = { + xdrmem_getlong, + xdrmem_putlong, + xdrmem_getbytes, + xdrmem_putbytes, + xdrmem_getpos, + xdrmem_setpos, + xdrmem_inline, + xdrmem_destroy +}; + +/* + * The procedure xdrmem_create initializes a stream descriptor for a + * memory buffer. + */ +void +xdrmem_create(xdrs, addr, size, op) + register XDR *xdrs; + caddr_t addr; + u_int size; + enum xdr_op op; +{ + + xdrs->x_op = op; + xdrs->x_ops = &xdrmem_ops; + xdrs->x_private = xdrs->x_base = addr; + xdrs->x_handy = size; +} + +static void +xdrmem_destroy(/*xdrs*/) + /*XDR *xdrs;*/ +{ +} + +static bool_t +xdrmem_getlong(xdrs, lp) + register XDR *xdrs; + long *lp; +{ + + if ((xdrs->x_handy -= sizeof(long)) < 0) + return (FALSE); + *lp = (long)ntohl((u_long)(*((long *)(xdrs->x_private)))); + xdrs->x_private += sizeof(long); + return (TRUE); +} + +static bool_t +xdrmem_putlong(xdrs, lp) + register XDR *xdrs; + long *lp; +{ + + if ((xdrs->x_handy -= sizeof(long)) < 0) + return (FALSE); + *(long *)xdrs->x_private = (long)htonl((u_long)(*lp)); + xdrs->x_private += sizeof(long); + return (TRUE); +} + +static bool_t +xdrmem_getbytes(xdrs, addr, len) + register XDR *xdrs; + caddr_t addr; + register u_int len; +{ + + if ((xdrs->x_handy -= len) < 0) + return (FALSE); + bcopy(xdrs->x_private, addr, len); + xdrs->x_private += len; + return (TRUE); +} + +static bool_t +xdrmem_putbytes(xdrs, addr, len) + register XDR *xdrs; + caddr_t addr; + register u_int len; +{ + + if ((xdrs->x_handy -= len) < 0) + return (FALSE); + bcopy(addr, xdrs->x_private, len); + xdrs->x_private += len; + return (TRUE); +} + +static u_int +xdrmem_getpos(xdrs) + register XDR *xdrs; +{ + + return ((u_int)xdrs->x_private - (u_int)xdrs->x_base); +} + +static bool_t +xdrmem_setpos(xdrs, pos) + register XDR *xdrs; + u_int pos; +{ + register caddr_t newaddr = xdrs->x_base + pos; + register caddr_t lastaddr = xdrs->x_private + xdrs->x_handy; + + if ((long)newaddr > (long)lastaddr) + return (FALSE); + xdrs->x_private = newaddr; + xdrs->x_handy = (int)lastaddr - (int)newaddr; + return (TRUE); +} + +static long * +xdrmem_inline(xdrs, len) + register XDR *xdrs; + int len; +{ + long *buf = 0; + + if (xdrs->x_handy >= len) { + xdrs->x_handy -= len; + buf = (long *) xdrs->x_private; + xdrs->x_private += len; + } + return (buf); +} diff --git a/src/xdr/xdr_rec.c b/src/xdr/xdr_rec.c new file mode 100755 index 0000000..e3ab631 --- /dev/null +++ b/src/xdr/xdr_rec.c @@ -0,0 +1,596 @@ +/* @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking" + * layer above tcp (for rpc's use). + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These routines interface XDRSTREAMS to a tcp/ip connection. + * There is a record marking layer between the xdr stream + * and the tcp transport level. A record is composed on one or more + * record fragments. A record fragment is a thirty-two bit header followed + * by n bytes of data, where n is contained in the header. The header + * is represented as a htonl(u_long). Thegh order bit encodes + * whether or not the fragment is the last fragment of the record + * (1 => fragment is last, 0 => more fragments to follow. + * The other 31 bits encode the byte length of the fragment. + */ + +#include + +#ifdef _WIN32 +#include +#include + +#if(_WIN32_WINNT >= 0x0400) +#include +#include +#else +#include +#endif /* _WIN32_WINNT >= 0x0400 */ + +#define bcopy(s1, s2, n) (memcpy (s2, s1, n)) + +#include "xdr.h" +#else +#include +#include +#include +#endif + +extern long lseek(); + +static u_int fix_buf_size(); + +static bool_t xdrrec_getlong(); +static bool_t xdrrec_putlong(); +static bool_t xdrrec_getbytes(); +static bool_t xdrrec_putbytes(); +static u_int xdrrec_getpos(); +static bool_t xdrrec_setpos(); +static long * xdrrec_inline(); +static void xdrrec_destroy(); + +static struct xdr_ops xdrrec_ops = { + xdrrec_getlong, + xdrrec_putlong, + xdrrec_getbytes, + xdrrec_putbytes, + xdrrec_getpos, + xdrrec_setpos, + xdrrec_inline, + xdrrec_destroy +}; + +/* + * A record is composed of one or more record fragments. + * A record fragment is a two-byte header followed by zero to + * 2**32-1 bytes. The header is treated as a long unsigned and is + * encode/decoded to the network via htonl/ntohl. The low order 31 bits + * are a byte count of the fragment. The highest order bit is a boolean: + * 1 => this fragment is the last fragment of the record, + * 0 => this fragment is followed by more fragment(s). + * + * The fragment/record machinery is not general; it is constructed to + * meet the needs of xdr and rpc based on tcp. + */ + +#define LAST_FRAG ((u_long)(1 << 31)) + +typedef struct rec_strm { + caddr_t tcp_handle; + caddr_t the_buffer; + /* + * out-goung bits + */ + int (*writeit)(); + caddr_t out_base; /* output buffer (points to frag header) */ + caddr_t out_finger; /* next output position */ + caddr_t out_boundry; /* data cannot up to this address */ + u_long *frag_header; /* beginning of curren fragment */ + bool_t frag_sent; /* true if buffer sent in middle of record */ + /* + * in-coming bits + */ + int (*readit)(); + u_long in_size; /* fixed size of the input buffer */ + caddr_t in_base; + caddr_t in_finger; /* location of next byte to be had */ + caddr_t in_boundry; /* can read up to this location */ + long fbtbc; /* fragment bytes to be consumed */ + bool_t last_frag; + u_int sendsize; + u_int recvsize; +} RECSTREAM; + + +/* + * Create an xdr handle for xdrrec + * xdrrec_create fills in xdrs. Sendsize and recvsize are + * send and recv buffer sizes (0 => use default). + * tcp_handle is an opaque handle that is passed as the first parameter to + * the procedures readit and writeit. Readit and writeit are read and + * write respectively. They are like the system + * calls expect that they take an opaque handle rather than an fd. + */ +void +xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit) + register XDR *xdrs; + register u_int sendsize; + register u_int recvsize; + caddr_t tcp_handle; + int (*readit)(); /* like read, but pass it a tcp_handle, not sock */ + int (*writeit)(); /* like write, but pass it a tcp_handle, not sock */ +{ + register RECSTREAM *rstrm = + (RECSTREAM *)mem_alloc(sizeof(RECSTREAM)); + + if (rstrm == NULL) { + (void)fprintf(stderr, "xdrrec_create: out of memory\n"); + /* + * This is bad. Should rework xdrrec_create to + * return a handle, and in this case return NULL + */ + return; + } + /* + * adjust sizes and allocate buffer quad byte aligned + */ + rstrm->sendsize = sendsize = fix_buf_size(sendsize); + rstrm->recvsize = recvsize = fix_buf_size(recvsize); + rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT); + if (rstrm->the_buffer == NULL) { + (void)fprintf(stderr, "xdrrec_create: out of memory\n"); + return; + } + for (rstrm->out_base = rstrm->the_buffer; + (u_int)rstrm->out_base % BYTES_PER_XDR_UNIT != 0; + rstrm->out_base++); + rstrm->in_base = rstrm->out_base + sendsize; + /* + * now the rest ... + */ + xdrs->x_ops = &xdrrec_ops; + xdrs->x_private = (caddr_t)rstrm; + rstrm->tcp_handle = tcp_handle; + rstrm->readit = readit; + rstrm->writeit = writeit; + rstrm->out_finger = rstrm->out_boundry = rstrm->out_base; + rstrm->frag_header = (u_long *)rstrm->out_base; + rstrm->out_finger += sizeof(u_long); + rstrm->out_boundry += sendsize; + rstrm->frag_sent = FALSE; + rstrm->in_size = recvsize; + rstrm->in_boundry = rstrm->in_base; + rstrm->in_finger = (rstrm->in_boundry += recvsize); + rstrm->fbtbc = 0; + rstrm->last_frag = TRUE; +} + + +/* + * The reoutines defined below are the xdr ops which will go into the + * xdr handle filled in by xdrrec_create. + */ + +static bool_t +xdrrec_getlong(xdrs, lp) + XDR *xdrs; + long *lp; +{ + register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + register long *buflp = (long *)(rstrm->in_finger); + long mylong; + + /* first try the inline, fast case */ + if ((rstrm->fbtbc >= sizeof(long)) && + (((int)rstrm->in_boundry - (int)buflp) >= sizeof(long))) { + *lp = (long)ntohl((u_long)(*buflp)); + rstrm->fbtbc -= sizeof(long); + rstrm->in_finger += sizeof(long); + } else { + if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(long))) + return (FALSE); + *lp = (long)ntohl((u_long)mylong); + } + return (TRUE); +} + +/* + * Internal useful routines + */ +static bool_t +flush_out(rstrm, eor) + register RECSTREAM *rstrm; + bool_t eor; +{ + register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0; + register u_long len = (u_long)(rstrm->out_finger) - + (u_long)(rstrm->frag_header) - sizeof(u_long); + + *(rstrm->frag_header) = htonl(len | eormask); + len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->out_base); + if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len) + != (int)len) + return (FALSE); + rstrm->frag_header = (u_long *)rstrm->out_base; + rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(u_long); + return (TRUE); +} + +static bool_t +xdrrec_putlong(xdrs, lp) + XDR *xdrs; + long *lp; +{ + register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + register long *dest_lp = ((long *)(rstrm->out_finger)); + + if ((rstrm->out_finger += sizeof(long)) > rstrm->out_boundry) { + /* + * this case should almost never happen so the code is + * inefficient + */ + rstrm->out_finger -= sizeof(long); + rstrm->frag_sent = TRUE; + if (! flush_out(rstrm, FALSE)) + return (FALSE); + dest_lp = ((long *)(rstrm->out_finger)); + rstrm->out_finger += sizeof(long); + } + *dest_lp = (long)htonl((u_long)(*lp)); + return (TRUE); +} + +static bool_t /* knows nothing about records! Only about input buffers */ +fill_input_buf(rstrm) + register RECSTREAM *rstrm; +{ + register caddr_t where; + u_int i; + register int len; + + where = rstrm->in_base; + i = (u_int)rstrm->in_boundry % BYTES_PER_XDR_UNIT; + where += i; + len = rstrm->in_size - i; + if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1) + return (FALSE); + rstrm->in_finger = where; + where += len; + rstrm->in_boundry = where; + return (TRUE); +} + +static bool_t /* knows nothing about records! Only about input buffers */ +get_input_bytes(rstrm, addr, len) + register RECSTREAM *rstrm; + register caddr_t addr; + register int len; +{ + register int current; + + while (len > 0) { + current = (int)rstrm->in_boundry - (int)rstrm->in_finger; + if (current == 0) { + if (! fill_input_buf(rstrm)) + return (FALSE); + continue; + } + current = (len < current) ? len : current; + bcopy(rstrm->in_finger, addr, current); + rstrm->in_finger += current; + addr += current; + len -= current; + } + return (TRUE); +} + +static bool_t /* next two bytes of the input stream are treated as a header */ +set_input_fragment(rstrm) + register RECSTREAM *rstrm; +{ + u_long header; + + if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header))) + return (FALSE); + header = (long)ntohl(header); + rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE; + rstrm->fbtbc = header & (~LAST_FRAG); + return (TRUE); +} + +static bool_t /* must manage buffers, fragments, and records */ +xdrrec_getbytes(xdrs, addr, len) + XDR *xdrs; + register caddr_t addr; + register u_int len; +{ + register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + register int current; + + while (len > 0) { + current = rstrm->fbtbc; + if (current == 0) { + if (rstrm->last_frag) + return (FALSE); + if (! set_input_fragment(rstrm)) + return (FALSE); + continue; + } + current = (len < current) ? len : current; + if (! get_input_bytes(rstrm, addr, current)) + return (FALSE); + addr += current; + rstrm->fbtbc -= current; + len -= current; + } + return (TRUE); +} + +static bool_t +xdrrec_putbytes(xdrs, addr, len) + XDR *xdrs; + register caddr_t addr; + register u_int len; +{ + register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + register int current; + + while (len > 0) { + current = (u_int)rstrm->out_boundry - (u_int)rstrm->out_finger; + current = (len < current) ? len : current; + bcopy(addr, rstrm->out_finger, current); + rstrm->out_finger += current; + addr += current; + len -= current; + if (rstrm->out_finger == rstrm->out_boundry) { + rstrm->frag_sent = TRUE; + if (! flush_out(rstrm, FALSE)) + return (FALSE); + } + } + return (TRUE); +} + +static u_int +xdrrec_getpos(xdrs) + register XDR *xdrs; +{ + register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + register long pos; + + pos = lseek((int)rstrm->tcp_handle, (long) 0, 1); + if (pos != -1) + switch (xdrs->x_op) { + + case XDR_ENCODE: + pos += rstrm->out_finger - rstrm->out_base; + break; + + case XDR_DECODE: + pos -= rstrm->in_boundry - rstrm->in_finger; + break; + + default: + pos = (u_int) -1; + break; + } + return ((u_int) pos); +} + +static bool_t +xdrrec_setpos(xdrs, pos) + register XDR *xdrs; + u_int pos; +{ + register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + u_int currpos = xdrrec_getpos(xdrs); + int delta = currpos - pos; + caddr_t newpos; + + if ((int)currpos != -1) + switch (xdrs->x_op) { + + case XDR_ENCODE: + newpos = rstrm->out_finger - delta; + if ((newpos > (caddr_t)(rstrm->frag_header)) && + (newpos < rstrm->out_boundry)) { + rstrm->out_finger = newpos; + return (TRUE); + } + break; + + case XDR_DECODE: + newpos = rstrm->in_finger - delta; + if ((delta < (int)(rstrm->fbtbc)) && + (newpos <= rstrm->in_boundry) && + (newpos >= rstrm->in_base)) { + rstrm->in_finger = newpos; + rstrm->fbtbc -= delta; + return (TRUE); + } + break; + } + return (FALSE); +} + +static long * +xdrrec_inline(xdrs, len) + register XDR *xdrs; + int len; +{ + register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + long * buf = NULL; + + switch (xdrs->x_op) { + + case XDR_ENCODE: + if ((rstrm->out_finger + len) <= rstrm->out_boundry) { + buf = (long *) rstrm->out_finger; + rstrm->out_finger += len; + } + break; + + case XDR_DECODE: + if ((len <= rstrm->fbtbc) && + ((rstrm->in_finger + len) <= rstrm->in_boundry)) { + buf = (long *) rstrm->in_finger; + rstrm->fbtbc -= len; + rstrm->in_finger += len; + } + break; + } + return (buf); +} + +static void +xdrrec_destroy(xdrs) + register XDR *xdrs; +{ + register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; + + mem_free(rstrm->the_buffer, + rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT); + mem_free((caddr_t)rstrm, sizeof(RECSTREAM)); +} + +static bool_t /* consumes input bytes; knows nothing about records! */ +skip_input_bytes(rstrm, cnt) + register RECSTREAM *rstrm; + long cnt; +{ + register int current; + + while (cnt > 0) { + current = (int)rstrm->in_boundry - (int)rstrm->in_finger; + if (current == 0) { + if (! fill_input_buf(rstrm)) + return (FALSE); + continue; + } + current = (cnt < current) ? cnt : current; + rstrm->in_finger += current; + cnt -= current; + } + return (TRUE); +} + +/* + * Exported routines to manage xdr records + */ + +/* + * Before reading (deserializing from the stream, one should always call + * this procedure to guarantee proper record alignment. + */ +bool_t +xdrrec_skiprecord(xdrs) + XDR *xdrs; +{ + register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + + while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { + if (! skip_input_bytes(rstrm, rstrm->fbtbc)) + return (FALSE); + rstrm->fbtbc = 0; + if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) + return (FALSE); + } + rstrm->last_frag = FALSE; + return (TRUE); +} + +/* + * Look ahead fuction. + * Returns TRUE iff there is no more input in the buffer + * after consuming the rest of the current record. + */ +bool_t +xdrrec_eof(xdrs) + XDR *xdrs; +{ + register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + + while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { + if (! skip_input_bytes(rstrm, rstrm->fbtbc)) + return (TRUE); + rstrm->fbtbc = 0; + if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) + return (TRUE); + } + if (rstrm->in_finger == rstrm->in_boundry) + return (TRUE); + return (FALSE); +} + +/* + * The client must tell the package when an end-of-record has occurred. + * The second paraemters tells whether the record should be flushed to the + * (output) tcp stream. (This let's the package support batched or + * pipelined procedure calls.) TRUE => immmediate flush to tcp connection. + */ +bool_t +xdrrec_endofrecord(xdrs, sendnow) + XDR *xdrs; + bool_t sendnow; +{ + register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); + register u_long len; /* fragment length */ + + if (sendnow || rstrm->frag_sent || + ((u_long)rstrm->out_finger + sizeof(u_long) >= + (u_long)rstrm->out_boundry)) { + rstrm->frag_sent = FALSE; + return (flush_out(rstrm, TRUE)); + } + len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) - + sizeof(u_long); + *(rstrm->frag_header) = htonl((u_long)len | LAST_FRAG); + rstrm->frag_header = (u_long *)rstrm->out_finger; + rstrm->out_finger += sizeof(u_long); + return (TRUE); +} + + +static u_int +fix_buf_size(s) + register u_int s; +{ + + if (s < 100) + s = 4000; + return (RNDUP(s)); +} diff --git a/src/xdr/xdr_reference.c b/src/xdr/xdr_reference.c new file mode 100755 index 0000000..20c0a5a --- /dev/null +++ b/src/xdr/xdr_reference.c @@ -0,0 +1,142 @@ +/* @(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)xdr_reference.c 1.11 87/08/11 SMI"; +#endif + +/* + * xdr_reference.c, Generic XDR routines impelmentation. + * + * Copyright (C) 1987, Sun Microsystems, Inc. + * + * These are the "non-trivial" xdr primitives used to serialize and de-serialize + * "pointers". See xdr.h for more info on the interface to xdr. + */ + +#include + +#ifdef _WIN32 +#include +#include + +#define bzero(s, n) (memset(s, 0, n)) + +#include "xdr.h" +#else +#include +#include +#endif + +#define LASTUNSIGNED ((u_int)0-1) + +/* + * XDR an indirect pointer + * xdr_reference is for recursively translating a structure that is + * referenced by a pointer inside the structure that is currently being + * translated. pp references a pointer to storage. If *pp is null + * the necessary storage is allocated. + * size is the sizeof the referneced structure. + * proc is the routine to handle the referenced structure. + */ +bool_t +xdr_reference(xdrs, pp, size, proc) + register XDR *xdrs; + caddr_t *pp; /* the pointer to work on */ + u_int size; /* size of the object pointed to */ + xdrproc_t proc; /* xdr routine to handle the object */ +{ + register caddr_t loc = *pp; + register bool_t stat; + + if (loc == NULL) + switch (xdrs->x_op) { + case XDR_FREE: + return (TRUE); + + case XDR_DECODE: + *pp = loc = (caddr_t) mem_alloc(size); + if (loc == NULL) { + (void) fprintf(stderr, + "xdr_reference: out of memory\n"); + return (FALSE); + } + bzero(loc, (int)size); + break; + } + + stat = (*proc)(xdrs, loc, LASTUNSIGNED); + + if (xdrs->x_op == XDR_FREE) { + mem_free(loc, size); + *pp = NULL; + } + return (stat); +} + + +/* + * xdr_pointer(): + * + * XDR a pointer to a possibly recursive data structure. This + * differs with xdr_reference in that it can serialize/deserialiaze + * trees correctly. + * + * What's sent is actually a union: + * + * union object_pointer switch (boolean b) { + * case TRUE: object_data data; + * case FALSE: void nothing; + * } + * + * > objpp: Pointer to the pointer to the object. + * > obj_size: size of the object. + * > xdr_obj: routine to XDR an object. + * + */ +bool_t +xdr_pointer(xdrs,objpp,obj_size,xdr_obj) + register XDR *xdrs; + char **objpp; + u_int obj_size; + xdrproc_t xdr_obj; +{ + + bool_t more_data; + + more_data = (*objpp != NULL); + if (! xdr_bool(xdrs,&more_data)) { + return (FALSE); + } + if (! more_data) { + *objpp = NULL; + return (TRUE); + } + return (xdr_reference(xdrs,objpp,obj_size,xdr_obj)); +} diff --git a/src/xdr/xdr_stdio.c b/src/xdr/xdr_stdio.c new file mode 100755 index 0000000..683bb1a --- /dev/null +++ b/src/xdr/xdr_stdio.c @@ -0,0 +1,204 @@ +/* @(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * xdr_stdio.c, XDR implementation on standard i/o file. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * This set of routines implements a XDR on a stdio stream. + * XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes + * from the stream. + */ + +#include + +#ifdef _WIN32 +#include +#include + +#if(_WIN32_WINNT >= 0x0400) +#include +#include +#else +#include +#endif /* _WIN32_WINNT >= 0x0400 */ + +#include "xdr.h" +#else +#include +#include +#endif + +static bool_t xdrstdio_getlong(); +static bool_t xdrstdio_putlong(); +static bool_t xdrstdio_getbytes(); +static bool_t xdrstdio_putbytes(); +static u_int xdrstdio_getpos(); +static bool_t xdrstdio_setpos(); +static long * xdrstdio_inline(); +static void xdrstdio_destroy(); + +/* + * Ops vector for stdio type XDR + */ +static struct xdr_ops xdrstdio_ops = { + xdrstdio_getlong, /* deseraialize a long int */ + xdrstdio_putlong, /* seraialize a long int */ + xdrstdio_getbytes, /* deserialize counted bytes */ + xdrstdio_putbytes, /* serialize counted bytes */ + xdrstdio_getpos, /* get offset in the stream */ + xdrstdio_setpos, /* set offset in the stream */ + xdrstdio_inline, /* prime stream for inline macros */ + xdrstdio_destroy /* destroy stream */ +}; + +/* + * Initialize a stdio xdr stream. + * Sets the xdr stream handle xdrs for use on the stream file. + * Operation flag is set to op. + */ +void +xdrstdio_create(xdrs, file, op) + register XDR *xdrs; + FILE *file; + enum xdr_op op; +{ + + xdrs->x_op = op; + xdrs->x_ops = &xdrstdio_ops; + xdrs->x_private = (caddr_t)file; + xdrs->x_handy = 0; + xdrs->x_base = 0; +} + +/* + * Destroy a stdio xdr stream. + * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create. + */ +static void +xdrstdio_destroy(xdrs) + register XDR *xdrs; +{ + (void)fflush((FILE *)xdrs->x_private); + /* xx should we close the file ?? */ +} + +static bool_t +xdrstdio_getlong(xdrs, lp) + XDR *xdrs; + register long *lp; +{ + + if (fread((caddr_t)lp, sizeof(long), 1, (FILE *)xdrs->x_private) != 1) + return (FALSE); +#ifndef mc68000 + *lp = ntohl(*lp); +#endif + return (TRUE); +} + +static bool_t +xdrstdio_putlong(xdrs, lp) + XDR *xdrs; + long *lp; +{ + +#ifndef mc68000 + long mycopy = htonl(*lp); + lp = &mycopy; +#endif + if (fwrite((caddr_t)lp, sizeof(long), 1, (FILE *)xdrs->x_private) != 1) + return (FALSE); + return (TRUE); +} + +static bool_t +xdrstdio_getbytes(xdrs, addr, len) + XDR *xdrs; + caddr_t addr; + u_int len; +{ + + if ((len != 0) && (fread(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1)) + return (FALSE); + return (TRUE); +} + +static bool_t +xdrstdio_putbytes(xdrs, addr, len) + XDR *xdrs; + caddr_t addr; + u_int len; +{ + + if ((len != 0) && (fwrite(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1)) + return (FALSE); + return (TRUE); +} + +static u_int +xdrstdio_getpos(xdrs) + XDR *xdrs; +{ + + return ((u_int) ftell((FILE *)xdrs->x_private)); +} + +static bool_t +xdrstdio_setpos(xdrs, pos) + XDR *xdrs; + u_int pos; +{ + + return ((fseek((FILE *)xdrs->x_private, (long)pos, 0) < 0) ? + FALSE : TRUE); +} + +static long * +xdrstdio_inline(xdrs, len) + XDR *xdrs; + u_int len; +{ + + /* + * Must do some work to implement this: must insure + * enough data in the underlying stdio buffer, + * that the buffer is aligned so that we can indirect through a + * long *, and stuff this pointer in xdrs->x_buf. Doing + * a fread or fwrite to a scratch buffer would defeat + * most of the gains to be had here and require storage + * management on this buffer, so we don't do this. + */ + return (NULL); +} diff --git a/test/Makefile b/test/Makefile new file mode 100755 index 0000000..2a22592 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,36 @@ +ARCH = OS +SHOBJ = YES + +include $(CDEV)/include/makeinclude/Makefile.$(ARCH) + +TARGETS = caServiceTest collectionTest cdevDataTest cdevDataEqualTest cdevDataTagMapTest + +targets: $(TARGETS) + +caServiceTest : $(OBJDIR)/caServiceTest.o + @$(LINK.cc) + +FIOTest : $(OBJDIR)/FIOTest.o + @$(LINK.cc) + +IOCTest : $(OBJDIR)/IOCTest.o + @$(LINK.cc) + +cdevDataTest : $(OBJDIR)/cdevDataTest.o + @$(LINK.cc) + +cdevDataTest3 : $(OBJDIR)/cdevDataTest3.o + @$(LINK.cc) + +collectionTest : $(OBJDIR)/collectionTest.o + @$(LINK.cc) + +cdevDataEqualTest : $(OBJDIR)/cdevDataEqualTest.o + @$(LINK.cc) + +cdevDataTagMapTest : $(OBJDIR)/cdevDataTagMapTest.o + @$(LINK.cc) + +cdevSelectorTest : $(OBJDIR)/cdevSelectorTest.o + @$(LINK.cc) + diff --git a/test/NMakefile.mak b/test/NMakefile.mak new file mode 100755 index 0000000..9e9e15a --- /dev/null +++ b/test/NMakefile.mak @@ -0,0 +1,25 @@ +.SUFFIXES: .cc .objbj + +ARCH = WINNT-4.0 +SHOBJ = YES +APPNAME = CDEV Test Applications +TARGETS = cdevDataTest.exe cdevDataTestSimple.exe + +include ..\include\makeinclude\Makefile.WINNT-4.0 + +targets: $(TARGETS) + +$(CDEVBIN): + @mkdir -p $@ + +cdevDataTest.exe: .exec\$(TARGETDIR)\cdevDataTest.obj + @$(LINK) \ + $(CDEVLIB)\cdev.lib $(LINK_EXE_FLAGS) /out:$@ \ + .exec\$(TARGETDIR)\cdevDataTest.obj + +cdevDataTestSimple.exe: .exec\$(TARGETDIR)\cdevDataTestSimple.obj + @$(LINK) \ + $(CDEVLIB)\cdev.lib $(LINK_EXE_FLAGS) /out:$@ \ + .exec\$(TARGETDIR)\cdevDataTestSimple.obj + + diff --git a/test/caServiceTest.cc b/test/caServiceTest.cc new file mode 100755 index 0000000..57326b6 --- /dev/null +++ b/test/caServiceTest.cc @@ -0,0 +1,465 @@ +#include +#include +#include +#include +#include +#include + +int accumulationValue = 0; +int accumulationCount = 0; +int accumulationSeqCnt = 0; + +char tempBuffer[1024] = "\0"; +char outputBuffer [65536] = "\0"; + +void accumulationCallback (int status, void *, cdevRequestObject &, cdevData & data) + { + int newValue; + if(status == CDEV_SUCCESS) accumulationCount++; + data.get("value", &newValue); + if(accumulationValue!=newValue-1) + { + sprintf(tempBuffer, " => ERROR: Missed a callback between value %i and new value %i\n", accumulationValue, newValue); + strcat (outputBuffer, tempBuffer); + accumulationSeqCnt++; + } + accumulationValue=newValue; + } + +void countingCallback ( int status, void * arg, cdevRequestObject &, cdevData &) + { + if(status==CDEV_SUCCESS) + { + int * ptr = (int *)arg; + *ptr = (*ptr)+1; + } + } + +int accumulationTest ( char * device, char * attrib, int steps ) + { + struct timeval first, second, lapsed; + struct timezone tzp; + int resultCode = 0; + int expectedHits = 0; + int callbackHits = 0; + int i; + char monMsg[255]; + char mofMsg[255]; + char setMsg[255]; + cdevCallback cb (accumulationCallback, NULL); + cdevCallback counter (countingCallback, (void *)&callbackHits); + cdevData data; + + sprintf(monMsg, "monitorOn %s", attrib); + sprintf(mofMsg, "monitorOff %s", attrib); + sprintf(setMsg, "set %s", attrib); + + *outputBuffer = 0; + strcat(outputBuffer, "******************************************************************************\n"); + strcat(outputBuffer, " CUMULATIVE MONITORING TESTS \n"); + strcat(outputBuffer, "------------------------------------------------------------------------------\n"); + + gettimeofday(&first, &tzp); + cdevRequestObject & monReq = cdevRequestObject::attachRef(device, monMsg); + cdevRequestObject & mofReq = cdevRequestObject::attachRef(device, mofMsg); + cdevRequestObject & setReq = cdevRequestObject::attachRef(device, setMsg); + gettimeofday(&second, &tzp); + + if (first.tv_usec > second.tv_usec) + { + second.tv_usec += 1000000; + second.tv_sec--; + } + lapsed.tv_usec = second.tv_usec - first.tv_usec; + lapsed.tv_sec = second.tv_sec - first.tv_sec; + sprintf(tempBuffer, "=> TIMER: Time necessary to create cdevRequestObjects: %li.%06li seconds\n\n", lapsed.tv_sec, lapsed.tv_usec); + strcat (outputBuffer, tempBuffer); + + // *************************** + // * Start with a synchronous + // * send test. + // *************************** + accumulationValue = -1; + data.insert ("value", 0); + setReq.send (data, NULL); + monReq.sendCallback(NULL, cb); + cdevSystem::defaultSystem().poll(); + accumulationCount = 0; + accumulationSeqCnt = 0; + + sprintf(tempBuffer, "=> Attempting to submit %i changes with send\n", steps); + strcat (outputBuffer, tempBuffer); + + gettimeofday(&first, &tzp); + for(i=1; i<=steps; i++) + { + data.insert("value", i); + if(setReq.send(data, NULL)==CDEV_SUCCESS) expectedHits++; + } + gettimeofday(&second, &tzp); + + if (first.tv_usec > second.tv_usec) + { + second.tv_usec += 1000000; + second.tv_sec--; + } + lapsed.tv_usec = second.tv_usec - first.tv_usec; + lapsed.tv_sec = second.tv_sec - first.tv_sec; + sprintf(tempBuffer, " => TIMER: Time to submit %i set requests : %li.%06li seconds\n", steps, lapsed.tv_sec, lapsed.tv_usec); + strcat (outputBuffer, tempBuffer); + + if(expectedHits < steps) + { + sprintf(tempBuffer, " => ERROR: Could not submit all requests to the device\n => Attempted Sends: %i\n => Actual Sends : %i\n", steps, expectedHits); + strcat (outputBuffer, tempBuffer); + resultCode = -1; + } + if(expectedHits > accumulationCount) + { + sprintf(tempBuffer, " => ERROR: Not all changes were delivered to callback\n => Expected Hits: %i\n => Actual Hits : %i\n", expectedHits, accumulationCount); + strcat (outputBuffer, tempBuffer); + resultCode = -1; + } + else if (expectedHits < accumulationCount) + { + sprintf(tempBuffer, " => WARN: Additional changes were delivered to callback\n => Expected Hits: %i\n => Actual Hits : %i\n", expectedHits, accumulationCount); + strcat (outputBuffer, tempBuffer); + } + if(accumulationSeqCnt > 0) + { + sprintf(tempBuffer, " => ERROR: %i Callbacks were out of sequence\n", accumulationSeqCnt); + strcat (outputBuffer, tempBuffer); + resultCode = -1; + } + if(resultCode != -1) strcat(outputBuffer, " => PASSED: Successfully passed the send monitoring test\n\n"); + else strcat(outputBuffer, " => FAILED: Failed to correctly execute send monitoring test\n\n"); + + // *************************** + // * Next with an asynchronous + // * sendCallback test. + // *************************** + resultCode = resultCode?-2:0; + cdevSystem::defaultSystem().poll(); + accumulationValue = -1; + data.insert ("value", 0); + setReq.send (data, NULL); + cdevSystem::defaultSystem().poll(); + accumulationCount = 0; + accumulationSeqCnt = 0; + + sprintf(tempBuffer, "=> Attempting to submit %i changes with sendCallback\n", steps); + strcat (outputBuffer, tempBuffer); + + gettimeofday(&first, &tzp); + for(expectedHits=0, i=1; i<=steps; i++) + { + data.insert("value", i); + if(setReq.sendCallback(data, counter)==CDEV_SUCCESS) expectedHits++; + } + + cdevTimeValue t(15.0); + cdevClock timer; + timer.schedule(NULL, t); + do { + cdevSystem::defaultSystem().poll(); + } while((accumulationCount second.tv_usec) + { + second.tv_usec += 1000000; + second.tv_sec--; + } + lapsed.tv_usec = second.tv_usec - first.tv_usec; + lapsed.tv_sec = second.tv_sec - first.tv_sec; + sprintf(tempBuffer, " => TIMER: Time to submit %i set requests : %li.%06li seconds\n", steps, lapsed.tv_sec, lapsed.tv_usec); + strcat (outputBuffer, tempBuffer); + + if(expectedHits < steps) + { + sprintf(tempBuffer, " => ERROR: Could not submit all requests to the device\n => Attempted Sends: %i\n => Actual Sends : %i\n", steps, expectedHits); + strcat (outputBuffer, tempBuffer); + resultCode = -1; + } + if(expectedHits > callbackHits) + { + sprintf(tempBuffer, " => ERROR: Not all set commands were processed\n => Actual Sends: %i\n => Sends Processed : %i\n", expectedHits, callbackHits); + strcat (outputBuffer, tempBuffer); + resultCode = -1; + } + if(expectedHits > accumulationCount) + { + sprintf(tempBuffer, " => ERROR: Not all changes were delivered to callback\n => Expected Hits: %i\n => Actual Hits : %i\n", expectedHits, accumulationCount); + strcat (outputBuffer, tempBuffer); + resultCode = -1; + } + else if (expectedHits < accumulationCount) + { + sprintf(tempBuffer, " => WARN: Additional changes were delivered to callback\n => Expected Hits: %i\n => Actual Hits : %i\n", expectedHits, accumulationCount); + strcat (outputBuffer, tempBuffer); + } + if(accumulationSeqCnt > 0) + { + sprintf(tempBuffer, " => ERROR: %i Callbacks were out of sequence\n", accumulationSeqCnt); + strcat (outputBuffer, tempBuffer); + resultCode = -1; + } + if(resultCode != -1) strcat(outputBuffer, " => PASSED: Successfully passed the sendCallback monitoring test\n\n"); + else strcat(outputBuffer, " => FAILED: Failed to correctly execute sendCallback monitoring test\n\n"); + + // *************************** + // * Finally strike with an + // * asynchronous + // * sendNoBlock test. + // *************************** + resultCode = resultCode?-2:0; + cdevSystem::defaultSystem().poll(); + accumulationValue = -1; + data.insert ("value", 0); + setReq.send (data, NULL); + cdevSystem::defaultSystem().poll(); + accumulationCount = 0; + accumulationSeqCnt = 0; + + sprintf(tempBuffer, "=> Attempting to submit %i changes with sendNoBlock\n", steps); + strcat (outputBuffer, tempBuffer); + + gettimeofday(&first, &tzp); + + cdevGroup group; + group.start(); + for(expectedHits=0, i=1; i<=steps; i++) + { + data.insert("value", i); + if(setReq.sendNoBlock(data, NULL)==CDEV_SUCCESS) expectedHits++; + } + group.end(); + + timer.schedule(NULL, t); + do { + group.poll(); + } while(!group.allFinished() && !timer.expired()); + + while(accumulationCount second.tv_usec) + { + second.tv_usec += 1000000; + second.tv_sec--; + } + lapsed.tv_usec = second.tv_usec - first.tv_usec; + lapsed.tv_sec = second.tv_sec - first.tv_sec; + sprintf(tempBuffer, " => TIMER: Time to submit %i set requests : %li.%06li seconds\n", steps, lapsed.tv_sec, lapsed.tv_usec); + strcat (outputBuffer, tempBuffer); + + if(expectedHits < steps) + { + sprintf(tempBuffer, " => ERROR: Could not submit all requests to the device\n => Attempted Sends: %i\n => Actual Sends : %i\n", steps, expectedHits); + strcat (outputBuffer, tempBuffer); + resultCode = -1; + } + if(expectedHits > callbackHits) + { + sprintf(tempBuffer, " => ERROR: Not all set commands were processed\n => Actual Sends: %i\n => Sends Processed : %i\n", expectedHits, callbackHits); + strcat (outputBuffer, tempBuffer); + resultCode = -1; + } + if(expectedHits > accumulationCount) + { + sprintf(tempBuffer, " => ERROR: Not all changes were delivered to callback\n => Expected Hits: %i\n => Actual Hits : %i\n", expectedHits, accumulationCount); + strcat (outputBuffer, tempBuffer); + resultCode = -1; + } + else if (expectedHits < accumulationCount) + { + sprintf(tempBuffer, " => WARN: Additional changes were delivered to callback\n => Expected Hits: %i\n => Actual Hits : %i\n", expectedHits, accumulationCount); + strcat (outputBuffer, tempBuffer); + } + if(accumulationSeqCnt > 0) + { + sprintf(tempBuffer, " => ERROR: %i Callbacks were out of sequence\n", accumulationSeqCnt); + strcat (outputBuffer, tempBuffer); + resultCode = -1; + } + if(resultCode != -1) strcat(outputBuffer, " => PASSED: Successfully passed the sendNoBlock monitoring test\n\n"); + else strcat(outputBuffer, " => FAILED: Failed to correctly execute sendNoBlock monitoring test\n\n"); + + + // ************************** + // * Detach the monitor using + // * the monitorOff command. + // ************************** + mofReq.sendCallback(NULL, cb); + cdevSystem::defaultSystem().poll(); + + strcat(outputBuffer, "******************************************************************************\n\n"); + return resultCode; + } + +int getTest ( char * device, char * attrib, int steps) + { + struct timeval first, second, lapsed; + struct timezone tzp; + int i; + int resultCode = 0; + int expectedHits = 0; + int callbackHits = 0; + char getMsg[255]; + cdevData data; + cdevCallback counter (countingCallback, (void *)&callbackHits); + sprintf(getMsg, "get %s", attrib); + + *outputBuffer = 0; + strcat(outputBuffer, "******************************************************************************\n"); + strcat(outputBuffer, " SIMPLE GET TESTS\n"); + strcat(outputBuffer, "------------------------------------------------------------------------------\n"); + + gettimeofday(&first, &tzp); + cdevRequestObject & getReq = cdevRequestObject::attachRef(device, getMsg); + gettimeofday(&second, &tzp); + + if (first.tv_usec > second.tv_usec) + { + second.tv_usec += 1000000; + second.tv_sec--; + } + lapsed.tv_usec = second.tv_usec - first.tv_usec; + lapsed.tv_sec = second.tv_sec - first.tv_sec; + sprintf(tempBuffer, "=> TIMER: Time necessary to create cdevRequestObjects: %li.%06li seconds\n\n", lapsed.tv_sec, lapsed.tv_usec); + strcat (outputBuffer, tempBuffer); + + // *************************** + // * Start with a synchronous + // * send test. + // *************************** + sprintf(tempBuffer, "=> Attempting to submit %i get requests with send\n", steps); + strcat (outputBuffer, tempBuffer); + + gettimeofday(&first, &tzp); + for(i=1; i<=steps; i++) if(getReq.send(NULL, data)==CDEV_SUCCESS) expectedHits++; + gettimeofday(&second, &tzp); + + if (first.tv_usec > second.tv_usec) + { + second.tv_usec += 1000000; + second.tv_sec--; + } + lapsed.tv_usec = second.tv_usec - first.tv_usec; + lapsed.tv_sec = second.tv_sec - first.tv_sec; + sprintf(tempBuffer, " => TIMER: Time to submit %i get requests : %li.%06li seconds\n", steps, lapsed.tv_sec, lapsed.tv_usec); + strcat (outputBuffer, tempBuffer); + + if(expectedHits < steps) + { + sprintf(tempBuffer, " => ERROR: Could not submit all requests to the device\n => Attempted Sends: %i\n => Actual Sends : %i\n", steps, expectedHits); + strcat (outputBuffer, tempBuffer); + resultCode = -1; + } + if(resultCode != -1) strcat(outputBuffer, " => PASSED: Successfully passed the send test\n\n"); + else strcat(outputBuffer, " => FAILED: Failed to correctly execute send test\n\n"); + + // *************************** + // * Next with an asynchronous + // * sendCallback test. + // *************************** + if(resultCode<0) resultCode = -2; + sprintf(tempBuffer, "=> Attempting to submit %i get requests with sendCallback\n", steps); + strcat (outputBuffer, tempBuffer); + + gettimeofday(&first, &tzp); + for(expectedHits=0, i=1; i<=steps; i++) + { + if(getReq.sendCallback(data, counter)==CDEV_SUCCESS) expectedHits++; + } + + cdevTimeValue t(15.0); + cdevClock timer; + timer.schedule(NULL, t); + do { + cdevSystem::defaultSystem().poll(); + } while(callbackHits second.tv_usec) + { + second.tv_usec += 1000000; + second.tv_sec--; + } + lapsed.tv_usec = second.tv_usec - first.tv_usec; + lapsed.tv_sec = second.tv_sec - first.tv_sec; + sprintf(tempBuffer, " => TIMER: Time to submit %i get requests : %li.%06li seconds\n", steps, lapsed.tv_sec, lapsed.tv_usec); + strcat (outputBuffer, tempBuffer); + + if(expectedHits < steps) + { + sprintf(tempBuffer, " => ERROR: Could not submit all requests to the device\n => Attempted Sends: %i\n => Actual Sends : %i\n", steps, expectedHits); + strcat (outputBuffer, tempBuffer); + resultCode = -1; + } + if(expectedHits > callbackHits) + { + sprintf(tempBuffer, " => ERROR: Not all get commands were processed\n => Actual Sends: %i\n => Sends Processed : %i\n", expectedHits, callbackHits); + strcat (outputBuffer, tempBuffer); + resultCode = -1; + } + if(resultCode != -1) strcat(outputBuffer, " => PASSED: Successfully passed the sendCallback get test\n\n"); + else strcat(outputBuffer, " => FAILED: Failed to correctly execute sendCallback get test\n\n"); + + // *************************** + // * Next with an asynchronous + // * sendNoBlock test. + // *************************** + if(resultCode<0) resultCode = -2; + sprintf(tempBuffer, "=> Attempting to submit %i get requests with sendNoBlock\n", steps); + strcat (outputBuffer, tempBuffer); + + gettimeofday(&first, &tzp); + cdevGroup group; + group.start(); + for(expectedHits=0, i=1; i<=steps; i++) + { + if(getReq.sendNoBlock(NULL, data)==CDEV_SUCCESS) expectedHits++; + } + group.end(); + while(!group.allFinished()) group.poll(); + gettimeofday(&second, &tzp); + + if (first.tv_usec > second.tv_usec) + { + second.tv_usec += 1000000; + second.tv_sec--; + } + lapsed.tv_usec = second.tv_usec - first.tv_usec; + lapsed.tv_sec = second.tv_sec - first.tv_sec; + sprintf(tempBuffer, " => TIMER: Time to submit %i get requests : %li.%06li seconds\n", steps, lapsed.tv_sec, lapsed.tv_usec); + strcat (outputBuffer, tempBuffer); + + if(expectedHits < steps) + { + sprintf(tempBuffer, " => ERROR: Could not submit all requests to the device\n => Attempted Sends: %i\n => Actual Sends : %i\n", steps, expectedHits); + strcat (outputBuffer, tempBuffer); + resultCode = -1; + } + if(resultCode != -1) strcat(outputBuffer, " => PASSED: Successfully passed the sendNoBlock get test\n\n"); + else strcat(outputBuffer, " => FAILED: Failed to correctly execute sendNoBlock get test\n\n"); + + strcat(outputBuffer, "******************************************************************************\n\n"); + return resultCode; + } + + +int main(int argc, char ** argv) + { + int repetition = argc>1?(atoi(argv[1])):100; + cdevSystem::defaultSystem().setThreshold(CDEV_SEVERITY_ERROR); + + accumulationTest("cdev_ai0", "VAL", repetition); + fprintf(stdout, outputBuffer); + getTest("cdev_ai0", "VAL", repetition); + fprintf(stdout, outputBuffer); + } diff --git a/test/cdevCollection/Makefile b/test/cdevCollection/Makefile new file mode 100755 index 0000000..34740bf --- /dev/null +++ b/test/cdevCollection/Makefile @@ -0,0 +1,26 @@ +######################################################################## +# Makefile for shared object +######################################################################## +CDEVROOT = $(CDEV) +include $(CDEVROOT)/examples/Makefile.common + +CXXEXTRA = $(CLASS_INCLUDES) $(EPICSINCLUDES) +EPICSLIBS = -L$(EPICSLIB) -lCom -lDb -lca + +LIBS = -L$(CDEVLIB) -lcdev -lEpicsCa -lSampleService -lSimpleService \ + $(EPICSLIBS) -lm -ly -ll + +TARGETS = attachCollection detachCollection add1 add2 add3 add4 add5 \ + remove1 remove2 remove3 remove4 remove5 getList + +targets: $(TARGETS) + +% : %.cc + @echo "=> Building $@" + @rm -f $@ + @$(PROOF) $(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ $(LIBS) -o $@ + @rm -rf ptrepository + +clean: + @rm -rf *.o *.a *~ *.?.? TC.Cache $(TARGETS) core ptrepository + diff --git a/test/cdevCollection/add1.cc b/test/cdevCollection/add1.cc new file mode 100755 index 0000000..1745607 --- /dev/null +++ b/test/cdevCollection/add1.cc @@ -0,0 +1,21 @@ +#include + +void main ( void ) +{ +/************************************************************** + * Attach to an undefined cdevCollection device and then add + * the cdevDevice "device0" to it. + **************************************************************/ +cdevCollection & brandNew = cdevCollection::attachRef("brandNew"); +brandNew.add("device0"); + +/************************************************************** + * Use the getList method to obtain the array of names that are + * currently stored in the cdevCollection and display them. + * Note that the list (not the list items) msut be deleted by + * the caller. + **************************************************************/ +char ** list = brandNew.getList(); +for(char **s = list; *s!=NULL; s++) printf("%s\n", *s); +delete list; +} diff --git a/test/cdevCollection/add2.cc b/test/cdevCollection/add2.cc new file mode 100755 index 0000000..176e586 --- /dev/null +++ b/test/cdevCollection/add2.cc @@ -0,0 +1,21 @@ +#include + +void main ( void ) +{ +/************************************************************** + * Attach to the cdevCollection "brandNew" and add four device + * names to it. + **************************************************************/ +cdevCollection & brandNew = cdevCollection::attachRef("brandNew"); +brandNew.add(4, "device0", "device1", "device2", "device3"); + +/************************************************************** + * Use the getList method to obtain the array of names that are + * currently stored in the cdevCollection and display them. + * Note that the list (not the list items) msut be deleted by + * the caller. + **************************************************************/ +char ** list = brandNew.getList(); +for(char **s = list; *s!=NULL; s++) printf("%s\n", *s); +delete list; +} diff --git a/test/cdevCollection/add3.cc b/test/cdevCollection/add3.cc new file mode 100755 index 0000000..4b59e4c --- /dev/null +++ b/test/cdevCollection/add3.cc @@ -0,0 +1,23 @@ +#include + +char * devices[] = {"device0", "device1", "device2", "device3"}; + +void main ( void ) +{ +/************************************************************** + * Attach to the cdevCollection "brandNew" and add four device + * names to it. + **************************************************************/ +cdevCollection & brandNew = cdevCollection::attachRef("brandNew"); +brandNew.add(4, devices); + +/************************************************************** + * Use the getList method to obtain the array of names that are + * currently stored in the cdevCollection and display them. + * Note that the list (not the list items) msut be deleted by + * the caller. + **************************************************************/ +char ** list = brandNew.getList(); +for(char **s = list; *s!=NULL; s++) printf("%s\n", *s); +delete list; +} diff --git a/test/cdevCollection/add4.cc b/test/cdevCollection/add4.cc new file mode 100755 index 0000000..be41022 --- /dev/null +++ b/test/cdevCollection/add4.cc @@ -0,0 +1,23 @@ +#include + +char * devices[] = {"device0", "device1", "device2", NULL}; + +void main ( void ) +{ +/************************************************************** + * Attach to the cdevCollection "brandNew" and add a NULL + * terminated list of devices to it. + **************************************************************/ +cdevCollection & brandNew = cdevCollection::attachRef("brandNew"); +brandNew.add(devices); + +/************************************************************** + * Use the getList method to obtain the array of names that are + * currently stored in the cdevCollection and display them. + * Note that the list (not the list items) msut be deleted by + * the caller. + **************************************************************/ +char ** list = brandNew.getList(); +for(char **s = list; *s!=NULL; s++) printf("%s\n", *s); +delete list; +} diff --git a/test/cdevCollection/add5.cc b/test/cdevCollection/add5.cc new file mode 100755 index 0000000..42a78b1 --- /dev/null +++ b/test/cdevCollection/add5.cc @@ -0,0 +1,21 @@ +#include + +void main ( void ) +{ +/************************************************************** + * Attach to the cdevCollection "brandNew" and add a NULL + * terminated list of devices to it. + **************************************************************/ +cdevCollection & brandNew = cdevCollection::attachRef("brandNew"); +brandNew.addRegexp("device?"); + +/************************************************************** + * Use the getList method to obtain the array of names that are + * currently stored in the cdevCollection and display them. + * Note that the list (not the list items) msut be deleted by + * the caller. + **************************************************************/ +char ** list = brandNew.getList(); +for(char **s = list; *s!=NULL; s++) printf("%s\n", *s); +delete list; +} diff --git a/test/cdevCollection/attachCollection.cc b/test/cdevCollection/attachCollection.cc new file mode 100755 index 0000000..355ad4e --- /dev/null +++ b/test/cdevCollection/attachCollection.cc @@ -0,0 +1,21 @@ +#include + +void main ( void ) +{ +/*************************************************************** + * Obtain a reference to a cdevCollection device named + * "brandNew". Because this collection is not defined in the + * CDEV DDL file, it will be created with no constituent + * devices. + ***************************************************************/ +cdevCollection & brandNew = cdevCollection::attachRef("brandNew"); + +/*************************************************************** + * Obtain a reference to a cdevCollection device named + * "cDevice1". This collection is defined in the CDEV DDL file + * and will be populated with the devices: "device0", "device1", + * and "device2". + ***************************************************************/ +cdevCollection * cDevice1 = cdevCollection::attachPtr("cDevice1"); +} + diff --git a/test/cdevCollection/collection.ddl b/test/cdevCollection/collection.ddl new file mode 100755 index 0000000..43b7e03 --- /dev/null +++ b/test/cdevCollection/collection.ddl @@ -0,0 +1,42 @@ +service Sample + { + tags {server} + } + +class Samples + { + verbs {get, set, monitorOn, monitorOff} + attributes + { + default Sample; + servers Sample; + attrib0 Sample; + attrib1 Sample; + attrib2 Sample; + attrib3 Sample; + attrib4 Sample; + attrib5 Sample; + attrib6 Sample; + attrib7 Sample; + attrib8 Sample; + attrib9 Sample; + } + } + + +Samples : + device0, device1, device2, device3, device4, + device5, device6, device7, device8, device9 +; + +collection cDevice1 : +device0, +device1, +device2 +; + +collection cDevice2 : +device3 +device4 +device5 +; diff --git a/test/cdevCollection/detachCollection.cc b/test/cdevCollection/detachCollection.cc new file mode 100755 index 0000000..4c773ea --- /dev/null +++ b/test/cdevCollection/detachCollection.cc @@ -0,0 +1,8 @@ +#include + +void main ( void ) +{ +cdevCollection & cDevice1 = cdevCollection::attachRef("cDevice1"); +cdevCollection::detach(cDevice1); +} + diff --git a/test/cdevCollection/getList.cc b/test/cdevCollection/getList.cc new file mode 100755 index 0000000..89df3fa --- /dev/null +++ b/test/cdevCollection/getList.cc @@ -0,0 +1,18 @@ +#include + +void main ( void ) +{ +/************************************************************** + * Attach to a cdevCollection device and then use the getList + * method to obtain the array of names that are currently + * stored in the cdevCollection and display them. + * + * Note that the list (not the list items) must be deleted by + * the caller. + **************************************************************/ +cdevCollection & cDevice1 = cdevCollection::attachRef("cDevice1"); + +char ** list = cDevice1.getList(); +for(char **s = list; *s!=NULL; s++) printf("%s\n", *s); +delete list; +} diff --git a/test/cdevCollection/remove1.cc b/test/cdevCollection/remove1.cc new file mode 100755 index 0000000..7b4a46b --- /dev/null +++ b/test/cdevCollection/remove1.cc @@ -0,0 +1,21 @@ +#include + +void main ( void ) +{ +/************************************************************** + * Attach to a defined cdevCollection device and then remove + * the cdevDevice "device0" from it. + **************************************************************/ +cdevCollection & cDevice1 = cdevCollection::attachRef("cDevice1"); +cDevice1.remove("device0"); + +/************************************************************** + * Use the getList method to obtain the array of names that are + * currently stored in the cdevCollection and display them. + * Note that the list (not the list items) msut be deleted by + * the caller. + **************************************************************/ +char ** list = cDevice1.getList(); +for(char **s = list; *s!=NULL; s++) printf("%s\n", *s); +delete list; +} diff --git a/test/cdevCollection/remove2.cc b/test/cdevCollection/remove2.cc new file mode 100755 index 0000000..b0efad1 --- /dev/null +++ b/test/cdevCollection/remove2.cc @@ -0,0 +1,21 @@ +#include + +void main ( void ) +{ +/************************************************************** + * Attach to a defined cdevCollection device and then remove + * two cdevDevices from it. + **************************************************************/ +cdevCollection & cDevice1 = cdevCollection::attachRef("cDevice1"); +cDevice1.remove(2, "device0", "device2"); + +/************************************************************** + * Use the getList method to obtain the array of names that are + * currently stored in the cdevCollection and display them. + * Note that the list (not the list items) msut be deleted by + * the caller. + **************************************************************/ +char ** list = cDevice1.getList(); +for(char **s = list; *s!=NULL; s++) printf("%s\n", *s); +delete list; +} diff --git a/test/cdevCollection/remove3.cc b/test/cdevCollection/remove3.cc new file mode 100755 index 0000000..dae3902 --- /dev/null +++ b/test/cdevCollection/remove3.cc @@ -0,0 +1,23 @@ +#include + +char * devices[] = {"device0", "device2"}; + +void main ( void ) +{ +/************************************************************** + * Attach to a defined cdevCollection device and then remove + * two cdevDevices from it. + **************************************************************/ +cdevCollection & cDevice1 = cdevCollection::attachRef("cDevice1"); +cDevice1.remove(2, devices); + +/************************************************************** + * Use the getList method to obtain the array of names that are + * currently stored in the cdevCollection and display them. + * Note that the list (not the list items) msut be deleted by + * the caller. + **************************************************************/ +char ** list = cDevice1.getList(); +for(char **s = list; *s!=NULL; s++) printf("%s\n", *s); +delete list; +} diff --git a/test/cdevCollection/remove4.cc b/test/cdevCollection/remove4.cc new file mode 100755 index 0000000..5d83b61 --- /dev/null +++ b/test/cdevCollection/remove4.cc @@ -0,0 +1,23 @@ +#include + +char * devices[] = {"device0", "device2", NULL}; + +void main ( void ) +{ +/************************************************************** + * Attach to a defined cdevCollection device and then remove + * a NULL terminated list of devices from it. + **************************************************************/ +cdevCollection & cDevice1 = cdevCollection::attachRef("cDevice1"); +cDevice1.remove(devices); + +/************************************************************** + * Use the getList method to obtain the array of names that are + * currently stored in the cdevCollection and display them. + * Note that the list (not the list items) msut be deleted by + * the caller. + **************************************************************/ +char ** list = cDevice1.getList(); +for(char **s = list; *s!=NULL; s++) printf("%s\n", *s); +delete list; +} diff --git a/test/cdevCollection/remove5.cc b/test/cdevCollection/remove5.cc new file mode 100755 index 0000000..08e352d --- /dev/null +++ b/test/cdevCollection/remove5.cc @@ -0,0 +1,21 @@ +#include + +void main ( void ) +{ +/************************************************************** + * Attach to a defined cdevCollection device and then remove + * all devices that match the specified regular expression. + **************************************************************/ +cdevCollection & cDevice1 = cdevCollection::attachRef("cDevice1"); +cDevice1.removeRegexp("device?"); + +/************************************************************** + * Use the getList method to obtain the array of names that are + * currently stored in the cdevCollection and display them. + * Note that the list (not the list items) msut be deleted by + * the caller. + **************************************************************/ +char ** list = cDevice1.getList(); +for(char **s = list; *s!=NULL; s++) printf("%s\n", *s); +delete list; +} diff --git a/test/cdevDataEqualTest.cc b/test/cdevDataEqualTest.cc new file mode 100755 index 0000000..e3c9ae1 --- /dev/null +++ b/test/cdevDataEqualTest.cc @@ -0,0 +1,91 @@ +#include + +void scalarTest( void ) + { + cdevData data1; + + data1.insert(1, (unsigned char)1); + data1.insert(2, (short)2); + data1.insert(3, (unsigned short)3); + data1.insert(4, (int) 4); + data1.insert(5, (unsigned int) 5); + data1.insert(6, (float) 6.0); + data1.insert(7, (double) 7.0); + data1.insert(8, "This is a test"); + + cdevData data2 (data1); + cdevData data3 (data1); + cdevData data4 (data1); + cdevData data5 (data1); + cdevData data6; + cdevData data7; + + + data3.insert(8, "This was a test"); + data4.remove(1); + data5.insert(1, (int)1); + data6 = data1; + data7.insert(9, "Test"); + + fprintf(stdout, "SCALAR TEST\n"); + fprintf(stdout, "Data 1 %s equal to Data 2 - should be equal...\n", data1==data2?"IS":"IS NOT"); + fprintf(stdout, "Data 1 %s equal to Data 3 - should NOT be equal...\n", data1==data3?"IS":"IS NOT"); + fprintf(stdout, "Data 1 %s equal to Data 4 - should NOT be equal...\n", data1==data4?"IS":"IS NOT"); + fprintf(stdout, "Data 1 %s equal to Data 5 - should NOT be equal...\n", data1==data5?"IS":"IS NOT"); + fprintf(stdout, "Data 1 %s equal to Data 6 - should be equal...\n", data1==data6?"IS":"IS NOT"); + fprintf(stdout, "Data 1 %s equal to Data 7 - should NOT be equal...\n", data1==data7?"IS":"IS NOT"); + fprintf(stdout, "\n"); + } + +int array1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; +unsigned char array2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; +char * array3[] = { + "This is a test", + "This is a test 2", + "This is a test 3", + "This is a test 4" + }; + +cdevBounds bounds1[2] = + { + {0, 1},{0, 4} + }; + +cdevBounds bounds2[2] = + { + {0, 1},{0, 2} + }; + +void vectorTest ( void ) + { + cdevData data1; + + data1.insert(1, array1, 10); + data1.insert(2, array2, 10); + data1.insert(3, array3, 4); + + cdevData data2 (data1); + + fprintf(stdout, "---------------------------------\n"); + fprintf(stdout, "Diagnostic Dump of cdevData data1\n"); + fprintf(stdout, "---------------------------------\n"); + data1.asciiDump(); + fprintf(stdout, "---------------------------------\n"); + + fprintf(stdout, "---------------------------------\n"); + fprintf(stdout, "Diagnostic Dump of cdevData data2\n"); + fprintf(stdout, "---------------------------------\n"); + data2.asciiDump(); + fprintf(stdout, "---------------------------------\n"); + + fprintf(stdout, "ARRAY TEST\n"); + fprintf(stdout, "Data 1 %s equal to Data 2 - should be equal...\n", data1==data2?"IS":"IS NOT"); + fprintf(stdout, "\n"); + } + +int main() + { + scalarTest(); + vectorTest(); + } + diff --git a/test/cdevDataTagMapTest.cc b/test/cdevDataTagMapTest.cc new file mode 100755 index 0000000..2236707 --- /dev/null +++ b/test/cdevDataTagMapTest.cc @@ -0,0 +1,57 @@ +#include + +class myDataCallback : public cdevTagTableCallback +{ +private: + char * name_; + +public: + myDataCallback ( char * name ) + { + name_ = strdup(name); + cdevData::addTagCallback(this); + } + ~myDataCallback ( void ) + { + cdevData::delTagCallback(this); + free(name_); + } + void callback (int newTag, char * newName) + { + fprintf(stdout, "%s: Tag %i was just assigned to name \"%s\"\n", name_, newTag, newName); + } +}; + +int main() +{ +char ** names = NULL; +int * tags = NULL; +int cnt = 0; +int i; + +cdevData::readTagTable (tags, names, cnt); +for(i=0; i +#include +#include "equal.h" + +typedef int (*cdevTest)(cdevData & data); + +int tagTest ( cdevData & data ); +int scalarTest ( cdevData & data ); +int byteArrayTest ( cdevData & data ); +int shortArrayTest ( cdevData & data ); +int ushortArrayTest ( cdevData & data ); +int intArrayTest ( cdevData & data ); +int uintArrayTest ( cdevData & data ); +int longArrayTest ( cdevData & data ); +int ulongArrayTest ( cdevData & data ); +int floatArrayTest ( cdevData & data ); +int doubleArrayTest ( cdevData & data ); +int stringArrayTest ( cdevData & data ); +int asciiDumpTest ( cdevData & data ); +int copyTest ( cdevData & data ); +int assignmentTest ( cdevData & data ); +int removeTest ( cdevData & data ); +int findTest ( cdevData & data ); +int xdrTest ( cdevData & data ); + +enum testTags + { + TAGTEST = 0, + SCALARTEST, + BYTEARRAYTEST, + SHORTARRAYTEST, + USHORTARRAYTEST, + INTARRAYTEST, + UINTARRAYTEST, + LONGARRAYTEST, + ULONGARRAYTEST, + FLOATARRAYTEST, + DOUBLEARRAYTEST, + STRINGARRAYTEST, + COPYTEST, + ASSIGNTEST, + FINDTEST, + XDRTEST, + ASCIIDUMPTEST, + REMOVETEST, + MAXTESTS + }; + +cdevTest testFunctions[MAXTESTS] = + { + tagTest, + scalarTest, + byteArrayTest, + shortArrayTest, + ushortArrayTest, + intArrayTest, + uintArrayTest, + longArrayTest, + ulongArrayTest, + floatArrayTest, + doubleArrayTest, + stringArrayTest, + copyTest, + assignmentTest, + findTest, + xdrTest, + asciiDumpTest, + removeTest, + }; + +char * testNames[MAXTESTS] = + { + "Tag Insertion/Extraction Test", + "Scalar Insertion/Extraction Test", + "Byte Array Insertion/Extraction Test", + "Short Array Insertion/Extraction Test", + "Unsigned Short Array Insert/Extract Test", + "Int Array Insert/Extract Test", + "Unsigned Int Array Insert/Extract Test", + "Long Array Insert/Extract Test", + "Unsigned Long Array Insert/Extract Test", + "Float Array Insert/Extract Test", + "Double Array Insert/Extract Test", + "String Insert/Extract Test", + "Copy Constructor Test", + "Assignment Operator Copy Test", + "Tagged Item Find Test", + "XDR Import/Export Facility Test", + "ASCII Dump Test", + "Tagged Item Deletion Test", + }; + + +int testResults[MAXTESTS]; + + +int main() +{ +int i; +cdevData data; + +for(i=0; i0.0001 || D[9]!=(double)atof(STR[9])) + { + fprintf(stdout, "* ERROR IN STRING INSERTION/EXTRACTION\n"); + result = -1; + } +return result; +} + + +int byteArrayTest ( cdevData & data ) +{ +int LOCALTAG = 10; +int result = 0, bresult = 0; +int x; +BYTE input[1000]; +cdevBounds bounds[3]; +cdevBounds obounds[3]; + +BYTE C[1000]; +short S[1000]; +unsigned short US[1000]; +int I[1000]; +unsigned int UI[1000]; +long L[1000]; +unsigned long UL[1000]; +float F[1000]; +double D[1000]; +char * STR[1000]; + +bounds[0].offset = 0; +bounds[0].length = 10; +bounds[1].offset = 0; +bounds[1].length = 10; +bounds[2].offset = 0; +bounds[2].length = 10; + +for(x=0; x<1000; x++) input[x] = (BYTE)x; +data.insert(globalTags[LOCALTAG], input, 1000, 3); +data.setBounds(globalTags[LOCALTAG], bounds, 3); +data.getBounds(globalTags[LOCALTAG], obounds, 3); +for(x=0; x<3; x++) + { + if(bounds[x].offset!=obounds[x].offset) bresult = -1; + } +if(bresult!=0) fprintf(stdout, "* MISMATCH BETWEEN BOUNDS SPECIFIED AND BOUNDS READ\n"); + +data.get(globalTags[LOCALTAG], C); +data.get(globalTags[LOCALTAG], S); +data.get(globalTags[LOCALTAG], US); +data.get(globalTags[LOCALTAG], I); +data.get(globalTags[LOCALTAG], UI); +data.get(globalTags[LOCALTAG], L); +data.get(globalTags[LOCALTAG], UL); +data.get(globalTags[LOCALTAG], F); +data.get(globalTags[LOCALTAG], D); +data.get(globalTags[LOCALTAG], STR); + +for(x=0; x<1000; x++) + { + if(input[x]!=(BYTE)C[x] || input[x]!=(BYTE)S[x] || + input[x]!=(BYTE)US[x] || input[x]!=(BYTE)I[x] || + input[x]!=(BYTE)UI[x] || input[x]!=(BYTE)L[x] || + input[x]!=(BYTE)UL[x] || input[x]!=(BYTE)F[x] || + input[x]!=(BYTE)D[x] || input[x]!=(BYTE)atof(STR[x])) + { + result = -1; + } + delete STR[x]; + } + +if(result) fprintf(stdout, "* MISMATCH BETWEEN SPECIFIED DATA AND RETRIEVED DATA\n"); + +if(result || bresult) return -1; +return 0; +} + +int shortArrayTest ( cdevData & data ) +{ +int LOCALTAG = 11; +int result = 0, bresult = 0; +int x; +short input[1000]; +cdevBounds bounds[3]; +cdevBounds obounds[3]; + +BYTE C[1000]; +short S[1000]; +unsigned short US[1000]; +int I[1000]; +unsigned int UI[1000]; +long L[1000]; +unsigned long UL[1000]; +float F[1000]; +double D[1000]; +char * STR[1000]; + +bounds[0].offset = 0; +bounds[0].length = 5; +bounds[1].offset = 0; +bounds[1].length = 2; +bounds[2].offset = 0; +bounds[2].length = 100; + +for(x=0; x<1000; x++) input[x] = (short)x*2; +data.insert(globalTags[LOCALTAG], input, 1000, 3); +data.setBounds(globalTags[LOCALTAG], bounds, 3); +data.getBounds(globalTags[LOCALTAG], obounds, 3); +for(x=0; x<3; x++) + { + if(bounds[x].offset!=obounds[x].offset) bresult = -1; + } +if(bresult!=0) fprintf(stdout, "* MISMATCH BETWEEN BOUNDS SPECIFIED AND BOUNDS READ\n"); + +data.get(globalTags[LOCALTAG], C); +data.get(globalTags[LOCALTAG], S); +data.get(globalTags[LOCALTAG], US); +data.get(globalTags[LOCALTAG], I); +data.get(globalTags[LOCALTAG], UI); +data.get(globalTags[LOCALTAG], L); +data.get(globalTags[LOCALTAG], UL); +data.get(globalTags[LOCALTAG], F); +data.get(globalTags[LOCALTAG], D); +data.get(globalTags[LOCALTAG], STR); + +for(x=0; x<1000; x++) + { + if((BYTE)input[x]!=C[x] || input[x]!=(short)S[x] || + input[x]!=(short)US[x] || input[x]!=(short)I[x] || + input[x]!=(short)UI[x] || input[x]!=(short)L[x] || + input[x]!=(short)UL[x] || input[x]!=(short)F[x] || + input[x]!=(short)D[x] || input[x]!=(short)atof(STR[x])) + { + result = -1; + } + delete STR[x]; + } + +if(result) fprintf(stdout, "* MISMATCH BETWEEN SPECIFIED DATA AND RETRIEVED DATA\n"); + +if(result || bresult) return -1; +return 0; +} + +int ushortArrayTest ( cdevData & data ) +{ +int LOCALTAG = 12; +int result = 0, bresult = 0; +int x; +unsigned short input[1000]; +cdevBounds bounds[3]; +cdevBounds obounds[3]; + +BYTE C[1000]; +short S[1000]; +unsigned short US[1000]; +int I[1000]; +unsigned int UI[1000]; +long L[1000]; +unsigned long UL[1000]; +float F[1000]; +double D[1000]; +char * STR[1000]; + +bounds[0].offset = 0; +bounds[0].length = 5; +bounds[1].offset = 0; +bounds[1].length = 2; +bounds[2].offset = 0; +bounds[2].length = 100; + +for(x=0; x<1000; x++) input[x] = (unsigned short)x*3; +data.insert(globalTags[LOCALTAG], input, 1000, 3); +data.setBounds(globalTags[LOCALTAG], bounds, 3); +data.getBounds(globalTags[LOCALTAG], obounds, 3); +for(x=0; x<3; x++) + { + if(bounds[x].offset!=obounds[x].offset) bresult = -1; + } +if(bresult!=0) fprintf(stdout, "* MISMATCH BETWEEN BOUNDS SPECIFIED AND BOUNDS READ\n"); + +data.get(globalTags[LOCALTAG], C); +data.get(globalTags[LOCALTAG], S); +data.get(globalTags[LOCALTAG], US); +data.get(globalTags[LOCALTAG], I); +data.get(globalTags[LOCALTAG], UI); +data.get(globalTags[LOCALTAG], L); +data.get(globalTags[LOCALTAG], UL); +data.get(globalTags[LOCALTAG], F); +data.get(globalTags[LOCALTAG], D); +data.get(globalTags[LOCALTAG], STR); + +for(x=0; x<1000; x++) + { + if((BYTE)input[x]!=C[x] || (short)input[x]!=S[x] || + input[x]!=(unsigned short)US[x] || input[x]!=(unsigned short)I[x] || + input[x]!=(unsigned short)UI[x] || input[x]!=(unsigned short)L[x] || + input[x]!=(unsigned short)UL[x] || input[x]!=(unsigned short)F[x] || + input[x]!=(unsigned short)D[x] || input[x]!=(unsigned short)atof(STR[x])) + { + result = -1; + } + delete STR[x]; + } + +if(result) fprintf(stdout, "* MISMATCH BETWEEN SPECIFIED DATA AND RETRIEVED DATA\n"); + +if(result || bresult) return -1; +return 0; +} + +int intArrayTest ( cdevData & data ) +{ +int LOCALTAG = 13; +int result = 0, bresult = 0; +int x; +int input[1000]; +cdevBounds bounds[3]; +cdevBounds obounds[3]; + +BYTE C[1000]; +short S[1000]; +unsigned short US[1000]; +int I[1000]; +unsigned int UI[1000]; +long L[1000]; +unsigned long UL[1000]; +float F[1000]; +double D[1000]; +char * STR[1000]; + +bounds[0].offset = 0; +bounds[0].length = 5; +bounds[1].offset = 0; +bounds[1].length = 2; +bounds[2].offset = 0; +bounds[2].length = 100; + +for(x=0; x<1000; x++) input[x] = (int)x*4; +data.insert(globalTags[LOCALTAG], input, 1000, 3); +data.setBounds(globalTags[LOCALTAG], bounds, 3); +data.getBounds(globalTags[LOCALTAG], obounds, 3); +for(x=0; x<3; x++) + { + if(bounds[x].offset!=obounds[x].offset) bresult = -1; + } +if(bresult!=0) fprintf(stdout, "* MISMATCH BETWEEN BOUNDS SPECIFIED AND BOUNDS READ\n"); + +data.get(globalTags[LOCALTAG], C); +data.get(globalTags[LOCALTAG], S); +data.get(globalTags[LOCALTAG], US); +data.get(globalTags[LOCALTAG], I); +data.get(globalTags[LOCALTAG], UI); +data.get(globalTags[LOCALTAG], L); +data.get(globalTags[LOCALTAG], UL); +data.get(globalTags[LOCALTAG], F); +data.get(globalTags[LOCALTAG], D); +data.get(globalTags[LOCALTAG], STR); + +for(x=0; x<1000; x++) + { + if((BYTE)input[x]!=C[x] || (short)input[x]!=S[x] || + (unsigned short)input[x]!=US[x] || input[x]!=(int)I[x] || + input[x]!=(int)UI[x] || input[x]!=(int)L[x] || + input[x]!=(int)UL[x] || input[x]!=(int)F[x] || + input[x]!=(int)D[x] || input[x]!=(int)atof(STR[x])) + { + result = -1; + } + delete STR[x]; + } + +if(result) fprintf(stdout, "* MISMATCH BETWEEN SPECIFIED DATA AND RETRIEVED DATA\n"); + +if(result || bresult) return -1; +return 0; +} + +int uintArrayTest ( cdevData & data ) +{ +int LOCALTAG = 14; +int result = 0, bresult = 0; +int x; +unsigned int input[1000]; +cdevBounds bounds[3]; +cdevBounds obounds[3]; + +BYTE C[1000]; +short S[1000]; +unsigned short US[1000]; +int I[1000]; +unsigned int UI[1000]; +long L[1000]; +unsigned long UL[1000]; +float F[1000]; +double D[1000]; +char * STR[1000]; + +bounds[0].offset = 0; +bounds[0].length = 5; +bounds[1].offset = 0; +bounds[1].length = 2; +bounds[2].offset = 0; +bounds[2].length = 100; + +for(x=0; x<1000; x++) input[x] = (unsigned int)x*5; +data.insert(globalTags[LOCALTAG], input, 1000, 3); +data.setBounds(globalTags[LOCALTAG], bounds, 3); +data.getBounds(globalTags[LOCALTAG], obounds, 3); +for(x=0; x<3; x++) + { + if(bounds[x].offset!=obounds[x].offset) bresult = -1; + } +if(bresult!=0) fprintf(stdout, "* MISMATCH BETWEEN BOUNDS SPECIFIED AND BOUNDS READ\n"); + +data.get(globalTags[LOCALTAG], C); +data.get(globalTags[LOCALTAG], S); +data.get(globalTags[LOCALTAG], US); +data.get(globalTags[LOCALTAG], I); +data.get(globalTags[LOCALTAG], UI); +data.get(globalTags[LOCALTAG], L); +data.get(globalTags[LOCALTAG], UL); +data.get(globalTags[LOCALTAG], F); +data.get(globalTags[LOCALTAG], D); +data.get(globalTags[LOCALTAG], STR); + +for(x=0; x<1000; x++) + { + if((BYTE)input[x]!=C[x] || (short)input[x]!=S[x] || + (unsigned short)input[x]!=US[x] || (int)input[x]!=I[x] || + input[x]!=(unsigned int)UI[x] || input[x]!=(unsigned int)L[x] || + input[x]!=(unsigned int)UL[x] || input[x]!=(unsigned int)F[x] || + input[x]!=(unsigned int)D[x] || input[x]!=(unsigned int)atof(STR[x])) + { + result = -1; + } + delete STR[x]; + } + +if(result) fprintf(stdout, "* MISMATCH BETWEEN SPECIFIED DATA AND RETRIEVED DATA\n"); + +if(result || bresult) return -1; +return 0; +} + + +int longArrayTest ( cdevData & data ) +{ +int LOCALTAG = 15; +int result = 0, bresult = 0; +int x; +long input[1000]; +cdevBounds bounds[3]; +cdevBounds obounds[3]; + +BYTE C[1000]; +short S[1000]; +unsigned short US[1000]; +int I[1000]; +unsigned int UI[1000]; +long L[1000]; +unsigned long UL[1000]; +float F[1000]; +double D[1000]; +char * STR[1000]; + +bounds[0].offset = 0; +bounds[0].length = 5; +bounds[1].offset = 0; +bounds[1].length = 2; +bounds[2].offset = 0; +bounds[2].length = 100; + +for(x=0; x<1000; x++) input[x] = (long)x*6; +data.insert(globalTags[LOCALTAG], input, 1000, 3); +data.setBounds(globalTags[LOCALTAG], bounds, 3); +data.getBounds(globalTags[LOCALTAG], obounds, 3); +for(x=0; x<3; x++) + { + if(bounds[x].offset!=obounds[x].offset) bresult = -1; + } +if(bresult!=0) fprintf(stdout, "* MISMATCH BETWEEN BOUNDS SPECIFIED AND BOUNDS READ\n"); + +data.get(globalTags[LOCALTAG], C); +data.get(globalTags[LOCALTAG], S); +data.get(globalTags[LOCALTAG], US); +data.get(globalTags[LOCALTAG], I); +data.get(globalTags[LOCALTAG], UI); +data.get(globalTags[LOCALTAG], L); +data.get(globalTags[LOCALTAG], UL); +data.get(globalTags[LOCALTAG], F); +data.get(globalTags[LOCALTAG], D); +data.get(globalTags[LOCALTAG], STR); + +for(x=0; x<1000; x++) + { + if((BYTE)input[x]!=C[x] || (short)input[x]!=S[x] || + (unsigned short)input[x]!=US[x] || (int)input[x]!=I[x] || + (unsigned int)input[x]!=UI[x] || input[x]!=(long)L[x] || + input[x]!=(long)UL[x] || input[x]!=(long)F[x] || + input[x]!=(long)D[x] || input[x]!=(long)atof(STR[x])) + { + result = -1; + } + delete STR[x]; + } + +if(result) fprintf(stdout, "* MISMATCH BETWEEN SPECIFIED DATA AND RETRIEVED DATA\n"); + +if(result || bresult) return -1; +return 0; +} + +int ulongArrayTest ( cdevData & data ) +{ +int LOCALTAG = 16; +int result = 0, bresult = 0; +int x; +unsigned long input[1000]; +cdevBounds bounds[3]; +cdevBounds obounds[3]; + +BYTE C[1000]; +short S[1000]; +unsigned short US[1000]; +int I[1000]; +unsigned int UI[1000]; +long L[1000]; +unsigned long UL[1000]; +float F[1000]; +double D[1000]; +char * STR[1000]; + +bounds[0].offset = 0; +bounds[0].length = 5; +bounds[1].offset = 0; +bounds[1].length = 2; +bounds[2].offset = 0; +bounds[2].length = 100; + +for(x=0; x<1000; x++) input[x] = (unsigned long)x*7; +data.insert(globalTags[LOCALTAG], input, 1000, 3); +data.setBounds(globalTags[LOCALTAG], bounds, 3); +data.getBounds(globalTags[LOCALTAG], obounds, 3); +for(x=0; x<3; x++) + { + if(bounds[x].offset!=obounds[x].offset) bresult = -1; + } +if(bresult!=0) fprintf(stdout, "* MISMATCH BETWEEN BOUNDS SPECIFIED AND BOUNDS READ\n"); + +data.get(globalTags[LOCALTAG], C); +data.get(globalTags[LOCALTAG], S); +data.get(globalTags[LOCALTAG], US); +data.get(globalTags[LOCALTAG], I); +data.get(globalTags[LOCALTAG], UI); +data.get(globalTags[LOCALTAG], L); +data.get(globalTags[LOCALTAG], UL); +data.get(globalTags[LOCALTAG], F); +data.get(globalTags[LOCALTAG], D); +data.get(globalTags[LOCALTAG], STR); + +for(x=0; x<1000; x++) + { + if((BYTE)input[x]!=C[x] || (short)input[x]!=S[x] || + (unsigned short)input[x]!=US[x] || (int)input[x]!=I[x] || + (unsigned int)input[x]!=UI[x] || (long)input[x]!=L[x] || + input[x]!=(unsigned long)UL[x] || input[x]!=(unsigned long)F[x] || + input[x]!=(unsigned long)D[x] || input[x]!=(unsigned long)atof(STR[x])) + { + result = -1; + } + delete STR[x]; + } + +if(result) fprintf(stdout, "* MISMATCH BETWEEN SPECIFIED DATA AND RETRIEVED DATA\n"); + +if(result || bresult) return -1; +return 0; +} + +int floatArrayTest ( cdevData & data ) +{ +int LOCALTAG = 17; +int result = 0, bresult = 0; +int x; +float input[1000]; +cdevBounds bounds[3]; +cdevBounds obounds[3]; + +BYTE C[1000]; +short S[1000]; +unsigned short US[1000]; +int I[1000]; +unsigned int UI[1000]; +long L[1000]; +unsigned long UL[1000]; +float F[1000]; +double D[1000]; +char * STR[1000]; + +bounds[0].offset = 0; +bounds[0].length = 5; +bounds[1].offset = 0; +bounds[1].length = 2; +bounds[2].offset = 0; +bounds[2].length = 100; + +for(x=0; x<1000; x++) input[x] = (float)2.1 * x; +data.insert(globalTags[LOCALTAG], input, 1000, 3); +data.setBounds(globalTags[LOCALTAG], bounds, 3); +data.getBounds(globalTags[LOCALTAG], obounds, 3); +for(x=0; x<3; x++) + { + if(bounds[x].offset!=obounds[x].offset) bresult = -1; + } +if(bresult!=0) fprintf(stdout, "* MISMATCH BETWEEN BOUNDS SPECIFIED AND BOUNDS READ\n"); + +data.get(globalTags[LOCALTAG], C); +data.get(globalTags[LOCALTAG], S); +data.get(globalTags[LOCALTAG], US); +data.get(globalTags[LOCALTAG], I); +data.get(globalTags[LOCALTAG], UI); +data.get(globalTags[LOCALTAG], L); +data.get(globalTags[LOCALTAG], UL); +data.get(globalTags[LOCALTAG], F); +data.get(globalTags[LOCALTAG], D); +data.get(globalTags[LOCALTAG], STR); + +for(x=0; x<1000; x++) + { + if((BYTE)input[x]!=C[x] || (short)input[x]!=S[x] || + (unsigned short)input[x]!=US[x] || (int)input[x]!=I[x] || + (unsigned int)input[x]!=UI[x] || (long)input[x]!=L[x] || + (unsigned long)input[x]!=UL[x] || input[x]!=(float)F[x] || + input[x]!=(float)D[x] || !equal(input[x], (float)atof(STR[x]))) + { + result = -1; + } + delete STR[x]; + } + +if(result) fprintf(stdout, "* MISMATCH BETWEEN SPECIFIED DATA AND RETRIEVED DATA\n"); + +if(result || bresult) return -1; +return 0; +} + +int doubleArrayTest ( cdevData & data ) +{ +int LOCALTAG = 18; +int result = 0, bresult = 0; +int x; +double input[1000]; +cdevBounds bounds[3]; +cdevBounds obounds[3]; + +BYTE C[1000]; +short S[1000]; +unsigned short US[1000]; +int I[1000]; +unsigned int UI[1000]; +long L[1000]; +unsigned long UL[1000]; +float F[1000]; +double D[1000]; +char * STR[1000]; + +bounds[0].offset = 0; +bounds[0].length = 5; +bounds[1].offset = 0; +bounds[1].length = 2; +bounds[2].offset = 0; +bounds[2].length = 100; + +for(x=0; x<1000; x++) input[x] = (double)5.1111112*x; +data.insert(globalTags[LOCALTAG], input, 1000, 3); +data.setBounds(globalTags[LOCALTAG], bounds, 3); +data.getBounds(globalTags[LOCALTAG], obounds, 3); +for(x=0; x<3; x++) + { + if(bounds[x].offset!=obounds[x].offset) bresult = -1; + } +if(bresult!=0) fprintf(stdout, "* MISMATCH BETWEEN BOUNDS SPECIFIED AND BOUNDS READ\n"); + +data.get(globalTags[LOCALTAG], C); +data.get(globalTags[LOCALTAG], S); +data.get(globalTags[LOCALTAG], US); +data.get(globalTags[LOCALTAG], I); +data.get(globalTags[LOCALTAG], UI); +data.get(globalTags[LOCALTAG], L); +data.get(globalTags[LOCALTAG], UL); +data.get(globalTags[LOCALTAG], F); +data.get(globalTags[LOCALTAG], D); +data.get(globalTags[LOCALTAG], STR); + +for(x=0; x<1000 && !result; x++) + { + if((BYTE)input[x]!=C[x] || + (short)input[x]!=S[x] || + (unsigned short)input[x]!=US[x] || + (int)input[x]!=I[x] || + (unsigned int)input[x]!=UI[x] || + (long)input[x]!=L[x] || + (unsigned long)input[x]!=UL[x] || + !equal((float)input[x],F[x]) || + !equal(input[x],(double)D[x]) || + !equal(input[x],(double)atof(STR[x]))) + { + if((BYTE)input[x]!=C[x]) fprintf(stdout, "* Byte %c != %c\n", (BYTE)input[x], C[x]); + if((short)input[x]!=S[x]) fprintf(stdout, "* Short %i != %i\n", (short)input[x], S[x]); + if((unsigned short)input[x]!=US[x]) fprintf(stdout, "* Unsigned short %i != %i\n", (unsigned short)input[x], US[x]); + if((int)input[x]!=I[x]) fprintf(stdout, "* Int %i != %i\n", (int)input[x], I[x]); + if((unsigned int)input[x]!=UI[x]) fprintf(stdout, "* Unsigned int %i != %i\n", (unsigned int)input[x], UI[x]); + if((long)input[x]!=L[x]) fprintf(stdout, "* Long %i != %i\n", (long)input[x], L[x]); + if((unsigned long)input[x]!=UL[x]) fprintf(stdout, "* Unsigned long %i != %i\n", (unsigned long)input[x], UL[x]); + if(!equal((float)input[x],(double)F[x])) fprintf(stdout, "* Float %f != %f\n", (float)input[x], F[x]); + if(!equal(input[x],D[x])) fprintf(stdout, "* Double %f != %f\n", input[x], D[x]); + if(!equal(input[x],atof(STR[x]))) fprintf(stdout, "* String %f != %f\n", input[x], atof(STR[x])); + result = -1; + } + delete STR[x]; + } + +if(result) fprintf(stdout, "* MISMATCH BETWEEN SPECIFIED DATA AND RETRIEVED DATA\n"); + +if(result || bresult) return -1; +return 0; +} + +int stringArrayTest ( cdevData & data ) +{ +int LOCALTAG = 19; +int result = 0, bresult = 0; +int x; +char * input[1000]; +cdevBounds bounds[3]; +cdevBounds obounds[3]; + +BYTE C[1000]; +short S[1000]; +unsigned short US[1000]; +int I[1000]; +unsigned int UI[1000]; +long L[1000]; +unsigned long UL[1000]; +float F[1000]; +double D[1000]; +char * STR[1000]; + +bounds[0].offset = 0; +bounds[0].length = 5; +bounds[1].offset = 0; +bounds[1].length = 2; +bounds[2].offset = 0; +bounds[2].length = 100; + +for(x=0; x<1000; x++) + { + input[x] = new char[32]; + sprintf(input[x], "%i.%i", x, x); + } + +data.insert(globalTags[LOCALTAG], input, 1000, 3); +data.setBounds(globalTags[LOCALTAG], bounds, 3); +data.getBounds(globalTags[LOCALTAG], obounds, 3); +for(x=0; x<3; x++) + { + if(bounds[x].offset!=obounds[x].offset) bresult = -1; + } +if(bresult!=0) fprintf(stdout, "* MISMATCH BETWEEN BOUNDS SPECIFIED AND BOUNDS READ\n"); + +data.get(globalTags[LOCALTAG], C); +data.get(globalTags[LOCALTAG], S); +data.get(globalTags[LOCALTAG], US); +data.get(globalTags[LOCALTAG], I); +data.get(globalTags[LOCALTAG], UI); +data.get(globalTags[LOCALTAG], L); +data.get(globalTags[LOCALTAG], UL); +data.get(globalTags[LOCALTAG], F); +data.get(globalTags[LOCALTAG], D); +data.get(globalTags[LOCALTAG], STR); + +for(x=0; x<1000; x++) + { + if((BYTE)atof(input[x])!=C[x] || + (short)atof(input[x])!=S[x] || + (unsigned short)atof(input[x])!=US[x] || + (int)atof(input[x])!=I[x] || + (unsigned int)atof(input[x])!=UI[x] || + (long)atof(input[x])!=L[x] || + (unsigned long)atof(input[x])!=UL[x] || + !equal(atof(input[x]),(double)F[x]) || + !equal(atof(input[x]),D[x]) || + strcmp(input[x],STR[x])) + { + result = -1; + } + delete STR[x]; + delete input[x]; + } + +if(result) fprintf(stdout, "* MISMATCH BETWEEN SPECIFIED DATA AND RETRIEVED DATA\n"); + +if(result || bresult) return -1; +return 0; +} + + +int asciiDumpTest ( cdevData & data ) +{ +data.asciiDump(stdout); +return 0; +} + +int copyTest ( cdevData & data ) +{ +int result = 0; +cdevData data2(data); +char Val1[64], Val2[64]; +char * val1[1000], * val2[1000]; +int i, x; +size_t dim1, dim2; + + +for(i=0; i<10; i++) + { + data.getDim(globalTags[i], &dim1); + data2.getDim(globalTags[i], &dim2); + + if(dim1!=dim2) + { + fprintf(stdout, "* MISMATCH BETWEEN DIMENSION SIZES ON %s\n", globalTagNames[i]); + result = -1; + } + else if(data.getType(globalTags[i]) != + data2.getType(globalTags[i])) + { + fprintf(stdout, "* MISMATCH BETWEEN DATA TYPES SIZES ON %s\n", globalTagNames[i]); + result = -1; + } + data.get(globalTags[i], Val1, 64); + data2.get(globalTags[i], Val2, 64); + if(strcmp(Val1, Val2)) + { + result = -1; + } + } + +for(i=10; i<20; i++) + { + memset(val1, 0, 1000*sizeof(char *)); + memset(val2, 0, 1000*sizeof(char *)); + + if(!data.get(globalTags[i], val1) && + !data2.get(globalTags[i], val2)) + { + data.getDim(globalTags[i], &dim1); + data2.getDim(globalTags[i], &dim2); + + if(dim1!=dim2) + { + fprintf(stdout, "* MISMATCH BETWEEN DIMENSION SIZES ON %s\n", globalTagNames[i]); + result = -1; + } + else if(data.getType(globalTags[i]) != + data2.getType(globalTags[i])) + { + fprintf(stdout, "* MISMATCH BETWEEN DATA TYPES SIZES ON %s\n", globalTagNames[i]); + result = -1; + } + else if(dim1) + { + cdevBounds * bounds1 = new cdevBounds[dim1]; + cdevBounds * bounds2 = new cdevBounds[dim2]; + data.getBounds(globalTags[i], bounds1, dim1); + data2.getBounds(globalTags[i], bounds2, dim2); + for(x=0; x<(int)dim1; x++) + { + if(bounds1[x].offset != bounds2[x].offset || + bounds1[x].length != bounds2[x].length) + { + result = -1; + fprintf(stdout, "* MISMATCH BETWEEN BOUNDS SIZES ON %s\n", globalTagNames[i]); + } + } + delete bounds1; + delete bounds2; + } + + for(x=0; x<1000; x++) + { + if(strcmp(val1[x], val2[x])) + { + fprintf(stdout, "* VALUE MISMATCH ON %s\n", globalTagNames[i]); + result = -1; + } + delete val1[x]; + delete val2[x]; + } + } + else + { + fprintf(stdout, "* FAILURE TO READ DATA ON %s\n", globalTagNames[i]); + for(x=0; x<1000; x++) + { + if(val1[x]!=NULL) delete val1[x]; + if(val2[x]!=NULL) delete val2[x]; + } + result = -1; + } + } +return result; +} + + + +int removeTest (cdevData & data ) +{ +int result = 0; +int removedCnt = 0; +int goneCnt = 0; +int i; + +for(i=0; i<20; i+=3) + { + data.remove(globalTags[i]); + removedCnt++; + } + +for(i=0; i<20; i++) + { + if(data.getType(globalTags[i])==CDEV_INVALID) goneCnt++; + } + +if(goneCnt!=removedCnt) return -1; + +for(i=0; i<20; i+=3) + { + if(data.getType(globalTags[i])!=CDEV_INVALID) return -1; + } +return 0; +} + + +int findTest ( cdevData & data ) +{ +int result = 0; +int x; + +// Test finding scalar value first +BYTE c1, * c2; +data.get (globalTags[0], &c1); +data.find(globalTags[0], (void * &)c2); +if(c1 != *c2) result = -1; + +// Test finding an array of values next +int i1[1000], *i2; +data.get(globalTags[13], i1); +data.find(globalTags[13], (void * &)i2); +for(x=0; x<1000; x++) + { + if(i1[x]!=i2[x]) result = -1; + } + +// Test finding a single character string next +char s1[100], *s2; +data.get(globalTags[9], s1, 100); +data.find(globalTags[9], (void * &)s2); +if(strcmp(s1, s2)) result = -1; + +// Test finding an array of character strings +char *S1[1000], ** S2; +data.get(globalTags[19], S1); +data.find(globalTags[19], (void * &)S2); +for(x=0; x<1000; x++) + { + if(strcmp(S1[x], S2[x])) result = -1; + delete S1[x]; + } +return result; +} + + +int xdrTest ( cdevData & data ) +{ +int result = 0; +char * buf; +size_t bufLen; +cdevData data2; + +data.xdrExport(&buf, &bufLen); +data2.xdrImport(buf, bufLen); + +char Val1[64], Val2[64]; +char * val1[1000], * val2[1000]; +int i, x; +size_t dim1, dim2; + + +for(i=0; i<10; i++) + { + data.getDim(globalTags[i], &dim1); + data2.getDim(globalTags[i], &dim2); + + if(dim1!=dim2) + { + fprintf(stdout, "* MISMATCH BETWEEN DIMENSION SIZES ON %s\n", globalTagNames[i]); + result = -1; + } + else if(data.getType(globalTags[i]) != + data2.getType(globalTags[i])) + { + fprintf(stdout, "* MISMATCH BETWEEN DATA TYPES SIZES ON %s\n", globalTagNames[i]); + result = -1; + } + data.get(globalTags[i], Val1, 64); + data2.get(globalTags[i], Val2, 64); + if(strcmp(Val1, Val2)) + { + result = -1; + } + } + +for(i=10; i<20; i++) + { + memset(val1, 0, 1000*sizeof(char *)); + memset(val2, 0, 1000*sizeof(char *)); + + if(!data.get(globalTags[i], val1) && + !data2.get(globalTags[i], val2)) + { + data.getDim(globalTags[i], &dim1); + data2.getDim(globalTags[i], &dim2); + + if(dim1!=dim2) + { + fprintf(stdout, "* MISMATCH BETWEEN DIMENSION SIZES ON %s\n", globalTagNames[i]); + result = -1; + } + else if(data.getType(globalTags[i]) != + data2.getType(globalTags[i])) + { + fprintf(stdout, "* MISMATCH BETWEEN DATA TYPES SIZES ON %s\n", globalTagNames[i]); + result = -1; + } + else if(dim1) + { + cdevBounds * bounds1 = new cdevBounds[dim1]; + cdevBounds * bounds2 = new cdevBounds[dim2]; + data.getBounds(globalTags[i], bounds1, dim1); + data2.getBounds(globalTags[i], bounds2, dim2); + for(x=0; x<(int)dim1; x++) + { + if(bounds1[x].offset != bounds2[x].offset || + bounds1[x].length != bounds2[x].length) + { + result = -1; + fprintf(stdout, "* MISMATCH BETWEEN BOUNDS SIZES ON %s\n", globalTagNames[i]); + } + } + delete bounds1; + delete bounds2; + } + + for(x=0; x<1000; x++) + { + if(strcmp(val1[x], val2[x])) + { + fprintf(stdout, "* VALUE MISMATCH ON %s\n", globalTagNames[i]); + result = -1; + } + delete val1[x]; + delete val2[x]; + } + } + else + { + fprintf(stdout, "* FAILURE TO READ DATA ON %s\n", globalTagNames[i]); + for(x=0; x<1000; x++) + { + if(val1[x]!=NULL) delete val1[x]; + if(val2[x]!=NULL) delete val2[x]; + } + result = -1; + } + } +return result; +} + + +int assignmentTest ( cdevData & data ) +{ +int result = 0; +cdevData data2; +char Val1[64], Val2[64]; +char * val1[1000], * val2[1000]; +int i, x; +size_t dim1, dim2; + +data2 = data; + +for(i=0; i<10; i++) + { + data.getDim(globalTags[i], &dim1); + data2.getDim(globalTags[i], &dim2); + + if(dim1!=dim2) + { + fprintf(stdout, "* MISMATCH BETWEEN DIMENSION SIZES ON %s\n", globalTagNames[i]); + result = -1; + } + else if(data.getType(globalTags[i]) != + data2.getType(globalTags[i])) + { + fprintf(stdout, "* MISMATCH BETWEEN DATA TYPES SIZES ON %s\n", globalTagNames[i]); + result = -1; + } + data.get(globalTags[i], Val1, 64); + data2.get(globalTags[i], Val2, 64); + if(strcmp(Val1, Val2)) + { + result = -1; + } + } + +for(i=10; i<20; i++) + { + memset(val1, 0, 1000*sizeof(char *)); + memset(val2, 0, 1000*sizeof(char *)); + + if(!data.get(globalTags[i], val1) && + !data2.get(globalTags[i], val2)) + { + data.getDim(globalTags[i], &dim1); + data2.getDim(globalTags[i], &dim2); + + if(dim1!=dim2) + { + fprintf(stdout, "* MISMATCH BETWEEN DIMENSION SIZES ON %s\n", globalTagNames[i]); + result = -1; + } + else if(data.getType(globalTags[i]) != + data2.getType(globalTags[i])) + { + fprintf(stdout, "* MISMATCH BETWEEN DATA TYPES SIZES ON %s\n", globalTagNames[i]); + result = -1; + } + else if(dim1) + { + cdevBounds * bounds1 = new cdevBounds[dim1]; + cdevBounds * bounds2 = new cdevBounds[dim2]; + data.getBounds(globalTags[i], bounds1, dim1); + data2.getBounds(globalTags[i], bounds2, dim2); + for(x=0; x<(int)dim1; x++) + { + if(bounds1[x].offset != bounds2[x].offset || + bounds1[x].length != bounds2[x].length) + { + result = -1; + fprintf(stdout, "* MISMATCH BETWEEN BOUNDS SIZES ON %s\n", globalTagNames[i]); + } + } + delete bounds1; + delete bounds2; + } + + for(x=0; x<1000; x++) + { + if(strcmp(val1[x], val2[x])) + { + fprintf(stdout, "* VALUE MISMATCH ON %s\n", globalTagNames[i]); + result = -1; + } + delete val1[x]; + delete val2[x]; + } + } + else + { + fprintf(stdout, "* FAILURE TO READ DATA ON %s\n", globalTagNames[i]); + for(x=0; x<1000; x++) + { + if(val1[x]!=NULL) delete val1[x]; + if(val2[x]!=NULL) delete val2[x]; + } + result = -1; + } + } +return result; +} diff --git a/test/cdevDataTest2.cc b/test/cdevDataTest2.cc new file mode 100755 index 0000000..5a7c432 --- /dev/null +++ b/test/cdevDataTest2.cc @@ -0,0 +1,24 @@ +#include +#include "equal.h" + +char * str[3] = + { + "This is the first string", + "This is the seconds string", + "This is the third string" + }; + +void main () +{ +char * binary; +size_t binaryLen; + +cdevData data, data2; +data.insert("value", str, 1); +data.insert("status", str[0]); +data.insert("severity", str[1]); +data.asciiDump(); +data.xdrExport(&binary, &binaryLen); +data2.xdrImport(binary, binaryLen); +data2.asciiDump(); +} diff --git a/test/cdevDataTestSimple.cc b/test/cdevDataTestSimple.cc new file mode 100644 index 0000000..fbc7052 --- /dev/null +++ b/test/cdevDataTestSimple.cc @@ -0,0 +1,28 @@ +#include "cdevData.h" + +char* str = "10.11"; + +main (int argc, char** argv) +{ + cdevData in; + cdevData out; + char temp[80]; + int ia; + + int barray[10]; + char *retstr[10]; + + for (int i = 0; i < 1000; i++) + barray[i] = i; + + if (in.insert ("status", barray, 1000) != CDEV_SUCCESS) + printf ("insert byte array error\n"); + + if (in.get ("status", retstr) != CDEV_SUCCESS) + printf ("convert byte array to string array error\n"); + + for (i = 0; i < 10; i++) { + printf ("retstr[%d] is %s\n", i, retstr[i]); + delete retstr[i]; + } +} diff --git a/test/cdevDirectory/Gillies.cc b/test/cdevDirectory/Gillies.cc new file mode 100755 index 0000000..020a61e --- /dev/null +++ b/test/cdevDirectory/Gillies.cc @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +int main() +{ + cdevDevice *dir = cdevDevice::attachPtr("cdevDirectory"); + cdevData input, output; + + cdevData::insertTag(0x1001, "PV"); + + // *********************************************************** + // * Insert the name of the device and message to be resolved. + // *********************************************************** + input.insert("device", "diag1"); + input.insert("message", "get value"); + + // *********************************************************** + // * Submit the request to the cdevDirectory object using the + // * send command, and output the result (using asciiDump) if + // * successful. + // *********************************************************** + if(dir->send("serviceData", input, output)==CDEV_SUCCESS) + { + output.asciiDump(stdout); + } else { + fprintf(stderr, "Send Failed\n"); + } +} + diff --git a/test/cdevDirectory/Gillies.ddl b/test/cdevDirectory/Gillies.ddl new file mode 100755 index 0000000..f147dd7 --- /dev/null +++ b/test/cdevDirectory/Gillies.ddl @@ -0,0 +1,16 @@ +service ca { + tags { PV } +} + +/* All items share these verbs and attributes */ +class Basic { + verbs { get, set, monitorOn, monitorOff } + + attributes { + value ca {PV=<>.VAL}; + } +} + +Basic : + diag1 { t10a:sad:test } +; diff --git a/test/cdevDirectory/Makefile b/test/cdevDirectory/Makefile new file mode 100755 index 0000000..461acf3 --- /dev/null +++ b/test/cdevDirectory/Makefile @@ -0,0 +1,60 @@ +######################################################################## +# Makefile for shared object +######################################################################## +CDEVROOT = $(CDEV) +include $(CDEVROOT)/examples/Makefile.common + +CXXEXTRA = $(CLASS_INCLUDES) $(EPICSINCLUDES) + +LIBS = -L$(CDEVLIB) -lcdev -lEpicsCa \ + -L$(EPICSLIB) -lca -lDb -lCom -lm -ly -ll + +TARGETS = ascii2Bin bin2Ascii cdevDirectoryTest Gillies + +targets: $(TARGETS) + +ascii2Bin : ascii2Bin.o + @rm -f $@ + @echo "=> $(CXX) -o $@ $<" + @$(PROOF) $(CXX) $(CXXFLAGS) $(CXXEXTRA) $< $(CDEVLIB)/libcdev.a $(LIBS) -o $@ + @rm -rf ptrepository + +bin2Ascii : bin2Ascii.o + @rm -f $@ + @echo "=> $(CXX) -o $@ $<" + @$(PROOF) $(CXX) $(CXXFLAGS) $(CXXEXTRA) $< $(CDEVLIB)/libcdev.a $(LIBS) -o $@ + @rm -rf ptrepository + +cdevDirectoryTest : cdevDirectoryTest.o + @rm -f $@ + @echo "=> $(CXX) -o $@ $<" + @$(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -L$(CDEVLIB) -lcdev -lm -ll -ly -o $@ + @rm -rf ptrepository + +Gillies : Gillies.o + @rm -f $@ + @echo "=> $(CXX) -o $@ $<" + @$(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -L$(CDEVLIB) -lcdev -lm -ll -ly -o $@ + @rm -rf ptrepository + +SpaceTest : SpaceTest.o + @rm -f $@ + @echo "=> $(CXX) -o $@ $<" + @$(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -L$(CDEVLIB) -lcdev -lm -ll -ly -o $@ + @rm -rf ptrepository + +implementTest : implementTest.o + @rm -f $@ + @echo "=> $(CXX) -o $@ $<" + @$(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -L$(CDEVLIB) -lcdev -lm -ll -ly -o $@ + @rm -rf ptrepository + +queryTest : queryTest.o + @rm -f $@ + @echo "=> $(CXX) -o $@ $<" + @$(CXX) $(CXXFLAGS) $(CXXEXTRA) $^ -L$(CDEVLIB) -lcdev -lm -ll -ly -o $@ + @rm -rf ptrepository + +clean: + @rm -rf $(TARGETS) *.o *.a *~ core ptrepository + diff --git a/test/cdevDirectory/NMakefile.mak b/test/cdevDirectory/NMakefile.mak new file mode 100755 index 0000000..e34824b --- /dev/null +++ b/test/cdevDirectory/NMakefile.mak @@ -0,0 +1,29 @@ +.SUFFIXES: .cc .objbj + +ARCH = WINNT-4.0 +SHOBJ = YES +APPNAME = CDEV Test Applications +TARGETS = ascii2Bin.exe bin2Ascii.exe cdevDirectoryTest.exe + +include ..\..\include\makeinclude\Makefile.WINNT-4.0 + +targets: $(TARGETS) + +$(CDEVBIN): + @mkdir -p $@ + +ascii2Bin.exe: .exec\$(TARGETDIR)\ascii2Bin.obj + @$(LINK) \ + $(CDEVLIB)\cdev.lib $(LINK_EXE_FLAGS) /out:$@ \ + .exec\$(TARGETDIR)\ascii2Bin.obj + +bin2Ascii.exe: .exec\$(TARGETDIR)\bin2Ascii.obj + @$(LINK) \ + $(CDEVLIB)\cdev.lib $(LINK_EXE_FLAGS) /out:$@ \ + .exec\$(TARGETDIR)\bin2Ascii.obj + +cdevDirectoryTest.exe: .exec\$(TARGETDIR)\cdevDirectoryTest.obj + @$(LINK) \ + $(CDEVLIB)\cdev.lib $(LINK_EXE_FLAGS) /out:$@ \ + .exec\$(TARGETDIR)\cdevDirectoryTest.obj + diff --git a/test/cdevDirectory/ascii2Bin.cc b/test/cdevDirectory/ascii2Bin.cc new file mode 100755 index 0000000..a6cf612 --- /dev/null +++ b/test/cdevDirectory/ascii2Bin.cc @@ -0,0 +1,30 @@ +#include + +int main ( int argc, char ** argv ) + { + int result = 0; + char * inputFile = NULL; + char * outputFile = NULL; + + for(int i=1; i Bad or missing arguments\n => Format is: ascii2Bin inputFile -o outputFile\n"); + result = -1; + } + else { + cdevDirectoryTable table; + + fprintf(stdout, "\nascii2Bin: Compiling %s to %s\n", inputFile, outputFile); + fflush (stdout); + + if(table.load (inputFile)==CDEV_SUCCESS) table.binaryDump(outputFile); + } + + return result; + } diff --git a/test/cdevDirectory/bin2Ascii.cc b/test/cdevDirectory/bin2Ascii.cc new file mode 100755 index 0000000..625caed --- /dev/null +++ b/test/cdevDirectory/bin2Ascii.cc @@ -0,0 +1,35 @@ +#include + +int main ( int argc, char ** argv ) + { + int result = 0; + char * inputFile = NULL; + char * outputFile = NULL; + + for(int i=1; i Bad or missing arguments\n => Format is: bin2Ascii inputFile -o outputFile\n"); + result = -1; + } + else { + cdevDirectoryTable table; + FILE * fp; + + fprintf(stdout, "bin2Ascii: Converting %s to %s\n", inputFile, outputFile); + fflush (stdout); + + if(table.load (inputFile)==CDEV_SUCCESS && (fp=fopen(outputFile, "w"))!=NULL) + { + table.asciiDump(fp); + fclose(fp); + } + } + + return result; + } diff --git a/test/cdevDirectory/cdevDirectoryTest.cc b/test/cdevDirectory/cdevDirectoryTest.cc new file mode 100755 index 0000000..da3913f --- /dev/null +++ b/test/cdevDirectory/cdevDirectoryTest.cc @@ -0,0 +1,205 @@ +#include +#include + +int getDirectoryDevices ( char ** & devices, size_t & nDevices ); +int getDeviceClass ( char * device, char *& className ); +void reportOnDevice ( char * device ); + +int main() + { + char ** devices; + size_t nDevices; + + cdevData::insertTag(9810, "RDONLY"); + cdevData::insertTag(9811, "PV"); + cdevData::insertTag(9812, "server"); + + if(getDirectoryDevices(devices, nDevices)==CDEV_SUCCESS) + { + fprintf(stdout, " CDEV Devices in DDL \n"); + fprintf(stdout, "=============================\n"); + for(int i=0; i.VAL}; + attrib1 ca {PV = <>.VAL}; + attrib2 ca {PV = <>.VAL}; + attrib3 ca {PV = <>.VAL}; + attrib4 ca {PV = <>.VAL}; + attrib5 ca {PV = <>.VAL}; + attrib6 ca {PV = <>.VAL}; + attrib7 ca {PV = <>.VAL}; + attrib8 ca {PV = <>.VAL}; + attrib9 ca {PV = <>.VAL}; + } +} + +class Samples + { + verbs {get, set, monitorOn, monitorOff} + attributes + { + default Sample; + servers Sample; + attrib0 Sample; + attrib1 Sample; + attrib2 Sample; + attrib3 Sample; + attrib4 Sample; + attrib5 Sample; + attrib6 Sample; + attrib7 Sample; + attrib8 Sample; + attrib9 Sample; + } + messages + { + disconnect Sample; + } + } + + +BPM : + IPM1S01, IPM1S02, IPM1S03, IPM1S05, IPM1S07, + IPM1S08, IPM1S09 +; + +Samples : + device0, device1, device2, device3, device4, + device5, device6, device7, device8, device9 +; + +collection new1 : + IPM1S01, IPM1S02, IPM1S03, IPM1S05, IPM1S07, + IPM1S08, IPM1S09, + device0, device1, device2, device3, device4, + device5, device6, device7, device8, device9 +; diff --git a/test/cdevSelectorTest.cc b/test/cdevSelectorTest.cc new file mode 100755 index 0000000..72b05ce --- /dev/null +++ b/test/cdevSelectorTest.cc @@ -0,0 +1,61 @@ +#include "cdevSelector.h" +#include +#include + +#define MASK(f) (1 << (f)) +#define NUMFDS 1 + +void main() +{ +int fd[NUMFDS]; +int fdmask[NUMFDS]; +int readmask = 0; +int readfds; +int nfound, i; +int count = 0; +struct timeval timeout; + +cdevSelector selector; +fd[0] = selector.readfd(); +selector.insertEvent(20); +selector.removeEvent(20); +selector.purge(); +selector.insertEvent(50); + +/* First open each terminal for reading and put the + * file descriptors into array fd[NUMFDS]. The code + * for opening the terminals is not shown here. + */ + +for (i=0; i < NUMFDS; i++) + { + fdmask[i] = MASK(fd[i]); + readmask |= fdmask[i]; + } + +timeout.tv_sec = 0; +timeout.tv_usec = 50000; +readfds = readmask; + +/* select on NUMFDS+3 file descriptors if stdin, stdout + * and stderr are also open + */ + +while((nfound = select (NUMFDS+3, &readfds, 0, 0, &timeout)) > 0) + { + for (i=0; i < NUMFDS; i++) + { + if (fdmask[i] & readfds) + { + if(i==0) + { + selector.removeEvent(); + printf("removed %i event from the selector\n", count++); + } + } + else printf ("fd[%d] is not ready for reading \n",i); + } + } +if(nfound < 0) perror ("select failed"); +else if (nfound == 0) printf ("select timed out \n"); +} diff --git a/test/collectionTest.cc b/test/collectionTest.cc new file mode 100755 index 0000000..c624aa2 --- /dev/null +++ b/test/collectionTest.cc @@ -0,0 +1,25 @@ +#include +#include +#include + +int main(int argc, char ** argv) +{ +cdevSystem::defaultSystem().setThreshold(CDEV_SEVERITY_ERROR); + +cdevData output; +cdevCollection & new1 = cdevCollection::attachRef("new1"); + +/* +new1.add(14, "IPM1S01", "IPM1S02", "IPM1S03", "IPM1S05", "IPM1S07", "IPM1S08", "IPM1S09", + "device0", "device1", "device2", "device3", "device4", "device5", "device6"); +*/ +int i = argc>1?atoi(argv[1]):100; +fprintf(stdout, "Running for %i iterations\n", i); +while(i>0) + { + new1.send("get attrib1", NULL, &output); + i--; + } +output.asciiDump(); +} + diff --git a/test/equal.h b/test/equal.h new file mode 100755 index 0000000..dae0e4a --- /dev/null +++ b/test/equal.h @@ -0,0 +1,37 @@ +//--------------------------------------------------------------------------- +// Copyright (c) 1995 Southeastern Universities Research Association, +// Continuous Electron Beam Accelerator Facility +// +// This software was developed under a United States Government license +// described in the NOTICE file included as part of this distribution. +//---------------------------------------------------------------------------- +// +// description: equal.h +// This file provides a method for comparing 2 floating point numbers +// and determining if they are reasonably equivalent. +// +// Author: Walt Akers +// +// Revision History: +// equal.h,v +// Revision 1.1 1995/09/22 18:36:26 akers +// Added comparison function for floats and doubles +// +// Revision 1.1 1995/09/01 18:15:51 akers +// Initial installation of the Compound Device Service +// +// +//-------------------------------------------------------------------------- +#ifndef _EQUAL_H_ +#define _EQUAL_H_ 1 + +#include + +inline double Fabs(double a) { return ((a)<0.0?-(a):(a)); } +inline double Max (double a, double b) { return (a>b)?a:b; } +static int equal(double a, double b) + { + return (Fabs((a-b)/((a+b)==0.0?Max(Fabs(a),1E-300):(a+b)))<=FLT_EPSILON); + } + +#endif /* _EQUAL_H_ */ diff --git a/test/test.ddl b/test/test.ddl new file mode 100755 index 0000000..9b2c09f --- /dev/null +++ b/test/test.ddl @@ -0,0 +1,69 @@ +service ca + { + tags {PV, READONLY} + } + +service Sample + { + tags {server} + } + +class BPM + { + verbs {get, set, monitorOn, monitorOff} + attributes + { + attrib0 ca {PV = <>.VAL}; + attrib1 ca {PV = <>.VAL}; + attrib2 ca {PV = <>.VAL}; + attrib3 ca {PV = <>.VAL}; + attrib4 ca {PV = <>.VAL}; + attrib5 ca {PV = <>.VAL}; + attrib6 ca {PV = <>.VAL}; + attrib7 ca {PV = <>.VAL}; + attrib8 ca {PV = <>.VAL}; + attrib9 ca {PV = <>.VAL}; + } +} + +class Samples + { + verbs {get, set, monitorOn, monitorOff} + attributes + { + default Sample; + servers Sample; + attrib0 Sample; + attrib1 Sample; + attrib2 Sample; + attrib3 Sample; + attrib4 Sample; + attrib5 Sample; + attrib6 Sample; + attrib7 Sample; + attrib8 Sample; + attrib9 Sample; + } + messages + { + disconnect Sample; + } + } + + +BPM : + IPM1S01, IPM1S02, IPM1S03, IPM1S05, IPM1S07, + IPM1S08, IPM1S09 +; + +Samples : + device0, device1, device2, device3, device4, + device5, device6, device7, device8, device9 +; + +collection new1 : + IPM1S01, IPM1S02, IPM1S03, IPM1S05, IPM1S07, + IPM1S08, IPM1S09, + device0, device1, device2, device3, device4, + device5, device6, device7, device8, device9 +;